1 /*****************************************************************************
2 * xvid.c: a decoder for libxvidcore, the Xvid video codec
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: xvid.c,v 1.8 2003/11/22 23:39:14 fenrir Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <vlc/decoder.h>
35 /*****************************************************************************
37 *****************************************************************************/
38 static int RunDecoder ( decoder_fifo_t * );
39 static int OpenDecoder ( vlc_object_t * );
41 /*****************************************************************************
43 *****************************************************************************/
45 set_description( _("Xvid video decoder") );
46 set_capability( "decoder", 50 );
47 set_callbacks( OpenDecoder, NULL );
48 add_bool( "xvid-direct-render", 0, NULL, "direct rendering",
49 "Use libxvidcore's direct rendering feature.", VLC_TRUE );
52 /*****************************************************************************
53 * OpenDecoder: probe the decoder and return score
54 *****************************************************************************
55 * FIXME: find fourcc formats supported by xvid
56 *****************************************************************************/
57 static int OpenDecoder ( vlc_object_t *p_this )
59 decoder_t *p_dec = (decoder_t*)p_this;
61 if( p_dec->fmt_in.i_codec != VLC_FOURCC('x','v','i','d')
62 && p_dec->fmt_in.i_codec != VLC_FOURCC('X','V','I','D')
63 && p_dec->fmt_in.i_codec != VLC_FOURCC('D','I','V','X') )
68 p_dec->pf_run = RunDecoder;
72 /*****************************************************************************
73 * RunDecoder: this function is called just after the thread is created
74 *****************************************************************************/
75 static int RunDecoder ( decoder_fifo_t *p_fifo )
77 XVID_INIT_PARAM xinit;
78 XVID_DEC_PARAM xparam;
79 BITMAPINFOHEADER * p_format;
82 pes_packet_t * p_pes = NULL;
83 bit_stream_t bit_stream;
84 vout_thread_t * p_vout;
86 uint8_t * p_buffer, * p_image;
88 int i_width, i_height, i_chroma, i_aspect;
89 int i_size, i_offset, i_image_size;
91 vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
93 if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
95 msg_Err( p_fifo, "cannot initialise bitstream" );
96 p_fifo->b_error = VLC_TRUE;
97 DecoderError( p_fifo );
100 if( ( p_format = (BITMAPINFOHEADER *)p_fifo->p_bitmapinfoheader ) == NULL )
103 i_height = 1; // avoid segfault anyway it's wrong
107 /* Guess picture properties from the BIH */
108 i_width = p_format->biWidth;
109 i_height = p_format->biHeight;
112 i_chroma = VLC_FOURCC('Y','V','1','2');
113 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
115 /* XXX: Completely arbitrary buffer size */
116 i_size = i_width * i_height / 4;
117 i_image_size = b_direct ? 0 : i_width * i_height * 4;
120 p_buffer = malloc( i_size + i_image_size );
121 p_image = p_buffer + i_size;
125 msg_Err( p_fifo, "out of memory" );
126 p_fifo->b_error = VLC_TRUE;
127 CloseBitstream( &bit_stream );
128 DecoderError( p_fifo );
133 xvid_init( NULL, 0, &xinit, NULL );
135 xparam.width = i_width;
136 xparam.height = i_height;
137 i_ret = xvid_decore( NULL, XVID_DEC_CREATE, &xparam, NULL );
141 msg_Err( p_fifo, "cannot create xvid decoder" );
142 p_fifo->b_error = VLC_TRUE;
144 CloseBitstream( &bit_stream );
145 DecoderError( p_fifo );
149 p_xvid = xparam.handle;
151 /* Spawn a video output if there is none. First we look amongst our
152 * children, then we look for any other vout that might be available */
153 p_vout = vout_Request( p_fifo, NULL,
154 i_width, i_height, i_chroma, i_aspect );
158 msg_Err( p_fifo, "could not spawn vout" );
159 p_fifo->b_error = VLC_TRUE;
160 xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
162 CloseBitstream( &bit_stream );
163 DecoderError( p_fifo );
168 while( !p_fifo->b_die && !p_fifo->b_error )
170 XVID_DEC_FRAME xframe;
171 XVID_DEC_PICTURE xpic;
175 GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
179 input_DeletePES( p_fifo->p_packets_mgt, p_pes );
182 input_ExtractPES( p_fifo, &p_pes );
185 /* Don't trust the sucker */
186 //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
187 i_pts = mdate() + DEFAULT_PTS_DELAY;
190 if( p_fifo->b_die || p_fifo->b_error )
195 while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
197 if( p_fifo->b_die || p_fifo->b_error )
201 msleep( VOUT_OUTMEM_SLEEP );
211 xpic.y = p_pic->p[0].p_pixels;
212 xpic.u = p_pic->p[1].p_pixels;
213 xpic.v = p_pic->p[2].p_pixels;
214 xpic.stride_y = p_pic->p[0].i_pitch;
215 xpic.stride_u = p_pic->p[1].i_pitch;
216 xpic.stride_v = p_pic->p[2].i_pitch;
219 /* Decode the stuff */
220 xframe.bitstream = p_buffer;
221 xframe.length = i_size;
222 xframe.image = b_direct ? (void*)&xpic : p_image;
223 xframe.stride = i_width;
224 xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
225 i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
226 /* FIXME: check i_ret */
230 /* TODO: use pf_memcpy when this is stable. */
231 memcpy( p_pic->p[0].p_pixels,
233 i_width * i_height );
234 memcpy( p_pic->p[2].p_pixels,
235 p_image + i_width * i_height,
236 i_width * i_height / 4 );
237 memcpy( p_pic->p[1].p_pixels,
238 p_image + i_width * i_height + i_width * i_height / 4,
239 i_width * i_height / 4 );
242 vout_DatePicture( p_vout, p_pic, i_pts );
243 vout_DisplayPicture( p_vout, p_pic );
245 /* Move the remaining data. TODO: only do this when necessary. */
246 memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
247 i_offset = i_size - xframe.length;
250 /* Clean up everything */
251 vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
253 xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
257 input_DeletePES( p_fifo->p_packets_mgt, p_pes );
261 CloseBitstream( &bit_stream );
263 if( p_fifo->b_error )
265 DecoderError( p_fifo );