Fix broken image when seeking frame. 90/18190/1
authorKitae Kim <kt920.kim@samsung.com>
Thu, 13 Mar 2014 08:44:33 +0000 (17:44 +0900)
committerKitae Kim <kt920.kim@samsung.com>
Mon, 17 Mar 2014 10:08:17 +0000 (19:08 +0900)
When seeking encoded frames, those images are distorted.
Its reason is that the encoder did not marks a specific flag into output buffer.
Encoder plugin has to inform gstreamer about the status of the encoded buffer

Change-Id: I78d8b53131b70d45a48e136183a862c034595112
Signed-off-by: Kitae Kim <kt920.kim@samsung.com>
src/gstmaruenc.c
src/gstmaruinterface.c
src/gstmaruinterface.h
src/gstmarumem.c
src/gstmarumem.h
src/gstmaruutils.c

index dec263d..8e4e64c 100644 (file)
@@ -201,6 +201,24 @@ gst_maruenc_init (GstMaruEnc *maruenc)
   maruenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src");
   gst_pad_use_fixed_caps (maruenc->srcpad);
 
+#if 0
+  maruenc->file = NULL;
+#endif
+  maruenc->delay = g_queue_new ();
+
+  // instead of AVCodecContext
+  maruenc->context = g_malloc0 (sizeof(CodecContext));
+  maruenc->context->video.pix_fmt = PIX_FMT_NONE;
+  maruenc->context->audio.sample_fmt = SAMPLE_FMT_NONE;
+
+  maruenc->opened = FALSE;
+
+  maruenc->dev = g_malloc0 (sizeof(CodecDevice));
+  if (!maruenc->dev) {
+    GST_ERROR_OBJECT (maruenc, "failed to allocate CodecDevice");
+    // TODO: error handling
+  }
+
   if (oclass->codec->media_type == AVMEDIA_TYPE_VIDEO) {
     gst_pad_set_chain_function (maruenc->sinkpad, gst_maruenc_chain_video);
     gst_pad_set_event_function (maruenc->sinkpad, gst_maruenc_event_video);
@@ -209,10 +227,7 @@ gst_maruenc_init (GstMaruEnc *maruenc)
     maruenc->bitrate = DEFAULT_VIDEO_BITRATE;
     maruenc->buffer_size = 512 * 1024;
     maruenc->gop_size = DEFAULT_VIDEO_GOP_SIZE;
-#if 0
-    maruenc->lmin = 2;
-    maruenc->lmax = 31;
-#endif
+
   } else if (oclass->codec->media_type == AVMEDIA_TYPE_AUDIO){
     gst_pad_set_chain_function (maruenc->sinkpad, gst_maruenc_chain_audio);
     maruenc->bitrate = DEFAULT_AUDIO_BITRATE;
@@ -221,23 +236,7 @@ gst_maruenc_init (GstMaruEnc *maruenc)
   gst_element_add_pad (GST_ELEMENT (maruenc), maruenc->sinkpad);
   gst_element_add_pad (GST_ELEMENT (maruenc), maruenc->srcpad);
 
-  maruenc->context = g_malloc0 (sizeof(CodecContext));
-  maruenc->context->video.pix_fmt = PIX_FMT_NONE;
-  maruenc->context->audio.sample_fmt = SAMPLE_FMT_NONE;
-
-  maruenc->opened = FALSE;
-
-#if 0
-  maruenc->file = NULL;
-#endif
-  maruenc->delay = g_queue_new ();
-
-  maruenc->dev = g_malloc0 (sizeof(CodecDevice));
-  if (!maruenc->dev) {
-    printf("[gst-maru][%d] failed to allocate memory\n", __LINE__);
-  }
-
-  // need to know what adapter does.
+  // TODO: need to know what adapter does.
   maruenc->adapter = gst_adapter_new ();
 }
 
@@ -257,6 +256,11 @@ gst_maruenc_finalize (GObject *object)
     maruenc->context = NULL;
   }
 
+  if (maruenc->dev) {
+    g_free (maruenc->dev);
+    maruenc->dev = NULL;
+  }
+
   g_queue_free (maruenc->delay);
 #if 0
   g_free (maruenc->filename);
@@ -626,6 +630,8 @@ gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer)
   uint32_t mem_offset = 0;
   uint8_t *working_buf = NULL;
 
+  int coded_frame, is_keyframe;
+
   GST_DEBUG_OBJECT (maruenc,
       "Received buffer of time %" GST_TIME_FORMAT,
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
@@ -652,13 +658,13 @@ gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer)
     maruenc->context.video.fps_n, maruen->context.video.fps_d);
 #endif
 
-  // TODO: check whether this func needs or not.
   gst_maruenc_setup_working_buf (maruenc);
 
   ret_size =
     codec_encode_video (maruenc->context, maruenc->working_buf,
                 maruenc->working_buf_size, GST_BUFFER_DATA (buffer),
                 GST_BUFFER_SIZE (buffer), GST_BUFFER_TIMESTAMP (buffer),
+                &coded_frame, &is_keyframe,
                 maruenc->dev);
 
   if (ret_size < 0) {
@@ -687,11 +693,10 @@ gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer)
   }
 #endif
 
