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