mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
vp8: Use correct strides and plane offsets for GStreamer
This commit is contained in:
parent
10a02618c2
commit
31d603b3c9
2 changed files with 95 additions and 31 deletions
|
@ -263,6 +263,53 @@ gst_vp8_dec_send_tags (GstVP8Dec * dec)
|
||||||
GST_BASE_VIDEO_CODEC_SRC_PAD (dec), list);
|
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
|
static GstFlowReturn
|
||||||
gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame)
|
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);
|
img = vpx_codec_get_frame (&dec->decoder, &iter);
|
||||||
if (img) {
|
if (img) {
|
||||||
int i;
|
|
||||||
|
|
||||||
ret = gst_base_video_decoder_alloc_src_frame (decoder, frame);
|
ret = gst_base_video_decoder_alloc_src_frame (decoder, frame);
|
||||||
|
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK)
|
||||||
for (i = 0; i < decoder->state.height; i++) {
|
gst_vp8_dec_image_to_buffer (dec, img, frame->src_buffer);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_base_video_decoder_finish_frame (decoder, frame);
|
gst_base_video_decoder_finish_frame (decoder, frame);
|
||||||
|
|
||||||
do {
|
|
||||||
vpx_img_free (img);
|
vpx_img_free (img);
|
||||||
} while ((img = vpx_codec_get_frame (&dec->decoder, &iter)));
|
|
||||||
|
while ((img = vpx_codec_get_frame (&dec->decoder, &iter))) {
|
||||||
|
GST_WARNING_OBJECT (decoder, "Multiple decoded frames... dropping");
|
||||||
|
vpx_img_free (img);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Invisible frame */
|
/* Invisible frame */
|
||||||
gst_base_video_decoder_skip_frame (decoder, frame);
|
gst_base_video_decoder_skip_frame (decoder, frame);
|
||||||
|
|
|
@ -519,7 +519,7 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder)
|
||||||
frame->is_sync_point = frame->is_sync_point || keyframe;
|
frame->is_sync_point = frame->is_sync_point || keyframe;
|
||||||
|
|
||||||
if (hook->image)
|
if (hook->image)
|
||||||
g_free (hook->image);
|
g_slice_free (vpx_image_t, hook->image);
|
||||||
hook->image = NULL;
|
hook->image = NULL;
|
||||||
|
|
||||||
if (invisible) {
|
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[] = {
|
static const int speed_table[] = {
|
||||||
0,
|
0,
|
||||||
100000,
|
100000,
|
||||||
|
@ -639,13 +675,9 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
|
||||||
encoder->inited = TRUE;
|
encoder->inited = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
image = g_malloc0 (sizeof (vpx_image_t));
|
image = gst_vp8_enc_buffer_to_image (encoder, frame->sink_buffer);
|
||||||
vpx_img_wrap (image, IMG_FMT_I420,
|
|
||||||
base_video_encoder->state.width,
|
|
||||||
base_video_encoder->state.height, 1,
|
|
||||||
GST_BUFFER_DATA (frame->sink_buffer));
|
|
||||||
|
|
||||||
hook = g_new0 (GstVP8EncCoderHook, 1);
|
hook = g_slice_new0 (GstVP8EncCoderHook);
|
||||||
hook->image = image;
|
hook->image = image;
|
||||||
frame->coder_hook = hook;
|
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);
|
memcpy (GST_BUFFER_DATA (buffer), pkt->data.frame.buf, pkt->data.frame.sz);
|
||||||
|
|
||||||
if (hook->image)
|
if (hook->image)
|
||||||
g_free (hook->image);
|
g_slice_free (vpx_image_t, hook->image);
|
||||||
hook->image = NULL;
|
hook->image = NULL;
|
||||||
|
|
||||||
if (invisible) {
|
if (invisible) {
|
||||||
|
@ -788,7 +820,7 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
|
||||||
done:
|
done:
|
||||||
g_list_foreach (hook->invisible, (GFunc) gst_mini_object_unref, NULL);
|
g_list_foreach (hook->invisible, (GFunc) gst_mini_object_unref, NULL);
|
||||||
g_list_free (hook->invisible);
|
g_list_free (hook->invisible);
|
||||||
g_free (hook);
|
g_slice_free (GstVP8EncCoderHook, hook);
|
||||||
frame->coder_hook = NULL;
|
frame->coder_hook = NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue