Tizen 2.1 base
[framework/multimedia/gstreamer-vaapi.git] / gst / vaapi / gstvaapiencode.c
1 /*
2  *  gstvaapiencode.c - VA-API video encoder
3  *
4  *  Copyright (C) 2011 Intel Corporation
5  *
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.
10  *
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.
15  *
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
20  */
21
22 #include "config.h"
23 #include "gstvaapiencode.h"
24
25 #include <string.h>
26 #include <X11/Xlib.h>
27 #include <gst/video/videocontext.h>
28 #include "gst/vaapi/gstvaapibaseencoder.h"
29
30 #include "gstvaapiencode_h264.h"
31 #include "gstvaapiencode_h263.h"
32 #include "gstvaapiencode_mpeg4.h"
33 #include "gstvaapipluginutil.h"
34 #include "gstvaapipluginbuffer.h"
35
36 /* gst_debug
37      GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_debug)
38      #define GST_CAT_DEFAULT gst_vaapi_encode_debug
39          //class_init
40          GST_DEBUG_CATEGORY_INIT (gst_vaapi_encode_debug, "vaapiencode", 0,
41           "vaapiencode element");
42 */
43 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_debug);
44 #define GST_CAT_DEFAULT gst_vaapi_encode_debug
45
46 #define GST_VAAPI_ENCODE_GET_PRIVATE(obj)                 \
47     (G_TYPE_INSTANCE_GET_PRIVATE ((obj),                  \
48                                   GST_TYPE_VAAPI_ENCODE,  \
49                                   GstVaapiEncodePrivate))
50
51 typedef struct _GstVaapiEncodePrivate GstVaapiEncodePrivate;
52
53 #define GstVideoContextClass GstVideoContextInterface
54
55 #define GST_VAAPI_ENCODE_MUTEX_LOCK(encode)  \
56     G_STMT_START{ g_mutex_lock((encode)->mutex); }G_STMT_END
57
58 #define GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode) \
59     G_STMT_START{ g_mutex_unlock((encode)->mutex); }G_STMT_END
60
61 #define GST_VAAPI_ENCODE_IDLE_BUF_WAIT(encode)                       \
62         G_STMT_START {                                               \
63             g_cond_wait((encode)->idle_buf_added, (encode)->mutex);  \
64         } G_STMT_END
65
66 #define GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode)                     \
67         G_STMT_START {                                               \
68             g_cond_signal((encode)->idle_buf_added);                 \
69         } G_STMT_END
70
71 #define GST_VAAPI_ENCODE_BUSY_BUF_WAIT(encode)                       \
72         G_STMT_START {                                               \
73             g_cond_wait((encode)->busy_buf_added, (encode)->mutex);  \
74         } G_STMT_END
75
76 #define GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode)                     \
77         G_STMT_START {                                               \
78             g_cond_signal((encode)->busy_buf_added);                 \
79         } G_STMT_END
80
81 GST_BOILERPLATE_WITH_INTERFACE(
82     GstVaapiEncode,
83     gst_vaapi_encode,
84     GstElement,
85     GST_TYPE_ELEMENT,
86     GstVideoContext,
87     GST_TYPE_VIDEO_CONTEXT,
88     gst_video_context)
89
90
91 enum {
92     PROP_0,
93 };
94
95 static char*
96 _encode_dump_caps(GstCaps *cpas)
97 {
98   guint i = 0, j = 0;
99   GstStructure const *structure;
100   GValue const *value;
101   static char caps_string[4096*5];
102   char *tmp;
103
104   char *cur = caps_string;
105   memset(caps_string, 0, sizeof(caps_string));
106   for (i = 0; i < gst_caps_get_size(cpas); i++) {
107     structure = gst_caps_get_structure(cpas, i);
108     const char* caps_name = gst_structure_get_name (structure);
109     sprintf(cur, "cap_%02d:%s\n", i, caps_name);
110     cur += strlen(cur);
111
112     for (j = 0; j < gst_structure_n_fields(structure); j++) {
113       const char* name = gst_structure_nth_field_name(structure, j);
114       value = gst_structure_get_value(structure, name);
115       tmp = gst_value_serialize(value);
116       sprintf(cur, "\t%s:%s(%s)\n", name, tmp, G_VALUE_TYPE_NAME(value));
117       cur += strlen(cur);
118       g_free(tmp);
119     }
120   }
121
122   return caps_string;
123 }
124
125 /* context(display) interface */
126 static void
127 gst_vaapi_encode_set_video_context(
128     GstVideoContext *context,
129     const gchar *type,
130     const GValue *value
131 )
132 {
133     GstVaapiEncode *encode = GST_VAAPI_ENCODE (context);
134     GstVaapiDisplay *display = NULL;
135
136     gst_vaapi_set_display (type, value, &display);
137     gst_vaapi_encoder_set_display(encode->encoder, display);
138 }
139
140 static gboolean
141 gst_video_context_supported (GstVaapiEncode *decode, GType iface_type)
142 {
143   return (iface_type == GST_TYPE_VIDEO_CONTEXT);
144 }
145
146 static void
147 gst_video_context_interface_init(GstVideoContextInterface *iface)
148 {
149     iface->set_context = gst_vaapi_encode_set_video_context;
150 }
151
152 static gboolean
153 gst_vaapi_encode_query (GstPad *pad, GstQuery *query)
154 {
155     GstVaapiEncode *encode = GST_VAAPI_ENCODE (gst_pad_get_parent_element (pad));
156     gboolean res;
157
158     if (encode->encoder &&
159         gst_vaapi_reply_to_query(query, ENCODER_DISPLAY(encode->encoder)))
160       res = TRUE;
161     else
162       res = gst_pad_query_default (pad, query);
163
164     g_object_unref (encode);
165     return res;
166 }
167
168 static inline gboolean
169 gst_vaapi_encode_ensure_display(GstVaapiEncode *encode)
170 {
171     return gst_vaapi_ensure_display(encode,
172                                     GST_VAAPI_DISPLAY_TYPE_ANY,
173                                     &ENCODER_DISPLAY(encode->encoder));
174 }
175
176 static void
177 gst_vaapi_encode_buffer_loop(GstVaapiEncode *encode)
178 {
179   GstBuffer *buf = NULL;
180   EncoderStatus encoder_ret = ENCODER_NO_ERROR;
181   gboolean is_running;
182
183   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
184   is_running = encode->is_running;
185   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
186   if (!is_running)
187     return;
188
189   encoder_ret =
190       gst_vaapi_encoder_get_encoded_buffer(
191           encode->encoder,
192           &buf);
193   if (encoder_ret < ENCODER_NO_ERROR) {
194     ENCODER_LOG_ERROR("get encoded buffer failed");
195     return;
196   }
197   GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode);
198
199   if (!buf)
200     return;
201
202   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
203   if (encode->first_src_frame) { /* Set src pad caps and codec data */
204     GstBuffer *codec_data = NULL;
205     if ((ENCODER_NO_ERROR ==
206          gst_vaapi_encoder_get_codec_data(encode->encoder, &codec_data)) &&
207         codec_data) {
208       gst_caps_set_simple(encode->srcpad_caps,
209                           "codec_data",GST_TYPE_BUFFER, codec_data,
210                           NULL);
211     }
212     gst_pad_set_caps (encode->srcpad, encode->srcpad_caps);
213     GST_BUFFER_CAPS(buf) = gst_caps_ref(encode->srcpad_caps);
214     ENCODER_LOG_INFO("gst_vaapi_encode_chain 1st push-buffer caps,\n%s",
215                      _encode_dump_caps(encode->srcpad_caps));
216     encode->first_src_frame = FALSE;
217   }
218   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
219   ENCODER_LOG_DEBUG(
220       "output:%" GST_TIME_FORMAT ", 0x%s",
221       GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)),
222       vaapi_encoder_dump_bytes(GST_BUFFER_DATA(buf),
223                                (GST_BUFFER_SIZE(buf) > 16 ?
224                                 16: GST_BUFFER_SIZE(buf)))
225                    );
226   gst_pad_push(encode->srcpad, buf);
227 }
228
229 static gboolean
230 _encoder_status_callback(
231     GstVaapiBaseEncoder* encoder,
232     EncoderStatus status,
233     void* user_data
234 )
235 {
236   GstVaapiEncode *encode = (GstVaapiEncode *)user_data;
237   gboolean ret = FALSE;
238
239   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
240
241   if (!encode->is_running) {
242     ret = FALSE;
243     goto end;
244   }
245
246   switch (status) {
247   case ENCODER_NO_IDLE_BUF:
248     GST_VAAPI_ENCODE_IDLE_BUF_WAIT(encode);
249     ret = TRUE;
250     break;
251
252   case ENCODER_NO_BUSY_BUF:
253     GST_VAAPI_ENCODE_BUSY_BUF_WAIT(encode);
254     ret = TRUE;
255     break;
256
257   default:
258     ret = FALSE;
259     goto end;
260   }
261
262   if (!encode->is_running)
263     ret = FALSE;
264
265 end:
266   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
267
268   return ret;
269 }
270
271 static gboolean
272 gst_vaapi_encode_set_caps(GstPad *sink_pad, GstCaps *caps)
273 {
274   GstVaapiEncode *encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
275   GstVaapiEncodeClass *encode_class = GST_VAAPI_ENCODE_GET_CLASS(encode);
276   GstStructure *structure = NULL, *src_struct = NULL;
277   gint width = 0, height = 0;
278   gint fps_n = 0, fps_d = 0;
279   const GValue *fps_value = NULL, *format_value;
280   guint32 format = 0;
281   gboolean ret = TRUE;
282   EncoderStatus encoder_ret = ENCODER_NO_ERROR;
283
284   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
285
286   encode->sinkpad_caps = caps;
287   gst_caps_ref(caps);
288   ENCODER_LOG_INFO("gst_vaapi_encode_set_caps,\n%s",
289                    _encode_dump_caps(caps));
290
291   structure = gst_caps_get_structure (caps, 0);
292
293   if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME))
294     encode->is_buffer_sharing = TRUE;
295   else
296     encode->is_buffer_sharing = FALSE;
297
298   if (gst_structure_get_int (structure, "width", &width)) {
299     encode->encoder->width = width;
300   }
301   if (gst_structure_get_int (structure, "height", &height)) {
302     encode->encoder->height = height;
303   }
304   fps_value = gst_structure_get_value (structure, "framerate");
305   if (fps_value) {
306     fps_n = gst_value_get_fraction_numerator (fps_value);
307     fps_d = gst_value_get_fraction_denominator (fps_value);
308     encode->encoder->frame_rate = fps_n/fps_d;
309   }
310   format_value = gst_structure_get_value (structure, "format");
311   if (format_value && GST_IS_VAAPI_ENCODE_H264(encode)) {
312     ENCODER_CHECK_STATUS((format_value &&
313                           GST_TYPE_FOURCC == G_VALUE_TYPE(format_value)),
314                          FALSE,
315                          "1st buffer caps' format type is not fourcc.");
316     format = gst_value_get_fourcc (format_value);
317     if (format) {
318       gst_vaapi_base_encoder_set_input_format(
319           GST_VAAPI_BASE_ENCODER(encode->encoder),
320           format);
321     }
322   }
323
324   /*set src pad caps*/
325   if (encode->srcpad_caps) {
326     gst_caps_unref(encode->srcpad_caps);
327   }
328   encode->srcpad_caps =
329       gst_caps_copy(gst_pad_get_pad_template_caps(encode->srcpad));
330   src_struct = gst_caps_get_structure(encode->srcpad_caps, 0);
331   gst_structure_set(src_struct,
332                     "width", G_TYPE_INT, width,
333                     "height", G_TYPE_INT, height,
334                     "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
335                     NULL);
336   if (encode_class->set_encoder_src_caps) {
337     encode_class->set_encoder_src_caps(encode, encode->srcpad_caps);
338   }
339
340   /*set display and initialize encoder*/
341   ENCODER_CHECK_STATUS(gst_vaapi_encode_ensure_display(encode),
342                        FALSE,
343                        "encoder ensure display failed on setting caps.");
344
345   gst_vaapi_base_encoder_set_notify_status(
346       GST_VAAPI_BASE_ENCODER(encode->encoder),
347       _encoder_status_callback,
348       encode);
349   gst_vaapi_base_encoder_set_buffer_sharing(
350       GST_VAAPI_BASE_ENCODER(encode->encoder),
351       encode->is_buffer_sharing);
352
353   encoder_ret = gst_vaapi_encoder_initialize(encode->encoder);
354   ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
355                         FALSE,
356                         "gst_vaapi_encoder_initialize failed.");
357
358   encoder_ret = gst_vaapi_encoder_open(encode->encoder);
359   ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
360                         FALSE,
361                         "gst_vaapi_encoder_open failed.");
362
363   encode->is_running = TRUE;
364
365 end:
366   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
367   if (ret) {
368     ret = gst_pad_start_task(encode->srcpad,
369                              (GstTaskFunction)gst_vaapi_encode_buffer_loop,
370                              encode);
371         if (!ret)
372            ENCODER_LOG_INFO("gstvaapiencode start task failed.");
373   }
374   return ret;
375 }
376
377 static GstCaps *
378 gst_vaapi_encode_get_caps(GstPad *sink_pad)
379 {
380   GstCaps *caps = NULL;
381   GstVaapiEncode * const encode =
382       GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
383
384   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
385
386   if (encode->sinkpad_caps) {
387     gst_caps_ref(encode->sinkpad_caps);
388     ENCODER_LOG_INFO("get caps,\n%s",
389                      _encode_dump_caps(encode->sinkpad_caps));
390     caps = encode->sinkpad_caps;
391   } else
392     caps = gst_caps_copy(gst_pad_get_pad_template_caps(sink_pad));
393
394   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
395   return caps;
396 }
397
398 static GstStateChangeReturn
399 gst_vaapi_encode_change_state(
400     GstElement *element,
401     GstStateChange transition
402 )
403 {
404   GstVaapiEncode * const encode = GST_VAAPI_ENCODE(element);
405   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
406
407   switch (transition) {
408   case GST_STATE_CHANGE_READY_TO_PAUSED:
409     break;
410   case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
411     break;
412   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
413     break;
414   case GST_STATE_CHANGE_PAUSED_TO_READY: {
415     GST_VAAPI_ENCODE_MUTEX_LOCK (encode);
416     encode->is_running = FALSE;
417     encode->is_buffer_sharing = FALSE;
418     GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode);
419     GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode);
420     GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
421     gst_pad_stop_task(encode->srcpad);
422     break;
423   }
424   default:
425     break;
426   }
427
428   ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
429   if (ret != GST_STATE_CHANGE_SUCCESS)
430     return ret;
431
432   switch (transition) {
433   case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
434     break;
435   case GST_STATE_CHANGE_PAUSED_TO_READY:
436     gst_vaapi_encoder_close(encode->encoder);
437     GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
438     if (encode->video_pool) {
439       g_object_unref(encode->video_pool);
440       encode->video_pool = NULL;
441     }
442     GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
443     break;
444   default:
445     break;
446   }
447
448   return GST_STATE_CHANGE_SUCCESS;
449 }
450
451 static GstFlowReturn
452 gst_vaapi_encode_chain(GstPad *sink_pad, GstBuffer *buf)
453 {
454   GstFlowReturn ret = GST_FLOW_OK;
455   GstVaapiEncode *encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
456   EncoderStatus encoder_ret = ENCODER_NO_ERROR;
457   gboolean is_buffer_sharing;
458
459   ENCODER_ASSERT(encode && encode->encoder);
460
461   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
462   is_buffer_sharing = encode->is_buffer_sharing;
463   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
464   
465   if (!is_buffer_sharing && !GST_VAAPI_IS_VIDEO_BUFFER(buf)) {
466     ENCODER_LOG_ERROR("gst_vaapi_encode_chain parameter doesn't have video buffer.");
467     ret = ENCODER_NO_ERROR;
468     goto end;
469   }
470
471   /*encoding frames*/
472   encoder_ret = gst_vaapi_encoder_encode(encode->encoder, buf);
473   GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode);
474   ENCODER_CHECK_STATUS (ENCODER_NO_ERROR <= encoder_ret,
475                         GST_FLOW_ERROR,
476                         "gst_vaapi_encoder_encode failed.");
477
478 end:
479   gst_buffer_unref(buf);
480   return ret;
481 }
482
483 static gboolean
484 gst_vaapi_encode_ensure_video_pool(
485     GstVaapiEncode *encode,
486     GstCaps *caps)
487 {
488   GstStructure *structure;
489   gint width = 0, height = 0;
490
491   g_return_val_if_fail(caps, FALSE);
492
493   structure = gst_caps_get_structure(caps, 0);
494   g_return_val_if_fail(structure, FALSE);
495
496   if (encode->video_pool)
497     return TRUE;
498
499   if (!gst_structure_get_int(structure, "width",  &width) ||
500       !gst_structure_get_int(structure, "height", &height))
501     return FALSE;
502
503   encode->video_pool =
504       gst_vaapi_surface_pool_new(ENCODER_DISPLAY(encode->encoder), caps);
505   if (!encode->video_pool)
506     return FALSE;
507
508   return TRUE;
509 }
510
511 static GstFlowReturn
512 gst_vaapi_encode_buffer_alloc(
513     GstPad * pad,
514     guint64 offset,
515     guint size,
516     GstCaps * caps,
517     GstBuffer ** buf
518 )
519 {
520   GstVaapiEncode * const encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(pad));
521   GstStructure *structure = NULL;
522   GstBuffer *video_buffer = NULL;
523   GstFlowReturn ret = GST_FLOW_ERROR;
524
525   if (!caps)
526     return GST_FLOW_ERROR;
527
528   structure = gst_caps_get_structure(caps, 0);
529   if (!structure ||
530       (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME) &&
531        !gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME)))
532     return GST_FLOW_ERROR;
533
534   ENCODER_CHECK_STATUS(
535       gst_vaapi_encode_ensure_display(encode),
536       GST_FLOW_ERROR,
537       "gst_vaapi_encode_buffer_alloc can't ensure display");
538
539   GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
540   if (!gst_vaapi_encode_ensure_video_pool(encode, caps))
541     goto unlock;
542
543   video_buffer = gst_vaapi_video_buffer_new_from_pool(encode->video_pool);
544
545 unlock:
546   GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
547
548   ENCODER_CHECK_STATUS(video_buffer,
549                        GST_FLOW_ERROR,
550                        "gst_vaapi_encode_buffer_alloc failed.");
551
552   if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME)) {
553     ENCODER_CHECK_STATUS(
554         gst_vaapi_video_buffer_ensure_pointer(GST_VAAPI_VIDEO_BUFFER(video_buffer)),
555         GST_FLOW_ERROR,
556         "gst_vaapi_video_buffer_ensure_pointer failed.");
557   }
558
559   if (caps) {
560     gst_buffer_set_caps(video_buffer, caps);
561   }
562   *buf = video_buffer;
563   ret = GST_FLOW_OK;
564
565 end:
566   return ret;
567 }
568
569 static void
570 gst_vaapi_encode_finalize(GObject *object)
571 {
572   GstVaapiEncode * const encode = GST_VAAPI_ENCODE(object);
573
574   if (encode->sinkpad_caps) {
575     gst_caps_unref(encode->sinkpad_caps);
576     encode->sinkpad_caps = NULL;
577   }
578   encode->sinkpad = NULL;
579
580   if (encode->srcpad_caps) {
581     gst_caps_unref(encode->srcpad_caps);
582     encode->srcpad_caps = NULL;
583   }
584   encode->srcpad = NULL;
585
586   if (encode->video_pool)
587     g_object_unref(encode->video_pool);
588
589   if (encode->encoder) {
590       gst_vaapi_encoder_close(encode->encoder);
591       gst_vaapi_encoder_uninitialize(encode->encoder);
592       gst_vaapi_encoder_unref(encode->encoder);
593       encode->encoder = NULL;
594   }
595
596   g_mutex_free(encode->mutex);
597   g_cond_free(encode->idle_buf_added);
598   g_cond_free(encode->busy_buf_added);
599
600   G_OBJECT_CLASS(parent_class)->finalize(object);
601 }
602
603 static void
604 gst_vaapi_encode_init(
605     GstVaapiEncode *encode,
606     GstVaapiEncodeClass *klass
607 )
608 {
609   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
610
611   encode->sinkpad_caps       = NULL;
612   encode->srcpad_caps        = NULL;
613   encode->first_src_frame    = TRUE;
614   encode->is_running         = FALSE;
615   encode->is_buffer_sharing  = FALSE;
616
617   encode->encoder = NULL;
618   encode->video_pool = NULL;
619
620   encode->mutex = g_mutex_new();
621   encode->idle_buf_added = g_cond_new();
622   encode->busy_buf_added = g_cond_new();
623
624   /*sink pad */
625   encode->sinkpad = gst_pad_new_from_template(
626       gst_element_class_get_pad_template(element_class, "sink"),
627       "sink"
628   );
629   gst_pad_set_getcaps_function(encode->sinkpad, gst_vaapi_encode_get_caps);
630   gst_pad_set_setcaps_function(encode->sinkpad, gst_vaapi_encode_set_caps);
631   gst_pad_set_chain_function(encode->sinkpad, gst_vaapi_encode_chain);
632   gst_pad_set_bufferalloc_function(encode->sinkpad,
633                                    gst_vaapi_encode_buffer_alloc);
634   /*gst_pad_set_event_function(encode->sinkpad, gst_vaapi_encode_sink_event); */
635   /*gst_pad_use_fixed_caps(encode->sinkpad);*/
636   gst_pad_set_query_function(encode->sinkpad, gst_vaapi_encode_query);
637   gst_element_add_pad(GST_ELEMENT(encode), encode->sinkpad);
638
639   /* src pad */
640   encode->srcpad = gst_pad_new_from_template(
641       gst_element_class_get_pad_template(element_class, "src"),
642       "src"
643   );
644   encode->srcpad_caps = NULL;
645
646   gst_pad_use_fixed_caps(encode->srcpad);
647   /*gst_pad_set_event_function(encode->srcpad, gst_vaapi_encode_src_event);*/
648   gst_pad_set_query_function(encode->srcpad, gst_vaapi_encode_query);
649   gst_element_add_pad(GST_ELEMENT(encode), encode->srcpad);
650 }
651
652 static void
653 gst_vaapi_encode_set_property(
654     GObject *object,
655     guint prop_id,
656     const GValue *value,
657     GParamSpec *pspec)
658 {
659   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
660   ENCODER_ASSERT(encode->encoder);
661
662   switch (prop_id) {
663   }
664 }
665
666 static void
667 gst_vaapi_encode_get_property (
668     GObject * object,
669     guint prop_id,
670     GValue * value,
671     GParamSpec * pspec
672 )
673 {
674   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
675   ENCODER_ASSERT(encode->encoder);
676
677   switch (prop_id) {
678   }
679 }
680
681 static void
682 gst_vaapi_encode_base_init(gpointer klass)
683 {
684   #if 0
685   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
686
687   gst_element_class_set_details(element_class, &gst_vaapi_encode_details);
688
689   /* sink pad */
690   gst_element_class_add_pad_template(
691       element_class,
692       gst_static_pad_template_get(&gst_vaapi_encode_sink_factory)
693   );
694
695   /* src pad */
696   gst_element_class_add_pad_template(
697       element_class,
698       gst_static_pad_template_get(&gst_vaapi_encode_src_factory)
699   );
700   #endif
701 }
702
703 static void
704 gst_vaapi_encode_class_init(GstVaapiEncodeClass *klass)
705 {
706   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
707   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
708
709   object_class->finalize      = gst_vaapi_encode_finalize;
710   object_class->set_property  = gst_vaapi_encode_set_property;
711   object_class->get_property  = gst_vaapi_encode_get_property;
712
713   GST_DEBUG_CATEGORY_INIT (gst_vaapi_encode_debug,
714                            "vaapiencode",
715                            0,
716                            "vaapiencode element");
717
718   element_class->change_state = gst_vaapi_encode_change_state;
719
720   klass->set_encoder_src_caps = NULL;
721
722   /* Registering debug symbols for function pointers */
723   GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_change_state);
724   GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_get_caps);
725   GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_set_caps);
726   GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_chain);
727   GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_buffer_alloc);
728 }