WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / bd.c
blob7da108c5019ac6be096326ad13ba6d3360c1b4d2
1 /* dvd.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "hb.h"
11 #include "lang.h"
12 #include "hbffmpeg.h"
14 #include "libbluray/bluray.h"
16 struct hb_bd_s
18 char * path;
19 BLURAY * bd;
20 int title_count;
21 BLURAY_TITLE_INFO ** title_info;
22 int64_t duration;
23 hb_stream_t * stream;
24 int chapter;
25 int next_chap;
26 hb_handle_t * h;
29 /***********************************************************************
30 * Local prototypes
31 **********************************************************************/
32 static int next_packet( BLURAY *bd, uint8_t *pkt );
33 static int title_info_compare_mpls(const void *, const void *);
35 /***********************************************************************
36 * hb_bd_init
37 ***********************************************************************
39 **********************************************************************/
40 hb_bd_t * hb_bd_init( hb_handle_t *h, char * path )
42 hb_bd_t * d;
43 int ii;
45 d = calloc( sizeof( hb_bd_t ), 1 );
46 d->h = h;
48 /* Open device */
49 d->bd = bd_open( path, NULL );
50 if( d->bd == NULL )
53 * Not an error, may be a stream - which we'll try in a moment.
55 hb_log( "bd: not a bd - trying as a stream/file instead" );
56 goto fail;
59 d->title_count = bd_get_titles( d->bd, TITLES_RELEVANT, 0 );
60 if ( d->title_count == 0 )
62 hb_log( "bd: not a bd - trying as a stream/file instead" );
63 goto fail;
65 d->title_info = calloc( sizeof( BLURAY_TITLE_INFO* ) , d->title_count );
66 for ( ii = 0; ii < d->title_count; ii++ )
68 d->title_info[ii] = bd_get_title_info( d->bd, ii, 0 );
70 qsort(d->title_info, d->title_count, sizeof( BLURAY_TITLE_INFO* ), title_info_compare_mpls );
71 d->path = strdup( path );
73 return d;
75 fail:
76 if( d->bd ) bd_close( d->bd );
77 free( d );
78 return NULL;
81 /***********************************************************************
82 * hb_bd_title_count
83 **********************************************************************/
84 int hb_bd_title_count( hb_bd_t * d )
86 return d->title_count;
89 static void add_subtitle(int track, hb_list_t *list_subtitle, BLURAY_STREAM_INFO *bdsub, uint32_t codec)
91 hb_subtitle_t * subtitle;
92 iso639_lang_t * lang;
94 subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
96 subtitle->track = track;
97 subtitle->id = bdsub->pid;
98 lang = lang_for_code2( (char*)bdsub->lang );
99 snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
100 strlen(lang->native_name) ? lang->native_name : lang->eng_name);
101 snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
102 lang->iso639_2);
104 switch ( bdsub->coding_type )
106 case BLURAY_STREAM_TYPE_SUB_PG:
107 subtitle->source = PGSSUB;
108 subtitle->format = PICTURESUB;
109 subtitle->config.dest = RENDERSUB;
110 break;
111 default:
112 // Unrecognized, don't add to list
113 free( subtitle );
114 return;
116 subtitle->reg_desc = STR4_TO_UINT32("HDMV");
117 subtitle->stream_type = bdsub->coding_type;
118 subtitle->codec = codec;
120 hb_log( "bd: subtitle id=0x%x, lang=%s, 3cc=%s", subtitle->id,
121 subtitle->lang, subtitle->iso639_2 );
123 hb_list_add( list_subtitle, subtitle );
124 return;
127 static void add_audio(int track, hb_list_t *list_audio, BLURAY_STREAM_INFO *bdaudio, int substream_type, uint32_t codec, uint32_t codec_param)
129 const char * codec_name;
130 hb_audio_t * audio;
131 iso639_lang_t * lang;
133 audio = calloc( sizeof( hb_audio_t ), 1 );
135 audio->id = (substream_type << 16) | bdaudio->pid;
136 audio->config.in.reg_desc = STR4_TO_UINT32("HDMV");
137 audio->config.in.stream_type = bdaudio->coding_type;
138 audio->config.in.substream_type = substream_type;
139 audio->config.in.codec = codec;
140 audio->config.in.codec_param = codec_param;
142 switch( audio->config.in.codec )
144 case HB_ACODEC_AC3:
145 codec_name = "AC3";
146 break;
147 case HB_ACODEC_DCA:
148 codec_name = "DTS";
149 break;
150 default:
152 if( audio->config.in.codec & HB_ACODEC_FF_MASK )
154 switch( bdaudio->coding_type )
156 case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
157 codec_name = "E-AC3";
158 break;
159 case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
160 codec_name = "DTS-HD HRA";
161 break;
162 case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
163 codec_name = "DTS-HD MA";
164 break;
165 case BLURAY_STREAM_TYPE_AUDIO_LPCM:
166 codec_name = "BD LPCM";
167 break;
168 case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
169 codec_name = "MPEG1";
170 break;
171 case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
172 codec_name = "MPEG2";
173 break;
174 case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
175 codec_name = "TrueHD";
176 break;
177 default:
178 codec_name = "Unknown FFmpeg";
179 break;
182 else
184 codec_name = "Unknown";
187 break;
190 lang = lang_for_code2( (char*)bdaudio->lang );
192 audio->config.lang.type = 0;
194 snprintf( audio->config.lang.simple,
195 sizeof( audio->config.lang.simple ), "%s",
196 strlen( lang->native_name ) ? lang->native_name : lang->eng_name );
197 snprintf( audio->config.lang.iso639_2,
198 sizeof( audio->config.lang.iso639_2 ), "%s", lang->iso639_2 );
200 hb_log("bd: audio id=0x%x, lang=%s (%s), 3cc=%s", audio->id,
201 audio->config.lang.simple, codec_name, audio->config.lang.iso639_2);
203 audio->config.in.track = track;
204 hb_list_add( list_audio, audio );
205 return;
208 static int bd_audio_equal( BLURAY_CLIP_INFO *a, BLURAY_CLIP_INFO *b )
210 int ii, jj, equal;
212 if ( a->audio_stream_count != b->audio_stream_count )
213 return 0;
215 if ( a->audio_stream_count == 0 )
216 return 0;
218 for ( ii = 0; ii < a->audio_stream_count; ii++ )
220 BLURAY_STREAM_INFO * s = &a->audio_streams[ii];
221 equal = 0;
222 for ( jj = 0; jj < b->audio_stream_count; jj++ )
224 if ( s->pid == b->audio_streams[jj].pid &&
225 s->coding_type == b->audio_streams[jj].coding_type)
227 equal = 1;
228 break;
231 if ( !equal )
232 return 0;
234 return 1;
237 /***********************************************************************
238 * hb_bd_title_scan
239 **********************************************************************/
240 hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
243 hb_title_t * title;
244 hb_chapter_t * chapter;
245 int ii, jj;
246 BLURAY_TITLE_INFO * ti = NULL;
248 hb_log( "bd: scanning title %d", tt );
250 title = hb_title_init( d->path, tt );
251 title->demuxer = HB_TS_DEMUXER;
252 title->type = HB_BD_TYPE;
253 title->reg_desc = STR4_TO_UINT32("HDMV");
255 char * p_cur, * p_last = d->path;
256 for( p_cur = d->path; *p_cur; p_cur++ )
258 if( IS_DIR_SEP(p_cur[0]) && p_cur[1] )
260 p_last = &p_cur[1];
263 snprintf( title->name, sizeof( title->name ), "%s", p_last );
264 char *dot_term = strrchr(title->name, '.');
265 if (dot_term)
266 *dot_term = '\0';
268 title->vts = 0;
269 title->ttn = 0;
271 ti = d->title_info[tt - 1];
272 if ( ti == NULL )
274 hb_log( "bd: invalid title" );
275 goto fail;
277 if ( ti->clip_count == 0 )
279 hb_log( "bd: stream has no clips" );
280 goto fail;
282 if ( ti->clips[0].video_stream_count == 0 )
284 hb_log( "bd: stream has no video" );
285 goto fail;
288 hb_log( "bd: playlist %05d.MPLS", ti->playlist );
289 title->playlist = ti->playlist;
291 uint64_t pkt_count = 0;
292 for ( ii = 0; ii < ti->clip_count; ii++ )
294 pkt_count += ti->clips[ii].pkt_count;
296 title->block_start = 0;
297 title->block_end = pkt_count;
298 title->block_count = pkt_count;
300 title->angle_count = ti->angle_count;
302 /* Get duration */
303 title->duration = ti->duration;
304 title->hours = title->duration / 90000 / 3600;
305 title->minutes = ( ( title->duration / 90000 ) % 3600 ) / 60;
306 title->seconds = ( title->duration / 90000 ) % 60;
307 hb_log( "bd: duration is %02d:%02d:%02d (%"PRIu64" ms)",
308 title->hours, title->minutes, title->seconds,
309 title->duration / 90 );
311 /* ignore short titles because they're often stills */
312 if( ti->duration < min_duration )
314 hb_log( "bd: ignoring title (too short)" );
315 goto fail;
318 BLURAY_STREAM_INFO * bdvideo = &ti->clips[0].video_streams[0];
320 title->video_id = bdvideo->pid;
321 title->video_stream_type = bdvideo->coding_type;
323 hb_log( "bd: video id=0x%x, stream type=%s, format %s", title->video_id,
324 bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG1 ? "MPEG1" :
325 bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG2 ? "MPEG2" :
326 bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_VC1 ? "VC-1" :
327 bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_H264 ? "H.264" :
328 "Unknown",
329 bdvideo->format == BLURAY_VIDEO_FORMAT_480I ? "480i" :
330 bdvideo->format == BLURAY_VIDEO_FORMAT_576I ? "576i" :
331 bdvideo->format == BLURAY_VIDEO_FORMAT_480P ? "480p" :
332 bdvideo->format == BLURAY_VIDEO_FORMAT_1080I ? "1080i" :
333 bdvideo->format == BLURAY_VIDEO_FORMAT_720P ? "720p" :
334 bdvideo->format == BLURAY_VIDEO_FORMAT_1080P ? "1080p" :
335 bdvideo->format == BLURAY_VIDEO_FORMAT_576P ? "576p" :
336 "Unknown"
339 switch( bdvideo->coding_type )
341 case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
342 case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
343 title->video_codec = WORK_DECAVCODECV;
344 title->video_codec_param = AV_CODEC_ID_MPEG2VIDEO;
345 break;
347 case BLURAY_STREAM_TYPE_VIDEO_VC1:
348 title->video_codec = WORK_DECAVCODECV;
349 title->video_codec_param = AV_CODEC_ID_VC1;
350 break;
352 case BLURAY_STREAM_TYPE_VIDEO_H264:
353 title->video_codec = WORK_DECAVCODECV;
354 title->video_codec_param = AV_CODEC_ID_H264;
355 break;
357 default:
358 hb_log( "scan: unknown video codec (0x%x)",
359 bdvideo->coding_type );
360 goto fail;
363 switch ( bdvideo->aspect )
365 case BLURAY_ASPECT_RATIO_4_3:
366 title->container_dar.num = 4;
367 title->container_dar.den = 3;
368 break;
369 case BLURAY_ASPECT_RATIO_16_9:
370 title->container_dar.num = 16;
371 title->container_dar.den = 9;
372 break;
373 default:
374 hb_log( "bd: unknown aspect" );
375 goto fail;
377 hb_log("bd: aspect = %d:%d",
378 title->container_dar.num, title->container_dar.den);
380 /* Detect audio */
381 // Max primary BD audios is 32
382 int matches;
383 int most_audio = 0;
384 int audio_clip_index = 0;
385 if (ti->clip_count > 2)
387 // All BD clips are not all required to have the same audio.
388 // But clips that have seamless transition are required
389 // to have the same audio as the previous clip.
390 // So find the clip that has the most other clips with the
391 // matching audio.
392 for ( ii = 0; ii < ti->clip_count; ii++ )
394 matches = 0;
395 for ( jj = 0; jj < ti->clip_count; jj++ )
397 if ( bd_audio_equal( &ti->clips[ii], &ti->clips[jj] ) )
399 matches++;
402 if ( matches > most_audio )
404 most_audio = matches;
405 audio_clip_index = ii;
409 else if (ti->clip_count == 2)
411 // If there are only 2 clips, pick audios from the longer clip
412 if (ti->clips[0].pkt_count < ti->clips[1].pkt_count)
413 audio_clip_index = 1;
416 // Add all the audios found in the above clip.
417 for (ii = 0; ii < ti->clips[audio_clip_index].audio_stream_count; ii++)
419 BLURAY_STREAM_INFO * bdaudio;
421 bdaudio = &ti->clips[audio_clip_index].audio_streams[ii];
423 switch (bdaudio->coding_type)
425 case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
426 // Add 2 audio tracks. One for TrueHD and one for AC-3
427 add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_AC3,
428 HB_ACODEC_AC3, AV_CODEC_ID_AC3);
429 add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_TRUEHD,
430 HB_ACODEC_FFTRUEHD, AV_CODEC_ID_TRUEHD);
431 break;
433 case BLURAY_STREAM_TYPE_AUDIO_DTS:
434 add_audio(ii, title->list_audio, bdaudio, 0,
435 HB_ACODEC_DCA, AV_CODEC_ID_DTS);
436 break;
438 case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
439 case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
440 add_audio(ii, title->list_audio, bdaudio, 0,
441 HB_ACODEC_FFMPEG, AV_CODEC_ID_MP2);
442 break;
444 case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
445 add_audio(ii, title->list_audio, bdaudio, 0,
446 HB_ACODEC_FFEAC3, AV_CODEC_ID_EAC3);
447 break;
449 case BLURAY_STREAM_TYPE_AUDIO_LPCM:
450 add_audio(ii, title->list_audio, bdaudio, 0,
451 HB_ACODEC_FFMPEG, AV_CODEC_ID_PCM_BLURAY);
452 break;
454 case BLURAY_STREAM_TYPE_AUDIO_AC3:
455 add_audio(ii, title->list_audio, bdaudio, 0,
456 HB_ACODEC_AC3, AV_CODEC_ID_AC3);
457 break;
459 case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
460 case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
461 // Add 2 audio tracks. One for DTS-HD and one for DTS
462 add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_DTS,
463 HB_ACODEC_DCA, AV_CODEC_ID_DTS);
464 // DTS-HD is special. The substreams must be concatinated
465 // DTS-core followed by DTS-hd-extensions. Setting
466 // a substream id of 0 says use all substreams.
467 add_audio(ii, title->list_audio, bdaudio, 0,
468 HB_ACODEC_DCA_HD, AV_CODEC_ID_DTS);
469 break;
471 default:
472 hb_log("scan: unknown audio pid 0x%x codec 0x%x", bdaudio->pid,
473 bdaudio->coding_type);
474 break;
478 // Add all the subtitles found in the above clip.
479 for ( ii = 0; ii < ti->clips[audio_clip_index].pg_stream_count; ii++ )
481 BLURAY_STREAM_INFO * bdpgs;
483 bdpgs = &ti->clips[audio_clip_index].pg_streams[ii];
485 switch( bdpgs->coding_type )
487 case BLURAY_STREAM_TYPE_SUB_PG:
488 add_subtitle(ii, title->list_subtitle, bdpgs, WORK_DECPGSSUB);
489 break;
490 default:
491 hb_log( "scan: unknown subtitle pid 0x%x codec 0x%x",
492 bdpgs->pid, bdpgs->coding_type );
493 break;
497 /* Chapters */
498 for ( ii = 0, jj = 0; ii < ti->chapter_count; ii++ )
500 char chapter_title[80];
502 // Sanity check start time of this chapter.
503 // If it is beyond the end of the title, drop it.
504 if (ti->chapters[ii].start > ti->duration)
506 hb_log("bd: chapter %d invalid start %"PRIu64", dropping", ii+1,
507 ti->chapters[ii].start);
508 continue;
511 chapter = calloc( sizeof( hb_chapter_t ), 1 );
513 chapter->index = ++jj;
514 sprintf( chapter_title, "Chapter %d", chapter->index );
515 hb_chapter_set_title( chapter, chapter_title );
517 chapter->duration = ti->chapters[ii].duration;
518 chapter->block_start = ti->chapters[ii].offset;
520 // Sanity check chapter duration and start times
521 // Have seen some invalid durations in the wild
522 if (ii < ti->chapter_count - 1)
524 // Validate start time
525 if (ti->chapters[ii+1].start < ti->chapters[ii].start)
527 hb_log("bd: chapter %d invalid start %"PRIu64"", ii+1,
528 ti->chapters[ii+1].start);
529 ti->chapters[ii+1].start = ti->chapters[ii].start +
530 chapter->duration;
532 if (ti->chapters[ii+1].start - ti->chapters[ii].start !=
533 chapter->duration)
535 hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1,
536 chapter->duration);
537 chapter->duration = ti->chapters[ii+1].start -
538 ti->chapters[ii].start;
541 else
543 if (ti->duration - ti->chapters[ii].start != chapter->duration)
545 hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1,
546 chapter->duration);
547 chapter->duration = ti->duration - ti->chapters[ii].start;
551 int seconds = ( chapter->duration + 45000 ) / 90000;
552 chapter->hours = ( seconds / 3600 );
553 chapter->minutes = ( seconds % 3600 ) / 60;
554 chapter->seconds = ( seconds % 60 );
556 hb_log( "bd: chap %d packet=%"PRIu64", %"PRIu64" ms",
557 chapter->index,
558 chapter->block_start,
559 chapter->duration / 90 );
561 hb_list_add( title->list_chapter, chapter );
563 hb_log( "bd: title %d has %d chapters", tt, ti->chapter_count );
565 /* This title is ok so far */
566 goto cleanup;
568 fail:
569 hb_title_close( &title );
571 cleanup:
573 return title;
576 /***********************************************************************
577 * hb_bd_main_feature
578 **********************************************************************/
579 int hb_bd_main_feature( hb_bd_t * d, hb_list_t * list_title )
581 int longest = 0;
582 int ii;
583 uint64_t longest_duration = 0;
584 int highest_rank = 0;
585 int most_chapters = 0;
586 int rank[8] = {0, 1, 3, 2, 6, 5, 7, 4};
587 BLURAY_TITLE_INFO * ti;
589 for ( ii = 0; ii < hb_list_count( list_title ); ii++ )
591 hb_title_t * title = hb_list_item( list_title, ii );
592 ti = d->title_info[title->index - 1];
593 if ( ti )
595 BLURAY_STREAM_INFO * bdvideo = &ti->clips[0].video_streams[0];
596 if ( title->duration > longest_duration * 0.7 && bdvideo->format < 8 )
598 if (highest_rank < rank[bdvideo->format] ||
599 ( title->duration > longest_duration &&
600 highest_rank == rank[bdvideo->format]))
602 longest = title->index;
603 longest_duration = title->duration;
604 highest_rank = rank[bdvideo->format];
605 most_chapters = ti->chapter_count;
607 else if (highest_rank == rank[bdvideo->format] &&
608 title->duration == longest_duration &&
609 ti->chapter_count > most_chapters)
611 longest = title->index;
612 most_chapters = ti->chapter_count;
616 else if ( title->duration > longest_duration )
618 longest_duration = title->duration;
619 longest = title->index;
622 return longest;
625 /***********************************************************************
626 * hb_bd_start
627 ***********************************************************************
628 * Title and chapter start at 1
629 **********************************************************************/
630 int hb_bd_start( hb_bd_t * d, hb_title_t *title )
632 BD_EVENT event;
634 d->duration = title->duration;
636 // Calling bd_get_event initializes libbluray event queue.
637 bd_select_title( d->bd, d->title_info[title->index - 1]->idx );
638 bd_get_event( d->bd, &event );
639 d->chapter = 1;
640 d->stream = hb_bd_stream_open( d->h, title );
641 if ( d->stream == NULL )
643 return 0;
645 return 1;
648 /***********************************************************************
649 * hb_bd_stop
650 ***********************************************************************
652 **********************************************************************/
653 void hb_bd_stop( hb_bd_t * d )
655 if( d->stream ) hb_stream_close( &d->stream );
658 /***********************************************************************
659 * hb_bd_seek
660 ***********************************************************************
662 **********************************************************************/
663 int hb_bd_seek( hb_bd_t * d, float f )
665 uint64_t pos = f * d->duration;
667 bd_seek_time(d->bd, pos);
668 d->next_chap = bd_get_current_chapter( d->bd ) + 1;
669 hb_ts_stream_reset(d->stream);
670 return 1;
673 int hb_bd_seek_pts( hb_bd_t * d, uint64_t pts )
675 bd_seek_time(d->bd, pts);
676 d->next_chap = bd_get_current_chapter( d->bd ) + 1;
677 hb_ts_stream_reset(d->stream);
678 return 1;
681 int hb_bd_seek_chapter( hb_bd_t * d, int c )
683 d->next_chap = c;
684 bd_seek_chapter( d->bd, c - 1 );
685 hb_ts_stream_reset(d->stream);
686 return 1;
689 /***********************************************************************
690 * hb_bd_read
691 ***********************************************************************
693 **********************************************************************/
694 hb_buffer_t * hb_bd_read( hb_bd_t * d )
696 int result;
697 int error_count = 0;
698 uint8_t buf[192];
699 BD_EVENT event;
700 uint64_t pos;
701 hb_buffer_t * out = NULL;
702 uint8_t discontinuity;
703 int new_chap = 0;
705 discontinuity = 0;
706 while ( 1 )
708 if ( d->next_chap != d->chapter )
710 new_chap = d->chapter = d->next_chap;
712 result = next_packet( d->bd, buf );
713 if ( result < 0 )
715 hb_error("bd: Read Error");
716 pos = bd_tell( d->bd );
717 bd_seek( d->bd, pos + 192 );
718 error_count++;
719 if (error_count > 10)
721 hb_error("bd: Error, too many consecutive read errors");
722 hb_set_work_error(d->h, HB_ERROR_READ);
723 return NULL;
725 continue;
727 else if ( result == 0 )
729 return NULL;
732 error_count = 0;
733 while ( bd_get_event( d->bd, &event ) )
735 switch ( event.event )
737 case BD_EVENT_CHAPTER:
738 // The muxers expect to only get chapter 2 and above
739 // They write chapter 1 when chapter 2 is detected.
740 d->next_chap = event.param;
741 break;
743 case BD_EVENT_PLAYITEM:
744 discontinuity = 1;
745 hb_deep_log(2, "bd: Playitem %u", event.param);
746 break;
748 case BD_EVENT_STILL:
749 bd_read_skip_still( d->bd );
750 break;
752 default:
753 break;
756 // buf+4 to skip the BD timestamp at start of packet
757 out = hb_ts_decode_pkt( d->stream, buf+4, new_chap, discontinuity );
758 if (out != NULL)
759 return out;
761 return NULL;
764 /***********************************************************************
765 * hb_bd_chapter
766 ***********************************************************************
767 * Returns in which chapter the next block to be read is.
768 * Chapter numbers start at 1.
769 **********************************************************************/
770 int hb_bd_chapter( hb_bd_t * d )
772 return d->next_chap;
775 /***********************************************************************
776 * hb_bd_close
777 ***********************************************************************
778 * Closes and frees everything
779 **********************************************************************/
780 void hb_bd_close( hb_bd_t ** _d )
782 hb_bd_t * d = *_d;
783 int ii;
785 if ( d->title_info )
787 for ( ii = 0; ii < d->title_count; ii++ )
788 bd_free_title_info( d->title_info[ii] );
789 free( d->title_info );
791 if( d->stream ) hb_stream_close( &d->stream );
792 if( d->bd ) bd_close( d->bd );
793 if( d->path ) free( d->path );
795 free( d );
796 *_d = NULL;
799 /***********************************************************************
800 * hb_bd_set_angle
801 ***********************************************************************
802 * Sets the angle to read
803 **********************************************************************/
804 void hb_bd_set_angle( hb_bd_t * d, int angle )
807 if ( !bd_select_angle( d->bd, angle) )
809 hb_log("bd_select_angle failed");
813 static int check_ts_sync(const uint8_t *buf)
815 // must have initial sync byte, no scrambling & a legal adaptation ctrl
816 return (buf[0] == 0x47) && ((buf[3] >> 6) == 0) && ((buf[3] >> 4) > 0);
819 static int have_ts_sync(const uint8_t *buf, int psize)
821 return check_ts_sync(&buf[0*psize]) && check_ts_sync(&buf[1*psize]) &&
822 check_ts_sync(&buf[2*psize]) && check_ts_sync(&buf[3*psize]) &&
823 check_ts_sync(&buf[4*psize]) && check_ts_sync(&buf[5*psize]) &&
824 check_ts_sync(&buf[6*psize]) && check_ts_sync(&buf[7*psize]);
827 #define MAX_HOLE 192*80
829 static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
831 int result;
832 uint8_t buf[MAX_HOLE];
833 uint64_t pos = 0;
834 uint64_t start = bd_tell(bd);
835 uint64_t orig;
836 uint64_t off = 192;
838 memcpy(buf, pkt, 192);
839 if ( start >= 192 ) {
840 start -= 192;
842 orig = start;
844 while (1)
846 result = bd_read(bd, buf + off, sizeof(buf) - off);
847 if (result == sizeof(buf) - off)
849 const uint8_t *bp = buf;
850 int i;
852 for ( i = sizeof(buf) - 8 * 192; --i >= 0; ++bp )
854 if ( have_ts_sync( bp, 192 ) )
856 break;
859 if ( i >= 0 )
861 pos = ( bp - buf );
862 break;
864 off = 8 * 192;
865 memcpy(buf, buf + sizeof(buf) - off, off);
866 start += sizeof(buf) - off;
868 else if (result < 0)
870 return -1;
872 else
874 return 0;
877 off = start + pos - 4;
878 // bd_seek seeks to the nearest access unit *before* the requested position
879 // we don't want to seek backwards, so we need to read until we get
880 // past that position.
881 bd_seek(bd, off);
882 while (off > bd_tell(bd))
884 result = bd_read(bd, buf, 192);
885 if (result < 0)
887 return -1;
889 else if (result != 192)
891 return 0;
894 return start - orig + pos;
897 static int next_packet( BLURAY *bd, uint8_t *pkt )
899 int result;
901 while ( 1 )
903 result = bd_read( bd, pkt, 192 );
904 if ( result < 0 )
906 return -1;
908 if ( result < 192 )
910 return 0;
912 // Sync byte is byte 4. 0-3 are timestamp.
913 if (pkt[4] == 0x47)
915 return 1;
917 // lost sync - back up to where we started then try to re-establish.
918 uint64_t pos = bd_tell(bd);
919 uint64_t pos2 = align_to_next_packet(bd, pkt);
920 if (pos2 < 0)
922 return -1;
924 else if (pos2 == 0)
926 hb_log("next_packet: eof while re-establishing sync @ %"PRIu64"", pos );
927 return 0;
929 hb_log("next_packet: sync lost @ %"PRIu64", regained after %"PRIu64" bytes",
930 pos, pos2 );
934 static int title_info_compare_mpls(const void *va, const void *vb)
936 BLURAY_TITLE_INFO *a, *b;
938 a = *(BLURAY_TITLE_INFO**)va;
939 b = *(BLURAY_TITLE_INFO**)vb;
941 return a->playlist - b->playlist;