1 #include "gstvaapih263encoder.h"
5 #include "gst/gstclock.h"
7 #include "gst/vaapi/gstvaapiobject.h"
8 #include "gst/vaapi/gstvaapiobject_priv.h"
9 #include "gst/vaapi/gstvaapicontext.h"
10 #include "gst/vaapi/gstvaapisurface.h"
11 #include "gst/vaapi/gstvaapivideobuffer.h"
12 #include "gst/vaapi/gstvaapidisplay_priv.h"
14 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h263_encoder_debug);
15 #define GST_CAT_DEFAULT gst_vaapi_h263_encoder_debug
17 struct _GstH263EncoderPrivate {
18 GstVaapiSurface *ref_surface; /* reference buffer*/
19 GstVaapiSurface *recon_surface; /* reconstruct buffer*/
21 VABufferID seq_parameter;
22 VABufferID pic_parameter;
23 VABufferID slice_parameter;
26 G_DEFINE_TYPE(GstH263Encoder, gst_h263_encoder, GST_TYPE_VAAPI_BASE_ENCODER);
28 static EncoderStatus gst_h263_encoder_flush(GstVaapiEncoder* encoder,
29 GstVaapiDisplay *display, GstVaapiContext *context,
33 static void gst_h263_encoder_class_init(GstH263EncoderClass *klass);
34 static void gst_h263_encoder_init(GstH263Encoder *encoder);
35 static void gst_h263_encoder_finalize(GObject *object);
37 static gboolean gst_h263_validate_parameters(GstVaapiBaseEncoder* encoder);
38 static gboolean gst_h263_encoder_release_resource(
39 GstVaapiBaseEncoder* encoder, GstVaapiDisplay *display,
40 GstVaapiContext *context);
41 static EncoderStatus gst_h263_prepare_encoding(GstVaapiBaseEncoder *encoder,
42 GstVaapiDisplay *display, GstVaapiContext *context,
43 GstVaapiSurface *surface, guint frame_index,
44 VABufferID coded_buf, gboolean *is_key);
46 static void h263_release_buffers(GstH263Encoder *h263_encoder,
47 GstVaapiDisplay *display);
50 gst_h263_encoder_new(void)
52 return GST_H263_ENCODER(g_object_new(GST_TYPE_H263_ENCODER, NULL));
57 gst_h263_encoder_class_init(GstH263EncoderClass *klass)
59 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
60 GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
61 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
62 g_type_class_add_private(klass, sizeof(GstH263EncoderPrivate));
64 GST_DEBUG_CATEGORY_INIT (gst_vaapi_h263_encoder_debug, "gst_va_h263_encoder", 0,
65 "gst_va_h263_encoder element");
67 object_class->finalize = gst_h263_encoder_finalize;
69 base_class->validate_attributes = gst_h263_validate_parameters;
70 base_class->pre_alloc_resource = NULL;
71 base_class->release_resource = gst_h263_encoder_release_resource;
72 base_class->prepare_frame = gst_h263_prepare_encoding;
73 base_class->notify_frame = NULL;
74 base_class->copy_coded_frame = NULL;
77 encoder_class->flush = gst_h263_encoder_flush;
79 encoder_class->get_codec_data = NULL;
84 gst_h263_encoder_init(GstH263Encoder *h263_encoder)
86 GstH263EncoderPrivate *h263_prv = GST_H263_ENCODER_GET_PRIVATE(h263_encoder);
87 GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(h263_encoder);
88 ENCODER_ASSERT(h263_prv);
91 h263_encoder->bitrate = 0;
92 h263_encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
93 h263_encoder->init_qp = H263_DEFAULT_INIT_QP;
94 h263_encoder->min_qp = H263_DEFAULT_MIN_QP;
97 h263_prv->ref_surface = NULL;
98 h263_prv->recon_surface = NULL;
100 h263_prv->seq_parameter = VA_INVALID_ID;
101 h263_prv->pic_parameter = VA_INVALID_ID;
102 h263_prv->slice_parameter = VA_INVALID_ID;
106 gst_h263_encoder_finalize(GObject *object)
108 /*free private buffers*/
109 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
110 GstH263EncoderPrivate *h263_prv = GST_H263_ENCODER_GET_PRIVATE(object);
112 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
113 gst_vaapi_encoder_uninitialize(encoder);
115 G_OBJECT_CLASS(gst_h263_encoder_parent_class)->finalize(object);
119 gst_h263_validate_parameters(GstVaapiBaseEncoder* encoder)
121 GstH263Encoder *h263_encoder = GST_H263_ENCODER(encoder);
122 if (!ENCODER_WIDTH(h263_encoder) || !ENCODER_HEIGHT(h263_encoder) || !ENCODER_FPS(h263_encoder)) {
125 if (!h263_encoder->intra_period) {
126 h263_encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
128 if (-1 == h263_encoder->init_qp) {
129 h263_encoder->init_qp = H263_DEFAULT_INIT_QP;
131 if (-1 == h263_encoder->min_qp) {
132 h263_encoder->min_qp = H263_DEFAULT_MIN_QP;
135 /* default compress ratio 1: (4*8*1.5) */
136 if (!h263_encoder->bitrate) {
137 h263_encoder->bitrate = ENCODER_WIDTH(h263_encoder)*ENCODER_HEIGHT(h263_encoder)*ENCODER_FPS(h263_encoder)/4;
139 gst_vaapi_base_encoder_set_va_profile(GST_VAAPI_BASE_ENCODER(h263_encoder), VAProfileH263Baseline);
146 h263_release_parameters(GstH263Encoder *h263_encoder, GstVaapiDisplay *display)
148 GstH263EncoderPrivate *h263_prv = GST_H263_ENCODER_GET_PRIVATE(h263_encoder);
149 VADisplay va_dpy = gst_vaapi_display_get_display(display);
150 VAStatus va_status = VA_STATUS_SUCCESS;
152 if (VA_INVALID_ID != h263_prv->seq_parameter) {
153 va_status = vaDestroyBuffer(va_dpy, h263_prv->seq_parameter);
154 h263_prv->seq_parameter = VA_INVALID_ID;
156 if (VA_INVALID_ID != h263_prv->pic_parameter) {
157 va_status = vaDestroyBuffer(va_dpy, h263_prv->pic_parameter);
158 h263_prv->pic_parameter = VA_INVALID_ID;
160 if (VA_INVALID_ID != h263_prv->slice_parameter) {
161 va_status = vaDestroyBuffer(va_dpy, h263_prv->slice_parameter);
162 h263_prv->slice_parameter = VA_INVALID_ID;
168 gst_h263_encoder_release_resource(GstVaapiBaseEncoder* encoder,
169 GstVaapiDisplay *display,
170 GstVaapiContext *context)
172 GstH263Encoder *h263_encoder = GST_H263_ENCODER(encoder);
173 GstH263EncoderPrivate *h263_prv = GST_H263_ENCODER_GET_PRIVATE(h263_encoder);
175 h263_release_parameters(h263_encoder, display);
177 /*remove ref_surface*/
178 if (h263_prv->ref_surface) {
180 gst_vaapi_context_put_surface(context, h263_prv->ref_surface);
182 g_object_unref(h263_prv->ref_surface);
184 h263_prv->ref_surface = NULL;
187 /*remove recon_surface*/
188 if (h263_prv->recon_surface) {
190 gst_vaapi_context_put_surface(context, h263_prv->recon_surface);
192 g_object_unref(h263_prv->recon_surface);
194 h263_prv->recon_surface = NULL;
201 gst_h263_prepare_encoding(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
202 GstVaapiContext *context, GstVaapiSurface *surface,
203 guint frame_index, VABufferID coded_buf, gboolean *is_key)
206 GstH263Encoder *h263_encoder = GST_H263_ENCODER(encoder);
207 GstH263EncoderPrivate *h263_prv = GST_H263_ENCODER_GET_PRIVATE(h263_encoder);
208 VADisplay va_dpy = gst_vaapi_display_get_display(display);
209 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
211 VAStatus va_status = VA_STATUS_SUCCESS;
212 EncoderStatus ret = ENCODER_NO_ERROR;
214 *is_key = (frame_index % h263_encoder->intra_period == 0);
216 /* initialize sequence parameter set, only first time */
217 if (VA_INVALID_ID == h263_prv->seq_parameter) { /*only the first time*/
218 VAEncSequenceParameterBufferH263 seq_h263 = {0};
220 seq_h263.intra_period = h263_encoder->intra_period;
221 seq_h263.bits_per_second = h263_encoder->bitrate;
222 seq_h263.frame_rate = ENCODER_FPS(h263_encoder);
223 seq_h263.initial_qp = h263_encoder->init_qp;
224 seq_h263.min_qp = h263_encoder->min_qp;
226 va_status = vaCreateBuffer(va_dpy, context_id,
227 VAEncSequenceParameterBufferType,
228 sizeof(seq_h263), 1, &seq_h263, &h263_prv->seq_parameter);
229 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "h263 alloc seq-buffer failed.\n");
230 va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->seq_parameter, 1);
231 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "h263 vaRenderPicture seq-parameters failed.\n");
234 /* set reference and reconstructed surfaces */
235 if (!h263_prv->ref_surface) {
236 h263_prv->ref_surface = gst_vaapi_context_get_surface(context);
237 ENCODER_CHECK_STATUS(h263_prv->ref_surface, ENCODER_SURFACE_ERR, "h263 reference surface, h263_pop_free_surface failed.\n");
239 if (!h263_prv->recon_surface) {
240 h263_prv->recon_surface = gst_vaapi_context_get_surface(context);
241 ENCODER_CHECK_STATUS(h263_prv->recon_surface, ENCODER_SURFACE_ERR, "h263 reconstructed surface, h263_pop_free_surface failed.\n");
244 /* initialize picture, every time, every frame */
245 VAEncPictureParameterBufferH263 pic_h263 = {0};
246 pic_h263.reference_picture = GST_VAAPI_OBJECT_ID(h263_prv->ref_surface);
247 pic_h263.reconstructed_picture = GST_VAAPI_OBJECT_ID(h263_prv->recon_surface);
248 pic_h263.coded_buf = coded_buf;
249 pic_h263.picture_width = ENCODER_WIDTH(h263_encoder);
250 pic_h263.picture_height = ENCODER_HEIGHT(h263_encoder);
251 pic_h263.picture_type = (*is_key) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
252 if (VA_INVALID_ID != h263_prv->pic_parameter) { /* destroy first*/
253 va_status = vaDestroyBuffer(va_dpy, h263_prv->pic_parameter);
254 h263_prv->pic_parameter = VA_INVALID_ID;
257 va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
258 sizeof(pic_h263), 1, &pic_h263, &h263_prv->pic_parameter);
259 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_ENC_RES_ERR, "h263 creating pic-param buffer failed.\n");
260 va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->pic_parameter, 1);
261 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "h263 rendering pic-param buffer failed.\n");
262 /*initialize slice parameters, only ONE slice for h263*/
263 VAEncSliceParameterBuffer slice_h263 = { 0 };
264 slice_h263.start_row_number = 0;
265 slice_h263.slice_height = (ENCODER_HEIGHT(h263_encoder)+15)/16; /*MB?*/
266 slice_h263.slice_flags.bits.is_intra = *is_key;
267 slice_h263.slice_flags.bits.disable_deblocking_filter_idc = 0;
268 if (VA_INVALID_ID != h263_prv->slice_parameter) {
269 vaDestroyBuffer(va_dpy, h263_prv->slice_parameter);
270 h263_prv->slice_parameter = VA_INVALID_ID;
273 va_status = vaCreateBuffer(va_dpy,
275 VAEncSliceParameterBufferType,
279 &h263_prv->slice_parameter);
280 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
282 "h263 creating slice-parameters buffer failed.\n");
284 va_status = vaRenderPicture(va_dpy, context_id, &h263_prv->slice_parameter, 1);
285 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
287 "h263 rendering slice-parameters buffer failed.\n");
289 /*swap ref_surface and recon_surface */
290 GstVaapiSurface *swap = h263_prv->ref_surface;
291 h263_prv->ref_surface = h263_prv->recon_surface;
292 h263_prv->recon_surface = swap;