90651c24e0026d024063970671a53bd8ff753583
[profile/ivi/gstreamer-vaapi.git] / gst / vaapiencode / gstvaapiencoder.c
1 #include "gstvaapiencoder.h"
2
3 #include <string.h>
4
5 #include "gst/vaapi/gstvaapidisplay_x11.h"
6
7 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encoder_debug);
8 #define GST_CAT_DEFAULT gst_vaapi_encoder_debug
9
10
11 G_DEFINE_TYPE(GstVaapiEncoder, gst_vaapi_encoder, G_TYPE_OBJECT);
12
13 static void gst_vaapi_encoder_class_init(GstVaapiEncoderClass *kclass);
14 static void gst_vaapi_encoder_init(GstVaapiEncoder *encoder);
15 static void gst_vaapi_encoder_finalize(GObject *object);
16
17 static void
18 gst_vaapi_encoder_class_init(GstVaapiEncoderClass *kclass)
19 {
20   GObjectClass * const object_class = G_OBJECT_CLASS(kclass);
21   g_type_class_add_private(kclass, sizeof(GstVaapiEncoderPrivate));
22
23
24   GST_DEBUG_CATEGORY_INIT (gst_vaapi_encoder_debug, "gst_va_encoder", 0,
25         "gst_va_encoder element");
26
27   object_class->finalize = gst_vaapi_encoder_finalize;
28   kclass->initialize = NULL;
29   kclass->uninitialize = NULL;
30   kclass->open = NULL;
31   kclass->close = NULL;
32   kclass->encode = NULL;
33   kclass->flush = NULL;
34   kclass->get_codec_data = NULL;
35 }
36
37 static void
38 gst_vaapi_encoder_init(GstVaapiEncoder *encoder)
39 {
40   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
41   ENCODER_ASSERT(encoder_prv);
42   encoder_prv->display = NULL;
43   encoder_prv->context = NULL;
44   encoder_prv->state = VAAPI_ENC_NULL;
45
46   encoder->width = 0;
47   encoder->height = 0;
48   encoder->frame_rate = 0;
49 }
50
51 static void
52 gst_vaapi_encoder_finalize(GObject *object)
53 {
54   GstVaapiEncoder* encoder = GST_VAAPI_ENCODER(object);
55   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(object);
56   if (VAAPI_ENC_NULL != encoder_prv->state) {
57     gst_vaapi_encoder_uninitialize(encoder);
58   }
59
60   if (encoder_prv->context) {
61     g_object_unref(encoder_prv->context);
62     encoder_prv->context = NULL;
63   }
64
65   if (encoder_prv->display) {
66     g_object_unref(encoder_prv->display);
67     encoder_prv->display = NULL;
68   }
69
70   G_OBJECT_CLASS (gst_vaapi_encoder_parent_class)->finalize (object);
71 }
72
73
74 gboolean
75 gst_vaapi_encoder_set_display(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
76 {
77   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
78   if (display == encoder_prv->display) {
79     return TRUE;
80   }
81
82   if (VAAPI_ENC_INIT < encoder_prv->state) {
83     return FALSE;
84   }
85   if (encoder_prv->display) {
86     g_object_unref(encoder_prv->display);
87     encoder_prv->display = NULL;
88   }
89   encoder_prv->display = g_object_ref(display);
90   return TRUE;
91 }
92
93 GstVaapiDisplay *
94 gst_vaapi_encoder_get_display(GstVaapiEncoder* encoder)
95 {
96   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
97   return (encoder_prv->display ? g_object_ref(encoder_prv->display) : NULL);
98 }
99
100 GstVaapiContext *
101 gst_vaapi_encoder_get_context(GstVaapiEncoder* encoder)
102 {
103   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
104   return (encoder_prv->context ? g_object_ref(encoder_prv->context) : NULL);
105 }
106
107
108 VAAPI_Encode_State
109 gst_vaapi_encoder_get_state(GstVaapiEncoder* encoder)
110 {
111   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
112   return encoder_prv->state;
113 }
114
115
116 EncoderStatus
117 gst_vaapi_encoder_initialize(GstVaapiEncoder* encoder)
118 {
119   EncoderStatus ret = ENCODER_NO_ERROR;
120   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
121   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
122
123   /* check state */
124   if (VAAPI_ENC_INIT == encoder_prv->state) {
125     return ENCODER_NO_ERROR;
126   }
127   ENCODER_ASSERT(VAAPI_ENC_NULL == encoder_prv->state);
128   if (VAAPI_ENC_NULL != encoder_prv->state) {
129     return ENCODER_STATE_ERR;
130   }
131
132   /* create va_dpy*/
133   if (!encoder_prv->display) {
134     encoder_prv->display = gst_vaapi_display_x11_new(NULL);
135     ENCODER_CHECK_STATUS(encoder_prv->display, ENCODER_DISPLAY_ERR, "gst_vaapi_display_x11_new failed.");
136   }
137
138   if (encoder_class->initialize) {
139     ret = encoder_class->initialize(encoder, encoder_prv->display);
140     ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == ret, ret, "encoder <initialize> failed.");
141   }
142   encoder_prv->state = VAAPI_ENC_INIT;
143
144 end:
145   return ret;
146 }
147
148 EncoderStatus
149 gst_vaapi_encoder_open(GstVaapiEncoder* encoder, void* private_data)
150 {
151   EncoderStatus ret = ENCODER_NO_ERROR;
152   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
153   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
154
155   /* check state */
156   if (VAAPI_ENC_OPENED == encoder_prv->state) {
157     return ENCODER_NO_ERROR;
158   }
159   ENCODER_ASSERT(VAAPI_ENC_INIT == encoder_prv->state);
160   if (VAAPI_ENC_INIT != encoder_prv->state) {
161     return ENCODER_STATE_ERR;
162   }
163   ENCODER_ASSERT(!encoder_prv->context);
164
165   ENCODER_CHECK_STATUS(encoder_class->open, ENCODER_FUNC_PTR_ERR, "encoder <open> function pointer empty.");
166   ret = encoder_class->open(encoder, encoder_prv->display, private_data, &encoder_prv->context);
167   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ret, "encoder <open> failed.");
168   ENCODER_CHECK_STATUS(encoder_prv->context, ENCODER_CONTEXT_ERR, "encoder <open> context failed.");
169
170   encoder_prv->state = VAAPI_ENC_OPENED;
171
172 end:
173   return ret;
174 }
175
176 EncoderStatus
177 gst_vaapi_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
178 {
179   EncoderStatus ret = ENCODER_NO_ERROR;
180   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
181   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
182
183   ENCODER_CHECK_STATUS(encoder_prv->state >= VAAPI_ENC_OPENED, ENCODER_STATE_ERR, "encoder was not opened before <encode>.");
184   ENCODER_CHECK_STATUS(encoder_class->encode, ENCODER_FUNC_PTR_ERR, "encoder <encode> function pointer empty.");
185   ret = encoder_class->encode(encoder, encoder_prv->display, encoder_prv->context, raw_pic, coded_pics);
186   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ret, "encoder <encode> failed.");
187   if (encoder_prv->state < VAAPI_ENC_ENCODING) {
188     encoder_prv->state = VAAPI_ENC_ENCODING;
189   }
190 end:
191   return ret;
192 }
193
194 EncoderStatus gst_vaapi_encoder_get_codec_data(GstVaapiEncoder* encoder, GstBuffer **codec_data)
195 {
196   EncoderStatus ret = ENCODER_NO_ERROR;
197   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
198   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
199
200   ENCODER_CHECK_STATUS(encoder_prv->state >= VAAPI_ENC_OPENED, ENCODER_STATE_ERR, "encoder was not opened before <get_codec_data>.");
201   if (!encoder_class->get_codec_data) {
202     *codec_data = NULL;
203     ENCODER_LOG_INFO("There's no codec_data");
204     return ret;
205   }
206   ret = encoder_class->get_codec_data(encoder, codec_data);
207
208 end:
209   return ret;
210 }
211
212 EncoderStatus
213 gst_vaapi_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics)
214 {
215   EncoderStatus ret = ENCODER_NO_ERROR;
216   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
217   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
218
219   if (encoder_prv->state < VAAPI_ENC_OPENED) {
220     return ENCODER_STATE_ERR;
221   }
222   ENCODER_CHECK_STATUS(encoder_class->flush, ENCODER_FUNC_PTR_ERR, "encoder <flush> function pointer empty.");
223   ret = encoder_class->flush(encoder, encoder_prv->display, encoder_prv->context, coded_pics);
224   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ret, "encoder <flush> failed.");
225   if (encoder_prv->state > VAAPI_ENC_OPENED) {
226     encoder_prv->state = VAAPI_ENC_OPENED;
227   }
228 end:
229   return ret;
230 }
231
232 EncoderStatus
233 gst_vaapi_encoder_close(GstVaapiEncoder* encoder)
234 {
235   EncoderStatus ret = ENCODER_NO_ERROR;
236   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
237   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
238
239   if (VAAPI_ENC_INIT >= encoder_prv->state) {
240     return ENCODER_NO_ERROR;
241   }
242   ENCODER_CHECK_STATUS(encoder_class->close, ENCODER_FUNC_PTR_ERR, "encoder <close> function pointers empty.");
243   ret = encoder_class->close(encoder, encoder_prv->display, encoder_prv->context);
244   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ret, "encoder <close> failed.");
245 end:
246   if (encoder_prv->context) {
247     g_object_unref(encoder_prv->context);
248     encoder_prv->context = NULL;
249   }
250
251   encoder_prv->state = VAAPI_ENC_INIT;
252   return ret;
253 }
254
255 EncoderStatus
256 gst_vaapi_encoder_uninitialize(GstVaapiEncoder* encoder)
257 {
258   EncoderStatus ret = ENCODER_NO_ERROR;
259   GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
260   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
261
262   if (VAAPI_ENC_NULL == encoder_prv->state) {
263     return ENCODER_NO_ERROR;
264   }
265
266   if (VAAPI_ENC_INIT < encoder_prv->state) {
267     ret = gst_vaapi_encoder_close(encoder);
268   }
269   ENCODER_ASSERT(VAAPI_ENC_INIT == encoder_prv->state);
270   if (encoder_class->uninitialize) {
271     ret = encoder_class->uninitialize(encoder, encoder_prv->display);
272     ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ret, "encoder <uninitialize> failed.");
273   }
274 end:
275   if (encoder_prv->display) {
276     g_object_unref(encoder_prv->display);
277     encoder_prv->display = NULL;
278   }
279   encoder_prv->state = VAAPI_ENC_NULL;
280   return ret;
281
282 }
283
284 char *vaapi_encoder_dump_bytes(const guint8 *buf, guint32 num)
285 {
286   static char tmp[1024];
287   guint32 i = 0;
288   memset(tmp, 0, sizeof(tmp));
289
290   char *p = tmp;
291   for (i = 0; i < num; i++) {
292     snprintf(p, 1024-(p-tmp), "%02x", (guint8)buf[i]);
293     p += strlen(p);
294   }
295   return tmp;
296 }
297