theoradec: move negotiation code around
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 2 Mar 2012 10:01:44 +0000 (11:01 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 2 Mar 2012 10:34:10 +0000 (11:34 +0100)
Move the format negotiation to the bufferpool negotiation.

ext/theora/gsttheoradec.c
ext/theora/gsttheoradec.h

index c747370..7c7cd24 100644 (file)
@@ -768,20 +768,107 @@ theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
 }
 
 static GstFlowReturn
-theora_negotiate_pool (GstTheoraDec * dec)
+theora_negotiate (GstTheoraDec * dec)
 {
+  GstVideoFormat format;
   GstQuery *query;
   GstBufferPool *pool;
   guint size, min, max, prefix, alignment;
   GstStructure *config;
   GstCaps *caps;
-  GstVideoInfo info;
+  GstVideoInfo info, cinfo;
+
+  /* theora has:
+   *
+   *  frame_width/frame_height : dimension of the encoded frame
+   *  pic_width/pic_height : dimension of the visible part
+   *  pic_x/pic_y : offset in encoded frame where visible part starts
+   */
+  GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, PAR %d/%d, fps %d/%d",
+      dec->info.frame_width, dec->info.frame_height,
+      dec->info.aspect_numerator, dec->info.aspect_denominator,
+      dec->info.fps_numerator, dec->info.fps_denominator);
+  GST_DEBUG_OBJECT (dec, "picture dimension %dx%d, offset %d:%d",
+      dec->info.pic_width, dec->info.pic_height, dec->info.pic_x,
+      dec->info.pic_y);
+
+  switch (dec->info.pixel_fmt) {
+    case TH_PF_444:
+      dec->output_bpp = 24;
+      format = GST_VIDEO_FORMAT_Y444;
+      break;
+    case TH_PF_420:
+      dec->output_bpp = 12;     /* Average bits per pixel. */
+      format = GST_VIDEO_FORMAT_I420;
+      break;
+    case TH_PF_422:
+      dec->output_bpp = 16;
+      format = GST_VIDEO_FORMAT_Y42B;
+      break;
+    default:
+      goto invalid_format;
+  }
+
+  if (dec->info.pic_width != dec->info.frame_width ||
+      dec->info.pic_height != dec->info.frame_height ||
+      dec->info.pic_x != 0 || dec->info.pic_y != 0) {
+    GST_DEBUG_OBJECT (dec, "we need to crop");
+    dec->need_cropping = TRUE;
+  } else {
+    GST_DEBUG_OBJECT (dec, "no cropping needed");
+    dec->need_cropping = FALSE;
+  }
+
+  /* info contains the dimensions for the coded picture before cropping */
+  gst_video_info_set_format (&info, format, dec->info.frame_width,
+      dec->info.frame_height);
+  info.fps_n = dec->info.fps_numerator;
+  info.fps_d = dec->info.fps_denominator;
+  /* calculate par
+   * the info.aspect_* values reflect PAR;
+   * 0:x and x:0 are allowed and can be interpreted as 1:1.
+   */
+  if (dec->have_par) {
+    /* we had a par on the sink caps, override the encoded par */
+    GST_DEBUG_OBJECT (dec, "overriding with input PAR %dx%d", dec->par_num,
+        dec->par_den);
+    info.par_n = dec->par_num;
+    info.par_d = dec->par_den;
+  } else {
+    /* take encoded par */
+    info.par_n = dec->info.aspect_numerator;
+    info.par_d = dec->info.aspect_denominator;
+  }
+  if (info.par_n == 0 || info.par_d == 0) {
+    info.par_n = info.par_d = 1;
+  }
+
+  /* these values are for all versions of the colorspace specified in the
+   * theora info */
+  info.chroma_site = GST_VIDEO_CHROMA_SITE_JPEG;
+  info.colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
+  info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
+  info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
+  switch (dec->info.colorspace) {
+    case TH_CS_ITU_REC_470M:
+      info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
+      break;
+    case TH_CS_ITU_REC_470BG:
+      info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
+      break;
+    default:
+      info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
+      break;
+  }
+
+  /* remove reconfigure flag now */
+  gst_pad_check_reconfigure (dec->srcpad);
 
   /* for the output caps we always take the cropped dimensions */
