diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2010-05-19 14:46:48 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2010-05-19 19:24:03 +0200 |
commit | 31d603b3c98c3ec27e5cc40584d8ba78fcbadecb (patch) | |
tree | 8a2fdb75ce95268c07f3eaf1f91abcdaf05e6643 /ext/vp8 | |
parent | 10a02618c208bfe587807e85dbaa21bd8ba6739e (diff) | |
download | gstreamer-plugins-bad-31d603b3c98c3ec27e5cc40584d8ba78fcbadecb.tar.gz |
vp8: Use correct strides and plane offsets for GStreamer
Diffstat (limited to 'ext/vp8')
-rw-r--r-- | ext/vp8/gstvp8dec.c | 76 | ||||
-rw-r--r-- | ext/vp8/gstvp8enc.c | 50 |
2 files changed, 95 insertions, 31 deletions
diff --git a/ext/vp8/gstvp8dec.c b/ext/vp8/gstvp8dec.c index 459640480..00eb7e20b 100644 --- a/ext/vp8/gstvp8dec.c +++ b/ext/vp8/gstvp8dec.c @@ -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); diff --git a/ext/vp8/gstvp8enc.c b/ext/vp8/gstvp8enc.c index 32310279a..bb22dfec5 100644 --- a/ext/vp8/gstvp8enc.c +++ b/ext/vp8/gstvp8enc.c @@ -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; |