]> git.sesse.net Git - vlc/blob - modules/codec/xvid.c
Cleanup action.
[vlc] / modules / codec / xvid.c
1 /*****************************************************************************
2  * xvid.c: a decoder for libxvidcore, the Xvid video codec
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: xvid.c,v 1.3 2002/11/28 17:34:59 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/vout.h>
29 #include <vlc/input.h>
30 #include <vlc/decoder.h>
31
32 #include <stdlib.h>
33
34 #include "codecs.h"
35
36 #include <xvid.h>
37
38 /*****************************************************************************
39  * Local prototypes
40  *****************************************************************************/
41 static int RunDecoder  ( decoder_fifo_t * );
42 static int OpenDecoder ( vlc_object_t * );
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 vlc_module_begin();
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." );
53 vlc_module_end();
54
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 )
61 {
62     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
63
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') )
67     {
68         return VLC_EGENERIC;
69     }
70
71     p_fifo->pf_run = RunDecoder;
72     return VLC_SUCCESS;
73 }
74
75 /*****************************************************************************
76  * RunDecoder: this function is called just after the thread is created
77  *****************************************************************************/
78 static int RunDecoder ( decoder_fifo_t *p_fifo )
79 {
80     XVID_INIT_PARAM    xinit;
81     XVID_DEC_PARAM     xparam;
82     BITMAPINFOHEADER * p_format;
83     void *             p_xvid;
84
85     pes_packet_t *     p_pes = NULL;
86     bit_stream_t       bit_stream;
87     vout_thread_t *    p_vout;
88
89     uint8_t *  p_buffer, * p_image;
90     int        i_ret;
91     int        i_width, i_height, i_chroma, i_aspect;
92     int        i_size, i_offset, i_image_size;
93
94     vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
95
96     if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
97     {
98         msg_Err( p_fifo, "cannot initialise bitstream" );
99         p_fifo->b_error = VLC_TRUE;
100         DecoderError( p_fifo );
101         return VLC_EGENERIC;
102     }
103
104     p_format = (BITMAPINFOHEADER *)p_fifo->p_demux_data;
105
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;
111
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;
115     i_offset = 0;
116
117     p_buffer = malloc( i_size + i_image_size );
118     p_image = p_buffer + i_size;
119
120     if( !p_buffer )
121     {
122         msg_Err( p_fifo, "out of memory" );
123         p_fifo->b_error = VLC_TRUE;
124         CloseBitstream( &bit_stream );
125         DecoderError( p_fifo );
126         return VLC_EGENERIC;
127     }
128
129     xinit.cpu_flags = 0;
130     xvid_init( NULL, 0, &xinit, NULL );
131
132     xparam.width = i_width;
133     xparam.height = i_height;
134     i_ret = xvid_decore( NULL, XVID_DEC_CREATE, &xparam, NULL );
135
136     if( i_ret )
137     {
138         msg_Err( p_fifo, "cannot create xvid decoder" );
139         p_fifo->b_error = VLC_TRUE;
140         free( p_buffer );
141         CloseBitstream( &bit_stream );
142         DecoderError( p_fifo );
143         return VLC_EGENERIC;
144     }
145
146     p_xvid = xparam.handle;
147
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 = vout_Request( p_fifo, NULL,
151                            i_width, i_height, i_chroma, i_aspect );
152
153     if( !p_vout )
154     {
155         msg_Err( p_fifo, "could not spawn vout" );
156         p_fifo->b_error = VLC_TRUE;
157         xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
158         free( p_buffer );
159         CloseBitstream( &bit_stream );
160         DecoderError( p_fifo );
161         return VLC_EGENERIC;
162     }
163
164     /* Main loop */
165     while( !p_fifo->b_die && !p_fifo->b_error )
166     {
167         XVID_DEC_FRAME xframe;
168         XVID_DEC_PICTURE xpic;
169         mtime_t i_pts = 0;
170         picture_t *p_pic;
171
172         GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
173
174         if( p_pes )
175         {
176             input_DeletePES( p_fifo->p_packets_mgt, p_pes );
177         }
178
179         input_ExtractPES( p_fifo, &p_pes );
180         if( p_pes )
181         {
182             /* Don't trust the sucker */
183             //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
184             i_pts = mdate() + DEFAULT_PTS_DELAY;
185         }
186
187         if( p_fifo->b_die || p_fifo->b_error )
188         {
189             break;
190         }
191
192         while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
193         {
194             if( p_fifo->b_die || p_fifo->b_error )
195             {
196                 break;
197             } 
198             msleep( VOUT_OUTMEM_SLEEP );
199         }
200
201         if( !p_pic )
202         {
203             break;
204         }
205
206         if( b_direct )
207         {
208             xpic.y = p_pic->p[0].p_pixels;
209             xpic.u = p_pic->p[1].p_pixels;
210             xpic.v = p_pic->p[2].p_pixels;
211             xpic.stride_y = p_pic->p[0].i_pitch;
212             xpic.stride_u = p_pic->p[1].i_pitch;
213             xpic.stride_v = p_pic->p[2].i_pitch;
214         }
215
216         /* Decode the stuff */
217         xframe.bitstream = p_buffer;
218         xframe.length = i_size;
219         xframe.image = b_direct ? (void*)&xpic : p_image;
220         xframe.stride = i_width;
221         xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
222         i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
223         /* FIXME: check i_ret */
224
225         if( !b_direct )
226         {
227             /* TODO: use pf_memcpy when this is stable. */
228             memcpy( p_pic->p[0].p_pixels,
229                     p_image,
230                     i_width * i_height );
231             memcpy( p_pic->p[2].p_pixels,
232                     p_image + i_width * i_height,
233                     i_width * i_height / 4 );
234             memcpy( p_pic->p[1].p_pixels,
235                     p_image + i_width * i_height + i_width * i_height / 4,
236                     i_width * i_height / 4 );
237         }
238
239         vout_DatePicture( p_vout, p_pic, i_pts );
240         vout_DisplayPicture( p_vout, p_pic );
241
242         /* Move the remaining data. TODO: only do this when necessary. */
243         memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
244         i_offset = i_size - xframe.length;
245     }
246
247     /* Clean up everything */
248     vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
249
250     xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
251
252     if( p_pes )
253     {
254         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
255     }
256
257     free( p_buffer );
258     CloseBitstream( &bit_stream );
259
260     if( p_fifo->b_error )
261     {
262         DecoderError( p_fifo );
263         return VLC_EGENERIC;
264     }
265
266     return VLC_SUCCESS;
267 }
268