From 9b7a6a3f907bd923dfa540bc979d0ae033e77b1d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 22 Jun 2013 10:57:41 +0200 Subject: [PATCH] vp9: Add support for YV12, Y42B and Y444 color formats The encoder does not work with Y42B and Y444 yet it seems. --- ext/vpx/gstvp9dec.c | 54 ++++++++++++++++++++++++++++++++++++++++++++--------- ext/vpx/gstvp9enc.c | 33 ++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/ext/vpx/gstvp9dec.c b/ext/vpx/gstvp9dec.c index 9f5fc06..208796a 100644 --- a/ext/vpx/gstvp9dec.c +++ b/ext/vpx/gstvp9dec.c @@ -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); diff --git a/ext/vpx/gstvp9enc.c b/ext/vpx/gstvp9enc.c index 29beed5..ea276f9 100644 --- a/ext/vpx/gstvp9enc.c +++ b/ext/vpx/gstvp9enc.c @@ -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); -- 2.7.4