• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
gst_openh264enc_usage_type_get_type(void)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
gst_openh264enc_rc_modes_get_type(void)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
gst_openh264enc_deblocking_mode_get_type(void)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
gst_openh264enc_slice_mode_get_type(void)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
gst_openh264enc_complexity_get_type(void)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
gst_openh264enc_class_init(GstOpenh264EncClass * klass)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
gst_openh264enc_init(GstOpenh264Enc * openh264enc)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
gst_openh264enc_set_usage_type(GstOpenh264Enc * openh264enc,gint usage_type)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
gst_openh264enc_set_rate_control(GstOpenh264Enc * openh264enc,gint rc_mode)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
gst_openh264enc_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)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
gst_openh264enc_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)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
gst_openh264enc_finalize(GObject * object)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
gst_openh264enc_start(GstVideoEncoder * encoder)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
gst_openh264enc_stop(GstVideoEncoder * encoder)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
gst_openh264enc_get_level_from_caps(GstCaps * outcaps,GstCaps * allowed_caps)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
gst_openh264enc_get_profile_from_caps(GstCaps * outcaps,GstCaps * allowed_caps)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     return PRO_HIGH;
720 
721   g_assert_not_reached ();
722   return PRO_BASELINE;
723 }
724 
725 static gboolean
gst_openh264enc_set_format(GstVideoEncoder * encoder,GstVideoCodecState * state)726 gst_openh264enc_set_format (GstVideoEncoder * encoder,
727     GstVideoCodecState * state)
728 {
729   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
730   gchar *debug_caps;
731   guint width, height, fps_n, fps_d;
732   SEncParamExt enc_params;
733   SliceModeEnum slice_mode = SM_SINGLE_SLICE;
734   guint n_slices = 1;
735   gint ret;
736   GstCaps *outcaps;
737   GstVideoCodecState *output_state;
738   openh264enc->frame_count = 0;
739   int video_format = videoFormatI420;
740   GstCaps *allowed_caps = NULL;
741 
742   debug_caps = gst_caps_to_string (state->caps);
743   GST_DEBUG_OBJECT (openh264enc, "gst_e26d4_enc_set_format called, caps: %s",
744       debug_caps);
745   g_free (debug_caps);
746 
747   gst_openh264enc_stop (encoder);
748 
749   if (openh264enc->input_state) {
750     gst_video_codec_state_unref (openh264enc->input_state);
751   }
752   openh264enc->input_state = gst_video_codec_state_ref (state);
753 
754   width = GST_VIDEO_INFO_WIDTH (&state->info);
755   height = GST_VIDEO_INFO_HEIGHT (&state->info);
756   fps_n = GST_VIDEO_INFO_FPS_N (&state->info);
757   fps_d = GST_VIDEO_INFO_FPS_D (&state->info);
758 
759   if (openh264enc->encoder != NULL) {
760     openh264enc->encoder->Uninitialize ();
761     WelsDestroySVCEncoder (openh264enc->encoder);
762     openh264enc->encoder = NULL;
763   }
764   WelsCreateSVCEncoder (&openh264enc->encoder);
765   unsigned int uiTraceLevel = WELS_LOG_ERROR;
766   openh264enc->encoder->SetOption (ENCODER_OPTION_TRACE_LEVEL, &uiTraceLevel);
767 
768   outcaps = gst_static_pad_template_get_caps (&gst_openh264enc_src_template);
769   outcaps = gst_caps_make_writable (outcaps);
770   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
771   allowed_caps = gst_caps_make_writable (allowed_caps);
772   allowed_caps = gst_caps_fixate (allowed_caps);
773 
774   GST_OBJECT_LOCK (openh264enc);
775 
776   openh264enc->encoder->GetDefaultParams (&enc_params);
777 
778   enc_params.iUsageType = openh264enc->usage_type;
779   enc_params.iPicWidth = width;
780   enc_params.iPicHeight = height;
781   enc_params.iTargetBitrate = openh264enc->bitrate;
782   enc_params.iMaxBitrate = openh264enc->max_bitrate;
783   enc_params.iMaxQp = openh264enc->qp_max;
784   enc_params.iMinQp = openh264enc->qp_min;
785   enc_params.iRCMode = openh264enc->rate_control;
786   enc_params.iTemporalLayerNum = 1;
787   enc_params.iSpatialLayerNum = 1;
788   enc_params.iLtrMarkPeriod = 30;
789   enc_params.iMultipleThreadIdc = openh264enc->multi_thread;
790   enc_params.bEnableDenoise = openh264enc->enable_denoise;
791   enc_params.iComplexityMode = openh264enc->complexity;
792   enc_params.uiIntraPeriod = openh264enc->gop_size;
793   enc_params.bEnableBackgroundDetection = openh264enc->background_detection;
794   enc_params.bEnableAdaptiveQuant = openh264enc->adaptive_quantization;
795   enc_params.bEnableSceneChangeDetect = openh264enc->scene_change_detection;
796   enc_params.bEnableFrameSkip = openh264enc->enable_frame_skip;
797   enc_params.bEnableLongTermReference = 0;
798 #if (OPENH264_MAJOR > 1 || (OPENH264_MAJOR == 1 && OPENH264_MINOR >= 4))
799   enc_params.eSpsPpsIdStrategy = CONSTANT_ID;
800 #else
801   enc_params.bEnableSpsPpsIdAddition = 0;
802 #endif
803   enc_params.bPrefixNalAddingCtrl = 0;
804   enc_params.fMaxFrameRate = fps_n * 1.0 / fps_d;
805   enc_params.iLoopFilterDisableIdc = openh264enc->deblocking_mode;
806   enc_params.sSpatialLayers[0].uiProfileIdc = gst_openh264enc_get_profile_from_caps (outcaps, allowed_caps);
807   enc_params.sSpatialLayers[0].uiLevelIdc = (ELevelIdc) gst_openh264enc_get_level_from_caps (outcaps, allowed_caps);
808   enc_params.sSpatialLayers[0].iVideoWidth = enc_params.iPicWidth;
809   enc_params.sSpatialLayers[0].iVideoHeight = enc_params.iPicHeight;
810   enc_params.sSpatialLayers[0].fFrameRate = fps_n * 1.0 / fps_d;
811   enc_params.sSpatialLayers[0].iSpatialBitrate = enc_params.iTargetBitrate;
812   enc_params.sSpatialLayers[0].iMaxSpatialBitrate = enc_params.iMaxBitrate;
813 
814   gst_clear_caps (&allowed_caps);
815 
816   if (openh264enc->slice_mode == GST_OPENH264_SLICE_MODE_N_SLICES) {
817     if (openh264enc->num_slices == 1)
818       slice_mode = SM_SINGLE_SLICE;
819     else
820       slice_mode = SM_FIXEDSLCNUM_SLICE;
821     n_slices = openh264enc->num_slices;
822   } else if (openh264enc->slice_mode == GST_OPENH264_SLICE_MODE_AUTO) {
823 #if OPENH264_MAJOR == 1 && OPENH264_MINOR < 6
824     slice_mode = SM_AUTO_SLICE;
825 #else
826     slice_mode = SM_FIXEDSLCNUM_SLICE;
827     n_slices = 0;
828 #endif
829   } else {
830     GST_ERROR_OBJECT (openh264enc, "unexpected slice mode %d",
831         openh264enc->slice_mode);
832     slice_mode = SM_SINGLE_SLICE;
833   }
834 
835 #if OPENH264_MAJOR == 1 && OPENH264_MINOR < 6
836   enc_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = slice_mode;
837   enc_params.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = n_slices;
838 #else
839   enc_params.sSpatialLayers[0].sSliceArgument.uiSliceMode = slice_mode;
840   enc_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = n_slices;
841 #endif
842 
843   openh264enc->framerate = (1 + fps_n / fps_d);
844 
845   ret = openh264enc->encoder->InitializeExt (&enc_params);
846 
847   openh264enc->bitrate_changed = FALSE;
848   openh264enc->max_bitrate_changed = FALSE;
849 
850   GST_OBJECT_UNLOCK (openh264enc);
851 
852   if (ret != cmResultSuccess) {
853     GST_ERROR_OBJECT (openh264enc, "failed to initialize encoder");
854     return FALSE;
855   }
856 
857   openh264enc->encoder->SetOption (ENCODER_OPTION_DATAFORMAT, &video_format);
858 
859   output_state = gst_video_encoder_set_output_state (encoder, outcaps, state);
860   gst_video_codec_state_unref (output_state);
861 
862   return gst_video_encoder_negotiate (encoder);
863 }
864 
865 static gboolean
gst_openh264enc_propose_allocation(GstVideoEncoder * encoder,GstQuery * query)866 gst_openh264enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
867 {
868   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
869 
870   return
871       GST_VIDEO_ENCODER_CLASS
872       (gst_openh264enc_parent_class)->propose_allocation (encoder, query);
873 }
874 
875 static GstFlowReturn
gst_openh264enc_handle_frame(GstVideoEncoder * encoder,GstVideoCodecFrame * frame)876 gst_openh264enc_handle_frame (GstVideoEncoder * encoder,
877     GstVideoCodecFrame * frame)
878 {
879   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
880   SSourcePicture *src_pic = NULL;
881   GstVideoFrame video_frame;
882   gboolean force_keyframe;
883   gint ret;
884   SFrameBSInfo frame_info;
885   gfloat fps;
886   gint i, j;
887   gsize buf_length = 0;
888 
889   GST_OBJECT_LOCK (openh264enc);
890 
891   if (openh264enc->bitrate_changed || openh264enc->max_bitrate_changed) {
892     SEncParamExt enc_params;
893     if (openh264enc->encoder->GetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
894             &enc_params) == cmResultSuccess) {
895       if (openh264enc->bitrate_changed) {
896         enc_params.iTargetBitrate = openh264enc->bitrate;
897         enc_params.sSpatialLayers[0].iSpatialBitrate =
898             enc_params.iTargetBitrate;
899       }
900       if (openh264enc->max_bitrate_changed) {
901         enc_params.iMaxBitrate = openh264enc->max_bitrate;
902         enc_params.sSpatialLayers[0].iMaxSpatialBitrate =
903             enc_params.iMaxBitrate;
904       }
905       if (openh264enc->encoder->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
906               &enc_params) != cmResultSuccess) {
907         GST_WARNING_OBJECT (openh264enc,
908             "Error changing bitrate/max bitrate, unable to set new enc_params");
909       }
910     } else {
911       GST_WARNING_OBJECT (openh264enc,
912           "Error changing bitrate/max bitrate, unable to get enc_params");
913     }
914     openh264enc->bitrate_changed = FALSE;
915     openh264enc->max_bitrate_changed = FALSE;
916   }
917 
918   GST_OBJECT_UNLOCK (openh264enc);
919 
920   if (frame) {
921     src_pic = new SSourcePicture;
922 
923     if (src_pic == NULL) {
924       if (frame)
925         gst_video_codec_frame_unref (frame);
926       return GST_FLOW_ERROR;
927     }
928     //fill default src_pic
929     src_pic->iColorFormat = videoFormatI420;
930     src_pic->uiTimeStamp = frame->pts / GST_MSECOND;
931   }
932 
933   openh264enc->frame_count++;
934   if (frame) {
935     if (G_UNLIKELY (openh264enc->frame_count == 1)) {
936       openh264enc->time_per_frame = (GST_SECOND / openh264enc->framerate);
937       openh264enc->previous_timestamp = frame->pts;
938     } else {
939       openh264enc->time_per_frame = (guint64)
940           (openh264enc->time_per_frame * 0.8 + (frame->pts -
941               openh264enc->previous_timestamp) * 0.2);
942       openh264enc->previous_timestamp = frame->pts;
943       if (openh264enc->frame_count % 10 == 0) {
944         fps = GST_SECOND / (gdouble) openh264enc->time_per_frame;
945         openh264enc->encoder->SetOption (ENCODER_OPTION_FRAME_RATE, &fps);
946       }
947     }
948   }
949 
950   if (frame) {
951     gst_video_frame_map (&video_frame, &openh264enc->input_state->info,
952         frame->input_buffer, GST_MAP_READ);
953     src_pic->iPicWidth = GST_VIDEO_FRAME_WIDTH (&video_frame);
954     src_pic->iPicHeight = GST_VIDEO_FRAME_HEIGHT (&video_frame);
955     src_pic->iStride[0] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 0);
956     src_pic->iStride[1] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 1);
957     src_pic->iStride[2] = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, 2);
958     src_pic->pData[0] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 0);
959     src_pic->pData[1] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 1);
960     src_pic->pData[2] = GST_VIDEO_FRAME_COMP_DATA (&video_frame, 2);
961 
962     force_keyframe = GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame);
963     if (force_keyframe) {
964       openh264enc->encoder->ForceIntraFrame (true);
965       GST_DEBUG_OBJECT (openh264enc,
966           "Got force key unit event, next frame coded as intra picture");
967     }
968   }
969 
970   memset (&frame_info, 0, sizeof (SFrameBSInfo));
971   ret = openh264enc->encoder->EncodeFrame (src_pic, &frame_info);
972   if (ret != cmResultSuccess) {
973     if (frame) {
974       gst_video_frame_unmap (&video_frame);
975       gst_video_codec_frame_unref (frame);
976       delete src_pic;
977       GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE,
978           ("Could not encode frame"), ("Openh264 returned %d", ret));
979       return GST_FLOW_ERROR;
980     } else {
981       return GST_FLOW_EOS;
982     }
983   }
984 
985   if (videoFrameTypeSkip == frame_info.eFrameType) {
986     if (frame) {
987       gst_video_frame_unmap (&video_frame);
988       gst_video_encoder_finish_frame (encoder, frame);
989       delete src_pic;
990     }
991 
992     return GST_FLOW_OK;
993   }
994 
995   if (frame) {
996     gst_video_frame_unmap (&video_frame);
997     gst_video_codec_frame_unref (frame);
998     delete src_pic;
999     src_pic = NULL;
1000     frame = NULL;
1001   }
1002 
1003   /* FIXME: openh264 has no way for us to get a connection
1004    * between the input and output frames, we just have to
1005    * guess based on the input */
1006   frame = gst_video_encoder_get_oldest_frame (encoder);
1007   if (!frame) {
1008     GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE,
1009         ("Could not encode frame"), ("openh264enc returned %d", ret));
1010     gst_video_codec_frame_unref (frame);
1011     return GST_FLOW_ERROR;
1012   }
1013 
1014   if (videoFrameTypeIDR == frame_info.eFrameType) {
1015     GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
1016   } else {
1017     GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
1018   }
1019 
1020   for (i = 0; i < frame_info.iLayerNum; i++) {
1021     for (j = 0; j < frame_info.sLayerInfo[i].iNalCount; j++) {
1022       buf_length += frame_info.sLayerInfo[i].pNalLengthInByte[j];
1023     }
1024   }
1025 
1026   frame->output_buffer =
1027       gst_video_encoder_allocate_output_buffer (encoder, buf_length);
1028 
1029 
1030   buf_length = 0;
1031   for (i = 0; i < frame_info.iLayerNum; i++) {
1032     gsize layer_size = 0;
1033     for (j = 0; j < frame_info.sLayerInfo[i].iNalCount; j++) {
1034       layer_size += frame_info.sLayerInfo[i].pNalLengthInByte[j];
1035     }
1036     gst_buffer_fill (frame->output_buffer, buf_length, frame_info.sLayerInfo[i].pBsBuf, layer_size);
1037     buf_length += layer_size;
1038   }
1039 
1040   GST_LOG_OBJECT (openh264enc, "openh264 picture %scoded OK!",
1041       (ret != cmResultSuccess) ? "NOT " : "");
1042 
1043   return gst_video_encoder_finish_frame (encoder, frame);
1044 }
1045 
1046 static GstFlowReturn
gst_openh264enc_finish(GstVideoEncoder * encoder)1047 gst_openh264enc_finish (GstVideoEncoder * encoder)
1048 {
1049   GstOpenh264Enc *openh264enc = GST_OPENH264ENC (encoder);
1050 
1051   if (openh264enc->frame_count == 0)
1052     return GST_FLOW_OK;
1053 
1054   /* Drain encoder */
1055   while ((gst_openh264enc_handle_frame (encoder, NULL)) == GST_FLOW_OK);
1056 
1057   return GST_FLOW_OK;
1058 }
1059 static gboolean
openh264enc_element_init(GstPlugin * plugin)1060 openh264enc_element_init (GstPlugin * plugin)
1061 {
1062   if (openh264_element_init (plugin))
1063     return gst_element_register (plugin, "openh264enc", GST_RANK_MARGINAL,
1064                                  GST_TYPE_OPENH264ENC);
1065 
1066  GST_ERROR ("Incorrect library version loaded, expecting %s", g_strCodecVer);
1067  return FALSE;
1068 }
1069