gstvp9dec.c 6.84 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/* VP9
 * Copyright (C) 2006 David Schleef <ds@schleef.org>
 * Copyright (C) 2008,2009,2010 Entropy Wave Inc
 * Copyright (C) 2010-2013 Sebastian Dröge <slomo@circular-chaos.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */
/**
 * SECTION:element-vp9dec
 * @see_also: vp9enc, matroskademux
 *
 * This element decodes VP9 streams into raw video.
 * <ulink url="http://www.webmproject.org">VP9</ulink> is a royalty-free
 * video codec maintained by <ulink url="http://www.google.com/">Google
 * </ulink>. It's the successor of On2 VP3, which was the base of the
 * Theora video codec.
 *
 * <refsect2>
 * <title>Example pipeline</title>
 * |[
35
 * gst-launch-1.0 -v filesrc location=videotestsrc.webm ! matroskademux ! vp9dec ! videoconvert ! videoscale ! autovideosink
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
 * ]| This example pipeline will decode a WebM stream and decodes the VP9 video.
 * </refsect2>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_VP9_DECODER

#include <string.h>

#include "gstvp8utils.h"
#include "gstvp9dec.h"

#include <gst/video/gstvideometa.h>
#include <gst/video/gstvideopool.h>

GST_DEBUG_CATEGORY_STATIC (gst_vp9dec_debug);
#define GST_CAT_DEFAULT gst_vp9dec_debug

57
#define VP9_DECODER_VIDEO_TAG "VP9 video"
58

59 60 61 62 63 64
static void gst_vp9_dec_set_stream_info (GstVPXDec * dec,
    vpx_codec_stream_info_t * stream_info);
static gboolean gst_vp9_dec_get_valid_format (GstVPXDec * dec,
    vpx_image_t * img, GstVideoFormat * fmt);
static void gst_vp9_dec_handle_resolution_change (GstVPXDec * dec,
    vpx_image_t * img, GstVideoFormat fmt);
65 66 67 68 69 70 71 72 73 74 75 76

static GstStaticPadTemplate gst_vp9_dec_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-vp9")
    );

static GstStaticPadTemplate gst_vp9_dec_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
77
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444 }"))
78 79 80
    );

#define parent_class gst_vp9_dec_parent_class
81
G_DEFINE_TYPE (GstVP9Dec, gst_vp9_dec, GST_TYPE_VPX_DEC);
82 83 84 85 86

static void
gst_vp9_dec_class_init (GstVP9DecClass * klass)
{
  GstElementClass *element_class;
87
  GstVPXDecClass *vpx_class;
88 89

  element_class = GST_ELEMENT_CLASS (klass);
90
  vpx_class = GST_VPX_DEC_CLASS (klass);
91

92 93 94 95
  gst_element_class_add_static_pad_template (element_class,
      &gst_vp9_dec_src_template);
  gst_element_class_add_static_pad_template (element_class,
      &gst_vp9_dec_sink_template);
96 97 98 99 100 101 102

  gst_element_class_set_static_metadata (element_class,
      "On2 VP9 Decoder",
      "Codec/Decoder/Video",
      "Decode VP9 video streams", "David Schleef <ds@entropywave.com>, "
      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");

103 104 105 106 107 108 109
  vpx_class->video_codec_tag = VP9_DECODER_VIDEO_TAG;
  vpx_class->codec_algo = &vpx_codec_vp9_dx_algo;
  vpx_class->set_stream_info = GST_DEBUG_FUNCPTR (gst_vp9_dec_set_stream_info);
  vpx_class->get_frame_format =
      GST_DEBUG_FUNCPTR (gst_vp9_dec_get_valid_format);
  vpx_class->handle_resolution_change =
      GST_DEBUG_FUNCPTR (gst_vp9_dec_handle_resolution_change);
110 111 112 113 114 115 116 117 118 119 120

  GST_DEBUG_CATEGORY_INIT (gst_vp9dec_debug, "vp9dec", 0, "VP9 Decoder");
}

static void
gst_vp9_dec_init (GstVP9Dec * gst_vp9_dec)
{
  GST_DEBUG_OBJECT (gst_vp9_dec, "gst_vp9_dec_init");
}

static void
121 122
gst_vp9_dec_set_stream_info (GstVPXDec * dec,
    vpx_codec_stream_info_t * stream_info)
123
{
124 125 126 127
  /* FIXME: peek_stream_info() does not return valid values, take input caps */
  stream_info->w = dec->input_state->info.width;
  stream_info->h = dec->input_state->info.height;
  return;
