openh264enc: Fix constrained-high encoding
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / ext / openh264 / gstopenh264enc.cpp
1 /*
2  * Copyright (c) 2014, Ericsson AB. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this
11  * list of conditions and the following disclaimer in the documentation and/or other
12  * materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23  * OF SUCH DAMAGE.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "gstopenh264elements.h"
31 #include "gstopenh264enc.h"
32
33 #include <gst/pbutils/pbutils.h>
34 #include <gst/gst.h>
35 #include <gst/base/base.h>
36 #include <gst/video/video.h>
37 #include <gst/video/gstvideoencoder.h>
38 #include <string.h>
39
40 GST_DEBUG_CATEGORY_STATIC (gst_openh264enc_debug_category);
41 #define GST_CAT_DEFAULT gst_openh264enc_debug_category
42
43 /* FIXME: we should not really directly use the enums from the openh264 API
44  * here, since it might change or be removed */
45 #define GST_TYPE_USAGE_TYPE (gst_openh264enc_usage_type_get_type ())
46 static GType
47 gst_openh264enc_usage_type_get_type (void)
48 {
49   static GType usage_type = 0;
50
51   if (!usage_type) {
52     static const GEnumValue usage_types[] = {
53       {CAMERA_VIDEO_REAL_TIME, "video from camera", "camera"},
54       {SCREEN_CONTENT_REAL_TIME, "screen content", "screen"},
55       {0, NULL, NULL},
56     };
57
58     usage_type = g_enum_register_static ("EUsageType", usage_types);
59   }
60
61   return usage_type;
62 }
63
64 #define GST_TYPE_RC_MODES (gst_openh264enc_rc_modes_get_type ())
65 static GType
66 gst_openh264enc_rc_modes_get_type (void)
67 {
68   static GType rc_modes_type = 0;
69
70   if (!rc_modes_type) {
71     static const GEnumValue rc_modes_types[] = {
72       {RC_QUALITY_MODE, "Quality mode", "quality"},
73       {RC_BITRATE_MODE, "Bitrate mode", "bitrate"},
74       {RC_BUFFERBASED_MODE, "No bitrate control, just using buffer status",
75           "buffer"},
76       {RC_OFF_MODE, "Rate control off mode", "off"},
77       {0, NULL, NULL},
78     };
79
80     rc_modes_type = g_enum_register_static ("RC_MODES", rc_modes_types);
81   }
82
83   return rc_modes_type;
84 }
85
86 #define GST_TYPE_OPENH264ENC_DEBLOCKING_MODE (gst_openh264enc_deblocking_mode_get_type ())
87 static GType
88 gst_openh264enc_deblocking_mode_get_type (void)
89 {
90   static const GEnumValue types[] = {
91     {GST_OPENH264_DEBLOCKING_ON, "Deblocking on", "on"},
92     {GST_OPENH264_DEBLOCKING_OFF, "Deblocking off", "off"},
93     {GST_OPENH264_DEBLOCKING_NOT_SLICE_BOUNDARIES,
94         "Deblocking on, except for slice boundaries", "not-slice-boundaries"},
95     {0, NULL, NULL},
96   };
97   static gsize id = 0;
98
99   if (g_once_init_enter (&id)) {
100     GType _id = g_enum_register_static ("GstOpenh264encDeblockingModes", types);
101     g_once_init_leave (&id, _id);
102   }
103
104   return (GType) id;
105 }
106
107 #define GST_TYPE_OPENH264ENC_SLICE_MODE (gst_openh264enc_slice_mode_get_type ())
108 static GType
109 gst_openh264enc_slice_mode_get_type (void)
110 {
111   static const GEnumValue types[] = {
112     {GST_OPENH264_SLICE_MODE_N_SLICES, "Fixed number of slices", "n-slices"},
113     {GST_OPENH264_SLICE_MODE_AUTO,
114         "Number of slices equal to number of threads", "auto"},
115     {0, NULL, NULL},
116   };
117   static gsize id = 0;
118
119   if (g_once_init_enter (&id)) {
120     GType _id = g_enum_register_static ("GstOpenh264EncSliceModes", types);
121     g_once_init_leave (&id, _id);
122   }
123
124   return (GType) id;
125 }
126
127 #define GST_TYPE_OPENH264ENC_COMPLEXITY (gst_openh264enc_complexity_get_type ())
128 static GType
129 gst_openh264enc_complexity_get_type (void)
130 {
131   static const GEnumValue types[] = {
132     {LOW_COMPLEXITY, "Low complexity / high speed encoding", "low"},
133     {MEDIUM_COMPLEXITY, "Medium complexity / medium speed encoding", "medium"},
134     {HIGH_COMPLEXITY, "High complexity / low speed encoding", "high"},
135     {0, NULL, NULL},
136   };
137   static gsize id = 0;
138
139   if (g_once_init_enter (&id)) {
140     GType _id = g_enum_register_static ("GstOpenh264encComplexity", types);
141     g_once_init_leave (&id, _id);
142   }
143
144   return (GType) id;
145 }
146
147 /* prototypes */
148
149 static void gst_openh264enc_set_property (GObject * object,
150     guint property_id, const GValue * value, GParamSpec * pspec);
151 static void gst_openh264enc_get_property (GObject * object,
152     guint property_id, GValue * value, GParamSpec * pspec);
153 static void gst_openh264enc_finalize (GObject * object);
154 static gboolean gst_openh264enc_start (GstVideoEncoder * encoder);
155 static gboolean gst_openh264enc_stop (GstVideoEncoder * encoder);
156 static gboolean gst_openh264enc_set_format (GstVideoEncoder * encoder,
157     GstVideoCodecState * state);
158 static GstFlowReturn gst_openh264enc_handle_frame (GstVideoEncoder * encoder,
159     GstVideoCodecFrame * frame);
160 static GstFlowReturn gst_openh264enc_finish (GstVideoEncoder * encoder);
161 static gboolean gst_openh264enc_propose_allocation (GstVideoEncoder * encoder,
162     GstQuery * query);
163 static void gst_openh264enc_set_usage_type (GstOpenh264Enc * openh264enc,
164     gint usage_type);
165 static void gst_openh264enc_set_rate_control (GstOpenh264Enc * openh264enc,
166     gint rc_mode);
167 static gboolean openh264enc_element_init (GstPlugin * plugin);
168
169
170 #define DEFAULT_BITRATE            (128000)
171 #define DEFAULT_MAX_BITRATE        (UNSPECIFIED_BIT_RATE)
172 #define DEFAULT_GOP_SIZE           (90)
173 #define DEFAULT_MAX_SLICE_SIZE     (1500000)
174 #define START_FRAMERATE            30
175 #define DEFAULT_USAGE_TYPE         CAMERA_VIDEO_REAL_TIME
176 #define DEFAULT_RATE_CONTROL       RC_QUALITY_MODE
177 #define DEFAULT_MULTI_THREAD       0
178 #define DEFAULT_ENABLE_DENOISE     FALSE
179 #define DEFAULT_ENABLE_FRAME_SKIP  FALSE
180 #define DEFAULT_DEBLOCKING_MODE GST_OPENH264_DEBLOCKING_ON
181 #define DEFAULT_BACKGROUND_DETECTION TRUE
182 #define DEFAULT_ADAPTIVE_QUANTIZATION TRUE
183 #define DEFAULT_SCENE_CHANGE_DETECTION TRUE
184 #define DEFAULT_SLICE_MODE      GST_OPENH264_SLICE_MODE_N_SLICES
185 #define DEFAULT_NUM_SLICES      1
186 #define DEFAULT_COMPLEXITY      MEDIUM_COMPLEXITY
187 #define DEFAULT_QP_MIN             0
188 #define DEFAULT_QP_MAX             51
189
190 enum
191 {
192   PROP_0,
193   PROP_USAGE_TYPE,
194   PROP_BITRATE,
195   PROP_MAX_BITRATE,
196   PROP_GOP_SIZE,
197   PROP_MAX_SLICE_SIZE,
198   PROP_RATE_CONTROL,
199   PROP_MULTI_THREAD,
200   PROP_ENABLE_DENOISE,
201   PROP_ENABLE_FRAME_SKIP,
202   PROP_DEBLOCKING_MODE,
203   PROP_BACKGROUND_DETECTION,
204   PROP_ADAPTIVE_QUANTIZATION,
205   PROP_SCENE_CHANGE_DETECTION,
206   PROP_SLICE_MODE,
207   PROP_NUM_SLICES,
208   PROP_COMPLEXITY,
209   PROP_QP_MIN,
210   PROP_QP_MAX,
211   N_PROPERTIES
212 };
213
214 /* pad templates */
215
216 static GstStaticPadTemplate gst_openh264enc_sink_template =
217 GST_STATIC_PAD_TEMPLATE ("sink",
218     GST_PAD_SINK,
219     GST_PAD_ALWAYS,
220     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
221     );
222
223 static GstStaticPadTemplate gst_openh264enc_src_template =
224 GST_STATIC_PAD_TEMPLATE ("src",
225     GST_PAD_SRC,
226     GST_PAD_ALWAYS,
227     GST_STATIC_CAPS
228     ("video/x-h264, "
229       "stream-format=(string)\"byte-stream\", alignment=(string)\"au\","
230       "profile = (string) { constrained-baseline, baseline, main, constrained-high, high }"
231     )
232 );
233
234 /* class initialization */
235
236 G_DEFINE_TYPE_WITH_CODE (GstOpenh264Enc, gst_openh264enc,
237     GST_TYPE_VIDEO_ENCODER,
238     G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL);
239     GST_DEBUG_CATEGORY_INIT (gst_openh264enc_debug_category, "openh264enc", 0,
240         "debug category for openh264enc element"));
241 GST_ELEMENT_REGISTER_DEFINE_CUSTOM (openh264enc, openh264enc_element_init);
242
243 static void
244 gst_openh264enc_class_init (GstOpenh264EncClass * klass)
245 {
246   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
247   GstVideoEncoderClass *video_encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
248
249   /* Setting up pads and setting metadata should be moved to
250      base_class_init if you intend to subclass this class. */
251   gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
252       &gst_openh264enc_src_template);
253   gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
254       &gst_openh264enc_sink_template);
255
256   gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
257       "OpenH264 video encoder", "Encoder/Video", "OpenH264 video encoder",
258       "Ericsson AB, http://www.ericsson.com");
259
260   gobject_class->set_property = gst_openh264enc_set_property;
261   gobject_class->get_property = gst_openh264enc_get_property;
262   gobject_class->finalize = gst_openh264enc_finalize;
263   video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_openh264enc_start);
264   video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_openh264enc_stop);
265   video_encoder_class->set_format =
266       GST_DEBUG_FUNCPTR (gst_openh264enc_set_format);
267   video_encoder_class->handle_frame =
268       GST_DEBUG_FUNCPTR (gst_openh264enc_handle_frame);
269   video_encoder_class->propose_allocation =
270       GST_DEBUG_FUNCPTR (gst_openh264enc_propose_allocation);
271   video_encoder_class->finish = GST_DEBUG_FUNCPTR (gst_openh264enc_finish);
272
273   /* define properties */
274   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_USAGE_TYPE,
275       g_param_spec_enum ("usage-type", "Usage type",
276           "Type of video content",
277           GST_TYPE_USAGE_TYPE, CAMERA_VIDEO_REAL_TIME,
278           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
279
280   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_RATE_CONTROL,
281       g_param_spec_enum ("rate-control", "Rate control",
282           "Rate control mode",
283           GST_TYPE_RC_MODES, RC_QUALITY_MODE,
284           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
285
286   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MULTI_THREAD,
287       g_param_spec_uint ("multi-thread", "Number of threads",
288           "The number of threads.",
289           0, G_MAXUINT, DEFAULT_MULTI_THREAD,
290           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
291
292   g_object_class_install_property (gobject_class, PROP_ENABLE_DENOISE,
293       g_param_spec_boolean ("enable-denoise", "Denoise Control",
294           "Denoise control",
295           FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
296
297   g_object_class_install_property (gobject_class, PROP_ENABLE_FRAME_SKIP,
298       g_param_spec_boolean ("enable-frame-skip", "Skip Frames",
299           "Skip frames to reach target bitrate",
300           FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
301
302   g_object_class_install_property (gobject_class, PROP_BITRATE,
303       g_param_spec_uint ("bitrate", "Bitrate",
304           "Bitrate (in bits per second)",
305           0, G_MAXUINT, DEFAULT_BITRATE,
306           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
307               GST_PARAM_MUTABLE_PLAYING)));
308
309   g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
310       g_param_spec_uint ("max-bitrate", "Max Bitrate",
311           "Maximum Bitrate (in bits per second)",
312           0, G_MAXUINT, DEFAULT_MAX_BITRATE,
313           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
314               GST_PARAM_MUTABLE_PLAYING)));
315
316   g_object_class_install_property (gobject_class, PROP_QP_MIN,
317       g_param_spec_uint ("qp-min", "Minimum Quantizer",
318           "Minimum quantizer", 0, 51, DEFAULT_QP_MIN,
319           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
320
321   g_object_class_install_property (gobject_class, PROP_QP_MAX,
322       g_param_spec_uint ("qp-max", "Maximum Quantizer",
323           "Maximum quantizer", 0, 51, DEFAULT_QP_MAX,
324           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
325
326   g_object_class_install_property (gobject_class, PROP_GOP_SIZE,
327       g_param_spec_uint ("gop-size", "GOP size",
328           "Number of frames between intra frames",
329           0, G_MAXUINT, DEFAULT_GOP_SIZE,
330           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
331
332   g_object_class_install_property (gobject_class, PROP_MAX_SLICE_SIZE,
333       g_param_spec_uint ("max-slice-size", "Max slice size",
334           "The maximum size of one slice (in bytes).",
335           0, G_MAXUINT, DEFAULT_MAX_SLICE_SIZE,
336           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
337
338   g_object_class_install_property (G_OBJECT_CLASS (klass),
339       PROP_DEBLOCKING_MODE, g_param_spec_enum ("deblocking",
340           "Deblocking mode", "Deblocking mode",
341           GST_TYPE_OPENH264ENC_DEBLOCKING_MODE, DEFAULT_DEBLOCKING_MODE,
342           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
343
344   g_object_class_install_property (gobject_class, PROP_BACKGROUND_DETECTION,
345       g_param_spec_boolean ("background-detection", "Background detection",
346           "Background detection", DEFAULT_BACKGROUND_DETECTION,
347           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
348
349   g_object_class_install_property (gobject_class, PROP_ADAPTIVE_QUANTIZATION,
350       g_param_spec_boolean ("adaptive-quantization", "Adaptive quantization",
351           "Adaptive quantization", DEFAULT_ADAPTIVE_QUANTIZATION,
352           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
353
354   g_object_class_install_property (gobject_class, PROP_SCENE_CHANGE_DETECTION,
355       g_param_spec_boolean ("scene-change-detection",
356           "Scene change detection", "Scene change detection",
357           DEFAULT_SCENE_CHANGE_DETECTION,
358           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
359
360   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLICE_MODE,
361       g_param_spec_enum ("slice-mode", "Slice mode", "Slice mode",
362           GST_TYPE_OPENH264ENC_SLICE_MODE, DEFAULT_SLICE_MODE,
363           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
364
365   g_object_class_install_property (gobject_class, PROP_NUM_SLICES,
366       g_param_spec_uint ("num-slices", "Number of slices",
367           "The number of slices (needs slice-mode=n-slices)",
368           0, G_MAXUINT, DEFAULT_NUM_SLICES,
369           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
370
371   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLEXITY,
372       g_param_spec_enum ("complexity", "Complexity / quality / speed tradeoff",
373           "Complexity", GST_TYPE_OPENH264ENC_COMPLEXITY, DEFAULT_COMPLEXITY,
374           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
375
376   gst_type_mark_as_plugin_api (GST_TYPE_OPENH264ENC_COMPLEXITY, (GstPluginAPIFlags) 0);
377   gst_type_mark_as_plugin_api (GST_TYPE_OPENH264ENC_DEBLOCKING_MODE, (GstPluginAPIFlags) 0);
378   gst_type_mark_as_plugin_api (GST_TYPE_OPENH264ENC_SLICE_MODE, (GstPluginAPIFlags) 0);
379   gst_type_mark_as_plugin_api (GST_TYPE_RC_MODES, (GstPluginAPIFlags) 0);
380   gst_type_mark_as_plugin_api (GST_TYPE_USAGE_TYPE, (GstPluginAPIFlags) 0);
381 }
382
383 static void
384 gst_openh264enc_init (GstOpenh264Enc * openh264enc)
385 {
386   openh264enc->gop_size = DEFAULT_GOP_SIZE;
387   openh264enc->usage_type = DEFAULT_USAGE_TYPE;
388   openh264enc->rate_control = DEFAULT_RATE_CONTROL;
389   openh264enc->multi_thread = DEFAULT_MULTI_THREAD;
390   openh264enc->max_slice_size = DEFAULT_MAX_SLICE_SIZE;
391   openh264enc->bitrate = DEFAULT_BITRATE;
392   openh264enc->max_bitrate = DEFAULT_MAX_BITRATE;
393   openh264enc->qp_min = DEFAULT_QP_MIN;
394   openh264enc->qp_max = DEFAULT_QP_MAX;
395   openh264enc->framerate = START_FRAMERATE;
396   openh264enc->input_state = NULL;
397   openh264enc->time_per_frame = GST_SECOND / openh264enc->framerate;
398   openh264enc->frame_count = 0;
399   openh264enc->previous_timestamp = 0;
400   openh264enc->enable_denoise = DEFAULT_ENABLE_DENOISE;
401   openh264enc->enable_frame_skip = DEFAULT_ENABLE_FRAME_SKIP;
402   openh264enc->deblocking_mode = DEFAULT_DEBLOCKING_MODE;
403   openh264enc->background_detection = DEFAULT_BACKGROUND_DETECTION;
404   openh264enc->adaptive_quantization = DEFAULT_ADAPTIVE_QUANTIZATION;
405   openh264enc->scene_change_detection = DEFAULT_SCENE_CHANGE_DETECTION;
406   openh264enc->slice_mode = DEFAULT_SLICE_MODE;
407   openh264enc->num_slices = DEFAULT_NUM_SLICES;
408   openh264enc->encoder = NULL;
409   openh264enc->complexity = DEFAULT_COMPLEXITY;
410   openh264enc->bitrate_changed = FALSE;
411   openh264enc->max_bitrate_changed = FALSE;
412   gst_openh264enc_set_usage_type (openh264enc, CAMERA_VIDEO_REAL_TIME);
413   gst_openh264enc_set_rate_control (openh264enc, RC_QUALITY_MODE);
414 }
415
416 static void
417 gst_openh264enc_set_usage_type (GstOpenh264Enc * openh264enc, gint usage_type)
418 {
419   switch (usage_type) {
420     case CAMERA_VIDEO_REAL_TIME:
421       openh264enc->usage_type = CAMERA_VIDEO_REAL_TIME;
422       break;
423     case SCREEN_CONTENT_REAL_TIME:
424       openh264enc->usage_type = SCREEN_CONTENT_REAL_TIME;
425       break;
426     default:
427       g_assert_not_reached ();
428   }
429 }
430
431 static void
432 gst_openh264enc_set_rate_control (GstOpenh264Enc * openh264enc, gint rc_mode)
433 {
434   switch (rc_mode) {
435     case RC_QUALITY_MODE:
436       openh264enc->rate_control = RC_QUALITY_MODE;
437       break;
438     case RC_BITRATE_MODE:
439       openh264enc->rate_control = RC_BITRATE_MODE;
440       break;
441     case RC_BUFFERBASED_MODE:
442       openh264enc->rate_control = RC_BUFFERBASED_MODE;
443       break;
444     case RC_OFF_MODE:
445       openh264enc->rate_control = RC_OFF_MODE;
446       break;
447     default:
448       g_assert_not_reached ();
449   }
450 }
451
452 void
453 gst_openh264enc_set_property (GObject * object, guint property_id,
454     const GValue * value, GParamSpec * pspec)
455 {
456   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (object);
457
458   GST_DEBUG_OBJECT (openh264enc, "set_property");
459
460   switch (property_id) {
461     case PROP_BITRATE:
462       GST_OBJECT_LOCK (openh264enc);
463       if (openh264enc->bitrate != g_value_get_uint (value)) {
464         openh264enc->bitrate = g_value_get_uint (value);
465         openh264enc->bitrate_changed = TRUE;
466       }
467       GST_OBJECT_UNLOCK (openh264enc);
468       break;
469
470     case PROP_MAX_BITRATE:
471       GST_OBJECT_LOCK (openh264enc);
472       if (openh264enc->max_bitrate != g_value_get_uint (value)) {
473         openh264enc->max_bitrate = g_value_get_uint (value);
474         openh264enc->max_bitrate_changed = TRUE;
475       }
476       GST_OBJECT_UNLOCK (openh264enc);
477       break;
478
479     case PROP_QP_MIN:
480       openh264enc->qp_min = g_value_get_uint (value);
481       break;
482
483     case PROP_QP_MAX:
484       openh264enc->qp_max = g_value_get_uint (value);
485       break;
486
487     case PROP_MULTI_THREAD:
488       openh264enc->multi_thread = g_value_get_uint (value);
489       break;
490
491     case PROP_USAGE_TYPE:
492       gst_openh264enc_set_usage_type (openh264enc, g_value_get_enum (value));
493       break;
494
495     case PROP_ENABLE_DENOISE:
496       openh264enc->enable_denoise = g_value_get_boolean (value);
497       break;
498
499     case PROP_ENABLE_FRAME_SKIP:
500       openh264enc->enable_frame_skip = g_value_get_boolean (value);
501       break;
502
503     case PROP_RATE_CONTROL:
504       gst_openh264enc_set_rate_control (openh264enc, g_value_get_enum (value));
505       break;
506
507     case PROP_GOP_SIZE:
508       openh264enc->gop_size = g_value_get_uint (value);
509       break;
510
511     case PROP_MAX_SLICE_SIZE:
512       openh264enc->max_slice_size = g_value_get_uint (value);
513       break;
514
515     case PROP_DEBLOCKING_MODE:
516       openh264enc->deblocking_mode =
517           (GstOpenh264encDeblockingMode) g_value_get_enum (value);
518       break;
519
520     case PROP_BACKGROUND_DETECTION:
521       openh264enc->background_detection = g_value_get_boolean (value);
522       break;
523
524     case PROP_ADAPTIVE_QUANTIZATION:
525       openh264enc->adaptive_quantization = g_value_get_boolean (value);
526       break;
527
528     case PROP_SCENE_CHANGE_DETECTION:
529       openh264enc->scene_change_detection = g_value_get_boolean (value);
530       break;
531
532     case PROP_SLICE_MODE:
533       openh264enc->slice_mode =
534           (GstOpenh264EncSliceMode) g_value_get_enum (value);
535       break;
536
537     case PROP_NUM_SLICES:
538       openh264enc->num_slices = g_value_get_uint (value);
539       break;
540
541     case PROP_COMPLEXITY:
542       openh264enc->complexity = (ECOMPLEXITY_MODE) g_value_get_enum (value);
543       break;
544
545     default:
546       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
547       break;
548   }
549 }
550
551 void
552 gst_openh264enc_get_property (GObject * object, guint property_id,
553     GValue * value, GParamSpec * pspec)
554 {
555   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (object);
556
557   GST_DEBUG_OBJECT (openh264enc, "get_property");
558
559   switch (property_id) {
560     case PROP_USAGE_TYPE:
561       g_value_set_enum (value, openh264enc->usage_type);
562       break;
563
564     case PROP_RATE_CONTROL:
565       g_value_set_enum (value, openh264enc->rate_control);
566       break;
567
568     case PROP_BITRATE:
569       g_value_set_uint (value, openh264enc->bitrate);
570       break;
571
572     case PROP_MAX_BITRATE:
573       g_value_set_uint (value, openh264enc->max_bitrate);
574       break;
575
576     case PROP_QP_MIN:
577       g_value_set_uint (value, openh264enc->qp_min);
578       break;
579
580     case PROP_QP_MAX:
581       g_value_set_uint (value, openh264enc->qp_max);
582       break;
583
584     case PROP_ENABLE_DENOISE:
585       g_value_set_boolean (value, openh264enc->enable_denoise);
586       break;
587
588     case PROP_ENABLE_FRAME_SKIP:
589       g_value_set_boolean (value, openh264enc->enable_frame_skip);
590       break;
591
592     case PROP_MULTI_THREAD:
593       g_value_set_uint (value, openh264enc->multi_thread);
594       break;
595
596     case PROP_GOP_SIZE:
597       g_value_set_uint (value, openh264enc->gop_size);
598       break;
599
600     case PROP_MAX_SLICE_SIZE:
601       g_value_set_uint (value, openh264enc->max_slice_size);
602       break;
603
604     case PROP_DEBLOCKING_MODE:
605       g_value_set_enum (value, openh264enc->deblocking_mode);
606       break;
607
608     case PROP_BACKGROUND_DETECTION:
609       g_value_set_boolean (value, openh264enc->background_detection);
610       break;
611
612     case PROP_ADAPTIVE_QUANTIZATION:
613       g_value_set_boolean (value, openh264enc->adaptive_quantization);
614       break;
615
616     case PROP_SCENE_CHANGE_DETECTION:
617       g_value_set_boolean (value, openh264enc->scene_change_detection);
618       break;
619
620     case PROP_SLICE_MODE:
621       g_value_set_enum (value, openh264enc->slice_mode);
622       break;
623
624     case PROP_NUM_SLICES:
625       g_value_set_uint (value, openh264enc->num_slices);
626       break;
627
628     case PROP_COMPLEXITY:
629       g_value_set_enum (value, openh264enc->complexity);
630       break;
631
632     default:
633       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
634       break;
635   }
636 }
637
638 void
639 gst_openh264enc_finalize (GObject * object)
640 {
641   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (object);
642
643   GST_DEBUG_OBJECT (openh264enc, "finalize");
644
645   /* clean up object here */
646
647   if (openh264enc->input_state) {
648     gst_video_codec_state_unref (openh264enc->input_state);
649   }
650   openh264enc->input_state = NULL;
651
652   G_OBJECT_CLASS (gst_openh264enc_parent_class)->finalize (object);
653 }
654
655 static gboolean
656 gst_openh264enc_start (GstVideoEncoder * encoder)
657 {
658   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
659   GST_DEBUG_OBJECT (openh264enc, "start");
660
661   return TRUE;
662 }
663
664 static gboolean
665 gst_openh264enc_stop (GstVideoEncoder * encoder)
666 {
667   GstOpenh264Enc *openh264enc;
668
669   openh264enc = GST_OPENH264ENC (encoder);
670
671   if (openh264enc->encoder != NULL) {
672     openh264enc->encoder->Uninitialize ();
673     WelsDestroySVCEncoder (openh264enc->encoder);
674     openh264enc->encoder = NULL;
675   }
676   openh264enc->encoder = NULL;
677
678   if (openh264enc->input_state) {
679     gst_video_codec_state_unref (openh264enc->input_state);
680   }
681   openh264enc->input_state = NULL;
682
683   GST_DEBUG_OBJECT (openh264enc, "openh264_enc_stop called");
684
685   return TRUE;
686 }
687
688 static guint8
689 gst_openh264enc_get_level_from_caps (GstCaps *outcaps, GstCaps *allowed_caps)
690 {
691   GstStructure *s = gst_caps_get_structure (outcaps, 0);
692   const gchar * level = gst_structure_get_string (gst_caps_get_structure (allowed_caps, 0), "level");
693
694   if (!level)
695     return LEVEL_UNKNOWN;
696
697   gst_structure_set (s, "level", G_TYPE_STRING, level, NULL);
698   return gst_codec_utils_h264_get_level_idc (level);
699 }
700
701 static EProfileIdc
702 gst_openh264enc_get_profile_from_caps (GstCaps *outcaps, GstCaps *allowed_caps)
703 {
704   EProfileIdc oh264_profile = PRO_BASELINE;
705   GstStructure *allowed_s = gst_caps_get_structure (allowed_caps, 0);
706   GstStructure *s = gst_caps_get_structure (outcaps, 0);
707   const gchar *profile = gst_structure_get_string (allowed_s, "profile");
708
709   if (!profile)
710     return oh264_profile;
711
712   gst_structure_set (s, "profile", G_TYPE_STRING, profile, NULL);
713   if (!g_strcmp0 (profile, "constrained-baseline") ||
714       !g_strcmp0 (profile, "baseline"))
715     return PRO_BASELINE;
716   else if (!g_strcmp0 (profile, "main"))
717     return PRO_MAIN;
718   else if (!g_strcmp0 (profile, "high") ||
719       !g_strcmp0 (profile, "constrained-high"))
720     return PRO_HIGH;
721
722   g_assert_not_reached ();
723   return PRO_BASELINE;
724 }
725
726 static gboolean
727 gst_openh264enc_set_format (GstVideoEncoder * encoder,
728     GstVideoCodecState * state)
729 {
730   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
731   gchar *debug_caps;
732   guint width, height, fps_n, fps_d;
733   SEncParamExt enc_params;
734   SliceModeEnum slice_mode = SM_SINGLE_SLICE;
735   guint n_slices = 1;
736   gint ret;
737   GstCaps *outcaps;
738   GstVideoCodecState *output_state;
739   openh264enc->frame_count = 0;
740   int video_format = videoFormatI420;
741   GstCaps *allowed_caps = NULL;
742
743   debug_caps = gst_caps_to_string (state->caps);
744   GST_DEBUG_OBJECT (openh264enc, "gst_e26d4_enc_set_format called, caps: %s",
745       debug_caps);
746   g_free (debug_caps);
747
748   gst_openh264enc_stop (encoder);
749
750   if (openh264enc->input_state) {
751     gst_video_codec_state_unref (openh264enc->input_state);
752   }
753   openh264enc->input_state = gst_video_codec_state_ref (state);
754
755   width = GST_VIDEO_INFO_WIDTH (&state->info);
756   height = GST_VIDEO_INFO_HEIGHT (&state->info);
757   fps_n = GST_VIDEO_INFO_FPS_N (&state->info);
758   fps_d = GST_VIDEO_INFO_FPS_D (&state->info);
759
760   if (openh264enc->encoder != NULL) {
761     openh264enc->encoder->Uninitialize ();
762     WelsDestroySVCEncoder (openh264enc->encoder);
763     openh264enc->encoder = NULL;
764   }
765   WelsCreateSVCEncoder (&openh264enc->encoder);
766   unsigned int uiTraceLevel = WELS_LOG_ERROR;
767   openh264enc->encoder->SetOption (ENCODER_OPTION_TRACE_LEVEL, &uiTraceLevel);
768
769   outcaps = gst_static_pad_template_get_caps (&gst_openh264enc_src_template);
770   outcaps = gst_caps_make_writable (outcaps);
771   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
772   allowed_caps = gst_caps_make_writable (allowed_caps);
773   allowed_caps = gst_caps_fixate (allowed_caps);
774
775   GST_OBJECT_LOCK (openh264enc);
776
777   openh264enc->encoder->GetDefaultParams (&enc_params);
778
779   enc_params.iUsageType = openh264enc->usage_type;
780   enc_params.iPicWidth = width;
781   enc_params.iPicHeight = height;
782   enc_params.iTargetBitrate = openh264enc->bitrate;
783   enc_params.iMaxBitrate = openh264enc->max_bitrate;
784   enc_params.iMaxQp = openh264enc->qp_max;
785   enc_params.iMinQp = openh264enc->qp_min;
786   enc_params.iRCMode = openh264enc->rate_control;
787   enc_params.iTemporalLayerNum = 1;
788   enc_params.iSpatialLayerNum = 1;
789   enc_params.iLtrMarkPeriod = 30;
790   enc_params.iMultipleThreadIdc = openh264enc->multi_thread;
791   enc_params.bEnableDenoise = openh264enc->enable_denoise;
792   enc_params.iComplexityMode = openh264enc->complexity;
793   enc_params.uiIntraPeriod = openh264enc->gop_size;
794   enc_params.bEnableBackgroundDetection = openh264enc->background_detection;
795   enc_params.bEnableAdaptiveQuant = openh264enc->adaptive_quantization;
796   enc_params.bEnableSceneChangeDetect = openh264enc->scene_change_detection;
797   enc_params.bEnableFrameSkip = openh264enc->enable_frame_skip;
798   enc_params.bEnableLongTermReference = 0;
799 #if (OPENH264_MAJOR > 1 || (OPENH264_MAJOR == 1 && OPENH264_MINOR >= 4))
800   enc_params.eSpsPpsIdStrategy = CONSTANT_ID;
801 #else
802   enc_params.bEnableSpsPpsIdAddition = 0;
803 #endif
804   enc_params.bPrefixNalAddingCtrl = 0;
805   enc_params.fMaxFrameRate = fps_n * 1.0 / fps_d;
806   enc_params.iLoopFilterDisableIdc = openh264enc->deblocking_mode;
807   enc_params.sSpatialLayers[0].uiProfileIdc = gst_openh264enc_get_profile_from_caps (outcaps, allowed_caps);
808   enc_params.sSpatialLayers[0].uiLevelIdc = (ELevelIdc) gst_openh264enc_get_level_from_caps (outcaps, allowed_caps);
809   enc_params.sSpatialLayers[0].iVideoWidth = enc_params.iPicWidth;
810   enc_params.sSpatialLayers[0].iVideoHeight = enc_params.iPicHeight;
811   enc_params.sSpatialLayers[0].fFrameRate = fps_n * 1.0 / fps_d;
812   enc_params.sSpatialLayers[0].iSpatialBitrate = enc_params.iTargetBitrate;
813   enc_params.sSpatialLayers[0].iMaxSpatialBitrate = enc_params.iMaxBitrate;
814
815   gst_clear_caps (&allowed_caps);
816
817   if (openh264enc->slice_mode == GST_OPENH264_SLICE_MODE_N_SLICES) {
818     if (openh264enc->num_slices == 1)
819       slice_mode = SM_SINGLE_SLICE;
820     else
821       slice_mode = SM_FIXEDSLCNUM_SLICE;
822     n_slices = openh264enc->num_slices;
823   } else if (openh264enc->slice_mode == GST_OPENH264_SLICE_MODE_AUTO) {
824 #if OPENH264_MAJOR == 1 && OPENH264_MINOR < 6
825     slice_mode = SM_AUTO_SLICE;
826 #else
827     slice_mode = SM_FIXEDSLCNUM_SLICE;
828     n_slices = 0;
829 #endif
830   } else {
831     GST_ERROR_OBJECT (openh264enc, "unexpected slice mode %d",
832         openh264enc->slice_mode);
833     slice_mode = SM_SINGLE_SLICE;
834   }
835
836 #if OPENH264_MAJOR == 1 && OPENH264_MINOR < 6
837   enc_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = slice_mode;
838   enc_params.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = n_slices;
839 #else
840   enc_params.sSpatialLayers[0].sSliceArgument.uiSliceMode = slice_mode;
841   enc_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = n_slices;
842 #endif
843
844   openh264enc->framerate = (1 + fps_n / fps_d);
845
846   ret = openh264enc->encoder->InitializeExt (&enc_params);
847
848   openh264enc->bitrate_changed = FALSE;
849   openh264enc->max_bitrate_changed = FALSE;
850
851   GST_OBJECT_UNLOCK (openh264enc);
852
853   if (ret != cmResultSuccess) {
854     GST_ERROR_OBJECT (openh264enc, "failed to initialize encoder");
855     return FALSE;
856   }
857
858   openh264enc->encoder->SetOption (ENCODER_OPTION_DATAFORMAT, &video_format);
859
860   output_state = gst_video_encoder_set_output_state (encoder, outcaps, state);
861   gst_video_codec_state_unref (output_state);
862
863   return gst_video_encoder_negotiate (encoder);
864 }
865
866 static gboolean
867 gst_openh264enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
868 {
869   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
870
871   return
872       GST_VIDEO_ENCODER_CLASS
873       (gst_openh264enc_parent_class)->propose_allocation (encoder, query);
874 }
875
876 static GstFlowReturn
877 gst_openh264enc_handle_frame (GstVideoEncoder * encoder,
878     GstVideoCodecFrame * frame)
879 {
880   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
881   SSourcePicture *src_pic = NULL;
882   GstVideoFrame video_frame;
883   gboolean force_keyframe;
884   gint ret;
885   SFrameBSInfo frame_info;
886   gfloat fps;
887   gint i, j;
888   gsize buf_length = 0;
889
890   GST_OBJECT_LOCK (openh264enc);
891
892   if (openh264enc->bitrate_changed || openh264enc->max_bitrate_changed) {
893     SEncParamExt enc_params;
894     if (openh264enc->encoder->GetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
895             &enc_params) == cmResultSuccess) {
896       if (openh264enc->bitrate_changed) {
897         enc_params.iTargetBitrate = openh264enc->bitrate;
898         enc_params.sSpatialLayers[0].iSpatialBitrate =
899             enc_params.iTargetBitrate;
900       }
901       if (openh264enc->max_bitrate_changed) {
902         enc_params.iMaxBitrate = openh264enc->max_bitrate;
903         enc_params.sSpatialLayers[0].iMaxSpatialBitrate =
904             enc_params.iMaxBitrate;
905       }
906       if (openh264enc->encoder->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
907               &enc_params) != cmResultSuccess) {
908         GST_WARNING_OBJECT (openh264enc,
909             "Error changing bitrate/max bitrate, unable to set new enc_params");
910       }
911     } else {
912       GST_WARNING_OBJECT (openh264enc,
913           "Error changing bitrate/max bitrate, unable to get enc_params");
914     }
915     openh264enc->bitrate_changed = FALSE;
916     openh264enc->max_bitrate_changed = FALSE;
917   }
918
919   GST_OBJECT_UNLOCK (openh264enc);
920
921   if (frame) {
922     src_pic = new SSourcePicture;
923
924     if (src_pic == NULL) {
925       if (frame)
926         gst_video_codec_frame_unref (frame);
927       return GST_FLOW_ERROR;
928     }
929     //fill default src_pic
930     src_pic->iColorFormat = videoFormatI420;
931     src_pic->uiTimeStamp = frame->pts / GST_MSECOND;
932   }
933
934   openh264enc->frame_count++;
935   if (frame) {
936     if (G_UNLIKELY (openh264enc->frame_count == 1)) {
937       openh264enc->time_per_frame = (GST_SECOND / openh264enc->framerate);
938       openh264enc->previous_timestamp = frame->pts;
939     } else {
940       openh264enc->time_per_frame = (guint64)
941           (openh264enc->time_per_frame * 0.8 + (frame->pts -
942               openh264enc->previous_timestamp) * 0.2);
943       openh264enc->previous_timestamp = frame->pts;
944       if (openh264enc->frame_count % 10 == 0) {
945         fps = GST_SECOND / (gdouble) openh264enc->time_per_frame;
946         openh264enc->encoder->SetOption (ENCODER_OPTION_FRAME_RATE, &fps);
947       }
948     }
949   }
950
951   if (frame) {
952     gst_video_frame_map (&video_frame, &openh264enc->input_state->info,
953         frame->input_buffer, GST_MAP_READ);
954     src_pic->iPicWidth = GST_VIDEO_FRAME_WIDTH (&video_frame);
955     src_pic->iPicHeight = GST_VIDEO_FRAME_HEIGHT (&video_frame);
956     src_pic->iStride[0] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 0);
957     src_pic->iStride[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1);
958     src_pic->iStride[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2);
959     src_pic->pData[0] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 0);
960     src_pic->pData[1] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 1);
961     src_pic->pData[2] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 2);
962
963     force_keyframe = GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame);
964     if (force_keyframe) {
965       openh264enc->encoder->ForceIntraFrame (true);
966       GST_DEBUG_OBJECT (openh264enc,
967           "Got force key unit event, next frame coded as intra picture");
968     }
969   }
970
971   memset (&frame_info, 0, sizeof (SFrameBSInfo));
972   ret = openh264enc->encoder->EncodeFrame (src_pic, &frame_info);
973   if (ret != cmResultSuccess) {
974     if (frame) {
975       gst_video_frame_unmap (&video_frame);
976       gst_video_codec_frame_unref (frame);
977       delete src_pic;
978       GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE,
979           ("Could not encode frame"), ("Openh264 returned %d", ret));
980       return GST_FLOW_ERROR;
981     } else {
982       return GST_FLOW_EOS;
983     }
984   }
985
986   if (videoFrameTypeSkip == frame_info.eFrameType) {
987     if (frame) {
988       gst_video_frame_unmap (&video_frame);
989       gst_video_encoder_finish_frame (encoder, frame);
990       delete src_pic;
991     }
992
993     return GST_FLOW_OK;
994   }
995
996   if (frame) {
997     gst_video_frame_unmap (&video_frame);
998     gst_video_codec_frame_unref (frame);
999     delete src_pic;
1000     src_pic = NULL;
1001     frame = NULL;
1002   }
1003
1004   /* FIXME: openh264 has no way for us to get a connection
1005    * between the input and output frames, we just have to
1006    * guess based on the input */
1007   frame = gst_video_encoder_get_oldest_frame (encoder);
1008   if (!frame) {
1009     GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE,
1010         ("Could not encode frame"), ("openh264enc returned %d", ret));
1011     gst_video_codec_frame_unref (frame);
1012     return GST_FLOW_ERROR;
1013   }
1014
1015   if (videoFrameTypeIDR == frame_info.eFrameType) {
1016     GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
1017   } else {
1018     GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
1019   }
1020
1021   for (i = 0; i < frame_info.iLayerNum; i++) {
1022     for (j = 0; j < frame_info.sLayerInfo[i].iNalCount; j++) {
1023       buf_length += frame_info.sLayerInfo[i].pNalLengthInByte[j];
1024     }
1025   }
1026
1027   frame->output_buffer =
1028       gst_video_encoder_allocate_output_buffer (encoder, buf_length);
1029
1030
1031   buf_length = 0;
1032   for (i = 0; i < frame_info.iLayerNum; i++) {
1033     gsize layer_size = 0;
1034     for (j = 0; j < frame_info.sLayerInfo[i].iNalCount; j++) {
1035       layer_size += frame_info.sLayerInfo[i].pNalLengthInByte[j];
1036     }
1037     gst_buffer_fill (frame->output_buffer, buf_length, frame_info.sLayerInfo[i].pBsBuf, layer_size);
1038     buf_length += layer_size;
1039   }
1040
1041   GST_LOG_OBJECT (openh264enc, "openh264 picture %scoded OK!",
1042       (ret != cmResultSuccess) ? "NOT " : "");
1043
1044   return gst_video_encoder_finish_frame (encoder, frame);
1045 }
1046
1047 static GstFlowReturn
1048 gst_openh264enc_finish (GstVideoEncoder * encoder)
1049 {
1050   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
1051
1052   if (openh264enc->frame_count == 0)
1053     return GST_FLOW_OK;
1054
1055   /* Drain encoder */
1056   while ((gst_openh264enc_handle_frame (encoder, NULL)) == GST_FLOW_OK);
1057
1058   return GST_FLOW_OK;
1059 }
1060 static gboolean
1061 openh264enc_element_init (GstPlugin * plugin)
1062 {
1063   if (openh264_element_init (plugin))
1064     return gst_element_register (plugin, "openh264enc", GST_RANK_MARGINAL,
1065                                  GST_TYPE_OPENH264ENC);
1066
1067  GST_ERROR ("Incorrect library version loaded, expecting %s", g_strCodecVer);
1068  return FALSE;
1069 }