1 /*****************************************************************************
2 * dv.c: a decoder for DV video
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: dv.c,v 1.4 2002/11/02 17:31:37 sigmunau 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 #undef vlc_error /*vlc_error is defined in the libdv headers, but not
32 * used in thes file */
33 #include <libdv/dv_types.h>
36 /*****************************************************************************
38 *****************************************************************************/
39 static int RunDecoder ( decoder_fifo_t * );
40 static int OpenDecoder ( vlc_object_t * );
42 static u32 GetFourCC ( dv_sample_t );
43 static pes_packet_t *GetFirstPES( decoder_fifo_t * );
45 /*****************************************************************************
47 *****************************************************************************/
49 set_description( _("DV video decoder") );
50 set_capability( "decoder", 70 );
51 set_callbacks( OpenDecoder, NULL );
54 /*****************************************************************************
55 * OpenDecoder: probe the decoder and return score
56 *****************************************************************************
57 * The fourcc format for DV is "dvsd"
58 *****************************************************************************/
59 static int OpenDecoder ( vlc_object_t *p_this )
61 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
63 if( p_fifo->i_fourcc != VLC_FOURCC('d','v','s','d') )
68 p_fifo->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 )
81 bit_stream_t bit_stream;
82 dv_decoder_t * p_decoder;
83 vout_thread_t * p_vout;
85 p_buffer = malloc( i_data );
88 msg_Err( p_fifo, "out of memory" );
90 DecoderError( p_fifo );
94 p_decoder = dv_decoder_new( TRUE, FALSE, FALSE );
97 msg_Err( p_fifo, "cannot create DV decoder" );
100 DecoderError( p_fifo );
104 if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
106 msg_Err( p_fifo, "cannot initialise bitstream" );
109 DecoderError( p_fifo );
113 /* Fill the buffer */
114 GetChunk( &bit_stream, p_buffer, i_data );
116 while( !p_fifo->b_die && !p_fifo->b_error )
118 /* Parsing the beginning of the stream */
119 if( dv_parse_header( p_decoder, p_buffer ) < 0 )
121 fprintf(stderr, "parse error\n");
126 if( dv_format_wide( p_decoder ) )
128 msg_Dbg( p_fifo, "aspect is 4:3" );
129 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
131 else if( dv_format_normal( p_decoder ) )
133 msg_Dbg( p_fifo, "aspect is 16:9" );
134 i_aspect = VOUT_ASPECT_FACTOR * 4/3;//16 / 9;
138 msg_Dbg( p_fifo, "aspect is square pixels" );
139 i_aspect = VOUT_ASPECT_FACTOR
140 * p_decoder->width / p_decoder->height;
143 if( p_decoder->frame_size <= i_data )
145 /* XXX: what to do? */
146 i_data = p_decoder->frame_size;
150 p_buffer = realloc( p_buffer, p_decoder->frame_size );
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;
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 = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_CHILD );
163 p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_ANYWHERE );
168 if( p_vout->render.i_width != p_decoder->width
169 || p_vout->render.i_height != p_decoder->height
170 || p_vout->render.i_chroma != GetFourCC( p_decoder->sampling )
171 || p_vout->render.i_aspect != i_aspect )
173 /* We are not interested in this format, close this vout */
174 vlc_object_detach( p_vout );
175 vlc_object_release( p_vout );
176 vout_DestroyThread( p_vout );
181 /* This video output is cool! Hijack it. */
182 vlc_object_detach( p_vout );
183 vlc_object_attach( p_vout, p_fifo );
184 vlc_object_release( p_vout );
190 msg_Dbg( p_fifo, "no vout present, spawning one" );
192 p_vout = vout_CreateThread( p_fifo,
193 p_decoder->width, p_decoder->height,
194 GetFourCC( p_decoder->sampling ),
199 while( !p_fifo->b_die && !p_fifo->b_error )
204 GetChunk( &bit_stream, p_buffer + i_data,
205 p_decoder->frame_size - i_data );
206 i_data = p_decoder->frame_size;
208 p_pes = GetFirstPES( p_fifo );
212 /* Don't trust the sucker */
213 //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
214 i_pts = mdate() + DEFAULT_PTS_DELAY;
217 if( p_fifo->b_die || p_fifo->b_error )
222 if( dv_parse_header( p_decoder, p_buffer ) > 0 )
224 fprintf(stderr, "size changed\n");
227 if( p_vout && ( !p_decoder->prev_frame_decoded
228 || dv_frame_changed( p_decoder ) ) )
234 while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
236 if( p_fifo->b_die || p_fifo->b_error )
240 msleep( VOUT_OUTMEM_SLEEP );
248 for( i = 0 ; i < p_pic->i_planes ; i++ )
250 pixels[i] = p_pic->p[i].p_pixels;
251 pitches[i] = p_pic->p[i].i_pitch;
254 dv_decode_full_frame( p_decoder, p_buffer,
255 e_dv_color_yuv, pixels, pitches );
256 p_decoder->prev_frame_decoded = 1;
258 vout_DatePicture( p_vout, p_pic, i_pts );
259 vout_DisplayPicture( p_vout, p_pic );
267 vout_DestroyThread( p_vout );
272 CloseBitstream( &bit_stream );
274 if( p_fifo->b_error )
276 DecoderError( p_fifo );
283 static u32 GetFourCC( dv_sample_t x )
287 case e_dv_sample_411: return VLC_FOURCC('Y','U','Y','2');
288 case e_dv_sample_420: return VLC_FOURCC('Y','U','Y','2');
289 case e_dv_sample_422: return VLC_FOURCC('Y','U','Y','2');
294 static pes_packet_t *GetFirstPES( decoder_fifo_t *p_fifo )
298 vlc_mutex_lock( &p_fifo->data_lock );
300 /* if fifo is empty wait */
301 while( !p_fifo->p_first )
305 vlc_mutex_unlock( &p_fifo->data_lock );
308 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
310 p_pes = p_fifo->p_first;
312 vlc_mutex_unlock( &p_fifo->data_lock );