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