gstv4ldec: CF1 calc pts and duration in decloop [1/1]
PD#SWPL-178744
Problem:
calc pts and duration in dec loop
Solution:
1. cal duration when resolution event.
2. cal pts befor get_right_frames
Verify:
Yocto
Change-Id: I41c806571e565d3e522d59af6793996d26e9f333
Signed-off-by: bo.xiao <bo.xiao@amlogic.com>
diff --git a/src/gstamlv4l2videodec.c b/src/gstamlv4l2videodec.c
index 4e2cd62..757ee73 100644
--- a/src/gstamlv4l2videodec.c
+++ b/src/gstamlv4l2videodec.c
@@ -122,6 +122,8 @@
#if GST_IMPORT_LGE_PROP
static void gst_aml_v4l2_video_dec_install_lge_properties_helper(GObjectClass *gobject_class);
#endif
+static GstClockTime calc_output_buffer_pts_func(GstVideoDecoder *decoder);
+static GstClockTime calc_duration_func(GstVideoDecoder *decoder);
static void
gst_aml_v4l2_video_dec_set_property(GObject *object,
@@ -706,38 +708,6 @@
}
static GstVideoCodecFrame *
-gst_aml_v4l2_video_dec_get_oldest_frame(GstVideoDecoder *decoder)
-{
- GstVideoCodecFrame *frame = NULL;
- GList *frames, *l;
- gint count = 0;
-
- frames = gst_video_decoder_get_frames(decoder);
-
- for (l = frames; l != NULL; l = l->next)
- {
- GstVideoCodecFrame *f = l->data;
-
- if (!frame || (GST_CLOCK_TIME_IS_VALID(frame->pts) && GST_CLOCK_TIME_IS_VALID(f->pts) && (frame->pts > f->pts)))
- frame = f;
-
- count++;
- }
-
- if (frame)
- {
- GST_LOG_OBJECT(decoder,
- "Oldest frame is %d %" GST_TIME_FORMAT " and %d frames left",
- frame->system_frame_number, GST_TIME_ARGS(frame->pts), count - 1);
- gst_video_codec_frame_ref(frame);
- }
-
- g_list_free_full(frames, (GDestroyNotify)gst_video_codec_frame_unref);
-
- return frame;
-}
-
-static GstVideoCodecFrame *
gst_aml_v4l2_video_dec_get_right_frame_for_frame_mode(GstVideoDecoder *decoder, GstClockTime pts)
{
GstVideoCodecFrame *frame = NULL;
@@ -775,14 +745,13 @@
if (frame)
{
GST_LOG_OBJECT(decoder,
- "frame is %d %" GST_TIME_FORMAT " and %d frames left",
- frame->system_frame_number, GST_TIME_ARGS(frame->pts), count - 1);
+ "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
+ frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), count - 1);
gst_video_codec_frame_ref(frame);
}
g_list_free_full(frames, (GDestroyNotify)gst_video_codec_frame_unref);
- GST_LOG_OBJECT (decoder, "trace out ret:%p", frame);
return frame;
}
@@ -807,6 +776,9 @@
if (GST_CLOCK_TIME_IS_VALID(pts) && (ABSDIFF(f->pts, pts)) < 1000)
{
/* found the right frame */
+ GST_LOG_OBJECT(decoder,
+ "found frame %" GST_TIME_FORMAT "with pts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS(f->pts), GST_TIME_ARGS(pts));
frame = f;
break;
}
@@ -834,15 +806,14 @@
g_list_free_full(l, (GDestroyNotify)gst_video_codec_frame_unref);
GST_LOG_OBJECT(decoder,
- "frame is %d %" GST_TIME_FORMAT " and %d frames left",
- frame->system_frame_number, GST_TIME_ARGS(frame->pts), l_len);
+ "frame %p is %d %" GST_TIME_FORMAT " and %d frames left",
+ frame, frame->system_frame_number, GST_TIME_ARGS(frame->pts), l_len);
gst_video_codec_frame_ref(frame);
}
g_list_free_full(frames, (GDestroyNotify)gst_video_codec_frame_unref);
done:
- GST_LOG_OBJECT (decoder, "trace out ret:%p", frame);
return frame;
}
@@ -1014,6 +985,50 @@
return FALSE;
}
+static GstClockTime
+calc_output_buffer_pts_func(GstVideoDecoder *decoder)
+{
+ GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
+ GstClockTime pts = GST_CLOCK_TIME_NONE;
+
+ if (GST_CLOCK_TIME_IS_VALID (self->last_out_pts) && GST_CLOCK_TIME_IS_VALID(self->frame_duration)) {
+ pts = self->last_out_pts + self->frame_duration;
+ GST_LOG_OBJECT (decoder,
+ "calculate PTS %" GST_TIME_FORMAT " by duration: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (pts), GST_TIME_ARGS (self->frame_duration));
+ }
+ else
+ {
+ pts = 0;
+ GST_INFO_OBJECT (decoder,"Set PTS=0");
+ }
+ return pts;
+}
+
+static GstClockTime
+calc_duration_func(GstVideoDecoder *decoder)
+{
+ GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
+ GstClockTime duration = GST_CLOCK_TIME_NONE;
+ gint fps_n, fps_d;
+ fps_n = gst_value_get_fraction_numerator(self->v4l2capture->fps);
+ fps_d = gst_value_get_fraction_denominator(self->v4l2capture->fps);
+
+ if (fps_n != 0 && fps_d != 0)
+ {
+ duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
+
+ if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
+ {
+ duration = duration / 2;
+ }
+ }
+
+ GST_INFO_OBJECT (decoder,"framerate(fps_d: %d, fps_n: %d) -> frame_duration = %" GST_TIME_FORMAT, fps_d, fps_n, GST_TIME_ARGS(duration));
+
+ return duration;
+}
+
static void
gst_aml_v4l2_video_dec_loop(GstVideoDecoder *decoder)
{
@@ -1142,6 +1157,9 @@
TRUE))
goto activate_failed;
+ //cal duration when got resolution event
+ self->frame_duration = calc_duration_func(decoder);
+
g_mutex_lock(&self->res_chg_lock);
GST_LOG_OBJECT(decoder, "signal resolution changed");
self->is_res_chg = FALSE;
@@ -1172,26 +1190,6 @@
ret = gst_buffer_pool_acquire_buffer(pool, &buffer, NULL);
- //calculate a new pts for interlace stream
- if (ret == GST_FLOW_OK && self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
- {
- //if buffer pts is valid, reduce 1/2 duration
- if (GST_BUFFER_DURATION_IS_VALID(buffer))
- {
- GST_BUFFER_DURATION(buffer) = GST_BUFFER_DURATION(buffer)/2;
- }
- GST_BUFFER_FLAG_UNSET(buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
- //reset pts
- if (GST_BUFFER_TIMESTAMP (buffer) == 0LL)
- {
- if (self->input_state->info.fps_n !=0 && self->input_state->info.fps_d !=0)
- {
- double rate = ((double)self->input_state->info.fps_n/(double)self->input_state->info.fps_d)*2;
- GST_BUFFER_TIMESTAMP(buffer) = self->last_out_pts + 1000000000LL/rate;
- }
- }
- }
-
g_object_unref(pool);
if (ret == GST_FLOW_OK && GST_BUFFER_FLAG_IS_SET(buffer,GST_AML_V4L2_BUFFER_FLAG_LAST_EMPTY)) {
@@ -1244,7 +1242,7 @@
GST_LOG_OBJECT(decoder, "Process output buffer (switching flow outstanding num:%d)", self->v4l2capture->outstanding_buf_num);
ret = gst_aml_v4l2_buffer_pool_process(v4l2_pool, &buffer);
- GST_DEBUG_OBJECT(decoder, "send pts:%lld - %" GST_TIME_FORMAT, GST_BUFFER_PTS(buffer), GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
+ GST_DEBUG_OBJECT(decoder, "decoded pts:%lld - %" GST_TIME_FORMAT, GST_BUFFER_PTS(buffer), GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));
g_signal_emit (self, g_signals[SIGNAL_DECODED_PTS], 0, GST_BUFFER_PTS(buffer));
if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
@@ -1260,36 +1258,27 @@
if (ret != GST_FLOW_OK)
goto beach;
+ if (!GST_BUFFER_PTS_IS_VALID (buffer))
+ {
+ GST_BUFFER_TIMESTAMP(buffer) = calc_output_buffer_pts_func(decoder);
+ }
+
+ if (self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
+ {
+ GST_BUFFER_DURATION(buffer) = self->frame_duration; // got at resolution event.
+ GST_BUFFER_FLAG_UNSET(buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
+ }
+
frame = gst_aml_v4l2_video_dec_get_right_frame(decoder, GST_BUFFER_TIMESTAMP (buffer));
if (frame)
{
- if (!GST_CLOCK_TIME_IS_VALID(frame->pts))
- {
- if (!GST_CLOCK_TIME_IS_VALID(self->last_out_pts))
- {
- if (GST_CLOCK_TIME_IS_VALID(frame->dts))
- {
- GST_BUFFER_TIMESTAMP(buffer) = frame->dts;
- }
- else
- {
- GST_WARNING_OBJECT (decoder,"sorry,we have no baseline to calculate pts");
- goto beach;
- }
- }
- else
- {
- double rate = ((double)self->input_state->info.fps_n/(double)self->input_state->info.fps_d);
- GST_BUFFER_TIMESTAMP(buffer) = self->last_out_pts + 1000000000LL/rate;
- }
- }
self->last_out_pts = GST_BUFFER_TIMESTAMP(buffer);
frame->output_buffer = buffer;
frame->pts = GST_BUFFER_TIMESTAMP(buffer);
frame->duration = GST_BUFFER_DURATION(buffer);
+
buffer = NULL;
- GST_DEBUG_OBJECT (decoder,"enable_cc_data:%d",self->v4l2capture->enable_cc_data);
if (self->v4l2capture->enable_cc_data)
{
if (foreach_cc_buffer_list_match_pts_func(v4l2_pool->cc_buffer_list, frame))
@@ -1322,7 +1311,8 @@
}
else
{
- GST_WARNING_OBJECT(decoder, "Decoder is producing too many buffers");
+ GST_WARNING_OBJECT(decoder, "Unmatch buffer, should be push, need refine");
+ //gst_pad_push (decoder->srcpad, buffer);
gst_buffer_unref(buffer);
}
@@ -1652,6 +1642,7 @@
GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(decoder);
gboolean ret;
GstEventType type = GST_EVENT_TYPE(event);
+ GST_DEBUG_OBJECT (self, "received event %p %" GST_PTR_FORMAT, event, event);
switch (type)
{
@@ -1659,7 +1650,6 @@
{
GstStructure *s;
GstEvent *event;
- GST_DEBUG_OBJECT(self, "new private event");
s = gst_structure_new("private_signal", "obj_ptr", G_TYPE_POINTER, self, "sig_name", G_TYPE_STRING, "decoded-pts", NULL);
event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
GST_DEBUG_OBJECT(self, "before Send private_signal Event :%p", event);
@@ -1675,8 +1665,6 @@
gst_event_parse_caps (event, &caps);
- GST_DEBUG_OBJECT(self, "event caps %" GST_PTR_FORMAT, caps);
-
structure= gst_caps_get_structure(caps, 0);
if ( gst_structure_has_field(structure, "parsed") )
{
@@ -1788,6 +1776,10 @@
GstAmlV4l2VideoDec *self = GST_AML_V4L2_VIDEO_DEC(element);
GstVideoDecoder *decoder = GST_VIDEO_DECODER(element);
+ GST_DEBUG_OBJECT(element, "change state from %s to %s",
+ gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
+ gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
+
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
{
g_atomic_int_set(&self->active, FALSE);
@@ -1841,6 +1833,7 @@
{
/* V4L2 object are created in subinstance_init */
self->last_out_pts = GST_CLOCK_TIME_NONE;
+ self->frame_duration = GST_CLOCK_TIME_NONE;
self->is_secure_path = FALSE;
self->is_res_chg = FALSE;
self->codec_data_inject = FALSE;