rendered paste bodyIndex: test/test.c
===================================================================
--- test/test.c (revision 1601)
+++ test/test.c (working copy)
@@ -318,11 +318,17 @@
for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
{
chapter = hb_list_item( title->list_chapter, i );
- fprintf( stderr, " + %d: cells %d->%d, %d blocks, duration "
- "%02d:%02d:%02d\n", chapter->index,
- chapter->cell_start, chapter->cell_end,
- chapter->block_count, chapter->hours, chapter->minutes,
- chapter->seconds );
+ if (chapter->use_frame)
+ fprintf( stderr, " + %d: frame=%lld, duration "
+ "%02d:%02d:%02d\n", chapter->index,
+ chapter->frame, chapter->hours, chapter->minutes,
+ chapter->seconds );
+ else
+ fprintf( stderr, " + %d: cells %d->%d, %d blocks, duration "
+ "%02d:%02d:%02d\n", chapter->index,
+ chapter->cell_start, chapter->cell_end,
+ chapter->block_count, chapter->hours, chapter->minutes,
+ chapter->seconds );
}
fprintf( stderr, " + audio tracks:\n" );
for( i = 0; i < hb_list_count( title->list_audio ); i++ )
@@ -452,18 +458,6 @@
/* Set job settings */
job = title->job;
- PrintTitleInfo( title );
-
- if( chapter_start && chapter_end )
- {
- job->chapter_start = MAX( job->chapter_start,
- chapter_start );
- job->chapter_end = MIN( job->chapter_end,
- chapter_end );
- job->chapter_end = MAX( job->chapter_start,
- job->chapter_end );
- }
-
if (preset)
{
fprintf( stderr, "+ Using preset: %s", preset_name);
@@ -719,6 +713,12 @@
int row = 0;
int chapter = 0;
+ /* extract chapter 1 as see if it was a stream, if
+ so we need to allocate a chapter for each row
+ of the marker file. */
+ hb_chapter_t* chapter1 = hb_list_item( job->title->list_chapter, 0);
+ int alloc_chapters = (chapter1 && chapter1->use_frame);
+
fprintf( stderr, "Reading chapter markers from file %s\n", marker_file );
if( file == NULL )
@@ -740,8 +740,17 @@
/* We have a chapter name */
if( cell->cell_col == 1 && row == cell->cell_row )
{
- /* If we have a valid chapter, copy the string an terminate it */
- if( chapter >= job->chapter_start && chapter <= job->chapter_end )
+ /* if the chapter in the marker file doesn't yet exist, add one */
+ if (alloc_chapters && !hb_list_item( job->title->list_chapter, chapter - 1)) {
+ hb_chapter_t * new_chapter_p;
+ new_chapter_p = calloc( sizeof( hb_chapter_t ), 1 );
+ new_chapter_p->index = chapter;
+ hb_list_add( job->title->list_chapter, new_chapter_p );
+ }
+
+ /* If we have a valid chapter, copy the string an terminate it.
+ NOTE: if allocating chapters the chapter_start and chapter_end are not yet valid. */
+ if( alloc_chapters || (chapter >= job->chapter_start && chapter <= job->chapter_end) )
{
hb_chapter_t * chapter_s;
@@ -751,11 +760,79 @@
}
}
+ /* We have a chapter frame location --
+ this value will be ignored if not for a
+ ffmpeg or transport stream */
+ if( cell->cell_col == 2 && row == cell->cell_row )
+ {
+ /* If we have a valid chapter, record the frame number.
+ NOTE: if allocating chapters the chapter_start and chapter_end are not yet valid. */
+ if( alloc_chapters || (chapter >= job->chapter_start && chapter <= job->chapter_end) )
+ {
+ hb_chapter_t * chapter_s;
+ chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
+ chapter_s->frame = atoi( cell->cell_text );
+ chapter_s->use_frame = 1;
+ }
+ }
+
+
hb_dispose_cell( cell );
}
hb_close_csv_file( file );
+
+ if (alloc_chapters) {
+ /* if we were allocating chapters as we went, we have some cleanup to do */
+ /* we need to fill in the duration information, the total title duration
+ is in chapter 1 from the title scan */
+
+ /* precalculate the amount of duration used by each from from the fps */
+ uint64_t duration_per_frame = 90000LL * job->title->rate_base / job->title->rate;
+
+ /* setup the loop with chapter 1 */
+ hb_chapter_t* last_chapter_p = hb_list_item( job->title->list_chapter, 0);
+ uint64_t rem_duration = last_chapter_p->duration/*title duration*/;
+ int number_of_chapters = hb_list_count(job->title->list_chapter);
+ int chapter;
+ int seconds;
+
+ for(chapter = 2; chapter <= number_of_chapters ; chapter++)
+ {
+ /* get next chapter */
+ hb_chapter_t * chapter_p;
+ chapter_p = hb_list_item( job->title->list_chapter, chapter - 1);
+
+ /* calculate duration used by previous chapter */
+ last_chapter_p->duration = (chapter_p->frame - last_chapter_p->frame) * duration_per_frame;
+
+ /* keep track of whats still left */
+ rem_duration -= last_chapter_p->duration;
+
+ /* make the pretty version of duration */
+ seconds = ( last_chapter_p->duration + 45000 ) / 90000;
+ last_chapter_p->hours = seconds / 3600;
+ last_chapter_p->minutes = ( seconds % 3600 ) / 60;
+ last_chapter_p->seconds = seconds % 60;
+
+ /* keep previous chapter around to fill in next */
+ last_chapter_p = chapter_p;
+ }
+
+ /* final chapter goes for rem_duration */
+ last_chapter_p->duration = rem_duration;
+ seconds = ( rem_duration + 45000 ) / 90000;
+ last_chapter_p->hours = seconds / 3600;
+ last_chapter_p->minutes = ( seconds % 3600 ) / 60;
+ last_chapter_p->seconds = seconds % 60;
+
+ /* setup the chapter_start/end correctly
+ now that we know how many chapters
+ there are */
+ job->chapter_start = 1;
+ job->chapter_end = number_of_chapters;
+ }
}
}
else
@@ -775,6 +852,18 @@
}
}
+ PrintTitleInfo( title );
+
+ if( chapter_start && chapter_end )
+ {
+ job->chapter_start = MAX( job->chapter_start,
+ chapter_start );
+ job->chapter_end = MIN( job->chapter_end,
+ chapter_end );
+ job->chapter_end = MAX( job->chapter_start,
+ job->chapter_end );
+ }
+
if( crop[0] >= 0 && crop[1] >= 0 &&
crop[2] >= 0 && crop[3] >= 0 )
{
Index: libhb/stream.c
===================================================================
--- libhb/stream.c (revision 1601)
+++ libhb/stream.c (working copy)
@@ -101,6 +101,8 @@
int last_error_count; /* # errors at last error message */
int packetsize; /* Transport Stream packet size */
+ int last_chapter; /* chapter number of last seen chapter */
+
int64_t ts_lastpcr; /* the last pcr we found in the TS stream */
int64_t ts_nextpcr; /* the next pcr to put in a PS packet */
@@ -176,10 +178,11 @@
/***********************************************************************
* Local prototypes
**********************************************************************/
+static int hb_stream_chapter_start( hb_stream_t *stream );
static void hb_stream_duration(hb_stream_t *stream, hb_title_t *inTitle);
static void hb_ts_stream_init(hb_stream_t *stream);
static void hb_ts_stream_find_pids(hb_stream_t *stream);
-static int hb_ts_stream_decode(hb_stream_t *stream, uint8_t *obuf);
+static int hb_ts_stream_decode(hb_stream_t *stream, hb_buffer_t *b);
static void hb_ts_stream_reset(hb_stream_t *stream);
static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
int aud_pid_index);
@@ -612,6 +615,7 @@
// One Chapter
hb_chapter_t * chapter;
chapter = calloc( sizeof( hb_chapter_t ), 1 );
+ chapter->use_frame = 1;
chapter->index = 1;
chapter->duration = aTitle->duration;
chapter->hours = aTitle->hours;
@@ -1021,7 +1025,7 @@
}
return 1;
}
- return hb_ts_stream_decode( src_stream, b->data );
+ return hb_ts_stream_decode( src_stream, b );
}
/***********************************************************************
@@ -2045,8 +2049,9 @@
***********************************************************************
*
**********************************************************************/
-static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf )
+static int hb_ts_stream_decode( hb_stream_t *stream, hb_buffer_t *b )
{
+ uint8_t* obuf = b->data;
/*
* stash the output buffer pointer in our stream so we don't have to
* pass it & its original value to everything we call.
@@ -2186,6 +2191,7 @@
stream->ts_foundfirst[0] = 1;
}
++stream->frames;
+ b->new_chap = hb_stream_chapter_start(stream);
}
else if ( ! stream->ts_foundfirst[curstream] )
{
@@ -2500,6 +2506,7 @@
// One Chapter
hb_chapter_t * chapter;
chapter = calloc( sizeof( hb_chapter_t ), 1 );
+ chapter->use_frame = 1;
chapter->index = 1;
chapter->duration = title->duration;
chapter->hours = title->hours;
@@ -2546,6 +2553,33 @@
return (int64_t)( (double)pts * conv_factor );
}
+static int hb_stream_chapter_start( hb_stream_t *stream )
+{
+ /* only look for chapter start if not scanning */
+ if (stream->title) {
+ int chapter = stream->last_chapter + 1;
+ hb_chapter_t * chapter_p;
+ chapter_p = hb_list_item( stream->title->list_chapter, chapter - 1);
+
+ /* just in case we somehow missed the frame for a chapter walk
+ forward until we are in the right place */
+ while (chapter_p->frame < stream->frames) {
+ ++chapter;
+ ++stream->last_chapter;
+ chapter_p = hb_list_item( stream->title->list_chapter, chapter - 1);
+ }
+
+ /* return this chapter if we just read the start frame */
+ if (chapter_p->frame == stream->frames) {
+ hb_log("start of chapter %d read", chapter);
+ stream->last_chapter = chapter;
+ return chapter;
+ }
+ }
+
+ return 0;
+}
+
static int ffmpeg_read( hb_stream_t *stream, hb_buffer_t *buf )
{
AVPacket pkt;
@@ -2568,6 +2602,10 @@
av_q2d(stream->ffmpeg_ic->streams[pkt.stream_index]->time_base)*90000. );
buf->renderOffset = av_to_hb_pts( pkt.pts,
av_q2d(stream->ffmpeg_ic->streams[pkt.stream_index]->time_base)*90000. );
+
+ ++stream->frames;
+ buf->new_chap = hb_stream_chapter_start(stream);
+
av_free_packet( &pkt );
return 1;
}
Index: libhb/common.h
===================================================================
--- libhb/common.h (revision 1601)
+++ libhb/common.h (working copy)
@@ -390,6 +390,12 @@
int block_end;
int block_count;
+ /* 1 if chapter is a bogus chapter for the full title (see
+ stream.c), or frame location specified in marker file */
+ int use_frame;
+ /* chapter location specified from marker file */
+ uint64_t frame;
+
/* Visual-friendly duration */
int hours;
int minutes;