]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugin-ducati.git/blobdiff - src/gstducatividenc.c
ducatividdec: remove another leftover -strided caps remnant
[glsdk/gst-plugin-ducati.git] / src / gstducatividenc.c
index 56fc1d1e3a5f9aedbabe221bc47ae342ed3b5a63..52a1b098da3c8f61e94fa1b02d708555791cdb87 100644 (file)
@@ -36,6 +36,7 @@
 
 #define DEFAULT_BITRATE 2048
 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
+#define DEFAULT_INTRA_INTERVAL 16
 
 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
 
@@ -49,7 +50,8 @@ enum
 {
   PROP_0,
   PROP_BITRATE,
-  PROP_RATE_PRESET
+  PROP_RATE_PRESET,
+  PROP_INTRA_INTERVAL
 };
 
 static void gst_ducati_videnc_set_property (GObject * object, guint prop_id,
@@ -72,6 +74,8 @@ static GstFlowReturn gst_ducati_videnc_handle_frame (GstBaseVideoEncoder *
 static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc *
     self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
     gint outargs_sz);
+static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc,
+    int type);
 static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self);
 static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
     GstEvent * event);
@@ -85,17 +89,17 @@ GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
 
 enum
 {
-  GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = 1,   /**< CBR rate control for video conferencing. */
-  GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = 2,     /**< VBR rate control for local storage (DVD)
+  GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY,   /**< CBR rate control for video conferencing. */
+  GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE,  /**< VBR rate control for local storage (DVD)
                            *   recording.
                            */
-  GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = 3,     /**< Two pass rate control for non real time
+  GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS,  /**< Two pass rate control for non real time
                            *   applications.
                            */
-  GST_DUCATI_VIDENC_RATE_PRESET_NONE = 4,        /**< No configurable video rate control
+  GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE,        /**< No configurable video rate control
                             *  mechanism.
                             */
-  GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = 5,/**< User defined configuration using extended
+  GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended
                            *   parameters.
                            */
 };