-  info = dec->vinfo;
-  gst_video_info_set_format (&info, GST_VIDEO_INFO_FORMAT (&info),
+  cinfo = info;
+  gst_video_info_set_format (&cinfo, GST_VIDEO_INFO_FORMAT (&info),
       dec->info.pic_width, dec->info.pic_height);
-  caps = gst_video_info_to_caps (&info);
+  caps = gst_video_info_to_caps (&cinfo);
   gst_pad_set_caps (dec->srcpad, caps);
 
   /* find a pool for the negotiated caps now */
@@ -805,6 +892,7 @@ theora_negotiate_pool (GstTheoraDec * dec)
     pool = NULL;
     dec->has_cropping = FALSE;
   }
+  GST_DEBUG_OBJECT (dec, "downstream cropping %d", dec->has_cropping);
 
   if (pool == NULL) {
     /* we did not get a pool, make one ourselves then */
@@ -816,16 +904,16 @@ theora_negotiate_pool (GstTheoraDec * dec)
   dec->pool = pool;
 
   if (dec->has_cropping) {
-    dec->outinfo = dec->vinfo;
+    dec->vinfo = info;
     /* we can crop, configure the pool with buffers of caps and size of the
      * decoded picture size and then crop them with metadata */
     gst_caps_unref (caps);
-    caps = gst_video_info_to_caps (&dec->vinfo);
+    caps = gst_video_info_to_caps (&info);
   } else {
     /* no cropping, use cropped videoinfo */
-    dec->outinfo = info;
+    dec->vinfo = cinfo;
   }
-  size = MAX (size, GST_VIDEO_INFO_SIZE (&dec->outinfo));
+  size = MAX (size, GST_VIDEO_INFO_SIZE (&dec->vinfo));
 
   config = gst_buffer_pool_get_config (pool);
   gst_buffer_pool_config_set (config, caps, size, min, max, prefix, alignment);
@@ -836,8 +924,6 @@ theora_negotiate_pool (GstTheoraDec * dec)
    * option and only activate it then. */
   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
 
-  GST_DEBUG_OBJECT (dec, "downstream cropping %d", dec->has_cropping);
-
   gst_buffer_pool_set_config (pool, config);
   /* and activate */
   gst_buffer_pool_set_active (pool, TRUE);
@@ -845,106 +931,23 @@ theora_negotiate_pool (GstTheoraDec * dec)
   gst_query_unref (query);
 
   return GST_FLOW_OK;
+
+  /* ERRORS */
+invalid_format:
+  {
+    GST_ERROR_OBJECT (dec, "Invalid pixel format %d", dec->info.pixel_fmt);
+    return GST_FLOW_ERROR;
+  }
 }
 
 static GstFlowReturn
 theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
 {
-  GstVideoFormat format;
-  gint par_num, par_den;
   GstFlowReturn ret = GST_FLOW_OK;
   GList *walk;
 
-  GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
-      dec->info.fps_numerator, dec->info.fps_denominator,
-      dec->info.aspect_numerator, dec->info.aspect_denominator);
-
-  /* calculate par
-   * the info.aspect_* values reflect PAR;
-   * 0:x and x:0 are allowed and can be interpreted as 1:1.
-   */
-  if (dec->have_par) {
-    /* we had a par on the sink caps, override the encoded par */
-    GST_DEBUG_OBJECT (dec, "overriding with input PAR");
-    par_num = dec->par_num;
-    par_den = dec->par_den;
-  } else {
-    /* take encoded par */
-    par_num = dec->info.aspect_numerator;
-    par_den = dec->info.aspect_denominator;
-  }
-  if (par_num == 0 || par_den == 0) {
-    par_num = par_den = 1;
-  }
-  /* theora has:
-   *
-   *  frame_width/frame_height : dimension of the encoded frame
-   *  pic_width/pic_height : dimension of the visible part
-   *  pic_x/pic_y : offset in encoded frame where visible part starts
-   */
-  GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, PAR %d/%d",
-      dec->info.frame_width, dec->info.frame_height, par_num, par_den);
-  GST_DEBUG_OBJECT (dec, "picture dimension %dx%d, offset %d:%d",
-      dec->info.pic_width, dec->info.pic_height, dec->info.pic_x,
-      dec->info.pic_y);
-
-  switch (dec->info.pixel_fmt) {
-    case TH_PF_444:
-      dec->output_bpp = 24;
-      format = GST_VIDEO_FORMAT_Y444;
-      break;
-    case TH_PF_420:
-      dec->output_bpp = 12;     /* Average bits per pixel. */
-      format = GST_VIDEO_FORMAT_I420;
-      break;
-    case TH_PF_422:
-      dec->output_bpp = 16;
-      format = GST_VIDEO_FORMAT_Y42B;
-      break;
-    default:
-      goto invalid_format;
-  }
-
-  if (dec->info.pic_width != dec->info.frame_width ||
-      dec->info.pic_height != dec->info.frame_height ||
-      dec->info.pic_x != 0 || dec->info.pic_y != 0) {
-    GST_DEBUG_OBJECT (dec, "we need to crop");
-    dec->need_cropping = TRUE;
-  } else {
-    GST_DEBUG_OBJECT (dec, "no cropping needed");
-    dec->need_cropping = FALSE;
-  }
-
-  /* our info contains the dimensions for the coded picture before cropping */
-  gst_video_info_set_format (&dec->vinfo, format, dec->info.frame_width,
-      dec->info.frame_height);
-  dec->vinfo.fps_n = dec->info.fps_numerator;
-  dec->vinfo.fps_d = dec->info.fps_denominator;
-  dec->vinfo.par_n = par_num;
-  dec->vinfo.par_d = par_den;
-
-  /* these values are for all versions of the colorspace specified in the
-   * theora info */
-  dec->vinfo.chroma_site = GST_VIDEO_CHROMA_SITE_JPEG;
-  dec->vinfo.colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
-  dec->vinfo.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
-  dec->vinfo.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
-  switch (dec->info.colorspace) {
-    case TH_CS_ITU_REC_470M:
-      dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
-      break;
-    case TH_CS_ITU_REC_470BG:
-      dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
-      break;
-    default:
-      dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
-      break;
-  }
-
-  /* remove reconfigure flag now */
-  gst_pad_check_reconfigure (dec->srcpad);
-
-  theora_negotiate_pool (dec);
+  if ((ret = theora_negotiate (dec)) != GST_FLOW_OK)
+    goto negotiate_failed;
 
   /* done */
   dec->decoder = th_decode_alloc (&dec->info, dec->setup);
