[MOVED FROM BAD 017/134] vp8: Use correct strides and plane offsets for GStreamer
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 19 May 2010 12:46:48 +0000 (14:46 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Sun, 16 Sep 2012 13:27:13 +0000 (15:27 +0200)
ext/vp8/gstvp8dec.c
ext/vp8/gstvp8enc.c

index 4596404805fd0da51c8f602cb0571e670a072a2b..00eb7e20b95cf50063ad2fd842b89670205b85c1 100644 (file)
@@ -263,6 +263,53 @@ gst_vp8_dec_send_tags (GstVP8Dec * dec)
       GST_BASE_VIDEO_CODEC_SRC_PAD (dec), list);
 }
 
+static void
+gst_vp8_dec_image_to_buffer (GstVP8Dec * dec, const vpx_image_t * img,
+    GstBuffer * buffer)
+{
+  GstBaseVideoDecoder *decoder = (GstBaseVideoDecoder *) dec;
+  int stride, w, h, i;
+  guint8 *d;
+
+  d = GST_BUFFER_DATA (buffer) +
+      gst_video_format_get_component_offset (decoder->state.format, 0,
+      decoder->state.width, decoder->state.height);
+  stride =
+      gst_video_format_get_row_stride (decoder->state.format, 0,
+      decoder->state.width);
+  h = gst_video_format_get_component_height (decoder->state.format, 0,
+      decoder->state.height);
+  h = MIN (h, img->h);
+  w = gst_video_format_get_component_width (decoder->state.format, 0,
+      decoder->state.width);
+  w = MIN (w, img->w);
+
+  for (i = 0; i < h; i++)
+    memcpy (d + i * stride, img->planes[PLANE_Y] + i * img->stride[PLANE_Y], w);
+
+  d = GST_BUFFER_DATA (buffer) +
+      gst_video_format_get_component_offset (decoder->state.format, 1,
+      decoder->state.width, decoder->state.height);
+  stride =
+      gst_video_format_get_row_stride (decoder->state.format, 1,
+      decoder->state.width);
+  h = gst_video_format_get_component_height (decoder->state.format, 1,
+      decoder->state.height);
+  h = MIN (h, img->h >> img->y_chroma_shift);
+  w = gst_video_format_get_component_width (decoder->state.format, 1,
+      decoder->state.width);
+  w = MIN (w, img->w >> img->x_chroma_shift);
+  for (i = 0; i < h; i++)
+    memcpy (d + i * stride, img->planes[PLANE_U] + i * img->stride[PLANE_U], w);
+
+  d = GST_BUFFER_DATA (buffer) +
+      gst_video_format_get_component_offset (decoder->state.format, 2,
+      decoder->state.width, decoder->state.height);
+  /* Same stride, height, width as above */
+  for (i = 0; i < h; i++)
+    memcpy (d + i * stride, img->planes[PLANE_V] + i * img->stride[PLANE_V], w);
+}
+
 static GstFlowReturn
 gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame)
 {
@@ -342,35 +389,20 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame)
 
   img = vpx_codec_get_frame (&dec->decoder, &iter);
   if (img) {
-    int i;
 
     ret = gst_base_video_decoder_alloc_src_frame (decoder, frame);
 
-    if (ret == GST_FLOW_OK) {
-      for (i = 0; i < decoder->state.height; i++) {
-        memcpy (GST_BUFFER_DATA (frame->src_buffer) + i * decoder->state.width,
-            img->planes[0] + i * img->stride[0], decoder->state.width);
-      }
-      for (i = 0; i < decoder->state.height / 2; i++) {
-        memcpy (GST_BUFFER_DATA (frame->src_buffer) +
-            decoder->state.width * decoder->state.height +
-            i * decoder->state.width / 2,
-            img->planes[1] + i * img->stride[1], decoder->state.width / 2);
-      }
-      for (i = 0; i < decoder->state.height / 2; i++) {
-        memcpy (GST_BUFFER_DATA (frame->src_buffer) +
-            decoder->state.width * decoder->state.height +
-            decoder->state.width * decoder->state.height / 4 +
-            i * decoder->state.width / 2,
-            img->planes[2] + i * img->stride[2], decoder->state.width / 2);
-      }
-    }
+    if (ret == GST_FLOW_OK)
+      gst_vp8_dec_image_to_buffer (dec, img, frame->src_buffer);
 
     gst_base_video_decoder_finish_frame (decoder, frame);
 
-    do {
+    vpx_img_free (img);
+
+    while ((img = vpx_codec_get_frame (&dec->decoder, &iter))) {
+      GST_WARNING_OBJECT (decoder, "Multiple decoded frames... dropping");
       vpx_img_free (img);
-    } while ((img = vpx_codec_get_frame (&dec->decoder, &iter)));
+    }
   } else {
     /* Invisible frame */
     gst_base_video_decoder_skip_frame (decoder, frame);
index 32310279a199d35343a6fd697878e7e590895162..bb22dfec5d35e9841543fe479f23f1c2076bc706 100644 (file)
@@ -519,7 +519,7 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder)
     frame->is_sync_point = frame->is_sync_point || keyframe;
 
     if (hook->image)
