schro: Add support for video metadata and arbitrary strides
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 23 Jul 2012 09:36:01 +0000 (11:36 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 23 Jul 2012 09:36:01 +0000 (11:36 +0200)
ext/schroedinger/gstschrodec.c
ext/schroedinger/gstschroenc.c
ext/schroedinger/gstschroutils.c
ext/schroedinger/gstschroutils.h

index ced4601..0e93b73 100644 (file)
@@ -24,6 +24,8 @@
 #include <gst/gst.h>
 #include <gst/base/gstadapter.h>
 #include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
 #include <gst/video/gstvideodecoder.h>
 #include <string.h>
 #include <schroedinger/schro.h>
@@ -89,6 +91,8 @@ static GstFlowReturn gst_schro_dec_handle_frame (GstVideoDecoder * decoder,
     GstVideoCodecFrame * frame);
 static gboolean gst_schro_dec_finish (GstVideoDecoder * base_video_decoder);
 static void gst_schrodec_send_tags (GstSchroDec * schro_dec);
+static gboolean gst_schro_dec_decide_allocation (GstVideoDecoder * decoder,
+    GstQuery * query);
 
 static GstStaticPadTemplate gst_schro_dec_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
@@ -136,6 +140,8 @@ gst_schro_dec_class_init (GstSchroDecClass * klass)
   base_video_decoder_class->handle_frame =
       GST_DEBUG_FUNCPTR (gst_schro_dec_handle_frame);
   base_video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_schro_dec_finish);
+  base_video_decoder_class->decide_allocation =
+      GST_DEBUG_FUNCPTR (gst_schro_dec_decide_allocation);
 }
 
 static void
@@ -457,10 +463,7 @@ gst_schro_dec_process (GstSchroDec * schro_dec, gboolean eos)
         outbuf =
             gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER
             (schro_dec));
-        schro_frame =
-            gst_schro_buffer_wrap (outbuf, TRUE,
-            GST_VIDEO_INFO_FORMAT (&state->info), state->info.width,
-            state->info.height);
+        schro_frame = gst_schro_buffer_wrap (outbuf, TRUE, &state->info);
         schro_decoder_add_output_picture (schro_dec->decoder, schro_frame);
         gst_video_codec_state_unref (state);
         break;
@@ -552,3 +555,26 @@ gst_schro_dec_finish (GstVideoDecoder * base_video_decoder)
 
   return gst_schro_dec_process (schro_dec, TRUE);
 }
+
+static gboolean
+gst_schro_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
+{
+  GstBufferPool *pool;
+  GstStructure *config;
+
+  if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
+          query))
+    return FALSE;
+
+  gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
+
+  config = gst_buffer_pool_get_config (pool);
+  if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_META);
+  }
+
+  gst_object_unref (pool);
+
+  return TRUE;
+}
index 0affaa2..3b9118c 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
 #include <gst/video/gstvideoencoder.h>
 #include <gst/video/gstvideoutils.h>
 #include <string.h>
@@ -104,6 +105,8 @@ static GstFlowReturn gst_schro_enc_handle_frame (GstVideoEncoder *
 static GstFlowReturn gst_schro_enc_pre_push (GstVideoEncoder *
     base_video_encoder, GstVideoCodecFrame * frame);
 static void gst_schro_enc_finalize (GObject * object);
+static gboolean gst_schro_enc_propose_allocation (GstVideoEncoder * encoder,
+    GstQuery * query);
 
 static GstStaticPadTemplate gst_schro_enc_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
@@ -214,6 +217,8 @@ gst_schro_enc_class_init (GstSchroEncClass * klass)
   basevideocoder_class->handle_frame =
       GST_DEBUG_FUNCPTR (gst_schro_enc_handle_frame);
   basevideocoder_class->pre_push = GST_DEBUG_FUNCPTR (gst_schro_enc_pre_push);
+  basevideocoder_class->propose_allocation =
+      GST_DEBUG_FUNCPTR (gst_schro_enc_propose_allocation);
 }
 
 static void
