1 /*****************************************************************************
2 * input_dvd.c: DVD reading
3 *****************************************************************************
4 * Copyright (C) 1998-2001 VideoLAN
5 * $Id: input_dvd.c,v 1.7 2001/01/29 06:10:10 stef Exp $
7 * Author: Stéphane Borel <stef@via.ecp.fr>
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 *****************************************************************************/
32 #include <netinet/in.h>
35 #include <sys/types.h>
41 #include <sys/ioctl.h>
42 #ifdef HAVE_SYS_DVDIO_H
43 # include <sys/dvdio.h>
46 # include <linux/cdrom.h>
58 #include "stream_control.h"
59 #include "input_ext-intf.h"
60 #include "input_ext-dec.h"
66 #include "input_dvd.h"
67 #include "mpeg_system.h"
72 /*****************************************************************************
74 *****************************************************************************/
75 static int DVDProbe ( struct input_thread_s * );
76 static int DVDRead ( struct input_thread_s *,
77 data_packet_t * p_packets[INPUT_READ_ONCE] );
78 static void DVDInit ( struct input_thread_s * );
79 static void DVDEnd ( struct input_thread_s * );
80 /* FIXME : DVDSeek should be on 64 bits ? Is it possible in input ? */
81 static int DVDSeek ( struct input_thread_s *, off_t );
82 static int DVDRewind ( struct input_thread_s * );
83 static struct data_packet_s * NewPacket ( void *, size_t );
84 static void DeletePacket( void *, struct data_packet_s * );
85 static void DeletePES ( void *, struct pes_packet_s * );
88 * Data reading functions
91 /*****************************************************************************
92 * DVDProbe: check the stream
93 *****************************************************************************/
94 static int DVDProbe( input_thread_t * p_input )
96 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
99 dvd.type = DVD_STRUCT_COPYRIGHT;
100 dvd.copyright.layer_num = 0;
102 if( ioctl( p_input->i_handle, DVD_READ_STRUCT, &dvd ) < 0 )
104 intf_ErrMsg( "DVD ioctl error" );
108 return dvd.copyright.cpst;
114 /*****************************************************************************
115 * DVDInit: initializes DVD structures
116 *****************************************************************************/
117 static void DVDInit( input_thread_t * p_input )
119 thread_dvd_data_t * p_method;
122 if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL )
124 intf_ErrMsg( "Out of memory" );
125 p_input->b_error = 1;
129 p_input->p_plugin_data = (void *)p_method;
130 p_input->p_method_data = NULL;
132 p_method->i_fd = p_input->i_handle;
135 lseek64( p_input->i_handle, 0, SEEK_SET );
137 /* Ifo initialisation */
138 intf_Msg( 3, "Ifo: Initialization" );
139 p_method->ifo = IfoInit( p_input->i_handle );
140 IfoRead( &(p_method->ifo) );
142 #if defined( HAVE_SYS_DVDIO_H ) || defined( LINUX_DVD )
143 /* CSS authentication and keys */
144 if( ( p_method->b_encrypted = DVDProbe( p_input ) ) )
148 intf_Msg( 3, "CSS: Initialization" );
149 p_method->css = CSSInit( p_input->i_handle );
150 p_method->css.i_title_nb = p_method->ifo.vmg.mat.i_tts_nb;
151 if( (p_method->css.p_title_key =
152 malloc( p_method->css.i_title_nb *
153 sizeof(p_method->css.p_title_key) ) ) == NULL )
155 intf_ErrMsg( "Out of memory" );
156 p_input->b_error = 1;
159 for( i=0 ; i<p_method->css.i_title_nb ; i++ )
161 p_method->css.p_title_key[i].i =
162 p_method->ifo.p_vts[i].i_pos +
163 p_method->ifo.p_vts[i].mat.i_tt_vobs_ssector *DVD_LB_SIZE;
165 CSSGetKeys( &(p_method->css) );
169 i_start = p_method->ifo.p_vts[0].i_pos +
170 p_method->ifo.p_vts[0].mat.i_tt_vobs_ssector *DVD_LB_SIZE;
172 i_start = lseek64( p_input->i_handle, i_start, SEEK_SET );
173 intf_Msg( "VOB start at : %lld", (long long)i_start );
176 input_InitStream( p_input, sizeof( stream_ps_data_t ) );
177 input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
179 if( p_input->stream.b_seekable )
181 stream_ps_data_t * p_demux_data =
182 (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
184 /* Pre-parse the stream to gather stream_descriptor_t. */
185 p_input->stream.pp_programs[0]->b_is_ok = 0;
186 p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
188 while( !p_input->b_die && !p_input->b_error
189 && !p_demux_data->b_has_PSM )
192 data_packet_t * pp_packets[INPUT_READ_ONCE];
194 i_result = DVDRead( p_input, pp_packets );
198 vlc_mutex_lock( &p_input->stream.stream_lock );
199 p_input->stream.pp_programs[0]->b_is_ok = 1;
200 vlc_mutex_unlock( &p_input->stream.stream_lock );
205 p_input->b_error = 1;
209 for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
211 /* FIXME: use i_p_config_t */
212 input_ParsePS( p_input, pp_packets[i] );
213 DeletePacket( p_input->p_method_data, pp_packets[i] );
217 if( p_input->stream.i_tell > INPUT_PREPARSE_LENGTH )
222 lseek64( p_input->i_handle, i_start, SEEK_SET );
223 vlc_mutex_lock( &p_input->stream.stream_lock );
224 p_input->stream.i_tell = 0;
225 if( p_demux_data->b_has_PSM )
227 /* (The PSM decoder will care about spawning the decoders) */
228 p_input->stream.pp_programs[0]->b_is_ok = 1;
233 /* (We have to do it ourselves) */
236 /* FIXME: we should do multiple passes in case an audio type
239 i_es < p_input->stream.pp_programs[0]->i_es_number;
242 #define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
243 switch( p_es->i_type )
247 input_SelectES( p_input, p_es );
252 if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
254 && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
255 == (p_es->i_id & 0x1F) )
257 input_SelectES( p_input, p_es );
262 if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
264 && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
265 == ((p_es->i_id & 0xF00) >> 8) )
267 input_SelectES( p_input, p_es );
272 if( main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, -1 )
273 == ((p_es->i_id & 0x1F00) >> 8) )
275 input_SelectES( p_input, p_es );
288 input_DumpStream( p_input );
290 vlc_mutex_unlock( &p_input->stream.stream_lock );
295 /* The programs will be added when we read them. */
296 vlc_mutex_lock( &p_input->stream.stream_lock );
297 p_input->stream.pp_programs[0]->b_is_ok = 0;
298 vlc_mutex_unlock( &p_input->stream.stream_lock );
302 /*****************************************************************************
303 * DVDEnd: frees unused data
304 *****************************************************************************/
305 static void DVDEnd( input_thread_t * p_input )
307 free( p_input->stream.p_demux_data );
308 free( p_input->p_plugin_data );
311 /*****************************************************************************
312 * SafeRead: reads a chunk of stream and correctly detects errors
313 *****************************************************************************/
314 static __inline__ int SafeRead( input_thread_t * p_input, byte_t * p_buffer,
317 // FIXME : aie aie ugly kludge for testing purposes :)
318 static byte_t p_tmp[2048];
321 thread_dvd_data_t * p_method;
325 p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
326 i_pos = lseek64( p_input->i_handle, 0, SEEK_CUR );
327 if( !p_method->b_encrypted )
329 i_nb = read( p_input->i_handle, p_buffer, i_len );
333 lseek64( p_input->i_handle, i_pos & ~0x7FF, SEEK_SET );
334 i_nb = read( p_input->i_handle, p_tmp, 0x800 );
335 CSSDescrambleSector( p_method->css.p_title_key[0].key, p_tmp );
336 memcpy( p_buffer, p_tmp + (i_pos & 0x7FF ), i_len );
344 intf_ErrMsg( "DVD: Read failed (%s)", strerror(errno) );
349 vlc_mutex_lock( &p_input->stream.stream_lock );
350 p_input->stream.i_tell =
351 lseek64( p_input->i_handle, i_pos+i_len, SEEK_SET );
352 vlc_mutex_unlock( &p_input->stream.stream_lock );
356 /*****************************************************************************
357 * DVDRead: reads data packets
358 *****************************************************************************
359 * Returns -1 in case of error, 0 if everything went well, and 1 in case of
361 *****************************************************************************/
362 static int DVDRead( input_thread_t * p_input,
363 data_packet_t * pp_packets[INPUT_READ_ONCE] )
366 data_packet_t * p_data;
367 size_t i_packet_size;
368 int i_packet, i_error;
369 thread_dvd_data_t * p_method;
371 p_method = (thread_dvd_data_t *)p_input->p_plugin_data;
373 memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
374 for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ )
376 /* Read what we believe to be a packet header. */
377 if( (i_error = SafeRead( p_input, p_header, 6 )) )
382 if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L )
384 /* This is not the startcode of a packet. Read the stream
385 * until we find one. */
386 u32 i_startcode = U32_AT(p_header);
392 /* It is common for MPEG-1 streams to pad with zeros
393 * (although it is forbidden by the recommendation), so
394 * don't bother everybody in this case. */
395 intf_WarnMsg( 1, "Garbage at input (%x)", i_startcode );
398 while( (i_startcode & 0xFFFFFF00) != 0x100L )
401 fprintf( stderr, "sprotch\n" );
402 if( (i_nb = SafeRead( p_input, &i_dummy, 1 )) != 0 )
404 i_startcode |= i_dummy;
413 *(u32 *)p_header = U32_AT(&i_startcode);
414 if( (i_error = SafeRead( p_input, p_header + 4, 2 )) )
420 if( U32_AT(p_header) != 0x1BA )
422 /* That's the case for all packets, except pack header. */
423 i_packet_size = U16_AT(&p_header[4]);
428 if( (p_header[4] & 0xC0) == 0x40 )
433 else if( (p_header[4] & 0xF0) == 0x20 )
440 intf_ErrMsg( "Unable to determine stream type" );
445 /* Fetch a packet of the appropriate size. */
446 if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL )
448 intf_ErrMsg( "Out of memory" );
452 /* Copy the header we already read. */
453 memcpy( p_data->p_buffer, p_header, 6 );
455 /* Read the remaining of the packet. */
456 if( i_packet_size && (i_error =
457 SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) )
462 /* In MPEG-2 pack headers we still have to read stuffing bytes. */
463 if( U32_AT(p_header) == 0x1BA )
465 if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 )
467 /* MPEG-2 stuffing bytes */
469 if( (i_error = SafeRead( p_input, p_garbage,
470 p_data->p_buffer[13] & 0x7)) )
477 /* Give the packet to the other input stages. */
478 pp_packets[i_packet] = p_data;
485 /*****************************************************************************
486 * DVDRewind : reads a stream backward
487 *****************************************************************************/
488 static int DVDRewind( input_thread_t * p_input )
493 /*****************************************************************************
494 * DVDSeek : Goes to a given position on the stream ; this one is used by the
495 * input and translate chronological position from input to logical postion
497 *****************************************************************************/
498 static int DVDSeek( input_thread_t * p_input, off_t i_off )
504 * Packet management utilities
507 /*****************************************************************************
508 * NewPacket: allocates a data packet
509 *****************************************************************************/
510 static struct data_packet_s * NewPacket( void * p_garbage,
513 data_packet_t * p_data;
516 if( i_size > INPUT_MAX_PACKET_SIZE )
518 intf_ErrMsg( "Packet too big (%d)", i_size );
522 if( (p_data = (data_packet_t *)malloc( sizeof(data_packet_t) )) == NULL )
524 intf_DbgMsg( "Out of memory" );
528 if( (p_data->p_buffer = (byte_t *)malloc( i_size )) == NULL )
530 intf_DbgMsg( "Out of memory" );
535 /* Initialize data */
536 p_data->p_next = NULL;
537 p_data->b_discard_payload = 0;
539 p_data->p_payload_start = p_data->p_buffer;
540 p_data->p_payload_end = p_data->p_buffer + i_size;
545 /*****************************************************************************
546 * NewPES: allocates a pes packet
547 *****************************************************************************/
548 static pes_packet_t * NewPES( void * p_garbage )
550 pes_packet_t * p_pes;
552 if( (p_pes = (pes_packet_t *)malloc( sizeof(pes_packet_t) )) == NULL )
554 intf_DbgMsg( "Out of memory" );
558 p_pes->b_messed_up = p_pes->b_data_alignment = p_pes->b_discontinuity =
559 p_pes->i_pts = p_pes->i_dts = 0;
560 p_pes->i_pes_size = 0;
561 p_pes->p_first = NULL;
566 /*****************************************************************************
567 * DeletePacket: deletes a data packet
568 *****************************************************************************/
569 static void DeletePacket( void * p_garbage,
570 data_packet_t * p_data )
573 ASSERT(p_data->p_buffer);
574 free( p_data->p_buffer );
578 /*****************************************************************************
579 * DeletePES: deletes a PES packet and associated data packets
580 *****************************************************************************/
581 static void DeletePES( void * p_garbage, pes_packet_t * p_pes )
583 data_packet_t * p_data;
584 data_packet_t * p_next;
586 p_data = p_pes->p_first;
588 while( p_data != NULL )
590 p_next = p_data->p_next;
591 free( p_data->p_buffer );
599 /*****************************************************************************
600 * DVDKludge: fakes a DVD plugin (FIXME)
601 *****************************************************************************/
602 input_capabilities_t * DVDKludge( void )
604 input_capabilities_t * p_plugin;
606 p_plugin = (input_capabilities_t *)malloc( sizeof(input_capabilities_t) );
607 p_plugin->pf_probe = DVDProbe;
608 p_plugin->pf_init = DVDInit;
609 p_plugin->pf_end = DVDEnd;
610 p_plugin->pf_read = DVDRead;
611 p_plugin->pf_demux = input_DemuxPS; /* FIXME: use i_p_config_t ! */
612 p_plugin->pf_new_packet = NewPacket;
613 p_plugin->pf_new_pes = NewPES;
614 p_plugin->pf_delete_packet = DeletePacket;
615 p_plugin->pf_delete_pes = DeletePES;
616 p_plugin->pf_rewind = DVDRewind;
617 p_plugin->pf_seek = DVDSeek;