diff --git a/src/gstducatih264dec.c b/src/gstducatih264dec.c
index 827304df65b2a86049711e889ffaeac41abac9c3..9b553505bcf599c3eee66ef2359767fdb43807e1 100644 (file)
--- a/src/gstducatih264dec.c
+++ b/src/gstducatih264dec.c
"framerate = (fraction)[ 0, max ],"
"profile = (string) {high, high-10-intra, high-10, high-4:2:2-intra, "
"high-4:2:2, high-4:4:4-intra, high-4:4:4, cavlc-4:4:4-intra}, "
- "level = (string) {1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5.1};")
+ "level = (string) {1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2};")
);
static const struct
structure = gst_caps_get_structure (caps, 0);
if (structure) {
- gint num_ref_frames = -1;
+ gint num_ref_frames = -1, num_reorder_frames = -1;
if (gst_structure_get_int (structure, "num-ref-frames", &num_ref_frames)
&& num_ref_frames >= 0) {
((IH264VDEC_Params *) self->params)->maxNumRefFrames = num_ref_frames;
-
- if (num_ref_frames > MAX_BACKLOG_FRAMES) {
+ }
+ if (gst_structure_get_int (structure, "num-reorder-frames",
+ &num_reorder_frames)
+ && num_reorder_frames >= 0) {
+ if (num_reorder_frames > MAX_BACKLOG_FRAMES) {
h264dec->backlog_maxframes = MAX_BACKLOG_FRAMES;
GST_WARNING_OBJECT (self,
"Stream needs %d frames for reordering, we can only accomodate %d",
- num_ref_frames, MAX_BACKLOG_FRAMES);
+ num_reorder_frames, MAX_BACKLOG_FRAMES);
} else {
- h264dec->backlog_maxframes = num_ref_frames;
+ h264dec->backlog_maxframes = num_reorder_frames;
GST_INFO_OBJECT (self, "Num frames for reordering: %d",
h264dec->backlog_maxframes);
}
h264dec->backlog_maxframes =
gst_ducati_h264dec_get_max_dpb_size (self, caps);
GST_WARNING_OBJECT (self,
- "num-ref-frames not found on caps, defaulting to %d",
+ "num-reorder-frames not found on caps, defaulting to %d",
h264dec->backlog_maxframes);
}
return TRUE;
}
-/* The following few functions reorder buffers by timestamp, on the
- assumption that buffers are properly timestamped by presentation
- time, but pushed in any (but presumably decode) order.
- They also assume all incoming buffers have a valid timestamp.
+/* The following few functions reorder buffers by "picture order
+ count", which is passed through OFFSET_END by h264parse.
*/
static GstFlowReturn
gst_ducati_h264dec_push_earliest (GstDucatiH264Dec * self)
{
- GstClockTime earliest_ts = GST_CLOCK_TIME_NONE;
+ guint64 earliest_poc = G_MAXUINT64;
guint earliest_index = 0, i;
GstBuffer *buf;
if (self->backlog_nframes == 0)
return GST_FLOW_OK;
- /* work out which frame has the earliest ts */
+ /* work out which frame has the earliest poc */
for (i = 0; i < self->backlog_nframes; i++) {
- GstClockTime ts = GST_BUFFER_TIMESTAMP (self->backlog_frames[i]);
- if (earliest_ts == GST_CLOCK_TIME_NONE || ts < earliest_ts) {
- earliest_ts = ts;
+ guint64 poc = GST_BUFFER_OFFSET_END (self->backlog_frames[i]);
+ if (earliest_poc == G_MAXUINT64 || poc < earliest_poc) {
+ earliest_poc = poc;
earliest_index = i;
}
}
return gst_pad_push (GST_DUCATIVIDDEC (self)->srcpad, buf);
}
+static GstBuffer *
+gst_ducati_h264dec_push_input (GstDucatiVidDec * self, GstBuffer * buf)
+{
+ GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self);
+
+ /* If we're about to push an IDR frame, then we can flush all the frames
+ we currently have queued. This is necessary as picture order count
+ is local to each IDR + set of non IDR frames, so will restart at 0
+ when next IDR frames comes in. */
+ if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+ GST_DEBUG_OBJECT (self, "Got keyframe, pushing %u frames",
+ h264dec->backlog_nframes);
+ while (h264dec->backlog_nframes > 0) {
+ gst_ducati_h264dec_push_earliest (h264dec);
+ }
+ }
+
+ return parent_class->push_input (self, buf);
+}
+
static GstFlowReturn
gst_ducati_h264dec_push_output (GstDucatiVidDec * self, GstBuffer * buf)
{
bclass->can_drop_frame =
GST_DEBUG_FUNCPTR (gst_ducati_h264dec_can_drop_frame);
bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query);
+ bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_push_input);
bclass->push_output = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_push_output);
bclass->on_flush = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_on_flush);
bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_set_sink_caps);