@@ -525,9 +530,7 @@ gst_schro_enc_handle_frame (GstVideoEncoder * base_video_encoder,
 
   /* FIXME : We could make that method just take GstVideoInfo ... */
   schro_frame = gst_schro_buffer_wrap (gst_buffer_ref (frame->input_buffer),
-      FALSE,
-      GST_VIDEO_INFO_FORMAT (info),
-      GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
+      FALSE, info);
 
   GST_DEBUG ("pushing frame %p", frame);
   schro_encoder_push_frame_full (schro_enc->encoder, schro_frame, frame);
@@ -580,6 +583,16 @@ gst_schro_enc_pre_push (GstVideoEncoder * base_video_encoder,
   return GST_FLOW_OK;
 }
 
+static gboolean
+gst_schro_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
+{
+  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
+
+  return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
+      query);
+}
+
+
 static GstFlowReturn
 gst_schro_enc_process (GstSchroEnc * schro_enc)
 {
index 3279209..db9ff3b 100644 (file)
@@ -38,8 +38,7 @@ GST_DEBUG_CATEGORY_EXTERN (schro_debug);
 
 typedef struct
 {
-  GstBuffer *buf;
-  GstMapInfo info;
+  GstVideoFrame frame;
 } FrameData;
 
 
@@ -48,8 +47,7 @@ gst_schro_frame_free (SchroFrame * frame, void *priv)
 {
   FrameData *data = priv;
 
-  gst_buffer_unmap (data->buf, &data->info);
-  gst_buffer_unref (data->buf);
+  gst_video_frame_unmap (&data->frame);
 
   g_slice_free (FrameData, data);
 }
@@ -58,58 +56,62 @@ GstBuffer *
 gst_schro_frame_get_buffer (SchroFrame * frame)
 {
   if (frame->priv)
-    return gst_buffer_ref (((FrameData *) frame->priv)->buf);
+    return gst_buffer_ref (((FrameData *) frame->priv)->frame.buffer);
 
   return NULL;
 }
 
 SchroFrame *
-gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoFormat format,
-    int width, int height)
+gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoInfo * vinfo)
 {
   SchroFrame *frame;
-  GstMapInfo info;
+  GstVideoFrame vframe;
   FrameData *data;
+  gint i;
 
-  if (!gst_buffer_map (buf, &info, (write ? GST_MAP_READWRITE : GST_MAP_READ)))
+  if (!gst_video_frame_map (&vframe, vinfo, buf,
+          (write ? GST_MAP_READWRITE : GST_MAP_READ)))
     return NULL;
 
-  switch (format) {
+  frame = schro_frame_new ();
+
+  frame->width = GST_VIDEO_FRAME_WIDTH (&vframe);
+  frame->height = GST_VIDEO_FRAME_HEIGHT (&vframe);
+
+  switch (GST_VIDEO_FRAME_FORMAT (&vframe)) {
     case GST_VIDEO_FORMAT_I420:
-      frame = schro_frame_new_from_data_I420 (info.data, width, height);
-      break;
     case GST_VIDEO_FORMAT_YV12:
-      frame = schro_frame_new_from_data_YV12 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_U8_420;
       break;
     case GST_VIDEO_FORMAT_YUY2:
-      frame = schro_frame_new_from_data_YUY2 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_YUYV;
       break;
     case GST_VIDEO_FORMAT_UYVY:
-      frame = schro_frame_new_from_data_UYVY (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_UYVY;
       break;
     case GST_VIDEO_FORMAT_AYUV:
-      frame = schro_frame_new_from_data_AYUV (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_AYUV;
       break;
 #if SCHRO_CHECK_VERSION(1,0,12)
     case GST_VIDEO_FORMAT_ARGB:
-      frame = schro_frame_new_from_data_ARGB (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_ARGB;
       break;
 #endif
 #if SCHRO_CHECK_VERSION(1,0,11)
     case GST_VIDEO_FORMAT_Y42B:
-      frame = schro_frame_new_from_data_Y42B (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_U8_422;
       break;
     case GST_VIDEO_FORMAT_Y444:
-      frame = schro_frame_new_from_data_Y444 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_U8_444;
       break;
     case GST_VIDEO_FORMAT_v210:
-      frame = schro_frame_new_from_data_v210 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_v210;
       break;
     case GST_VIDEO_FORMAT_v216:
-      frame = schro_frame_new_from_data_v216 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_v216;
       break;
     case GST_VIDEO_FORMAT_AYUV64:
-      frame = schro_frame_new_from_data_AY64 (info.data, width, height);
+      frame->format = SCHRO_FRAME_FORMAT_AY64;
       break;
 #endif
     default:
@@ -117,9 +119,38 @@ gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoFormat format,
       return NULL;
   }
 
+  if (SCHRO_FRAME_IS_PACKED (frame->format)) {
+    frame->components[0].format = frame->format;
+    frame->components[0].width = frame->width;
+    frame->components[0].height = frame->height;
+    frame->components[0].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0);
+    frame->components[0].length = frame->components[0].stride * frame->height;
+    frame->components[0].data = vframe.data[0];
+    frame->components[0].v_shift = 0;
+    frame->components[0].h_shift = 0;
+  } else {
+    for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&vframe); i++) {
+      frame->components[i].format = frame->format;
+      frame->components[i].width = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, i);
+      frame->components[i].height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
+      frame->components[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
+      frame->components[i].length =
+          frame->components[i].stride * frame->components[i].height;
+      frame->components[i].data = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
+      if (i == 0) {
+        frame->components[i].v_shift = 0;
+        frame->components[i].h_shift = 0;
+      } else {
+        frame->components[i].v_shift =
+            SCHRO_FRAME_FORMAT_H_SHIFT (frame->format);
+        frame->components[i].h_shift =
+            SCHRO_FRAME_FORMAT_H_SHIFT (frame->format);
+      }
+    }
+  }
+
   data = g_slice_new0 (FrameData);
-  data->buf = buf;
-  data->info = info;
+  data->frame = vframe;
   schro_frame_set_free_callback (frame, gst_schro_frame_free, data);
 
   return frame;
index 705dd8c..bdc41b6 100644 (file)
@@ -35,8 +35,7 @@
 #endif
 
 SchroFrame *
-gst_schro_buffer_wrap (GstBuffer *buf, gboolean write, GstVideoFormat format, int width,
-    int height);
+gst_schro_buffer_wrap (GstBuffer *buf, gboolean write, GstVideoInfo * vinfo);
 GstBuffer * gst_schro_frame_get_buffer (SchroFrame * frame);
 
 GstBuffer * gst_schro_wrap_schro_buffer (SchroBuffer *buffer);