summaryrefslogtreecommitdiffstats
path: root/libhb/encx264.c
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2016-05-17 11:51:25 -0600
committerJohn Stebbins <[email protected]>2016-05-17 11:51:25 -0600
commitde858d1600ac61258dc895b2fc8756b7c5d1d3a8 (patch)
treecdbd82e3d9ee83cfb9a31ebbb034852aa36fb2cb /libhb/encx264.c
parent9dcce9df07f4db1fa61f25ffeb106aa00bd64190 (diff)
libhb: send initial chapter through pipeline
Eliminate the need for everyone to assume that the first chapter starts at the first frame.
Diffstat (limited to 'libhb/encx264.c')
-rw-r--r--libhb/encx264.c179
1 files changed, 59 insertions, 120 deletions
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 30cee1096..50f7fe197 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -48,34 +48,27 @@ hb_work_object_t hb_encx264 =
struct hb_work_private_s
{
- hb_job_t * job;
- x264_t * x264;
- x264_picture_t pic_in;
+ hb_job_t * job;
+ x264_t * x264;
+ x264_picture_t pic_in;
- int64_t last_stop; // Debugging - stop time of previous input frame
+ int64_t last_stop; // Debugging - stop time of previous input frame
+
+ hb_chapter_queue_t * chapter_queue;
- hb_list_t * delayed_chapters;
- int64_t next_chapter_pts;
struct {
- int64_t duration;
+ int64_t duration;
} frame_info[FRAME_INFO_SIZE];
- char filename[1024];
+ char filename[1024];
// Multiple bit-depth
- const x264_api_t * api;
+ const x264_api_t * api;
};
#define HB_X264_API_COUNT 2
static x264_api_t x264_apis[HB_X264_API_COUNT];
-// used in delayed_chapters list
-struct chapter_s
-{
- int index;
- int64_t start;
-};
-
const char *libx264_10bit_names[] = {
"libx26410b", "libx264_main10", NULL
};
@@ -313,12 +306,12 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
if (pv->api == NULL)
{
hb_error("encx264: hb_x264_api_get failed, bit-depth %d", bit_depth);
+ return 1;
}
pv->job = job;
- pv->next_chapter_pts = AV_NOPTS_VALUE;
pv->last_stop = AV_NOPTS_VALUE;
- pv->delayed_chapters = hb_list_init();
+ pv->chapter_queue = hb_chapter_queue_init();
if (pv->api->param_default_preset(&param,
job->encoder_preset, job->encoder_tune) < 0)
@@ -613,22 +606,12 @@ void encx264Close( hb_work_object_t * w )
// Not initialized
return;
}
- if (pv->delayed_chapters != NULL)
- {
- struct chapter_s *item;
- while ((item = hb_list_item(pv->delayed_chapters, 0)) != NULL)
- {
- hb_list_rem(pv->delayed_chapters, item);
- free(item);
- }
- hb_list_close(&pv->delayed_chapters);
- }
+
+ hb_chapter_queue_close(&pv->chapter_queue);
pv->api->encoder_close( pv->x264 );
free( pv );
w->private_data = NULL;
-
- /* TODO */
}
/*
@@ -669,6 +652,50 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
w->config->h264.init_delay = -pic_out->i_dts;
}
+ /* Decide what type of frame we have. */
+ switch( pic_out->i_type )
+ {
+ case X264_TYPE_IDR:
+ // Handled in b_keyframe check below.
+ break;
+
+ case X264_TYPE_I:
+ buf->s.frametype = HB_FRAME_I;
+ break;
+
+ case X264_TYPE_P:
+ buf->s.frametype = HB_FRAME_P;
+ break;
+
+ case X264_TYPE_B:
+ buf->s.frametype = HB_FRAME_B;
+ break;
+
+ /* This is for b-pyramid, which has reference b-frames
+ However, it doesn't seem to ever be used... */
+ case X264_TYPE_BREF:
+ buf->s.frametype = HB_FRAME_BREF;
+ break;
+
+ // If it isn't the above, what type of frame is it??
+ default:
+ buf->s.frametype = 0;
+ break;
+ }
+
+ // PIR has no IDR frames, but x264 marks recovery points
+ // as keyframes. So fake an IDR at these points. This flag
+ // is also set for real IDR frames.
+ if (pic_out->b_keyframe)
+ {
+ buf->s.frametype = HB_FRAME_IDR;
+ /* if we have a chapter marker pending and this
+ frame's presentation time stamp is at or after
+ the marker's time stamp, use this as the
+ chapter start. */
+ hb_chapter_dequeue(pv->chapter_queue, buf);
+ }
+
/* Encode all the NALs we were given into buf.
NOTE: This code assumes one video frame per NAL (but there can
be other stuff like SPS and/or PPS). If there are multiple
@@ -701,37 +728,6 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
break;
}
- /* Decide what type of frame we have. */
- switch( pic_out->i_type )
- {
- case X264_TYPE_IDR:
- // Handled in b_keyframe check below.
- break;
-
- case X264_TYPE_I:
- buf->s.frametype = HB_FRAME_I;
- break;
-
- case X264_TYPE_P:
- buf->s.frametype = HB_FRAME_P;
- break;
-
- case X264_TYPE_B:
- buf->s.frametype = HB_FRAME_B;
- break;
-
- /* This is for b-pyramid, which has reference b-frames
- However, it doesn't seem to ever be used... */
- case X264_TYPE_BREF:
- buf->s.frametype = HB_FRAME_BREF;
- break;
-
- // If it isn't the above, what type of frame is it??
- default:
- buf->s.frametype = 0;
- break;
- }
-
/* Since libx264 doesn't tell us when b-frames are
themselves reference frames, figure it out on our own. */
if( (buf->s.frametype == HB_FRAME_B) &&
@@ -744,43 +740,6 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
else
buf->s.flags |= HB_FRAME_REF;
- // PIR has no IDR frames, but x264 marks recovery points
- // as keyframes. So fake an IDR at these points. This flag
- // is also set for real IDR frames.
- if( pic_out->b_keyframe )
- {
- buf->s.frametype = HB_FRAME_IDR;
- /* if we have a chapter marker pending and this
- frame's presentation time stamp is at or after
- the marker's time stamp, use this as the
- chapter start. */
- if (pv->next_chapter_pts != AV_NOPTS_VALUE &&
- pv->next_chapter_pts <= pic_out->i_pts)
- {
- // we're no longer looking for this chapter
- pv->next_chapter_pts = AV_NOPTS_VALUE;
-
- // get the chapter index from the list
- struct chapter_s *item = hb_list_item(pv->delayed_chapters, 0);
- if (item != NULL)
- {
- // we're done with this chapter
- buf->s.new_chap = item->index;
- hb_list_rem(pv->delayed_chapters, item);
- free(item);
-
- // we may still have another pending chapter
- item = hb_list_item(pv->delayed_chapters, 0);
- if (item != NULL)
- {
- // we're looking for this one now
- // we still need it, don't remove it
- pv->next_chapter_pts = item->start;
- }
- }
- }
- }
-
buf->size += size;
}
// make sure we found at least one video frame
@@ -845,7 +804,7 @@ static hb_buffer_t *x264_encode( hb_work_object_t *w, hb_buffer_t *in )
pv->pic_in.img.plane[2] = in->plane[2].data;
}
- if( in->s.new_chap && job->chapter_markers )
+ if( in->s.new_chap > 0 && job->chapter_markers )
{
/* chapters have to start with an IDR frame so request that this
frame be coded as IDR. Since there may be up to 16 frames
@@ -853,27 +812,7 @@ static hb_buffer_t *x264_encode( hb_work_object_t *w, hb_buffer_t *in )
when this frame finally pops out of the encoder we'll mark
its buffer as the start of a chapter. */
pv->pic_in.i_type = X264_TYPE_IDR;
- if (pv->next_chapter_pts == AV_NOPTS_VALUE)
- {
- pv->next_chapter_pts = in->s.start;
- }
- /*
- * Chapter markers are sometimes so close we can get a new one before the
- * previous marker has been through the encoding queue.
- *
- * Dropping markers can cause weird side-effects downstream, including but
- * not limited to missing chapters in the output, so we need to save it
- * somehow.
- */
- struct chapter_s *item = malloc(sizeof(struct chapter_s));
- if (item != NULL)
- {
- item->start = in->s.start;
- item->index = in->s.new_chap;
- hb_list_add(pv->delayed_chapters, item);
- }
- /* don't let 'work_loop' put a chapter mark on the wrong buffer */
- in->s.new_chap = 0;
+ hb_chapter_enqueue(pv->chapter_queue, in);
}
else
{