omxvideoenc: Implement getcaps() vfunc
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 12 Feb 2013 09:53:24 +0000 (10:53 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 12 Feb 2013 10:03:30 +0000 (11:03 +0100)
omx/gstomxvideoenc.c

index 0832381..84dc9f1 100644 (file)
@@ -92,6 +92,8 @@ static GstFlowReturn gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
 static gboolean gst_omx_video_enc_finish (GstVideoEncoder * encoder);
 static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
     GstQuery * query);
+static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
+    GstCaps * filter);
 
 static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self,
     gboolean at_eos);
@@ -188,6 +190,7 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
   video_encoder_class->finish = GST_DEBUG_FUNCPTR (gst_omx_video_enc_finish);
   video_encoder_class->propose_allocation =
       GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
+  video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
 
   klass->cdata.default_sink_template_caps = "video/x-raw, "
       "width = " GST_VIDEO_SIZE_RANGE ", "
@@ -1508,3 +1511,75 @@ gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
       GST_VIDEO_ENCODER_CLASS
       (gst_omx_video_enc_parent_class)->propose_allocation (encoder, query);
 }
+
+static GstCaps *
+gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
+{
+  GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+  GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+  GstOMXPort *port = self->in_port;
+  OMX_VIDEO_PARAM_PORTFORMATTYPE param;
+  OMX_ERRORTYPE err;
+  GstCaps *comp_supported_caps;
+  gint old_index;
+
+  if (!self->component)
+    return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = port->index;
+  param.nIndex = 0;
+  if (!(klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER))
+    param.xFramerate = (25 << 16) / (1);
+  else
+    param.xFramerate = (25) / (1);
+
+  old_index = -1;
+  comp_supported_caps = gst_caps_new_empty ();
+  do {
+    err =
+        gst_omx_component_get_parameter (self->component,
+        OMX_IndexParamVideoPortFormat, &param);
+
+    /* FIXME: Workaround for Bellagio that simply always
+     * returns the same value regardless of nIndex and
+     * never returns OMX_ErrorNoMore
+     */
+    if (old_index == param.nIndex)
+      break;
+
+    if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
+      switch (param.eColorFormat) {
+        case OMX_COLOR_FormatYUV420Planar:
+        case OMX_COLOR_FormatYUV420PackedPlanar:
+          gst_caps_append_structure (comp_supported_caps,
+              gst_structure_new ("video/x-raw",
+                  "format", G_TYPE_STRING, "I420", NULL));
+          GST_DEBUG_OBJECT (self, "Component supports I420 (%d) at index %d",
+              param.eColorFormat, param.nIndex);
+          break;
+        case OMX_COLOR_FormatYUV420SemiPlanar:
+          gst_caps_append_structure (comp_supported_caps,
+              gst_structure_new ("video/x-raw",
+                  "format", G_TYPE_STRING, "NV12", NULL));
+          GST_DEBUG_OBJECT (self, "Component supports NV12 (%d) at index %d",
+              param.eColorFormat, param.nIndex);
+          break;
+        default:
+          break;
+      }
+    }
+    old_index = param.nIndex++;
+  } while (err == OMX_ErrorNone);
+
+  if (!gst_caps_is_empty (comp_supported_caps)) {
+    GstCaps *ret =
+        gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
+
+    gst_caps_unref (comp_supported_caps);
+    return ret;
+  } else {
+    gst_caps_unref (comp_supported_caps);
+    return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+  }
+}