]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugin-ducati.git/blobdiff - src/gstducatividenc.c
ducatividenc: log extended error info, and use the correct one from _process
[glsdk/gst-plugin-ducati.git] / src / gstducatividenc.c
index d658be69943d84c676c1766580b7e4b90b0f1421..30470e620d412d741d0dc9f6a181d1454126f0b9 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "gstducati.h"
 #include "gstducatividenc.h"
-#include <ti/sdo/codecs/mpeg4enc/impeg4enc.h>
+#include "gstducatibufferpriv.h"
 
 #include <string.h>
 
@@ -36,6 +36,7 @@
 
 #define DEFAULT_BITRATE 2048
 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE
+#define DEFAULT_INTRA_INTERVAL 15
 
 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ())
 
@@ -49,13 +50,16 @@ 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,
     const GValue * value, GParamSpec * pspec);
 static void gst_ducati_videnc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
+static GstDucatiBufferPriv *get_buffer_priv (GstDucatiVidEnc * self,
+    GstBuffer * buf, gint stride, gint height);
 
 static gboolean gst_ducati_videnc_set_format (GstBaseVideoEncoder *
     base_video_encoder, GstVideoState * state);
@@ -71,6 +75,8 @@ 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_configure_default (GstDucatiVidEnc * self);
+static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc,
+    GstEvent * event);
 
 
 GST_BOILERPLATE (GstDucatiVidEnc, gst_ducati_videnc, GstBaseVideoEncoder,
@@ -139,6 +145,7 @@ gst_ducati_videnc_class_init (GstDucatiVidEncClass * klass)
   basevideoencoder_class->finish = GST_DEBUG_FUNCPTR (gst_ducati_videnc_finish);
   basevideoencoder_class->handle_frame =
       GST_DEBUG_FUNCPTR (gst_ducati_videnc_handle_frame);
+  basevideoencoder_class->event = GST_DEBUG_FUNCPTR (gst_ducati_videnc_event);
 
   klass->allocate_params = gst_ducati_videnc_allocate_params_default;
   klass->configure = gst_ducati_videnc_configure_default;
@@ -152,6 +159,10 @@ 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
@@ -159,6 +170,7 @@ gst_ducati_videnc_init (GstDucatiVidEnc * self, GstDucatiVidEncClass * klass)
 {
   GST_DEBUG ("gst_ducati_videnc_init");
 
+  self->device = NULL;
   self->engine = NULL;
   self->codec = NULL;
   self->params = NULL;
@@ -172,6 +184,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
@@ -201,6 +214,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);
   }
@@ -222,6 +238,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);
   }
@@ -229,14 +248,14 @@ gst_ducati_videnc_get_property (GObject * object, guint prop_id,
 
 static gboolean
 gst_ducati_videnc_configure (GstDucatiVidEnc * self)
-{  
+{
   int err;
   int i;
   int max_out_size = 0;
   const GstVideoState *state;
 
   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
-  
+
   if (!GST_DUCATIVIDENC_GET_CLASS (self)->configure (self))
     return FALSE;
 
@@ -251,12 +270,13 @@ gst_ducati_videnc_configure (GstDucatiVidEnc * self)
       return FALSE;
     }
   }
-  
+
   err = VIDENC2_control (self->codec,
       XDM_SETPARAMS, self->dynParams, self->status);
   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;
   }
@@ -278,13 +298,12 @@ gst_ducati_videnc_configure (GstDucatiVidEnc * self)
   }
 
   g_assert (self->input_pool == NULL);
-  self->input_pool =
-      gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL,
-      state->bytes_per_picture);
+  self->input_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
+      dce_get_fd (), NULL, state->bytes_per_picture);
 
   g_assert (self->output_pool == NULL);
-  self->output_pool =
-      gst_ducati_bufferpool_new (GST_ELEMENT (self), NULL, max_out_size);
+  self->output_pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
+      dce_get_fd (), NULL, max_out_size);
 
   GST_INFO_OBJECT (self, "configured");
 
@@ -297,42 +316,49 @@ static gboolean
 gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
 {
   VIDENC2_DynamicParams *dynParams;
+  VIDENC2_Params *params;
   const GstVideoState *state;
   int i;
 
   state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (self));
 
-  self->params = (VIDENC2_Params *) self->params;
-  self->params->encodingPreset = 0x03;
-  self->params->rateControlPreset = self->rate_preset;
-  self->params->maxHeight = state->height;
-  self->params->maxWidth = state->width;
-  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;
+  if (self->rect.w == 0)
+    self->rect.w = state->width;
+
+  if (self->rect.h == 0)
+    self->rect.h = state->height;
+
+  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 =
       gst_util_uint64_scale (1000, state->fps_n, state->fps_d);
   dynParams->targetFrameRate = dynParams->refFrameRate;
