vaapidecoder, vaapidecode: signal the interlacing property in caps
[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     if (v_interlace_mode) 
168         gst_structure_set_value(structure, "interlace-mode", v_interlace_mode);
169     else
170         gst_structure_set(structure, "interlace-mode", G_TYPE_STRING, "progressive", NULL);
171
172     /*Fixme: setting interlace-mode to progressive , otherwise deinterlace element which is 
173              autoplugging in playbin will change the caps and which will create a mess */
174     gst_structure_set(structure, "interlace-mode", G_TYPE_STRING, "progressive", NULL);
175     /*Fixme: setting format to NV12 for now*/
176     gst_structure_set(structure, "format", G_TYPE_STRING, "NV12", NULL); /*Fixme*/
177     gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
178     gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
179
180     return TRUE;
181 }
182
183 static inline gboolean
184 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
185 {
186     return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
187         &decode->display);
188 }
189
190 static inline guint
191 gst_vaapi_codec_from_caps(GstCaps *caps)
192 {
193     return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
194 }
195
196 static gboolean
197 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
198 {
199     GstVaapiDisplay *dpy;
200
201     if (!gst_vaapidecode_ensure_display(decode))
202         return FALSE;
203     dpy = decode->display;
204
205     switch (gst_vaapi_codec_from_caps(caps)) {
206     case GST_VAAPI_CODEC_MPEG2:
207         decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
208         break;
209 #if 0
210     case GST_VAAPI_CODEC_MPEG4:
211     case GST_VAAPI_CODEC_H263:
212         decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
213         break;
214 #endif
215     case GST_VAAPI_CODEC_H264:
216         decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
217         break;
218     case GST_VAAPI_CODEC_WMV3:
219     case GST_VAAPI_CODEC_VC1:
220         decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
221         break;
222 #if USE_JPEG_DECODER
223     case GST_VAAPI_CODEC_JPEG:
224         decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
225         break;
226 #endif
227     default:
228         decode->decoder = NULL;
229         break;
230     }
231     if (!decode->decoder)
232         return FALSE;
233
234     g_signal_connect(
235         G_OBJECT(decode->decoder),
236         "notify::caps",
237         G_CALLBACK(gst_vaapi_decoder_notify_caps),
238         decode
239     );
240
241     decode->decoder_caps = gst_caps_ref(caps);
242     return TRUE;
243 }
244
245 static void
246 gst_vaapidecode_destroy(GstVaapiDecode *decode)
247 {
248     if (decode->decoder) {
249         g_object_unref(decode->decoder);
250         decode->decoder = NULL;
251     }
252     if (decode->decoder_caps) {
253         gst_caps_unref(decode->decoder_caps);
254         decode->decoder_caps = NULL;
255     }
256 }
257
258 static gboolean
259 gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
260 {
261     GstVaapiCodec codec;
262
263     /* Only reset decoder if codec type changed */
264     if (decode->decoder && decode->decoder_caps) {
265         if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
266             return TRUE;
267         codec = gst_vaapi_codec_from_caps(caps);
268         if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
269             return TRUE;
270     }
271
272     gst_vaapidecode_destroy(decode);
273     return gst_vaapidecode_create(decode, caps);
274 }
275
276 /* GstVideoContext interface */
277 static void
278 gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
279     const GValue *value)
280 {
281     GstVaapiDecode *decode = GST_VAAPIDECODE (context);
282     gst_vaapi_set_display (type, value, &decode->display);
283 }
284
285 static void
286 gst_video_context_interface_init(GstVideoContextInterface *iface)
287 {
288     iface->set_context = gst_vaapidecode_set_video_context;
289 }
290
291 static void
292 gst_vaapidecode_finalize(GObject *object)
293 {
294     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
295
296     gst_vaapidecode_destroy(decode);
297
298     if (decode->sinkpad_caps) {
299         gst_caps_unref(decode->sinkpad_caps);
300         decode->sinkpad_caps = NULL;
301     }
302
303     if (decode->srcpad_caps) {
304         gst_caps_unref(decode->srcpad_caps);
305         decode->srcpad_caps = NULL;
306     }
307
308     g_clear_object(&decode->display);
309
310     if (decode->allowed_caps) {
311         gst_caps_unref(decode->allowed_caps);
312         decode->allowed_caps = NULL;
313     }
314
315     G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
316 }
317
318 static void
319 gst_vaapidecode_set_property(
320     GObject      *object,
321     guint         prop_id,
322     const GValue *value,
323     GParamSpec   *pspec
324 )
325 {
326     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
327
328     switch (prop_id) {
329     default:
330         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
331         break;
332     }
333 }
334
335 static void
336 gst_vaapidecode_get_property(
337     GObject    *object,
338     guint       prop_id,
339     GValue     *value,
340     GParamSpec *pspec
341 )
342 {
343     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
344
345     switch (prop_id) {
346     default:
347         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
348         break;
349     }
350 }
351
352 static void
353 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
354 {
355     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
356     GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
357     GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
358     GstPadTemplate *pad_template;
359
360     GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
361                             GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
362
363     object_class->finalize      = gst_vaapidecode_finalize;
364
365     video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_vaapi_dec_open);
366     video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_vaapi_dec_start);
367     video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vaapi_dec_stop);
368     video_decoder_class->reset = GST_DEBUG_FUNCPTR (gst_vaapi_dec_reset);
369     video_decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vaapi_dec_set_format);
370     video_decoder_class->decide_allocation = GST_DEBUG_FUNCPTR(gst_vaapi_dec_decide_allocation);
371     video_decoder_class->parse = GST_DEBUG_FUNCPTR (gst_vaapi_dec_parse);
372     video_decoder_class->handle_frame =
373       GST_DEBUG_FUNCPTR (gst_vaapi_dec_handle_frame);
374    
375     gst_element_class_set_static_metadata (element_class,
376       "VA-API decoder",
377       "Codec/Decoder/Video", GST_PLUGIN_DESC,
378       "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
379
380    /* sink pad */
381    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_vaapidecode_sink_factory));
382
383    /* src pad */
384    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&gst_vaapidecode_src_factory));
385 }
386
387 /* Fixme? : No more get_caps..Is there any need to test the allowded caps(allowded by current display) ? */
388 #if 0
389 static gboolean
390 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
391 {
392     GstCaps *decode_caps;
393     guint i, n_decode_caps;
394
395     if (decode->allowed_caps)
396         return TRUE;
397
398     if (!gst_vaapidecode_ensure_display(decode))
399         goto error_no_display;
400
401     decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
402     if (!decode_caps)
403         goto error_no_decode_caps;
404     n_decode_caps = gst_caps_get_size(decode_caps);
405
406     decode->allowed_caps = gst_caps_new_empty();
407     if (!decode->allowed_caps)
408         goto error_no_memory;
409
410     for (i = 0; i < n_decode_caps; i++) {
411         GstStructure *structure;
412         structure = gst_caps_get_structure(decode_caps, i);
413         if (!structure)
414             continue;
415         structure = gst_structure_copy(structure);
416         if (!structure)
417             continue;
418         gst_structure_remove_field(structure, "profile");
419         gst_structure_set(
420             structure,
421             "width",  GST_TYPE_INT_RANGE, 1, G_MAXINT,
422             "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
423             NULL
424         );
425         gst_caps_merge_structure(decode->allowed_caps, structure);
426     }
427
428     gst_caps_unref(decode_caps);
429     return TRUE;
430
431     /* ERRORS */
432 error_no_display:
433     {
434         GST_DEBUG("failed to retrieve VA display");
435         return FALSE;
436     }
437 error_no_decode_caps:
438     {
439         GST_DEBUG("failed to retrieve VA decode caps");
440         return FALSE;
441     }
442 error_no_memory:
443     {
444         GST_DEBUG("failed to allocate allowed-caps set");
445         gst_caps_unref(decode_caps);
446         return FALSE;
447     }
448 }
449
450 static GstCaps *
451 gst_vaapidecode_get_caps(GstVaapiDecode *decode, GstPad *pad, GstCaps *filter)
452 {
453     if (!decode->is_ready)
454         return gst_static_pad_template_get_caps(&gst_vaapidecode_sink_factory);
455
456     if (!gst_vaapidecode_ensure_allowed_caps(decode))
457         return gst_caps_new_empty();
458
459     return gst_caps_ref(decode->allowed_caps);
460 }
461 #endif
462
463 static gboolean
464 gst_vaapidecode_query (GstPad *pad, GstObject *parent, GstQuery *query) {
465     GstVaapiDecode *decode = GST_VAAPIDECODE (parent);
466     GstVideoDecoder *bdec  = GST_VIDEO_DECODER (decode);
467     gboolean res = TRUE;
468
469     GST_DEBUG ("sharing display %p", decode->display);
470
471     if (gst_vaapi_reply_to_query (query, decode->display))
472        res = TRUE;
473     else {
474       if (GST_PAD_IS_SINK(pad))
475         res = decode->sinkpad_qfunc (GST_VIDEO_DECODER_SINK_PAD(bdec), parent,  query);
476       else
477         res = decode->srcpad_qfunc (GST_VIDEO_DECODER_SRC_PAD(bdec), parent, query);
478     }
479     return res;
480 }
481
482 static void
483 gst_vaapidecode_init(GstVaapiDecode *decode)
484 {
485     GstVideoDecoder *bdec       = GST_VIDEO_DECODER (decode);
486     decode->display             = NULL;
487     decode->decoder             = NULL;
488     decode->is_ready            = FALSE;
489     decode->sinkpad_caps        = NULL;
490     decode->srcpad_caps         = NULL;
491     decode->decoder_caps        = NULL;
492     decode->allowed_caps        = NULL;
493
494     decode->sinkpad_qfunc       = GST_PAD_QUERYFUNC (GST_VIDEO_DECODER_SINK_PAD(bdec));
495     decode->srcpad_qfunc        = GST_PAD_QUERYFUNC (GST_VIDEO_DECODER_SRC_PAD(bdec));
496
497     gst_pad_set_query_function(GST_VIDEO_DECODER_SINK_PAD(decode), gst_vaapidecode_query);
498     gst_pad_set_query_function(GST_VIDEO_DECODER_SRC_PAD(decode), gst_vaapidecode_query); 
499  
500     /*gst_pad_set_getcaps_function(GST_VIDEO_DECODER (decode)->sinkpad, gst_vaapidecode_get_caps); */
501     gst_video_decoder_set_packetized (GST_VIDEO_DECODER(decode), FALSE);
502     
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 sice we manually setting 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_surface2(dec->decoder, frame,  &status); /*will merge with gvd_get_surface later*/
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 =  (GstVaapiSurfaceMeta *)gst_buffer_get_meta((buffer),GST_VAAPI_SURFACE_META_API_TYPE);
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         /*Fixme: this will change with gvd_get_surface2() with frame=NULL*/
765         proxy = gst_vaapi_decoder_get_surface_proxy(dec->decoder);
766
767     }while (proxy); /* to handle SEQUENCE_END, multiple frames might be pending to render*/
768    
769     return ret;
770  
771 error_decode:
772     {
773         GST_DEBUG("decode error %d", status);
774         return GST_FLOW_EOS;
775     }
776 error_create_buffer:
777     {
778          const GstVaapiID surface_id =
779              gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
780
781          GST_DEBUG("video sink failed to create video buffer for proxy'ed "
782                   "surface %" GST_VAAPI_ID_FORMAT " (error %d)",
783                   GST_VAAPI_ID_ARGS(surface_id), ret);
784          g_object_unref(proxy);
785          return GST_FLOW_EOS;
786     }
787 error_commit_buffer:
788     {
789         GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
790         g_object_unref(proxy);
791         return GST_FLOW_EOS;
792     }
793 }