128 129 130
}

static gboolean
131 132
gst_vp9_dec_get_valid_format (GstVPXDec * dec, vpx_image_t * img,
    GstVideoFormat * fmt)
133
{
134 135 136 137
  switch (img->fmt) {
    case VPX_IMG_FMT_I420:
      *fmt = GST_VIDEO_FORMAT_I420;
      return TRUE;
138

139 140 141
    case VPX_IMG_FMT_YV12:
      *fmt = GST_VIDEO_FORMAT_YV12;
      return TRUE;
142

143 144 145
    case VPX_IMG_FMT_I422:
      *fmt = GST_VIDEO_FORMAT_Y42B;
      return TRUE;
146

147 148 149
    case VPX_IMG_FMT_I444:
      *fmt = GST_VIDEO_FORMAT_Y444;
      return TRUE;
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    case VPX_IMG_FMT_I440:
      /* Planar, half height, full width U/V */
      GST_FIXME_OBJECT (dec, "Please add a 4:4:0 planar frame format");
      GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED,
          (NULL), ("Unsupported frame format - 4:4:0 planar"));
      return FALSE;
    case VPX_IMG_FMT_I42016:
      /* VPX_IMG_FMT_I420 | VPX_IMG_FMT_HIGHBITDEPTH */
      GST_FIXME_OBJECT (dec, "Please add 16-bit I420 format");
      GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED,
          (NULL), ("Unsupported frame format - 16-bit 4:2:0 planar"));
      return FALSE;
    case VPX_IMG_FMT_I42216:
      /* VPX_IMG_FMT_I422 | VPX_IMG_FMT_HIGHBITDEPTH */
      GST_FIXME_OBJECT (dec, "Please add 16-bit Y42B format");
      GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED,
          (NULL), ("Unsupported frame format - 16-bit 4:2:2 planar"));
      return FALSE;
    case VPX_IMG_FMT_I44416:
      /* VPX_IMG_FMT_I444 | VPX_IMG_FMT_HIGHBITDEPTH */
      GST_FIXME_OBJECT (dec, "Please add 16-bit Y444 format");
      GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED,
          (NULL), ("Unsupported frame format - 16-bit 4:4:4 planar"));
      return FALSE;
    case VPX_IMG_FMT_I44016:
      /* VPX_IMG_FMT_I440 | VPX_IMG_FMT_HIGHBITDEPTH */
      GST_FIXME_OBJECT (dec, "Please add 16-bit 4:4:0 planar frame format");
      GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED,
          (NULL), ("Unsupported frame format - 16-bit 4:4:0 planar"));
      return FALSE;

182 183
    default:
      return FALSE;
184 185 186 187
  }
}

static void
188 189
gst_vp9_dec_handle_resolution_change (GstVPXDec * dec, vpx_image_t * img,
    GstVideoFormat fmt)
190
{
191
  GstVPXDecClass *vpxclass = GST_VPX_DEC_GET_CLASS (dec);
192

193 194 195 196
  if (!dec->output_state || dec->output_state->info.finfo->format != fmt ||
      dec->output_state->info.width != img->d_w ||
      dec->output_state->info.height != img->d_h) {
    gboolean send_tags = !dec->output_state;
197

198 199
    if (dec->output_state)
      gst_video_codec_state_unref (dec->output_state);
200

201 202 203 204
    dec->output_state =
        gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec),
        fmt, img->d_w, img->d_h, dec->input_state);
    gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec));
205

206 207
    if (send_tags)
      vpxclass->send_tags (dec);
208 209 210
  }
}

211
#endif /* HAVE_VP9_DECODER */