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;