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)
{
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);
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) {
}
}
+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,
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;
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) {
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;