-  mem_offset = maruenc->dev->mem_info.offset;
-  working_buf = maruenc->dev->buf + mem_offset;
+  // mem_offset = maruenc->dev->mem_info.offset;
+  // working_buf = maruenc->dev->buf + mem_offset;
 
-  CODEC_LOG (DEBUG,
-    "encoded video. mem_offset = 0x%x\n",  mem_offset);
+  GST_DEBUG_OBJECT (maruenc, "encoded video. mem_offset = 0x%x",  mem_offset);
 
   outbuf = gst_buffer_new_and_alloc (ret_size);
   memcpy (GST_BUFFER_DATA (outbuf), maruenc->working_buf, ret_size);
@@ -706,21 +711,21 @@ gst_maruenc_chain_video (GstPad *pad, GstBuffer *buffer)
   }
 #endif
 
-#if 0
-  if (maruenc->context->coded_frame) {
-    if (!maruenc->context->coded_frame->key_frame) {
+  if (coded_frame) {
+    if (!is_keyframe) {
+      GST_DEBUG_OBJECT (maruenc, "this frame is not a keyframe");
       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+      // GST_BUFFER_FLAG_DELTA_UNIT
+      // - this unit cannot be decoded independently.
     }
   } else {
     GST_WARNING_OBJECT (maruenc, "codec did not provide keyframe info");
   }
-#endif
   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (maruenc->srcpad));
 
   gst_buffer_unref (buffer);
 
 #if 0
-
   if (force_keyframe) {
     gst_pad_push_event (maruenc->srcpad,
       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
index 7181f4c..afd8107 100644 (file)
@@ -352,7 +352,9 @@ codec_decode_audio (CodecContext *ctx, int16_t *samples,
 int
 codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
                     int out_size, uint8_t *in_buf,
-                    int in_size, int64_t in_timestamp, CodecDevice *dev)
+                    int in_size, int64_t in_timestamp,
+                    int *coded_frame, int *is_keyframe,
+                    CodecDevice *dev)
 {
   int len = 0, ret = 0;
   gpointer buffer = NULL;
@@ -380,7 +382,7 @@ codec_encode_video (CodecContext *ctx, uint8_t *out_buf,
   }
   CODEC_LOG (DEBUG, "encode_video. mem_offset = 0x%x\n", opaque.buffer_size);
 
-  len = codec_encode_video_data_from (out_buf, device_mem + opaque.buffer_size);
+  len = codec_encode_video_data_from (out_buf, coded_frame, is_keyframe, device_mem + opaque.buffer_size);
   dev->mem_info.offset = opaque.buffer_size;
 
   release_device_mem(dev->fd, device_mem + opaque.buffer_size);
index f337efd..14b96f4 100644 (file)
@@ -120,6 +120,7 @@ int
 codec_encode_video (CodecContext *ctx, uint8_t*out_buf,
                     int out_size, uint8_t *in_buf,
                     int in_size, int64_t in_timestamp,
+                    int *coded_frame, int *is_keyframe,
                     CodecDevice *dev);
 
 int
index 2d5f191..749ae64 100644 (file)
@@ -219,7 +219,7 @@ codec_encode_video_data_to (int in_size, int64_t in_timestamp,
 }
 
 int
-codec_encode_video_data_from (uint8_t *out_buf, gpointer buffer)
+codec_encode_video_data_from (uint8_t *out_buf, int *coded_frame, int *is_keyframe, gpointer buffer)
 {
   int len = 0, size = 0;
 
@@ -228,7 +228,13 @@ codec_encode_video_data_from (uint8_t *out_buf, gpointer buffer)
 
   CODEC_LOG (DEBUG, "encode_video. outbuf size: %d\n", len);
   if (len > 0) {
+    memcpy (coded_frame, buffer + size, sizeof(int));
+    size += sizeof(int);
+    memcpy (is_keyframe, buffer + size, sizeof(int));
+    size += sizeof(int);
     memcpy (out_buf, buffer + size, len);
+
+    GST_DEBUG ("coded_frame %d, is_keyframe: %d", *coded_frame, *is_keyframe);
   }
 
   return len;
index bade429..48993d2 100644 (file)
@@ -47,7 +47,7 @@ int codec_decode_audio_data_from (int *, int16_t *, AudioData *, gpointer);
 
 void codec_encode_video_data_to (int, int64_t, uint8_t *, gpointer);
 
-int codec_encode_video_data_from (uint8_t *, gpointer);
+int codec_encode_video_data_from (uint8_t *, int *, int *, gpointer);
 
 void codec_encode_audio_data_to (int in_size, int max_size, uint8_t *in_buf, gpointer buffer);
 
index cabdd07..9919535 100644 (file)
@@ -276,7 +276,7 @@ gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
   if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
     ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
     ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
-  ctx->video.ticks_per_frame = 1;
+    ctx->video.ticks_per_frame = 1;
 
     GST_DEBUG ("setting framerate %d/%d = %lf",
         ctx->video.fps_d, ctx->video.fps_n,
@@ -320,7 +320,6 @@ gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
         break;
       }
     }
-//    printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
     gint bpp = 0, rmask = 0, endianness = 0;