vp9: Add support for YV12, Y42B and Y444 color formats
authorSebastian Dröge <slomo@circular-chaos.org>
Sat, 22 Jun 2013 08:57:41 +0000 (10:57 +0200)
committerSebastian Dröge <slomo@circular-chaos.org>
Sat, 22 Jun 2013 08:57:41 +0000 (10:57 +0200)
The encoder does not work with Y42B and Y444 yet it seems.

ext/vpx/gstvp9dec.c
ext/vpx/gstvp9enc.c

index 9f5fc06..208796a 100644 (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);
index 29beed5..ea276f9 100644 (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);