-  dynParams->inputWidth = state->width;
-  dynParams->inputHeight = state->height;
+  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->forceFrame = IVIDEO_NA_FRAME;
   dynParams->interFrameInterval = 1;
   dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
@@ -351,7 +377,15 @@ gst_ducati_videnc_configure_default (GstDucatiVidEnc * self)
 static gboolean
 gst_ducati_videnc_open_engine (GstDucatiVidEnc * self)
 {
-  self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, NULL);
+  int error_code;
+
+  if (self->device == NULL) {
+    self->device = dce_init ();
+    if (self->device == NULL)
+      return FALSE;
+  }
+
+  self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &error_code);
   if (self->engine == NULL) {
     GST_ERROR_OBJECT (self, "couldn't open engine");
     return FALSE;
@@ -370,8 +404,9 @@ gst_ducati_videnc_allocate_params (GstDucatiVidEnc * self)
 }
 
 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)
+gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self,
+    gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
+    gint outargs_sz)
 {
   self->params = dce_alloc (params_sz);
   memset (self->params, 0, params_sz);
@@ -439,7 +474,7 @@ gst_ducati_videnc_free_params (GstDucatiVidEnc * self)
 
   if (self->outBufs) {
     dce_free (self->outBufs);
-    self->inBufs = NULL;
+    self->outBufs = NULL;
   }
 
   if (self->codec) {
@@ -457,6 +492,11 @@ gst_ducati_videnc_close_engine (GstDucatiVidEnc * self)
     Engine_close (self->engine);
     self->engine = NULL;
   }
+
+  if (self->device) {
+    dce_deinit (self->device);
+    self->device = NULL;
+  }
 }
 
 
@@ -466,6 +506,7 @@ gst_ducati_videnc_start (GstBaseVideoEncoder * base_video_encoder)
   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
 
   self->configure = TRUE;
+  memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
 
   if (!gst_ducati_videnc_open_engine (self))
     goto fail;
@@ -490,15 +531,18 @@ gst_ducati_videnc_stop (GstBaseVideoEncoder * base_video_encoder)
   gst_ducati_videnc_close_engine (self);
 
   if (self->input_pool) {
-    gst_ducati_bufferpool_destroy (self->input_pool);
+    gst_drm_buffer_pool_destroy (self->input_pool);
     self->input_pool = NULL;
   }
 
   if (self->output_pool) {
-    gst_ducati_bufferpool_destroy (self->output_pool);
+    gst_drm_buffer_pool_destroy (self->output_pool);
     self->output_pool = NULL;
   }
 
+  /* reset cropping rect */
+  memset (&self->rect, 0, sizeof (GstDucatiVideoRectangle));
+
   return TRUE;
 }
 
@@ -518,10 +562,8 @@ gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
 {
   GstDucatiVidEnc *self = GST_DUCATIVIDENC (base_video_encoder);
   GstBuffer *inbuf, *outbuf;
-  guint8 *y_vaddr, *uv_vaddr;
-  SSPtr y_paddr, uv_paddr, outbuf_paddr;
+  GstDucatiBufferPriv *priv_in, *priv_out;
   XDAS_Int32 err;
-  XDAS_Int16 y_type, uv_type;
   const GstVideoState *state;
   int i;
 
@@ -538,52 +580,47 @@ gst_ducati_videnc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
 
   inbuf = gst_buffer_ref (frame->sink_buffer);
 have_inbuf:
-  y_vaddr = GST_BUFFER_DATA (inbuf);
-  uv_vaddr = y_vaddr + gst_video_format_get_component_offset (state->format,
-      1, state->width, state->height);
-  y_paddr = TilerMem_VirtToPhys (y_vaddr);
-  uv_paddr = TilerMem_VirtToPhys (uv_vaddr);
-  y_type = gst_ducati_get_mem_type (y_paddr);
-  uv_type = gst_ducati_get_mem_type (uv_paddr);
-  if (y_type < 0 || uv_type < 0) {
-    GST_DEBUG_OBJECT (self, "memcpying input %d %d", y_type, uv_type);
+  priv_in = get_buffer_priv (self, inbuf, state->width, state->height);
+  if (priv_in == NULL) {
+    GST_DEBUG_OBJECT (self, "memcpying input");
     gst_buffer_unref (inbuf);
-    inbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->input_pool, NULL));
+    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));
     goto have_inbuf;
   }
 
-  outbuf = GST_BUFFER (gst_ducati_bufferpool_get (self->output_pool, NULL));
+  outbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->output_pool, FALSE));
+  priv_out = get_buffer_priv (self, outbuf, state->width, state->height);
 
