1 /* GStreamer H265 encoder plugin
2 * Copyright (C) 2005 Michal Benes <michal.benes@itonis.tv>
3 * Copyright (C) 2005 Josef Zlomek <josef.zlomek@itonis.tv>
4 * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
5 * Copyright (C) 2014 Thijs Vermeir <thijs.vermeir@barco.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * SECTION:element-x265enc
27 * This element encodes raw video into H265 compressed data.
35 #include "gstx265enc.h"
37 #include <gst/pbutils/pbutils.h>
38 #include <gst/video/video.h>
39 #include <gst/video/gstvideometa.h>
40 #include <gst/video/gstvideopool.h>
45 GST_DEBUG_CATEGORY_STATIC (x265_enc_debug);
46 #define GST_CAT_DEFAULT x265_enc_debug
48 static x265_api default_vtable;
50 static const x265_api *vtable_8bit = NULL;
51 static const x265_api *vtable_10bit = NULL;
52 static const x265_api *vtable_12bit = NULL;
66 #define PROP_BITRATE_DEFAULT (2 * 1024)
67 #define PROP_QP_DEFAULT -1
68 #define PROP_OPTION_STRING_DEFAULT ""
69 #define PROP_LOG_LEVEL_DEFAULT -1 /* None */
70 #define PROP_SPEED_PRESET_DEFAULT 6 /* Medium */
71 #define PROP_TUNE_DEFAULT 2 /* SSIM */
72 #define PROP_KEY_INT_MAX_DEFAULT 0 /* x265 lib default */
74 #define GST_X265_ENC_LOG_LEVEL_TYPE (gst_x265_enc_log_level_get_type())
76 gst_x265_enc_log_level_get_type (void)
78 static GType log_level = 0;
80 static const GEnumValue log_levels[] = {
81 {X265_LOG_NONE, "No logging", "none"},
82 {X265_LOG_ERROR, "Error", "error"},
83 {X265_LOG_WARNING, "Warning", "warning"},
84 {X265_LOG_INFO, "Info", "info"},
85 {X265_LOG_DEBUG, "Debug", "debug"},
86 {X265_LOG_FULL, "Full", "full"},
91 log_level = g_enum_register_static ("GstX265LogLevel", log_levels);
96 #define GST_X265_ENC_SPEED_PRESET_TYPE (gst_x265_enc_speed_preset_get_type())
98 gst_x265_enc_speed_preset_get_type (void)
100 static GType speed_preset = 0;
101 static GEnumValue *speed_presets;
104 if (speed_preset != 0)
108 while (x265_preset_names[n] != NULL)
111 speed_presets = g_new0 (GEnumValue, n + 2);
113 speed_presets[0].value = 0;
114 speed_presets[0].value_name = "No preset";
115 speed_presets[0].value_nick = "No preset";
117 for (i = 0; i < n; i++) {
118 speed_presets[i + 1].value = i + 1;
119 speed_presets[i + 1].value_name = x265_preset_names[i];
120 speed_presets[i + 1].value_nick = x265_preset_names[i];
123 speed_preset = g_enum_register_static ("GstX265SpeedPreset", speed_presets);
128 #define GST_X265_ENC_TUNE_TYPE (gst_x265_enc_tune_get_type())
130 gst_x265_enc_tune_get_type (void)
132 static GType tune = 0;
133 static GEnumValue *tune_values;
140 while (x265_tune_names[n] != NULL)
143 tune_values = g_new0 (GEnumValue, n + 2);
145 tune_values[0].value = 0;
146 tune_values[0].value_name = "No tunning";
147 tune_values[0].value_nick = "No tunning";
149 for (i = 0; i < n; i++) {
150 tune_values[i + 1].value = i + 1;
151 tune_values[i + 1].value_name = x265_tune_names[i];
152 tune_values[i + 1].value_nick = x265_tune_names[i];
155 tune = g_enum_register_static ("GstX265Tune", tune_values);
160 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
163 GST_STATIC_CAPS ("video/x-h265, "
164 "framerate = (fraction) [0/1, MAX], "
165 "width = (int) [ 16, MAX ], " "height = (int) [ 16, MAX ], "
166 "stream-format = (string) byte-stream, "
167 "alignment = (string) au, "
168 "profile = (string) { main, main-still-picture, main-intra, main-444,"
169 " main-444-intra, main-444-still-picture,"
170 " main-10, main-10-intra, main-422-10, main-422-10-intra,"
171 " main-444-10, main-444-10-intra,"
172 " main-12, main-12-intra, main-422-12, main-422-12-intra,"
173 " main-444-12, main-444-12-intra }")
176 static void gst_x265_enc_finalize (GObject * object);
177 static gboolean gst_x265_enc_start (GstVideoEncoder * encoder);
178 static gboolean gst_x265_enc_stop (GstVideoEncoder * encoder);
179 static gboolean gst_x265_enc_flush (GstVideoEncoder * encoder);
181 static gboolean gst_x265_enc_init_encoder (GstX265Enc * encoder);
182 static void gst_x265_enc_close_encoder (GstX265Enc * encoder);
184 static GstFlowReturn gst_x265_enc_finish (GstVideoEncoder * encoder);
185 static GstFlowReturn gst_x265_enc_handle_frame (GstVideoEncoder * encoder,
186 GstVideoCodecFrame * frame);
187 static void gst_x265_enc_flush_frames (GstX265Enc * encoder, gboolean send);
188 static GstFlowReturn gst_x265_enc_encode_frame (GstX265Enc * encoder,
189 x265_picture * pic_in, GstVideoCodecFrame * input_frame, guint32 * i_nal,
191 static gboolean gst_x265_enc_set_format (GstVideoEncoder * video_enc,
192 GstVideoCodecState * state);
193 static gboolean gst_x265_enc_propose_allocation (GstVideoEncoder * encoder,
196 static void gst_x265_enc_set_property (GObject * object, guint prop_id,
197 const GValue * value, GParamSpec * pspec);
198 static void gst_x265_enc_get_property (GObject * object, guint prop_id,
199 GValue * value, GParamSpec * pspec);
201 #define gst_x265_enc_parent_class parent_class
202 G_DEFINE_TYPE_WITH_CODE (GstX265Enc, gst_x265_enc, GST_TYPE_VIDEO_ENCODER,
203 G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
206 gst_x265_enc_add_x265_chroma_format (GstStructure * s,
207 gboolean allow_420, gboolean allow_422, gboolean allow_444,
208 gboolean allow_8bit, gboolean allow_10bit, gboolean allow_12bit)
210 GValue fmts = G_VALUE_INIT;
211 GValue fmt = G_VALUE_INIT;
212 gboolean ret = FALSE;
214 g_value_init (&fmts, GST_TYPE_LIST);
215 g_value_init (&fmt, G_TYPE_STRING);
219 g_value_set_string (&fmt, "Y444");
220 gst_value_list_append_value (&fmts, &fmt);
224 g_value_set_string (&fmt, "Y42B");
225 gst_value_list_append_value (&fmts, &fmt);
229 g_value_set_string (&fmt, "I420");
230 gst_value_list_append_value (&fmts, &fmt);
236 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
237 g_value_set_string (&fmt, "Y444_10LE");
239 g_value_set_string (&fmt, "Y444_10BE");
241 gst_value_list_append_value (&fmts, &fmt);
245 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
246 g_value_set_string (&fmt, "I422_10LE");
248 g_value_set_string (&fmt, "I422_10BE");
250 gst_value_list_append_value (&fmts, &fmt);
254 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
255 g_value_set_string (&fmt, "I420_10LE");
257 g_value_set_string (&fmt, "I420_10BE");
259 gst_value_list_append_value (&fmts, &fmt);
265 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
266 g_value_set_string (&fmt, "Y444_12LE");
268 g_value_set_string (&fmt, "Y444_12BE");
270 gst_value_list_append_value (&fmts, &fmt);
274 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
275 g_value_set_string (&fmt, "I422_12LE");
277 g_value_set_string (&fmt, "I422_12BE");
279 gst_value_list_append_value (&fmts, &fmt);
283 if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
284 g_value_set_string (&fmt, "I420_12LE");
286 g_value_set_string (&fmt, "I420_12BE");
288 gst_value_list_append_value (&fmts, &fmt);
292 if (gst_value_list_get_size (&fmts) != 0) {
293 gst_structure_take_value (s, "format", &fmts);
296 g_value_unset (&fmts);
299 g_value_unset (&fmt);
305 gst_x265_enc_sink_query (GstVideoEncoder * enc, GstQuery * query)
307 GstPad *pad = GST_VIDEO_ENCODER_SINK_PAD (enc);
310 switch (GST_QUERY_TYPE (query)) {
311 case GST_QUERY_ACCEPT_CAPS:{
312 GstCaps *acceptable, *caps;
314 acceptable = gst_pad_get_pad_template_caps (pad);
316 gst_query_parse_accept_caps (query, &caps);
318 gst_query_set_accept_caps_result (query,
319 gst_caps_is_subset (caps, acceptable));
320 gst_caps_unref (acceptable);
325 res = GST_VIDEO_ENCODER_CLASS (parent_class)->sink_query (enc, query);
333 check_formats (const gchar * str, guint * max_chroma, guint * max_bit_minus_8)
338 if (g_strrstr (str, "-444"))
340 else if (g_strrstr (str, "-422") && *max_chroma < 1)
343 if (g_strrstr (str, "-12"))
344 *max_bit_minus_8 = 4;
345 else if (g_strrstr (str, "-10") && *max_bit_minus_8 < 2)
346 *max_bit_minus_8 = 2;
350 gst_x265_enc_sink_getcaps (GstVideoEncoder * enc, GstCaps * filter)
352 GstCaps *templ_caps, *supported_incaps;
356 gboolean has_profile = FALSE;
357 guint max_chroma_index = 0;
358 guint max_bit_minus_8 = 0;
360 templ_caps = gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SINK_PAD (enc));
361 allowed = gst_pad_get_allowed_caps (enc->srcpad);
363 GST_LOG_OBJECT (enc, "template caps %" GST_PTR_FORMAT, templ_caps);
364 GST_LOG_OBJECT (enc, "allowed caps %" GST_PTR_FORMAT, allowed);
368 supported_incaps = templ_caps;
370 } else if (gst_caps_is_empty (allowed)) {
371 /* cannot negotiate, return empty caps */
372 gst_caps_unref (templ_caps);
376 /* fill format based on requested profile */
377 for (i = 0; i < gst_caps_get_size (allowed); i++) {
378 const GstStructure *allowed_s = gst_caps_get_structure (allowed, i);
381 if ((val = gst_structure_get_value (allowed_s, "profile"))) {
382 if (G_VALUE_HOLDS_STRING (val)) {
383 check_formats (g_value_get_string (val), &max_chroma_index,
386 } else if (GST_VALUE_HOLDS_LIST (val)) {
387 for (j = 0; j < gst_value_list_get_size (val); j++) {
388 const GValue *vlist = gst_value_list_get_value (val, j);
390 if (G_VALUE_HOLDS_STRING (vlist)) {
391 check_formats (g_value_get_string (vlist), &max_chroma_index,
401 /* downstream did not request profile */
402 supported_incaps = templ_caps;
405 gboolean has_12bit = FALSE;
406 gboolean has_10bit = FALSE;
407 gboolean has_8bit = TRUE;
408 gboolean has_444 = FALSE;
409 gboolean has_422 = FALSE;
410 gboolean has_420 = TRUE;
412 supported_incaps = gst_caps_new_simple ("video/x-raw",
413 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
414 "width", GST_TYPE_INT_RANGE, 16, G_MAXINT,
415 "height", GST_TYPE_INT_RANGE, 16, G_MAXINT, NULL);
417 /* NOTE: 12bits profiles can accept 8bits and 10bits format */
418 if (max_bit_minus_8 >= 4)
420 if (max_bit_minus_8 >= 2)
423 has_8bit &= ! !vtable_8bit;
424 has_10bit &= ! !vtable_10bit;
425 has_12bit &= ! !vtable_12bit;
427 /* 4:4:4 profiles can handle 4:2:2 and 4:2:0 */
428 if (max_chroma_index >= 2)
430 if (max_chroma_index >= 1)
433 s = gst_caps_get_structure (supported_incaps, 0);
434 gst_x265_enc_add_x265_chroma_format (s, has_420, has_422, has_444,
435 has_8bit, has_10bit, has_12bit);
437 gst_caps_unref (templ_caps);
441 GST_LOG_OBJECT (enc, "supported caps %" GST_PTR_FORMAT, supported_incaps);
442 fcaps = gst_video_encoder_proxy_getcaps (enc, supported_incaps, filter);
443 gst_clear_caps (&supported_incaps);
444 gst_clear_caps (&allowed);
446 GST_LOG_OBJECT (enc, "proxy caps %" GST_PTR_FORMAT, fcaps);
452 gst_x265_enc_class_init (GstX265EncClass * klass)
454 GObjectClass *gobject_class;
455 GstElementClass *element_class;
456 GstVideoEncoderClass *gstencoder_class;
457 GstPadTemplate *sink_templ;
458 GstCaps *supported_sinkcaps;
460 gobject_class = G_OBJECT_CLASS (klass);
461 element_class = GST_ELEMENT_CLASS (klass);
462 gstencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
464 gobject_class->set_property = gst_x265_enc_set_property;
465 gobject_class->get_property = gst_x265_enc_get_property;
466 gobject_class->finalize = gst_x265_enc_finalize;
468 gstencoder_class->set_format = GST_DEBUG_FUNCPTR (gst_x265_enc_set_format);
469 gstencoder_class->handle_frame =
470 GST_DEBUG_FUNCPTR (gst_x265_enc_handle_frame);
471 gstencoder_class->start = GST_DEBUG_FUNCPTR (gst_x265_enc_start);
472 gstencoder_class->stop = GST_DEBUG_FUNCPTR (gst_x265_enc_stop);
473 gstencoder_class->flush = GST_DEBUG_FUNCPTR (gst_x265_enc_flush);
474 gstencoder_class->finish = GST_DEBUG_FUNCPTR (gst_x265_enc_finish);
475 gstencoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_x265_enc_sink_getcaps);
476 gstencoder_class->sink_query = GST_DEBUG_FUNCPTR (gst_x265_enc_sink_query);
477 gstencoder_class->propose_allocation =
478 GST_DEBUG_FUNCPTR (gst_x265_enc_propose_allocation);
480 g_object_class_install_property (gobject_class, PROP_BITRATE,
481 g_param_spec_uint ("bitrate", "Bitrate", "Bitrate in kbit/sec", 1,
482 100 * 1024, PROP_BITRATE_DEFAULT,
483 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
484 GST_PARAM_MUTABLE_PLAYING));
486 g_object_class_install_property (gobject_class, PROP_QP,
487 g_param_spec_int ("qp", "Quantization parameter",
488 "QP for P slices in (implied) CQP mode (-1 = disabled)", -1,
489 51, PROP_QP_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
491 g_object_class_install_property (gobject_class, PROP_OPTION_STRING,
492 g_param_spec_string ("option-string", "Option string",
493 "String of x265 options (overridden by element properties)"
494 " in the format \"key1=value1:key2=value2\".",
495 PROP_OPTION_STRING_DEFAULT,
496 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
498 g_object_class_install_property (gobject_class, PROP_X265_LOG_LEVEL,
499 g_param_spec_enum ("log-level", "(internal) x265 log level",
500 "x265 log level", GST_X265_ENC_LOG_LEVEL_TYPE,
501 PROP_LOG_LEVEL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
503 g_object_class_install_property (gobject_class, PROP_SPEED_PRESET,
504 g_param_spec_enum ("speed-preset", "Speed preset",
505 "Preset name for speed/quality tradeoff options",
506 GST_X265_ENC_SPEED_PRESET_TYPE, PROP_SPEED_PRESET_DEFAULT,
507 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
509 g_object_class_install_property (gobject_class, PROP_TUNE,
510 g_param_spec_enum ("tune", "Tune options",
511 "Preset name for tuning options", GST_X265_ENC_TUNE_TYPE,
512 PROP_TUNE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
514 * GstX265Enc::key-int-max:
516 * Controls maximum number of frames since the last keyframe
520 g_object_class_install_property (gobject_class, PROP_KEY_INT_MAX,
521 g_param_spec_int ("key-int-max", "Max key frame",
522 "Maximal distance between two key-frames (0 = x265 default / 250)",
523 0, G_MAXINT32, PROP_KEY_INT_MAX_DEFAULT, G_PARAM_READWRITE));
525 gst_element_class_set_static_metadata (element_class,
526 "x265enc", "Codec/Encoder/Video", "H265 Encoder",
527 "Thijs Vermeir <thijs.vermeir@barco.com>");
529 supported_sinkcaps = gst_caps_new_simple ("video/x-raw",
530 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
531 "width", GST_TYPE_INT_RANGE, 16, G_MAXINT,
532 "height", GST_TYPE_INT_RANGE, 16, G_MAXINT, NULL);
534 gst_x265_enc_add_x265_chroma_format (gst_caps_get_structure
535 (supported_sinkcaps, 0), TRUE, TRUE, TRUE, ! !vtable_8bit,
536 ! !vtable_10bit, ! !vtable_12bit);
538 sink_templ = gst_pad_template_new ("sink",
539 GST_PAD_SINK, GST_PAD_ALWAYS, supported_sinkcaps);
541 gst_caps_unref (supported_sinkcaps);
543 gst_element_class_add_pad_template (element_class, sink_templ);
544 gst_element_class_add_static_pad_template (element_class, &src_factory);
547 /* initialize the new element
548 * instantiate pads and add them to element
550 * initialize structure
553 gst_x265_enc_init (GstX265Enc * encoder)
555 encoder->push_header = TRUE;
557 encoder->bitrate = PROP_BITRATE_DEFAULT;
558 encoder->qp = PROP_QP_DEFAULT;
559 encoder->option_string_prop = g_string_new (PROP_OPTION_STRING_DEFAULT);
560 encoder->log_level = PROP_LOG_LEVEL_DEFAULT;
561 encoder->speed_preset = PROP_SPEED_PRESET_DEFAULT;
562 encoder->tune = PROP_TUNE_DEFAULT;
563 encoder->keyintmax = PROP_KEY_INT_MAX_DEFAULT;
564 encoder->api = &default_vtable;
566 encoder->api->param_default (&encoder->x265param);
568 encoder->peer_profiles = g_ptr_array_new ();
573 GstVideoCodecFrame *frame;
574 GstVideoFrame vframe;
578 gst_x265_enc_queue_frame (GstX265Enc * enc, GstVideoCodecFrame * frame,
581 GstVideoFrame vframe;
584 if (!gst_video_frame_map (&vframe, info, frame->input_buffer, GST_MAP_READ))
587 fdata = g_slice_new (FrameData);
588 fdata->frame = gst_video_codec_frame_ref (frame);
589 fdata->vframe = vframe;
591 enc->pending_frames = g_list_prepend (enc->pending_frames, fdata);
597 gst_x265_enc_dequeue_frame (GstX265Enc * enc, GstVideoCodecFrame * frame)
601 for (l = enc->pending_frames; l; l = l->next) {
602 FrameData *fdata = l->data;
604 if (fdata->frame != frame)
607 gst_video_frame_unmap (&fdata->vframe);
608 gst_video_codec_frame_unref (fdata->frame);
609 g_slice_free (FrameData, fdata);
611 enc->pending_frames = g_list_delete_link (enc->pending_frames, l);
617 gst_x265_enc_dequeue_all_frames (GstX265Enc * enc)
621 for (l = enc->pending_frames; l; l = l->next) {
622 FrameData *fdata = l->data;
624 gst_video_frame_unmap (&fdata->vframe);
625 gst_video_codec_frame_unref (fdata->frame);
626 g_slice_free (FrameData, fdata);
628 g_list_free (enc->pending_frames);
629 enc->pending_frames = NULL;
633 gst_x265_enc_start (GstVideoEncoder * encoder)
635 GstX265Enc *x265enc = GST_X265_ENC (encoder);
637 g_ptr_array_set_size (x265enc->peer_profiles, 0);
643 gst_x265_enc_stop (GstVideoEncoder * encoder)
645 GstX265Enc *x265enc = GST_X265_ENC (encoder);
647 GST_DEBUG_OBJECT (encoder, "stop encoder");
649 gst_x265_enc_flush_frames (x265enc, FALSE);
650 gst_x265_enc_close_encoder (x265enc);
651 gst_x265_enc_dequeue_all_frames (x265enc);
653 if (x265enc->input_state)
654 gst_video_codec_state_unref (x265enc->input_state);
655 x265enc->input_state = NULL;
657 g_ptr_array_set_size (x265enc->peer_profiles, 0);
664 gst_x265_enc_flush (GstVideoEncoder * encoder)
666 GstX265Enc *x265enc = GST_X265_ENC (encoder);
668 GST_DEBUG_OBJECT (encoder, "flushing encoder");
670 gst_x265_enc_flush_frames (x265enc, FALSE);
671 gst_x265_enc_close_encoder (x265enc);
672 gst_x265_enc_dequeue_all_frames (x265enc);
674 gst_x265_enc_init_encoder (x265enc);
680 gst_x265_enc_finalize (GObject * object)
682 GstX265Enc *encoder = GST_X265_ENC (object);
684 if (encoder->input_state)
685 gst_video_codec_state_unref (encoder->input_state);
686 encoder->input_state = NULL;
688 gst_x265_enc_close_encoder (encoder);
690 g_string_free (encoder->option_string_prop, TRUE);
692 if (encoder->peer_profiles)
693 g_ptr_array_free (encoder->peer_profiles, FALSE);
695 G_OBJECT_CLASS (parent_class)->finalize (object);
699 gst_x265_enc_gst_to_x265_video_format (GstVideoFormat format, gint * nplanes)
702 case GST_VIDEO_FORMAT_I420:
703 case GST_VIDEO_FORMAT_YV12:
704 case GST_VIDEO_FORMAT_I420_10LE:
705 case GST_VIDEO_FORMAT_I420_10BE:
706 case GST_VIDEO_FORMAT_I420_12LE:
707 case GST_VIDEO_FORMAT_I420_12BE:
710 return X265_CSP_I420;
711 case GST_VIDEO_FORMAT_Y444:
712 case GST_VIDEO_FORMAT_Y444_10LE:
713 case GST_VIDEO_FORMAT_Y444_10BE:
714 case GST_VIDEO_FORMAT_Y444_12LE:
715 case GST_VIDEO_FORMAT_Y444_12BE:
718 return X265_CSP_I444;
719 case GST_VIDEO_FORMAT_Y42B:
720 case GST_VIDEO_FORMAT_I422_10LE:
721 case GST_VIDEO_FORMAT_I422_10BE:
722 case GST_VIDEO_FORMAT_I422_12LE:
723 case GST_VIDEO_FORMAT_I422_12BE:
726 return X265_CSP_I422;
728 g_return_val_if_reached (GST_VIDEO_FORMAT_UNKNOWN);
733 * gst_x265_enc_parse_options
734 * @encoder: Encoder to which options are assigned
735 * @str: Option string
737 * Parse option string and assign to x265 parameters
741 gst_x265_enc_parse_options (GstX265Enc * encoder, const gchar * str)
745 gint parse_result = 0, ret = 0;
746 gchar *options = (gchar *) str;
747 const x265_api *api = encoder->api;
749 g_assert (api != NULL);
751 while (*options == ':')
754 kvpairs = g_strsplit (options, ":", 0);
755 npairs = g_strv_length (kvpairs);
757 for (i = 0; i < npairs; i++) {
758 GStrv key_val = g_strsplit (kvpairs[i], "=", 2);
761 api->param_parse (&encoder->x265param, key_val[0], key_val[1]);
763 if (parse_result == X265_PARAM_BAD_NAME) {
764 GST_ERROR_OBJECT (encoder, "Bad name for option %s=%s",
765 key_val[0] ? key_val[0] : "", key_val[1] ? key_val[1] : "");
767 if (parse_result == X265_PARAM_BAD_VALUE) {
768 GST_ERROR_OBJECT (encoder,
769 "Bad value for option %s=%s (Note: a NULL value for a non-boolean triggers this)",
770 key_val[0] ? key_val[0] : "", key_val[1] ? key_val[1] : "");
773 g_strfreev (key_val);
779 g_strfreev (kvpairs);
784 * gst_x265_enc_init_encoder
785 * @encoder: Encoder which should be initialized.
787 * Initialize x265 encoder.
791 gst_x265_enc_init_encoder (GstX265Enc * encoder)
795 gboolean peer_intra = FALSE;
797 if (!encoder->input_state) {
798 GST_DEBUG_OBJECT (encoder, "Have no input state yet");
802 info = &encoder->input_state->info;
804 /* make sure that the encoder is closed */
805 gst_x265_enc_close_encoder (encoder);
807 GST_OBJECT_LOCK (encoder);
808 bitdepth = GST_VIDEO_INFO_COMP_DEPTH (info, 0);
814 encoder->api = vtable_8bit;
815 else if (vtable_10bit)
816 encoder->api = vtable_10bit;
818 encoder->api = vtable_12bit;
822 encoder->api = vtable_10bit;
824 encoder->api = vtable_12bit;
827 encoder->api = vtable_12bit;
834 GST_ERROR_OBJECT (encoder, "no %d bitdepth vtable available", bitdepth);
835 GST_OBJECT_UNLOCK (encoder);
839 if (encoder->api->param_default_preset (&encoder->x265param,
840 x265_preset_names[encoder->speed_preset - 1],
841 x265_tune_names[encoder->tune - 1]) < 0) {
842 GST_DEBUG_OBJECT (encoder, "preset or tune unrecognized");
843 GST_OBJECT_UNLOCK (encoder);
847 /* set up encoder parameters */
848 encoder->x265param.logLevel = encoder->log_level;
849 encoder->x265param.internalCsp =
850 gst_x265_enc_gst_to_x265_video_format (info->finfo->format, NULL);
851 if (info->fps_d == 0 || info->fps_n == 0) {
853 encoder->x265param.fpsNum = info->fps_n;
854 encoder->x265param.fpsDenom = info->fps_d;
856 encoder->x265param.sourceWidth = info->width;
857 encoder->x265param.sourceHeight = info->height;
859 /* x265 does not allow user to configure a picture size smaller than
860 * at least one CU size, and maxCUSize must be 16, 32, or 64.
861 * Therefore, we should be set the CU size according to the input resolution.
863 if (encoder->x265param.sourceWidth < 64
864 || encoder->x265param.sourceHeight < 64)
865 encoder->x265param.maxCUSize = 32;
866 if (encoder->x265param.sourceWidth < 32
867 || encoder->x265param.sourceHeight < 32)
868 encoder->x265param.maxCUSize = 16;
870 if (info->par_d > 0) {
871 encoder->x265param.vui.aspectRatioIdc = X265_EXTENDED_SAR;
872 encoder->x265param.vui.sarWidth = info->par_n;
873 encoder->x265param.vui.sarHeight = info->par_d;
876 encoder->x265param.vui.bEnableVideoSignalTypePresentFlag = 1;
877 /* Unspecified video format (5) */
878 encoder->x265param.vui.videoFormat = 5;
879 if (info->colorimetry.range == GST_VIDEO_COLOR_RANGE_0_255) {
880 encoder->x265param.vui.bEnableVideoFullRangeFlag = 1;
882 encoder->x265param.vui.bEnableVideoFullRangeFlag = 0;
885 encoder->x265param.vui.bEnableColorDescriptionPresentFlag = 1;
886 encoder->x265param.vui.matrixCoeffs =
887 gst_video_color_matrix_to_iso (info->colorimetry.matrix);
888 encoder->x265param.vui.colorPrimaries =
889 gst_video_color_primaries_to_iso (info->colorimetry.primaries);
890 encoder->x265param.vui.transferCharacteristics =
891 gst_video_color_transfer_to_iso (info->colorimetry.transfer);
893 if (encoder->qp != -1) {
895 encoder->x265param.rc.qp = encoder->qp;
896 encoder->x265param.rc.rateControlMode = X265_RC_CQP;
899 encoder->x265param.rc.bitrate = encoder->bitrate;
900 encoder->x265param.rc.rateControlMode = X265_RC_ABR;
903 if (encoder->peer_profiles->len > 0) {
906 for (i = 0; i < encoder->peer_profiles->len; i++) {
907 const gchar *profile = g_ptr_array_index (encoder->peer_profiles, i);
909 GST_DEBUG_OBJECT (encoder, "Apply peer profile %s", profile);
910 if (encoder->api->param_apply_profile (&encoder->x265param, profile) < 0) {
911 GST_WARNING_OBJECT (encoder, "Failed to apply profile %s", profile);
913 /* libx265 chooses still-picture profile only if x265_param::totalFrames
914 * equals to one (otherwise, -intra profile will be chosen) */
915 if (g_strrstr (profile, "stillpicture"))
916 encoder->x265param.totalFrames = 1;
918 if (g_str_has_suffix (profile, "-intra"))
925 if (i == encoder->peer_profiles->len) {
926 GST_ERROR_OBJECT (encoder, "Couldn't apply peer profile");
927 GST_OBJECT_UNLOCK (encoder);
934 encoder->x265param.keyframeMax = 1;
935 } else if (encoder->keyintmax > 0) {
936 encoder->x265param.keyframeMax = encoder->keyintmax;
938 #if (X265_BUILD >= 79)
940 GstVideoMasteringDisplayInfo minfo;
941 GstVideoContentLightLevel cll;
943 if (gst_video_mastering_display_info_from_caps (&minfo,
944 encoder->input_state->caps)) {
945 guint16 displayPrimaryX[3];
946 guint16 displayPrimaryY[3];
947 guint16 whitePointX, whitePointY;
948 guint32 maxDisplayMasteringLuminance;
949 guint32 minDisplayMasteringLuminance;
950 const guint chroma_scale = 50000;
951 const guint luma_scale = 10000;
953 GST_DEBUG_OBJECT (encoder, "Apply mastering display info");
956 (guint16) gst_util_uint64_scale_round (minfo.Gx_n, chroma_scale,
959 (guint16) gst_util_uint64_scale_round (minfo.Bx_n, chroma_scale,
962 (guint16) gst_util_uint64_scale_round (minfo.Rx_n, chroma_scale,
966 (guint16) gst_util_uint64_scale_round (minfo.Gy_n, chroma_scale,
969 (guint16) gst_util_uint64_scale_round (minfo.By_n, chroma_scale,
972 (guint16) gst_util_uint64_scale_round (minfo.Ry_n, chroma_scale,
976 (guint16) gst_util_uint64_scale_round (minfo.Wx_n, chroma_scale,
979 (guint16) gst_util_uint64_scale_round (minfo.Wy_n, chroma_scale,
982 maxDisplayMasteringLuminance =
983 (guint32) gst_util_uint64_scale_round (minfo.max_luma_n, luma_scale,
985 minDisplayMasteringLuminance =
986 (guint32) gst_util_uint64_scale_round (minfo.min_luma_n, luma_scale,
989 encoder->x265param.masteringDisplayColorVolume =
990 g_strdup_printf ("G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)",
991 displayPrimaryX[0], displayPrimaryY[0],
992 displayPrimaryX[1], displayPrimaryY[1],
993 displayPrimaryX[2], displayPrimaryY[2],
994 whitePointX, whitePointY,
995 maxDisplayMasteringLuminance, minDisplayMasteringLuminance);
998 if (gst_video_content_light_level_from_caps (&cll,
999 encoder->input_state->caps)) {
1002 GST_DEBUG_OBJECT (encoder, "Apply content light level");
1004 gst_util_fraction_to_double (cll.maxCLL_n, cll.maxCLL_d, &val);
1005 encoder->x265param.maxCLL = (guint16) val;
1007 gst_util_fraction_to_double (cll.maxFALL_n, cll.maxFALL_d, &val);
1008 encoder->x265param.maxFALL = (guint16) val;
1013 /* apply option-string property */
1014 if (encoder->option_string_prop && encoder->option_string_prop->len) {
1015 GST_DEBUG_OBJECT (encoder, "Applying option-string: %s",
1016 encoder->option_string_prop->str);
1017 if (gst_x265_enc_parse_options (encoder,
1018 encoder->option_string_prop->str) == FALSE) {
1019 GST_DEBUG_OBJECT (encoder, "Your option-string contains errors.");
1020 GST_OBJECT_UNLOCK (encoder);
1025 encoder->reconfig = FALSE;
1027 /* good start, will be corrected if needed */
1028 encoder->dts_offset = 0;
1030 GST_OBJECT_UNLOCK (encoder);
1032 encoder->x265enc = encoder->api->encoder_open (&encoder->x265param);
1033 if (!encoder->x265enc) {
1034 GST_ELEMENT_ERROR (encoder, STREAM, ENCODE,
1035 ("Can not initialize x265 encoder."), (NULL));
1039 encoder->push_header = TRUE;
1044 /* gst_x265_enc_close_encoder
1045 * @encoder: Encoder which should close.
1047 * Close x265 encoder.
1050 gst_x265_enc_close_encoder (GstX265Enc * encoder)
1052 if (encoder->x265enc != NULL) {
1053 g_assert (encoder->api != NULL);
1055 encoder->api->encoder_close (encoder->x265enc);
1056 encoder->x265enc = NULL;
1061 gst_x265_enc_bytestream_to_nal (x265_nal * input)
1066 output = g_malloc (sizeof (x265_nal));
1067 output->payload = g_malloc (input->sizeBytes - 4);
1068 output->sizeBytes = input->sizeBytes - 4;
1069 output->type = input->type;
1072 for (i = 4, j = 0; i < input->sizeBytes; (i++, j++)) {
1073 if (input->payload[i] == 0x00) {
1075 } else if (input->payload[i] == 0x03 && zeros == 2) {
1078 output->sizeBytes--;
1083 output->payload[j] = input->payload[i];
1090 x265_nal_free (x265_nal * nal)
1092 g_free (nal->payload);
1097 gst_x265_enc_set_level_tier_and_profile (GstX265Enc * encoder, GstCaps * caps)
1099 x265_nal *nal, *vps_nal;
1102 const x265_api *api = encoder->api;
1104 const gchar *profile;
1105 GstCaps *allowed_caps;
1107 const gchar *allowed_profile;
1109 GST_DEBUG_OBJECT (encoder, "set profile, level and tier");
1111 g_assert (api != NULL);
1113 header_return = api->encoder_headers (encoder->x265enc, &nal, &i_nal);
1114 if (header_return < 0) {
1115 GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 header failed."),
1116 ("x265_encoder_headers return code=%d", header_return));
1120 GST_DEBUG_OBJECT (encoder, "%d nal units in header", i_nal);
1122 g_assert (nal[0].type == NAL_UNIT_VPS);
1123 vps_nal = gst_x265_enc_bytestream_to_nal (&nal[0]);
1125 GST_MEMDUMP ("VPS", vps_nal->payload, vps_nal->sizeBytes);
1127 gst_codec_utils_h265_caps_set_level_tier_and_profile (caps,
1128 vps_nal->payload + 6, vps_nal->sizeBytes - 6);
1129 x265_nal_free (vps_nal);
1131 /* relaxing the profile condition since libx265 can select lower profile than
1132 * requested one via param_apply_profile()
1134 s = gst_caps_get_structure (caps, 0);
1135 profile = gst_structure_get_string (s, "profile");
1137 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1139 if (allowed_caps == NULL)
1142 if (!gst_caps_can_intersect (allowed_caps, caps)) {
1143 guint peer_bitdepth = 0;
1144 guint peer_chroma_format = 0;
1146 guint chroma_format = 0;
1148 allowed_caps = gst_caps_make_writable (allowed_caps);
1149 allowed_caps = gst_caps_truncate (allowed_caps);
1150 s2 = gst_caps_get_structure (allowed_caps, 0);
1151 gst_structure_fixate_field_string (s2, "profile", profile);
1152 allowed_profile = gst_structure_get_string (s2, "profile");
1154 check_formats (allowed_profile, &peer_chroma_format, &peer_bitdepth);
1155 check_formats (profile, &chroma_format, &bitdepth);
1157 if (chroma_format <= peer_chroma_format && bitdepth <= peer_bitdepth) {
1158 GST_INFO_OBJECT (encoder, "downstream requested %s profile, but "
1159 "encoder will now output %s profile (which is a subset), due "
1160 "to how it's been configured", allowed_profile, profile);
1161 gst_structure_set (s, "profile", G_TYPE_STRING, allowed_profile, NULL);
1164 gst_caps_unref (allowed_caps);
1172 gst_x265_enc_get_header_buffer (GstX265Enc * encoder)
1175 guint32 i_nal, i, offset;
1176 gint32 vps_idx, sps_idx, pps_idx;
1179 gsize header_size = 0;
1180 const x265_api *api = encoder->api;
1182 g_assert (api != NULL);
1184 header_return = api->encoder_headers (encoder->x265enc, &nal, &i_nal);
1185 if (header_return < 0) {
1186 GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 header failed."),
1187 ("x265_encoder_headers return code=%d", header_return));
1191 GST_DEBUG_OBJECT (encoder, "%d nal units in header", i_nal);
1193 /* x265 returns also non header nal units with the call x265_encoder_headers.
1194 * The useful headers are sequential (VPS, SPS and PPS), so we look for this
1195 * nal units and only copy these tree nal units as the header */
1197 vps_idx = sps_idx = pps_idx = -1;
1198 for (i = 0; i < i_nal; i++) {
1199 if (nal[i].type == NAL_UNIT_VPS) {
1201 header_size += nal[i].sizeBytes;
1202 } else if (nal[i].type == NAL_UNIT_SPS) {
1204 header_size += nal[i].sizeBytes;
1205 } else if (nal[i].type == NAL_UNIT_PPS) {
1207 header_size += nal[i].sizeBytes;
1208 } else if (nal[i].type == NAL_UNIT_PREFIX_SEI) {
1209 header_size += nal[i].sizeBytes;
1213 if (vps_idx == -1 || sps_idx == -1 || pps_idx == -1) {
1214 GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 header failed."),
1215 ("x265_encoder_headers did not return VPS, SPS and PPS"));
1220 buf = gst_buffer_new_allocate (NULL, header_size, NULL);
1221 gst_buffer_fill (buf, offset, nal[vps_idx].payload, nal[vps_idx].sizeBytes);
1222 offset += nal[vps_idx].sizeBytes;
1223 gst_buffer_fill (buf, offset, nal[sps_idx].payload, nal[sps_idx].sizeBytes);
1224 offset += nal[sps_idx].sizeBytes;
1225 gst_buffer_fill (buf, offset, nal[pps_idx].payload, nal[pps_idx].sizeBytes);
1226 offset += nal[pps_idx].sizeBytes;
1228 for (i = 0; i < i_nal; i++) {
1229 if (nal[i].type == NAL_UNIT_PREFIX_SEI) {
1230 gst_buffer_fill (buf, offset, nal[i].payload, nal[i].sizeBytes);
1231 offset += nal[i].sizeBytes;
1238 /* gst_x265_enc_set_src_caps
1239 * Returns: TRUE on success.
1242 gst_x265_enc_set_src_caps (GstX265Enc * encoder, GstCaps * caps)
1245 GstStructure *structure;
1246 GstVideoCodecState *state;
1249 outcaps = gst_caps_new_empty_simple ("video/x-h265");
1250 structure = gst_caps_get_structure (outcaps, 0);
1252 gst_structure_set (structure, "stream-format", G_TYPE_STRING, "byte-stream",
1254 gst_structure_set (structure, "alignment", G_TYPE_STRING, "au", NULL);
1256 if (!gst_x265_enc_set_level_tier_and_profile (encoder, outcaps)) {
1257 gst_caps_unref (outcaps);
1261 state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (encoder),
1262 outcaps, encoder->input_state);
1263 GST_DEBUG_OBJECT (encoder, "output caps: %" GST_PTR_FORMAT, state->caps);
1264 gst_video_codec_state_unref (state);
1266 tags = gst_tag_list_new_empty ();
1267 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, "x265",
1268 GST_TAG_ENCODER_VERSION, x265_version_str, NULL);
1269 gst_video_encoder_merge_tags (GST_VIDEO_ENCODER (encoder), tags,
1270 GST_TAG_MERGE_REPLACE);
1271 gst_tag_list_unref (tags);
1277 gst_x265_enc_set_latency (GstX265Enc * encoder)
1279 GstVideoInfo *info = &encoder->input_state->info;
1280 gint max_delayed_frames;
1281 GstClockTime latency;
1283 /* FIXME get a real value from the encoder, this is currently not exposed */
1284 if (encoder->tune > 0 && encoder->tune <= G_N_ELEMENTS (x265_tune_names) &&
1285 strcmp (x265_tune_names[encoder->tune - 1], "zerolatency") == 0)
1286 max_delayed_frames = 0;
1288 max_delayed_frames = 5;
1291 latency = gst_util_uint64_scale_ceil (GST_SECOND * info->fps_d,
1292 max_delayed_frames, info->fps_n);
1294 /* FIXME: Assume 25fps. This is better than reporting no latency at
1295 * all and then later failing in live pipelines
1297 latency = gst_util_uint64_scale_ceil (GST_SECOND * 1,
1298 max_delayed_frames, 25);
1301 GST_INFO_OBJECT (encoder,
1302 "Updating latency to %" GST_TIME_FORMAT " (%d frames)",
1303 GST_TIME_ARGS (latency), max_delayed_frames);
1305 gst_video_encoder_set_latency (GST_VIDEO_ENCODER (encoder), latency, latency);
1310 const gchar *gst_profile;
1311 const gchar *x265_profile;
1312 } GstX265EncProfileTable;
1314 static const gchar *
1315 gst_x265_enc_profile_from_gst (const gchar * profile)
1318 static const GstX265EncProfileTable profile_table[] = {
1321 {"main-still-picture", "mainstillpicture"},
1322 {"main-intra", "main-intra"},
1323 {"main-444", "main444-8"},
1324 {"main-444-intra", "main444-intra"},
1325 {"main-444-still-picture", "main444-stillpicture"},
1327 {"main-10", "main10"},
1328 {"main-10-intra", "main10-intra"},
1329 {"main-422-10", "main422-10"},
1330 {"main-422-10-intra", "main422-10-intra"},
1331 {"main-444-10", "main444-10"},
1332 {"main-444-10-intra", "main444-10-intra"},
1334 {"main-12", "main12"},
1335 {"main-12-intra", "main12-intra"},
1336 {"main-422-12", "main422-12"},
1337 {"main-422-12-intra", "main422-12-intra"},
1338 {"main-444-12", "main444-12"},
1339 {"main-444-12-intra", "main444-12-intra"},
1345 for (i = 0; i < G_N_ELEMENTS (profile_table); i++) {
1346 if (!strcmp (profile, profile_table[i].gst_profile))
1347 return profile_table[i].x265_profile;
1354 gst_x265_enc_set_format (GstVideoEncoder * video_enc,
1355 GstVideoCodecState * state)
1357 GstX265Enc *encoder = GST_X265_ENC (video_enc);
1358 GstVideoInfo *info = &state->info;
1359 GstCaps *template_caps;
1360 GstCaps *allowed_caps = NULL;
1362 /* If the encoder is initialized, do not reinitialize it again if not
1364 if (encoder->x265enc) {
1365 GstVideoInfo *old = &encoder->input_state->info;
1367 if (info->finfo->format == old->finfo->format
1368 && info->width == old->width && info->height == old->height
1369 && info->fps_n == old->fps_n && info->fps_d == old->fps_d
1370 && info->par_n == old->par_n && info->par_d == old->par_d) {
1371 gst_video_codec_state_unref (encoder->input_state);
1372 encoder->input_state = gst_video_codec_state_ref (state);
1376 /* clear out pending frames */
1377 gst_x265_enc_flush_frames (encoder, TRUE);
1380 if (encoder->input_state)
1381 gst_video_codec_state_unref (encoder->input_state);
1382 encoder->input_state = gst_video_codec_state_ref (state);
1384 g_ptr_array_set_size (encoder->peer_profiles, 0);
1386 template_caps = gst_static_pad_template_get_caps (&src_factory);
1387 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1389 GST_DEBUG_OBJECT (encoder, "allowed caps %" GST_PTR_FORMAT, allowed_caps);
1391 /* allowed != template is meaning that downstream has some restriction
1392 * so we need check whether there is requested profile or not */
1393 if (allowed_caps && !gst_caps_is_equal (allowed_caps, template_caps)) {
1396 if (gst_caps_is_empty (allowed_caps)) {
1397 gst_caps_unref (allowed_caps);
1398 gst_caps_unref (template_caps);
1402 for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
1405 const gchar *profile;
1406 const gchar *x265_profile;
1408 s = gst_caps_get_structure (allowed_caps, i);
1410 if ((val = gst_structure_get_value (s, "profile"))) {
1411 if (G_VALUE_HOLDS_STRING (val)) {
1412 profile = g_value_get_string (val);
1413 x265_profile = gst_x265_enc_profile_from_gst (profile);
1416 GST_DEBUG_OBJECT (encoder,
1417 "Add profile %s to peer profile list", x265_profile);
1419 g_ptr_array_add (encoder->peer_profiles, (gpointer) x265_profile);
1421 } else if (GST_VALUE_HOLDS_LIST (val)) {
1422 for (j = 0; j < gst_value_list_get_size (val); j++) {
1423 const GValue *vlist = gst_value_list_get_value (val, j);
1424 profile = g_value_get_string (vlist);
1425 x265_profile = gst_x265_enc_profile_from_gst (profile);
1428 GST_DEBUG_OBJECT (encoder,
1429 "Add profile %s to peer profile list", x265_profile);
1431 g_ptr_array_add (encoder->peer_profiles, (gpointer) x265_profile);
1439 gst_clear_caps (&allowed_caps);
1440 gst_caps_unref (template_caps);
1443 if (!gst_x265_enc_init_encoder (encoder))
1446 if (!gst_x265_enc_set_src_caps (encoder, state->caps)) {
1447 gst_x265_enc_close_encoder (encoder);
1451 gst_x265_enc_set_latency (encoder);
1456 static GstFlowReturn
1457 gst_x265_enc_finish (GstVideoEncoder * encoder)
1459 GST_DEBUG_OBJECT (encoder, "finish encoder");
1461 gst_x265_enc_flush_frames (GST_X265_ENC (encoder), TRUE);
1462 gst_x265_enc_flush_frames (GST_X265_ENC (encoder), TRUE);
1467 gst_x265_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
1469 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1471 return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
1476 * this function does the actual processing
1478 static GstFlowReturn
1479 gst_x265_enc_handle_frame (GstVideoEncoder * video_enc,
1480 GstVideoCodecFrame * frame)
1482 GstX265Enc *encoder = GST_X265_ENC (video_enc);
1483 GstVideoInfo *info = &encoder->input_state->info;
1485 x265_picture pic_in;
1489 const x265_api *api = encoder->api;
1491 g_assert (api != NULL);
1493 if (G_UNLIKELY (encoder->x265enc == NULL))
1496 /* set up input picture */
1497 api->picture_init (&encoder->x265param, &pic_in);
1499 fdata = gst_x265_enc_queue_frame (encoder, frame, info);
1504 gst_x265_enc_gst_to_x265_video_format (info->finfo->format, &nplanes);
1505 for (i = 0; i < nplanes; i++) {
1506 pic_in.planes[i] = GST_VIDEO_FRAME_PLANE_DATA (&fdata->vframe, i);
1507 pic_in.stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (&fdata->vframe, i);
1510 pic_in.sliceType = X265_TYPE_AUTO;
1511 pic_in.pts = frame->pts;
1512 pic_in.dts = frame->dts;
1513 pic_in.bitDepth = info->finfo->depth[0];
1514 pic_in.userData = GINT_TO_POINTER (frame->system_frame_number);
1516 ret = gst_x265_enc_encode_frame (encoder, &pic_in, frame, &i_nal, TRUE);
1518 /* input buffer is released later on */
1524 GST_WARNING_OBJECT (encoder, "Got buffer before set_caps was called");
1525 return GST_FLOW_NOT_NEGOTIATED;
1529 GST_ERROR_OBJECT (encoder, "Failed to map frame");
1530 return GST_FLOW_ERROR;
1534 static GstFlowReturn
1535 gst_x265_enc_encode_frame (GstX265Enc * encoder, x265_picture * pic_in,
1536 GstVideoCodecFrame * input_frame, guint32 * i_nal, gboolean send)
1538 GstVideoCodecFrame *frame = NULL;
1539 GstBuffer *out_buf = NULL;
1540 x265_picture pic_out;
1542 int i_size, i, offset;
1544 GstFlowReturn ret = GST_FLOW_OK;
1545 gboolean update_latency = FALSE;
1546 const x265_api *api;
1548 if (G_UNLIKELY (encoder->x265enc == NULL)) {
1550 gst_video_codec_frame_unref (input_frame);
1551 return GST_FLOW_NOT_NEGOTIATED;
1555 g_assert (api != NULL);
1557 GST_OBJECT_LOCK (encoder);
1558 if (encoder->reconfig) {
1559 /* x265_encoder_reconfig is not yet implemented thus we shut down and re-create encoder */
1560 gst_x265_enc_init_encoder (encoder);
1561 update_latency = TRUE;
1564 if (pic_in && input_frame) {
1565 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (input_frame)) {
1566 GST_INFO_OBJECT (encoder, "Forcing key frame");
1567 pic_in->sliceType = X265_TYPE_IDR;
1570 GST_OBJECT_UNLOCK (encoder);
1572 if (G_UNLIKELY (update_latency))
1573 gst_x265_enc_set_latency (encoder);
1575 encoder_return = api->encoder_encode (encoder->x265enc,
1576 &nal, i_nal, pic_in, &pic_out);
1578 GST_DEBUG_OBJECT (encoder, "encoder result (%d) with %u nal units",
1579 encoder_return, *i_nal);
1581 if (encoder_return < 0) {
1582 GST_ELEMENT_ERROR (encoder, STREAM, ENCODE, ("Encode x265 frame failed."),
1583 ("x265_encoder_encode return code=%d", encoder_return));
1584 ret = GST_FLOW_ERROR;
1585 /* Make sure we finish this frame */
1586 frame = input_frame;
1590 /* Input frame is now queued */
1592 gst_video_codec_frame_unref (input_frame);
1596 GST_LOG_OBJECT (encoder, "no output yet");
1600 frame = gst_video_encoder_get_frame (GST_VIDEO_ENCODER (encoder),
1601 GPOINTER_TO_INT (pic_out.userData));
1602 g_assert (frame || !send);
1604 GST_DEBUG_OBJECT (encoder,
1605 "output picture ready POC=%d system=%d frame found %d", pic_out.poc,
1606 GPOINTER_TO_INT (pic_out.userData), frame != NULL);
1608 if (!send || !frame) {
1609 GST_LOG_OBJECT (encoder, "not sending (%d) or frame not found (%d)", send,
1617 for (i = 0; i < *i_nal; i++)
1618 i_size += nal[i].sizeBytes;
1619 out_buf = gst_buffer_new_allocate (NULL, i_size, NULL);
1620 for (i = 0; i < *i_nal; i++) {
1621 gst_buffer_fill (out_buf, offset, nal[i].payload, nal[i].sizeBytes);
1622 offset += nal[i].sizeBytes;
1625 if (pic_out.sliceType == X265_TYPE_IDR || pic_out.sliceType == X265_TYPE_I) {
1626 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
1629 frame->output_buffer = out_buf;
1631 if (encoder->push_header) {
1634 header = gst_x265_enc_get_header_buffer (encoder);
1635 frame->output_buffer = gst_buffer_append (header, frame->output_buffer);
1636 encoder->push_header = FALSE;
1639 GST_LOG_OBJECT (encoder,
1640 "output: dts %" G_GINT64_FORMAT " pts %" G_GINT64_FORMAT,
1641 (gint64) pic_out.dts, (gint64) pic_out.pts);
1643 frame->dts = pic_out.dts + encoder->dts_offset;
1647 gst_x265_enc_dequeue_frame (encoder, frame);
1648 ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (encoder), frame);
1655 gst_x265_enc_flush_frames (GstX265Enc * encoder, gboolean send)
1657 GstFlowReturn flow_ret;
1660 /* first send the remaining frames */
1661 if (encoder->x265enc)
1663 flow_ret = gst_x265_enc_encode_frame (encoder, NULL, NULL, &i_nal, send);
1664 } while (flow_ret == GST_FLOW_OK && i_nal > 0);
1668 gst_x265_enc_reconfig (GstX265Enc * encoder)
1670 encoder->x265param.rc.bitrate = encoder->bitrate;
1671 encoder->reconfig = TRUE;
1675 gst_x265_enc_set_property (GObject * object, guint prop_id,
1676 const GValue * value, GParamSpec * pspec)
1678 GstX265Enc *encoder;
1681 encoder = GST_X265_ENC (object);
1683 GST_OBJECT_LOCK (encoder);
1685 state = GST_STATE (encoder);
1686 if ((state != GST_STATE_READY && state != GST_STATE_NULL) &&
1687 !(pspec->flags & GST_PARAM_MUTABLE_PLAYING))
1692 encoder->bitrate = g_value_get_uint (value);
1695 encoder->qp = g_value_get_int (value);
1697 case PROP_OPTION_STRING:
1698 g_string_assign (encoder->option_string_prop, g_value_get_string (value));
1700 case PROP_X265_LOG_LEVEL:
1701 encoder->log_level = g_value_get_enum (value);
1703 case PROP_SPEED_PRESET:
1704 encoder->speed_preset = g_value_get_enum (value);
1707 encoder->tune = g_value_get_enum (value);
1709 case PROP_KEY_INT_MAX:
1710 encoder->keyintmax = g_value_get_int (value);
1713 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1717 gst_x265_enc_reconfig (encoder);
1718 GST_OBJECT_UNLOCK (encoder);
1723 GST_WARNING_OBJECT (encoder, "setting property in wrong state");
1724 GST_OBJECT_UNLOCK (encoder);
1729 gst_x265_enc_get_property (GObject * object, guint prop_id,
1730 GValue * value, GParamSpec * pspec)
1732 GstX265Enc *encoder;
1734 encoder = GST_X265_ENC (object);
1736 GST_OBJECT_LOCK (encoder);
1739 g_value_set_uint (value, encoder->bitrate);
1742 g_value_set_int (value, encoder->qp);
1744 case PROP_OPTION_STRING:
1745 g_value_set_string (value, encoder->option_string_prop->str);
1747 case PROP_X265_LOG_LEVEL:
1748 g_value_set_enum (value, encoder->log_level);
1750 case PROP_SPEED_PRESET:
1751 g_value_set_enum (value, encoder->speed_preset);
1754 g_value_set_enum (value, encoder->tune);
1756 case PROP_KEY_INT_MAX:
1757 g_value_set_int (value, encoder->keyintmax);
1760 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1763 GST_OBJECT_UNLOCK (encoder);
1767 plugin_init (GstPlugin * plugin)
1769 GST_DEBUG_CATEGORY_INIT (x265_enc_debug, "x265enc", 0,
1770 "h265 encoding element");
1772 GST_INFO ("x265 build: %u", X265_BUILD);
1774 default_vtable = *x265_api_get (0);
1776 GST_INFO ("x265 default bitdepth: %u", default_vtable.bit_depth);
1778 switch (default_vtable.bit_depth) {
1780 vtable_8bit = &default_vtable;
1783 vtable_10bit = &default_vtable;
1786 vtable_12bit = &default_vtable;
1789 GST_WARNING ("Unknown default bitdepth %d", default_vtable.bit_depth);
1793 if (!vtable_8bit && (vtable_8bit = x265_api_get (8)))
1794 GST_INFO ("x265 8bit api available");
1796 if (!vtable_10bit && (vtable_10bit = x265_api_get (10)))
1797 GST_INFO ("x265 10bit api available");
1799 #if (X265_BUILD >= 68)
1800 if (!vtable_12bit && (vtable_12bit = x265_api_get (12)))
1801 GST_INFO ("x265 12bit api available");
1804 return gst_element_register (plugin, "x265enc",
1805 GST_RANK_PRIMARY, GST_TYPE_X265_ENC);
1808 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1811 "x265-based H265 plugins",
1812 plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)