@@ -110,6 +114,9 @@ gst_ducati_videnc_rate_preset_get_type (void)
       {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"},
       {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"},
       {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"},
+      {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"},
+      {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined",
+          "user-defined"},
       {0, NULL, NULL},
     };
 
@@ -147,6 +154,7 @@ gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
 
   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
   klass->configure = gst_ducati_videnc_configure_default;
+  klass->is_sync_point = gst_ducati_videnc_is_sync_point_default;
 
   g_object_class_install_property (gobject_class, PROP_BITRATE,
       g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1,
@@ -157,6 +165,11 @@ gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
           "H.264 Rate Control",
           GST_TYPE_DUCATI_VIDENC_RATE_PRESET, DEFAULT_RATE_PRESET,
           G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL,
+      g_param_spec_int ("intra-interval", "Intra-frame interval",
+          "Interval between intra frames (keyframes)", 0, INT_MAX,
+          DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE));
 }
 
 static void
@@ -178,6 +191,7 @@ gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
 
   self->bitrate = DEFAULT_BITRATE * 1000;
   self->rate_preset = DEFAULT_RATE_PRESET;
+  self->intra_interval = DEFAULT_INTRA_INTERVAL;
 }
 
 static gboolean
@@ -195,7 +209,7 @@ static void
 gst_ducati_videnc_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
+  GstDucatiVidEnc *self;
 
   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
   self = GST_DUCATIVIDENC (object);
@@ -207,6 +221,9 @@ gst_ducati_videnc_set_property (GObject * object, guint prop_id,
     case PROP_RATE_PRESET:
       self->rate_preset = g_value_get_enum (value);
       break;
+    case PROP_INTRA_INTERVAL:
+      self->intra_interval = g_value_get_int (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -216,7 +233,7 @@ static void
 gst_ducati_videnc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
-  GstDucatiVidEnc *self = GST_DUCATIVIDENC (object);
+  GstDucatiVidEnc *self;
 
   g_return_if_fail (GST_IS_DUCATIVIDENC (object));
   self = GST_DUCATIVIDENC (object);
@@ -228,6 +245,9 @@ gst_ducati_videnc_get_property (GObject * object, guint prop_id,
     case PROP_RATE_PRESET:
       g_value_set_enum (value, self->rate_preset);
       break;
+    case PROP_INTRA_INTERVAL:
+      g_value_set_int (value, self->intra_interval);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -263,6 +283,7 @@ gst_ducati_videnc_configure (GstDucatiVidEnc * self)
   if (err) {
     GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x",
         err, self->status->extendedError);
+    gst_ducati_log_extended_error_info (self->status->extendedError);
 
     return FALSE;
   }
@@ -302,6 +323,7 @@ static gboolean
 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
 {
   VIDENC2_DynamicParams *dynParams;
+  VIDENC2_Params *params;
   const GstVideoState *state;
   int i;
 
@@ -313,27 +335,26 @@ gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
   if (self->rect.h == 0)
     self->rect.h = state->height;
 
-  self->params = (VIDENC2_Params *) self->params;
-  self->params->encodingPreset = 0x03;
-  self->params->rateControlPreset = self->rate_preset;
-  self->params->maxHeight = self->rect.h;
-  self->params->maxWidth = self->rect.w;
-  self->params->dataEndianness = XDM_BYTE;
-  self->params->maxInterFrameInterval = 1;
-  self->params->maxBitRate = -1;
-  self->params->minBitRate = 0;
-  self->params->inputChromaFormat = XDM_YUV_420SP;
-  self->params->inputContentType = IVIDEO_PROGRESSIVE;
-  self->params->operatingMode = IVIDEO_ENCODE_ONLY;
-  self->params->inputDataMode = IVIDEO_ENTIREFRAME;
-  self->params->outputDataMode = IVIDEO_ENTIREFRAME;
-  self->params->numInputDataUnits = 1;
-  self->params->numOutputDataUnits = 1;
+  params = (VIDENC2_Params *) self->params;
+  params->encodingPreset = 0x03;
+  params->rateControlPreset = self->rate_preset;
+  params->maxHeight = self->rect.h;
+  params->maxWidth = self->rect.w;
+  params->dataEndianness = XDM_BYTE;
+  params->maxInterFrameInterval = 1;
+  params->maxBitRate = -1;
+  params->minBitRate = 0;
+  params->inputChromaFormat = XDM_YUV_420SP;
+  params->inputContentType = IVIDEO_PROGRESSIVE;
+  params->operatingMode = IVIDEO_ENCODE_ONLY;
+  params->inputDataMode = IVIDEO_ENTIREFRAME;
+  params->outputDataMode = IVIDEO_ENTIREFRAME;
+  params->numInputDataUnits = 1;
+  params->numOutputDataUnits = 1;
   for (i = 0; i < IVIDEO_MAX_NUM_METADATA_PLANES; i++) {
-    self->params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
+    params->metadataType[i] = IVIDEO_METADATAPLANE_NONE;
   }
 
-  dynParams = self->dynParams;
   dynParams = (VIDENC2_DynamicParams *) self->dynParams;
 
   dynParams->refFrameRate =
@@ -342,9 +363,8 @@ gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
   dynParams->inputWidth = self->rect.w;
   dynParams->inputHeight = self->rect.h;
   dynParams->targetBitRate = self->bitrate;
-  dynParams->intraFrameInterval = 15;
+  dynParams->intraFrameInterval = self->intra_interval;
   dynParams->captureWidth = dynParams->inputWidth;
-  dynParams->captureWidth = dynParams->inputWidth = self->rect.w;
 
   dynParams->forceFrame = IVIDEO_NA_FRAME;
   dynParams->interFrameInterval = 1;
@@ -461,7 +481,7 @@ gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
 
   if (self->outBufs) {
     dce_free (self->outBufs);
-    self->inBufs = NULL;
+    self->outBufs = NULL;
   }
 
   if (self->codec) {
@@ -553,6 +573,8 @@ gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
   XDAS_Int32 err;
   const GstVideoState *state;
   int i;
+  GstClockTime ts;
+  GstClockTime t;
 
   state = gst_base_video_encoder_get_state (base_video_encoder);
 
@@ -566,6 +588,7 @@ gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
   }
 
   inbuf = gst_buffer_ref (frame->sink_buffer);
+  ts = GST_BUFFER_TIMESTAMP (inbuf);
 have_inbuf:
   priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
   if (priv_in == NULL) {
@@ -574,6 +597,7 @@ have_inbuf:
     inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE));
     memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer),
         GST_BUFFER_SIZE (frame->sink_buffer));
+    GST_BUFFER_TIMESTAMP (inbuf) = ts;
     goto have_inbuf;
   }
 
