vp9: Add support for YV12, Y42B and Y444 color formats

The encoder does not work with Y42B and Y444 yet it seems.
This commit is contained in:
Sebastian Dröge 2013-06-22 10:57:41 +02:00
parent 9788976fd4
commit 9b7a6a3f90
2 changed files with 74 additions and 13 deletions

View file

@ -123,7 +123,7 @@ static GstStaticPadTemplate gst_vp9_dec_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444 }"))
);
#define parent_class gst_vp9_dec_parent_class
@ -397,7 +397,6 @@ open_codec (GstVP9Dec * dec, GstVideoCodecFrame * frame)
vpx_codec_stream_info_t stream_info;
vpx_codec_caps_t caps;
vpx_codec_dec_cfg_t cfg;
GstVideoCodecState *state = dec->input_state;
vpx_codec_err_t status;
GstMapInfo minfo;
@ -431,13 +430,6 @@ open_codec (GstVP9Dec * dec, GstVideoCodecFrame * frame)
stream_info.w = dec->input_state->info.width;
stream_info.h = dec->input_state->info.height;
g_assert (dec->output_state == NULL);
dec->output_state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec),
GST_VIDEO_FORMAT_I420, stream_info.w, stream_info.h, state);
gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec));
gst_vp9_dec_send_tags (dec);
cfg.w = stream_info.w;
cfg.h = stream_info.h;
cfg.threads = dec->threads;
@ -531,6 +523,50 @@ gst_vp9_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
img = vpx_codec_get_frame (&dec->decoder, &iter);
if (img) {
GstVideoFormat fmt;
switch (img->fmt) {
case VPX_IMG_FMT_I420:
fmt = GST_VIDEO_FORMAT_I420;
break;
case VPX_IMG_FMT_YV12:
fmt = GST_VIDEO_FORMAT_YV12;
break;
case VPX_IMG_FMT_I422:
fmt = GST_VIDEO_FORMAT_Y42B;
break;
case VPX_IMG_FMT_I444:
fmt = GST_VIDEO_FORMAT_Y444;
break;
default:
vpx_img_free (img);
GST_ELEMENT_ERROR (decoder, LIBRARY, ENCODE,
("Failed to decode frame"), ("Unsupported color format %d",
img->fmt));
return GST_FLOW_ERROR;
break;
}
/* FIXME: Width/height in the img is wrong */
if (!dec->output_state || dec->output_state->info.finfo->format != fmt /*||
dec->output_state->info.width != img->w ||
dec->output_state->info.height != img->h */ ) {
gboolean send_tags = !dec->output_state;
if (dec->output_state)
gst_video_codec_state_unref (dec->output_state);
/* FIXME: The width/height in the img is wrong */
dec->output_state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec),
fmt, dec->input_state->info.width, dec->input_state->info.height,
dec->input_state);
gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec));
if (send_tags)
gst_vp9_dec_send_tags (dec);
}
if (deadline < 0) {
GST_LOG_OBJECT (dec, "Skipping late frame (%f s past deadline)",
(double) -deadline / GST_SECOND);

View file

@ -353,11 +353,13 @@ static gboolean gst_vp9_enc_sink_event (GstVideoEncoder *
static gboolean gst_vp9_enc_propose_allocation (GstVideoEncoder * encoder,
GstQuery * query);
/* FIXME: Y42B and Y444 do not work yet it seems */
static GstStaticPadTemplate gst_vp9_enc_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
/*GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444 }")) */
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12 }"))
);
static GstStaticPadTemplate gst_vp9_enc_src_template =
@ -1675,9 +1677,32 @@ gst_vp9_enc_set_format (GstVideoEncoder * video_encoder,
image = &encoder->image;
memset (image, 0, sizeof (*image));
image->fmt = VPX_IMG_FMT_I420;
image->bps = 12;
image->x_chroma_shift = image->y_chroma_shift = 1;
switch (encoder->input_state->info.finfo->format) {
case GST_VIDEO_FORMAT_I420:
image->fmt = VPX_IMG_FMT_I420;
image->bps = 12;
image->x_chroma_shift = image->y_chroma_shift = 1;
break;
case GST_VIDEO_FORMAT_YV12:
image->fmt = VPX_IMG_FMT_YV12;
image->bps = 12;
image->x_chroma_shift = image->y_chroma_shift = 1;
break;
case GST_VIDEO_FORMAT_Y42B:
image->fmt = VPX_IMG_FMT_I422;
image->bps = 16;
image->x_chroma_shift = 1;
image->y_chroma_shift = 0;
break;
case GST_VIDEO_FORMAT_Y444:
image->fmt = VPX_IMG_FMT_I444;
image->bps = 24;
image->x_chroma_shift = image->y_chroma_shift = 0;
break;
default:
g_assert_not_reached ();
break;
}
image->w = image->d_w = GST_VIDEO_INFO_WIDTH (info);
image->h = image->d_h = GST_VIDEO_INFO_HEIGHT (info);