diff options
author | Michael Smith <msmith@syncword.(none)> | 2009-04-27 21:30:04 -0700 |
---|---|---|
committer | Michael Smith <msmith@syncword.(none)> | 2009-05-10 18:08:13 -0700 |
commit | 62b571b93bef342597644011fe64d7370507f76b (patch) | |
tree | 95608fb10c6a9b2b6d67d23942407081952c5473 | |
parent | a91b7f0857ff4933eecd147f441cc097344d00e9 (diff) |
theoradec: handle 422 images (as YUY2).
-rw-r--r-- | ext/theora/theoradec.c | 84 |
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 { |