2 * gstvaapidecode.c - VA-API video decoder
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011-2013 Intel Corporation
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 * SECTION:gstvaapidecode
25 * @short_description: A VA-API based video decoder
27 * vaapidecode decodes from raw bitstreams to surfaces suitable for
28 * the vaapisink element.
31 #include "gst/vaapi/sysdeps.h"
32 #include <gst/vaapi/gstvaapidisplay.h>
34 #include "gstvaapidecode.h"
35 #include "gstvaapipluginutil.h"
36 #include "gstvaapivideocontext.h"
37 #include "gstvaapivideobuffer.h"
38 #if GST_CHECK_VERSION(1,1,0)
39 #include "gstvaapivideometa_texture.h"
41 #if GST_CHECK_VERSION(1,0,0)
42 #include "gstvaapivideobufferpool.h"
43 #include "gstvaapivideomemory.h"
46 #include <gst/vaapi/gstvaapidecoder_h264.h>
47 #include <gst/vaapi/gstvaapidecoder_jpeg.h>
48 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
49 #include <gst/vaapi/gstvaapidecoder_mpeg4.h>
50 #include <gst/vaapi/gstvaapidecoder_vc1.h>
52 #define GST_PLUGIN_NAME "vaapidecode"
53 #define GST_PLUGIN_DESC "A VA-API based video decoder"
55 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
56 #define GST_CAT_DEFAULT gst_debug_vaapidecode
58 /* Default templates */
59 #define GST_CAPS_CODEC(CODEC) CODEC "; "
61 static const char gst_vaapidecode_sink_caps_str[] =
62 GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
63 GST_CAPS_CODEC("video/mpeg, mpegversion=4")
64 GST_CAPS_CODEC("video/x-divx")
65 GST_CAPS_CODEC("video/x-xvid")
66 GST_CAPS_CODEC("video/x-h263")
67 GST_CAPS_CODEC("video/x-h264")
68 GST_CAPS_CODEC("video/x-wmv")
69 GST_CAPS_CODEC("image/jpeg")
72 static const char gst_vaapidecode_src_caps_str[] =
73 #if GST_CHECK_VERSION(1,1,0)
74 GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
75 GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, NV12, I420, YV12 }") ";"
76 GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
77 GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "RGBA");
79 GST_VAAPI_SURFACE_CAPS;
82 static GstStaticPadTemplate gst_vaapidecode_sink_factory =
83 GST_STATIC_PAD_TEMPLATE(
87 GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
89 static GstStaticPadTemplate gst_vaapidecode_src_factory =
90 GST_STATIC_PAD_TEMPLATE(
94 GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
96 /* GstImplementsInterface interface */
97 #if !GST_CHECK_VERSION(1,0,0)
99 gst_vaapidecode_implements_interface_supported(
100 GstImplementsInterface *iface,
104 return (type == GST_TYPE_VIDEO_CONTEXT);
108 gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface)
110 iface->supported = gst_vaapidecode_implements_interface_supported;
114 /* GstVideoContext interface */
115 #if !GST_CHECK_VERSION(1,1,0)
117 gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
120 GstVaapiDecode *decode = GST_VAAPIDECODE (context);
121 gst_vaapi_set_display (type, value, &decode->display);
125 gst_video_context_interface_init(GstVideoContextInterface *iface)
127 iface->set_context = gst_vaapidecode_set_video_context;
130 #define GstVideoContextClass GstVideoContextInterface
133 G_DEFINE_TYPE_WITH_CODE(
136 GST_TYPE_VIDEO_DECODER,
137 #if !GST_CHECK_VERSION(1,0,0)
138 G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
139 gst_vaapidecode_implements_iface_init);
141 #if !GST_CHECK_VERSION(1,1,0)
142 G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
143 gst_video_context_interface_init)
148 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
149 const GstVideoCodecState *ref_state);
152 gst_vaapi_decoder_state_changed(GstVaapiDecoder *decoder,
153 const GstVideoCodecState *codec_state, gpointer user_data)
155 GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
157 g_assert(decode->decoder == decoder);
159 gst_vaapidecode_update_src_caps(decode, codec_state);
162 static inline gboolean
163 gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
165 gst_caps_replace(&decode->sinkpad_caps, caps);
170 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
171 const GstVideoCodecState *ref_state)
173 GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
174 GstVideoCodecState *state;
175 GstVideoInfo *vi, vis;
177 state = gst_video_decoder_set_output_state(vdec,
178 GST_VIDEO_INFO_FORMAT(&ref_state->info),
179 ref_state->info.width, ref_state->info.height,
180 (GstVideoCodecState *)ref_state);
185 if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
186 gst_video_info_init(&vis);
187 gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
188 GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
191 gst_video_codec_state_unref(state);
193 #if GST_CHECK_VERSION(1,1,0)
195 if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
196 /* XXX: this is a workaround until auto-plugging is fixed when
197 format=ENCODED + memory:VASurface caps feature are provided.
198 Meanwhile, providing a random format here works but this is
199 a terribly wrong thing per se. */
200 gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
201 GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
203 state->caps = gst_video_info_to_caps(&vis);
205 /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not
206 reconstruct suitable caps for "encoded" video formats */
207 state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
211 gst_caps_set_simple(state->caps,
212 "type", G_TYPE_STRING, "vaapi",
213 "opengl", G_TYPE_BOOLEAN, USE_GLX,
214 "width", G_TYPE_INT, vi->width,
215 "height", G_TYPE_INT, vi->height,
216 "framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d,
217 "pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d,
220 gst_caps_set_interlaced(state->caps, vi);
222 gst_caps_replace(&decode->srcpad_caps, state->caps);
227 gst_vaapidecode_release(GstVaapiDecode *decode)
229 g_mutex_lock(&decode->decoder_mutex);
230 g_cond_signal(&decode->decoder_ready);
231 g_mutex_unlock(&decode->decoder_mutex);
235 gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
237 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
238 GstVaapiDecoderStatus status;
242 if (decode->render_time_base)
243 end_time = decode->render_time_base;
245 end_time = g_get_monotonic_time();
246 end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
247 end_time += G_TIME_SPAN_SECOND;
249 /* Decode current frame */
251 status = gst_vaapi_decoder_decode(decode->decoder, frame);
252 if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
253 gboolean was_signalled;
254 GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
255 g_mutex_lock(&decode->decoder_mutex);
256 was_signalled = g_cond_wait_until(
257 &decode->decoder_ready,
258 &decode->decoder_mutex,
261 g_mutex_unlock(&decode->decoder_mutex);
262 GST_VIDEO_DECODER_STREAM_LOCK(vdec);
265 goto error_decode_timeout;
267 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
274 error_decode_timeout:
276 GST_WARNING("decode timeout. Decoder required a VA surface but none "
277 "got available within one second");
282 GST_ERROR("decode error %d", status);
284 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
285 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
286 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
287 ret = GST_FLOW_NOT_SUPPORTED;
293 gst_video_decoder_drop_frame(vdec, frame);
299 gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec)
301 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
302 GstVaapiSurfaceProxy *proxy;
303 GstVaapiDecoderStatus status;
304 GstVideoCodecFrame *out_frame;
306 #if GST_CHECK_VERSION(1,0,0)
307 const GstVaapiRectangle *crop_rect;
308 GstVaapiVideoMeta *meta;
312 status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
314 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
315 return GST_VIDEO_DECODER_FLOW_NEED_DATA;
317 if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) {
318 proxy = gst_video_codec_frame_get_user_data(out_frame);
320 gst_vaapi_surface_proxy_set_destroy_notify(proxy,
321 (GDestroyNotify)gst_vaapidecode_release, decode);
323 #if GST_CHECK_VERSION(1,0,0)
324 ret = gst_video_decoder_allocate_output_frame(vdec, out_frame);
325 if (ret != GST_FLOW_OK)
326 goto error_create_buffer;
328 meta = gst_buffer_get_vaapi_video_meta(out_frame->output_buffer);
331 gst_vaapi_video_meta_set_surface_proxy(meta, proxy);
333 flags = gst_vaapi_surface_proxy_get_flags(proxy);
334 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
335 guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED;
336 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF)
337 out_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
338 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF)
339 out_flags |= GST_VIDEO_BUFFER_FLAG_RFF;
340 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD)
341 out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD;
342 GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags);
345 crop_rect = gst_vaapi_surface_proxy_get_crop_rect(proxy);
347 GstVideoCropMeta * const crop_meta =
348 gst_buffer_add_video_crop_meta(out_frame->output_buffer);
350 crop_meta->x = crop_rect->x;
351 crop_meta->y = crop_rect->y;
352 crop_meta->width = crop_rect->width;
353 crop_meta->height = crop_rect->height;
357 #if GST_CHECK_VERSION(1,1,0)
358 if (decode->has_texture_upload_meta)
359 gst_buffer_add_texture_upload_meta(out_frame->output_buffer);
362 out_frame->output_buffer =
363 gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
364 if (!out_frame->output_buffer)
365 goto error_create_buffer;
369 ret = gst_video_decoder_finish_frame(vdec, out_frame);
370 if (ret != GST_FLOW_OK)
371 goto error_commit_buffer;
373 /* Estimate when this frame would no longer be needed for rendering */
374 if (GST_CLOCK_TIME_IS_VALID(out_frame->pts)) {
375 if (!decode->render_time_base)
376 decode->render_time_base = g_get_monotonic_time() -
377 GST_TIME_AS_USECONDS(out_frame->pts);
378 decode->last_buffer_time = out_frame->pts;
379 if (GST_CLOCK_TIME_IS_VALID(out_frame->duration))
380 decode->last_buffer_time += out_frame->duration;
382 decode->last_buffer_time += GST_SECOND;
385 decode->render_time_base = 0;
386 decode->last_buffer_time = 0;
389 gst_video_codec_frame_unref(out_frame);
395 const GstVaapiID surface_id =
396 gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
398 GST_ERROR("video sink failed to create video buffer for proxy'ed "
399 "surface %" GST_VAAPI_ID_FORMAT,
400 GST_VAAPI_ID_ARGS(surface_id));
401 gst_video_decoder_drop_frame(vdec, out_frame);
402 gst_video_codec_frame_unref(out_frame);
405 #if GST_CHECK_VERSION(1,0,0)
408 GST_ERROR("failed to get vaapi video meta attached to video buffer");
409 gst_video_decoder_drop_frame(vdec, out_frame);
410 gst_video_codec_frame_unref(out_frame);
416 if (ret != GST_FLOW_FLUSHING)
417 GST_ERROR("video sink rejected the video buffer (error %d)", ret);
418 gst_video_codec_frame_unref(out_frame);
424 gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
428 /* Make sure to release the base class stream lock so that decode
429 loop can call gst_video_decoder_finish_frame() without blocking */
430 GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
431 ret = gst_vaapidecode_decode_frame(vdec, frame);
432 GST_VIDEO_DECODER_STREAM_LOCK(vdec);
437 gst_vaapidecode_decode_loop(GstVaapiDecode *decode)
439 GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
442 ret = gst_vaapidecode_push_decoded_frame(vdec);
443 if (ret == GST_FLOW_OK)
446 /* If invoked from gst_vaapidecode_finish(), then return right
447 away no matter the errors, or the GstVaapiDecoder needs further
448 data to complete decoding (there no more data to feed in) */
449 if (decode->decoder_finish) {
450 g_mutex_lock(&decode->decoder_mutex);
451 g_cond_signal(&decode->decoder_finish_done);
452 g_mutex_unlock(&decode->decoder_mutex);
456 /* Suspend the task if an error occurred */
457 if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA)
458 gst_pad_pause_task(decode->srcpad);
462 gst_vaapidecode_finish(GstVideoDecoder *vdec)
464 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
465 GstVaapiDecoderStatus status;
467 /* If there is something in GstVideoDecoder's output adapter, then
468 submit the frame for decoding */
469 if (decode->current_frame_size)
470 gst_video_decoder_have_frame(vdec);
472 status = gst_vaapi_decoder_flush(decode->decoder);
473 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
476 /* Make sure the decode loop function has a chance to return, thus
477 possibly unlocking gst_video_decoder_finish_frame() */
478 GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
479 g_mutex_lock(&decode->decoder_mutex);
480 decode->decoder_finish = TRUE;
481 g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex);
482 g_mutex_unlock(&decode->decoder_mutex);
483 gst_pad_stop_task(decode->srcpad);
484 GST_VIDEO_DECODER_STREAM_LOCK(vdec);
490 GST_ERROR("failed to flush decoder (status %d)", status);
495 #if GST_CHECK_VERSION(1,0,0)
497 gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
499 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
500 GstCaps *caps = NULL;
502 GstStructure *config;
504 guint size, min, max;
505 gboolean need_pool, update_pool;
507 gst_query_parse_allocation(query, &caps, &need_pool);
512 gst_video_info_init(&vi);
513 gst_video_info_from_caps(&vi, caps);
514 if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED)
515 gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
516 GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
518 g_return_val_if_fail(decode->display != NULL, FALSE);
520 if (gst_query_get_n_allocation_pools(query) > 0) {
521 gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min, &max);
522 size = MAX(size, vi.size);
532 if (!pool || !gst_buffer_pool_has_option(pool,
533 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
534 GST_INFO("no pool or doesn't support GstVaapiVideoMeta, "
536 pool = gst_vaapi_video_buffer_pool_new(decode->display);
538 goto error_create_pool;
540 config = gst_buffer_pool_get_config(pool);
541 gst_buffer_pool_config_set_params(config, caps, size, min, max);
542 gst_buffer_pool_config_add_option(config,
543 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
544 gst_buffer_pool_set_config(pool, config);
547 decode->has_texture_upload_meta = FALSE;
548 if (gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL)) {
549 config = gst_buffer_pool_get_config(pool);
550 gst_buffer_pool_config_add_option(config,
551 GST_BUFFER_POOL_OPTION_VIDEO_META);
552 gst_buffer_pool_set_config(pool, config);
553 #if GST_CHECK_VERSION(1,1,0)
554 decode->has_texture_upload_meta = gst_query_find_allocation_meta(query,
555 GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
560 gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max);
562 gst_query_add_allocation_pool(query, pool, size, min, max);
564 gst_object_unref(pool);
570 GST_ERROR("no caps specified");
575 GST_ERROR("failed to create buffer pool");
581 #if GST_CHECK_VERSION(1,1,0)
583 gst_vaapidecode_set_context(GstElement *element, GstContext *context)
585 GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
586 GstVaapiDisplay *display = NULL;
588 if (gst_vaapi_video_context_get_display(context, &display)) {
589 GST_INFO_OBJECT(element, "set display %p", display);
590 gst_vaapi_display_replace(&decode->display, display);
595 static inline gboolean
596 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
598 return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
603 gst_vaapi_codec_from_caps(GstCaps *caps)
605 return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
609 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
611 GstVaapiDisplay *dpy;
613 if (!gst_vaapidecode_ensure_display(decode))
615 dpy = decode->display;
617 switch (gst_vaapi_codec_from_caps(caps)) {
618 case GST_VAAPI_CODEC_MPEG2:
619 decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
621 case GST_VAAPI_CODEC_MPEG4:
622 case GST_VAAPI_CODEC_H263:
623 decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
625 case GST_VAAPI_CODEC_H264:
626 decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
628 case GST_VAAPI_CODEC_WMV3:
629 case GST_VAAPI_CODEC_VC1:
630 decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
633 case GST_VAAPI_CODEC_JPEG:
634 decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
638 decode->decoder = NULL;
641 if (!decode->decoder)
644 gst_vaapi_decoder_set_codec_state_changed_func(decode->decoder,
645 gst_vaapi_decoder_state_changed, decode);
647 decode->decoder_caps = gst_caps_ref(caps);
648 return gst_pad_start_task(decode->srcpad,
649 (GstTaskFunction)gst_vaapidecode_decode_loop, decode, NULL);
653 gst_vaapidecode_destroy(GstVaapiDecode *decode)
655 gst_pad_stop_task(decode->srcpad);
656 gst_vaapi_decoder_replace(&decode->decoder, NULL);
657 gst_caps_replace(&decode->decoder_caps, NULL);
658 gst_vaapidecode_release(decode);
662 gst_vaapidecode_reset_full(GstVaapiDecode *decode, GstCaps *caps, gboolean hard)
666 decode->has_texture_upload_meta = FALSE;
668 /* Reset timers if hard reset was requested (e.g. seek) */
670 decode->render_time_base = 0;
671 decode->last_buffer_time = 0;
674 /* Only reset decoder if codec type changed */
675 else if (decode->decoder && decode->decoder_caps) {
676 if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
678 codec = gst_vaapi_codec_from_caps(caps);
679 if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
683 /* Reset tracked frame size */
684 decode->current_frame_size = 0;
686 gst_vaapidecode_destroy(decode);
687 return gst_vaapidecode_create(decode, caps);
691 gst_vaapidecode_finalize(GObject *object)
693 GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
695 gst_caps_replace(&decode->sinkpad_caps, NULL);
696 gst_caps_replace(&decode->srcpad_caps, NULL);
697 gst_caps_replace(&decode->allowed_caps, NULL);
699 gst_vaapi_display_replace(&decode->display, NULL);
701 g_cond_clear(&decode->decoder_finish_done);
702 g_cond_clear(&decode->decoder_ready);
703 g_mutex_clear(&decode->decoder_mutex);
705 G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
709 gst_vaapidecode_open(GstVideoDecoder *vdec)
711 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
712 GstVaapiDisplay * const old_display = decode->display;
715 /* Let GstVideoContext ask for a proper display to its neighbours */
716 /* Note: steal old display that may be allocated from get_caps()
717 so that to retain a reference to it, thus avoiding extra
718 initialization steps if we turn out to simply re-use the
719 existing (cached) VA display */
720 decode->display = NULL;
721 success = gst_vaapidecode_ensure_display(decode);
723 gst_vaapi_display_unref(old_display);
728 gst_vaapidecode_close(GstVideoDecoder *vdec)
730 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
732 gst_vaapidecode_destroy(decode);
733 gst_vaapi_display_replace(&decode->display, NULL);
738 gst_vaapidecode_reset(GstVideoDecoder *vdec, gboolean hard)
740 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
742 return gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, hard);
746 gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
748 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
750 if (!gst_vaapidecode_update_sink_caps(decode, state->caps))
752 if (!gst_vaapidecode_update_src_caps(decode, state))
754 if (!gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, FALSE))
760 gst_vaapidecode_parse(GstVideoDecoder *vdec,
761 GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
763 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
764 GstVaapiDecoderStatus status;
769 status = gst_vaapi_decoder_parse(decode->decoder, frame,
770 adapter, at_eos, &got_unit_size, &got_frame);
773 case GST_VAAPI_DECODER_STATUS_SUCCESS:
774 if (got_unit_size > 0) {
775 gst_video_decoder_add_to_frame(vdec, got_unit_size);
776 decode->current_frame_size += got_unit_size;
779 ret = gst_video_decoder_have_frame(vdec);
780 decode->current_frame_size = 0;
785 case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
786 ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
788 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
789 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
790 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
791 GST_WARNING("parse error %d", status);
792 ret = GST_FLOW_NOT_SUPPORTED;
793 decode->current_frame_size = 0;
796 GST_ERROR("parse error %d", status);
798 decode->current_frame_size = 0;
805 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
807 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
808 GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
809 GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass);
810 GstPadTemplate *pad_template;
812 GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
813 GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
815 object_class->finalize = gst_vaapidecode_finalize;
817 vdec_class->open = GST_DEBUG_FUNCPTR(gst_vaapidecode_open);
818 vdec_class->close = GST_DEBUG_FUNCPTR(gst_vaapidecode_close);
819 vdec_class->set_format = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_format);
820 vdec_class->reset = GST_DEBUG_FUNCPTR(gst_vaapidecode_reset);
821 vdec_class->parse = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse);
822 vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame);
823 vdec_class->finish = GST_DEBUG_FUNCPTR(gst_vaapidecode_finish);
825 #if GST_CHECK_VERSION(1,0,0)
826 vdec_class->decide_allocation =
827 GST_DEBUG_FUNCPTR(gst_vaapidecode_decide_allocation);
830 #if GST_CHECK_VERSION(1,1,0)
831 element_class->set_context = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_context);
834 gst_element_class_set_static_metadata(element_class,
836 "Codec/Decoder/Video",
838 "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
841 pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
842 gst_element_class_add_pad_template(element_class, pad_template);
845 pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
846 gst_element_class_add_pad_template(element_class, pad_template);
850 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
852 GstCaps *decode_caps;
853 guint i, n_decode_caps;
855 if (decode->allowed_caps)
858 if (!gst_vaapidecode_ensure_display(decode))
859 goto error_no_display;
861 decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
863 goto error_no_decode_caps;
864 n_decode_caps = gst_caps_get_size(decode_caps);
866 decode->allowed_caps = gst_caps_new_empty();
867 if (!decode->allowed_caps)
868 goto error_no_memory;
870 for (i = 0; i < n_decode_caps; i++) {
871 GstStructure *structure;
872 structure = gst_caps_get_structure(decode_caps, i);
875 structure = gst_structure_copy(structure);
878 gst_structure_remove_field(structure, "profile");
879 decode->allowed_caps =
880 gst_caps_merge_structure(decode->allowed_caps, structure);
883 gst_caps_unref(decode_caps);
889 GST_ERROR("failed to retrieve VA display");
892 error_no_decode_caps:
894 GST_ERROR("failed to retrieve VA decode caps");
899 GST_ERROR("failed to allocate allowed-caps set");
900 gst_caps_unref(decode_caps);
906 gst_vaapidecode_get_caps(GstPad *pad)
908 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
910 if (!gst_vaapidecode_ensure_allowed_caps(decode))
911 return gst_caps_new_empty();
913 return gst_caps_ref(decode->allowed_caps);
917 gst_vaapidecode_query(GST_PAD_QUERY_FUNCTION_ARGS)
919 GstVaapiDecode * const decode =
920 GST_VAAPIDECODE(gst_pad_get_parent_element(pad));
923 GST_INFO_OBJECT(decode, "query type %s", GST_QUERY_TYPE_NAME(query));
925 if (gst_vaapi_reply_to_query(query, decode->display)) {
926 GST_DEBUG("sharing display %p", decode->display);
929 else if (GST_PAD_IS_SINK(pad)) {
930 switch (GST_QUERY_TYPE(query)) {
931 #if GST_CHECK_VERSION(1,0,0)
932 case GST_QUERY_CAPS: {
933 GstCaps * const caps = gst_vaapidecode_get_caps(pad);
934 gst_query_set_caps_result(query, caps);
935 gst_caps_unref(caps);
941 res = GST_PAD_QUERY_FUNCTION_CALL(decode->sinkpad_query,
942 decode->sinkpad, parent, query);
947 res = GST_PAD_QUERY_FUNCTION_CALL(decode->srcpad_query,
948 decode->srcpad, parent, query);
950 gst_object_unref(decode);
955 gst_vaapidecode_init(GstVaapiDecode *decode)
957 GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
959 decode->display = NULL;
960 decode->decoder = NULL;
961 decode->decoder_caps = NULL;
962 decode->allowed_caps = NULL;
963 decode->render_time_base = 0;
964 decode->last_buffer_time = 0;
966 g_mutex_init(&decode->decoder_mutex);
967 g_cond_init(&decode->decoder_ready);
968 g_cond_init(&decode->decoder_finish_done);
970 gst_video_decoder_set_packetized(vdec, FALSE);
972 /* Pad through which data comes in to the element */
973 decode->sinkpad = GST_VIDEO_DECODER_SINK_PAD(vdec);
974 decode->sinkpad_query = GST_PAD_QUERYFUNC(decode->sinkpad);
975 gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
976 #if !GST_CHECK_VERSION(1,0,0)
977 gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
980 /* Pad through which data goes out of the element */
981 decode->srcpad = GST_VIDEO_DECODER_SRC_PAD(vdec);
982 decode->srcpad_query = GST_PAD_QUERYFUNC(decode->srcpad);
983 gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);