-      g_free (hook->image);
+      g_slice_free (vpx_image_t, hook->image);
     hook->image = NULL;
 
     if (invisible) {
@@ -563,6 +563,42 @@ vpx_error_name (vpx_codec_err_t status)
   }
 }
 
+static vpx_image_t *
+gst_vp8_enc_buffer_to_image (GstVP8Enc * enc, GstBuffer * buffer)
+{
+  vpx_image_t *image = g_slice_new0 (vpx_image_t);
+  GstBaseVideoEncoder *encoder = (GstBaseVideoEncoder *) enc;
+  guint8 *data = GST_BUFFER_DATA (buffer);
+
+  image->fmt = IMG_FMT_I420;
+  image->bps = 12;
+  image->x_chroma_shift = image->y_chroma_shift = 1;
+  image->img_data = data;
+  image->w = image->d_w = encoder->state.width;
+  image->h = image->d_h = encoder->state.height;
+
+  image->stride[PLANE_Y] =
+      gst_video_format_get_row_stride (encoder->state.format, 0,
+      encoder->state.width);
+  image->stride[PLANE_U] =
+      gst_video_format_get_row_stride (encoder->state.format, 1,
+      encoder->state.width);
+  image->stride[PLANE_V] =
+      gst_video_format_get_row_stride (encoder->state.format, 2,
+      encoder->state.width);
+  image->planes[PLANE_Y] =
+      data + gst_video_format_get_component_offset (encoder->state.format, 0,
+      encoder->state.width, encoder->state.height);
+  image->planes[PLANE_U] =
+      data + gst_video_format_get_component_offset (encoder->state.format, 1,
+      encoder->state.width, encoder->state.height);
+  image->planes[PLANE_V] =
+      data + gst_video_format_get_component_offset (encoder->state.format, 2,
+      encoder->state.width, encoder->state.height);
+
+  return image;
+}
+
 static const int speed_table[] = {
   0,
   100000,
@@ -639,13 +675,9 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
     encoder->inited = TRUE;
   }
 
-  image = g_malloc0 (sizeof (vpx_image_t));
-  vpx_img_wrap (image, IMG_FMT_I420,
-      base_video_encoder->state.width,
-      base_video_encoder->state.height, 1,
-      GST_BUFFER_DATA (frame->sink_buffer));
+  image = gst_vp8_enc_buffer_to_image (encoder, frame->sink_buffer);
 
-  hook = g_new0 (GstVP8EncCoderHook, 1);
+  hook = g_slice_new0 (GstVP8EncCoderHook);
   hook->image = image;
   frame->coder_hook = hook;
 
@@ -682,7 +714,7 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
     memcpy (GST_BUFFER_DATA (buffer), pkt->data.frame.buf, pkt->data.frame.sz);
 
     if (hook->image)
-      g_free (hook->image);
+      g_slice_free (vpx_image_t, hook->image);
     hook->image = NULL;
 
     if (invisible) {
@@ -788,7 +820,7 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
 done:
   g_list_foreach (hook->invisible, (GFunc) gst_mini_object_unref, NULL);
   g_list_free (hook->invisible);
-  g_free (hook);
+  g_slice_free (GstVP8EncCoderHook, hook);
   frame->coder_hook = NULL;
 
   return ret;