@@ -608,14 +632,19 @@ have_inbuf:
   self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf);
   self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
 
-
   self->inArgs->inputID = GPOINTER_TO_INT (inbuf);
 
+  GST_DEBUG ("Calling VIDENC2_process");
+  t = gst_util_get_timestamp ();
   err = VIDENC2_process (self->codec, self->inBufs, self->outBufs,
       self->inArgs, self->outArgs);
+  t = gst_util_get_timestamp () - t;
+  GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t,
+      (gint) (t / 1000000));
   if (err) {
     GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x",
-        err, self->status->extendedError);
+        err, self->outArgs->extendedError);
+    gst_ducati_log_extended_error_info (self->outArgs->extendedError);
 
     err = VIDENC2_control (self->codec,
         XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams,
@@ -627,11 +656,39 @@ have_inbuf:
     return GST_FLOW_ERROR;
   }
 
-  if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME)
-    frame->is_sync_point = TRUE;
-  frame->src_buffer = gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
-  memcpy (GST_BUFFER_DATA (frame->src_buffer),
-      GST_BUFFER_DATA (outbuf), self->outArgs->bytesGenerated);
+  if (self->outArgs->bytesGenerated > 0) {
+    frame->is_sync_point =
+        GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self,
+        self->outArgs->encodedFrameType);
+    frame->src_buffer =
+        gst_buffer_new_and_alloc (self->outArgs->bytesGenerated);
+    memcpy (GST_BUFFER_DATA (frame->src_buffer), GST_BUFFER_DATA (outbuf),
+        self->outArgs->bytesGenerated);
+    GST_DEBUG_OBJECT (self, "Encoded frame in %u bytes",
+        self->outArgs->bytesGenerated);
+
+    /* As we can get frames in a different order we sent them (if the codec
+       supports B frames and we set it up for generating those), we need to
+       work out what input frame corresponds to the frame we just got, to
+       keep presentation times correct.
+       It seems that the codec will free buffers in the right order for this,
+       but I can not find anything saying this in the docs, so:
+       - it might be subject to change
+       - it might not be true in all setups
+       - it might not be true for all codecs
+       However, that's the only way I can see to do it. So there's a nice
+       assert below that will blow up if the codec does not free exactly one
+       input frame when it outputs a frame. That doesn't catch all cases,
+       such as when it frees them in the wrong order, but that seems less
+       likely to happen.
+       The timestamp and duration are given to the base class, which will
+       in turn set them onto the encoded buffer. */
+    g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]);
+    inbuf = GST_BUFFER (self->outArgs->freeBufID[0]);
+    frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+    frame->presentation_duration = GST_BUFFER_DURATION (inbuf);
+    GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf);
+  }
 
   gst_buffer_unref (outbuf);
 
@@ -645,6 +702,12 @@ have_inbuf:
   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
 }
 
+static gboolean
+gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type)
+{
+  return type == IVIDEO_I_FRAME;
+}
+
 static gboolean
 gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
 {