1 /*****************************************************************************
2 * xvid.c: a decoder for libxvidcore, the Xvid video codec
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: xvid.c,v 1.2 2002/11/06 09:26:25 sam 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/input.h>
30 #include <vlc/decoder.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static int RunDecoder ( decoder_fifo_t * );
42 static int OpenDecoder ( vlc_object_t * );
44 /*****************************************************************************
46 *****************************************************************************/
48 set_description( _("Xvid video decoder") );
49 set_capability( "decoder", 50 );
50 set_callbacks( OpenDecoder, NULL );
51 add_bool( "xvid-direct-render", 0, NULL, "direct rendering",
52 "Use libxvidcore's direct rendering feature." );
55 /*****************************************************************************
56 * OpenDecoder: probe the decoder and return score
57 *****************************************************************************
58 * FIXME: find fourcc formats supported by xvid
59 *****************************************************************************/
60 static int OpenDecoder ( vlc_object_t *p_this )
62 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
64 if( p_fifo->i_fourcc != VLC_FOURCC('x','v','i','d')
65 && p_fifo->i_fourcc != VLC_FOURCC('X','V','I','D')
66 && p_fifo->i_fourcc != VLC_FOURCC('D','I','V','X') )
71 p_fifo->pf_run = RunDecoder;
75 /*****************************************************************************
76 * RunDecoder: this function is called just after the thread is created
77 *****************************************************************************/
78 static int RunDecoder ( decoder_fifo_t *p_fifo )
80 XVID_INIT_PARAM xinit;
81 XVID_DEC_PARAM xparam;
82 BITMAPINFOHEADER * p_format;
85 pes_packet_t * p_pes = NULL;
86 bit_stream_t bit_stream;
87 vout_thread_t * p_vout;
89 uint8_t * p_buffer, * p_image;
91 int i_width, i_height, i_chroma, i_aspect;
92 int i_size, i_offset, i_image_size;
94 vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
96 if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
98 msg_Err( p_fifo, "cannot initialise bitstream" );
99 p_fifo->b_error = VLC_TRUE;
100 DecoderError( p_fifo );
104 p_format = (BITMAPINFOHEADER *)p_fifo->p_demux_data;
106 /* Guess picture properties from the BIH */
107 i_width = p_format->biWidth;
108 i_height = p_format->biHeight;
109 i_chroma = VLC_FOURCC('Y','V','1','2');
110 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
112 /* XXX: Completely arbitrary buffer size */
113 i_size = i_width * i_height / 4;
114 i_image_size = b_direct ? 0 : i_width * i_height * 4;
117 p_buffer = malloc( i_size + i_image_size );
118 p_image = p_buffer + i_size;
122 msg_Err( p_fifo, "out of memory" );
123 p_fifo->b_error = VLC_TRUE;
124 CloseBitstream( &bit_stream );
125 DecoderError( p_fifo );
130 xvid_init( NULL, 0, &xinit, NULL );
132 xparam.width = i_width;
133 xparam.height = i_height;
134 i_ret = xvid_decore( NULL, XVID_DEC_CREATE, &xparam, NULL );
138 msg_Err( p_fifo, "cannot create xvid decoder" );
139 p_fifo->b_error = VLC_TRUE;
141 CloseBitstream( &bit_stream );
142 DecoderError( p_fifo );
146 p_xvid = xparam.handle;
148 /* Spawn a video output if there is none. First we look amongst our
149 * children, then we look for any other vout that might be available */
150 p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_CHILD );
153 p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_ANYWHERE );
158 if( p_vout->render.i_width != i_width
159 || p_vout->render.i_height != i_height
160 || p_vout->render.i_chroma != i_chroma
161 || p_vout->render.i_aspect != i_aspect )
163 /* We are not interested in this format, close this vout */
164 vlc_object_detach( p_vout );
165 vlc_object_release( p_vout );
166 vout_DestroyThread( p_vout );
171 /* This video output is cool! Hijack it. */
172 vlc_object_detach( p_vout );
173 vlc_object_attach( p_vout, p_fifo );
174 vlc_object_release( p_vout );
180 msg_Dbg( p_fifo, "no vout present, spawning one" );
182 p_vout = vout_CreateThread( p_fifo,
184 i_chroma, i_aspect );
187 msg_Err( p_fifo, "could not spawn vout" );
188 p_fifo->b_error = VLC_TRUE;
189 xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
191 CloseBitstream( &bit_stream );
192 DecoderError( p_fifo );
198 while( !p_fifo->b_die && !p_fifo->b_error )
200 XVID_DEC_FRAME xframe;
201 XVID_DEC_PICTURE xpic;
205 GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
209 input_DeletePES( p_fifo->p_packets_mgt, p_pes );
212 input_ExtractPES( p_fifo, &p_pes );
215 /* Don't trust the sucker */
216 //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
217 i_pts = mdate() + DEFAULT_PTS_DELAY;
220 if( p_fifo->b_die || p_fifo->b_error )
225 while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
227 if( p_fifo->b_die || p_fifo->b_error )
231 msleep( VOUT_OUTMEM_SLEEP );
241 xpic.y = p_pic->p[0].p_pixels;
242 xpic.u = p_pic->p[1].p_pixels;
243 xpic.v = p_pic->p[2].p_pixels;
244 xpic.stride_y = p_pic->p[0].i_pitch;
245 xpic.stride_u = p_pic->p[1].i_pitch;
246 xpic.stride_v = p_pic->p[2].i_pitch;
249 /* Decode the stuff */
250 xframe.bitstream = p_buffer;
251 xframe.length = i_size;
252 xframe.image = b_direct ? (void*)&xpic : p_image;
253 xframe.stride = i_width;
254 xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
255 i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
256 /* FIXME: check i_ret */
260 /* TODO: use pf_memcpy when this is stable. */
261 memcpy( p_pic->p[0].p_pixels,
263 i_width * i_height );
264 memcpy( p_pic->p[2].p_pixels,
265 p_image + i_width * i_height,
266 i_width * i_height / 4 );
267 memcpy( p_pic->p[1].p_pixels,
268 p_image + i_width * i_height + i_width * i_height / 4,
269 i_width * i_height / 4 );
272 vout_DatePicture( p_vout, p_pic, i_pts );
273 vout_DisplayPicture( p_vout, p_pic );
275 /* Move the remaining data. TODO: only do this when necessary. */
276 memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
277 i_offset = i_size - xframe.length;
280 /* Clean up everything */
281 vlc_object_detach( p_vout );
282 vout_DestroyThread( p_vout );
284 xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
288 input_DeletePES( p_fifo->p_packets_mgt, p_pes );
292 CloseBitstream( &bit_stream );
294 if( p_fifo->b_error )
296 DecoderError( p_fifo );