diff options
author | eddyg <[email protected]> | 2008-12-02 01:07:02 +0000 |
---|---|---|
committer | eddyg <[email protected]> | 2008-12-02 01:07:02 +0000 |
commit | 29f8a536e11e713e6f8d983aca4405ab017a21e7 (patch) | |
tree | 108bc0a97311cdfc82ac63e27c136de60fc531ff /libhb/stream.c | |
parent | 2dddca5b3135ed939df9cdcaf2e5ffb2e4d7f44f (diff) |
Add metadata support to libhb, add importing of MP4 metadata, add export of MP4 metadata, add importing of MP4 chapters, add seek to chapter for input files, add new libmp4v2, remove old MP4 chapter muxing - now in libmp4v2.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1987 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/stream.c')
-rwxr-xr-x | libhb/stream.c | 146 |
1 files changed, 136 insertions, 10 deletions
diff --git a/libhb/stream.c b/libhb/stream.c index d5ab019d5..483755659 100755 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -13,6 +13,7 @@ #include "a52dec/a52.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "mp4v2/mp4v2.h" #define min(a, b) a < b ? a : b @@ -119,6 +120,9 @@ struct hb_stream_s hb_buffer_t *fwrite_buf; /* PS buffer (set by hb_ts_stream_decode) */ + int chapter; /* Chapter that we are currently in */ + uint64_t chapter_end; /* HB time that the current chapter ends */ + /* * Stuff before this point is dynamic state updated as we read the * stream. Stuff after this point is stream description state that @@ -1082,6 +1086,70 @@ int hb_stream_read( hb_stream_t * src_stream, hb_buffer_t * b ) } /*********************************************************************** + * hb_stream_seek_chapter + *********************************************************************** + * + **********************************************************************/ +int hb_stream_seek_chapter( hb_stream_t * stream, int chapter_num ) +{ + AVFormatContext *ic = stream->ffmpeg_ic; + uint64_t end_offset = 0; + uint64_t start_offset = 0; + uint64_t pos = 0; + hb_chapter_t *chapter = NULL; + int i; + + if( !stream || !stream->title ) + { + return 0; + } + + for( i = 0; i < chapter_num; i++) + { + chapter = hb_list_item( stream->title->list_chapter, + i ); + + if( chapter ) + { + /* + * Seeking to a chapter means that we are in that chapter, + * so track which chapter we are in so that we can output + * the correct chapter numbers in buf->new_chap + */ + start_offset = end_offset; + end_offset += chapter->duration; + stream->chapter = i; + stream->chapter_end = end_offset; + } else { + return 0; + } + } + + /* + * Is the the correct way to convert timebases? It seems to get it pretty + * much right - plus a few seconds, which is odd. + */ + pos = ((start_offset * AV_TIME_BASE) / 90000); + + hb_deep_log( 2, "Seeking to chapter %d time (starts: %lld ends %lld) AV pos %lld", chapter_num-1, start_offset, end_offset, pos); + + av_seek_frame( ic, -1, pos, 0); + + return 1; +} + +/*********************************************************************** + * hb_stream_chapter + *********************************************************************** + * Return the number of the chapter that we are currently in. We store + * the chapter number starting from 0, so + 1 for the real chpater num. + **********************************************************************/ +int hb_stream_chapter( hb_stream_t * src_stream ) +{ + return( src_stream->chapter + 1 ); +} + +/*********************************************************************** * hb_stream_seek *********************************************************************** * @@ -2585,16 +2653,6 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) title->minutes = ( dur % 3600 ) / 60; title->seconds = dur % 60; - // One Chapter - hb_chapter_t * chapter; - chapter = calloc( sizeof( hb_chapter_t ), 1 ); - chapter->index = 1; - chapter->duration = title->duration; - chapter->hours = title->hours; - chapter->minutes = title->minutes; - chapter->seconds = title->seconds; - hb_list_add( title->list_chapter, chapter ); - // set the title to decode the first video stream in the file title->demuxer = HB_NULL_DEMUXER; title->video_codec = 0; @@ -2625,6 +2683,26 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream ) title->container_name = strdup( ic->iformat->name ); title->data_rate = ic->bit_rate; + hb_deep_log( 2, "Found ffmpeg %d chapters, container=%s", ic->nb_chapters, ic->iformat->name); + + /* + * Fill the metadata. + */ + decmetadata( title ); + + if( hb_list_count( title->list_chapter ) == 0 ) + { + // Need at least one chapter + hb_chapter_t * chapter; + chapter = calloc( sizeof( hb_chapter_t ), 1 ); + chapter->index = 1; + chapter->duration = title->duration; + chapter->hours = title->hours; + chapter->minutes = title->minutes; + chapter->seconds = title->seconds; + hb_list_add( title->list_chapter, chapter ); + } + return title; } @@ -2714,6 +2792,54 @@ static int ffmpeg_read( hb_stream_t *stream, hb_buffer_t *buf ) { buf->start = buf->renderOffset; } + + /* + * Check to see whether this video buffer is on a chapter + * boundary, if so mark it as such in the buffer. The chapters for + * a stream have a simple duration for each chapter. So we keep + * track of what chapter we are in currently, and when it is due + * to end. + */ + hb_deep_log( 3, "title=0x%x, job=0x%x, chapter_markers=%d, time=%lld, chapter=%d, end_chapter=%lld", + stream->title, + stream->title ? (stream->title->job ? stream->title->job : 0x0) : 0x0, + stream->title ? (stream->title->job ? stream->title->job->chapter_markers : 2) : 0x0, + buf->start, stream->chapter, stream->chapter_end); + + if( stream->title && + stream->title->job && + stream->title->job->chapter_markers && + buf->id == stream->ffmpeg_video_id && + buf->start >= stream->chapter_end ) + { + hb_chapter_t *chapter = NULL; + + /* + * Store when this chapter ends using HB time. + */ + chapter = hb_list_item( stream->title->list_chapter, + stream->chapter ); + + if( chapter ) + { + if( stream->chapter != 0 ) + { + buf->new_chap = stream->chapter + 2; + } + + hb_deep_log( 2, "Starting chapter %i at %lld", buf->new_chap, buf->start); + stream->chapter_end += chapter->duration; + stream->chapter++; + hb_deep_log( 2, "Looking for chapter %i at %lld", stream->chapter+1, stream->chapter_end ); + } else { + /* + * Must have run out of chapters, stop looking. + */ + stream->chapter_end = -1; + } + } else { + buf->new_chap = 0; + } av_free_packet( stream->ffmpeg_pkt ); return 1; } |