summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Smith <msmith@syncword.(none)>2009-04-27 21:30:04 -0700
committerMichael Smith <msmith@syncword.(none)>2009-05-10 18:08:13 -0700
commit62b571b93bef342597644011fe64d7370507f76b (patch)
tree95608fb10c6a9b2b6d67d23942407081952c5473
parenta91b7f0857ff4933eecd147f441cc097344d00e9 (diff)
theoradec: handle 422 images (as YUY2).
-rw-r--r--ext/theora/theoradec.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/ext/theora/theoradec.c b/ext/theora/theoradec.c
index 64b07fbd1..ac4136c1d 100644
--- a/ext/theora/theoradec.c
+++ b/ext/theora/theoradec.c
@@ -1115,6 +1115,88 @@ theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf)
return result;
}
+/* Allocate buffer and copy image data into YUY2 format */
+static GstFlowReturn
+theora_handle_422_image (GstTheoraDec * dec, yuv_buffer * yuv, GstBuffer ** out)
+{
+ gint width = dec->width;
+ gint height = dec->height;
+ gint out_size;
+ gint stride;
+ GstFlowReturn result;
+ int i, j;
+
+ stride = GST_ROUND_UP_2 (width) * 2;
+ out_size = stride * height;
+
+ /* now copy over the area contained in offset_x,offset_y,
+ * frame_width, frame_height */
+ result =
+ gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
+ out_size, GST_PAD_CAPS (dec->srcpad), out);
+ if (G_UNLIKELY (result != GST_FLOW_OK))
+ goto no_buffer;
+
+ /* The output pixels look like:
+ * YUYVYUYV....
+ *
+ * Do the interleaving... Note that this is kinda messed up if our width is
+ * odd. In that case, we can't represent it properly in YUY2, so we just
+ * pad out to even in that case (this is why we have GST_ROUND_UP_2() above).
+ */
+ {
+ guchar *src_y;
+ guchar *src_cb;
+ guchar *src_cr;
+ guchar *dest;
+ guchar *curdest;
+ guchar *src;
+
+ dest = GST_BUFFER_DATA (*out);
+
+ src_y = yuv->y + dec->offset_x + dec->offset_y * yuv->y_stride;
+ src_cb = yuv->u + dec->offset_x / 2 + dec->offset_y * yuv->uv_stride;
+ src_cr = yuv->v + dec->offset_x / 2 + dec->offset_y * yuv->uv_stride;
+
+ for (i = 0; i < height; i++) {
+ /* Y first */
+ curdest = dest;
+ src = src_y;
+ for (j = 0; j < width; j++) {
+ *curdest = *src++;
+ curdest += 2;
+ }
+ src_y += yuv->y_stride;
+
+ curdest = dest + 1;
+ src = src_cb;
+ for (j = 0; j < width; j++) {
+ *curdest = *src++;
+ curdest += 4;
+ }
+ src_cb += yuv->uv_stride;
+
+ curdest = dest + 3;
+ src = src_cr;
+ for (j = 0; j < width; j++) {
+ *curdest = *src++;
+ curdest += 4;
+ }
+ src_cr += yuv->uv_stride;
+
+ dest += stride;
+ }
+ }
+
+no_buffer:
+ {
+ GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
+ gst_flow_get_name (result));
+ return result;
+ }
+}
+
+/* Allocate buffer and copy image data into I420 format */
static GstFlowReturn
theora_handle_420_image (GstTheoraDec * dec, yuv_buffer * yuv, GstBuffer ** out)
{
@@ -1257,9 +1339,9 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
if (dec->info.pixelformat == OC_PF_420) {
result = theora_handle_420_image (dec, &yuv, &out);
-#if 0
} else if (dec->info.pixelformat == OC_PF_422) {
result = theora_handle_422_image (dec, &yuv, &out);
+#if 0
} else if (dec->info.pixelformat == OC_PF_444) {
result = theora_handle_444_image (dec, &yuv, &out);
} else {