decoder: h264: add support for NALU "alignment" optimization.
[platform/upstream/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  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2014 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23 */
24
25 /**
26  * SECTION:gstvaapidecode
27  * @short_description: A VA-API based video decoder
28  *
29  * vaapidecode decodes from raw bitstreams to surfaces suitable for
30  * the vaapisink element.
31  */
32
33 #include "gst/vaapi/sysdeps.h"
34 #include <gst/vaapi/gstvaapidisplay.h>
35
36 #include "gstvaapidecode.h"
37 #include "gstvaapipluginutil.h"
38 #include "gstvaapivideobuffer.h"
39 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
40 #include "gstvaapivideometa_texture.h"
41 #endif
42 #if GST_CHECK_VERSION(1,0,0)
43 #include "gstvaapivideobufferpool.h"
44 #include "gstvaapivideomemory.h"
45 #endif
46
47 #include <gst/vaapi/gstvaapidecoder_h264.h>
48 #include <gst/vaapi/gstvaapidecoder_jpeg.h>
49 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
50 #include <gst/vaapi/gstvaapidecoder_mpeg4.h>
51 #include <gst/vaapi/gstvaapidecoder_vc1.h>
52 #include <gst/vaapi/gstvaapidecoder_vp8.h>
53
54 #define GST_PLUGIN_NAME "vaapidecode"
55 #define GST_PLUGIN_DESC "A VA-API based video decoder"
56
57 #define GST_VAAPI_DECODE_FLOW_PARSE_DATA        GST_FLOW_CUSTOM_SUCCESS_2
58
59 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
60 #define GST_CAT_DEFAULT gst_debug_vaapidecode
61
62 /* Default templates */
63 #define GST_CAPS_CODEC(CODEC) CODEC "; "
64
65 static const char gst_vaapidecode_sink_caps_str[] =
66     GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
67     GST_CAPS_CODEC("video/mpeg, mpegversion=4")
68     GST_CAPS_CODEC("video/x-divx")
69     GST_CAPS_CODEC("video/x-xvid")
70     GST_CAPS_CODEC("video/x-h263")
71     GST_CAPS_CODEC("video/x-h264")
72     GST_CAPS_CODEC("video/x-wmv")
73     GST_CAPS_CODEC("video/x-vp8")
74     GST_CAPS_CODEC("image/jpeg")
75     ;
76
77 static const char gst_vaapidecode_src_caps_str[] =
78 #if GST_CHECK_VERSION(1,1,0)
79     GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
80         GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, NV12, I420, YV12 }") ";"
81     GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
82         GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "RGBA") ";"
83     GST_VIDEO_CAPS_MAKE("{ NV12, I420, YV12 }");
84 #else
85     GST_VAAPI_SURFACE_CAPS;
86 #endif
87
88 static GstStaticPadTemplate gst_vaapidecode_sink_factory =
89     GST_STATIC_PAD_TEMPLATE(
90         "sink",
91         GST_PAD_SINK,
92         GST_PAD_ALWAYS,
93         GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
94
95 static GstStaticPadTemplate gst_vaapidecode_src_factory =
96     GST_STATIC_PAD_TEMPLATE(
97         "src",
98         GST_PAD_SRC,
99         GST_PAD_ALWAYS,
100         GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
101
102 G_DEFINE_TYPE_WITH_CODE(
103     GstVaapiDecode,
104     gst_vaapidecode,
105     GST_TYPE_VIDEO_DECODER,
106     GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES)
107
108 static gboolean
109 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
110     const GstVideoCodecState *ref_state);
111
112 static void
113 gst_vaapi_decoder_state_changed(GstVaapiDecoder *decoder,
114     const GstVideoCodecState *codec_state, gpointer user_data)
115 {
116     GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
117     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
118
119     g_assert(decode->decoder == decoder);
120
121     gst_vaapidecode_update_src_caps(decode, codec_state);
122     gst_video_decoder_negotiate(vdec);
123 }
124
125 static inline gboolean
126 gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
127 {
128     gst_caps_replace(&decode->sinkpad_caps, caps);
129     return TRUE;
130 }
131
132 static void
133 gst_vaapidecode_video_info_change_format(GstVideoInfo *info,
134     GstVideoFormat format, guint width, guint height)
135 {
136     GstVideoInfo vi = *info;
137
138     gst_video_info_set_format (info, format, width, height);
139
140     info->interlace_mode = vi.interlace_mode;
141     info->flags = vi.flags;
142     info->views = vi.views;
143     info->par_n = vi.par_n;
144     info->par_d = vi.par_d;
145     info->fps_n = vi.fps_n;
146     info->fps_d = vi.fps_d;
147 }
148
149 static gboolean
150 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
151     const GstVideoCodecState *ref_state)
152 {
153     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
154     GstVideoCodecState *state;
155     GstVideoInfo *vi, vis;
156 #if GST_CHECK_VERSION(1,1,0)
157     GstCapsFeatures *features = NULL;
158     GstVaapiCapsFeature feature;
159
160     feature = gst_vaapi_find_preferred_caps_feature(
161         GST_VIDEO_DECODER_SRC_PAD(vdec),
162         GST_VIDEO_INFO_FORMAT(&ref_state->info));
163 #endif
164
165     state = gst_video_decoder_set_output_state(vdec,
166         GST_VIDEO_INFO_FORMAT(&ref_state->info),
167         ref_state->info.width, ref_state->info.height,
168         (GstVideoCodecState *)ref_state);
169     if (!state)
170         return FALSE;
171
172     vi = &state->info;
173     if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
174         gst_video_info_init(&vis);
175         gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
176             GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
177         vi->size = vis.size;
178     }
179     gst_video_codec_state_unref(state);
180
181 #if GST_CHECK_VERSION(1,1,0)
182     vis = *vi;
183     switch (feature) {
184     case GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META:
185         gst_vaapidecode_video_info_change_format(&vis, GST_VIDEO_FORMAT_RGBA,
186             GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
187         features = gst_caps_features_new(
188             GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
189         break;
190     default:
191         if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
192             /* XXX: this is a workaround until auto-plugging is fixed when
193             format=ENCODED + memory:VASurface caps feature are provided.
194             Meanwhile, providing a random format here works but this is
195             a terribly wrong thing per se. */
196             gst_vaapidecode_video_info_change_format(&vis, GST_VIDEO_FORMAT_NV12,
197                 GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
198 #if GST_CHECK_VERSION(1,3,0)
199             if (feature == GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
200                 features = gst_caps_features_new(
201                     GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL);
202 #endif
203         }
204         break;
205     }
206     state->caps = gst_video_info_to_caps(&vis);
207     if (features)
208         gst_caps_set_features(state->caps, 0, features);
209 #else
210     /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not
211        reconstruct suitable caps for "encoded" video formats */
212     state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
213     if (!state->caps)
214         return FALSE;
215
216     gst_caps_set_simple(state->caps,
217         "type", G_TYPE_STRING, "vaapi",
218         "opengl", G_TYPE_BOOLEAN, USE_GLX,
219         "width", G_TYPE_INT, vi->width,
220         "height", G_TYPE_INT, vi->height,
221         "framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d,
222         "pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d,
223         NULL);
224
225     gst_caps_set_interlaced(state->caps, vi);
226 #endif
227     gst_caps_replace(&decode->srcpad_caps, state->caps);
228     return TRUE;
229 }
230
231 static void
232 gst_vaapidecode_release(GstVaapiDecode *decode)
233 {
234     g_mutex_lock(&decode->decoder_mutex);
235     g_cond_signal(&decode->decoder_ready);
236     g_mutex_unlock(&decode->decoder_mutex);
237 }
238
239 static GstFlowReturn
240 gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
241 {
242     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
243     GstVaapiDecoderStatus status;
244     GstFlowReturn ret;
245
246     /* Decode current frame */
247     for (;;) {
248         status = gst_vaapi_decoder_decode(decode->decoder, frame);
249         if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
250             GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
251             g_mutex_lock(&decode->decoder_mutex);
252             g_cond_wait(&decode->decoder_ready, &decode->decoder_mutex);
253             g_mutex_unlock(&decode->decoder_mutex);
254             GST_VIDEO_DECODER_STREAM_LOCK(vdec);
255             if (decode->decoder_loop_status < 0)
256                 goto error_decode_loop;
257             continue;
258         }
259         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
260             goto error_decode;
261         break;
262     }
263
264     /* Try to report back early any error that occured in the decode task */
265     GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
266     GST_VIDEO_DECODER_STREAM_LOCK(vdec);
267     return decode->decoder_loop_status;
268
269     /* ERRORS */
270 error_decode_loop:
271     {
272         GST_ERROR("decode loop error %d", decode->decoder_loop_status);
273         gst_video_decoder_drop_frame(vdec, frame);
274         return decode->decoder_loop_status;
275     }
276 error_decode:
277     {
278         GST_ERROR("decode error %d", status);
279         switch (status) {
280         case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
281         case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
282         case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
283             ret = GST_FLOW_NOT_SUPPORTED;
284             break;
285         default:
286             ret = GST_FLOW_ERROR;
287             break;
288         }
289         gst_video_decoder_drop_frame(vdec, frame);
290         return ret;
291     }
292 }
293
294 static GstFlowReturn
295 gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec,
296     GstVideoCodecFrame *out_frame)
297 {
298     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
299     GstVaapiSurfaceProxy *proxy;
300     GstFlowReturn ret;
301 #if GST_CHECK_VERSION(1,0,0)
302     const GstVaapiRectangle *crop_rect;
303     GstVaapiVideoMeta *meta;
304     guint flags;
305 #endif
306
307     if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) {
308         proxy = gst_video_codec_frame_get_user_data(out_frame);
309
310         gst_vaapi_surface_proxy_set_destroy_notify(proxy,
311             (GDestroyNotify)gst_vaapidecode_release, decode);
312
313 #if GST_CHECK_VERSION(1,0,0)
314         ret = gst_video_decoder_allocate_output_frame(vdec, out_frame);
315         if (ret != GST_FLOW_OK)
316             goto error_create_buffer;
317
318         meta = gst_buffer_get_vaapi_video_meta(out_frame->output_buffer);
319         if (!meta)
320             goto error_get_meta;
321         gst_vaapi_video_meta_set_surface_proxy(meta, proxy);
322
323         flags = gst_vaapi_surface_proxy_get_flags(proxy);
324         if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
325             guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED;
326             if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF)
327                 out_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
328             if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF)
329                 out_flags |= GST_VIDEO_BUFFER_FLAG_RFF;
330             if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD)
331                 out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD;
332             GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags);
333         }
334
335         crop_rect = gst_vaapi_surface_proxy_get_crop_rect(proxy);
336         if (crop_rect) {
337             GstVideoCropMeta * const crop_meta =
338                 gst_buffer_add_video_crop_meta(out_frame->output_buffer);
339             if (crop_meta) {
340                 crop_meta->x = crop_rect->x;
341                 crop_meta->y = crop_rect->y;
342                 crop_meta->width = crop_rect->width;
343                 crop_meta->height = crop_rect->height;
344             }
345         }
346
347 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
348         if (decode->has_texture_upload_meta)
349             gst_buffer_ensure_texture_upload_meta(out_frame->output_buffer);
350 #endif
351 #else
352         out_frame->output_buffer =
353             gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
354         if (!out_frame->output_buffer)
355             goto error_create_buffer;
356 #endif
357     }
358
359     ret = gst_video_decoder_finish_frame(vdec, out_frame);
360     if (ret != GST_FLOW_OK)
361         goto error_commit_buffer;
362
363     gst_video_codec_frame_unref(out_frame);
364     return GST_FLOW_OK;
365
366     /* ERRORS */
367 error_create_buffer:
368     {
369         const GstVaapiID surface_id =
370             gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
371
372         GST_ERROR("video sink failed to create video buffer for proxy'ed "
373                   "surface %" GST_VAAPI_ID_FORMAT,
374                   GST_VAAPI_ID_ARGS(surface_id));
375         gst_video_decoder_drop_frame(vdec, out_frame);
376         gst_video_codec_frame_unref(out_frame);
377         return GST_FLOW_ERROR;
378     }
379 #if GST_CHECK_VERSION(1,0,0)
380 error_get_meta:
381     {
382         GST_ERROR("failed to get vaapi video meta attached to video buffer");
383         gst_video_decoder_drop_frame(vdec, out_frame);
384         gst_video_codec_frame_unref(out_frame);
385         return GST_FLOW_ERROR;
386     }
387 #endif
388 error_commit_buffer:
389     {
390         if (ret != GST_FLOW_FLUSHING)
391             GST_ERROR("video sink rejected the video buffer (error %d)", ret);
392         gst_video_codec_frame_unref(out_frame);
393         return ret;
394     }
395 }
396
397 static GstFlowReturn
398 gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
399 {
400     GstFlowReturn ret;
401
402     /* Make sure to release the base class stream lock so that decode
403        loop can call gst_video_decoder_finish_frame() without blocking */
404     GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
405     ret = gst_vaapidecode_decode_frame(vdec, frame);
406     GST_VIDEO_DECODER_STREAM_LOCK(vdec);
407     return ret;
408 }
409
410 static void
411 gst_vaapidecode_decode_loop(GstVaapiDecode *decode)
412 {
413     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
414     GstVaapiDecoderStatus status;
415     GstVideoCodecFrame *out_frame;
416     GstFlowReturn ret;
417
418     status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
419         &out_frame, 100000);
420
421     GST_VIDEO_DECODER_STREAM_LOCK(vdec);
422     switch (status) {
423     case GST_VAAPI_DECODER_STATUS_SUCCESS:
424         ret = gst_vaapidecode_push_decoded_frame(vdec, out_frame);
425         break;
426     case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
427         ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
428         break;
429     default:
430         ret = GST_FLOW_ERROR;
431         break;
432     }
433     decode->decoder_loop_status = ret;
434     GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
435
436     if (ret == GST_FLOW_OK)
437         return;
438
439     /* If invoked from gst_vaapidecode_finish(), then return right
440        away no matter the errors, or the GstVaapiDecoder needs further
441        data to complete decoding (there no more data to feed in) */
442     if (decode->decoder_finish) {
443         g_mutex_lock(&decode->decoder_mutex);
444         g_cond_signal(&decode->decoder_finish_done);
445         g_mutex_unlock(&decode->decoder_mutex);
446         return;
447     }
448
449     /* Suspend the task if an error occurred */
450     if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA)
451         gst_pad_pause_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
452 }
453
454 static gboolean
455 gst_vaapidecode_flush(GstVideoDecoder *vdec)
456 {
457     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
458     GstVaapiDecoderStatus status;
459
460     /* If there is something in GstVideoDecoder's output adapter, then
461        submit the frame for decoding */
462     if (decode->current_frame_size) {
463         gst_video_decoder_have_frame(vdec);
464         decode->current_frame_size = 0;
465     }
466
467     status = gst_vaapi_decoder_flush(decode->decoder);
468     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
469         goto error_flush;
470     return TRUE;
471
472     /* ERRORS */
473 error_flush:
474     {
475         GST_ERROR("failed to flush decoder (status %d)", status);
476         return FALSE;
477     }
478 }
479
480 static GstFlowReturn
481 gst_vaapidecode_finish(GstVideoDecoder *vdec)
482 {
483     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
484     GstFlowReturn ret = GST_FLOW_OK;
485
486     if (!gst_vaapidecode_flush(vdec))
487         ret = GST_FLOW_OK;
488
489     /* Make sure the decode loop function has a chance to return, thus
490        possibly unlocking gst_video_decoder_finish_frame() */
491     GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
492     g_mutex_lock(&decode->decoder_mutex);
493     decode->decoder_finish = TRUE;
494     g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex);
495     g_mutex_unlock(&decode->decoder_mutex);
496     gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
497     GST_VIDEO_DECODER_STREAM_LOCK(vdec);
498     return ret;
499 }
500
501 #if GST_CHECK_VERSION(1,0,0)
502 static gboolean
503 gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
504 {
505     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
506     GstCaps *caps = NULL;
507     GstBufferPool *pool;
508     GstStructure *config;
509     GstVideoInfo vi;
510     guint size, min, max;
511     gboolean need_pool, update_pool;
512     gboolean has_video_meta = FALSE;
513     GstVideoCodecState *state;
514 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
515     GstCapsFeatures *features, *features2;
516 #endif
517
518     gst_query_parse_allocation(query, &caps, &need_pool);
519
520     if (!caps)
521         goto error_no_caps;
522
523     state = gst_video_decoder_get_output_state(vdec);
524
525     decode->has_texture_upload_meta = FALSE;
526     has_video_meta = gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
527 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
528     if (has_video_meta)
529         decode->has_texture_upload_meta = gst_query_find_allocation_meta(query,
530             GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
531
532     features = gst_caps_get_features(state->caps, 0);
533     features2 = gst_caps_features_new(GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
534
535     /* Update src caps if feature is not handled downstream */
536     if (!decode->has_texture_upload_meta &&
537         gst_caps_features_is_equal(features, features2))
538         gst_vaapidecode_update_src_caps (decode, state);
539     gst_caps_features_free(features2);
540 #endif
541
542     gst_video_codec_state_unref(state);
543
544     gst_video_info_init(&vi);
545     gst_video_info_from_caps(&vi, caps);
546     if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED)
547         gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
548             GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
549
550     g_return_val_if_fail(GST_VAAPI_PLUGIN_BASE_DISPLAY(decode) != NULL, FALSE);
551
552     if (gst_query_get_n_allocation_pools(query) > 0) {
553         gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min, &max);
554         size = MAX(size, vi.size);
555         update_pool = TRUE;
556     }
557     else {
558         pool = NULL;
559         size = vi.size;
560         min = max = 0;
561         update_pool = FALSE;
562     }
563
564     if (!pool || !gst_buffer_pool_has_option(pool,
565             GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
566         GST_INFO("no pool or doesn't support GstVaapiVideoMeta, "
567             "making new pool");
568         if (pool)
569             gst_object_unref(pool);
570         pool = gst_vaapi_video_buffer_pool_new(
571             GST_VAAPI_PLUGIN_BASE_DISPLAY(decode));
572         if (!pool)
573             goto error_create_pool;
574
575         config = gst_buffer_pool_get_config(pool);
576         gst_buffer_pool_config_set_params(config, caps, size, min, max);
577         gst_buffer_pool_config_add_option(config,
578             GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
579         gst_buffer_pool_set_config(pool, config);
580     }
581
582     if (has_video_meta) {
583         config = gst_buffer_pool_get_config(pool);
584         gst_buffer_pool_config_add_option(config,
585             GST_BUFFER_POOL_OPTION_VIDEO_META);
586 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
587         if (decode->has_texture_upload_meta)
588             gst_buffer_pool_config_add_option(config,
589                 GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
590 #endif
591         gst_buffer_pool_set_config(pool, config);
592     }
593
594     if (update_pool)
595         gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max);
596     else
597         gst_query_add_allocation_pool(query, pool, size, min, max);
598     if (pool)
599         gst_object_unref(pool);
600     return TRUE;
601
602     /* ERRORS */
603 error_no_caps:
604     {
605         GST_ERROR("no caps specified");
606         return FALSE;
607     }
608 error_create_pool:
609     {
610         GST_ERROR("failed to create buffer pool");
611         return FALSE;
612     }
613 }
614 #endif
615
616 static inline gboolean
617 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
618 {
619     return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(decode));
620 }
621
622 static inline guint
623 gst_vaapi_codec_from_caps(GstCaps *caps)
624 {
625     return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
626 }
627
628 static gboolean
629 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
630 {
631     GstVaapiDisplay *dpy;
632
633     if (!gst_vaapidecode_ensure_display(decode))
634         return FALSE;
635     dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode);
636
637     switch (gst_vaapi_codec_from_caps(caps)) {
638     case GST_VAAPI_CODEC_MPEG2:
639         decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
640         break;
641     case GST_VAAPI_CODEC_MPEG4:
642     case GST_VAAPI_CODEC_H263:
643         decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
644         break;
645     case GST_VAAPI_CODEC_H264:
646         decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
647
648         /* Set the stream buffer alignment for better optimizations */
649         if (decode->decoder && caps) {
650             GstStructure * const structure = gst_caps_get_structure(caps, 0);
651             const gchar *str = NULL;
652
653             if ((str = gst_structure_get_string(structure, "alignment"))) {
654                 GstVaapiStreamAlignH264 alignment;
655                 if (g_strcmp0(str, "au") == 0)
656                     alignment = GST_VAAPI_STREAM_ALIGN_H264_AU;
657                 else if (g_strcmp0(str, "nal") == 0)
658                     alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU;
659                 else
660                     alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE;
661                 gst_vaapi_decoder_h264_set_alignment(
662                     GST_VAAPI_DECODER_H264(decode->decoder), alignment);
663             }
664         }
665         break;
666     case GST_VAAPI_CODEC_WMV3:
667     case GST_VAAPI_CODEC_VC1:
668         decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
669         break;
670 #if USE_JPEG_DECODER
671     case GST_VAAPI_CODEC_JPEG:
672         decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
673         break;
674 #endif
675 #if USE_VP8_DECODER
676     case GST_VAAPI_CODEC_VP8:
677         decode->decoder = gst_vaapi_decoder_vp8_new(dpy, caps);
678         break;
679 #endif
680     default:
681         decode->decoder = NULL;
682         break;
683     }
684     if (!decode->decoder)
685         return FALSE;
686
687     gst_vaapi_decoder_set_codec_state_changed_func(decode->decoder,
688         gst_vaapi_decoder_state_changed, decode);
689
690     decode->decoder_caps = gst_caps_ref(caps);
691     return gst_pad_start_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode),
692         (GstTaskFunction)gst_vaapidecode_decode_loop, decode, NULL);
693 }
694
695 static void
696 gst_vaapidecode_destroy(GstVaapiDecode *decode)
697 {
698     gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
699     gst_vaapi_decoder_replace(&decode->decoder, NULL);
700     gst_caps_replace(&decode->decoder_caps, NULL);
701     gst_vaapidecode_release(decode);
702 }
703
704 static gboolean
705 gst_vaapidecode_reset_full(GstVaapiDecode *decode, GstCaps *caps, gboolean hard)
706 {
707     GstVaapiCodec codec;
708
709     decode->has_texture_upload_meta = FALSE;
710
711     /* Reset tracked frame size */
712     decode->current_frame_size = 0;
713
714     /* Reset timers if hard reset was requested (e.g. seek) */
715     if (hard) {
716         GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
717         GstVideoCodecFrame *out_frame = NULL;
718
719         gst_vaapi_decoder_flush(decode->decoder);
720         GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
721         gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
722         GST_VIDEO_DECODER_STREAM_LOCK(vdec);
723         decode->decoder_loop_status = GST_FLOW_OK;
724
725         /* Purge all decoded frames as we don't need them (e.g. seek) */
726         while (gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
727                    &out_frame, 0) == GST_VAAPI_DECODER_STATUS_SUCCESS) {
728             gst_video_codec_frame_unref(out_frame);
729             out_frame = NULL;
730         }
731     }
732
733     /* Only reset decoder if codec type changed */
734     else if (decode->decoder && decode->decoder_caps) {
735         if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
736             return TRUE;
737         codec = gst_vaapi_codec_from_caps(caps);
738         if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
739             return TRUE;
740     }
741
742     gst_vaapidecode_destroy(decode);
743     return gst_vaapidecode_create(decode, caps);
744 }
745
746 static void
747 gst_vaapidecode_finalize(GObject *object)
748 {
749     GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
750
751     gst_caps_replace(&decode->sinkpad_caps, NULL);
752     gst_caps_replace(&decode->srcpad_caps,  NULL);
753     gst_caps_replace(&decode->allowed_caps, NULL);
754
755     g_cond_clear(&decode->decoder_finish_done);
756     g_cond_clear(&decode->decoder_ready);
757     g_mutex_clear(&decode->decoder_mutex);
758
759     gst_vaapi_plugin_base_finalize(GST_VAAPI_PLUGIN_BASE(object));
760     G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
761 }
762
763 static gboolean
764 gst_vaapidecode_open(GstVideoDecoder *vdec)
765 {
766     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
767     GstVaapiDisplay * const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode);
768     gboolean success;
769
770     if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(decode)))
771         return FALSE;
772
773     /* Let GstVideoContext ask for a proper display to its neighbours */
774     /* Note: steal old display that may be allocated from get_caps()
775        so that to retain a reference to it, thus avoiding extra
776        initialization steps if we turn out to simply re-use the
777        existing (cached) VA display */
778     GST_VAAPI_PLUGIN_BASE_DISPLAY(decode) = NULL;
779     success = gst_vaapidecode_ensure_display(decode);
780     if (old_display)
781         gst_vaapi_display_unref(old_display);
782     return success;
783 }
784
785 static gboolean
786 gst_vaapidecode_close(GstVideoDecoder *vdec)
787 {
788     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
789
790     gst_vaapidecode_destroy(decode);
791     gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(decode));
792     return TRUE;
793 }
794
795 static gboolean
796 gst_vaapidecode_reset(GstVideoDecoder *vdec, gboolean hard)
797 {
798     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
799
800     /* In GStreamer 1.0 context, this means a flush */
801     if (decode->decoder && !hard && !gst_vaapidecode_flush(vdec))
802         return FALSE;
803     return gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, hard);
804 }
805
806 static gboolean
807 gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
808 {
809     GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec);
810     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
811
812     if (!gst_vaapidecode_update_sink_caps(decode, state->caps))
813         return FALSE;
814     if (!gst_vaapidecode_update_src_caps(decode, state))
815         return FALSE;
816     if (!gst_video_decoder_negotiate(vdec))
817         return FALSE;
818     if (!gst_vaapi_plugin_base_set_caps(plugin, decode->sinkpad_caps,
819             decode->srcpad_caps))
820         return FALSE;
821     if (!gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, FALSE))
822         return FALSE;
823     return TRUE;
824 }
825
826 static GstFlowReturn
827 gst_vaapidecode_parse_frame(GstVideoDecoder *vdec,
828     GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
829 {
830     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
831     GstVaapiDecoderStatus status;
832     GstFlowReturn ret;
833     guint got_unit_size;
834     gboolean got_frame;
835
836     status = gst_vaapi_decoder_parse(decode->decoder, frame,
837         adapter, at_eos, &got_unit_size, &got_frame);
838
839     switch (status) {
840     case GST_VAAPI_DECODER_STATUS_SUCCESS:
841         if (got_unit_size > 0) {
842             gst_video_decoder_add_to_frame(vdec, got_unit_size);
843             decode->current_frame_size += got_unit_size;
844         }
845         if (got_frame) {
846             ret = gst_video_decoder_have_frame(vdec);
847             decode->current_frame_size = 0;
848         }
849         else
850             ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA;
851         break;
852     case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
853         ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
854         break;
855     case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
856     case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
857     case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
858         GST_WARNING("parse error %d", status);
859         ret = GST_FLOW_NOT_SUPPORTED;
860         decode->current_frame_size = 0;
861         break;
862     default:
863         GST_ERROR("parse error %d", status);
864         ret = GST_FLOW_EOS;
865         decode->current_frame_size = 0;
866         break;
867     }
868     return ret;
869 }
870
871 static GstFlowReturn
872 gst_vaapidecode_parse(GstVideoDecoder *vdec,
873     GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
874 {
875     GstFlowReturn ret;
876
877     do {
878         ret = gst_vaapidecode_parse_frame(vdec, frame, adapter, at_eos);
879     } while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA);
880     return ret;
881 }
882
883 static GstStateChangeReturn
884 gst_vaapidecode_change_state (GstElement * element, GstStateChange transition)
885 {
886     GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
887
888     switch (transition) {
889     case GST_STATE_CHANGE_PAUSED_TO_READY:
890         gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
891         break;
892     default:
893         break;
894     }
895     return GST_ELEMENT_CLASS(gst_vaapidecode_parent_class)->change_state(
896         element, transition);
897 }
898
899 static void
900 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
901 {
902     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
903     GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
904     GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass);
905     GstPadTemplate *pad_template;
906
907     GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
908                             GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
909
910     gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass));
911
912     object_class->finalize   = gst_vaapidecode_finalize;
913
914     element_class->change_state =
915         GST_DEBUG_FUNCPTR(gst_vaapidecode_change_state);
916
917     vdec_class->open         = GST_DEBUG_FUNCPTR(gst_vaapidecode_open);
918     vdec_class->close        = GST_DEBUG_FUNCPTR(gst_vaapidecode_close);
919     vdec_class->set_format   = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_format);
920     vdec_class->reset        = GST_DEBUG_FUNCPTR(gst_vaapidecode_reset);
921     vdec_class->parse        = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse);
922     vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame);
923     vdec_class->finish       = GST_DEBUG_FUNCPTR(gst_vaapidecode_finish);
924
925 #if GST_CHECK_VERSION(1,0,0)
926     vdec_class->decide_allocation =
927         GST_DEBUG_FUNCPTR(gst_vaapidecode_decide_allocation);
928 #endif
929
930     gst_element_class_set_static_metadata(element_class,
931         "VA-API decoder",
932         "Codec/Decoder/Video",
933         GST_PLUGIN_DESC,
934         "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
935
936     /* sink pad */
937     pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
938     gst_element_class_add_pad_template(element_class, pad_template);
939
940     /* src pad */
941     pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
942     gst_element_class_add_pad_template(element_class, pad_template);
943 }
944
945 static gboolean
946 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
947 {
948     GstCaps *caps, *allowed_caps;
949     GArray *profiles;
950     guint i;
951
952     if (decode->allowed_caps)
953         return TRUE;
954
955     if (!gst_vaapidecode_ensure_display(decode))
956         goto error_no_display;
957
958     profiles = gst_vaapi_display_get_decode_profiles(
959         GST_VAAPI_PLUGIN_BASE_DISPLAY(decode));
960     if (!profiles)
961         goto error_no_profiles;
962
963     allowed_caps = gst_caps_new_empty();
964     if (!allowed_caps)
965         goto error_no_memory;
966
967     for (i = 0; i < profiles->len; i++) {
968         const GstVaapiProfile profile =
969             g_array_index(profiles, GstVaapiProfile, i);
970         const gchar *media_type_name;
971
972         media_type_name = gst_vaapi_profile_get_media_type_name(profile);
973         if (!media_type_name)
974             continue;
975
976         caps = gst_caps_from_string(media_type_name);
977         if (!caps)
978             continue;
979         allowed_caps = gst_caps_merge(allowed_caps, caps);
980     }
981     decode->allowed_caps = allowed_caps;
982
983     g_array_unref(profiles);
984     return TRUE;
985
986     /* ERRORS */
987 error_no_display:
988     {
989         GST_ERROR("failed to retrieve VA display");
990         return FALSE;
991     }
992 error_no_profiles:
993     {
994         GST_ERROR("failed to retrieve VA decode profiles");
995         return FALSE;
996     }
997 error_no_memory:
998     {
999         GST_ERROR("failed to allocate allowed-caps set");
1000         g_array_unref(profiles);
1001         return FALSE;
1002     }
1003 }
1004
1005 static GstCaps *
1006 gst_vaapidecode_get_caps(GstPad *pad)
1007 {
1008     GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
1009
1010     if (!gst_vaapidecode_ensure_allowed_caps(decode))
1011         return gst_caps_new_empty();
1012
1013     return gst_caps_ref(decode->allowed_caps);
1014 }
1015
1016 static gboolean
1017 gst_vaapidecode_query(GST_PAD_QUERY_FUNCTION_ARGS)
1018 {
1019     GstVaapiDecode * const decode =
1020         GST_VAAPIDECODE(gst_pad_get_parent_element(pad));
1021     GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(decode);
1022     gboolean res;
1023
1024     GST_INFO_OBJECT(decode, "query type %s", GST_QUERY_TYPE_NAME(query));
1025
1026     if (gst_vaapi_reply_to_query(query, plugin->display)) {
1027         GST_DEBUG("sharing display %p", plugin->display);
1028         res = TRUE;
1029     }
1030     else if (GST_PAD_IS_SINK(pad)) {
1031         switch (GST_QUERY_TYPE(query)) {
1032 #if GST_CHECK_VERSION(1,0,0)
1033         case GST_QUERY_CAPS: {
1034             GstCaps * const caps = gst_vaapidecode_get_caps(pad);
1035             gst_query_set_caps_result(query, caps);
1036             gst_caps_unref(caps);
1037             res = TRUE;
1038             break;
1039         }
1040 #endif
1041         default:
1042             res = GST_PAD_QUERY_FUNCTION_CALL(plugin->sinkpad_query, pad,
1043                 parent, query);
1044             break;
1045         }
1046     }
1047     else
1048         res = GST_PAD_QUERY_FUNCTION_CALL(plugin->srcpad_query, pad,
1049             parent, query);
1050
1051     gst_object_unref(decode);
1052     return res;
1053 }
1054
1055 static void
1056 gst_vaapidecode_init(GstVaapiDecode *decode)
1057 {
1058     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
1059     GstPad *pad;
1060
1061     gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(decode), GST_CAT_DEFAULT);
1062
1063     decode->decoder             = NULL;
1064     decode->decoder_caps        = NULL;
1065     decode->allowed_caps        = NULL;
1066     decode->decoder_loop_status = GST_FLOW_OK;
1067
1068     g_mutex_init(&decode->decoder_mutex);
1069     g_cond_init(&decode->decoder_ready);
1070     g_cond_init(&decode->decoder_finish_done);
1071
1072     gst_video_decoder_set_packetized(vdec, FALSE);
1073
1074     /* Pad through which data comes in to the element */
1075     pad = GST_VAAPI_PLUGIN_BASE_SINK_PAD(decode);
1076     gst_pad_set_query_function(pad, gst_vaapidecode_query);
1077 #if !GST_CHECK_VERSION(1,0,0)
1078     gst_pad_set_getcaps_function(pad, gst_vaapidecode_get_caps);
1079 #endif
1080
1081     /* Pad through which data goes out of the element */
1082     pad = GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode);
1083     gst_pad_set_query_function(pad, gst_vaapidecode_query);
1084 }