Fix some of the Fixme:
[vaapi:sree-gstreamer-vaapi.git] / gst / vaapi / gstvaapidecode.c
1 /*
2  *  gstvaapidecode.c - VA-API video decoder
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *  Copyright (C) 2011-2012 Intel Corporation
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public License
9  *  as published by the Free Software Foundation; either version 2.1
10  *  of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301 USA
21 */
22
23 /**
24  * SECTION:gstvaapidecode
25  * @short_description: A VA-API based video decoder
26  *
27  * vaapidecode decodes from raw bitstreams to surfaces suitable for
28  * the vaapisink element.
29  */
30
31 #include "gst/vaapi/sysdeps.h"
32 #include <gst/vaapi/gstvaapidisplay.h>
33 #include <gst/video/videocontext.h>
34
35 #include "gstvaapidecode.h"
36 #include "gstvaapipluginutil.h"
37
38 # include <gst/vaapi/gstvaapidecoder_h264.h>
39 # include <gst/vaapi/gstvaapidecoder_jpeg.h>
40 # include <gst/vaapi/gstvaapidecoder_mpeg2.h>
41 //# include <gst/vaapi/gstvaapidecoder_mpeg4.h>
42 # include <gst/vaapi/gstvaapidecoder_vc1.h>
43
44 #define GST_PLUGIN_NAME "vaapidecode"
45 #define GST_PLUGIN_DESC "A VA-API based video decoder"
46
47 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
48 #define GST_CAT_DEFAULT gst_debug_vaapidecode
49
50 /* Default templates */
51 #define GST_CAPS_CODEC(CODEC) CODEC "; "
52
53 static const char gst_vaapidecode_sink_caps_str[] =
54     GST_CAPS_CODEC("video/mpeg, mpegversion=[1, 2], systemstream=(boolean)false")
55     GST_CAPS_CODEC("video/mpeg, mpegversion=4")
56     GST_CAPS_CODEC("video/x-divx")
57     GST_CAPS_CODEC("video/x-xvid")
58     GST_CAPS_CODEC("video/x-h263")
59     GST_CAPS_CODEC("video/x-h264")
60     GST_CAPS_CODEC("video/x-wmv")
61     GST_CAPS_CODEC("image/jpeg")
62     ;
63
64 /*static const char gst_vaapidecode_src_caps_str[] =
65     GST_VAAPI_SURFACE_CAPS;*/
66
67 static GstStaticPadTemplate gst_vaapidecode_sink_factory =
68     GST_STATIC_PAD_TEMPLATE(
69         "sink",
70         GST_PAD_SINK,
71         GST_PAD_ALWAYS,
72         GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
73
74 static GstStaticPadTemplate gst_vaapidecode_src_factory =
75     GST_STATIC_PAD_TEMPLATE(
76         "src",
77         GST_PAD_SRC,
78         GST_PAD_ALWAYS,
79         GST_STATIC_CAPS("video/x-raw"));
80
81 static void
82 gst_video_context_interface_init(GstVideoContextInterface *iface);
83
84 static void 
85 gst_vaapi_dec_negotiate(GstVideoDecoder *dec);
86
87 #define GstVideoContextClass GstVideoContextInterface
88 G_DEFINE_TYPE_WITH_CODE(
89     GstVaapiDecode,
90     gst_vaapidecode,
91     GST_TYPE_VIDEO_DECODER,
92     G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
93                           gst_video_context_interface_init))
94
95 static gboolean gst_vaapi_dec_open (GstVideoDecoder * decoder);
96 static gboolean gst_vaapi_dec_start (GstVideoDecoder * decoder);
97 static gboolean gst_vaapi_dec_stop (GstVideoDecoder * decoder);
98 static gboolean gst_vaapi_dec_set_format (GstVideoDecoder * decoder,
99     GstVideoCodecState * state);
100 static gboolean gst_vaapi_dec_decide_allocation (GstVideoDecoder * decoder,
101     GstQuery * query);
102 static gboolean gst_vaapi_dec_reset (GstVideoDecoder * decoder, gboolean hard);
103 static GstFlowReturn gst_vaapi_dec_parse (GstVideoDecoder * decoder,
104     GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
105 static GstFlowReturn gst_vaapi_dec_handle_frame (GstVideoDecoder * decoder,
106     GstVideoCodecFrame * frame);
107
108 static gboolean
109 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps);
110
111 static void
112 gst_vaapi_decoder_notify_caps(GObject *obj, GParamSpec *pspec, void *user_data)
113 {
114     GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
115     GstCaps *caps;
116
117     g_assert(decode->decoder == GST_VAAPI_DECODER(obj));
118
119     caps = gst_vaapi_decoder_get_caps(decode->decoder);
120     /*negotiate with downstream once the caps property of GstVideoDecoder has changed*/
121     gst_vaapidecode_update_src_caps(decode, caps);
122 }
123
124 static inline gboolean
125 gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
126 {
127     if (decode->sinkpad_caps)
128         gst_caps_unref(decode->sinkpad_caps);
129     decode->sinkpad_caps = gst_caps_ref(caps);
130     return TRUE;
131 }
132
133 static gboolean
134 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps)
135 {
136     GstStructure *structure;
137     GstCaps *other_caps;
138     const GValue *v_width, *v_height, *v_framerate, *v_par, *v_interlace_mode;
139     gboolean success = TRUE;
140
141     if (!decode->srcpad_caps) {
142         decode->srcpad_caps = gst_caps_from_string("video/x-raw");
143         if (!decode->srcpad_caps)
144             return FALSE;
145     }
146     
147     structure    = gst_caps_get_structure(caps, 0);
148     v_width      = gst_structure_get_value(structure, "width");
149     v_height     = gst_structure_get_value(structure, "height");
150     v_framerate  = gst_structure_get_value(structure, "framerate");
151     v_par        = gst_structure_get_value(structure, "pixel-aspect-ratio");
152     v_interlace_mode = gst_structure_get_value(structure, "interlace-mode");
153
154     other_caps = decode->srcpad_caps;
155     decode->srcpad_caps = gst_caps_copy(decode->srcpad_caps);
156     gst_caps_unref(other_caps);
157
158     structure = gst_caps_get_structure(decode->srcpad_caps, 0); 
159     if (v_width && v_height) {
160         gst_structure_set_value(structure, "width", v_width);
161         gst_structure_set_value(structure, "height", v_height);
162     }
163     if (v_framerate)
164         gst_structure_set_value(structure, "framerate", v_framerate);
165     if (v_par)
166         gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
167     
168     /*Fixme: setting a new "va-interlace-mode" to get the interlacing working with vaapipostproc element*/
169     if (v_interlace_mode) 
170         gst_structure_set_value(structure, "va-interlace-mode", v_interlace_mode);
171     else
172         gst_structure_set(structure, "va-interlace-mode", G_TYPE_STRING, "progressive", NULL);
173
174     /*Fixme: setting interlace-mode to progressive , otherwise deinterlace element which is autoplugging 
175              in playbin will do the deinterlacing which will end up with unnecessary vaSurface mapping. */
176     gst_structure_set(structure, "interlace-mode", G_TYPE_STRING, "progressive", NULL);
177     /*Fixme: setting format to NV12 for now*/
178     gst_structure_set(structure, "format", G_TYPE_STRING, "NV12", NULL); /*Fixme*/
179     gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
180     gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
181
182     return TRUE;
183 }
184
185 static inline gboolean
186 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
187 {
188     return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
189         &decode->display);
190 }
191
192 static inline guint
193 gst_vaapi_codec_from_caps(GstCaps *caps)
194 {
195     return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
196 }
197
198 static gboolean
199 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
200 {
201     GstVaapiDisplay *dpy;
202
203     if (!gst_vaapidecode_ensure_display(decode))
204         return FALSE;
205     dpy = decode->display;
206
207     switch (gst_vaapi_codec_from_caps(caps)) {
208     case GST_VAAPI_CODEC_MPEG2:
209         decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
210         break;
211 #if 0
212     case GST_VAAPI_CODEC_MPEG4:
213     case GST_VAAPI_CODEC_H263:
214         decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
215         break;
216 #endif
217     case GST_VAAPI_CODEC_H264:
218         decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
219         break;
220     case GST_VAAPI_CODEC_WMV3:
221     case GST_VAAPI_CODEC_VC1:
222         decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
223         break;
224 #if USE_JPEG_DECODER
225     case GST_VAAPI_CODEC_JPEG:
226         decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
227         break;
228 #endif
229     default:
230         decode->decoder = NULL;
231         break;
232     }
233     if (!decode->decoder)
234         return FALSE;
235
236     g_signal_connect(
237         G_OBJECT(decode->decoder),
238         "notify::caps",
239         G_CALLBACK(gst_vaapi_decoder_notify_caps),
240         decode
241     );
242
243     decode->decoder_caps = gst_caps_ref(caps);
244     return TRUE;
245 }
246
247 static void
248 gst_vaapidecode_destroy(GstVaapiDecode *decode)
249 {
250     if (decode->decoder) {
251         g_object_unref(decode->decoder);
252         decode->decoder = NULL;
253     }
254     if (decode->decoder_caps) {
255         gst_caps_unref(decode->decoder_caps);
256         decode->decoder_caps = NULL;
257     }
258 }
259
260 static gboolean
261 gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
262 {
263     GstVaapiCodec codec;
264
265     /* Only reset decoder if codec type changed */
266     if (decode->decoder && decode->decoder_caps) {
267         if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
268             return TRUE;
269         codec = gst_vaapi_codec_from_caps(caps);
270         if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
271             return TRUE;
272     }
273
274     gst_vaapidecode_destroy(decode);
275     return gst_vaapidecode_create(decode, caps);
276 }
277
278 /* GstVideoContext interface */
279 static void
280 gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
281     const GValue *value)
282 {
283     GstVaapiDecode *decode = GST_VAAPIDECODE (context);
284     gst_vaapi_set_display (type, value, &decode->display);
285 }
286
287 static void
288 gst_video_context_interface_init(GstVideoContextInterface *iface)
289 {
290     iface->set_context = gst_vaapidecode_set_video_context;
291 }
292
293 static void
294 gst_vaapidecode_finalize(GObject *object)
295 {
296     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
297
298     gst_vaapidecode_destroy(decode);
299
300     if (decode->sinkpad_caps) {
301         gst_caps_unref(decode->sinkpad_caps);
302         decode->sinkpad_caps = NULL;
303     }
304
305     if (decode->srcpad_caps) {
306         gst_caps_unref(decode->srcpad_caps);
307         decode->srcpad_caps = NULL;
308     }
309
310     g_clear_object(&decode->display);
311
312     if (decode->allowed_caps) {
313         gst_caps_unref(decode->allowed_caps);
314         decode->allowed_caps = NULL;
315     }
316
317     G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
318 }
319
320 static void
321 gst_vaapidecode_set_property(
322     GObject      *object,
323     guint         prop_id,
324     const GValue *value,
325     GParamSpec   *pspec
326 )
327 {
328     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
329
330     switch (prop_id) {
331     default:
332         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
333         break;
334     }
335 }
336
337 static void
338 gst_vaapidecode_get_property(
339     GObject    *object,
340     guint       prop_id,
341     GValue     *value,
342     GParamSpec *pspec
343 )
344 {
345     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
346
347     switch (prop_id) {
348     default:
349         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
350         break;
351     }
352 }
353
354 static void
355 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
356 {
357     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
358     GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
359     GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
360     GstPadTemplate *pad_template;
361
362     GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
363                             GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
364
365     object_class->finalize      = gst_vaapidecode_finalize;
366
367     video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_vaapi_dec_open);
368     video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_vaapi_dec_start);
369     video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vaapi_dec_stop);
370     video_decoder_class->reset = GST_DEBUG_FUNCPTR (gst_vaapi_dec_reset);
371     video_decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vaapi_dec_set_format);
372     video_decoder_class->decide_allocation = GST_DEBUG_FUNCPTR(gst_vaapi_dec_decide_allocation);
373     video_decoder_class->parse = GST_DEBUG_FUNCPTR (gst_vaapi_dec_parse);
374     video_decoder_class->handle_frame =
375       GST_DEBUG_FUNCPTR (gst_vaapi_dec_handle_frame);
376    
377     gst_element_class_set_static_metadata (element_class,
378       "VA-API decoder",
379       "Codec/Decoder/Video", GST_PLUGIN_DESC,
380       "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
381
382    /* sink pad */
383    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_vaapidecode_sink_factory));
384
385    /* src pad */
386    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_vaapidecode_src_factory));
387 }
388
389 /* Fixme? : No more get_caps..Is there any need to test the allowded caps(allowded by current display) ? */
390 #if 0
391 static gboolean
392 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
393 {
394     GstCaps *decode_caps;
395     guint i, n_decode_caps;
396
397     if (decode->allowed_caps)
398         return TRUE;
399
400     if (!gst_vaapidecode_ensure_display(decode))
401         goto error_no_display;
402
403     decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
404     if (!decode_caps)
405         goto error_no_decode_caps;
406     n_decode_caps = gst_caps_get_size(decode_caps);
407
408     decode->allowed_caps = gst_caps_new_empty();
409     if (!decode->allowed_caps)
410         goto error_no_memory;
411
412     for (i = 0; i < n_decode_caps; i++) {
413         GstStructure *structure;
414         structure = gst_caps_get_structure(decode_caps, i);
415         if (!structure)
416             continue;
417         structure = gst_structure_copy(structure);
418         if (!structure)
419             continue;
420         gst_structure_remove_field(structure, "profile");
421         gst_structure_set(
422             structure,
423             "width",  GST_TYPE_INT_RANGE, 1, G_MAXINT,
424             "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
425             NULL
426         );
427         gst_caps_merge_structure(decode->allowed_caps, structure);
428     }
429
430     gst_caps_unref(decode_caps);
431     return TRUE;
432
433     /* ERRORS */
434 error_no_display:
435     {
436         GST_DEBUG("failed to retrieve VA display");
437         return FALSE;
438     }
439 error_no_decode_caps:
440     {
441         GST_DEBUG("failed to retrieve VA decode caps");
442         return FALSE;
443     }
444 error_no_memory:
445     {
446         GST_DEBUG("failed to allocate allowed-caps set");
447         gst_caps_unref(decode_caps);
448         return FALSE;
449     }
450 }
451
452 static GstCaps *
453 gst_vaapidecode_get_caps(GstVaapiDecode *decode, GstPad *pad, GstCaps *filter)
454 {
455     if (!decode->is_ready)
456         return gst_static_pad_template_get_caps(&gst_vaapidecode_sink_factory);
457
458     if (!gst_vaapidecode_ensure_allowed_caps(decode))
459         return gst_caps_new_empty();
460
461     return gst_caps_ref(decode->allowed_caps);
462 }
463 #endif
464
465 static gboolean
466 gst_vaapidecode_query (GstPad *pad, GstObject *parent, GstQuery *query) {
467     GstVaapiDecode *decode = GST_VAAPIDECODE (parent);
468     GstVideoDecoder *bdec  = GST_VIDEO_DECODER (decode);
469     gboolean res = TRUE;
470
471     GST_DEBUG ("sharing display %p", decode->display);
472
473     if (gst_vaapi_reply_to_query (query, decode->display))
474        res = TRUE;
475     else {
476       if (GST_PAD_IS_SINK(pad))
477         res = decode->sinkpad_qfunc (GST_VIDEO_DECODER_SINK_PAD(bdec), parent,  query);
478       else
479         res = decode->srcpad_qfunc (GST_VIDEO_DECODER_SRC_PAD(bdec), parent, query);
480     }
481     return res;
482 }
483
484 static void
485 gst_vaapidecode_init(GstVaapiDecode *decode)
486 {
487     GstVideoDecoder *bdec       = GST_VIDEO_DECODER (decode);
488     decode->display             = NULL;
489     decode->decoder             = NULL;
490     decode->is_ready            = FALSE;
491     decode->sinkpad_caps        = NULL;
492     decode->srcpad_caps         = NULL;
493     decode->decoder_caps        = NULL;
494     decode->allowed_caps        = NULL;
495
496     decode->sinkpad_qfunc       = GST_PAD_QUERYFUNC (GST_VIDEO_DECODER_SINK_PAD(bdec));
497     decode->srcpad_qfunc        = GST_PAD_QUERYFUNC (GST_VIDEO_DECODER_SRC_PAD(bdec));
498
499     gst_pad_set_query_function(GST_VIDEO_DECODER_SINK_PAD(decode), gst_vaapidecode_query);
500     gst_pad_set_query_function(GST_VIDEO_DECODER_SRC_PAD(decode), gst_vaapidecode_query); 
501  
502     gst_video_decoder_set_packetized (GST_VIDEO_DECODER(decode), FALSE);
503 }
504
505 static gboolean
506 gst_vaapi_dec_open(GstVideoDecoder *decoder)
507 {
508     GstVaapiDecode *dec = GST_VAAPIDECODE (decoder);
509     GST_DEBUG_OBJECT (decoder, "open");
510     dec->is_ready = TRUE;
511     return TRUE;
512 }
513
514 static gboolean
515 gst_vaapi_dec_start(GstVideoDecoder * decoder)
516 {
517     GstVaapiDecode *dec = GST_VAAPIDECODE (decoder);
518     gboolean ret = TRUE;
519
520     GST_DEBUG_OBJECT (decoder, "start");
521     if (!gst_vaapi_decoder_start(dec->decoder)) {
522         GST_ERROR_OBJECT(decoder, "Failed to start the processing..");
523         ret = FALSE;
524     }
525
526     return ret;
527 }
528
529 static gboolean
530 gst_vaapi_dec_stop(GstVideoDecoder * decoder)
531 {
532     GstVaapiDecode *dec = GST_VAAPIDECODE (decoder);
533     gboolean ret = TRUE; 
534     
535     GST_DEBUG_OBJECT (dec, "stop");
536
537     if (!gst_vaapi_decoder_stop(dec->decoder)) {
538         GST_ERROR_OBJECT(decoder, "Failed to stop processing,,");
539         ret = FALSE;
540     }
541     dec->is_ready = FALSE;
542
543     return ret;
544 }
545
546 /*To perform post-seek semantics reset*/
547 static gboolean
548 gst_vaapi_dec_reset(GstVideoDecoder * bdec, gboolean hard)
549 {
550     GstVaapiDecode *dec = GST_VAAPIDECODE (bdec);
551   
552     GST_DEBUG_OBJECT (dec, "reset");
553     if(dec->decoder) {
554         if(!gst_vaapi_decoder_reset(dec->decoder)){
555             GST_ERROR_OBJECT(dec, "Failed to reset : seeking might fail..");
556             return FALSE;
557         }
558     }
559     return TRUE;
560 }
561
562 static gboolean
563 gst_vaapi_dec_set_format(GstVideoDecoder * bdec, GstVideoCodecState * state)
564 {
565     GstVaapiDecode *dec;
566     GstCaps *caps;
567     GstVideoInfo info;
568     guint width, height;
569     GstVaapiDisplay *dpy;
570     GstStructure *structure;
571     GstVideoFormat fmt;
572     
573     dec = GST_VAAPIDECODE (bdec);
574     if (!state)
575         return FALSE;
576  
577     /* Keep a copy of the input state */
578     if (dec->input_state)
579         gst_video_codec_state_unref (dec->input_state);
580     dec->input_state = gst_video_codec_state_ref (state);
581
582     info = state->info;
583     caps = state->caps;
584     width = info.width;
585     height = info.height;
586
587     if (!gst_vaapidecode_update_sink_caps(dec, caps))
588         return FALSE;
589
590     if (!gst_vaapidecode_update_src_caps(dec, caps))
591         return FALSE;
592
593     if (!gst_vaapidecode_reset(dec, dec->sinkpad_caps))
594         return FALSE;
595     
596     /*Fixme: add codec_dat hadling from state->codec_data*/
597 }
598
599 static GstFlowReturn
600 gst_vaapi_dec_parse(GstVideoDecoder * decoder,
601     GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
602 {
603     GstVaapiDecode *dec;
604     GstVaapiDecoderStatus status;
605     GstFlowReturn ret = GST_FLOW_OK;
606     gint toadd;
607     gboolean have_frame = FALSE;
608
609     dec = GST_VAAPIDECODE (decoder);
610     if (at_eos) {
611         GST_DEBUG_OBJECT (dec, "Stop parsing and render the pending frames");
612         gst_video_decoder_add_to_frame(decoder, gst_adapter_available (adapter));
613         ret = gst_video_decoder_have_frame(decoder);
614         goto beach;
615     }
616
617     status = gst_vaapi_decoder_parse(dec->decoder, adapter, &toadd, &have_frame);
618     /* if parse() returns GST_VAAPI_DECODER_STATUS_SUCCESS,
619         -- size we got in #toadd is to be added to #frame
620         -- send the data for decoding if #have_frame is TRUE */
621     if (status == GST_VAAPI_DECODER_STATUS_SUCCESS) {
622         
623         if(toadd) 
624             gst_video_decoder_add_to_frame(decoder, toadd);
625         if(have_frame)
626             ret = gst_video_decoder_have_frame(decoder);
627         goto beach; 
628
629     } else if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) {
630           ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
631           goto beach;
632     } else
633           goto error_decode;
634
635     error_decode:
636     {
637          GST_DEBUG("parse/decode error %d", status);
638          switch (status) {
639          case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
640          case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
641          case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
642              ret = GST_FLOW_NOT_SUPPORTED;
643              break;
644          default:
645              ret = GST_FLOW_EOS;
646              break;
647          }
648     }   
649 beach: 
650     return ret;
651 }
652
653 static gboolean
654 gst_vaapi_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
655 {
656     GstVaapiDecode *dec = GST_VAAPIDECODE (decoder);
657     GstVideoCodecState *state;
658     GstBufferPool *pool;
659     guint size, min, max;
660     GstStructure *config, *structure;
661     GstVideoInfo info;
662     GstCaps *caps;
663     gboolean ret;
664     gboolean need_pool;
665
666     gst_query_parse_allocation (query, &caps, &need_pool);
667
668     if (need_pool) {
669         ret = gst_vaapi_decoder_decide_allocation (dec->decoder, query);
670         if (!ret) {
671             GST_DEBUG_OBJECT (dec, "Failed to allocate buffer pool..");
672             return FALSE;
673         }
674     }
675     return  TRUE;
676 }
677
678 static void
679 gst_vaapi_dec_negotiate(GstVideoDecoder *dec)
680
681     GstVaapiDecode *vaapi_dec;
682     GstVideoCodecState *outstate;
683     GstVideoInfo srcpad_info, outstate_info;
684     GstVideoFormat format;
685     GstCaps *caps;
686
687     vaapi_dec = GST_VAAPIDECODE(dec);
688     
689     if(vaapi_dec->srcpad_caps)   
690         gst_video_info_from_caps(&srcpad_info, vaapi_dec->srcpad_caps);
691
692     outstate = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec));
693     if (outstate) {
694         gst_video_info_from_caps(&outstate_info, outstate->caps);
695         if (srcpad_info.width                   == outstate_info.width &&
696             srcpad_info.height                  == outstate_info.height &&
697             GST_VIDEO_INFO_FORMAT(&srcpad_info) == GST_VIDEO_INFO_FORMAT(&outstate_info)) {
698
699             gst_video_codec_state_unref (outstate);
700             return;
701         } 
702         gst_video_codec_state_unref (outstate);
703     }
704     /*Fixme: Setting o/p state has no effect now since we manually set the output_state->caps to srcpad_caps */
705     vaapi_dec->output_state =
706         gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), GST_VIDEO_FORMAT_NV12,
707         srcpad_info.width, srcpad_info.height, vaapi_dec->input_state);
708
709     vaapi_dec->output_state->caps = vaapi_dec->srcpad_caps;
710     gst_video_decoder_negotiate (dec); 
711 }
712
713 static GstFlowReturn
714 gst_vaapi_dec_handle_frame(GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
715 {
716     GstVaapiDecode *dec;
717     GstVideoCodecFrame *frame_out = NULL;
718     gint frame_id = -1;
719     GstVaapiSurfaceProxy *proxy;
720     GstBuffer *buffer;
721     GstFlowReturn ret = GST_FLOW_OK;
722     GstVaapiDecoderStatus status;
723     GstVaapiSurfaceMeta *meta;
724
725     dec = GST_VAAPIDECODE(bdec);
726
727     gst_vaapi_dec_negotiate (bdec);
728     
729     proxy = gst_vaapi_decoder_get_surface(dec->decoder, frame,  &status);
730
731     do {
732         if (proxy) {
733             buffer = gst_vaapi_surface_proxy_get_surface_buffer(proxy);
734             if (!buffer)
735                 goto error_create_buffer;
736
737             GST_BUFFER_TIMESTAMP(buffer) = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
738  
739             meta = gst_buffer_get_vaapi_surface_meta (buffer);
740
741             /*Fixme: add to videometa? */           
742             if (GST_VAAPI_SURFACE_PROXY_INTERLACED(proxy)) {
743                 meta->interlaced = TRUE;
744                 if (GST_VAAPI_SURFACE_PROXY_TFF(proxy))
745                     meta->tff = TRUE;
746                 else
747                     meta->tff = FALSE;
748             } 
749
750             frame_id  = gst_vaapi_surface_proxy_get_frame_id(proxy);
751             frame_out = gst_video_decoder_get_frame(bdec, frame_id);
752             frame_out->output_buffer = buffer;
753             frame_out->pts = GST_BUFFER_TIMESTAMP(buffer);
754             ret = gst_video_decoder_finish_frame(bdec, frame_out);
755             if (ret != GST_FLOW_OK)
756                 goto error_commit_buffer;               
757             /*gvd_get_frame() creating an extra ref which we need to unref*/
758             gst_video_codec_frame_unref (frame_out);
759             g_object_unref (proxy);
760         } 
761         else if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
762             goto error_decode;
763
764         proxy = gst_vaapi_decoder_get_surface(dec->decoder, NULL,  &status);
765
766     }while (proxy); /* to handle SEQUENCE_END, multiple frames might be pending to render*/
767    
768     return ret;
769  
770 error_decode:
771     {
772         GST_DEBUG("decode error %d", status);
773         return GST_FLOW_EOS;
774     }
775 error_create_buffer:
776     {
777          const GstVaapiID surface_id =
778              gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
779
780          GST_DEBUG("video sink failed to create video buffer for proxy'ed "
781                   "surface %" GST_VAAPI_ID_FORMAT " (error %d)",
782                   GST_VAAPI_ID_ARGS(surface_id), ret);
783          g_object_unref(proxy);
784          return GST_FLOW_EOS;
785     }
786 error_commit_buffer:
787     {
788         GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
789         g_object_unref(proxy);
790         return GST_FLOW_EOS;
791     }
792 }