2 * gstvaapiencoder_h263.c - H.263 encoder
4 * Copyright (C) 2011 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include "gstvaapiencoder_h263.h"
25 #include <gst/gstclock.h>
27 #include "gstvaapiobject.h"
28 #include "gstvaapiobject_priv.h"
29 #include "gstvaapicontext.h"
30 #include "gstvaapisurface.h"
31 #include "gstvaapivideobuffer.h"
32 #include "gstvaapidisplay_priv.h"
34 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h263_encoder_debug);
35 #define GST_CAT_DEFAULT gst_vaapi_h263_encoder_debug
37 #define GST_VAAPI_ENCODER_H263_CAST(encoder) ((GstVaapiEncoderH263 *)(encoder))
39 struct _GstVaapiEncoderH263Private {
40 GstVaapiSurface *ref_surface; /* reference buffer*/
41 GstVaapiSurface *recon_surface; /* reconstruct buffer*/
43 VABufferID seq_param_id;
44 VABufferID pic_param_id;
45 VABufferID slic_param_id;
48 G_DEFINE_TYPE(GstVaapiEncoderH263, gst_vaapi_encoder_h263, GST_TYPE_VAAPI_BASE_ENCODER)
51 gst_vaapi_encoder_h263_new(void)
53 return GST_VAAPI_ENCODER_H263_CAST(g_object_new(GST_TYPE_VAAPI_ENCODER_H263, NULL));
57 gst_vaapi_encoder_h263_validate_attributes(
58 GstVaapiBaseEncoder* base
61 GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
62 if (!ENCODER_WIDTH(encoder) ||
63 !ENCODER_HEIGHT(encoder) ||
64 !ENCODER_FPS(encoder))
68 if (!encoder->intra_period) {
69 encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
71 if (-1 == encoder->init_qp) {
72 encoder->init_qp = H263_DEFAULT_INIT_QP;
74 if (-1 == encoder->min_qp) {
75 encoder->min_qp = H263_DEFAULT_MIN_QP;
78 /* default compress ratio 1: (4*8*1.5) */
79 if (!encoder->bitrate) {
81 ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4/1024;
83 gst_vaapi_base_encoder_set_va_profile(GST_VAAPI_BASE_ENCODER(encoder),
84 VAProfileH263Baseline);
91 h263_release_parameters(
92 GstVaapiEncoderH263 *encoder
95 GstVaapiEncoderH263Private *priv = encoder->priv;
96 VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
97 VAStatus va_status = VA_STATUS_SUCCESS;
99 VAAPI_UNUSED_ARG(va_status);
101 if (VA_INVALID_ID != priv->seq_param_id) {
102 va_status = vaDestroyBuffer(va_dpy, priv->seq_param_id);
103 priv->seq_param_id = VA_INVALID_ID;
105 if (VA_INVALID_ID != priv->pic_param_id) {
106 va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
107 priv->pic_param_id = VA_INVALID_ID;
109 if (VA_INVALID_ID != priv->slic_param_id) {
110 va_status = vaDestroyBuffer(va_dpy, priv->slic_param_id);
111 priv->slic_param_id = VA_INVALID_ID;
117 gst_vaapi_encoder_h263_release_resource(
118 GstVaapiBaseEncoder* base
121 GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
122 GstVaapiEncoderH263Private *priv = encoder->priv;
123 GstVaapiContext *context = ENCODER_CONTEXT(base);
125 h263_release_parameters(encoder);
127 /*remove ref_surface*/
128 if (priv->ref_surface) {
130 gst_vaapi_context_put_surface(context, priv->ref_surface);
132 g_object_unref(priv->ref_surface);
134 priv->ref_surface = NULL;
137 /*remove recon_surface*/
138 if (priv->recon_surface) {
140 gst_vaapi_context_put_surface(context, priv->recon_surface);
142 g_object_unref(priv->recon_surface);
144 priv->recon_surface = NULL;
151 gst_vaapi_encoder_h263_rendering(
152 GstVaapiBaseEncoder *base,
153 GstVaapiSurface *surface,
155 VABufferID coded_buf,
160 GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
161 GstVaapiEncoderH263Private *priv = encoder->priv;
162 GstVaapiContext *context = ENCODER_CONTEXT(base);
163 VADisplay va_dpy = ENCODER_VA_DISPLAY(base);
164 VAContextID context_id = ENCODER_VA_CONTEXT(base);
165 VABufferID va_buffers[64];
166 guint32 va_buffers_count = 0;
168 VAStatus va_status = VA_STATUS_SUCCESS;
169 EncoderStatus ret = ENCODER_NO_ERROR;
171 *is_key = (frame_index % encoder->intra_period == 0);
173 /* initialize sequence parameter set, only first time */
174 if (VA_INVALID_ID == priv->seq_param_id) { /*only the first time*/
175 VAEncSequenceParameterBufferH263 seq_param = {0};
177 seq_param.intra_period = encoder->intra_period;
178 seq_param.bits_per_second = encoder->bitrate * 1024;
179 seq_param.frame_rate = ENCODER_FPS(encoder);
180 seq_param.initial_qp = encoder->init_qp;
181 seq_param.min_qp = encoder->min_qp;
183 va_status = vaCreateBuffer(va_dpy, context_id,
184 VAEncSequenceParameterBufferType,
185 sizeof(seq_param), 1,
187 &priv->seq_param_id);
188 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
190 "h263 alloc seq-buffer failed.");
191 va_buffers[va_buffers_count++] = priv->seq_param_id;
194 /* set reference and reconstructed surfaces */
195 if (!priv->ref_surface) {
196 priv->ref_surface = gst_vaapi_context_get_surface(context);
197 ENCODER_CHECK_STATUS(priv->ref_surface,
199 "h263 reference surface, h263_pop_free_surface failed.");
201 if (!priv->recon_surface) {
202 priv->recon_surface = gst_vaapi_context_get_surface(context);
203 ENCODER_CHECK_STATUS(priv->recon_surface,
205 "h263 reconstructed surface, h263_pop_free_surface failed.");
208 /* initialize picture, every time, every frame */
209 VAEncPictureParameterBufferH263 pic_param = {0};
210 pic_param.reference_picture = GST_VAAPI_OBJECT_ID(priv->ref_surface);
211 pic_param.reconstructed_picture = GST_VAAPI_OBJECT_ID(priv->recon_surface);
212 pic_param.coded_buf = coded_buf;
213 pic_param.picture_width = ENCODER_WIDTH(encoder);
214 pic_param.picture_height = ENCODER_HEIGHT(encoder);
215 pic_param.picture_type = (*is_key) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
216 if (VA_INVALID_ID != priv->pic_param_id) { /* destroy first*/
217 va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
218 priv->pic_param_id = VA_INVALID_ID;
221 va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
222 sizeof(pic_param), 1, &pic_param, &priv->pic_param_id);
223 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
224 ENCODER_ENC_RES_ERR, "h263 creating pic-param buffer failed.");
225 va_buffers[va_buffers_count++] = priv->pic_param_id;
227 /*initialize slice parameters, only ONE slice for h263*/
228 VAEncSliceParameterBuffer slice_param = { 0 };
229 slice_param.start_row_number = 0;
230 slice_param.slice_height = (ENCODER_HEIGHT(encoder)+15)/16; /*MB?*/
231 slice_param.slice_flags.bits.is_intra = *is_key;
232 slice_param.slice_flags.bits.disable_deblocking_filter_idc = 0;
233 if (VA_INVALID_ID != priv->slic_param_id) {
234 vaDestroyBuffer(va_dpy, priv->slic_param_id);
235 priv->slic_param_id = VA_INVALID_ID;
238 va_status = vaCreateBuffer(va_dpy,
240 VAEncSliceParameterBufferType,
244 &priv->slic_param_id);
245 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
247 "h263 creating slice-parameters buffer failed.");
248 va_buffers[va_buffers_count++] = priv->slic_param_id;
250 ret = gst_vaapi_encoder_render_picture(GST_VAAPI_ENCODER_CAST(encoder),
254 ENCODER_CHECK_STATUS(ret == ENCODER_NO_ERROR,
256 "h263 rendering slice-parameters buffer failed.");
258 /*swap ref_surface and recon_surface */
259 GstVaapiSurface *swap = priv->ref_surface;
260 priv->ref_surface = priv->recon_surface;
261 priv->recon_surface = swap;
268 gst_vaapi_encoder_h263_init(GstVaapiEncoderH263 *encoder)
270 GstVaapiEncoderH263Private *priv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(encoder);
271 encoder->priv = priv;
272 ENCODER_ASSERT(priv);
275 encoder->bitrate = 0;
276 encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
277 encoder->init_qp = H263_DEFAULT_INIT_QP;
278 encoder->min_qp = H263_DEFAULT_MIN_QP;
281 priv->ref_surface = NULL;
282 priv->recon_surface = NULL;
284 priv->seq_param_id = VA_INVALID_ID;
285 priv->pic_param_id = VA_INVALID_ID;
286 priv->slic_param_id = VA_INVALID_ID;
290 gst_vaapi_encoder_h263_finalize(GObject *object)
292 /*free private buffers*/
293 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
295 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
296 gst_vaapi_encoder_uninitialize(encoder);
298 G_OBJECT_CLASS(gst_vaapi_encoder_h263_parent_class)->finalize(object);
302 gst_vaapi_encoder_h263_class_init(GstVaapiEncoderH263Class *klass)
304 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
305 GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
306 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
307 g_type_class_add_private(klass, sizeof(GstVaapiEncoderH263Private));
309 GST_DEBUG_CATEGORY_INIT (gst_vaapi_h263_encoder_debug, "gst_va_h263_encoder", 0,
310 "gst_va_h263_encoder element");
312 object_class->finalize = gst_vaapi_encoder_h263_finalize;
314 base_class->validate_attributes = gst_vaapi_encoder_h263_validate_attributes;
315 base_class->pre_alloc_resource = NULL;
316 base_class->release_resource = gst_vaapi_encoder_h263_release_resource;
317 base_class->render_frame = gst_vaapi_encoder_h263_rendering;
318 base_class->notify_buffer = NULL;
319 base_class->wrap_buffer = NULL;
322 encoder_class->flush = gst_vaapi_encoder_h263_flush;
324 encoder_class->get_codec_data = NULL;