-  y_vaddr = GST_BUFFER_DATA (inbuf);
-  uv_vaddr = y_vaddr + gst_video_format_get_component_offset (state->format,
-      1, state->width, state->height);
-
-  y_paddr = TilerMem_VirtToPhys (y_vaddr);
-  uv_paddr = TilerMem_VirtToPhys (uv_vaddr);
-
-  outbuf_paddr = TilerMem_VirtToPhys (GST_BUFFER_DATA (outbuf));
-
-  self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) y_paddr;
-  self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_TILEDPAGE;
+  self->inBufs->planeDesc[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_in->bo);
+  self->inBufs->planeDesc[0].memType = XDM_MEMTYPE_BO;
   self->inBufs->planeDesc[0].bufSize.tileMem.width = state->width;
   self->inBufs->planeDesc[0].bufSize.tileMem.height = state->height;
-  self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) uv_paddr;
-  self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_TILEDPAGE;
+  self->inBufs->planeDesc[1].buf = (XDAS_Int8 *) priv_in->uv_offset;
+  self->inBufs->planeDesc[1].memType = XDM_MEMTYPE_BO_OFFSET;
   self->inBufs->planeDesc[1].bufSize.tileMem.width = state->width;
   self->inBufs->planeDesc[1].bufSize.tileMem.height = state->height / 2;
+  /* setting imageRegion doesn't seem to be strictly needed if activeFrameRegion
+   * is set but we set it anyway...
+   */
+  self->inBufs->imageRegion.topLeft.x = self->rect.x;
+  self->inBufs->imageRegion.topLeft.y = self->rect.y;
+  self->inBufs->imageRegion.bottomRight.x = self->rect.x + self->rect.w;
+  self->inBufs->imageRegion.bottomRight.y = self->rect.y + self->rect.h;
+  self->inBufs->activeFrameRegion.topLeft.x = self->rect.x;
+  self->inBufs->activeFrameRegion.topLeft.y = self->rect.y;
+  self->inBufs->activeFrameRegion.bottomRight.x = self->rect.x + self->rect.w;
+  self->inBufs->activeFrameRegion.bottomRight.y = self->rect.y + self->rect.h;
   self->inBufs->imagePitch[0] = state->width;
   self->inBufs->imagePitch[1] = state->width;
-  self->inBufs->imageRegion.bottomRight.x = state->width;
-  self->inBufs->activeFrameRegion.bottomRight.x = state->width;
-  self->inBufs->imageRegion.bottomRight.y = state->height;
-  self->inBufs->activeFrameRegion.bottomRight.y = state->height;
   self->inBufs->topFieldFirstFlag = TRUE;
 
   self->outBufs->numBufs = 1;
-  self->outBufs->descs[0].buf = (XDAS_Int8 *) outbuf_paddr;
+  self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv_out->bo);
   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);
 
@@ -591,7 +628,8 @@ have_inbuf:
       self->inArgs, self->outArgs);
   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,
@@ -603,6 +641,13 @@ have_inbuf:
     return GST_FLOW_ERROR;
   }
 
+  if (!strcmp (GST_DUCATIVIDENC_GET_CLASS (self)->codec_name, "ivahd_h264enc")) {
+    if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME)
+      frame->is_sync_point = TRUE;
+  } else {
+    if (self->outArgs->encodedFrameType == IVIDEO_I_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);
@@ -618,3 +663,53 @@ have_inbuf:
 
   return gst_base_video_encoder_finish_frame (base_video_encoder, frame);
 }
+
+static gboolean
+gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event)
+{
+  gboolean handled = FALSE;
+  GstDucatiVidEnc *self = GST_DUCATIVIDENC (enc);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CROP:
+      gst_event_parse_crop (event, &self->rect.y, &self->rect.x,
+          &self->rect.w, &self->rect.h);
+      GST_INFO_OBJECT (self, "got crop event top %d left %d %dx%d",
+          self->rect.x, self->rect.y, self->rect.w, self->rect.h);
+      handled = TRUE;
+      break;
+    default:
+      break;
+  }
+
+  return handled;
+}
+
+static GstDucatiBufferPriv *
+get_buffer_priv (GstDucatiVidEnc * self, GstBuffer * buf,
+    gint stride, gint height)
+{
+  GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
+  if (!priv) {
+    GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
+    GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
+
+    /* if it isn't a dmabuf buffer that we can import, then there
+     * is nothing we can do with it:
+     */
+    if (!dmabuf) {
+      GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
+      return NULL;
+    }
+
+    priv = gst_ducati_buffer_priv_new ();
+    priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
+
+    priv->uv_offset = gst_video_format_get_component_offset (format,
+        1, stride, height);
+    priv->size = gst_video_format_get_size (format, stride, height);
+
+    gst_ducati_buffer_priv_set (buf, priv);
+  }
+  return priv;
+}