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"
28 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encoder_debug);
29 #define GST_CAT_DEFAULT gst_vaapi_encoder_debug
32 G_DEFINE_TYPE(GstVaapiEncoder, gst_vaapi_encoder, G_TYPE_OBJECT)
35 gst_vaapi_encoder_set_display(
36 GstVaapiEncoder* encoder,
37 GstVaapiDisplay *display
40 GstVaapiEncoderPrivate *priv = encoder->priv;
41 if (display == priv->display) {
45 if (VAAPI_ENC_INIT < priv->state) {
49 g_object_unref(priv->display);
51 priv->va_display = NULL;
54 priv->display = g_object_ref(display);
55 priv->va_display = gst_vaapi_display_get_display(display);
61 gst_vaapi_encoder_get_display(GstVaapiEncoder* encoder)
63 GstVaapiEncoderPrivate *priv = encoder->priv;
64 return (priv->display ? g_object_ref(priv->display) : NULL);
68 gst_vaapi_encoder_get_context(GstVaapiEncoder* encoder)
70 GstVaapiEncoderPrivate *priv = encoder->priv;
71 return (priv->context ? g_object_ref(priv->context) : NULL);
76 gst_vaapi_encoder_get_state(GstVaapiEncoder* encoder)
78 GstVaapiEncoderPrivate *priv = encoder->priv;
84 gst_vaapi_encoder_initialize(GstVaapiEncoder* encoder)
86 EncoderStatus ret = ENCODER_NO_ERROR;
87 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
88 GstVaapiEncoderPrivate *priv = encoder->priv;
91 if (VAAPI_ENC_INIT == priv->state) {
92 return ENCODER_NO_ERROR;
94 ENCODER_ASSERT(VAAPI_ENC_NULL == priv->state);
95 if (VAAPI_ENC_NULL != priv->state) {
96 return ENCODER_STATE_ERR;
100 if (!priv->display) {
101 priv->display = gst_vaapi_display_x11_new(NULL);
102 ENCODER_CHECK_STATUS(priv->display,
104 "gst_vaapi_display_x11_new failed.");
105 priv->va_display = gst_vaapi_display_get_display(priv->display);
108 if (encoder_class->initialize) {
109 ret = encoder_class->initialize(encoder);
110 ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == ret,
112 "encoder <initialize> failed.");
114 priv->state = VAAPI_ENC_INIT;
121 gst_vaapi_encoder_open(GstVaapiEncoder* encoder)
123 EncoderStatus ret = ENCODER_NO_ERROR;
124 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
125 GstVaapiEncoderPrivate *priv = encoder->priv;
128 if (VAAPI_ENC_OPENED == priv->state) {
129 return ENCODER_NO_ERROR;
131 ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
132 if (VAAPI_ENC_INIT != priv->state) {
133 return ENCODER_STATE_ERR;
135 ENCODER_ASSERT(!priv->context);
137 ENCODER_CHECK_STATUS(encoder_class->open,
138 ENCODER_FUNC_PTR_ERR,
139 "encoder <open> function pointer empty.");
140 ret = encoder_class->open(encoder, &priv->context);
141 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
143 "encoder <open> failed.");
144 ENCODER_CHECK_STATUS(priv->context,
146 "encoder <open> context failed.");
147 priv->va_context = gst_vaapi_context_get_id(priv->context);
148 priv->state = VAAPI_ENC_OPENED;
155 gst_vaapi_encoder_encode(
156 GstVaapiEncoder* encoder,
161 EncoderStatus ret = ENCODER_NO_ERROR;
162 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
163 GstVaapiEncoderPrivate *priv = encoder->priv;
165 ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
167 "encoder was not opened before <encode>.");
168 ENCODER_CHECK_STATUS(encoder_class->encode,
169 ENCODER_FUNC_PTR_ERR,
170 "encoder <encode> function pointer empty.");
171 ret = encoder_class->encode(encoder, raw_pic, coded_pics);
172 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
174 "encoder <encode> failed.");
175 if (priv->state < VAAPI_ENC_ENCODING) {
176 priv->state = VAAPI_ENC_ENCODING;
183 gst_vaapi_encoder_get_codec_data(
184 GstVaapiEncoder* encoder,
185 GstBuffer **codec_data
188 EncoderStatus ret = ENCODER_NO_ERROR;
189 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
190 GstVaapiEncoderPrivate *priv = encoder->priv;
192 ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
194 "encoder was not opened before <get_codec_data>.");
195 if (!encoder_class->get_codec_data) {
197 ENCODER_LOG_INFO("There's no codec_data");
200 ret = encoder_class->get_codec_data(encoder, codec_data);
207 gst_vaapi_encoder_flush(
208 GstVaapiEncoder* encoder,
212 EncoderStatus ret = ENCODER_NO_ERROR;
213 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
214 GstVaapiEncoderPrivate *priv = encoder->priv;
216 if (priv->state < VAAPI_ENC_OPENED) {
217 return ENCODER_STATE_ERR;
219 ENCODER_CHECK_STATUS(encoder_class->flush,
220 ENCODER_FUNC_PTR_ERR,
221 "encoder <flush> function pointer empty.");
222 ret = encoder_class->flush(encoder, coded_pics);
223 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
225 "encoder <flush> failed.");
226 if (priv->state > VAAPI_ENC_OPENED) {
227 priv->state = VAAPI_ENC_OPENED;
234 gst_vaapi_encoder_close(GstVaapiEncoder* encoder)
236 EncoderStatus ret = ENCODER_NO_ERROR;
237 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
238 GstVaapiEncoderPrivate *priv = encoder->priv;
240 if (VAAPI_ENC_INIT >= priv->state) {
241 return ENCODER_NO_ERROR;
243 ENCODER_CHECK_STATUS(encoder_class->close,
244 ENCODER_FUNC_PTR_ERR,
245 "encoder <close> function pointers empty.");
246 ret = encoder_class->close(encoder);
247 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
249 "encoder <close> failed.");
252 g_object_unref(priv->context);
253 priv->context = NULL;
254 priv->va_context = VA_INVALID_ID;
257 priv->state = VAAPI_ENC_INIT;
262 gst_vaapi_encoder_uninitialize(GstVaapiEncoder* encoder)
264 EncoderStatus ret = ENCODER_NO_ERROR;
265 GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
266 GstVaapiEncoderPrivate *priv = encoder->priv;
268 if (VAAPI_ENC_NULL == priv->state) {
269 return ENCODER_NO_ERROR;
272 if (VAAPI_ENC_INIT < priv->state) {
273 ret = gst_vaapi_encoder_close(encoder);
275 ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
276 if (encoder_class->uninitialize) {
277 ret = encoder_class->uninitialize(encoder);
278 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
280 "encoder <uninitialize> failed.");
285 g_object_unref(priv->display);
286 priv->display = NULL;
287 priv->va_display = NULL;
289 priv->state = VAAPI_ENC_NULL;
295 vaapi_encoder_dump_bytes(const guint8 *buf, guint32 num)
297 static char tmp[1024];
299 memset(tmp, 0, sizeof(tmp));
302 for (i = 0; i < num; i++) {
303 snprintf(p, 1024-(p-tmp), "%02x", (guint8)buf[i]);
310 gst_vaapi_encoder_init(GstVaapiEncoder *encoder)
312 GstVaapiEncoderPrivate *priv;
314 encoder->priv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
315 priv = encoder->priv;
316 ENCODER_ASSERT(priv);
318 priv->display = NULL;
319 priv->va_display = NULL;
320 priv->context = NULL;
321 priv->va_context = VA_INVALID_ID;
322 priv->state = VAAPI_ENC_NULL;
326 encoder->frame_rate = 0;
327 encoder->rate_control = GST_VAAPI_RATECONTROL_NONE;
331 gst_vaapi_encoder_finalize(GObject *object)
333 GstVaapiEncoder* encoder = GST_VAAPI_ENCODER(object);
334 GstVaapiEncoderPrivate *priv = encoder->priv;
335 if (VAAPI_ENC_NULL != priv->state) {
336 gst_vaapi_encoder_uninitialize(encoder);
340 g_object_unref(priv->context);
341 priv->context = NULL;
342 priv->va_context = VA_INVALID_ID;
346 g_object_unref(priv->display);
347 priv->display = NULL;
348 priv->va_display = NULL;
351 G_OBJECT_CLASS (gst_vaapi_encoder_parent_class)->finalize (object);
355 gst_vaapi_encoder_class_init(GstVaapiEncoderClass *kclass)
357 GObjectClass * const object_class = G_OBJECT_CLASS(kclass);
358 g_type_class_add_private(kclass, sizeof(GstVaapiEncoderPrivate));
361 GST_DEBUG_CATEGORY_INIT (gst_vaapi_encoder_debug,
364 "gst_va_encoder element");
366 object_class->finalize = gst_vaapi_encoder_finalize;