• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* VP9
2  * Copyright (C) 2006 David Schleef <ds@schleef.org>
3  * Copyright (C) 2010 Entropy Wave Inc
4  * Copyright (C) 2010-2013 Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 /**
23  * SECTION:element-vp9enc
24  * @title: vp9enc
25  * @see_also: vp9dec, webmmux, oggmux
26  *
27  * This element encodes raw video into a VP9 stream.
28  * [VP9](http://www.webmproject.org) is a royalty-free video codec maintained by
29  * [Google](http://www.google.com/). It's the successor of On2 VP3, which was
30  * the base of the Theora video codec.
31  *
32  * To control the quality of the encoding, the #GstVPXEnc:target-bitrate,
33  * #GstVPXEnc:min-quantizer, #GstVPXEnc:max-quantizer or #GstVPXEnc:cq-level
34  * properties can be used. Which one is used depends on the mode selected by
35  * the #GstVPXEnc:end-usage property.
36  * See [Encoder Parameters](http://www.webmproject.org/docs/encoder-parameters/)
37  * for explanation, examples for useful encoding parameters and more details
38  * on the encoding parameters.
39  *
40  * ## Example pipeline
41  * |[
42  * gst-launch-1.0 -v videotestsrc num-buffers=1000 ! vp9enc ! webmmux ! filesink location=videotestsrc.webm
43  * ]| This example pipeline will encode a test video source to VP9 muxed in an
44  * WebM container.
45  *
46  */
47 
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51 
52 #ifdef HAVE_VP9_ENCODER
53 
54 /* glib decided in 2.32 it would be a great idea to deprecated GValueArray without
55  * providing an alternative
56  *
57  * See https://bugzilla.gnome.org/show_bug.cgi?id=667228
58  * */
59 #define GLIB_DISABLE_DEPRECATION_WARNINGS
60 
61 #include <gst/tag/tag.h>
62 #include <gst/video/video.h>
63 #include <string.h>
64 
65 #include "gstvpxelements.h"
66 #include "gstvpxenums.h"
67 #include "gstvpx-enumtypes.h"
68 #include "gstvp8utils.h"
69 #include "gstvp9enc.h"
70 
71 GST_DEBUG_CATEGORY_STATIC (gst_vp9enc_debug);
72 #define GST_CAT_DEFAULT gst_vp9enc_debug
73 
74 #define DEFAULT_TILE_COLUMNS 6
75 #define DEFAULT_TILE_ROWS 0
76 #define DEFAULT_ROW_MT 0
77 #define DEFAULT_AQ_MODE GST_VPX_AQ_OFF
78 #define DEFAULT_FRAME_PARALLEL_DECODING TRUE
79 
80 enum
81 {
82   PROP_0,
83   PROP_TILE_COLUMNS,
84   PROP_TILE_ROWS,
85   PROP_ROW_MT,
86   PROP_AQ_MODE,
87   PROP_FRAME_PARALLEL_DECODING,
88 };
89 
90 /* FIXME: Y42B do not work yet it seems */
91 static GstStaticPadTemplate gst_vp9_enc_sink_template =
92 GST_STATIC_PAD_TEMPLATE ("sink",
93     GST_PAD_SINK,
94     GST_PAD_ALWAYS,
95     /*GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444 }")) */
96     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
97         ("{ I420, YV12, Y444, I420_10LE, I422_10LE }"))
98     );
99 
100 static GstStaticPadTemplate gst_vp9_enc_src_template =
101 GST_STATIC_PAD_TEMPLATE ("src",
102     GST_PAD_SRC,
103     GST_PAD_ALWAYS,
104     GST_STATIC_CAPS ("video/x-vp9, " "profile = (string) {0, 1, 2, 3}")
105     );
106 
107 #define parent_class gst_vp9_enc_parent_class
108 G_DEFINE_TYPE (GstVP9Enc, gst_vp9_enc, GST_TYPE_VPX_ENC);
109 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (vp9enc, "vp9enc", GST_RANK_PRIMARY,
110     gst_vp9_enc_get_type (), vpx_element_init (plugin));
111 
112 static vpx_codec_iface_t *gst_vp9_enc_get_algo (GstVPXEnc * enc);
113 static gboolean gst_vp9_enc_enable_scaling (GstVPXEnc * enc);
114 static void gst_vp9_enc_set_image_format (GstVPXEnc * enc, vpx_image_t * image);
115 static GstCaps *gst_vp9_enc_get_new_simple_caps (GstVPXEnc * enc);
116 static void gst_vp9_enc_set_stream_info (GstVPXEnc * enc, GstCaps * caps,
117     GstVideoInfo * info);
118 static void *gst_vp9_enc_process_frame_user_data (GstVPXEnc * enc,
119     GstVideoCodecFrame * frame);
120 static GstFlowReturn gst_vp9_enc_handle_invisible_frame_buffer (GstVPXEnc * enc,
121     void *user_data, GstBuffer * buffer);
122 static void gst_vp9_enc_set_frame_user_data (GstVPXEnc * enc,
123     GstVideoCodecFrame * frame, vpx_image_t * image);
124 static void gst_vp9_enc_set_property (GObject * object, guint prop_id,
125     const GValue * value, GParamSpec * pspec);
126 static void gst_vp9_enc_get_property (GObject * object, guint prop_id,
127     GValue * value, GParamSpec * pspec);
128 static gboolean gst_vp9_enc_configure_encoder (GstVPXEnc * encoder,
129     GstVideoCodecState * state);
130 
131 #define DEFAULT_BITS_PER_PIXEL 0.0289
132 
133 static void
gst_vp9_enc_class_init(GstVP9EncClass * klass)134 gst_vp9_enc_class_init (GstVP9EncClass * klass)
135 {
136   GObjectClass *gobject_class;
137   GstElementClass *element_class;
138   GstVPXEncClass *vpx_encoder_class;
139 
140   gobject_class = G_OBJECT_CLASS (klass);
141   element_class = GST_ELEMENT_CLASS (klass);
142   vpx_encoder_class = GST_VPX_ENC_CLASS (klass);
143 
144   gobject_class->set_property = gst_vp9_enc_set_property;
145   gobject_class->get_property = gst_vp9_enc_get_property;
146 
147   /**
148    * GstVP9Enc:tile-columns:
149    *
150    * Number of tile columns, log2
151    *
152    * Since: 1.20
153    */
154   g_object_class_install_property (gobject_class, PROP_TILE_COLUMNS,
155       g_param_spec_int ("tile-columns", "Tile Columns",
156           "Number of tile columns, log2",
157           0, 6, DEFAULT_TILE_COLUMNS,
158           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
159 
160   /**
161    * GstVP9Enc:tile-rows:
162    *
163    * Number of tile rows, log2
164    *
165    * Since: 1.20
166    */
167   g_object_class_install_property (gobject_class, PROP_TILE_ROWS,
168       g_param_spec_int ("tile-rows", "Tile Rows",
169           "Number of tile rows, log2",
170           0, 2, DEFAULT_TILE_ROWS,
171           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
172 
173   /**
174    * GstVP9Enc:row-mt:
175    *
176    * Whether each row should be encoded using multiple threads
177    *
178    * Since: 1.20
179    */
180   g_object_class_install_property (gobject_class, PROP_ROW_MT,
181       g_param_spec_boolean ("row-mt", "Row Multithreading",
182           "Whether each row should be encoded using multiple threads",
183           DEFAULT_ROW_MT,
184           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
185 
186   /**
187    * GstVP9Enc:aq-mode:
188    *
189    * Adaptive Quantization Mode
190    *
191    * Since: 1.20
192    */
193   g_object_class_install_property (gobject_class, PROP_AQ_MODE,
194       g_param_spec_enum ("aq-mode", "Adaptive Quantization Mode",
195           "Which adaptive quantization mode should be used",
196           GST_TYPE_VPXAQ, DEFAULT_AQ_MODE,
197           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
198   gst_type_mark_as_plugin_api (GST_TYPE_VPXAQ, 0);
199 
200   /**
201    * GstVP9Enc:frame-parallel-decoding:
202    *
203    * Whether encoded bitstream should allow parallel processing of video frames in the decoder
204    *
205    * Since: 1.20
206    */
207   g_object_class_install_property (gobject_class, PROP_FRAME_PARALLEL_DECODING,
208       g_param_spec_boolean ("frame-parallel-decoding",
209           "Frame Parallel Decoding",
210           "Whether encoded bitstream should allow parallel processing of video frames in the decoder "
211           "(default is on)", DEFAULT_FRAME_PARALLEL_DECODING,
212           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
213 
214   gst_element_class_add_static_pad_template (element_class,
215       &gst_vp9_enc_src_template);
216   gst_element_class_add_static_pad_template (element_class,
217       &gst_vp9_enc_sink_template);
218 
219   gst_element_class_set_static_metadata (element_class,
220       "On2 VP9 Encoder",
221       "Codec/Encoder/Video",
222       "Encode VP9 video streams", "David Schleef <ds@entropywave.com>, "
223       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
224 
225   vpx_encoder_class->get_algo = gst_vp9_enc_get_algo;
226   vpx_encoder_class->enable_scaling = gst_vp9_enc_enable_scaling;
227   vpx_encoder_class->set_image_format = gst_vp9_enc_set_image_format;
228   vpx_encoder_class->get_new_vpx_caps = gst_vp9_enc_get_new_simple_caps;
229   vpx_encoder_class->set_stream_info = gst_vp9_enc_set_stream_info;
230   vpx_encoder_class->process_frame_user_data =
231       gst_vp9_enc_process_frame_user_data;
232   vpx_encoder_class->handle_invisible_frame_buffer =
233       gst_vp9_enc_handle_invisible_frame_buffer;
234   vpx_encoder_class->set_frame_user_data = gst_vp9_enc_set_frame_user_data;
235   vpx_encoder_class->configure_encoder = gst_vp9_enc_configure_encoder;
236 
237   GST_DEBUG_CATEGORY_INIT (gst_vp9enc_debug, "vp9enc", 0, "VP9 Encoder");
238 }
239 
240 static void
gst_vp9_enc_init(GstVP9Enc * gst_vp9_enc)241 gst_vp9_enc_init (GstVP9Enc * gst_vp9_enc)
242 {
243   vpx_codec_err_t status;
244   GstVPXEnc *gst_vpx_enc = GST_VPX_ENC (gst_vp9_enc);
245   GST_DEBUG_OBJECT (gst_vp9_enc, "gst_vp9_enc_init");
246   status =
247       vpx_codec_enc_config_default (gst_vp9_enc_get_algo (gst_vpx_enc),
248       &gst_vpx_enc->cfg, 0);
249   if (status != VPX_CODEC_OK) {
250     GST_ERROR_OBJECT (gst_vpx_enc,
251         "Failed to get default encoder configuration: %s",
252         gst_vpx_error_name (status));
253     gst_vpx_enc->have_default_config = FALSE;
254   } else {
255     gst_vpx_enc->have_default_config = TRUE;
256   }
257   gst_vpx_enc->bits_per_pixel = DEFAULT_BITS_PER_PIXEL;
258 
259   gst_vp9_enc->tile_columns = DEFAULT_TILE_COLUMNS;
260   gst_vp9_enc->tile_rows = DEFAULT_TILE_ROWS;
261   gst_vp9_enc->row_mt = DEFAULT_ROW_MT;
262   gst_vp9_enc->aq_mode = DEFAULT_AQ_MODE;
263   gst_vp9_enc->frame_parallel_decoding = DEFAULT_FRAME_PARALLEL_DECODING;
264 }
265 
266 static void
gst_vp9_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)267 gst_vp9_enc_set_property (GObject * object, guint prop_id,
268     const GValue * value, GParamSpec * pspec)
269 {
270   GstVPXEnc *gst_vpx_enc = GST_VPX_ENC (object);
271   GstVP9Enc *gst_vp9_enc = GST_VP9_ENC (object);
272   vpx_codec_err_t status;
273 
274   g_mutex_lock (&gst_vpx_enc->encoder_lock);
275 
276   switch (prop_id) {
277     case PROP_TILE_COLUMNS:
278       gst_vp9_enc->tile_columns = g_value_get_int (value);
279       if (gst_vpx_enc->inited) {
280         status =
281             vpx_codec_control (&gst_vpx_enc->encoder, VP9E_SET_TILE_COLUMNS,
282             gst_vp9_enc->tile_columns);
283         if (status != VPX_CODEC_OK) {
284           GST_WARNING_OBJECT (gst_vpx_enc,
285               "Failed to set VP9E_SET_TILE_COLUMNS: %s",
286               gst_vpx_error_name (status));
287         }
288       }
289       break;
290     case PROP_TILE_ROWS:
291       gst_vp9_enc->tile_rows = g_value_get_int (value);
292       if (gst_vpx_enc->inited) {
293         status =
294             vpx_codec_control (&gst_vpx_enc->encoder, VP9E_SET_TILE_ROWS,
295             gst_vp9_enc->tile_rows);
296         if (status != VPX_CODEC_OK) {
297           GST_WARNING_OBJECT (gst_vpx_enc,
298               "Failed to set VP9E_SET_TILE_ROWS: %s",
299               gst_vpx_error_name (status));
300         }
301       }
302       break;
303     case PROP_ROW_MT:
304       gst_vp9_enc->row_mt = g_value_get_boolean (value);
305       if (gst_vpx_enc->inited) {
306         status =
307             vpx_codec_control (&gst_vpx_enc->encoder, VP9E_SET_ROW_MT,
308             gst_vp9_enc->row_mt ? 1 : 0);
309         if (status != VPX_CODEC_OK) {
310           GST_WARNING_OBJECT (gst_vpx_enc,
311               "Failed to set VP9E_SET_ROW_MT: %s", gst_vpx_error_name (status));
312         }
313       }
314       break;
315     case PROP_AQ_MODE:
316       gst_vp9_enc->aq_mode = g_value_get_enum (value);
317       if (gst_vpx_enc->inited) {
318         status = vpx_codec_control (&gst_vpx_enc->encoder, VP9E_SET_AQ_MODE,
319             gst_vp9_enc->aq_mode);
320         if (status != VPX_CODEC_OK) {
321           GST_WARNING_OBJECT (gst_vpx_enc,
322               "Failed to set VP9E_SET_AQ_MODE: %s",
323               gst_vpx_error_name (status));
324         }
325       }
326       break;
327     case PROP_FRAME_PARALLEL_DECODING:
328       gst_vp9_enc->frame_parallel_decoding = g_value_get_boolean (value);
329       if (gst_vpx_enc->inited) {
330         status = vpx_codec_control (&gst_vpx_enc->encoder,
331             VP9E_SET_FRAME_PARALLEL_DECODING,
332             gst_vp9_enc->frame_parallel_decoding ? 1 : 0);
333         if (status != VPX_CODEC_OK) {
334           GST_WARNING_OBJECT (gst_vpx_enc,
335               "Failed to set VP9E_SET_FRAME_PARALLEL_DECODING: %s",
336               gst_vpx_error_name (status));
337         }
338       }
339       break;
340     default:
341       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
342       break;
343   }
344 
345   g_mutex_unlock (&gst_vpx_enc->encoder_lock);
346 }
347 
348 static void
gst_vp9_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)349 gst_vp9_enc_get_property (GObject * object, guint prop_id, GValue * value,
350     GParamSpec * pspec)
351 {
352   GstVPXEnc *gst_vpx_enc = GST_VPX_ENC (object);
353   GstVP9Enc *gst_vp9_enc = GST_VP9_ENC (object);
354 
355   g_mutex_lock (&gst_vpx_enc->encoder_lock);
356 
357   switch (prop_id) {
358     case PROP_TILE_COLUMNS:
359       g_value_set_int (value, gst_vp9_enc->tile_columns);
360       break;
361     case PROP_TILE_ROWS:
362       g_value_set_int (value, gst_vp9_enc->tile_rows);
363       break;
364     case PROP_ROW_MT:
365       g_value_set_boolean (value, gst_vp9_enc->row_mt);
366       break;
367     case PROP_AQ_MODE:
368       g_value_set_enum (value, gst_vp9_enc->aq_mode);
369       break;
370     case PROP_FRAME_PARALLEL_DECODING:
371       g_value_set_boolean (value, gst_vp9_enc->frame_parallel_decoding);
372       break;
373     default:
374       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
375       break;
376   }
377 
378   g_mutex_unlock (&gst_vpx_enc->encoder_lock);
379 }
380 
381 static vpx_color_space_t
gst_vp9_get_vpx_colorspace(GstVPXEnc * encoder,GstVideoColorimetry * in_cinfo,GstVideoFormat format)382 gst_vp9_get_vpx_colorspace (GstVPXEnc * encoder, GstVideoColorimetry * in_cinfo,
383     GstVideoFormat format)
384 {
385   vpx_color_space_t colorspace = VPX_CS_UNKNOWN;
386   GstVideoColorimetry cinfo = *in_cinfo;
387   gchar *colorimetry_str;
388   guint i;
389 
390   static const struct
391   {
392     const gchar *str;
393     vpx_color_space_t vpx_color_space;
394   } colorimetry_map[] = {
395     {
396     GST_VIDEO_COLORIMETRY_BT601, VPX_CS_BT_601}, {
397     GST_VIDEO_COLORIMETRY_BT709, VPX_CS_BT_709}, {
398     GST_VIDEO_COLORIMETRY_SMPTE240M, VPX_CS_SMPTE_240}, {
399     GST_VIDEO_COLORIMETRY_BT2020, VPX_CS_BT_2020}
400   };
401 
402   /* We support any range, all mapped CSC are by default reduced range. */
403   cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
404   colorimetry_str = gst_video_colorimetry_to_string (&cinfo);
405 
406   if (colorimetry_str != NULL) {
407     for (i = 0; i < G_N_ELEMENTS (colorimetry_map); ++i) {
408       if (g_strcmp0 (colorimetry_map[i].str, colorimetry_str) == 0) {
409         colorspace = colorimetry_map[i].vpx_color_space;
410         break;
411       }
412     }
413   }
414 
415   if (colorspace == VPX_CS_UNKNOWN) {
416     if (format == GST_VIDEO_FORMAT_GBR
417         || format == GST_VIDEO_FORMAT_GBR_10BE
418         || format == GST_VIDEO_FORMAT_GBR_10LE
419         || format == GST_VIDEO_FORMAT_GBR_12BE
420         || format == GST_VIDEO_FORMAT_GBR_12LE) {
421       /* Currently has no effect because vp*enc elements only accept YUV video
422        * formats.
423        *
424        * FIXME: Support encoding GST_VIDEO_FORMAT_GBR and its high bits variants.
425        */
426       colorspace = VPX_CS_SRGB;
427     } else {
428       GST_WARNING_OBJECT (encoder, "Unsupported colorspace \"%s\"",
429           GST_STR_NULL (colorimetry_str));
430     }
431   }
432 
433   g_free (colorimetry_str);
434 
435   return colorspace;
436 }
437 
438 static gint
gst_vp9_get_vpx_color_range(GstVideoColorimetry * colorimetry)439 gst_vp9_get_vpx_color_range (GstVideoColorimetry * colorimetry)
440 {
441   if (colorimetry->range == GST_VIDEO_COLOR_RANGE_0_255)
442     /* Full range (0..255 or HBD equivalent) */
443     return 1;
444 
445   /* Limited range (16..235 or HBD equivalent) */
446   return 0;
447 }
448 
449 static gboolean
gst_vp9_enc_configure_encoder(GstVPXEnc * encoder,GstVideoCodecState * state)450 gst_vp9_enc_configure_encoder (GstVPXEnc * encoder, GstVideoCodecState * state)
451 {
452   GstVP9Enc *vp9enc = GST_VP9_ENC (encoder);
453   GstVideoInfo *info = &state->info;
454   vpx_codec_err_t status;
455 
456   status = vpx_codec_control (&encoder->encoder, VP9E_SET_COLOR_SPACE,
457       gst_vp9_get_vpx_colorspace (encoder, &GST_VIDEO_INFO_COLORIMETRY (info),
458           GST_VIDEO_INFO_FORMAT (info)));
459   if (status != VPX_CODEC_OK) {
460     GST_WARNING_OBJECT (encoder,
461         "Failed to set VP9E_SET_COLOR_SPACE: %s", gst_vpx_error_name (status));
462   }
463 
464   status = vpx_codec_control (&encoder->encoder, VP9E_SET_COLOR_RANGE,
465       gst_vp9_get_vpx_color_range (&GST_VIDEO_INFO_COLORIMETRY (info)));
466   if (status != VPX_CODEC_OK) {
467     GST_WARNING_OBJECT (encoder,
468         "Failed to set VP9E_SET_COLOR_RANGE: %s", gst_vpx_error_name (status));
469   }
470 
471   status =
472       vpx_codec_control (&encoder->encoder, VP9E_SET_TILE_COLUMNS,
473       vp9enc->tile_columns);
474   if (status != VPX_CODEC_OK) {
475     GST_DEBUG_OBJECT (encoder, "Failed to set VP9E_SET_TILE_COLUMNS: %s",
476         gst_vpx_error_name (status));
477   }
478 
479   status =
480       vpx_codec_control (&encoder->encoder, VP9E_SET_TILE_ROWS,
481       vp9enc->tile_rows);
482   if (status != VPX_CODEC_OK) {
483     GST_DEBUG_OBJECT (encoder, "Failed to set VP9E_SET_TILE_ROWS: %s",
484         gst_vpx_error_name (status));
485   }
486   status =
487       vpx_codec_control (&encoder->encoder, VP9E_SET_ROW_MT,
488       vp9enc->row_mt ? 1 : 0);
489   if (status != VPX_CODEC_OK) {
490     GST_DEBUG_OBJECT (encoder,
491         "Failed to set VP9E_SET_ROW_MT: %s", gst_vpx_error_name (status));
492   }
493   status =
494       vpx_codec_control (&encoder->encoder, VP9E_SET_AQ_MODE, vp9enc->aq_mode);
495   if (status != VPX_CODEC_OK) {
496     GST_WARNING_OBJECT (encoder,
497         "Failed to set VP9E_SET_AQ_MODE: %s", gst_vpx_error_name (status));
498   }
499   status =
500       vpx_codec_control (&encoder->encoder, VP9E_SET_FRAME_PARALLEL_DECODING,
501       vp9enc->frame_parallel_decoding ? 1 : 0);
502   if (status != VPX_CODEC_OK) {
503     GST_WARNING_OBJECT (encoder,
504         "Failed to set VP9E_SET_FRAME_PARALLEL_DECODING: %s",
505         gst_vpx_error_name (status));
506   }
507 
508   return TRUE;
509 }
510 
511 static vpx_codec_iface_t *
gst_vp9_enc_get_algo(GstVPXEnc * enc)512 gst_vp9_enc_get_algo (GstVPXEnc * enc)
513 {
514   return &vpx_codec_vp9_cx_algo;
515 }
516 
517 static gboolean
gst_vp9_enc_enable_scaling(GstVPXEnc * enc)518 gst_vp9_enc_enable_scaling (GstVPXEnc * enc)
519 {
520   return FALSE;
521 }
522 
523 static void
gst_vp9_enc_set_image_format(GstVPXEnc * enc,vpx_image_t * image)524 gst_vp9_enc_set_image_format (GstVPXEnc * enc, vpx_image_t * image)
525 {
526   switch (enc->input_state->info.finfo->format) {
527     case GST_VIDEO_FORMAT_I420:
528       image->fmt = VPX_IMG_FMT_I420;
529       image->bps = 12;
530       image->x_chroma_shift = image->y_chroma_shift = 1;
531       break;
532     case GST_VIDEO_FORMAT_YV12:
533       image->fmt = VPX_IMG_FMT_YV12;
534       image->bps = 12;
535       image->x_chroma_shift = image->y_chroma_shift = 1;
536       break;
537     case GST_VIDEO_FORMAT_Y42B:
538       image->fmt = VPX_IMG_FMT_I422;
539       image->bps = 16;
540       image->x_chroma_shift = 1;
541       image->y_chroma_shift = 0;
542       break;
543     case GST_VIDEO_FORMAT_Y444:
544       image->fmt = VPX_IMG_FMT_I444;
545       image->bps = 24;
546       image->x_chroma_shift = image->y_chroma_shift = 0;
547       break;
548     case GST_VIDEO_FORMAT_I420_10LE:
549       image->fmt = VPX_IMG_FMT_I42016;
550       image->bps = 15;
551       image->x_chroma_shift = image->y_chroma_shift = 1;
552       break;
553     case GST_VIDEO_FORMAT_I422_10LE:
554       image->fmt = VPX_IMG_FMT_I42216;
555       image->bps = 20;
556       image->x_chroma_shift = 1;
557       image->y_chroma_shift = 0;
558       break;
559     default:
560       g_assert_not_reached ();
561       break;
562   }
563 }
564 
565 static GstCaps *
gst_vp9_enc_get_new_simple_caps(GstVPXEnc * enc)566 gst_vp9_enc_get_new_simple_caps (GstVPXEnc * enc)
567 {
568   GstCaps *caps;
569   gchar *profile_str = g_strdup_printf ("%d", enc->cfg.g_profile);
570   caps = gst_caps_new_simple ("video/x-vp9",
571       "profile", G_TYPE_STRING, profile_str, NULL);
572   g_free (profile_str);
573   return caps;
574 }
575 
576 static void
gst_vp9_enc_set_stream_info(GstVPXEnc * enc,GstCaps * caps,GstVideoInfo * info)577 gst_vp9_enc_set_stream_info (GstVPXEnc * enc, GstCaps * caps,
578     GstVideoInfo * info)
579 {
580   return;
581 }
582 
583 static void *
gst_vp9_enc_process_frame_user_data(GstVPXEnc * enc,GstVideoCodecFrame * frame)584 gst_vp9_enc_process_frame_user_data (GstVPXEnc * enc,
585     GstVideoCodecFrame * frame)
586 {
587   return NULL;
588 }
589 
590 static GstFlowReturn
gst_vp9_enc_handle_invisible_frame_buffer(GstVPXEnc * enc,void * user_data,GstBuffer * buffer)591 gst_vp9_enc_handle_invisible_frame_buffer (GstVPXEnc * enc, void *user_data,
592     GstBuffer * buffer)
593 {
594   GstFlowReturn ret;
595   g_mutex_unlock (&enc->encoder_lock);
596   ret = gst_pad_push (GST_VIDEO_ENCODER_SRC_PAD (enc), buffer);
597   g_mutex_lock (&enc->encoder_lock);
598   return ret;
599 }
600 
601 static void
gst_vp9_enc_user_data_free(vpx_image_t * image)602 gst_vp9_enc_user_data_free (vpx_image_t * image)
603 {
604   g_slice_free (vpx_image_t, image);
605 }
606 
607 static void
gst_vp9_enc_set_frame_user_data(GstVPXEnc * enc,GstVideoCodecFrame * frame,vpx_image_t * image)608 gst_vp9_enc_set_frame_user_data (GstVPXEnc * enc, GstVideoCodecFrame * frame,
609     vpx_image_t * image)
610 {
611   gst_video_codec_frame_set_user_data (frame, image,
612       (GDestroyNotify) gst_vp9_enc_user_data_free);
613   return;
614 }
615 
616 #endif /* HAVE_VP9_ENCODER */
617