mfc: Recreate fimc context if settings change
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 31 Dec 2012 10:56:51 +0000 (11:56 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 31 Dec 2012 14:59:08 +0000 (15:59 +0100)
sys/mfc/gstmfcdec.c

index c466170..84a5562 100644 (file)
@@ -123,7 +123,6 @@ static gboolean
 gst_mfc_dec_start (GstVideoDecoder * decoder)
 {
   GstMFCDec *self = GST_MFC_DEC (decoder);
-  Fimc *fimc;
 
   GST_DEBUG_OBJECT (self, "Starting");
 
@@ -153,15 +152,6 @@ gst_mfc_dec_start (GstVideoDecoder * decoder)
     return FALSE;
   }
 
-  fimc = fimc_new ();
-
-  if (!fimc) {
-    GST_ELEMENT_ERROR (self, LIBRARY, INIT,
-        ("Failed to initialize FIMC context"), (NULL));
-    return FALSE;
-  }
-  self->fimc = fimc;
-
   return TRUE;
 }
 
@@ -381,29 +371,20 @@ enqueue_error:
 }
 
 static gboolean
-gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
+gst_mfc_dec_create_fimc (GstMFCDec * self, GstVideoCodecState * state)
 {
-  GstMFCDec *self = GST_MFC_DEC (decoder);
-  Fimc *fimc = self->fimc;
-  GstVideoCodecState *state;
-  GstCaps *allowed_caps;
-  GstVideoFormat format = GST_VIDEO_FORMAT_I420;
+  Fimc *fimc;
   FimcColorFormat fimc_format;
 
-  allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
-  allowed_caps = gst_caps_truncate (allowed_caps);
-  allowed_caps = gst_caps_fixate (allowed_caps);
-  if (!gst_caps_is_empty (allowed_caps)) {
-    const gchar *format_str;
-    GstStructure *s = gst_caps_get_structure (allowed_caps, 0);
-
-    format_str = gst_structure_get_string (s, "format");
-    if (format_str)
-      format = gst_video_format_from_string (format_str);
+  fimc = self->fimc;
+  if (fimc) {
+    fimc_free (fimc);
+    self->fimc = fimc = NULL;
   }
-  gst_caps_unref (allowed_caps);
 
-  switch (format) {
+  fimc = fimc_new ();
+
+  switch (state->info.finfo->format) {
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
       fimc_format = FIMC_COLOR_FORMAT_YUV420P;
@@ -416,8 +397,6 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
       break;
   }
 
-  fimc_release_src_buffers (fimc);
-
   if (fimc_set_src_format (fimc, FIMC_COLOR_FORMAT_YUV420SPT, self->width,
           self->height, self->src_stride, self->crop_left, self->crop_top,
           self->crop_width, self->crop_height) < 0)
@@ -426,7 +405,7 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
   if (fimc_request_src_buffers (fimc) < 0)
     goto fimc_src_requestbuffers_error;
 
-  fimc_release_dst_buffers (fimc);
+  self->fimc = fimc;
   self->dst[0] = NULL;
   self->dst[1] = NULL;
   self->dst[2] = NULL;
@@ -436,24 +415,13 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
 
   self->fimc_format = fimc_format;
 
-  state =
-      gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
-      format, self->crop_width, self->crop_height, self->input_state);
-
-  gst_video_codec_state_unref (state);
-
-  return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
-
-
-  GST_DEBUG_OBJECT (self,
-      "Got direct output buffer: %p [%d], %p [%d], %p [%d]", self->dst[0],
-      self->dst_stride[0], self->dst[1], self->dst_stride[1], self->dst[2],
-      self->dst_stride[2]);
+  return TRUE;
 
 fimc_src_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED,
         ("Failed to set FIMC source parameters"), (NULL));
+    fimc_free (fimc);
     return FALSE;
   }
 
@@ -461,10 +429,41 @@ fimc_src_requestbuffers_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED,
         ("Failed to request FIMC source buffers"), (NULL));
+    fimc_free (fimc);
     return FALSE;
   }
 }
 
+static gboolean
+gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
+{
+  GstMFCDec *self = GST_MFC_DEC (decoder);
+  GstVideoCodecState *state;
+  GstCaps *allowed_caps;
+  GstVideoFormat format = GST_VIDEO_FORMAT_I420;
+
+  allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
+  allowed_caps = gst_caps_truncate (allowed_caps);
+  allowed_caps = gst_caps_fixate (allowed_caps);
+  if (!gst_caps_is_empty (allowed_caps)) {
+    const gchar *format_str;
+    GstStructure *s = gst_caps_get_structure (allowed_caps, 0);
+
+    format_str = gst_structure_get_string (s, "format");
+    if (format_str)
+      format = gst_video_format_from_string (format_str);
+  }
+  gst_caps_unref (allowed_caps);
+
+  state =
+      gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
+      format, self->crop_width, self->crop_height, self->input_state);
+
+  gst_video_codec_state_unref (state);
+
+  return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
+}
+
 static GstFlowReturn
 gst_mfc_dec_fill_outbuf (GstMFCDec * self, GstBuffer * outbuf,
     struct mfc_buffer *mfc_outbuf, GstVideoCodecState * state)
@@ -490,8 +489,11 @@ gst_mfc_dec_fill_outbuf (GstMFCDec * self, GstBuffer * outbuf,
       && strcmp (mem->allocator->mem_type, "GstEGLImage") == 0) {
     void *dst[3];
 
-    if (self->mmap) {
-      fimc_release_dst_buffers (fimc);
+    if (self->mmap || !self->fimc) {
+      if (!gst_mfc_dec_create_fimc (self, state))
+        goto fimc_create_error;
+
+      fimc = self->fimc;
 
       if (self->format == GST_VIDEO_FORMAT_NV12) {
         self->dst_stride[0] = GST_ROUND_UP_4 (self->width);
@@ -526,13 +528,15 @@ gst_mfc_dec_fill_outbuf (GstMFCDec * self, GstBuffer * outbuf,
     if (fimc_convert (fimc, (void **) mfc_outbuf_comps, (void **) dst) < 0)
       goto fimc_convert_error;
   } else {
-    if (!self->mmap) {
-      fimc_release_dst_buffers (fimc);
+    if (!self->mmap || !self->fimc) {
+      if (!gst_mfc_dec_create_fimc (self, state))
+        goto fimc_create_error;
 
       self->dst_stride[0] = 0;
       self->dst_stride[1] = 0;
       self->dst_stride[2] = 0;
       self->mmap = TRUE;
+      fimc = self->fimc;
     }
 
     if (!self->dst[0]) {
@@ -601,6 +605,11 @@ frame_map_error:
     goto done;
   }
 
+fimc_create_error:
+  {
+    ret = GST_FLOW_ERROR;
+    goto done;
+  }
 
 fimc_dst_error:
   {