vdpau: implement GstVdpauVideoBuffer -> I420 conversion
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
Mon, 13 Apr 2009 17:36:53 +0000 (19:36 +0200)
committerJan Schmidt <thaytan@noraisin.net>
Sat, 20 Jun 2009 14:21:26 +0000 (15:21 +0100)
sys/vdpau/gstvdpauvideoyuv.c
sys/vdpau/gstvdpauyuvvideo.c

index 6855ba8..f7ebe8a 100644 (file)
@@ -101,10 +101,10 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer)
       data[0] = GST_BUFFER_DATA (outbuf) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           0, video_yuv->width, video_yuv->height);
-      data[1] = data[0] +
+      data[1] = GST_BUFFER_DATA (outbuf) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           2, video_yuv->width, video_yuv->height);
-      data[2] = data[0] +
+      data[2] = GST_BUFFER_DATA (outbuf) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           1, video_yuv->width, video_yuv->height);
 
@@ -123,7 +123,53 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer)
             ("Couldn't get data from vdpau"),
             ("Error returned from vdpau was: %s",
                 device->vdp_get_error_string (status)));
-        break;
+        goto error;
+      }
+      break;
+    }
+    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+    {
+      gint size;
+      GstFlowReturn result;
+      VdpStatus status;
+      guint8 *data[3];
+      guint32 stride[3];
+
+      size =
+          gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width,
+          video_yuv->height);
+      result =
+          gst_pad_alloc_buffer_and_set_caps (video_yuv->src,
+          GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf);
+      if (G_UNLIKELY (result != GST_FLOW_OK))
+        return result;
+
+      data[0] = GST_BUFFER_DATA (outbuf) +
+          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+          0, video_yuv->width, video_yuv->height);
+      data[1] = GST_BUFFER_DATA (outbuf) +
+          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+          2, video_yuv->width, video_yuv->height);
+      data[2] = GST_BUFFER_DATA (outbuf) +
+          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
+          1, video_yuv->width, video_yuv->height);
+
+      stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
+          0, video_yuv->width);
+      stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
+          2, video_yuv->width);
+      stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
+          1, video_yuv->width);
+
+      status =
+          device->vdp_video_surface_get_bits_ycbcr (surface,
+          VDP_YCBCR_FORMAT_YV12, (void *) data, stride);
+      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
+        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
+            ("Couldn't get data from vdpau"),
+            ("Error returned from vdpau was: %s",
+                device->vdp_get_error_string (status)));
+        goto error;
       }
       break;
     }
@@ -159,7 +205,7 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer)
             ("Couldn't get data from vdpau"),
             ("Error returned from vdpau was: %s",
                 device->vdp_get_error_string (status)));
-        break;
+        goto error;
       }
       break;
     }
@@ -169,12 +215,11 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer)
 
   gst_buffer_unref (buffer);
 
-  if (outbuf) {
-    gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
-
-    return gst_pad_push (video_yuv->src, outbuf);
-  }
+  gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
+  return gst_pad_push (video_yuv->src, outbuf);
 
+error:
+  gst_buffer_unref (outbuf);
   return GST_FLOW_ERROR;
 }
 
index d5935a8..51500c5 100644 (file)
@@ -95,10 +95,10 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer)
       data[0] = GST_BUFFER_DATA (buffer) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           0, yuv_video->width, yuv_video->height);
-      data[1] = data[0] +
+      data[1] = GST_BUFFER_DATA (buffer) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           2, yuv_video->width, yuv_video->height);
-      data[2] = data[0] +
+      data[2] = GST_BUFFER_DATA (buffer) +
           gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
           1, yuv_video->width, yuv_video->height);
 
@@ -117,7 +117,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer)
             ("Couldn't push YV12 data to VDPAU"),
             ("Error returned from vdpau was: %s",
                 device->vdp_get_error_string (status)));
-        break;
+        goto error;
       }
       break;
     }
@@ -152,7 +152,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer)
             ("Couldn't push YV12 data to VDPAU"),
             ("Error returned from vdpau was: %s",
                 device->vdp_get_error_string (status)));
-        break;
+        goto error;
       }
       break;
     }
@@ -176,7 +176,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer)
             ("Couldn't get data from vdpau"),
             ("Error returned from vdpau was: %s",
                 device->vdp_get_error_string (status)));
-        break;
+        goto error;
       }
       break;
     }
@@ -186,13 +186,13 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer)
 
   gst_buffer_unref (buffer);
 
-  if (outbuf) {
-    gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
-    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src));
+  gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
+  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src));
 
-    return gst_pad_push (yuv_video->src, outbuf);
-  }
+  return gst_pad_push (yuv_video->src, outbuf);
 
+error:
+  gst_buffer_unref (outbuf);
   return GST_FLOW_ERROR;
 }