]> git.sesse.net Git - vlc/blob - modules/codec/dv.c
* ALL: final improvements to the decoders/packetizers api.
[vlc] / modules / codec / dv.c
1 /*****************************************************************************
2  * dv.c: a decoder for DV video
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: dv.c,v 1.6 2003/11/16 21:07:30 gbazin 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/decoder.h>
30
31 #undef vlc_error /*vlc_error is defined in the libdv headers, but not
32                   * used in thes file */
33 #include <libdv/dv_types.h>
34 #include <libdv/dv.h>
35
36 /*****************************************************************************
37  * Local prototypes
38  *****************************************************************************/
39 static int RunDecoder  ( decoder_fifo_t * );
40 static int OpenDecoder ( vlc_object_t * );
41
42 static vlc_fourcc_t GetFourCC   ( dv_sample_t );
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 vlc_module_begin();
48     set_description( _("DV video decoder") );
49     set_capability( "decoder", 70 );
50     set_callbacks( OpenDecoder, NULL );
51 vlc_module_end();
52
53 /*****************************************************************************
54  * OpenDecoder: probe the decoder and return score
55  *****************************************************************************
56  * The fourcc format for DV is "dvsd"
57  *****************************************************************************/
58 static int OpenDecoder ( vlc_object_t *p_this )
59 {
60     decoder_t *p_dec = (decoder_t*)p_this;
61
62     if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','s','d') )
63     {
64         return VLC_EGENERIC;
65     }
66
67     p_dec->pf_run = RunDecoder;
68     return VLC_SUCCESS;
69 }
70
71 /*****************************************************************************
72  * RunDecoder: this function is called just after the thread is created
73  *****************************************************************************/
74 static int RunDecoder ( decoder_fifo_t *p_fifo )
75 {
76     uint8_t *p_buffer;
77     pes_packet_t *p_pes = NULL;
78     unsigned int i_data = 120000;
79     int i_aspect;
80
81     bit_stream_t    bit_stream;
82     dv_decoder_t *  p_decoder;
83     vout_thread_t * p_vout;
84
85     p_buffer = malloc( i_data );
86     if( !p_buffer )
87     {
88         msg_Err( p_fifo, "out of memory" );
89         p_fifo->b_error = 1;
90         DecoderError( p_fifo );
91         return -1;
92     }
93
94     p_decoder = dv_decoder_new( TRUE, FALSE, FALSE );
95     if( !p_decoder )
96     {
97         msg_Err( p_fifo, "cannot create DV decoder" );
98         free( p_buffer );
99         p_fifo->b_error = 1;
100         DecoderError( p_fifo );
101         return -1;
102     }
103
104     if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
105     {
106         msg_Err( p_fifo, "cannot initialise bitstream" );
107         free( p_buffer );
108         p_fifo->b_error = 1;
109         DecoderError( p_fifo );
110         return -1;
111     }
112
113     /* Fill the buffer */
114     GetChunk( &bit_stream, p_buffer, i_data );
115
116     while( !p_fifo->b_die && !p_fifo->b_error )
117     {
118         /* Parsing the beginning of the stream */
119         if( dv_parse_header( p_decoder, p_buffer ) < 0 )
120         {
121             fprintf(stderr, "parse error\n");
122             p_fifo->b_error = 1;
123             break;
124         }
125
126         if( dv_format_wide( p_decoder ) )
127         {
128             msg_Dbg( p_fifo, "aspect is 4:3" );
129             i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
130         }
131         else if( dv_format_normal( p_decoder ) )
132         {
133             msg_Dbg( p_fifo, "aspect is 16:9" );
134             i_aspect = VOUT_ASPECT_FACTOR * 4/3;//16 / 9;
135         }
136         else
137         {
138             msg_Dbg( p_fifo, "aspect is square pixels" );
139             i_aspect = VOUT_ASPECT_FACTOR
140                         * p_decoder->width / p_decoder->height;
141         }
142
143         if( p_decoder->frame_size <= i_data )
144         {
145             /* XXX: what to do? */
146             i_data = p_decoder->frame_size;
147         }
148         else
149         {
150             p_buffer = realloc( p_buffer, p_decoder->frame_size );
151         }
152
153         /* Don't trust the sucker */
154         //p_decoder->quality = p_decoder->video->quality;
155         p_decoder->quality = DV_QUALITY_BEST;
156         p_decoder->prev_frame_decoded = 0;
157
158         /* Spawn a video output if there is none. First we look amongst our
159          * children, then we look for any other vout that might be available */
160         p_vout = vout_Request( p_fifo, NULL,
161                                p_decoder->width, p_decoder->height,
162                                GetFourCC( p_decoder->sampling ), i_aspect );
163
164         /* Main loop */
165         while( !p_fifo->b_die && !p_fifo->b_error )
166         {
167             mtime_t i_pts = 0;
168
169             GetChunk( &bit_stream, p_buffer + i_data,
170                                    p_decoder->frame_size - i_data );
171             i_data = p_decoder->frame_size;
172
173             if( p_pes )
174             {
175                 input_DeletePES( p_fifo->p_packets_mgt, p_pes );
176             }
177
178             input_ExtractPES( p_fifo, &p_pes );
179             if( p_pes )
180             {
181                 /* Don't trust the sucker */
182                 //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
183                 i_pts = mdate() + DEFAULT_PTS_DELAY;
184             }
185
186             if( p_fifo->b_die || p_fifo->b_error )
187             {
188                 break;
189             }
190
191             if( dv_parse_header( p_decoder, p_buffer ) > 0 )
192             {
193                 fprintf(stderr, "size changed\n");
194             }
195
196             if( p_vout && ( !p_decoder->prev_frame_decoded
197                              || dv_frame_changed( p_decoder ) ) )
198             {
199                 picture_t *p_pic;
200                 uint8_t *pixels[3];
201                 int pitches[3], i;
202
203                 while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
204                 {
205                     if( p_fifo->b_die || p_fifo->b_error )
206                     {
207                         break;
208                     }
209                     msleep( VOUT_OUTMEM_SLEEP );
210                 }
211
212                 if( !p_pic )
213                 {
214                     break;
215                 }
216
217                 for( i = 0 ; i < p_pic->i_planes ; i++ )
218                 {
219                     pixels[i] = p_pic->p[i].p_pixels;
220                     pitches[i] = p_pic->p[i].i_pitch;
221                 }
222
223                 dv_decode_full_frame( p_decoder, p_buffer,
224                                       e_dv_color_yuv, pixels, pitches );
225                 p_decoder->prev_frame_decoded = 1;
226
227                 vout_DatePicture( p_vout, p_pic, i_pts );
228                 vout_DisplayPicture( p_vout, p_pic );
229             }
230
231             i_data = 0;
232         }
233
234         vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
235     }
236
237     if( p_pes )
238     {
239         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
240     }
241
242     free( p_buffer );
243     CloseBitstream( &bit_stream );
244
245     if( p_fifo->b_error )
246     {
247         DecoderError( p_fifo );
248         return -1;
249     }
250
251     return 0;
252 }
253
254 static vlc_fourcc_t GetFourCC( dv_sample_t x )
255 {
256     switch( x )
257     {
258         case e_dv_sample_411: return VLC_FOURCC('Y','U','Y','2');
259         case e_dv_sample_420: return VLC_FOURCC('Y','U','Y','2');
260         case e_dv_sample_422: return VLC_FOURCC('Y','U','Y','2');
261         default: return 0;
262     }
263 }
264