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