2 * gstvaapiencoder.c - VA-API encoder interface
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.h"
26 #include "gstvaapidisplay_x11.h"
27 #include "gstvaapiobject_priv.h"
28 #include "gstvaapidisplay_priv.h"
30 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encoder_debug);
31 #define GST_CAT_DEFAULT gst_vaapi_encoder_debug
34 G_DEFINE_TYPE(GstVaapiEncoder, gst_vaapi_encoder, G_TYPE_OBJECT)
37 gst_vaapi_encoder_set_display(
38 GstVaapiEncoder* encoder,
39 GstVaapiDisplay *display
42 GstVaapiEncoderPrivate *priv = encoder->priv;
43 if (display == priv->display) {
47 if (VAAPI_ENC_INIT < priv->state) {
51 g_object_unref(priv->display);
53 priv->va_display = NULL;
56 priv->display = g_object_ref(display);
57 priv->va_display = gst_vaapi_display_get_display(display);
63 gst_vaapi_encoder_get_display(GstVaapiEncoder* encoder)
65 GstVaapiEncoderPrivate *priv = encoder->priv;
66 return (priv->display ? g_object_ref(priv->display) : NULL);
70 gst_vaapi_encoder_get_context(GstVaapiEncoder* encoder)
72 GstVaapiEncoderPrivate *priv = encoder->priv;
73 return (priv->context ? g_object_ref(priv->context) : NULL);
78 gst_vaapi_encoder_get_state(GstVaapiEncoder* encoder)
80 GstVaapiEncoderPrivate *priv = encoder->priv;
86 gst_vaapi_encoder_initialize(GstVaapiEncoder* encoder)
88 EncoderStatus ret = ENCODER_NO_ERROR;
89 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
90 GstVaapiEncoderPrivate *priv = encoder->priv;
93 if (VAAPI_ENC_INIT == priv->state) {
94 return ENCODER_NO_ERROR;
96 ENCODER_ASSERT(VAAPI_ENC_NULL == priv->state);
97 if (VAAPI_ENC_NULL != priv->state) {
98 return ENCODER_STATE_ERR;
102 if (!priv->display) {
103 priv->display = gst_vaapi_display_x11_new(NULL);
104 ENCODER_CHECK_STATUS(priv->display,
106 "gst_vaapi_display_x11_new failed.");
108 priv->va_display = gst_vaapi_display_get_display(priv->display);
110 if (encoder_class->initialize) {
111 ret = encoder_class->initialize(encoder);
112 ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == ret,
114 "encoder <initialize> failed.");
116 priv->state = VAAPI_ENC_INIT;
123 gst_vaapi_encoder_open(GstVaapiEncoder* encoder)
125 EncoderStatus ret = ENCODER_NO_ERROR;
126 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
127 GstVaapiEncoderPrivate *priv = encoder->priv;
130 if (VAAPI_ENC_OPENED == priv->state) {
131 return ENCODER_NO_ERROR;
133 ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
134 if (VAAPI_ENC_INIT != priv->state) {
135 return ENCODER_STATE_ERR;
137 ENCODER_ASSERT(!priv->context);
139 ENCODER_CHECK_STATUS(encoder_class->open,
140 ENCODER_FUNC_PTR_ERR,
141 "encoder <open> function pointer empty.");
142 ret = encoder_class->open(encoder, &priv->context);
143 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
145 "encoder <open> failed.");
146 ENCODER_CHECK_STATUS(priv->context,
148 "encoder <open> context failed.");
149 priv->va_context = gst_vaapi_context_get_id(priv->context);
150 priv->state = VAAPI_ENC_OPENED;
157 gst_vaapi_encoder_encode(
158 GstVaapiEncoder* encoder,
162 EncoderStatus ret = ENCODER_NO_ERROR;
163 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
164 GstVaapiEncoderPrivate *priv = encoder->priv;
166 ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
168 "encoder was not opened before <encode>.");
169 ENCODER_CHECK_STATUS(encoder_class->encode,
170 ENCODER_FUNC_PTR_ERR,
171 "encoder <encode> function pointer empty.");
172 ret = encoder_class->encode(encoder, pic);
173 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR <= ret,
175 "encoder <encode> failed.");
176 if (priv->state < VAAPI_ENC_ENCODING) {
177 priv->state = VAAPI_ENC_ENCODING;
184 gst_vaapi_encoder_get_encoded_buffer(
185 GstVaapiEncoder* encoder,
189 EncoderStatus ret = ENCODER_NO_ERROR;
190 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
191 GstVaapiEncoderPrivate *priv = encoder->priv;
193 ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
195 "encoder was not encoding <encode>.");
196 ENCODER_CHECK_STATUS(encoder_class->get_buf,
197 ENCODER_FUNC_PTR_ERR,
198 "encoder <get_buf> function pointer empty.");
199 ret = encoder_class->get_buf(encoder, buf);
200 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR <= ret,
202 "encoder <get_buf> failed.");
209 gst_vaapi_encoder_get_codec_data(
210 GstVaapiEncoder* encoder,
211 GstBuffer **codec_data
214 EncoderStatus ret = ENCODER_NO_ERROR;
215 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
216 GstVaapiEncoderPrivate *priv = encoder->priv;
218 ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
220 "encoder was not opened before <get_codec_data>.");
221 if (!encoder_class->get_codec_data) {
223 ENCODER_LOG_INFO("There's no codec_data");
226 ret = encoder_class->get_codec_data(encoder, codec_data);
233 gst_vaapi_encoder_flush(
234 GstVaapiEncoder* encoder
237 EncoderStatus ret = ENCODER_NO_ERROR;
238 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
239 GstVaapiEncoderPrivate *priv = encoder->priv;
241 if (priv->state < VAAPI_ENC_OPENED) {
242 return ENCODER_STATE_ERR;
244 ENCODER_CHECK_STATUS(encoder_class->flush,
245 ENCODER_FUNC_PTR_ERR,
246 "encoder <flush> function pointer empty.");
247 ret = encoder_class->flush(encoder);
248 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
250 "encoder <flush> failed.");
256 gst_vaapi_encoder_close(GstVaapiEncoder* encoder)
258 EncoderStatus ret = ENCODER_NO_ERROR;
259 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
260 GstVaapiEncoderPrivate *priv = encoder->priv;
262 if (VAAPI_ENC_INIT >= priv->state) {
263 return ENCODER_NO_ERROR;
265 ENCODER_CHECK_STATUS(encoder_class->close,
266 ENCODER_FUNC_PTR_ERR,
267 "encoder <close> function pointers empty.");
268 ret = encoder_class->close(encoder);
269 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
271 "encoder <close> failed.");
274 g_object_unref(priv->context);
275 priv->context = NULL;
276 priv->va_context = VA_INVALID_ID;
279 priv->state = VAAPI_ENC_INIT;
284 gst_vaapi_encoder_render_picture(
285 GstVaapiEncoder *encoder,
286 GstVaapiSurface *surface,
291 GstVaapiDisplay *display;
292 VASurfaceID surface_id;
293 VAContextID context_id;
294 VADisplay va_display;
296 gboolean is_locked = FALSE;
297 EncoderStatus ret = ENCODER_NO_ERROR;
299 display = ENCODER_DISPLAY(encoder);
301 g_return_val_if_fail(surface, ENCODER_PARAMETER_ERR);
302 g_return_val_if_fail(ENCODER_CONTEXT(encoder), ENCODER_PARAMETER_ERR);
304 surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(surface);
305 context_id = ENCODER_VA_CONTEXT(encoder);
306 va_display = ENCODER_VA_DISPLAY(encoder);
307 g_return_val_if_fail(surface_id != VA_INVALID_SURFACE, ENCODER_PARAMETER_ERR);
310 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
311 va_status = vaBeginPicture(va_display, context_id, surface_id);
312 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
313 ENCODER_PARAMETER_ERR,
314 "vaBeginPicture failed");
316 va_status = vaRenderPicture(va_display,
320 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
321 ENCODER_PARAMETER_ERR,
322 "vaRenderPicture failed");
324 va_status = vaEndPicture(va_display, context_id);
325 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
326 ENCODER_PARAMETER_ERR,
327 "vaRenderPicture failed");
330 ENCODER_RELEASE_DISPLAY_LOCK(display);
335 gst_vaapi_encoder_uninitialize(GstVaapiEncoder* encoder)
337 EncoderStatus ret = ENCODER_NO_ERROR;
338 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
339 GstVaapiEncoderPrivate *priv = encoder->priv;
341 if (VAAPI_ENC_NULL == priv->state) {
342 return ENCODER_NO_ERROR;
345 if (VAAPI_ENC_INIT < priv->state) {
346 ret = gst_vaapi_encoder_close(encoder);
348 ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
349 if (encoder_class->uninitialize) {
350 ret = encoder_class->uninitialize(encoder);
351 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
353 "encoder <uninitialize> failed.");
358 g_object_unref(priv->display);
359 priv->display = NULL;
360 priv->va_display = NULL;
362 priv->state = VAAPI_ENC_NULL;
368 vaapi_encoder_dump_bytes(const guint8 *buf, guint32 num)
370 static char tmp[1024];
372 memset(tmp, 0, sizeof(tmp));
375 for (i = 0; i < num; i++) {
376 snprintf(p, 1024-(p-tmp), "%02x", (guint8)buf[i]);
383 gst_vaapi_encoder_init(GstVaapiEncoder *encoder)
385 GstVaapiEncoderPrivate *priv;
387 encoder->priv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
388 priv = encoder->priv;
389 ENCODER_ASSERT(priv);
391 priv->display = NULL;
392 priv->va_display = NULL;
393 priv->context = NULL;
394 priv->va_context = VA_INVALID_ID;
395 priv->state = VAAPI_ENC_NULL;
399 encoder->frame_rate = 0;
400 encoder->rate_control = GST_VAAPI_RATECONTROL_NONE;
404 gst_vaapi_encoder_finalize(GObject *object)
406 GstVaapiEncoder* encoder = GST_VAAPI_ENCODER(object);
407 GstVaapiEncoderPrivate *priv = encoder->priv;
408 if (VAAPI_ENC_NULL != priv->state) {
409 gst_vaapi_encoder_uninitialize(encoder);
413 g_object_unref(priv->context);
414 priv->context = NULL;
415 priv->va_context = VA_INVALID_ID;
419 g_object_unref(priv->display);
420 priv->display = NULL;
421 priv->va_display = NULL;
424 G_OBJECT_CLASS (gst_vaapi_encoder_parent_class)->finalize (object);
428 gst_vaapi_encoder_class_init(GstVaapiEncoderClass *kclass)
430 GObjectClass * const object_class = G_OBJECT_CLASS(kclass);
431 g_type_class_add_private(kclass, sizeof(GstVaapiEncoderPrivate));
434 GST_DEBUG_CATEGORY_INIT (gst_vaapi_encoder_debug,
437 "gst_va_encoder element");
439 object_class->finalize = gst_vaapi_encoder_finalize;