1 /*****************************************************************************
2 * dv.c: a decoder for DV video
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: dv.c,v 1.3 2002/10/27 16:58:13 gbazin 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>
31 #include <libdv/dv_types.h>
34 /*****************************************************************************
36 *****************************************************************************/
37 static int RunDecoder ( decoder_fifo_t * );
38 static int OpenDecoder ( vlc_object_t * );
40 static u32 GetFourCC ( dv_sample_t );
41 static pes_packet_t *GetFirstPES( decoder_fifo_t * );
43 /*****************************************************************************
45 *****************************************************************************/
47 set_description( _("DV video decoder") );
48 set_capability( "decoder", 70 );
49 set_callbacks( OpenDecoder, NULL );
52 /*****************************************************************************
53 * OpenDecoder: probe the decoder and return score
54 *****************************************************************************
55 * The fourcc format for DV is "dvsd"
56 *****************************************************************************/
57 static int OpenDecoder ( vlc_object_t *p_this )
59 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
61 if( p_fifo->i_fourcc != VLC_FOURCC('d','v','s','d') )
66 p_fifo->pf_run = RunDecoder;
70 /*****************************************************************************
71 * RunDecoder: this function is called just after the thread is created
72 *****************************************************************************/
73 static int RunDecoder ( decoder_fifo_t *p_fifo )
79 bit_stream_t bit_stream;
80 dv_decoder_t * p_decoder;
81 vout_thread_t * p_vout;
83 p_buffer = malloc( i_data );
86 msg_Err( p_fifo, "out of memory" );
88 DecoderError( p_fifo );
92 p_decoder = dv_decoder_new( TRUE, FALSE, FALSE );
95 msg_Err( p_fifo, "cannot create DV decoder" );
98 DecoderError( p_fifo );
102 if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
104 msg_Err( p_fifo, "cannot initialise bitstream" );
107 DecoderError( p_fifo );
111 /* Fill the buffer */
112 GetChunk( &bit_stream, p_buffer, i_data );
114 while( !p_fifo->b_die && !p_fifo->b_error )
116 /* Parsing the beginning of the stream */
117 if( dv_parse_header( p_decoder, p_buffer ) < 0 )
119 fprintf(stderr, "parse error\n");
124 if( dv_format_wide( p_decoder ) )
126 msg_Dbg( p_fifo, "aspect is 4:3" );
127 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
129 else if( dv_format_normal( p_decoder ) )
131 msg_Dbg( p_fifo, "aspect is 16:9" );
132 i_aspect = VOUT_ASPECT_FACTOR * 4/3;//16 / 9;
136 msg_Dbg( p_fifo, "aspect is square pixels" );
137 i_aspect = VOUT_ASPECT_FACTOR
138 * p_decoder->width / p_decoder->height;
141 if( p_decoder->frame_size <= i_data )
143 /* XXX: what to do? */
144 i_data = p_decoder->frame_size;
148 p_buffer = realloc( p_buffer, p_decoder->frame_size );
151 /* Don't trust the sucker */
152 //p_decoder->quality = p_decoder->video->quality;
153 p_decoder->quality = DV_QUALITY_BEST;
154 p_decoder->prev_frame_decoded = 0;
156 /* Spawn a video output if there is none. First we look amongst our
157 * children, then we look for any other vout that might be available */
158 p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_CHILD );
161 p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_ANYWHERE );
166 if( p_vout->render.i_width != p_decoder->width
167 || p_vout->render.i_height != p_decoder->height
168 || p_vout->render.i_chroma != GetFourCC( p_decoder->sampling )
169 || p_vout->render.i_aspect != i_aspect )
171 /* We are not interested in this format, close this vout */
172 vlc_object_detach( p_vout );
173 vlc_object_release( p_vout );
174 vout_DestroyThread( p_vout );
179 /* This video output is cool! Hijack it. */
180 vlc_object_detach( p_vout );
181 vlc_object_attach( p_vout, p_fifo );
182 vlc_object_release( p_vout );
188 msg_Dbg( p_fifo, "no vout present, spawning one" );
190 p_vout = vout_CreateThread( p_fifo,
191 p_decoder->width, p_decoder->height,
192 GetFourCC( p_decoder->sampling ),
197 while( !p_fifo->b_die && !p_fifo->b_error )
202 GetChunk( &bit_stream, p_buffer + i_data,
203 p_decoder->frame_size - i_data );
204 i_data = p_decoder->frame_size;
206 p_pes = GetFirstPES( p_fifo );
210 /* Don't trust the sucker */
211 //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
212 i_pts = mdate() + DEFAULT_PTS_DELAY;
215 if( p_fifo->b_die || p_fifo->b_error )
220 if( dv_parse_header( p_decoder, p_buffer ) > 0 )
222 fprintf(stderr, "size changed\n");
225 if( p_vout && ( !p_decoder->prev_frame_decoded
226 || dv_frame_changed( p_decoder ) ) )
232 while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
234 if( p_fifo->b_die || p_fifo->b_error )
238 msleep( VOUT_OUTMEM_SLEEP );
246 for( i = 0 ; i < p_pic->i_planes ; i++ )
248 pixels[i] = p_pic->p[i].p_pixels;
249 pitches[i] = p_pic->p[i].i_pitch;
252 dv_decode_full_frame( p_decoder, p_buffer,
253 e_dv_color_yuv, pixels, pitches );
254 p_decoder->prev_frame_decoded = 1;
256 vout_DatePicture( p_vout, p_pic, i_pts );
257 vout_DisplayPicture( p_vout, p_pic );
265 vout_DestroyThread( p_vout );
270 CloseBitstream( bit_stream );
272 if( p_fifo->b_error )
274 DecoderError( p_fifo );
281 static u32 GetFourCC( dv_sample_t x )
285 case e_dv_sample_411: return VLC_FOURCC('Y','U','Y','2');
286 case e_dv_sample_420: return VLC_FOURCC('Y','U','Y','2');
287 case e_dv_sample_422: return VLC_FOURCC('Y','U','Y','2');
292 static pes_packet_t *GetFirstPES( decoder_fifo_t *p_fifo )
296 vlc_mutex_lock( &p_fifo->data_lock );
298 /* if fifo is empty wait */
299 while( !p_fifo->p_first )
303 vlc_mutex_unlock( &p_fifo->data_lock );
306 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
308 p_pes = p_fifo->p_first;
310 vlc_mutex_unlock( &p_fifo->data_lock );