@@ -983,10 +986,10 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
   return ret;
 
   /* ERRORS */
-invalid_format:
+negotiate_failed:
   {
-    GST_ERROR_OBJECT (dec, "Invalid pixel format %d", dec->info.pixel_fmt);
-    return GST_FLOW_ERROR;
+    GST_ERROR_OBJECT (dec, "failed to negotiate");
+    return ret;
   }
 }
 
@@ -1114,15 +1117,19 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out)
   GstVideoCropMeta *crop;
   gint offset_x, offset_y;
 
-  if (gst_pad_check_reconfigure (dec->srcpad))
-    theora_negotiate_pool (dec);
+  if G_UNLIKELY
+    (gst_pad_check_reconfigure (dec->srcpad))
+        if G_UNLIKELY
+      ((result = theora_negotiate (dec)) != GST_FLOW_OK)
+          goto negotiate_failed;
 
   result = gst_buffer_pool_acquire_buffer (dec->pool, out, NULL);
   if (G_UNLIKELY (result != GST_FLOW_OK))
     goto no_buffer;
 
-  if (!gst_video_frame_map (&frame, &dec->outinfo, *out, GST_MAP_WRITE))
-    goto invalid_frame;
+  if G_UNLIKELY
+    (!gst_video_frame_map (&frame, &dec->vinfo, *out, GST_MAP_WRITE))
+        goto invalid_frame;
 
   if (!dec->has_cropping) {
     /* we need to crop the hard way */
@@ -1180,6 +1187,12 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out)
   return GST_FLOW_OK;
 
   /* ERRORS */
+negotiate_failed:
+  {
+    GST_DEBUG_OBJECT (dec, "could not negotiate, reason: %s",
+        gst_flow_get_name (result));
+    return result;
+  }
 no_buffer:
   {
     GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
index 6c671e1..e9fe1a8 100644 (file)
@@ -70,7 +70,6 @@ struct _GstTheoraDec
   guint64 frame_nr;
   gboolean need_keyframe;
   GstVideoInfo vinfo;
-  GstVideoInfo outinfo;
 
   gint output_bpp;
   GstBufferPool *pool;