2010-04-29 17:55:58 +00:00
|
|
|
/*
|
|
|
|
* gstvaapidecode.c - VA-API video decoder
|
|
|
|
*
|
2012-01-16 09:41:10 +00:00
|
|
|
* Copyright (C) 2010-2011 Splitted-Desktop Systems
|
2013-11-22 04:57:18 +00:00
|
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
|
2014-01-22 17:54:14 +00:00
|
|
|
* Copyright (C) 2011-2014 Intel Corporation
|
2013-11-22 04:57:18 +00:00
|
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
|
2010-04-29 17:55:58 +00:00
|
|
|
*
|
2011-10-18 07:06:52 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
|
|
* of the License, or (at your option) any later version.
|
2010-04-29 17:55:58 +00:00
|
|
|
*
|
2011-10-18 07:06:52 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2010-04-29 17:55:58 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-10-18 07:06:52 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2010-04-29 17:55:58 +00:00
|
|
|
*
|
2011-10-18 07:06:52 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free
|
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:gstvaapidecode
|
|
|
|
* @short_description: A VA-API based video decoder
|
|
|
|
*
|
|
|
|
* vaapidecode decodes from raw bitstreams to surfaces suitable for
|
|
|
|
* the vaapisink element.
|
|
|
|
*/
|
|
|
|
|
2012-09-12 11:41:47 +00:00
|
|
|
#include "gst/vaapi/sysdeps.h"
|
2011-11-04 20:50:15 +00:00
|
|
|
#include <gst/vaapi/gstvaapidisplay.h>
|
|
|
|
|
|
|
|
#include "gstvaapidecode.h"
|
|
|
|
#include "gstvaapipluginutil.h"
|
2013-03-21 16:17:53 +00:00
|
|
|
#include "gstvaapivideobuffer.h"
|
2015-02-20 14:29:17 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0) && (USE_GLX || USE_EGL)
|
2013-07-15 11:41:00 +00:00
|
|
|
#include "gstvaapivideometa_texture.h"
|
|
|
|
#endif
|
2013-03-20 13:40:57 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2012-11-08 14:41:22 +00:00
|
|
|
#include "gstvaapivideobufferpool.h"
|
|
|
|
#include "gstvaapivideomemory.h"
|
2013-03-20 13:40:57 +00:00
|
|
|
#endif
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-07-19 15:16:28 +00:00
|
|
|
#include <gst/vaapi/gstvaapidecoder_h264.h>
|
|
|
|
#include <gst/vaapi/gstvaapidecoder_jpeg.h>
|
|
|
|
#include <gst/vaapi/gstvaapidecoder_mpeg2.h>
|
|
|
|
#include <gst/vaapi/gstvaapidecoder_mpeg4.h>
|
|
|
|
#include <gst/vaapi/gstvaapidecoder_vc1.h>
|
2013-12-26 23:18:24 +00:00
|
|
|
#include <gst/vaapi/gstvaapidecoder_vp8.h>
|
2011-08-12 08:21:19 +00:00
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
#define GST_PLUGIN_NAME "vaapidecode"
|
|
|
|
#define GST_PLUGIN_DESC "A VA-API based video decoder"
|
|
|
|
|
2014-06-18 11:47:36 +00:00
|
|
|
#define GST_VAAPI_DECODE_FLOW_PARSE_DATA GST_FLOW_CUSTOM_SUCCESS_2
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
|
|
|
|
#define GST_CAT_DEFAULT gst_debug_vaapidecode
|
|
|
|
|
|
|
|
/* Default templates */
|
2011-09-14 11:07:18 +00:00
|
|
|
#define GST_CAPS_CODEC(CODEC) CODEC "; "
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
static const char gst_vaapidecode_sink_caps_str[] =
|
2011-09-14 09:34:05 +00:00
|
|
|
GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
|
2010-04-29 17:55:58 +00:00
|
|
|
GST_CAPS_CODEC("video/mpeg, mpegversion=4")
|
2010-05-03 17:36:01 +00:00
|
|
|
GST_CAPS_CODEC("video/x-divx")
|
|
|
|
GST_CAPS_CODEC("video/x-xvid")
|
2010-04-29 17:55:58 +00:00
|
|
|
GST_CAPS_CODEC("video/x-h263")
|
|
|
|
GST_CAPS_CODEC("video/x-h264")
|
2010-05-03 11:44:23 +00:00
|
|
|
GST_CAPS_CODEC("video/x-wmv")
|
2013-12-26 23:18:24 +00:00
|
|
|
GST_CAPS_CODEC("video/x-vp8")
|
2012-02-09 16:21:04 +00:00
|
|
|
GST_CAPS_CODEC("image/jpeg")
|
2010-04-29 17:55:58 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
static const char gst_vaapidecode_src_caps_str[] =
|
2013-07-04 08:03:52 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0)
|
|
|
|
GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
|
2014-07-23 08:23:06 +00:00
|
|
|
GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, I420, YV12, NV12 }") ";"
|
2013-07-15 11:41:00 +00:00
|
|
|
GST_VIDEO_CAPS_MAKE_WITH_FEATURES(
|
2015-02-09 20:09:07 +00:00
|
|
|
GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "{ RGBA, BGRA }") ";"
|
2014-07-23 08:23:06 +00:00
|
|
|
GST_VIDEO_CAPS_MAKE("{ I420, YV12, NV12 }");
|
2013-07-04 08:03:52 +00:00
|
|
|
#else
|
2010-05-07 06:35:31 +00:00
|
|
|
GST_VAAPI_SURFACE_CAPS;
|
2013-07-04 08:03:52 +00:00
|
|
|
#endif
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
static GstStaticPadTemplate gst_vaapidecode_sink_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE(
|
|
|
|
"sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
|
|
|
|
|
|
|
|
static GstStaticPadTemplate gst_vaapidecode_src_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE(
|
|
|
|
"src",
|
|
|
|
GST_PAD_SRC,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
|
|
|
|
|
2012-06-30 17:58:36 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE(
|
2010-04-29 17:55:58 +00:00
|
|
|
GstVaapiDecode,
|
|
|
|
gst_vaapidecode,
|
2012-12-04 13:45:29 +00:00
|
|
|
GST_TYPE_VIDEO_DECODER,
|
2013-12-13 15:03:08 +00:00
|
|
|
GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES)
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2011-07-22 13:39:51 +00:00
|
|
|
static gboolean
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gst_vaapi_decode_input_state_replace(GstVaapiDecode *decode,
|
|
|
|
const GstVideoCodecState *new_state);
|
2011-07-22 13:39:51 +00:00
|
|
|
|
|
|
|
static void
|
2013-05-06 12:43:38 +00:00
|
|
|
gst_vaapi_decoder_state_changed(GstVaapiDecoder *decoder,
|
|
|
|
const GstVideoCodecState *codec_state, gpointer user_data)
|
2011-07-22 13:39:51 +00:00
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
|
2013-12-11 18:08:26 +00:00
|
|
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
2015-01-15 15:23:24 +00:00
|
|
|
GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec);
|
2011-07-22 13:39:51 +00:00
|
|
|
|
2013-05-06 12:43:38 +00:00
|
|
|
g_assert(decode->decoder == decoder);
|
2011-07-22 13:39:51 +00:00
|
|
|
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
if (!gst_vaapi_decode_input_state_replace(decode, codec_state))
|
|
|
|
return;
|
|
|
|
if (!gst_vaapidecode_update_src_caps(decode))
|
|
|
|
return;
|
|
|
|
if (!gst_video_decoder_negotiate(vdec))
|
|
|
|
return;
|
|
|
|
if (!gst_vaapi_plugin_base_set_caps(plugin, NULL, decode->srcpad_caps))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gst_vaapi_decode_input_state_replace(GstVaapiDecode *decode,
|
|
|
|
const GstVideoCodecState *new_state)
|
|
|
|
{
|
|
|
|
if (decode->input_state) {
|
|
|
|
if (new_state) {
|
|
|
|
const GstCaps *curcaps = decode->input_state->caps;
|
|
|
|
if (gst_caps_is_always_compatible(curcaps, new_state->caps))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
gst_video_codec_state_unref(decode->input_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_state)
|
|
|
|
decode->input_state = gst_video_codec_state_ref
|
|
|
|
((GstVideoCodecState*) new_state);
|
|
|
|
else
|
|
|
|
decode->input_state = NULL;
|
|
|
|
|
|
|
|
return TRUE;
|
2011-07-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
|
|
|
|
{
|
2012-12-04 13:53:15 +00:00
|
|
|
gst_caps_replace(&decode->sinkpad_caps, caps);
|
2011-07-22 13:39:51 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode)
|
2011-07-22 13:39:51 +00:00
|
|
|
{
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
GstVideoCodecState *state, *ref_state;
|
2015-02-26 10:28:02 +00:00
|
|
|
GstVideoInfo *vi;
|
|
|
|
GstVideoFormat format = GST_VIDEO_FORMAT_I420;
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
|
|
|
|
if (!decode->input_state)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ref_state = decode->input_state;
|
|
|
|
|
2013-12-11 18:08:26 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0)
|
|
|
|
GstCapsFeatures *features = NULL;
|
|
|
|
GstVaapiCapsFeature feature;
|
|
|
|
|
|
|
|
feature = gst_vaapi_find_preferred_caps_feature(
|
|
|
|
GST_VIDEO_DECODER_SRC_PAD(vdec),
|
2015-02-26 10:28:02 +00:00
|
|
|
GST_VIDEO_INFO_FORMAT(&ref_state->info), &format);
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
|
|
|
|
if (feature == GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED)
|
|
|
|
return FALSE;
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-02-26 10:28:02 +00:00
|
|
|
switch (feature) {
|
|
|
|
#if (USE_GLX || USE_EGL)
|
|
|
|
case GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META:
|
|
|
|
if (decode->has_texture_upload_meta)
|
|
|
|
features = gst_caps_features_new(
|
|
|
|
GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
|
|
|
|
else
|
|
|
|
format = GST_VIDEO_FORMAT_I420;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if GST_CHECK_VERSION(1,5,0)
|
|
|
|
case GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE:
|
|
|
|
features = gst_caps_features_new(
|
|
|
|
GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
2014-07-22 16:54:29 +00:00
|
|
|
|
|
|
|
state = gst_video_decoder_set_output_state(vdec, format,
|
2013-05-06 12:43:38 +00:00
|
|
|
ref_state->info.width, ref_state->info.height,
|
|
|
|
(GstVideoCodecState *)ref_state);
|
2015-01-15 15:19:59 +00:00
|
|
|
if (!state || state->info.width == 0 || state->info.height == 0)
|
2012-12-04 13:45:29 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2012-12-12 14:22:32 +00:00
|
|
|
vi = &state->info;
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2013-07-04 08:03:52 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0)
|
2015-02-26 10:28:02 +00:00
|
|
|
state->caps = gst_video_info_to_caps(vi);
|
2013-12-11 18:08:26 +00:00
|
|
|
if (features)
|
|
|
|
gst_caps_set_features(state->caps, 0, features);
|
2013-07-04 08:03:52 +00:00
|
|
|
#else
|
2012-12-04 13:45:29 +00:00
|
|
|
/* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not
|
|
|
|
reconstruct suitable caps for "encoded" video formats */
|
|
|
|
state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
|
|
|
|
if (!state->caps)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
gst_caps_set_simple(state->caps,
|
|
|
|
"type", G_TYPE_STRING, "vaapi",
|
|
|
|
"opengl", G_TYPE_BOOLEAN, USE_GLX,
|
2012-12-12 14:22:32 +00:00
|
|
|
"width", G_TYPE_INT, vi->width,
|
|
|
|
"height", G_TYPE_INT, vi->height,
|
|
|
|
"framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d,
|
|
|
|
"pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d,
|
2012-12-04 13:45:29 +00:00
|
|
|
NULL);
|
|
|
|
|
2013-10-04 17:30:36 +00:00
|
|
|
gst_caps_set_interlaced(state->caps, vi);
|
2013-07-04 08:03:52 +00:00
|
|
|
#endif
|
2012-12-04 13:45:29 +00:00
|
|
|
gst_caps_replace(&decode->srcpad_caps, state->caps);
|
2015-02-26 10:28:02 +00:00
|
|
|
gst_video_codec_state_unref(state);
|
2012-12-04 13:45:29 +00:00
|
|
|
return TRUE;
|
2011-07-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
2010-05-16 21:04:32 +00:00
|
|
|
static void
|
2012-12-03 12:46:28 +00:00
|
|
|
gst_vaapidecode_release(GstVaapiDecode *decode)
|
2010-05-16 21:04:32 +00:00
|
|
|
{
|
2012-10-04 16:39:53 +00:00
|
|
|
g_mutex_lock(&decode->decoder_mutex);
|
|
|
|
g_cond_signal(&decode->decoder_ready);
|
|
|
|
g_mutex_unlock(&decode->decoder_mutex);
|
2010-05-16 21:04:32 +00:00
|
|
|
}
|
|
|
|
|
2010-04-30 15:37:28 +00:00
|
|
|
static GstFlowReturn
|
2013-01-17 17:19:14 +00:00
|
|
|
gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
2010-04-30 15:37:28 +00:00
|
|
|
GstVaapiDecoderStatus status;
|
2010-04-29 17:55:58 +00:00
|
|
|
GstFlowReturn ret;
|
|
|
|
|
2015-02-04 16:34:59 +00:00
|
|
|
|
2012-12-13 13:30:18 +00:00
|
|
|
/* Decode current frame */
|
2010-04-30 15:50:19 +00:00
|
|
|
for (;;) {
|
2012-12-13 13:30:18 +00:00
|
|
|
status = gst_vaapi_decoder_decode(decode->decoder, frame);
|
2012-12-04 13:45:29 +00:00
|
|
|
if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
|
2013-04-18 13:50:02 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
2012-12-04 13:45:29 +00:00
|
|
|
g_mutex_lock(&decode->decoder_mutex);
|
2015-02-04 16:34:59 +00:00
|
|
|
if (gst_vaapi_decoder_check_status (decode->decoder) ==
|
|
|
|
GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE)
|
|
|
|
g_cond_wait(&decode->decoder_ready, &decode->decoder_mutex);
|
2012-12-04 13:45:29 +00:00
|
|
|
g_mutex_unlock(&decode->decoder_mutex);
|
2013-04-18 13:50:02 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
2013-11-20 18:21:05 +00:00
|
|
|
if (decode->decoder_loop_status < 0)
|
|
|
|
goto error_decode_loop;
|
2013-08-29 06:12:10 +00:00
|
|
|
continue;
|
2010-04-30 15:50:19 +00:00
|
|
|
}
|
2012-12-04 13:45:29 +00:00
|
|
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
|
|
goto error_decode;
|
2012-12-13 13:30:18 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-08-29 06:12:10 +00:00
|
|
|
|
|
|
|
/* Try to report back early any error that occured in the decode task */
|
2013-11-20 18:21:05 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
|
|
|
return decode->decoder_loop_status;
|
2013-01-17 17:19:14 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
2013-11-20 18:21:05 +00:00
|
|
|
error_decode_loop:
|
|
|
|
{
|
2015-01-27 12:50:12 +00:00
|
|
|
if (decode->decoder_loop_status != GST_FLOW_FLUSHING)
|
|
|
|
GST_ERROR("decode loop error %d", decode->decoder_loop_status);
|
2013-11-20 18:21:05 +00:00
|
|
|
gst_video_decoder_drop_frame(vdec, frame);
|
|
|
|
return decode->decoder_loop_status;
|
|
|
|
}
|
2013-01-17 17:19:14 +00:00
|
|
|
error_decode:
|
|
|
|
{
|
|
|
|
GST_ERROR("decode error %d", status);
|
|
|
|
switch (status) {
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
|
|
|
|
ret = GST_FLOW_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
default:
|
2015-02-18 09:19:26 +00:00
|
|
|
GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding error"),
|
|
|
|
("Decode error %d", status));
|
2013-08-29 06:12:10 +00:00
|
|
|
ret = GST_FLOW_ERROR;
|
2013-01-17 17:19:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
gst_video_decoder_drop_frame(vdec, frame);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstFlowReturn
|
2013-11-20 18:21:05 +00:00
|
|
|
gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec,
|
|
|
|
GstVideoCodecFrame *out_frame)
|
2013-01-17 17:19:14 +00:00
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
GstVaapiSurfaceProxy *proxy;
|
|
|
|
GstFlowReturn ret;
|
2013-07-08 12:50:42 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
|
|
const GstVaapiRectangle *crop_rect;
|
|
|
|
GstVaapiVideoMeta *meta;
|
2013-04-17 08:18:45 +00:00
|
|
|
guint flags;
|
2013-07-08 12:50:42 +00:00
|
|
|
#endif
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2013-04-18 13:50:02 +00:00
|
|
|
if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) {
|
|
|
|
proxy = gst_video_codec_frame_get_user_data(out_frame);
|
2010-04-30 15:50:19 +00:00
|
|
|
|
2013-04-18 13:50:02 +00:00
|
|
|
gst_vaapi_surface_proxy_set_destroy_notify(proxy,
|
|
|
|
(GDestroyNotify)gst_vaapidecode_release, decode);
|
2010-05-16 21:04:32 +00:00
|
|
|
|
2012-11-08 14:41:22 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2013-04-18 13:50:02 +00:00
|
|
|
ret = gst_video_decoder_allocate_output_frame(vdec, out_frame);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto error_create_buffer;
|
|
|
|
|
|
|
|
meta = gst_buffer_get_vaapi_video_meta(out_frame->output_buffer);
|
|
|
|
if (!meta)
|
|
|
|
goto error_get_meta;
|
|
|
|
gst_vaapi_video_meta_set_surface_proxy(meta, proxy);
|
|
|
|
|
|
|
|
flags = gst_vaapi_surface_proxy_get_flags(proxy);
|
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
|
|
|
|
guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED;
|
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF)
|
|
|
|
out_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
|
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF)
|
|
|
|
out_flags |= GST_VIDEO_BUFFER_FLAG_RFF;
|
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD)
|
|
|
|
out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD;
|
|
|
|
GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags);
|
|
|
|
}
|
2013-07-08 12:50:42 +00:00
|
|
|
|
|
|
|
crop_rect = gst_vaapi_surface_proxy_get_crop_rect(proxy);
|
|
|
|
if (crop_rect) {
|
|
|
|
GstVideoCropMeta * const crop_meta =
|
|
|
|
gst_buffer_add_video_crop_meta(out_frame->output_buffer);
|
|
|
|
if (crop_meta) {
|
|
|
|
crop_meta->x = crop_rect->x;
|
|
|
|
crop_meta->y = crop_rect->y;
|
|
|
|
crop_meta->width = crop_rect->width;
|
|
|
|
crop_meta->height = crop_rect->height;
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 11:41:00 +00:00
|
|
|
|
2015-02-20 14:29:17 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0) && (USE_GLX || USE_EGL)
|
2013-07-15 11:41:00 +00:00
|
|
|
if (decode->has_texture_upload_meta)
|
2013-11-20 17:20:07 +00:00
|
|
|
gst_buffer_ensure_texture_upload_meta(out_frame->output_buffer);
|
2013-07-15 11:41:00 +00:00
|
|
|
#endif
|
2012-11-08 14:41:22 +00:00
|
|
|
#else
|
2013-04-18 13:50:02 +00:00
|
|
|
out_frame->output_buffer =
|
|
|
|
gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
|
|
|
|
if (!out_frame->output_buffer)
|
|
|
|
goto error_create_buffer;
|
2012-11-08 14:41:22 +00:00
|
|
|
#endif
|
2013-04-18 13:50:02 +00:00
|
|
|
}
|
2010-04-30 15:50:19 +00:00
|
|
|
|
2013-04-18 13:50:02 +00:00
|
|
|
ret = gst_video_decoder_finish_frame(vdec, out_frame);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto error_commit_buffer;
|
2013-01-03 12:10:33 +00:00
|
|
|
|
2013-04-18 13:50:02 +00:00
|
|
|
gst_video_codec_frame_unref(out_frame);
|
2010-04-30 15:37:28 +00:00
|
|
|
return GST_FLOW_OK;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
error_create_buffer:
|
|
|
|
{
|
|
|
|
const GstVaapiID surface_id =
|
|
|
|
gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
|
|
|
|
|
2015-02-18 09:19:26 +00:00
|
|
|
GST_ELEMENT_ERROR(vdec, STREAM, FAILED,
|
|
|
|
("Failed to create sink buffer"),
|
|
|
|
("video sink failed to create video buffer for proxy'ed "
|
2012-10-17 12:52:35 +00:00
|
|
|
"surface %" GST_VAAPI_ID_FORMAT,
|
2015-02-18 09:19:26 +00:00
|
|
|
GST_VAAPI_ID_ARGS(surface_id)));
|
2012-12-04 13:45:29 +00:00
|
|
|
gst_video_decoder_drop_frame(vdec, out_frame);
|
2012-12-13 14:34:10 +00:00
|
|
|
gst_video_codec_frame_unref(out_frame);
|
2013-08-29 06:12:10 +00:00
|
|
|
return GST_FLOW_ERROR;
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
2013-03-20 13:40:57 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2012-11-08 14:41:22 +00:00
|
|
|
error_get_meta:
|
|
|
|
{
|
2015-02-18 09:19:26 +00:00
|
|
|
GST_ELEMENT_ERROR(vdec, STREAM, FAILED,
|
|
|
|
("Failed to get vaapi video meta attached to video buffer"),
|
|
|
|
("Failed to get vaapi video meta attached to video buffer"));
|
2012-11-08 14:41:22 +00:00
|
|
|
gst_video_decoder_drop_frame(vdec, out_frame);
|
|
|
|
gst_video_codec_frame_unref(out_frame);
|
2013-08-29 06:12:10 +00:00
|
|
|
return GST_FLOW_ERROR;
|
2012-11-08 14:41:22 +00:00
|
|
|
}
|
2013-03-20 13:40:57 +00:00
|
|
|
#endif
|
2010-04-29 17:55:58 +00:00
|
|
|
error_commit_buffer:
|
|
|
|
{
|
2013-04-18 13:55:26 +00:00
|
|
|
if (ret != GST_FLOW_FLUSHING)
|
2015-02-18 09:21:35 +00:00
|
|
|
GST_ERROR("video sink rejected the video buffer (error: %s [%d])",
|
|
|
|
gst_flow_get_name (ret), ret);
|
2012-12-13 14:34:10 +00:00
|
|
|
gst_video_codec_frame_unref(out_frame);
|
2013-08-29 06:12:10 +00:00
|
|
|
return ret;
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-17 17:19:14 +00:00
|
|
|
static GstFlowReturn
|
|
|
|
gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
|
|
|
{
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
2013-01-17 17:19:14 +00:00
|
|
|
GstFlowReturn ret;
|
|
|
|
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
if (!decode->input_state)
|
|
|
|
goto not_negotiated;
|
|
|
|
|
|
|
|
if (G_UNLIKELY(!decode->active) ||
|
|
|
|
gst_pad_needs_reconfigure(GST_VIDEO_DECODER_SRC_PAD(vdec))) {
|
|
|
|
GST_DEBUG_OBJECT(decode, "activating the decoder");
|
|
|
|
if (!gst_vaapidecode_update_src_caps(decode))
|
|
|
|
goto not_negotiated;
|
|
|
|
|
|
|
|
if (!gst_video_decoder_negotiate(vdec))
|
|
|
|
goto not_negotiated;
|
|
|
|
|
|
|
|
GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec);
|
|
|
|
if (!gst_vaapi_plugin_base_set_caps(plugin, NULL, decode->srcpad_caps))
|
|
|
|
goto not_negotiated;
|
|
|
|
|
|
|
|
decode->active = TRUE;
|
|
|
|
}
|
|
|
|
|
2013-04-18 13:50:02 +00:00
|
|
|
/* Make sure to release the base class stream lock so that decode
|
|
|
|
loop can call gst_video_decoder_finish_frame() without blocking */
|
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
2013-01-17 17:19:14 +00:00
|
|
|
ret = gst_vaapidecode_decode_frame(vdec, frame);
|
2013-04-18 13:50:02 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
|
|
|
return ret;
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
not_negotiated:
|
|
|
|
{
|
|
|
|
GST_ERROR_OBJECT (decode, "not negotiated");
|
|
|
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
|
|
|
gst_video_decoder_drop_frame (vdec, frame);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-04-18 13:50:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_vaapidecode_decode_loop(GstVaapiDecode *decode)
|
|
|
|
{
|
|
|
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
2013-11-20 18:21:05 +00:00
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
GstVideoCodecFrame *out_frame;
|
2013-04-18 13:50:02 +00:00
|
|
|
GstFlowReturn ret;
|
|
|
|
|
2013-11-20 18:21:05 +00:00
|
|
|
status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
|
|
|
|
&out_frame, 100000);
|
|
|
|
|
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
|
|
|
switch (status) {
|
|
|
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
|
|
|
ret = gst_vaapidecode_push_decoded_frame(vdec, out_frame);
|
|
|
|
break;
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
|
|
|
ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
|
|
|
break;
|
|
|
|
default:
|
2015-02-18 09:19:26 +00:00
|
|
|
GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding failed"),
|
|
|
|
("Unknown decoding error"));
|
2013-11-20 18:21:05 +00:00
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
decode->decoder_loop_status = ret;
|
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
|
|
|
|
2013-08-29 09:55:05 +00:00
|
|
|
/* If invoked from gst_vaapidecode_finish(), then return right
|
|
|
|
away no matter the errors, or the GstVaapiDecoder needs further
|
|
|
|
data to complete decoding (there no more data to feed in) */
|
|
|
|
if (decode->decoder_finish) {
|
|
|
|
g_mutex_lock(&decode->decoder_mutex);
|
|
|
|
g_cond_signal(&decode->decoder_finish_done);
|
|
|
|
g_mutex_unlock(&decode->decoder_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-29 06:22:01 +00:00
|
|
|
if (ret == GST_FLOW_OK)
|
|
|
|
return;
|
|
|
|
|
2013-08-29 09:55:05 +00:00
|
|
|
/* Suspend the task if an error occurred */
|
|
|
|
if (ret != GST_VIDEO_DECODER_FLOW_NEED_DATA)
|
2013-12-17 17:46:07 +00:00
|
|
|
gst_pad_pause_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
|
2013-01-17 17:19:14 +00:00
|
|
|
}
|
|
|
|
|
2013-11-21 10:01:41 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_flush(GstVideoDecoder *vdec)
|
2013-01-17 17:22:49 +00:00
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
|
2014-08-11 14:14:53 +00:00
|
|
|
if (!decode->decoder)
|
|
|
|
return TRUE;
|
|
|
|
|
2013-07-30 06:05:39 +00:00
|
|
|
/* If there is something in GstVideoDecoder's output adapter, then
|
|
|
|
submit the frame for decoding */
|
2013-11-21 10:01:41 +00:00
|
|
|
if (decode->current_frame_size) {
|
2013-07-30 06:05:39 +00:00
|
|
|
gst_video_decoder_have_frame(vdec);
|
2013-11-21 10:01:41 +00:00
|
|
|
decode->current_frame_size = 0;
|
|
|
|
}
|
2013-07-30 06:05:39 +00:00
|
|
|
|
2013-01-17 17:22:49 +00:00
|
|
|
status = gst_vaapi_decoder_flush(decode->decoder);
|
|
|
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
|
|
goto error_flush;
|
2013-11-21 10:01:41 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
error_flush:
|
|
|
|
{
|
|
|
|
GST_ERROR("failed to flush decoder (status %d)", status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstFlowReturn
|
|
|
|
gst_vaapidecode_finish(GstVideoDecoder *vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
GstFlowReturn ret = GST_FLOW_OK;
|
|
|
|
|
2014-08-11 14:14:53 +00:00
|
|
|
if (!decode->decoder)
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
|
2013-11-21 10:01:41 +00:00
|
|
|
if (!gst_vaapidecode_flush(vdec))
|
|
|
|
ret = GST_FLOW_OK;
|
2013-04-18 13:50:02 +00:00
|
|
|
|
|
|
|
/* Make sure the decode loop function has a chance to return, thus
|
|
|
|
possibly unlocking gst_video_decoder_finish_frame() */
|
2014-07-29 06:22:01 +00:00
|
|
|
if (decode->decoder_loop_status == GST_FLOW_OK) {
|
2014-08-12 10:01:57 +00:00
|
|
|
decode->decoder_finish = TRUE;
|
2014-07-29 06:22:01 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
|
|
|
g_mutex_lock(&decode->decoder_mutex);
|
2014-07-29 13:47:46 +00:00
|
|
|
while (decode->decoder_loop_status == GST_FLOW_OK)
|
2014-07-29 06:22:01 +00:00
|
|
|
g_cond_wait(&decode->decoder_finish_done, &decode->decoder_mutex);
|
|
|
|
g_mutex_unlock(&decode->decoder_mutex);
|
|
|
|
gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
|
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
2014-08-12 10:01:57 +00:00
|
|
|
decode->decoder_finish = FALSE;
|
|
|
|
gst_pad_start_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode),
|
|
|
|
(GstTaskFunction)gst_vaapidecode_decode_loop, decode, NULL);
|
2014-07-29 06:22:01 +00:00
|
|
|
}
|
2013-11-21 10:01:41 +00:00
|
|
|
return ret;
|
2013-01-17 17:22:49 +00:00
|
|
|
}
|
|
|
|
|
2013-03-20 13:40:57 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2012-11-08 14:41:22 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
GstCaps *caps = NULL;
|
2014-07-28 16:00:19 +00:00
|
|
|
GstVideoCodecState *state;
|
2014-08-21 12:10:36 +00:00
|
|
|
GstVaapiCapsFeature feature;
|
2015-02-09 20:09:07 +00:00
|
|
|
GstVideoFormat out_format;
|
2012-11-08 14:41:22 +00:00
|
|
|
|
vaapidecode: upload meta only if feature and allocation
When vaapidecode finishes the decoding of a frame and pushes it,
if, in the decide_allocation() method, it is determined if the
next element supports the GL texture upload meta feature, the
decoder adds the buffer's meta.
Nonetheless, in the same spirit of the commit 71d3ce4d, the
determination if the next element supports the GL texture upload
meta needs to check both the preferred caps feature *and* if the
allocation query request the API type.
This patch, first removes the unused variable need_pool, and
determines the attribute has_texture_upload_meta using the
preferred caps feature *and* the allocation query.
Also, the feature passed to GstVaapPluginBase is not longer
determined by has_texture_upload_meta, but by the computed
preferred one.
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:26:54 +00:00
|
|
|
gst_query_parse_allocation(query, &caps, NULL);
|
2012-11-08 14:41:22 +00:00
|
|
|
|
vaapidecode: upload meta only if feature and allocation
When vaapidecode finishes the decoding of a frame and pushes it,
if, in the decide_allocation() method, it is determined if the
next element supports the GL texture upload meta feature, the
decoder adds the buffer's meta.
Nonetheless, in the same spirit of the commit 71d3ce4d, the
determination if the next element supports the GL texture upload
meta needs to check both the preferred caps feature *and* if the
allocation query request the API type.
This patch, first removes the unused variable need_pool, and
determines the attribute has_texture_upload_meta using the
preferred caps feature *and* the allocation query.
Also, the feature passed to GstVaapPluginBase is not longer
determined by has_texture_upload_meta, but by the computed
preferred one.
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:26:54 +00:00
|
|
|
feature =
|
|
|
|
gst_vaapi_find_preferred_caps_feature(GST_VIDEO_DECODER_SRC_PAD(vdec),
|
|
|
|
GST_VIDEO_FORMAT_ENCODED, &out_format);
|
2013-12-11 18:08:26 +00:00
|
|
|
decode->has_texture_upload_meta = FALSE;
|
2015-02-20 14:29:17 +00:00
|
|
|
#if GST_CHECK_VERSION(1,1,0) && (USE_GLX || USE_EGL)
|
2014-07-28 16:00:19 +00:00
|
|
|
decode->has_texture_upload_meta =
|
vaapidecode: upload meta only if feature and allocation
When vaapidecode finishes the decoding of a frame and pushes it,
if, in the decide_allocation() method, it is determined if the
next element supports the GL texture upload meta feature, the
decoder adds the buffer's meta.
Nonetheless, in the same spirit of the commit 71d3ce4d, the
determination if the next element supports the GL texture upload
meta needs to check both the preferred caps feature *and* if the
allocation query request the API type.
This patch, first removes the unused variable need_pool, and
determines the attribute has_texture_upload_meta using the
preferred caps feature *and* the allocation query.
Also, the feature passed to GstVaapPluginBase is not longer
determined by has_texture_upload_meta, but by the computed
preferred one.
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:26:54 +00:00
|
|
|
(feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) &&
|
|
|
|
gst_query_find_allocation_meta (query,
|
|
|
|
GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
|
2014-07-28 16:00:19 +00:00
|
|
|
#endif
|
2014-06-13 20:45:04 +00:00
|
|
|
|
2013-12-11 18:08:26 +00:00
|
|
|
/* Update src caps if feature is not handled downstream */
|
2014-08-21 12:10:36 +00:00
|
|
|
state = gst_video_decoder_get_output_state(vdec);
|
2015-02-26 10:28:02 +00:00
|
|
|
if (!gst_caps_is_always_compatible(caps, state->caps))
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
gst_vaapidecode_update_src_caps(decode);
|
2013-12-11 18:08:26 +00:00
|
|
|
gst_video_codec_state_unref(state);
|
|
|
|
|
2014-08-21 12:10:36 +00:00
|
|
|
return gst_vaapi_plugin_base_decide_allocation(GST_VAAPI_PLUGIN_BASE(vdec),
|
|
|
|
query, feature);
|
2012-11-08 14:41:22 +00:00
|
|
|
}
|
2013-03-20 13:40:57 +00:00
|
|
|
#endif
|
2012-11-08 14:41:22 +00:00
|
|
|
|
2012-07-25 08:02:29 +00:00
|
|
|
static inline gboolean
|
|
|
|
gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
|
|
|
|
{
|
2013-12-13 10:52:47 +00:00
|
|
|
return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(decode));
|
2012-07-25 08:02:29 +00:00
|
|
|
}
|
|
|
|
|
2012-09-11 14:41:32 +00:00
|
|
|
static inline guint
|
|
|
|
gst_vaapi_codec_from_caps(GstCaps *caps)
|
|
|
|
{
|
|
|
|
return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
|
|
|
|
}
|
|
|
|
|
2010-05-05 15:36:25 +00:00
|
|
|
static gboolean
|
2010-05-12 08:32:34 +00:00
|
|
|
gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
|
2010-05-05 15:36:25 +00:00
|
|
|
{
|
2012-04-10 11:29:10 +00:00
|
|
|
GstVaapiDisplay *dpy;
|
2011-08-12 08:21:19 +00:00
|
|
|
|
2012-07-25 08:02:29 +00:00
|
|
|
if (!gst_vaapidecode_ensure_display(decode))
|
2010-05-05 15:36:25 +00:00
|
|
|
return FALSE;
|
2013-12-13 09:24:26 +00:00
|
|
|
dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-09-11 14:41:32 +00:00
|
|
|
switch (gst_vaapi_codec_from_caps(caps)) {
|
|
|
|
case GST_VAAPI_CODEC_MPEG2:
|
|
|
|
decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
|
|
|
|
break;
|
|
|
|
case GST_VAAPI_CODEC_MPEG4:
|
|
|
|
case GST_VAAPI_CODEC_H263:
|
|
|
|
decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
|
|
|
|
break;
|
|
|
|
case GST_VAAPI_CODEC_H264:
|
2012-07-19 15:16:28 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
|
2014-02-06 06:30:10 +00:00
|
|
|
|
|
|
|
/* Set the stream buffer alignment for better optimizations */
|
|
|
|
if (decode->decoder && caps) {
|
|
|
|
GstStructure * const structure = gst_caps_get_structure(caps, 0);
|
|
|
|
const gchar *str = NULL;
|
|
|
|
|
|
|
|
if ((str = gst_structure_get_string(structure, "alignment"))) {
|
|
|
|
GstVaapiStreamAlignH264 alignment;
|
|
|
|
if (g_strcmp0(str, "au") == 0)
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_AU;
|
|
|
|
else if (g_strcmp0(str, "nal") == 0)
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU;
|
|
|
|
else
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE;
|
|
|
|
gst_vaapi_decoder_h264_set_alignment(
|
|
|
|
GST_VAAPI_DECODER_H264(decode->decoder), alignment);
|
|
|
|
}
|
|
|
|
}
|
2012-09-11 14:41:32 +00:00
|
|
|
break;
|
|
|
|
case GST_VAAPI_CODEC_WMV3:
|
|
|
|
case GST_VAAPI_CODEC_VC1:
|
2012-07-19 15:16:28 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
|
2012-09-11 14:41:32 +00:00
|
|
|
break;
|
2012-02-09 16:21:04 +00:00
|
|
|
#if USE_JPEG_DECODER
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_JPEG:
|
2012-07-19 15:16:28 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
|
2012-09-11 14:41:32 +00:00
|
|
|
break;
|
2011-08-12 08:21:19 +00:00
|
|
|
#endif
|
2014-04-29 10:22:47 +00:00
|
|
|
#if USE_VP8_DECODER
|
2013-12-26 23:18:24 +00:00
|
|
|
case GST_VAAPI_CODEC_VP8:
|
|
|
|
decode->decoder = gst_vaapi_decoder_vp8_new(dpy, caps);
|
|
|
|
break;
|
2014-04-29 10:22:47 +00:00
|
|
|
#endif
|
2012-09-11 14:41:32 +00:00
|
|
|
default:
|
|
|
|
decode->decoder = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2010-05-12 08:32:34 +00:00
|
|
|
if (!decode->decoder)
|
|
|
|
return FALSE;
|
|
|
|
|
2013-05-06 12:43:38 +00:00
|
|
|
gst_vaapi_decoder_set_codec_state_changed_func(decode->decoder,
|
|
|
|
gst_vaapi_decoder_state_changed, decode);
|
2011-07-22 13:39:51 +00:00
|
|
|
|
2010-05-12 08:32:34 +00:00
|
|
|
decode->decoder_caps = gst_caps_ref(caps);
|
2013-12-17 17:46:07 +00:00
|
|
|
return gst_pad_start_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode),
|
2013-04-18 13:50:02 +00:00
|
|
|
(GstTaskFunction)gst_vaapidecode_decode_loop, decode, NULL);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_vaapidecode_destroy(GstVaapiDecode *decode)
|
|
|
|
{
|
2013-12-17 17:46:07 +00:00
|
|
|
gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
|
2013-05-06 12:43:38 +00:00
|
|
|
gst_vaapi_decoder_replace(&decode->decoder, NULL);
|
2012-12-04 13:53:15 +00:00
|
|
|
gst_caps_replace(&decode->decoder_caps, NULL);
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
|
|
|
|
decode->active = FALSE;
|
|
|
|
|
2012-12-03 12:46:28 +00:00
|
|
|
gst_vaapidecode_release(decode);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2010-05-12 08:32:34 +00:00
|
|
|
static gboolean
|
2013-01-23 22:49:17 +00:00
|
|
|
gst_vaapidecode_reset_full(GstVaapiDecode *decode, GstCaps *caps, gboolean hard)
|
2010-05-12 08:32:34 +00:00
|
|
|
{
|
2012-09-11 15:03:33 +00:00
|
|
|
GstVaapiCodec codec;
|
|
|
|
|
2013-07-15 11:41:00 +00:00
|
|
|
decode->has_texture_upload_meta = FALSE;
|
|
|
|
|
2013-11-21 10:01:41 +00:00
|
|
|
/* Reset tracked frame size */
|
|
|
|
decode->current_frame_size = 0;
|
|
|
|
|
2013-01-23 22:49:17 +00:00
|
|
|
/* Reset timers if hard reset was requested (e.g. seek) */
|
|
|
|
if (hard) {
|
2013-08-29 06:12:10 +00:00
|
|
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
|
|
|
GstVideoCodecFrame *out_frame = NULL;
|
|
|
|
|
|
|
|
gst_vaapi_decoder_flush(decode->decoder);
|
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
2013-12-17 17:46:07 +00:00
|
|
|
gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
|
2013-08-29 06:12:10 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
|
|
|
decode->decoder_loop_status = GST_FLOW_OK;
|
|
|
|
|
|
|
|
/* Purge all decoded frames as we don't need them (e.g. seek) */
|
|
|
|
while (gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
|
|
|
|
&out_frame, 0) == GST_VAAPI_DECODER_STATUS_SUCCESS) {
|
|
|
|
gst_video_codec_frame_unref(out_frame);
|
|
|
|
out_frame = NULL;
|
|
|
|
}
|
2013-01-23 22:49:17 +00:00
|
|
|
}
|
|
|
|
|
2012-09-11 15:03:33 +00:00
|
|
|
/* Only reset decoder if codec type changed */
|
2013-01-23 22:49:17 +00:00
|
|
|
else if (decode->decoder && decode->decoder_caps) {
|
2012-09-11 15:03:33 +00:00
|
|
|
if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
|
|
|
|
return TRUE;
|
|
|
|
codec = gst_vaapi_codec_from_caps(caps);
|
|
|
|
if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
|
|
|
|
return TRUE;
|
|
|
|
}
|
2010-05-12 08:32:34 +00:00
|
|
|
|
|
|
|
gst_vaapidecode_destroy(decode);
|
|
|
|
return gst_vaapidecode_create(decode, caps);
|
|
|
|
}
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
static void
|
|
|
|
gst_vaapidecode_finalize(GObject *object)
|
|
|
|
{
|
2010-05-12 08:32:34 +00:00
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
|
|
|
|
|
2012-12-04 13:53:15 +00:00
|
|
|
gst_caps_replace(&decode->sinkpad_caps, NULL);
|
|
|
|
gst_caps_replace(&decode->srcpad_caps, NULL);
|
|
|
|
gst_caps_replace(&decode->allowed_caps, NULL);
|
2011-07-22 13:39:51 +00:00
|
|
|
|
2013-08-29 09:55:05 +00:00
|
|
|
g_cond_clear(&decode->decoder_finish_done);
|
2012-10-04 16:39:53 +00:00
|
|
|
g_cond_clear(&decode->decoder_ready);
|
|
|
|
g_mutex_clear(&decode->decoder_mutex);
|
|
|
|
|
2013-12-13 09:24:26 +00:00
|
|
|
gst_vaapi_plugin_base_finalize(GST_VAAPI_PLUGIN_BASE(object));
|
2012-06-30 17:58:36 +00:00
|
|
|
G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_open(GstVideoDecoder *vdec)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
2013-12-13 09:24:26 +00:00
|
|
|
GstVaapiDisplay * const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode);
|
2013-04-03 12:59:33 +00:00
|
|
|
gboolean success;
|
|
|
|
|
2013-12-13 09:24:26 +00:00
|
|
|
if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(decode)))
|
|
|
|
return FALSE;
|
|
|
|
|
2013-04-03 12:59:33 +00:00
|
|
|
/* Let GstVideoContext ask for a proper display to its neighbours */
|
|
|
|
/* Note: steal old display that may be allocated from get_caps()
|
|
|
|
so that to retain a reference to it, thus avoiding extra
|
|
|
|
initialization steps if we turn out to simply re-use the
|
|
|
|
existing (cached) VA display */
|
2013-12-13 09:24:26 +00:00
|
|
|
GST_VAAPI_PLUGIN_BASE_DISPLAY(decode) = NULL;
|
2013-04-03 12:59:33 +00:00
|
|
|
success = gst_vaapidecode_ensure_display(decode);
|
2013-05-06 12:43:38 +00:00
|
|
|
if (old_display)
|
|
|
|
gst_vaapi_display_unref(old_display);
|
2013-04-03 12:59:33 +00:00
|
|
|
return success;
|
2012-12-04 13:45:29 +00:00
|
|
|
}
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_close(GstVideoDecoder *vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
gst_vaapi_decode_input_state_replace(decode, NULL);
|
2012-12-04 13:45:29 +00:00
|
|
|
gst_vaapidecode_destroy(decode);
|
2013-12-13 09:24:26 +00:00
|
|
|
gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(decode));
|
2012-12-04 13:45:29 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-01-23 22:49:17 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_reset(GstVideoDecoder *vdec, gboolean hard)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
|
2013-11-21 10:01:41 +00:00
|
|
|
/* In GStreamer 1.0 context, this means a flush */
|
|
|
|
if (decode->decoder && !hard && !gst_vaapidecode_flush(vdec))
|
|
|
|
return FALSE;
|
2013-01-23 22:49:17 +00:00
|
|
|
return gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, hard);
|
|
|
|
}
|
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
|
|
|
|
{
|
2013-12-17 17:46:07 +00:00
|
|
|
GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec);
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
if (!gst_vaapi_decode_input_state_replace(decode, state))
|
|
|
|
return TRUE;
|
2012-12-12 14:22:32 +00:00
|
|
|
if (!gst_vaapidecode_update_sink_caps(decode, state->caps))
|
2012-12-04 13:45:29 +00:00
|
|
|
return FALSE;
|
2015-01-15 15:19:59 +00:00
|
|
|
if (!gst_vaapi_plugin_base_set_caps(plugin, decode->sinkpad_caps, NULL))
|
2013-12-17 17:46:07 +00:00
|
|
|
return FALSE;
|
2015-01-22 21:45:24 +00:00
|
|
|
if (!gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, FALSE))
|
|
|
|
return FALSE;
|
vaapidecode: delayed src caps negotiation
Currently the src caps are set immediately after the sink caps are set, but in
that moment the pipeline might not fully constructed and the video sink has
not negotiated its supported caps and features. As a consequence, in many cases
of playback, the least optimized caps feature is forced. This is partially the
responsible of bug #744039.
Also, vaapidecode doesn't attend the reconfigure events from downstream,
which is a problem too, since the video sink can be changed with different
caps features.
This patch delays the src caps, setting them until the first frame arrives to
the decoder, assuming until that very moment the whole pipeline is already
negotiated. Particularly, it checks if the src pad needs to be reconfigured,
as a consequence of a reconfiguration event from downstream.
A key part of this patch is the new GstVaapiCapsFeature
GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED, which is returned when the src pad
doesn't have a peer yet. Also, for a better report of the caps allowed
through the src pad and its peer, this patch uses gst_pad_get_allowed_caps()
instead of gst_pad_peer_query_caps() when looking for the preferred feature.
v3: move the input_state unref to close(), since videodecoder resets at
some events such as navigation.
v4: a) the state_changed() callback replaces the input_state if the media
changed, so this case is also handled.
b) since the parameter ref_state in gst_vaapidecode_update_src_caps() is
always the input_state, the parameter were removed.
c) there were a lot of repeated code handling the input_state, so I
refactored it with the function gst_vaapi_decode_input_state_replace().
https://bugzilla.gnome.org/show_bug.cgi?id=744618
Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
2015-02-26 10:24:55 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static GstFlowReturn
|
2014-06-18 11:47:36 +00:00
|
|
|
gst_vaapidecode_parse_frame(GstVideoDecoder *vdec,
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
GstFlowReturn ret;
|
|
|
|
guint got_unit_size;
|
|
|
|
gboolean got_frame;
|
|
|
|
|
|
|
|
status = gst_vaapi_decoder_parse(decode->decoder, frame,
|
|
|
|
adapter, at_eos, &got_unit_size, &got_frame);
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
2013-07-30 06:05:39 +00:00
|
|
|
if (got_unit_size > 0) {
|
2012-12-04 13:45:29 +00:00
|
|
|
gst_video_decoder_add_to_frame(vdec, got_unit_size);
|
2013-07-30 06:05:39 +00:00
|
|
|
decode->current_frame_size += got_unit_size;
|
|
|
|
}
|
|
|
|
if (got_frame) {
|
2012-12-04 13:45:29 +00:00
|
|
|
ret = gst_video_decoder_have_frame(vdec);
|
2013-07-30 06:05:39 +00:00
|
|
|
decode->current_frame_size = 0;
|
|
|
|
}
|
2012-12-04 13:45:29 +00:00
|
|
|
else
|
2014-06-18 11:47:36 +00:00
|
|
|
ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA;
|
2010-04-29 17:55:58 +00:00
|
|
|
break;
|
2012-12-04 13:45:29 +00:00
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
|
|
|
ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
2010-04-29 17:55:58 +00:00
|
|
|
break;
|
2012-12-04 13:45:29 +00:00
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
|
|
|
|
GST_WARNING("parse error %d", status);
|
|
|
|
ret = GST_FLOW_NOT_SUPPORTED;
|
2013-07-30 06:05:39 +00:00
|
|
|
decode->current_frame_size = 0;
|
2011-12-08 10:54:59 +00:00
|
|
|
break;
|
2010-04-29 17:55:58 +00:00
|
|
|
default:
|
2012-12-04 13:45:29 +00:00
|
|
|
GST_ERROR("parse error %d", status);
|
2012-09-03 11:00:25 +00:00
|
|
|
ret = GST_FLOW_EOS;
|
2013-07-30 06:05:39 +00:00
|
|
|
decode->current_frame_size = 0;
|
2010-04-29 17:55:58 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-12-04 13:45:29 +00:00
|
|
|
return ret;
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-18 11:47:36 +00:00
|
|
|
static GstFlowReturn
|
|
|
|
gst_vaapidecode_parse(GstVideoDecoder *vdec,
|
|
|
|
GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
|
|
|
|
{
|
|
|
|
GstFlowReturn ret;
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = gst_vaapidecode_parse_frame(vdec, frame, adapter, at_eos);
|
|
|
|
} while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-17 02:26:03 +00:00
|
|
|
static GstStateChangeReturn
|
|
|
|
gst_vaapidecode_change_state (GstElement * element, GstStateChange transition)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
|
|
|
|
|
|
|
|
switch (transition) {
|
|
|
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
2014-08-12 10:00:03 +00:00
|
|
|
g_mutex_lock(&decode->decoder_mutex);
|
|
|
|
decode->decoder_finish = TRUE;
|
|
|
|
g_cond_signal(&decode->decoder_finish_done);
|
|
|
|
g_cond_signal(&decode->decoder_ready);
|
|
|
|
g_mutex_unlock(&decode->decoder_mutex);
|
2013-12-17 02:26:03 +00:00
|
|
|
gst_pad_stop_task(GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode));
|
2014-08-12 10:00:03 +00:00
|
|
|
decode->decoder_finish = FALSE;
|
2013-12-17 02:26:03 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return GST_ELEMENT_CLASS(gst_vaapidecode_parent_class)->change_state(
|
|
|
|
element, transition);
|
|
|
|
}
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
static void
|
|
|
|
gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
|
|
|
|
GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass);
|
2012-06-30 17:58:36 +00:00
|
|
|
GstPadTemplate *pad_template;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2011-09-14 19:12:41 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
|
|
|
|
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
|
|
|
|
2013-12-13 09:24:26 +00:00
|
|
|
gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass));
|
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
object_class->finalize = gst_vaapidecode_finalize;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2013-12-17 02:26:03 +00:00
|
|
|
element_class->change_state =
|
|
|
|
GST_DEBUG_FUNCPTR(gst_vaapidecode_change_state);
|
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
vdec_class->open = GST_DEBUG_FUNCPTR(gst_vaapidecode_open);
|
|
|
|
vdec_class->close = GST_DEBUG_FUNCPTR(gst_vaapidecode_close);
|
|
|
|
vdec_class->set_format = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_format);
|
2013-01-23 22:49:17 +00:00
|
|
|
vdec_class->reset = GST_DEBUG_FUNCPTR(gst_vaapidecode_reset);
|
2012-12-04 13:45:29 +00:00
|
|
|
vdec_class->parse = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse);
|
|
|
|
vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame);
|
2013-01-17 17:22:49 +00:00
|
|
|
vdec_class->finish = GST_DEBUG_FUNCPTR(gst_vaapidecode_finish);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2013-03-20 13:40:57 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2012-11-08 14:41:22 +00:00
|
|
|
vdec_class->decide_allocation =
|
|
|
|
GST_DEBUG_FUNCPTR(gst_vaapidecode_decide_allocation);
|
2013-03-20 13:40:57 +00:00
|
|
|
#endif
|
2012-11-08 14:41:22 +00:00
|
|
|
|
2013-03-20 17:41:40 +00:00
|
|
|
gst_element_class_set_static_metadata(element_class,
|
|
|
|
"VA-API decoder",
|
|
|
|
"Codec/Decoder/Video",
|
|
|
|
GST_PLUGIN_DESC,
|
|
|
|
"Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
|
2012-06-30 17:58:36 +00:00
|
|
|
|
|
|
|
/* sink pad */
|
|
|
|
pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
|
|
|
|
gst_element_class_add_pad_template(element_class, pad_template);
|
|
|
|
|
|
|
|
/* src pad */
|
|
|
|
pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
|
|
|
|
gst_element_class_add_pad_template(element_class, pad_template);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2010-05-12 09:22:49 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
|
|
|
|
{
|
2013-12-20 14:31:14 +00:00
|
|
|
GstCaps *caps, *allowed_caps;
|
|
|
|
GArray *profiles;
|
|
|
|
guint i;
|
2010-05-12 09:22:49 +00:00
|
|
|
|
|
|
|
if (decode->allowed_caps)
|
|
|
|
return TRUE;
|
|
|
|
|
2012-07-25 08:02:29 +00:00
|
|
|
if (!gst_vaapidecode_ensure_display(decode))
|
2011-11-04 20:50:15 +00:00
|
|
|
goto error_no_display;
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2013-12-20 14:31:14 +00:00
|
|
|
profiles = gst_vaapi_display_get_decode_profiles(
|
2013-12-13 09:24:26 +00:00
|
|
|
GST_VAAPI_PLUGIN_BASE_DISPLAY(decode));
|
2013-12-20 14:31:14 +00:00
|
|
|
if (!profiles)
|
|
|
|
goto error_no_profiles;
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2013-12-20 14:31:14 +00:00
|
|
|
allowed_caps = gst_caps_new_empty();
|
|
|
|
if (!allowed_caps)
|
2010-05-12 09:22:49 +00:00
|
|
|
goto error_no_memory;
|
|
|
|
|
2013-12-20 14:31:14 +00:00
|
|
|
for (i = 0; i < profiles->len; i++) {
|
|
|
|
const GstVaapiProfile profile =
|
|
|
|
g_array_index(profiles, GstVaapiProfile, i);
|
|
|
|
const gchar *media_type_name;
|
2014-10-29 13:46:47 +00:00
|
|
|
const gchar *profile_name;
|
|
|
|
GstStructure *structure;
|
2013-12-20 14:31:14 +00:00
|
|
|
|
|
|
|
media_type_name = gst_vaapi_profile_get_media_type_name(profile);
|
|
|
|
if (!media_type_name)
|
2010-05-12 09:22:49 +00:00
|
|
|
continue;
|
2013-12-20 14:31:14 +00:00
|
|
|
|
|
|
|
caps = gst_caps_from_string(media_type_name);
|
|
|
|
if (!caps)
|
2010-05-12 09:22:49 +00:00
|
|
|
continue;
|
2014-10-29 13:46:47 +00:00
|
|
|
structure = gst_caps_get_structure (caps, 0);
|
2014-11-12 06:46:53 +00:00
|
|
|
|
|
|
|
profile_name = gst_vaapi_profile_get_name(profile);
|
|
|
|
if (profile_name)
|
|
|
|
gst_structure_set(structure, "profile", G_TYPE_STRING,
|
|
|
|
profile_name, NULL);
|
2014-10-29 13:46:47 +00:00
|
|
|
|
2013-12-20 14:31:14 +00:00
|
|
|
allowed_caps = gst_caps_merge(allowed_caps, caps);
|
2010-05-12 09:22:49 +00:00
|
|
|
}
|
2014-10-29 13:46:47 +00:00
|
|
|
decode->allowed_caps = gst_caps_simplify (allowed_caps);
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2013-12-20 14:31:14 +00:00
|
|
|
g_array_unref(profiles);
|
2010-05-12 09:22:49 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
error_no_display:
|
|
|
|
{
|
2012-12-27 09:35:45 +00:00
|
|
|
GST_ERROR("failed to retrieve VA display");
|
2010-05-12 09:22:49 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2013-12-20 14:31:14 +00:00
|
|
|
error_no_profiles:
|
2010-05-12 09:22:49 +00:00
|
|
|
{
|
2013-12-20 14:31:14 +00:00
|
|
|
GST_ERROR("failed to retrieve VA decode profiles");
|
2010-05-12 09:22:49 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
error_no_memory:
|
|
|
|
{
|
2012-12-27 09:35:45 +00:00
|
|
|
GST_ERROR("failed to allocate allowed-caps set");
|
2013-12-20 14:31:14 +00:00
|
|
|
g_array_unref(profiles);
|
2010-05-12 09:22:49 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstCaps *
|
|
|
|
gst_vaapidecode_get_caps(GstPad *pad)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
|
|
|
|
|
|
|
|
if (!gst_vaapidecode_ensure_allowed_caps(decode))
|
|
|
|
return gst_caps_new_empty();
|
|
|
|
|
|
|
|
return gst_caps_ref(decode->allowed_caps);
|
|
|
|
}
|
|
|
|
|
2011-11-04 20:50:15 +00:00
|
|
|
static gboolean
|
2013-03-20 13:40:57 +00:00
|
|
|
gst_vaapidecode_query(GST_PAD_QUERY_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
GstVaapiDecode * const decode =
|
|
|
|
GST_VAAPIDECODE(gst_pad_get_parent_element(pad));
|
2013-12-17 17:46:07 +00:00
|
|
|
GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(decode);
|
2011-11-04 20:50:15 +00:00
|
|
|
gboolean res;
|
|
|
|
|
2013-07-12 16:58:57 +00:00
|
|
|
GST_INFO_OBJECT(decode, "query type %s", GST_QUERY_TYPE_NAME(query));
|
2011-11-04 20:50:15 +00:00
|
|
|
|
2013-12-17 17:46:07 +00:00
|
|
|
if (gst_vaapi_reply_to_query(query, plugin->display)) {
|
|
|
|
GST_DEBUG("sharing display %p", plugin->display);
|
2013-03-20 13:40:57 +00:00
|
|
|
res = TRUE;
|
2013-07-12 16:58:57 +00:00
|
|
|
}
|
2013-04-02 14:12:16 +00:00
|
|
|
else if (GST_PAD_IS_SINK(pad)) {
|
|
|
|
switch (GST_QUERY_TYPE(query)) {
|
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
|
|
case GST_QUERY_CAPS: {
|
2015-02-18 11:36:16 +00:00
|
|
|
GstCaps *filter, *caps = NULL;
|
|
|
|
|
|
|
|
gst_query_parse_caps(query, &filter);
|
2015-02-19 11:37:09 +00:00
|
|
|
caps = gst_vaapidecode_get_caps(pad);
|
2015-02-18 11:36:16 +00:00
|
|
|
|
|
|
|
if (filter) {
|
|
|
|
GstCaps *tmp = caps;
|
|
|
|
caps = gst_caps_intersect_full(filter, tmp,
|
|
|
|
GST_CAPS_INTERSECT_FIRST);
|
|
|
|
gst_caps_unref(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT(decode, "Returning sink caps %" GST_PTR_FORMAT,
|
|
|
|
caps);
|
|
|
|
|
2013-04-02 14:12:16 +00:00
|
|
|
gst_query_set_caps_result(query, caps);
|
|
|
|
gst_caps_unref(caps);
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
default:
|
2013-12-17 17:46:07 +00:00
|
|
|
res = GST_PAD_QUERY_FUNCTION_CALL(plugin->sinkpad_query, pad,
|
|
|
|
parent, query);
|
2013-04-02 14:12:16 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-02-18 11:36:16 +00:00
|
|
|
else {
|
|
|
|
switch (GST_QUERY_TYPE(query)) {
|
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
|
|
case GST_QUERY_CAPS: {
|
|
|
|
GstCaps *filter, *caps = NULL;
|
|
|
|
|
|
|
|
gst_query_parse_caps(query, &filter);
|
2015-02-19 11:37:09 +00:00
|
|
|
caps = gst_pad_get_pad_template_caps(pad);
|
2015-02-18 11:36:16 +00:00
|
|
|
|
|
|
|
if (filter) {
|
|
|
|
GstCaps *tmp = caps;
|
|
|
|
caps = gst_caps_intersect_full(filter, tmp,
|
|
|
|
GST_CAPS_INTERSECT_FIRST);
|
|
|
|
gst_caps_unref(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT(decode, "Returning src caps %" GST_PTR_FORMAT,
|
|
|
|
caps);
|
|
|
|
|
|
|
|
gst_query_set_caps_result(query, caps);
|
|
|
|
gst_caps_unref(caps);
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
res = GST_PAD_QUERY_FUNCTION_CALL(plugin->srcpad_query, pad,
|
|
|
|
parent, query);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-11-04 20:50:15 +00:00
|
|
|
|
2013-04-18 08:06:15 +00:00
|
|
|
gst_object_unref(decode);
|
2011-11-04 20:50:15 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
static void
|
2012-06-30 17:58:36 +00:00
|
|
|
gst_vaapidecode_init(GstVaapiDecode *decode)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2012-12-04 13:45:29 +00:00
|
|
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
2013-12-17 17:46:07 +00:00
|
|
|
GstPad *pad;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2013-12-13 09:24:26 +00:00
|
|
|
gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(decode), GST_CAT_DEFAULT);
|
|
|
|
|
2010-05-16 21:04:32 +00:00
|
|
|
decode->decoder = NULL;
|
|
|
|
decode->decoder_caps = NULL;
|
|
|
|
decode->allowed_caps = NULL;
|
2013-08-29 06:12:10 +00:00
|
|
|
decode->decoder_loop_status = GST_FLOW_OK;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-10-04 16:39:53 +00:00
|
|
|
g_mutex_init(&decode->decoder_mutex);
|
|
|
|
g_cond_init(&decode->decoder_ready);
|
2013-08-29 09:55:05 +00:00
|
|
|
g_cond_init(&decode->decoder_finish_done);
|
2012-10-04 16:39:53 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
gst_video_decoder_set_packetized(vdec, FALSE);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
/* Pad through which data comes in to the element */
|
2013-12-17 17:46:07 +00:00
|
|
|
pad = GST_VAAPI_PLUGIN_BASE_SINK_PAD(decode);
|
2015-02-18 09:22:21 +00:00
|
|
|
gst_pad_set_query_function(pad, GST_DEBUG_FUNCPTR(gst_vaapidecode_query));
|
2012-09-03 11:00:25 +00:00
|
|
|
#if !GST_CHECK_VERSION(1,0,0)
|
2013-12-17 17:46:07 +00:00
|
|
|
gst_pad_set_getcaps_function(pad, gst_vaapidecode_get_caps);
|
2012-09-03 11:00:25 +00:00
|
|
|
#endif
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
/* Pad through which data goes out of the element */
|
2013-12-17 17:46:07 +00:00
|
|
|
pad = GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode);
|
2015-02-18 09:22:21 +00:00
|
|
|
gst_pad_set_query_function(pad, GST_DEBUG_FUNCPTR(gst_vaapidecode_query));
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|