1 /*****************************************************************************
2 * input_dvd.c: DVD raw reading plugin.
3 *****************************************************************************
4 * This plugins should handle all the known specificities of the DVD format,
5 * especially the 2048 bytes logical block size.
7 * -input_netlist used to read packets
8 * -dvd_ifo for ifo parsing and analyse
9 * -dvd_css for unscrambling
10 * -dvd_udf to find files
11 *****************************************************************************
12 * Copyright (C) 1998-2001 VideoLAN
13 * $Id: input_dvd.c,v 1.63 2001/05/31 01:37:08 sam Exp $
15 * Author: Stéphane Borel <stef@via.ecp.fr>
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
30 *****************************************************************************/
32 /*****************************************************************************
34 *****************************************************************************/
38 #define MODULE_NAME dvd
40 #define MODULE_NAME dvdnocss
42 #include "modules_inner.h"
52 #include <netinet/in.h>
56 #include <sys/types.h>
59 #ifdef STRNCASECMP_IN_STRINGS_H
65 #include <sys/uio.h> /* struct iovec */
81 #include "stream_control.h"
82 #include "input_ext-intf.h"
83 #include "input_ext-dec.h"
87 #include "dvd_netlist.h"
90 #include "dvd_summary.h"
91 #include "input_dvd.h"
92 #include "mpeg_system.h"
98 /*****************************************************************************
100 *****************************************************************************/
101 /* called from outside */
102 static int DVDProbe ( probedata_t
*p_data
);
103 static void DVDInit ( struct input_thread_s
* );
104 static void DVDEnd ( struct input_thread_s
* );
105 static int DVDSetArea ( struct input_thread_s
*, struct input_area_s
* );
106 static int DVDRead ( struct input_thread_s
*, data_packet_t
** );
107 static void DVDSeek ( struct input_thread_s
*, off_t
);
108 static int DVDRewind ( struct input_thread_s
* );
110 /* called only inside */
111 static int DVDChooseAngle( thread_dvd_data_t
* );
112 static int DVDFindCell( thread_dvd_data_t
* );
113 static int DVDFindSector( thread_dvd_data_t
* );
114 static int DVDChapterSelect( thread_dvd_data_t
*, int );
116 /*****************************************************************************
117 * Functions exported as capabilities. They are declared as static so that
118 * we don't pollute the namespace too much.
119 *****************************************************************************/
120 void _M( input_getfunctions
)( function_list_t
* p_function_list
)
122 #define input p_function_list->functions.input
123 p_function_list
->pf_probe
= DVDProbe
;
124 input
.pf_init
= DVDInit
;
125 input
.pf_open
= NULL
; /* Set in DVDInit */
126 input
.pf_close
= NULL
;
127 input
.pf_end
= DVDEnd
;
128 input
.pf_read
= DVDRead
;
129 input
.pf_set_area
= DVDSetArea
;
130 input
.pf_demux
= input_DemuxPS
;
131 input
.pf_new_packet
= DVDNewPacket
;
132 input
.pf_new_pes
= DVDNewPES
;
133 input
.pf_delete_packet
= DVDDeletePacket
;
134 input
.pf_delete_pes
= DVDDeletePES
;
135 input
.pf_rewind
= DVDRewind
;
136 input
.pf_seek
= DVDSeek
;
141 * Data reading functions
144 /*****************************************************************************
145 * DVDProbe: verifies that the stream is a PS stream
146 *****************************************************************************/
147 static int DVDProbe( probedata_t
*p_data
)
149 input_thread_t
* p_input
= (input_thread_t
*)p_data
;
151 char * psz_name
= p_input
->p_source
;
155 if( TestMethod( INPUT_METHOD_VAR
, "dvd" ) )
161 #endif /* HAVE_CSS */
164 if( ( strlen(psz_name
) > 4 ) && !strncasecmp( psz_name
, "dvd:", 4 ) )
166 /* If the user specified "dvd:" then it's probably a DVD */
171 #endif /* HAVE_CSS */
175 i_handle
= open( psz_name
, 0 );
185 /*****************************************************************************
186 * DVDInit: initializes DVD structures
187 *****************************************************************************/
188 static void DVDInit( input_thread_t
* p_input
)
190 thread_dvd_data_t
* p_dvd
;
191 input_area_t
* p_area
;
196 p_dvd
= malloc( sizeof(thread_dvd_data_t
) );
199 intf_ErrMsg( "dvd error: out of memory" );
200 p_input
->b_error
= 1;
204 p_input
->p_plugin_data
= (void *)p_dvd
;
205 p_input
->p_method_data
= NULL
;
207 p_dvd
->i_fd
= p_input
->i_handle
;
209 /* reading several block once seems to cause lock-up
210 * when using input_ToggleES
211 * who wrote thez damn buggy piece of shit ??? --stef */
212 p_dvd
->i_block_once
= 32;
213 p_input
->i_read_once
= 128;
215 i
= CSSTest( p_input
->i_handle
);
219 intf_ErrMsg( "dvd error: error in css" );
221 p_input
->b_error
= 1;
225 p_dvd
->b_encrypted
= i
;
227 lseek( p_input
->i_handle
, 0, SEEK_SET
);
229 /* Reading structures initialisation */
230 p_input
->p_method_data
=
231 DVDNetlistInit( 2048, 4096, 2048, DVD_LB_SIZE
, p_dvd
->i_block_once
);
232 intf_WarnMsg( 2, "dvd info: netlist initialized" );
234 /* Ifo allocation & initialisation */
235 if( IfoCreate( p_dvd
) < 0 )
237 intf_ErrMsg( "dvd error: allcation error in ifo" );
238 p_input
->b_error
= 1;
242 if( IfoInit( p_dvd
->p_ifo
) < 0 )
244 intf_ErrMsg( "dvd error: fatal failure in ifo" );
246 p_input
->b_error
= 1;
250 /* CSS initialisation */
251 if( p_dvd
->b_encrypted
)
253 p_dvd
->p_css
= malloc( sizeof(css_t
) );
254 if( p_dvd
->p_css
== NULL
)
256 intf_ErrMsg( "dvd error: couldn't create css structure" );
258 p_input
->b_error
= 1;
262 p_dvd
->p_css
->i_agid
= 0;
264 if( CSSInit( p_input
->i_handle
, p_dvd
->p_css
) < 0 )
266 intf_ErrMsg( "dvd error: fatal failure in css" );
267 free( p_dvd
->p_css
);
269 p_input
->b_error
= 1;
273 intf_WarnMsg( 2, "dvd info: css initialized" );
276 /* Set stream and area data */
277 vlc_mutex_lock( &p_input
->stream
.stream_lock
);
279 /* Initialize ES structures */
280 input_InitStream( p_input
, sizeof( stream_ps_data_t
) );
282 /* disc input method */
283 p_input
->stream
.i_method
= INPUT_METHOD_DVD
;
285 #define title_inf p_dvd->p_ifo->vmg.title_inf
286 intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf
.i_title_nb
);
288 #define area p_input->stream.pp_areas
289 /* We start from 1 here since the default area 0
290 * is reserved for video_ts.vob */
291 for( i
= 1 ; i
<= title_inf
.i_title_nb
; i
++ )
293 input_AddArea( p_input
);
295 /* Titles are Program Chains */
298 /* Absolute start offset and size
299 * We can only set that with vts ifo, so we do it during the
300 * first call to DVDSetArea */
301 area
[i
]->i_start
= 0;
304 /* Number of chapters */
305 area
[i
]->i_part_nb
= title_inf
.p_attr
[i
-1].i_chapter_nb
;
308 /* Number of angles */
309 area
[i
]->i_angle_nb
= 0;
310 area
[i
]->i_angle
= 1;
312 /* Offset to vts_i_0.ifo */
313 area
[i
]->i_plugin_data
= p_dvd
->p_ifo
->i_off
+
314 ( title_inf
.p_attr
[i
-1].i_start_sector
* DVD_LB_SIZE
);
318 /* Get requested title - if none try the first title */
319 i_title
= main_GetIntVariable( INPUT_TITLE_VAR
, 1 );
320 if( i_title
<= 0 || i_title
> title_inf
.i_title_nb
)
327 /* Get requested chapter - if none defaults to first one */
328 i_chapter
= main_GetIntVariable( INPUT_CHAPTER_VAR
, 1 );
334 p_input
->stream
.pp_areas
[i_title
]->i_part
= i_chapter
;
336 p_area
= p_input
->stream
.pp_areas
[i_title
];
338 /* set title, chapter, audio and subpic */
339 DVDSetArea( p_input
, p_area
);
341 vlc_mutex_unlock( &p_input
->stream
.stream_lock
);
346 /*****************************************************************************
347 * DVDEnd: frees unused data
348 *****************************************************************************/
349 static void DVDEnd( input_thread_t
* p_input
)
351 thread_dvd_data_t
* p_dvd
;
352 dvd_netlist_t
* p_netlist
;
354 p_dvd
= (thread_dvd_data_t
*)p_input
->p_plugin_data
;
355 p_netlist
= (dvd_netlist_t
*)p_input
->p_method_data
;
357 if( p_dvd
->b_encrypted
)
359 free( p_dvd
->p_css
);
362 IfoDestroy( p_dvd
->p_ifo
);
364 DVDNetlistEnd( p_netlist
);
367 /*****************************************************************************
368 * DVDSetArea: initialize input data for title x, chapter y.
369 * It should be called for each user navigation request.
370 *****************************************************************************
371 * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
372 * Note that you have to take the lock before entering here.
373 *****************************************************************************/
374 static int DVDSetArea( input_thread_t
* p_input
, input_area_t
* p_area
)
376 thread_dvd_data_t
* p_dvd
;
377 es_descriptor_t
* p_es
;
385 p_dvd
= (thread_dvd_data_t
*)p_input
->p_plugin_data
;
387 /* we can't use the interface slider until initilization is complete */
388 p_input
->stream
.b_seekable
= 0;
390 if( p_area
!= p_input
->stream
.p_selected_area
)
394 * We have to load all title information
396 /* Change the default area */
397 p_input
->stream
.p_selected_area
=
398 p_input
->stream
.pp_areas
[p_area
->i_id
];
400 /* release the lock to to let the interface go */
401 // vlc_mutex_unlock( &p_input->stream.stream_lock );
403 /* title number: it is not vts nb!,
404 * it is what appears in the interface list */
405 p_dvd
->i_title
= p_area
->i_id
;
406 p_dvd
->p_ifo
->i_title
= p_dvd
->i_title
;
408 /* set number of chapters of current title */
409 p_dvd
->i_chapter_nb
= p_area
->i_part_nb
;
412 if( IfoTitleSet( p_dvd
->p_ifo
) < 0 )
414 intf_ErrMsg( "dvd error: fatal error in vts ifo" );
416 p_input
->b_error
= 1;
420 #define vmg p_dvd->p_ifo->vmg
421 #define vts p_dvd->p_ifo->vts
422 /* title position inside the selected vts */
423 i_vts_title
= vmg
.title_inf
.p_attr
[p_dvd
->i_title
-1].i_title_num
;
425 vts
.title_inf
.p_title_start
[i_vts_title
-1].i_title_id
;
427 intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d",
432 /* css title key for current vts */
433 if( p_dvd
->b_encrypted
)
435 /* this one is vts number */
436 p_dvd
->p_css
->i_title
=
437 vmg
.title_inf
.p_attr
[p_dvd
->i_title
-1].i_title_set_num
;
438 p_dvd
->p_css
->i_title_pos
=
440 vts
.manager_inf
.i_title_vob_start_sector
* DVD_LB_SIZE
;
442 j
= CSSGetKey( p_input
->i_handle
, p_dvd
->p_css
);
445 intf_ErrMsg( "dvd error: fatal error in vts css key" );
447 p_input
->b_error
= 1;
452 intf_ErrMsg( "dvd error: css decryption unavailable" );
454 p_input
->b_error
= 1;
462 p_dvd
->i_angle_nb
= vmg
.title_inf
.p_attr
[p_dvd
->i_title
-1].i_angle_nb
;
463 p_dvd
->i_angle
= main_GetIntVariable( INPUT_ANGLE_VAR
, 1 );
464 if( ( p_dvd
->i_angle
<= 0 ) || p_dvd
->i_angle
> p_dvd
->i_angle_nb
)
470 * Set selected title start and size
473 /* title set offset */
474 p_dvd
->i_title_start
= vts
.i_pos
+ DVD_LB_SIZE
*
475 (off_t
)( vts
.manager_inf
.i_title_vob_start_sector
);
477 /* last video cell */
479 p_dvd
->i_prg_cell
= -1 +
480 vts
.title_unit
.p_title
[p_dvd
->i_title_id
-1].title
.i_cell_nb
;
482 if( DVDFindCell( p_dvd
) < 0 )
484 intf_ErrMsg( "dvd error: can't find title end" );
485 p_input
->b_error
= 1;
489 /* temporary hack to fix size in some dvds */
490 if( p_dvd
->i_cell
>= vts
.cell_inf
.i_cell_nb
)
492 p_dvd
->i_cell
= vts
.cell_inf
.i_cell_nb
- 1;
496 p_dvd
->i_size
= DVD_LB_SIZE
*
497 (off_t
)( vts
.cell_inf
.p_cell_map
[p_dvd
->i_cell
].i_end_sector
);
498 intf_WarnMsg( 2, "dvd info: stream size 1: %lld @ %d", p_dvd
->i_size
,
499 vts
.cell_inf
.p_cell_map
[p_dvd
->i_cell
].i_end_sector
);
501 if( DVDChapterSelect( p_dvd
, 1 ) < 0 )
503 intf_ErrMsg( "dvd error: can't find first chapter" );
504 p_input
->b_error
= 1;
508 p_dvd
->i_size
-= (off_t
)( p_dvd
->i_sector
+ 1 ) *DVD_LB_SIZE
;
510 IfoPrintTitle( p_dvd
);
512 // vlc_mutex_lock( &p_input->stream.stream_lock );
514 /* Area definition */
515 p_input
->stream
.p_selected_area
->i_start
= p_dvd
->i_start
;
516 p_input
->stream
.p_selected_area
->i_size
= p_dvd
->i_size
;
517 p_input
->stream
.p_selected_area
->i_angle_nb
= p_dvd
->i_angle_nb
;
518 p_input
->stream
.p_selected_area
->i_angle
= p_dvd
->i_angle
;
521 * Destroy obsolete ES by reinitializing program 0
522 * and find all ES in title with ifo data
524 if( p_input
->stream
.pp_programs
!= NULL
)
526 /* We don't use input_EndStream here since
527 * we keep area structures */
529 for( i
= 0 ; i
< p_input
->stream
.i_selected_es_number
; i
++ )
531 input_UnselectES( p_input
, p_input
->stream
.pp_selected_es
[i
] );
534 input_DelProgram( p_input
, p_input
->stream
.pp_programs
[0] );
536 p_input
->stream
.pp_selected_es
= NULL
;
537 p_input
->stream
.i_selected_es_number
= 0;
540 input_AddProgram( p_input
, 0, sizeof( stream_ps_data_t
) );
542 /* No PSM to read in DVD mode, we already have all information */
543 p_input
->stream
.pp_programs
[0]->b_is_ok
= 1;
544 p_input
->stream
.pp_programs
[0]->i_synchro_state
= SYNCHRO_START
;
548 /* ES 0 -> video MPEG2 */
549 IfoPrintVideo( p_dvd
);
551 p_es
= input_AddES( p_input
, p_input
->stream
.pp_programs
[0], 0xe0, 0 );
552 p_es
->i_stream_id
= 0xe0;
553 p_es
->i_type
= MPEG2_VIDEO_ES
;
554 p_es
->i_cat
= VIDEO_ES
;
555 intf_WarnMsg( 1, "dvd info: video mpeg2 stream" );
556 if( p_main
->b_video
)
558 input_SelectES( p_input
, p_es
);
560 intf_WarnMsg( 4, "dvd info: video selected" );
562 #define audio_status \
563 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
564 /* Audio ES, in the order they appear in .ifo */
565 for( i
= 1 ; i
<= vts
.manager_inf
.i_audio_nb
; i
++ )
567 IfoPrintAudio( p_dvd
, i
);
569 /* audio channel is active if first byte is 0x80 */
570 if( audio_status
.i_available
)
572 switch( vts
.manager_inf
.p_audio_attr
[i
-1].i_coding_mode
)
575 i_id
= ( ( 0x80 + audio_status
.i_position
) << 8 ) | 0xbd;
576 p_es
= input_AddES( p_input
,
577 p_input
->stream
.pp_programs
[0], i_id
, 0 );
578 p_es
->i_stream_id
= 0xbd;
579 p_es
->i_type
= AC3_AUDIO_ES
;
581 p_es
->i_cat
= AUDIO_ES
;
582 strcpy( p_es
->psz_desc
, IfoLanguage( hton16(
583 vts
.manager_inf
.p_audio_attr
[i
-1].i_lang_code
) ) );
584 strcat( p_es
->psz_desc
, " (ac3)" );
586 intf_WarnMsg( 3, "dvd info: audio stream %d %s\t(0x%x)",
587 i
, p_es
->psz_desc
, i_id
);
591 case 0x03: /* MPEG audio */
592 i_id
= 0xc0 + audio_status
.i_position
;
593 p_es
= input_AddES( p_input
,
594 p_input
->stream
.pp_programs
[0], i_id
, 0 );
595 p_es
->i_stream_id
= i_id
;
596 p_es
->i_type
= MPEG2_AUDIO_ES
;
598 p_es
->i_cat
= AUDIO_ES
;
599 strcpy( p_es
->psz_desc
, IfoLanguage( hton16(
600 vts
.manager_inf
.p_audio_attr
[i
-1].i_lang_code
) ) );
601 strcat( p_es
->psz_desc
, " (mpeg)" );
603 intf_WarnMsg( 3, "dvd info: audio stream %d %s\t(0x%x)",
604 i
, p_es
->psz_desc
, i_id
);
607 case 0x04: /* LPCM */
609 i_id
= ( ( 0xa0 + audio_status
.i_position
) << 8 ) | 0xbd;
610 p_es
= input_AddES( p_input
,
611 p_input
->stream
.pp_programs
[0], i_id
, 0 );
612 p_es
->i_stream_id
= i_id
;
613 p_es
->i_type
= LPCM_AUDIO_ES
;
615 p_es
->i_cat
= AUDIO_ES
;
616 strcpy( p_es
->psz_desc
, IfoLanguage( hton16(
617 vts
.manager_inf
.p_audio_attr
[i
-1].i_lang_code
) ) );
618 strcat( p_es
->psz_desc
, " (lpcm)" );
620 intf_WarnMsg( 3, "dvd info: audio stream %d %s\t(0x%x)",
621 i
, p_es
->psz_desc
, i_id
);
624 i_id
= ( ( 0x88 + audio_status
.i_position
) << 8 ) | 0xbd;
625 intf_ErrMsg( "dvd warning: DTS audio not handled yet"
630 intf_ErrMsg( "dvd warning: unknown audio type %.2x",
631 vts
.manager_inf
.p_audio_attr
[i
-1].i_coding_mode
);
637 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
641 for( i
= 1 ; i
<= vts
.manager_inf
.i_spu_nb
; i
++ )
643 IfoPrintSpu( p_dvd
, i
);
645 if( spu_status
.i_available
)
647 /* there are several streams for one spu */
648 if( vts
.manager_inf
.video_attr
.i_ratio
)
651 switch( vts
.manager_inf
.video_attr
.i_perm_displ
)
654 i_id
= ( ( 0x20 + spu_status
.i_position_pan
) << 8 )
658 i_id
= ( ( 0x20 + spu_status
.i_position_letter
) << 8 )
662 i_id
= ( ( 0x20 + spu_status
.i_position_wide
) << 8 )
670 i_id
= ( ( 0x20 + spu_status
.i_position_43
) << 8 )
673 p_es
= input_AddES( p_input
,
674 p_input
->stream
.pp_programs
[0], i_id
, 0 );
675 p_es
->i_stream_id
= 0xbd;
676 p_es
->i_type
= DVD_SPU_ES
;
677 p_es
->i_cat
= SPU_ES
;
678 strcpy( p_es
->psz_desc
, IfoLanguage( hton16(
679 vts
.manager_inf
.p_spu_attr
[i
-1].i_lang_code
) ) );
680 intf_WarnMsg( 3, "dvd info: spu stream %d %s\t(0x%x)",
681 i
, p_es
->psz_desc
, i_id
);
685 if( p_main
->b_audio
)
687 /* For audio: first one if none or a not existing one specified */
688 i_audio
= main_GetIntVariable( INPUT_CHANNEL_VAR
, 1 );
689 if( i_audio
< 0 || i_audio
> vts
.manager_inf
.i_audio_nb
)
691 main_PutIntVariable( INPUT_CHANNEL_VAR
, 1 );
694 if( i_audio
> 0 && vts
.manager_inf
.i_audio_nb
> 0 )
696 input_SelectES( p_input
, p_input
->stream
.pp_es
[i_audio
] );
700 if( p_main
->b_video
)
702 /* for spu, default is none */
703 i_spu
= main_GetIntVariable( INPUT_SUBTITLE_VAR
, 0 );
704 if( i_spu
< 0 || i_spu
> vts
.manager_inf
.i_spu_nb
)
706 main_PutIntVariable( INPUT_SUBTITLE_VAR
, 0 );
709 if( i_spu
> 0 && vts
.manager_inf
.i_spu_nb
> 0 )
711 i_spu
+= vts
.manager_inf
.i_audio_nb
;
712 input_SelectES( p_input
, p_input
->stream
.pp_es
[i_spu
] );
718 p_area
= p_input
->stream
.p_selected_area
;
728 if( p_area
->i_part
!= p_dvd
->i_chapter
)
730 if( ( p_area
->i_part
> 0 ) &&
731 ( p_area
->i_part
<= p_area
->i_part_nb
))
733 if( DVDChapterSelect( p_dvd
, p_area
->i_part
) < 0 )
735 intf_ErrMsg( "dvd error: can't set chapter in area" );
736 p_input
->b_error
= 1;
740 p_input
->stream
.p_selected_area
->i_tell
= p_dvd
->i_start
-
742 p_input
->stream
.p_selected_area
->i_part
= p_dvd
->i_chapter
;
744 intf_WarnMsg( 2, "dvd info: chapter %d start at: %lld",
745 p_area
->i_part
, p_area
->i_tell
);
750 p_dvd
->i_chapter
= 1;
755 p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
756 if( p_area
->i_angle
!= p_dvd
->i_angle
)
758 if( title
.p_cell_play
[p_dvd
->i_prg_cell
].i_category
& 0xf000 )
760 if( ( p_area
->i_angle
- p_dvd
->i_angle
) < 0 )
764 p_dvd
->i_prg_cell
+= ( p_area
->i_angle
- p_dvd
->i_angle
);
765 p_dvd
->i_angle
= p_area
->i_angle
;
767 DVDFindSector( p_dvd
);
768 p_dvd
->i_cell
+= p_dvd
->i_angle_cell
;
772 p_dvd
->i_angle
= p_area
->i_angle
;
775 intf_WarnMsg( 2, "dvd info: angle %d selected", p_area
->i_angle
);
778 /* warn interface that something has changed */
779 p_input
->stream
.b_seekable
= 1;
780 p_input
->stream
.b_changed
= 1;
782 p_input
->stream
.pp_programs
[0]->i_synchro_state
= SYNCHRO_REINIT
;
788 /*****************************************************************************
789 * DVDRead: reads data packets into the netlist.
790 *****************************************************************************
791 * Returns -1 in case of error, 0 if everything went well, and 1 in case of
793 *****************************************************************************/
794 static int DVDRead( input_thread_t
* p_input
,
795 data_packet_t
** pp_packets
)
797 thread_dvd_data_t
* p_dvd
;
798 dvd_netlist_t
* p_netlist
;
799 struct iovec
* p_vec
;
800 struct data_packet_s
** pp_data
;
813 pp_data
= (struct data_packet_s
**) malloc( p_input
->i_read_once
*
814 sizeof( struct data_packet_s
* ) );
815 if( pp_data
== NULL
)
817 intf_ErrMsg( "dvd error: out of memory" );
821 p_dvd
= (thread_dvd_data_t
*)p_input
->p_plugin_data
;
822 p_netlist
= (dvd_netlist_t
*)p_input
->p_method_data
;
824 /* Get an iovec pointer */
825 if( ( p_vec
= DVDGetiovec( p_netlist
) ) == NULL
)
827 intf_ErrMsg( "dvd error: can't get iovec" );
832 i_block_once
= p_dvd
->i_end_sector
- p_dvd
->i_sector
+ 1;
834 /* Get the position of the next cell if we're at cell end */
835 if( i_block_once
<= 0 )
840 p_dvd
->i_angle_cell
++;
842 /* Find cell index in adress map */
843 if( DVDFindSector( p_dvd
) < 0 )
845 pp_packets
[0] = NULL
;
846 intf_ErrMsg( "dvd error: can't find next cell" );
851 /* Position the fd pointer on the right address */
852 i_off
= lseek( p_dvd
->i_fd
,
853 p_dvd
->i_title_start
+
854 (off_t
)( p_dvd
->i_sector
) *DVD_LB_SIZE
, SEEK_SET
);
856 /* update chapter : it will be easier when we have navigation
858 if( p_dvd
->i_chapter
< ( p_dvd
->i_chapter_nb
- 1 ) )
860 if( title
.p_cell_play
[p_dvd
->i_prg_cell
].i_category
& 0xf000 )
862 i_angle
= p_dvd
->i_angle
- 1;
868 if( title
.chapter_map
.pi_start_cell
[p_dvd
->i_chapter
] <=
869 ( p_dvd
->i_prg_cell
- i_angle
+ 1 ) )
875 vlc_mutex_lock( &p_input
->stream
.stream_lock
);
877 p_input
->stream
.p_selected_area
->i_tell
= i_off
-
878 p_input
->stream
.p_selected_area
->i_start
;
879 p_input
->stream
.p_selected_area
->i_part
= p_dvd
->i_chapter
;
881 /* the synchro has to be reinitialized when we change cell */
882 p_input
->stream
.pp_programs
[0]->i_synchro_state
= SYNCHRO_REINIT
;
884 vlc_mutex_unlock( &p_input
->stream
.stream_lock
);
886 i_block_once
= p_dvd
->i_end_sector
- p_dvd
->i_sector
+ 1;
889 /* the number of blocks read is the maw between the requested
890 * value and the leaving block in the cell */
891 if( i_block_once
> p_dvd
->i_block_once
)
893 i_block_once
= p_dvd
->i_block_once
;
895 //intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
897 p_netlist
->i_read_once
= i_block_once
;
900 i_read_bytes
= readv( p_dvd
->i_fd
, p_vec
, i_block_once
);
901 i_read_blocks
= ( i_read_bytes
+ 0x7ff ) >> 11;
903 /* Update netlist indexes */
904 DVDMviovec( p_netlist
, i_read_blocks
, pp_data
);
906 /* Update global position */
907 p_dvd
->i_sector
+= i_read_blocks
;
911 /* Read headers to compute payload length */
912 for( i_iovec
= 0 ; i_iovec
< i_read_blocks
; i_iovec
++ )
914 if( p_dvd
->b_encrypted
)
916 CSSDescrambleSector( p_dvd
->p_css
->pi_title_key
,
917 p_vec
[i_iovec
].iov_base
);
918 ((u8
*)(p_vec
[i_iovec
].iov_base
))[0x14] &= 0x8F;
923 while( i_pos
< p_netlist
->i_buffer_size
)
925 pi_cur
= ((u8
*)p_vec
[i_iovec
].iov_base
+ i_pos
);
928 if( U32_AT( pi_cur
) != 0x1BA )
930 /* That's the case for all packets, except pack header. */
931 i_packet_size
= U16_AT( pi_cur
+ 4 );
932 pp_packets
[i_packet
] = DVDNewPtr( p_netlist
);
937 if( ( pi_cur
[4] & 0xC0 ) == 0x40 )
942 else if( ( pi_cur
[4] & 0xF0 ) == 0x20 )
949 intf_ErrMsg( "Unable to determine stream type" );
954 pp_packets
[i_packet
] = pp_data
[i_iovec
];
958 (*pp_data
[i_iovec
]->pi_refcount
)++;
960 pp_packets
[i_packet
]->pi_refcount
= pp_data
[i_iovec
]->pi_refcount
;
962 pp_packets
[i_packet
]->p_buffer
= pp_data
[i_iovec
]->p_buffer
;
964 pp_packets
[i_packet
]->p_payload_start
=
965 pp_packets
[i_packet
]->p_buffer
+ i_pos
;
967 pp_packets
[i_packet
]->p_payload_end
=
968 pp_packets
[i_packet
]->p_payload_start
+ i_packet_size
+ 6;
970 pp_packets
[i_packet
]->p_next
= NULL
;
971 pp_packets
[i_packet
]->b_discard_payload
= 0;
974 i_pos
+= i_packet_size
+ 6;
978 pp_packets
[i_packet
] = NULL
;
980 vlc_mutex_lock( &p_input
->stream
.stream_lock
);
982 p_input
->stream
.p_selected_area
->i_tell
+= i_read_bytes
;
983 b_eot
= !( p_input
->stream
.p_selected_area
->i_tell
< p_dvd
->i_size
);
984 b_eof
= b_eot
&& ( ( p_dvd
->i_title
+ 1 ) >= p_input
->stream
.i_area_nb
);
986 vlc_mutex_unlock( &p_input
->stream
.stream_lock
);
997 intf_WarnMsg( 4, "dvd info: new title" );
999 vlc_mutex_lock( &p_input
->stream
.stream_lock
);
1000 DVDSetArea( p_input
, p_input
->stream
.pp_areas
[p_dvd
->i_title
] );
1001 vlc_mutex_unlock( &p_input
->stream
.stream_lock
);
1005 if( i_read_blocks
== i_block_once
)
1013 /*****************************************************************************
1014 * DVDRewind : reads a stream backward
1015 *****************************************************************************/
1016 static int DVDRewind( input_thread_t
* p_input
)
1021 /*****************************************************************************
1022 * DVDSeek : Goes to a given position on the stream.
1023 *****************************************************************************
1024 * This one is used by the input and translate chronological position from
1025 * input to logical position on the device.
1026 * The lock should be taken before calling this function.
1027 *****************************************************************************/
1028 static void DVDSeek( input_thread_t
* p_input
, off_t i_off
)
1030 thread_dvd_data_t
* p_dvd
;
1037 p_dvd
= ( thread_dvd_data_t
* )p_input
->p_plugin_data
;
1039 /* we have to take care of offset of beginning of title */
1040 i_pos
= i_off
+ p_input
->stream
.p_selected_area
->i_start
1041 - p_dvd
->i_title_start
;
1043 /* update navigation data */
1044 p_dvd
->i_sector
= i_pos
>> 11;
1049 /* parse vobu address map to find program cell */
1050 while( title
.p_cell_play
[i_prg_cell
].i_end_sector
< p_dvd
->i_sector
)
1055 p_dvd
->i_prg_cell
= i_prg_cell
;
1057 if( DVDChooseAngle( p_dvd
) < 0 )
1059 p_input
->b_error
= 1;
1065 /* Find first title cell which is inside program cell */
1066 if( DVDFindCell( p_dvd
) < 0 )
1068 /* no following cell : we're at eof */
1069 intf_ErrMsg( "dvd error: cell seeking failed" );
1070 p_input
->b_error
= 1;
1074 i_cell
= p_dvd
->i_cell
;
1076 #define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
1077 /* parse cell address map to find title cell containing sector */
1078 while( cell
.i_end_sector
< p_dvd
->i_sector
)
1083 p_dvd
->i_cell
= i_cell
;
1085 /* if we're inside a multi-angle zone, we have to choose i_sector
1086 * in the current angle ; we can't do it all the time since cells
1087 * can be very wide out of such zones */
1088 if( title
.p_cell_play
[p_dvd
->i_prg_cell
].i_category
& 0xf000 )
1090 p_dvd
->i_sector
= MAX(
1091 cell
.i_start_sector
,
1092 title
.p_cell_play
[p_dvd
->i_prg_cell
].i_start_sector
);
1095 p_dvd
->i_end_sector
= MIN(
1097 title
.p_cell_play
[p_dvd
->i_prg_cell
].i_end_sector
);
1099 /* update chapter */
1100 if( title
.p_cell_play
[p_dvd
->i_prg_cell
].i_category
& 0xf000 )
1102 i_angle
= p_dvd
->i_angle
- 1;
1108 while( ( title
.chapter_map
.pi_start_cell
[i_chapter
] <=
1109 ( p_dvd
->i_prg_cell
- i_angle
+ 1 ) ) &&
1110 ( i_chapter
< ( p_dvd
->i_chapter_nb
- 1 ) ) )
1115 p_dvd
->i_chapter
= i_chapter
;
1116 p_input
->stream
.p_selected_area
->i_part
= p_dvd
->i_chapter
;
1118 p_input
->stream
.p_selected_area
->i_tell
=
1119 lseek( p_dvd
->i_fd
, p_dvd
->i_title_start
+
1120 (off_t
)( p_dvd
->i_sector
) *DVD_LB_SIZE
, SEEK_SET
) -
1121 p_input
->stream
.p_selected_area
->i_start
;
1123 intf_WarnMsg( 3, "Program Cell: %d Cell: %d Chapter: %d",
1124 p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter );
1130 #define cell p_dvd->p_ifo->vts.cell_inf
1132 /*****************************************************************************
1133 * DVDFindCell: adjust the title cell index with the program cell
1134 *****************************************************************************/
1135 static int DVDFindCell( thread_dvd_data_t
* p_dvd
)
1140 i_cell
= p_dvd
->i_cell
;
1141 i_index
= p_dvd
->i_prg_cell
;
1143 if( i_cell
>= cell
.i_cell_nb
)
1148 while( ( ( title
.p_cell_pos
[i_index
].i_vob_id
!=
1149 cell
.p_cell_map
[i_cell
].i_vob_id
) ||
1150 ( title
.p_cell_pos
[i_index
].i_cell_id
!=
1151 cell
.p_cell_map
[i_cell
].i_cell_id
) ) &&
1152 ( i_cell
< cell
.i_cell_nb
- 1 ) )
1158 intf_WarnMsg( 3, "FindCell: i_cell %d i_index %d found %d nb %d",
1165 p_dvd
->i_cell
= i_cell
;
1172 /*****************************************************************************
1173 * DVDFindSector: find cell index in adress map from index in
1174 * information table program map and give corresponding sectors.
1175 *****************************************************************************/
1176 static int DVDFindSector( thread_dvd_data_t
* p_dvd
)
1179 if( p_dvd
->i_sector
> title
.p_cell_play
[p_dvd
->i_prg_cell
].i_end_sector
)
1181 p_dvd
->i_prg_cell
++;
1183 if( DVDChooseAngle( p_dvd
) < 0 )
1189 if( DVDFindCell( p_dvd
) < 0 )
1191 intf_ErrMsg( "dvd error: can't find sector" );
1195 /* Find start and end sectors of new cell */
1197 p_dvd
->i_sector
= MAX(
1198 p_dvd
->p_ifo
->vts
.cell_inf
.p_cell_map
[p_dvd
->i_cell
].i_start_sector
,
1199 title
.p_cell_play
[p_dvd
->i_prg_cell
].i_start_sector
);
1200 p_dvd
->i_end_sector
= MIN(
1201 p_dvd
->p_ifo
->vts
.cell_inf
.p_cell_map
[p_dvd
->i_cell
].i_end_sector
,
1202 title
.p_cell_play
[p_dvd
->i_prg_cell
].i_end_sector
);
1204 p_dvd
->i_sector
= title
.p_cell_play
[p_dvd
->i_prg_cell
].i_start_sector
;
1205 p_dvd
->i_end_sector
= title
.p_cell_play
[p_dvd
->i_prg_cell
].i_end_sector
;
1209 intf_WarnMsg( 3, "cell: %d sector1: 0x%x end1: 0x%x\n"
1210 "index: %d sector2: 0x%x end2: 0x%x\n"
1211 "category: 0x%x ilvu end: 0x%x vobu start 0x%x",
1213 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1214 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1216 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector,
1217 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector,
1218 title.p_cell_play[p_dvd->i_prg_cell].i_category,
1219 title.p_cell_play[p_dvd->i_prg_cell].i_first_ilvu_vobu_esector,
1220 title.p_cell_play[p_dvd->i_prg_cell].i_last_vobu_start_sector );
1226 /*****************************************************************************
1227 * DVDChapterSelect: find the cell corresponding to requested chapter
1228 *****************************************************************************/
1229 static int DVDChapterSelect( thread_dvd_data_t
* p_dvd
, int i_chapter
)
1232 /* Find cell index in Program chain for current chapter */
1233 p_dvd
->i_prg_cell
= title
.chapter_map
.pi_start_cell
[i_chapter
-1] - 1;
1235 p_dvd
->i_sector
= 0;
1237 DVDChooseAngle( p_dvd
);
1239 /* Search for cell_index in cell adress_table and initialize
1241 if( DVDFindSector( p_dvd
) < 0 )
1243 intf_ErrMsg( "dvd error: can't select chapter" );
1247 /* start is : beginning of vts vobs + offset to vob x */
1248 p_dvd
->i_start
= p_dvd
->i_title_start
+
1249 DVD_LB_SIZE
* (off_t
)( p_dvd
->i_sector
);
1251 /* Position the fd pointer on the right address */
1252 p_dvd
->i_start
= lseek( p_dvd
->i_fd
, p_dvd
->i_start
, SEEK_SET
);
1254 p_dvd
->i_chapter
= i_chapter
;
1258 /*****************************************************************************
1259 * DVDChooseAngle: select the cell corresponding to the selected angle
1260 *****************************************************************************/
1261 static int DVDChooseAngle( thread_dvd_data_t
* p_dvd
)
1263 /* basic handling of angles */
1264 switch( ( ( title
.p_cell_play
[p_dvd
->i_prg_cell
].i_category
& 0xf000 )
1267 /* we enter a muli-angle section */
1269 p_dvd
->i_prg_cell
+= p_dvd
->i_angle
- 1;
1270 p_dvd
->i_angle_cell
= 0;
1272 /* we exit a multi-angle section */
1275 p_dvd
->i_prg_cell
+= p_dvd
->i_angle_nb
- p_dvd
->i_angle
;