xref: /OK3568_Linux_fs/external/gstreamer-rockchip/gst/rockchipmpp/gstmpph264enc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2017 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *     Author: Randy Li <randy.li@rock-chips.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2021 Rockchip Electronics Co., Ltd
6*4882a593Smuzhiyun  *     Author: Jeffy Chen <jeffy.chen@rock-chips.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This library is free software; you can redistribute it and/or
9*4882a593Smuzhiyun  * modify it under the terms of the GNU Library General Public
10*4882a593Smuzhiyun  * License as published by the Free Software Foundation; either
11*4882a593Smuzhiyun  * version 2 of the License, or (at your option) any later version.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * This library is distributed in the hope that it will be useful,
14*4882a593Smuzhiyun  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*4882a593Smuzhiyun  * Library General Public License for more details.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * You should have received a copy of the GNU Library General Public
19*4882a593Smuzhiyun  * License along with this library; if not, write to the
20*4882a593Smuzhiyun  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21*4882a593Smuzhiyun  * Boston, MA 02110-1301, USA.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #ifdef HAVE_CONFIG_H
26*4882a593Smuzhiyun #include "config.h"
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <string.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include "gstmpph264enc.h"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* FIXME: Not all chips support NV24 and Y444. */
34*4882a593Smuzhiyun #define MPP_H264_ENC_FORMATS MPP_ENC_FORMATS ", NV24, Y444"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define GST_MPP_H264_ENC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
37*4882a593Smuzhiyun     GST_TYPE_MPP_H264_ENC, GstMppH264Enc))
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define GST_CAT_DEFAULT mpp_h264_enc_debug
40*4882a593Smuzhiyun GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun typedef enum
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun   GST_MPP_H264_PROFILE_BASELINE = 66,
45*4882a593Smuzhiyun   GST_MPP_H264_PROFILE_MAIN = 77,
46*4882a593Smuzhiyun   GST_MPP_H264_PROFILE_HIGH = 100,
47*4882a593Smuzhiyun } GstMppH264Profile;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun struct _GstMppH264Enc
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun   GstMppEnc parent;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun   GstMppH264Profile profile;
54*4882a593Smuzhiyun   gint level;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun   guint qp_init;
57*4882a593Smuzhiyun   guint qp_min;
58*4882a593Smuzhiyun   guint qp_max;
59*4882a593Smuzhiyun   gint qp_max_step;
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define parent_class gst_mpp_h264_enc_parent_class
63*4882a593Smuzhiyun G_DEFINE_TYPE (GstMppH264Enc, gst_mpp_h264_enc, GST_TYPE_MPP_ENC);
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define DEFAULT_PROP_LEVEL 40   /* 1080p@30fps */
66*4882a593Smuzhiyun #define DEFAULT_PROP_PROFILE GST_MPP_H264_PROFILE_HIGH
67*4882a593Smuzhiyun #define DEFAULT_PROP_QP_INIT 26
68*4882a593Smuzhiyun #define DEFAULT_PROP_QP_MIN 0   /* Auto */
69*4882a593Smuzhiyun #define DEFAULT_PROP_QP_MAX 0   /* Auto */
70*4882a593Smuzhiyun #define DEFAULT_PROP_QP_MAX_STEP -1     /* Auto */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun enum
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun   PROP_0,
75*4882a593Smuzhiyun   PROP_PROFILE,
76*4882a593Smuzhiyun   PROP_LEVEL,
77*4882a593Smuzhiyun   PROP_QP_INIT,
78*4882a593Smuzhiyun   PROP_QP_MIN,
79*4882a593Smuzhiyun   PROP_QP_MAX,
80*4882a593Smuzhiyun   PROP_QP_MAX_STEP,
81*4882a593Smuzhiyun   PROP_LAST,
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define GST_MPP_H264_ENC_SIZE_CAPS \
85*4882a593Smuzhiyun     "width  = (int) [ 96, MAX ], height = (int) [ 64, MAX ]"
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static GstStaticPadTemplate gst_mpp_h264_enc_src_template =
88*4882a593Smuzhiyun GST_STATIC_PAD_TEMPLATE ("src",
89*4882a593Smuzhiyun     GST_PAD_SRC,
90*4882a593Smuzhiyun     GST_PAD_ALWAYS,
91*4882a593Smuzhiyun     GST_STATIC_CAPS ("video/x-h264, "
92*4882a593Smuzhiyun         GST_MPP_H264_ENC_SIZE_CAPS ","
93*4882a593Smuzhiyun         "stream-format = (string) { byte-stream }, "
94*4882a593Smuzhiyun         "alignment = (string) { au }, "
95*4882a593Smuzhiyun         "profile = (string) { baseline, main, high }"));
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun static GstStaticPadTemplate gst_mpp_h264_enc_sink_template =
98*4882a593Smuzhiyun GST_STATIC_PAD_TEMPLATE ("sink",
99*4882a593Smuzhiyun     GST_PAD_SINK,
100*4882a593Smuzhiyun     GST_PAD_ALWAYS,
101*4882a593Smuzhiyun     GST_STATIC_CAPS ("video/x-raw,"
102*4882a593Smuzhiyun         "format = (string) { " MPP_H264_ENC_FORMATS " }, "
103*4882a593Smuzhiyun         GST_MPP_H264_ENC_SIZE_CAPS));
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun #define GST_TYPE_MPP_H264_ENC_PROFILE (gst_mpp_h264_enc_profile_get_type ())
106*4882a593Smuzhiyun static GType
gst_mpp_h264_enc_profile_get_type(void)107*4882a593Smuzhiyun gst_mpp_h264_enc_profile_get_type (void)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun   static GType profile = 0;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun   if (!profile) {
112*4882a593Smuzhiyun     static const GEnumValue profiles[] = {
113*4882a593Smuzhiyun       {GST_MPP_H264_PROFILE_BASELINE, "Baseline", "baseline"},
114*4882a593Smuzhiyun       {GST_MPP_H264_PROFILE_MAIN, "Main", "main"},
115*4882a593Smuzhiyun       {GST_MPP_H264_PROFILE_HIGH, "High", "high"},
116*4882a593Smuzhiyun       {0, NULL, NULL},
117*4882a593Smuzhiyun     };
118*4882a593Smuzhiyun     profile = g_enum_register_static ("GstMppH264Profile", profiles);
119*4882a593Smuzhiyun   }
120*4882a593Smuzhiyun   return profile;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #define GST_TYPE_MPP_H264_ENC_LEVEL (gst_mpp_h264_enc_level_get_type ())
124*4882a593Smuzhiyun static GType
gst_mpp_h264_enc_level_get_type(void)125*4882a593Smuzhiyun gst_mpp_h264_enc_level_get_type (void)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun   static GType level = 0;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun   if (!level) {
130*4882a593Smuzhiyun     static const GEnumValue levels[] = {
131*4882a593Smuzhiyun       {10, "1", "1"},
132*4882a593Smuzhiyun       {99, "1b", "1b"},
133*4882a593Smuzhiyun       {11, "1.1", "1.1"},
134*4882a593Smuzhiyun       {12, "1.2", "1.2"},
135*4882a593Smuzhiyun       {13, "1.3", "1.3"},
136*4882a593Smuzhiyun       {20, "2", "2"},
137*4882a593Smuzhiyun       {21, "2.1", "2.1"},
138*4882a593Smuzhiyun       {22, "2.2", "2.2"},
139*4882a593Smuzhiyun       {30, "3", "3"},
140*4882a593Smuzhiyun       {31, "3.1", "3.1"},
141*4882a593Smuzhiyun       {32, "3.2", "3.2"},
142*4882a593Smuzhiyun       {40, "4", "4"},
143*4882a593Smuzhiyun       {41, "4.1", "4.1"},
144*4882a593Smuzhiyun       {42, "4.2", "4.2"},
145*4882a593Smuzhiyun       {50, "5", "5"},
146*4882a593Smuzhiyun       {51, "5.1", "5.1"},
147*4882a593Smuzhiyun       {52, "5.2", "5.2"},
148*4882a593Smuzhiyun       {60, "6", "6"},
149*4882a593Smuzhiyun       {61, "6.1", "6.1"},
150*4882a593Smuzhiyun       {62, "6.2", "6.2"},
151*4882a593Smuzhiyun       {0, NULL, NULL},
152*4882a593Smuzhiyun     };
153*4882a593Smuzhiyun     level = g_enum_register_static ("GstMppH264Level", levels);
154*4882a593Smuzhiyun   }
155*4882a593Smuzhiyun   return level;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun static void
gst_mpp_h264_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)159*4882a593Smuzhiyun gst_mpp_h264_enc_set_property (GObject * object,
160*4882a593Smuzhiyun     guint prop_id, const GValue * value, GParamSpec * pspec)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun   GstVideoEncoder *encoder = GST_VIDEO_ENCODER (object);
163*4882a593Smuzhiyun   GstMppH264Enc *self = GST_MPP_H264_ENC (encoder);
164*4882a593Smuzhiyun   GstMppEnc *mppenc = GST_MPP_ENC (encoder);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun   switch (prop_id) {
167*4882a593Smuzhiyun     case PROP_PROFILE:{
168*4882a593Smuzhiyun       GstMppH264Profile profile = g_value_get_enum (value);
169*4882a593Smuzhiyun       if (self->profile == profile)
170*4882a593Smuzhiyun         return;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun       self->profile = profile;
173*4882a593Smuzhiyun       break;
174*4882a593Smuzhiyun     }
175*4882a593Smuzhiyun     case PROP_LEVEL:{
176*4882a593Smuzhiyun       gint level = g_value_get_enum (value);
177*4882a593Smuzhiyun       if (self->level == level)
178*4882a593Smuzhiyun         return;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun       self->level = level;
181*4882a593Smuzhiyun       break;
182*4882a593Smuzhiyun     }
183*4882a593Smuzhiyun     case PROP_QP_INIT:{
184*4882a593Smuzhiyun       guint qp_init = g_value_get_uint (value);
185*4882a593Smuzhiyun       if (self->qp_init == qp_init)
186*4882a593Smuzhiyun         return;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun       self->qp_init = qp_init;
189*4882a593Smuzhiyun       break;
190*4882a593Smuzhiyun     }
191*4882a593Smuzhiyun     case PROP_QP_MIN:{
192*4882a593Smuzhiyun       guint qp_min = g_value_get_uint (value);
193*4882a593Smuzhiyun       if (self->qp_min == qp_min)
194*4882a593Smuzhiyun         return;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun       self->qp_min = qp_min;
197*4882a593Smuzhiyun       break;
198*4882a593Smuzhiyun     }
199*4882a593Smuzhiyun     case PROP_QP_MAX:{
200*4882a593Smuzhiyun       guint qp_max = g_value_get_uint (value);
201*4882a593Smuzhiyun       if (self->qp_max == qp_max)
202*4882a593Smuzhiyun         return;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun       self->qp_max = qp_max;
205*4882a593Smuzhiyun       break;
206*4882a593Smuzhiyun     }
207*4882a593Smuzhiyun     case PROP_QP_MAX_STEP:{
208*4882a593Smuzhiyun       gint qp_max_step = g_value_get_int (value);
209*4882a593Smuzhiyun       if (self->qp_max_step == qp_max_step)
210*4882a593Smuzhiyun         return;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun       self->qp_max_step = qp_max_step;
213*4882a593Smuzhiyun       break;
214*4882a593Smuzhiyun     }
215*4882a593Smuzhiyun     default:
216*4882a593Smuzhiyun       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
217*4882a593Smuzhiyun       return;
218*4882a593Smuzhiyun   }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun   mppenc->prop_dirty = TRUE;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static void
gst_mpp_h264_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)224*4882a593Smuzhiyun gst_mpp_h264_enc_get_property (GObject * object,
225*4882a593Smuzhiyun     guint prop_id, GValue * value, GParamSpec * pspec)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun   GstVideoEncoder *encoder = GST_VIDEO_ENCODER (object);
228*4882a593Smuzhiyun   GstMppH264Enc *self = GST_MPP_H264_ENC (encoder);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun   switch (prop_id) {
231*4882a593Smuzhiyun     case PROP_PROFILE:
232*4882a593Smuzhiyun       g_value_set_enum (value, self->profile);
233*4882a593Smuzhiyun       break;
234*4882a593Smuzhiyun     case PROP_LEVEL:
235*4882a593Smuzhiyun       g_value_set_enum (value, self->level);
236*4882a593Smuzhiyun       break;
237*4882a593Smuzhiyun     case PROP_QP_INIT:
238*4882a593Smuzhiyun       g_value_set_uint (value, self->qp_init);
239*4882a593Smuzhiyun       break;
240*4882a593Smuzhiyun     case PROP_QP_MIN:
241*4882a593Smuzhiyun       g_value_set_uint (value, self->qp_min);
242*4882a593Smuzhiyun       break;
243*4882a593Smuzhiyun     case PROP_QP_MAX:
244*4882a593Smuzhiyun       g_value_set_uint (value, self->qp_max);
245*4882a593Smuzhiyun       break;
246*4882a593Smuzhiyun     case PROP_QP_MAX_STEP:
247*4882a593Smuzhiyun       g_value_set_int (value, self->qp_max_step);
248*4882a593Smuzhiyun       break;
249*4882a593Smuzhiyun     default:
250*4882a593Smuzhiyun       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
251*4882a593Smuzhiyun       break;
252*4882a593Smuzhiyun   }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static gboolean
gst_mpp_h264_enc_set_src_caps(GstVideoEncoder * encoder)256*4882a593Smuzhiyun gst_mpp_h264_enc_set_src_caps (GstVideoEncoder * encoder)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun   GstMppH264Enc *self = GST_MPP_H264_ENC (encoder);
259*4882a593Smuzhiyun   GstStructure *structure;
260*4882a593Smuzhiyun   GstCaps *caps;
261*4882a593Smuzhiyun   gchar *string;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun   caps = gst_caps_new_empty_simple ("video/x-h264");
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun   structure = gst_caps_get_structure (caps, 0);
266*4882a593Smuzhiyun   gst_structure_set (structure, "stream-format",
267*4882a593Smuzhiyun       G_TYPE_STRING, "byte-stream", NULL);
268*4882a593Smuzhiyun   gst_structure_set (structure, "alignment", G_TYPE_STRING, "au", NULL);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun   string = g_enum_to_string (GST_TYPE_MPP_H264_ENC_PROFILE, self->profile);
271*4882a593Smuzhiyun   gst_structure_set (structure, "profile", G_TYPE_STRING, string, NULL);
272*4882a593Smuzhiyun   g_free (string);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun   string = g_enum_to_string (GST_TYPE_MPP_H264_ENC_LEVEL, self->level);
275*4882a593Smuzhiyun   gst_structure_set (structure, "level", G_TYPE_STRING, string, NULL);
276*4882a593Smuzhiyun   g_free (string);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun   return gst_mpp_enc_set_src_caps (encoder, caps);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun static gboolean
gst_mpp_h264_enc_apply_properties(GstVideoEncoder * encoder)282*4882a593Smuzhiyun gst_mpp_h264_enc_apply_properties (GstVideoEncoder * encoder)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun   GstMppH264Enc *self = GST_MPP_H264_ENC (encoder);
285*4882a593Smuzhiyun   GstMppEnc *mppenc = GST_MPP_ENC (encoder);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun   if (G_LIKELY (!mppenc->prop_dirty))
288*4882a593Smuzhiyun     return TRUE;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_init", self->qp_init);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun   if (mppenc->rc_mode == MPP_ENC_RC_MODE_FIXQP) {
293*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_max", self->qp_init);
294*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_min", self->qp_init);
295*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_step", 0);
296*4882a593Smuzhiyun   } else if (mppenc->rc_mode == MPP_ENC_RC_MODE_CBR) {
297*4882a593Smuzhiyun     /* NOTE: These settings have been tuned for better quality */
298*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_max",
299*4882a593Smuzhiyun         self->qp_max ? self->qp_max : 28);
300*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_min",
301*4882a593Smuzhiyun         self->qp_min ? self->qp_min : 4);
302*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_step",
303*4882a593Smuzhiyun         self->qp_max_step >= 0 ? self->qp_max_step : 8);
304*4882a593Smuzhiyun   } else if (mppenc->rc_mode == MPP_ENC_RC_MODE_VBR) {
305*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_max",
306*4882a593Smuzhiyun         self->qp_max ? self->qp_max : 40);
307*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_min",
308*4882a593Smuzhiyun         self->qp_min ? self->qp_min : 12);
309*4882a593Smuzhiyun     mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:qp_step",
310*4882a593Smuzhiyun         self->qp_max_step >= 0 ? self->qp_max_step : 8);
311*4882a593Smuzhiyun   }
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:profile", self->profile);
314*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:level", self->level);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:trans8x8",
317*4882a593Smuzhiyun       self->profile == GST_MPP_H264_PROFILE_HIGH);
318*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:cabac_en",
319*4882a593Smuzhiyun       self->profile != GST_MPP_H264_PROFILE_BASELINE);
320*4882a593Smuzhiyun   mpp_enc_cfg_set_s32 (mppenc->mpp_cfg, "h264:cabac_idc", 0);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun   if (!gst_mpp_enc_apply_properties (encoder))
323*4882a593Smuzhiyun     return FALSE;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun   return gst_mpp_h264_enc_set_src_caps (encoder);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun static gboolean
gst_mpp_h264_enc_set_format(GstVideoEncoder * encoder,GstVideoCodecState * state)329*4882a593Smuzhiyun gst_mpp_h264_enc_set_format (GstVideoEncoder * encoder,
330*4882a593Smuzhiyun     GstVideoCodecState * state)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun   GstVideoEncoderClass *pclass = GST_VIDEO_ENCODER_CLASS (parent_class);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun   if (!pclass->set_format (encoder, state))
335*4882a593Smuzhiyun     return FALSE;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun   return gst_mpp_h264_enc_apply_properties (encoder);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static GstFlowReturn
gst_mpp_h264_enc_handle_frame(GstVideoEncoder * encoder,GstVideoCodecFrame * frame)341*4882a593Smuzhiyun gst_mpp_h264_enc_handle_frame (GstVideoEncoder * encoder,
342*4882a593Smuzhiyun     GstVideoCodecFrame * frame)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun   GstVideoEncoderClass *pclass = GST_VIDEO_ENCODER_CLASS (parent_class);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun   if (G_UNLIKELY (!gst_mpp_h264_enc_apply_properties (encoder))) {
347*4882a593Smuzhiyun     gst_video_codec_frame_unref (frame);
348*4882a593Smuzhiyun     return GST_FLOW_NOT_NEGOTIATED;
349*4882a593Smuzhiyun   }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun   return pclass->handle_frame (encoder, frame);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun static void
gst_mpp_h264_enc_init(GstMppH264Enc * self)355*4882a593Smuzhiyun gst_mpp_h264_enc_init (GstMppH264Enc * self)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun   self->parent.mpp_type = MPP_VIDEO_CodingAVC;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun   self->profile = DEFAULT_PROP_PROFILE;
360*4882a593Smuzhiyun   self->level = DEFAULT_PROP_LEVEL;
361*4882a593Smuzhiyun   self->qp_init = DEFAULT_PROP_QP_INIT;
362*4882a593Smuzhiyun   self->qp_min = DEFAULT_PROP_QP_MIN;
363*4882a593Smuzhiyun   self->qp_max = DEFAULT_PROP_QP_MAX;
364*4882a593Smuzhiyun   self->qp_max_step = DEFAULT_PROP_QP_MAX_STEP;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static void
gst_mpp_h264_enc_class_init(GstMppH264EncClass * klass)368*4882a593Smuzhiyun gst_mpp_h264_enc_class_init (GstMppH264EncClass * klass)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun   GstVideoEncoderClass *encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
371*4882a593Smuzhiyun   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
372*4882a593Smuzhiyun   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun   GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "mpph264enc", 0,
375*4882a593Smuzhiyun       "MPP H264 encoder");
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun   encoder_class->set_format = GST_DEBUG_FUNCPTR (gst_mpp_h264_enc_set_format);
378*4882a593Smuzhiyun   encoder_class->handle_frame =
379*4882a593Smuzhiyun       GST_DEBUG_FUNCPTR (gst_mpp_h264_enc_handle_frame);
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun   gobject_class->set_property =
382*4882a593Smuzhiyun       GST_DEBUG_FUNCPTR (gst_mpp_h264_enc_set_property);
383*4882a593Smuzhiyun   gobject_class->get_property =
384*4882a593Smuzhiyun       GST_DEBUG_FUNCPTR (gst_mpp_h264_enc_get_property);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_PROFILE,
387*4882a593Smuzhiyun       g_param_spec_enum ("profile", "H264 profile",
388*4882a593Smuzhiyun           "H264 profile",
389*4882a593Smuzhiyun           GST_TYPE_MPP_H264_ENC_PROFILE, DEFAULT_PROP_PROFILE,
390*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_LEVEL,
393*4882a593Smuzhiyun       g_param_spec_enum ("level", "H264 level",
394*4882a593Smuzhiyun           "H264 level (40~41 = 1080p@30fps, 42 = 1080p60fps, 50~52 = 4K@30fps)",
395*4882a593Smuzhiyun           GST_TYPE_MPP_H264_ENC_LEVEL, DEFAULT_PROP_LEVEL,
396*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_QP_INIT,
399*4882a593Smuzhiyun       g_param_spec_uint ("qp-init", "Initial QP",
400*4882a593Smuzhiyun           "Initial QP (lower value means higher quality)",
401*4882a593Smuzhiyun           0, 51, DEFAULT_PROP_QP_INIT,
402*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_QP_MIN,
405*4882a593Smuzhiyun       g_param_spec_uint ("qp-min", "Min QP",
406*4882a593Smuzhiyun           "Min QP (0 = default)", 0, 51, DEFAULT_PROP_QP_MIN,
407*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_QP_MAX,
410*4882a593Smuzhiyun       g_param_spec_uint ("qp-max", "Max QP",
411*4882a593Smuzhiyun           "Max QP (0 = default)", 0, 51, DEFAULT_PROP_QP_MAX,
412*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun   g_object_class_install_property (gobject_class, PROP_QP_MAX_STEP,
415*4882a593Smuzhiyun       g_param_spec_int ("qp-max-step", "Max QP step",
416*4882a593Smuzhiyun           "Max delta QP step between two frames (-1 = default)", -1, 51,
417*4882a593Smuzhiyun           DEFAULT_PROP_QP_MAX_STEP,
418*4882a593Smuzhiyun           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun   gst_element_class_add_pad_template (element_class,
421*4882a593Smuzhiyun       gst_static_pad_template_get (&gst_mpp_h264_enc_src_template));
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun   gst_element_class_add_pad_template (element_class,
424*4882a593Smuzhiyun       gst_static_pad_template_get (&gst_mpp_h264_enc_sink_template));
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun   gst_element_class_set_static_metadata (element_class,
427*4882a593Smuzhiyun       "Rockchip Mpp H264 Encoder", "Codec/Encoder/Video",
428*4882a593Smuzhiyun       "Encode video streams via Rockchip Mpp",
429*4882a593Smuzhiyun       "Randy Li <randy.li@rock-chips.com>, "
430*4882a593Smuzhiyun       "Jeffy Chen <jeffy.chen@rock-chips.com>");
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun gboolean
gst_mpp_h264_enc_register(GstPlugin * plugin,guint rank)434*4882a593Smuzhiyun gst_mpp_h264_enc_register (GstPlugin * plugin, guint rank)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun   if (!gst_mpp_enc_supported (MPP_VIDEO_CodingAVC))
437*4882a593Smuzhiyun     return FALSE;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun   return gst_element_register (plugin, "mpph264enc", rank,
440*4882a593Smuzhiyun       gst_mpp_h264_enc_get_type ());
441*4882a593Smuzhiyun }
442