1 /*****************************************************************************
2 * rawdv.c : raw dv input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: rawdv.c,v 1.3 2003/01/23 09:00:36 fenrir Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
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 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
28 #include <string.h> /* strdup() */
32 #include <vlc/input.h>
34 #include <sys/types.h>
36 #include <codecs.h> /* BITMAPINFOHEADER, WAVEFORMATEX */
38 /*****************************************************************************
39 A little bit of background information (copied over from libdv glossary).
41 - DIF block: A block of 80 bytes. This is the basic data framing unit of the
42 DVC tape format, analogous to sectors of hard disc.
44 - Video Section: Each DIF sequence contains a video section, consisting of
45 135 DIF blocks, which are further subdivided into Video Segments.
47 - Video Segment: A video segment consists of 5 DIF blocks, each corresponding
48 to a single compressed macroblock.
50 *****************************************************************************/
53 /*****************************************************************************
55 *****************************************************************************/
56 #define DV_PAL_FRAME_SIZE 144000
57 #define DV_NTSC_FRAME_SIZE 122000
59 /*****************************************************************************
60 * Definitions of structures used by this plugin
61 *****************************************************************************/
63 int8_t sct; /* Section type (header,subcode,aux,audio,video) */
64 int8_t dsn; /* DIF sequence number (0-12) */
65 int fsc; /* First (0)/Second channel (1) */
66 int8_t dbn; /* DIF block number (0-134) */
70 int dsf; /* DIF sequence flag: 525/60 (0) or 625,50 (1) */
84 es_descriptor_t *p_video_es;
85 es_descriptor_t *p_audio_es;
87 /* codec specific stuff */
88 BITMAPINFOHEADER *p_bih;
93 /* program clock reference (in units of 90kHz) */
97 /*****************************************************************************
99 *****************************************************************************/
100 static int Activate ( vlc_object_t * );
101 static void Deactivate( vlc_object_t * );
102 static int Demux ( input_thread_t * );
104 static uint32_t GetDWBE( uint8_t *p_buff )
106 return (uint32_t)p_buff[3] | ( ((uint32_t)p_buff[2]) << 8 ) |
107 ( ((uint32_t)p_buff[1]) << 16 ) | ( ((uint32_t)p_buff[0]) << 24 );
110 /*****************************************************************************
112 *****************************************************************************/
114 set_description( _("raw dv demux") );
115 set_capability( "demux", 2 );
116 set_callbacks( Activate, NULL );
117 add_shortcut( "rawdv" );
120 /*****************************************************************************
121 * Activate: initializes raw dv demux structures
122 *****************************************************************************/
123 static int Activate( vlc_object_t * p_this )
125 input_thread_t *p_input = (input_thread_t *)p_this;
128 demux_sys_t *p_rawdv;
129 dv_header_t dv_header;
133 /* It isn't easy to recognize a raw dv stream. The chances that we'll
134 * mistake a stream from another type for a raw dv stream are too high, so
135 * we'll rely on the file extension to trigger this demux. Alternatively,
136 * it is possible to force this demux. */
138 /* Check for dv file extension */
139 psz_ext = strrchr ( p_input->psz_name, '.' );
140 if( ( !psz_ext || strcasecmp( psz_ext, ".dv") )&&
141 ( !p_input->psz_demux || strcmp(p_input->psz_demux, "rawdv") ) )
146 p_input->pf_demux = Demux;
148 /* Have a peep at the show. */
149 if( input_Peek(p_input, &p_peek, DV_PAL_FRAME_SIZE) < DV_NTSC_FRAME_SIZE )
151 /* Stream too short ... */
152 msg_Err( p_input, "cannot peek()" );
156 /* fill in the dv_id_t structure */
157 i_dword = GetDWBE( p_peek ); p_peek += 4;
158 dv_id.sct = i_dword >> (32 - 3);
160 dv_id.dsn = i_dword >> (32 - 4);
162 dv_id.fsc = i_dword >> (32 - 1);
164 dv_id.dbn = i_dword >> (32 - 8);
169 msg_Warn( p_input, "not a raw dv stream header" );
173 /* fill in the dv_header_t structure */
174 dv_header.dsf = i_dword >> (32 - 1);
176 if( i_dword >> (32 - 1) ) /* incorrect bit */
178 msg_Warn( p_input, "incorrect bit" );
182 i_dword = GetDWBE( p_peek ); p_peek += 4;
184 dv_header.apt = i_dword >> (32 - 3);
186 dv_header.tf1 = i_dword >> (32 - 1);
188 dv_header.ap1 = i_dword >> (32 - 3);
190 dv_header.tf2 = i_dword >> (32 - 1);
192 dv_header.ap2 = i_dword >> (32 - 3);
194 dv_header.tf3 = i_dword >> (32 - 1);
196 dv_header.ap3 = i_dword >> (32 - 3);
198 p_peek += 72; /* skip rest of DIF block */
201 /* Setup the structures for our demuxer */
202 if( !( p_rawdv = malloc( sizeof( demux_sys_t ) ) ) )
204 msg_Err( p_input, "out of memory" );
207 memset( p_rawdv, 0, sizeof( demux_sys_t ) );
208 p_rawdv->p_bih = NULL;
209 p_input->p_demux_data = p_rawdv;
211 p_rawdv->p_bih = (BITMAPINFOHEADER *) malloc( sizeof(BITMAPINFOHEADER) );
212 if( !p_rawdv->p_bih )
214 msg_Err( p_input, "out of memory" );
217 p_rawdv->p_bih->biSize = sizeof(BITMAPINFOHEADER);
218 p_rawdv->p_bih->biCompression = VLC_FOURCC( 'd','v','s','d' );
219 p_rawdv->p_bih->biSize = 40;
220 p_rawdv->p_bih->biWidth = 720;
221 p_rawdv->p_bih->biHeight = dv_header.dsf ? 576 : 480;
222 p_rawdv->p_bih->biPlanes = 1;
223 p_rawdv->p_bih->biBitCount = 24;
224 p_rawdv->p_bih->biSizeImage =
225 p_rawdv->p_bih->biWidth * p_rawdv->p_bih->biHeight
226 * (p_rawdv->p_bih->biBitCount >> 3);
228 /* Properties of our video */
231 p_rawdv->frame_size = 12 * 150 * 80;
232 p_rawdv->f_rate = 25;
236 p_rawdv->frame_size = 10 * 150 * 80;
237 p_rawdv->f_rate = 29.97;
240 /* necessary because input_SplitBuffer() will only get
241 * INPUT_DEFAULT_BUFSIZE bytes at a time. */
242 p_input->i_bufsize = p_rawdv->frame_size;
244 /* Create one program */
245 vlc_mutex_lock( &p_input->stream.stream_lock );
246 if( input_InitStream( p_input, 0 ) == -1)
248 vlc_mutex_unlock( &p_input->stream.stream_lock );
249 msg_Err( p_input, "cannot init stream" );
252 if( input_AddProgram( p_input, 0, 0) == NULL )
254 vlc_mutex_unlock( &p_input->stream.stream_lock );
255 msg_Err( p_input, "cannot add program" );
258 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
259 p_input->stream.i_mux_rate = p_rawdv->frame_size * p_rawdv->f_rate;
260 vlc_mutex_unlock( &p_input->stream.stream_lock );
262 /* Add video stream */
263 vlc_mutex_lock( &p_input->stream.stream_lock );
264 p_rawdv->p_video_es = input_AddES( p_input,
265 p_input->stream.p_selected_program,
267 p_rawdv->p_video_es->i_stream_id = 0;
268 p_rawdv->p_video_es->i_fourcc = VLC_FOURCC( 'd','v','s','d' );
269 p_rawdv->p_video_es->i_cat = VIDEO_ES;
270 p_rawdv->p_video_es->p_bitmapinfoheader = (void *)p_rawdv->p_bih;
271 input_SelectES( p_input, p_rawdv->p_video_es );
272 vlc_mutex_unlock( &p_input->stream.stream_lock );
280 if( p_rawdv->p_bih ) free( p_rawdv->p_bih );
281 Deactivate( (vlc_object_t *)p_input );
285 /*****************************************************************************
286 * Deactivate: frees unused data
287 *****************************************************************************/
288 static void Deactivate( vlc_object_t *p_this )
290 input_thread_t *p_input = (input_thread_t *)p_this;
291 demux_sys_t *p_rawdv = (demux_sys_t *)p_input->p_demux_data;
296 /*****************************************************************************
297 * Demux: reads and demuxes data packets
298 *****************************************************************************
299 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
300 *****************************************************************************/
301 static int Demux( input_thread_t * p_input )
303 demux_sys_t *p_rawdv = (demux_sys_t *)p_input->p_demux_data;
304 decoder_fifo_t *p_fifo =
305 p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
307 data_packet_t *p_data;
315 if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
319 msg_Warn( p_input, "synchro reinit" );
321 /* If the user tried to seek in the stream, we need to make sure
322 * the new position is at a DIF block boundary. */
323 vlc_mutex_lock( &p_input->stream.stream_lock );
324 i_pos= p_input->stream.p_selected_area->i_tell;
325 vlc_mutex_unlock( &p_input->stream.stream_lock );
327 if( (i_pos % p_rawdv->frame_size) &&
328 p_input->stream.b_seekable &&
329 p_input->stream.i_method == INPUT_METHOD_FILE )
331 p_input->pf_seek( p_input, (i_pos / p_rawdv->frame_size)
332 * p_rawdv->frame_size );
333 input_AccessReinit( p_input );
337 /* Call the pace control */
338 input_ClockManageRef( p_input, p_input->stream.p_selected_program,
341 i_read = input_SplitBuffer( p_input, &p_data, p_rawdv->frame_size );
347 p_pes = input_NewPES( p_input->p_method_data );
350 msg_Err( p_input, "out of memory" );
351 input_DeletePacket( p_input->p_method_data, p_data );
355 p_pes->i_rate = p_input->stream.control.i_rate;
356 p_pes->p_first = p_pes->p_last = p_data;
357 p_pes->i_pes_size = i_read;
358 p_pes->i_nb_data = 1;
360 input_ClockGetTS( p_input, p_input->stream.p_selected_program,
363 input_DecodePES( p_fifo, p_pes );
365 p_rawdv->i_pcr += ( 90000 / p_rawdv->f_rate );