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
|
2016-03-29 11:50:00 +00:00
|
|
|
*/
|
|
|
|
|
2015-04-03 14:08:30 +00:00
|
|
|
#include "gstcompat.h"
|
2011-11-04 20:50:15 +00:00
|
|
|
#include <gst/vaapi/gstvaapidisplay.h>
|
2019-08-05 17:47:30 +00:00
|
|
|
#include <gst/vaapi/gstvaapiprofilecaps.h>
|
2011-11-04 20:50:15 +00:00
|
|
|
|
|
|
|
#include "gstvaapidecode.h"
|
2017-06-14 16:23:34 +00:00
|
|
|
#include "gstvaapidecode_props.h"
|
2011-11-04 20:50:15 +00:00
|
|
|
#include "gstvaapipluginutil.h"
|
2013-03-21 16:17:53 +00:00
|
|
|
#include "gstvaapivideobuffer.h"
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (GST_VAAPI_USE_GLX || GST_VAAPI_USE_EGL)
|
2013-07-15 11:41:00 +00:00
|
|
|
#include "gstvaapivideometa_texture.h"
|
|
|
|
#endif
|
2012-11-08 14:41:22 +00:00
|
|
|
#include "gstvaapivideobufferpool.h"
|
|
|
|
#include "gstvaapivideomemory.h"
|
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>
|
2015-04-13 12:43:30 +00:00
|
|
|
#include <gst/vaapi/gstvaapidecoder_h265.h>
|
2015-11-06 13:19:38 +00:00
|
|
|
#include <gst/vaapi/gstvaapidecoder_vp9.h>
|
2022-12-10 13:11:08 +00:00
|
|
|
#if GST_VAAPI_USE_AV1_DECODER
|
2020-08-27 13:46:41 +00:00
|
|
|
#include <gst/vaapi/gstvaapidecoder_av1.h>
|
|
|
|
#endif
|
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
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapidecode);
|
2017-03-20 15:45:01 +00:00
|
|
|
#ifndef GST_DISABLE_GST_DEBUG
|
2010-04-29 17:55:58 +00:00
|
|
|
#define GST_CAT_DEFAULT gst_debug_vaapidecode
|
2017-03-20 15:45:01 +00:00
|
|
|
#else
|
|
|
|
#define GST_CAT_DEFAULT NULL
|
|
|
|
#endif
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
#define GST_VAAPI_DECODE_PARAMS_QDATA \
|
|
|
|
g_quark_from_static_string("vaapidec-params")
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
/* Default templates */
|
2011-09-14 11:07:18 +00:00
|
|
|
#define GST_CAPS_CODEC(CODEC) CODEC "; "
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
/* *INDENT-OFF* */
|
2021-12-01 11:26:11 +00:00
|
|
|
char *gst_vaapidecode_sink_caps_str = NULL;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
static const char gst_vaapidecode_src_caps_str[] =
|
2020-02-07 15:50:52 +00:00
|
|
|
GST_VAAPI_MAKE_SURFACE_CAPS "; "
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (GST_VAAPI_USE_GLX || GST_VAAPI_USE_EGL)
|
2020-02-07 15:50:52 +00:00
|
|
|
GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS "; "
|
2016-04-13 13:44:20 +00:00
|
|
|
#endif
|
2020-02-07 15:50:52 +00:00
|
|
|
GST_VIDEO_CAPS_MAKE(GST_VAAPI_FORMATS_ALL);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
|
|
|
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));
|
2015-03-02 12:59:16 +00:00
|
|
|
/* *INDENT-ON* */
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
typedef struct _GstVaapiDecoderMap GstVaapiDecoderMap;
|
|
|
|
struct _GstVaapiDecoderMap
|
|
|
|
{
|
|
|
|
guint codec;
|
|
|
|
guint rank;
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *caps_str;
|
2017-06-14 15:07:30 +00:00
|
|
|
|
|
|
|
void (*install_properties) (GObjectClass * klass);
|
2016-03-09 19:25:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const GstVaapiDecoderMap vaapi_decode_map[] = {
|
2017-06-14 15:07:30 +00:00
|
|
|
{GST_VAAPI_CODEC_JPEG, GST_RANK_MARGINAL, "jpeg", "image/jpeg", NULL},
|
2016-06-07 14:28:07 +00:00
|
|
|
{GST_VAAPI_CODEC_MPEG2, GST_RANK_PRIMARY, "mpeg2",
|
2017-06-14 15:07:30 +00:00
|
|
|
"video/mpeg, mpegversion=2, systemstream=(boolean)false", NULL},
|
2016-06-07 14:28:07 +00:00
|
|
|
{GST_VAAPI_CODEC_MPEG4, GST_RANK_PRIMARY, "mpeg4",
|
2017-06-14 15:07:30 +00:00
|
|
|
"video/mpeg, mpegversion=4", NULL},
|
|
|
|
{GST_VAAPI_CODEC_H263, GST_RANK_PRIMARY, "h263", "video/x-h263", NULL},
|
2021-07-09 09:01:14 +00:00
|
|
|
{GST_VAAPI_CODEC_H264, GST_RANK_PRIMARY, "h264", "video/x-h264",
|
2017-06-14 16:23:34 +00:00
|
|
|
gst_vaapi_decode_h264_install_properties},
|
2021-07-09 09:01:14 +00:00
|
|
|
{GST_VAAPI_CODEC_VC1, GST_RANK_PRIMARY, "vc1",
|
2017-06-14 15:07:30 +00:00
|
|
|
"video/x-wmv, wmvversion=3, format={WMV3,WVC1}", NULL},
|
2021-07-09 09:01:14 +00:00
|
|
|
{GST_VAAPI_CODEC_VP8, GST_RANK_PRIMARY, "vp8", "video/x-vp8", NULL},
|
|
|
|
{GST_VAAPI_CODEC_VP9, GST_RANK_PRIMARY, "vp9", "video/x-vp9", NULL},
|
|
|
|
{GST_VAAPI_CODEC_H265, GST_RANK_PRIMARY, "h265", "video/x-h265", NULL},
|
|
|
|
{GST_VAAPI_CODEC_AV1, GST_RANK_PRIMARY, "av1", "video/x-av1", NULL},
|
2021-12-01 11:26:11 +00:00
|
|
|
{0 /* the rest */ , GST_RANK_PRIMARY + 1, NULL, NULL, NULL},
|
2016-03-09 19:25:08 +00:00
|
|
|
};
|
|
|
|
|
2016-03-09 17:41:49 +00:00
|
|
|
static GstElementClass *parent_class = NULL;
|
2016-07-12 18:38:07 +00:00
|
|
|
GST_VAAPI_PLUGIN_BASE_DEFINE_SET_CONTEXT (parent_class);
|
2016-03-09 17:41:49 +00:00
|
|
|
|
2016-03-10 11:47:49 +00:00
|
|
|
static gboolean gst_vaapidecode_update_sink_caps (GstVaapiDecode * decode,
|
|
|
|
GstCaps * caps);
|
|
|
|
static gboolean gst_vaapi_decode_input_state_replace (GstVaapiDecode * decode,
|
2015-03-02 12:59:16 +00:00
|
|
|
const GstVideoCodecState * new_state);
|
2015-03-06 12:09:22 +00:00
|
|
|
|
2017-01-13 20:26:15 +00:00
|
|
|
/* invoked if actual VASurface size (not the cropped values)
|
|
|
|
* changed */
|
2011-07-22 13:39:51 +00:00
|
|
|
static void
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_decoder_state_changed (GstVaapiDecoder * decoder,
|
|
|
|
const GstVideoCodecState * codec_state, gpointer user_data)
|
2011-07-22 13:39:51 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (user_data);
|
|
|
|
|
|
|
|
g_assert (decode->decoder == decoder);
|
|
|
|
|
|
|
|
if (!gst_vaapi_decode_input_state_replace (decode, codec_state))
|
|
|
|
return;
|
2015-08-28 21:18:57 +00:00
|
|
|
if (!gst_vaapidecode_update_sink_caps (decode, decode->input_state->caps))
|
2015-08-28 14:06:08 +00:00
|
|
|
return;
|
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
|
|
|
}
|
|
|
|
|
2015-08-28 20:43:47 +00:00
|
|
|
static GstVideoCodecState *
|
|
|
|
copy_video_codec_state (const GstVideoCodecState * in_state)
|
|
|
|
{
|
|
|
|
GstVideoCodecState *state;
|
|
|
|
|
|
|
|
g_return_val_if_fail (in_state != NULL, NULL);
|
|
|
|
|
2023-01-24 19:16:47 +00:00
|
|
|
state = g_new0 (GstVideoCodecState, 1);
|
2015-08-28 20:43:47 +00:00
|
|
|
state->ref_count = 1;
|
2015-09-23 10:13:41 +00:00
|
|
|
state->info = in_state->info;
|
2015-08-28 20:43:47 +00:00
|
|
|
state->caps = gst_caps_copy (in_state->caps);
|
2015-10-12 11:13:03 +00:00
|
|
|
if (in_state->codec_data)
|
|
|
|
state->codec_data = gst_buffer_copy_deep (in_state->codec_data);
|
2015-08-28 20:43:47 +00:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_decode_input_state_replace (GstVaapiDecode * decode,
|
|
|
|
const GstVideoCodecState * new_state)
|
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
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
if (decode->input_state) {
|
|
|
|
if (new_state) {
|
|
|
|
const GstCaps *curcaps = decode->input_state->caps;
|
2015-08-28 21:27:05 +00:00
|
|
|
/* If existing caps are equal of the new state, keep the
|
|
|
|
* existing state without renegotiating. */
|
|
|
|
if (gst_caps_is_strictly_equal (curcaps, new_state->caps)) {
|
|
|
|
GST_DEBUG ("Ignoring new caps %" GST_PTR_FORMAT
|
|
|
|
" since are equal to current ones", new_state->caps);
|
2015-03-02 12:59:16 +00:00
|
|
|
return FALSE;
|
2015-08-28 21:27:05 +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
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_video_codec_state_unref (decode->input_state);
|
|
|
|
}
|
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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (new_state)
|
2015-08-28 20:43:47 +00:00
|
|
|
decode->input_state = copy_video_codec_state (new_state);
|
2015-03-02 12:59:16 +00:00
|
|
|
else
|
|
|
|
decode->input_state = 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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
return TRUE;
|
2011-07-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_update_sink_caps (GstVaapiDecode * decode, GstCaps * caps)
|
2011-07-22 13:39:51 +00:00
|
|
|
{
|
2015-02-12 11:31:57 +00:00
|
|
|
GST_INFO_OBJECT (decode, "new sink caps = %" GST_PTR_FORMAT, caps);
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_caps_replace (&decode->sinkpad_caps, caps);
|
|
|
|
return TRUE;
|
2011-07-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
2016-07-19 14:40:10 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_ensure_allowed_srcpad_caps (GstVaapiDecode * decode)
|
|
|
|
{
|
2020-08-12 15:50:50 +00:00
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
GstCaps *out_caps, *raw_caps, *va_caps, *dma_caps, *gltexup_caps, *base_caps;
|
|
|
|
GArray *formats;
|
|
|
|
gint min_width, min_height, max_width, max_height;
|
|
|
|
guint mem_types;
|
|
|
|
gboolean ret = FALSE;
|
2016-07-19 14:40:10 +00:00
|
|
|
|
|
|
|
if (decode->allowed_srcpad_caps)
|
|
|
|
return TRUE;
|
|
|
|
|
2020-08-12 15:50:50 +00:00
|
|
|
if (!display)
|
2016-07-19 14:40:10 +00:00
|
|
|
return FALSE;
|
|
|
|
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
if (!decode->decoder)
|
2016-07-19 14:40:10 +00:00
|
|
|
return FALSE;
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
|
2020-05-25 15:02:26 +00:00
|
|
|
dma_caps = gltexup_caps = NULL;
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
|
|
|
|
formats = gst_vaapi_decoder_get_surface_attributes (decode->decoder,
|
|
|
|
&min_width, &min_height, &max_width, &max_height, &mem_types);
|
|
|
|
if (!formats)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
base_caps = gst_vaapi_video_format_new_template_caps_from_list (formats);
|
|
|
|
if (!base_caps)
|
|
|
|
goto bail;
|
2020-05-25 15:02:26 +00:00
|
|
|
gst_vaapi_caps_set_width_and_height_range (base_caps, min_width, min_height,
|
|
|
|
max_width, max_height);
|
2016-07-19 14:40:10 +00:00
|
|
|
|
2020-08-12 15:50:50 +00:00
|
|
|
{
|
|
|
|
GArray *img_formats = gst_vaapi_display_get_image_formats (display);
|
|
|
|
GstVideoFormat decoded_format =
|
|
|
|
GST_VIDEO_INFO_FORMAT (&decode->decoded_info);
|
|
|
|
|
|
|
|
if (!img_formats)
|
|
|
|
img_formats = g_array_ref (formats);
|
|
|
|
|
|
|
|
if (decoded_format != GST_VIDEO_FORMAT_UNKNOWN) {
|
|
|
|
guint decoded_chroma =
|
|
|
|
gst_vaapi_video_format_get_chroma_type (decoded_format);
|
|
|
|
GArray *new_img_formats =
|
|
|
|
g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; i < img_formats->len; i++) {
|
|
|
|
const GstVideoFormat fmt =
|
|
|
|
g_array_index (img_formats, GstVideoFormat, i);
|
|
|
|
if (gst_vaapi_video_format_get_chroma_type (fmt) == decoded_chroma)
|
|
|
|
g_array_append_val (new_img_formats, fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_img_formats->len == 0) {
|
|
|
|
g_clear_pointer (&new_img_formats, g_array_unref);
|
|
|
|
} else {
|
|
|
|
g_clear_pointer (&img_formats, g_array_unref);
|
|
|
|
img_formats = new_img_formats;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
raw_caps = gst_vaapi_video_format_new_template_caps_from_list (img_formats);
|
|
|
|
gst_vaapi_caps_set_width_and_height_range (raw_caps, min_width, min_height,
|
|
|
|
max_width, max_height);
|
|
|
|
g_array_unref (img_formats);
|
|
|
|
}
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
|
|
|
|
va_caps = gst_caps_copy (base_caps);
|
|
|
|
gst_caps_set_features_simple (va_caps,
|
|
|
|
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE));
|
|
|
|
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (GST_VAAPI_USE_GLX || GST_VAAPI_USE_EGL)
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
if (!GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAN_DMABUF (decode)
|
|
|
|
&& gst_vaapi_display_has_opengl (GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))) {
|
|
|
|
gltexup_caps = gst_caps_from_string (GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS);
|
|
|
|
if (gltexup_caps) {
|
2020-05-25 15:02:26 +00:00
|
|
|
gst_vaapi_caps_set_width_and_height_range (base_caps, min_width,
|
|
|
|
min_height, max_width, max_height);
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
}
|
2016-07-19 14:40:10 +00:00
|
|
|
}
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
out_caps = va_caps;
|
|
|
|
if (dma_caps)
|
|
|
|
gst_caps_append (out_caps, dma_caps);
|
|
|
|
if (gltexup_caps)
|
|
|
|
gst_caps_append (out_caps, gltexup_caps);
|
2020-08-17 11:26:43 +00:00
|
|
|
gst_caps_append (out_caps, raw_caps);
|
2016-07-19 14:40:10 +00:00
|
|
|
decode->allowed_srcpad_caps = out_caps;
|
|
|
|
|
|
|
|
GST_INFO_OBJECT (decode, "allowed srcpad caps: %" GST_PTR_FORMAT,
|
|
|
|
decode->allowed_srcpad_caps);
|
|
|
|
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
bail:
|
|
|
|
if (formats)
|
|
|
|
g_array_unref (formats);
|
|
|
|
if (base_caps)
|
|
|
|
gst_caps_unref (base_caps);
|
|
|
|
return ret;
|
2016-07-19 14:40:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static GstCaps *
|
|
|
|
gst_vaapidecode_get_allowed_srcpad_caps (GstVaapiDecode * decode)
|
|
|
|
{
|
|
|
|
GstPad *const srcpad = GST_VIDEO_DECODER_SRC_PAD (decode);
|
|
|
|
|
|
|
|
if (gst_vaapidecode_ensure_allowed_srcpad_caps (decode))
|
|
|
|
return gst_caps_ref (decode->allowed_srcpad_caps);
|
|
|
|
return gst_pad_get_pad_template_caps (srcpad);
|
|
|
|
}
|
|
|
|
|
2011-07-22 13:39:51 +00:00
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_update_src_caps (GstVaapiDecode * decode)
|
2011-07-22 13:39:51 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
|
2016-03-29 12:17:54 +00:00
|
|
|
GstPad *const srcpad = GST_VIDEO_DECODER_SRC_PAD (vdec);
|
2016-07-19 14:40:10 +00:00
|
|
|
GstCaps *allowed;
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVideoCodecState *state, *ref_state;
|
2016-02-01 13:02:13 +00:00
|
|
|
GstVaapiCapsFeature feature;
|
2016-04-05 11:37:40 +00:00
|
|
|
GstCapsFeatures *features;
|
2016-04-14 13:46:32 +00:00
|
|
|
GstCaps *allocation_caps;
|
2016-04-14 14:31:34 +00:00
|
|
|
GstVideoInfo *vi;
|
2016-04-18 15:28:51 +00:00
|
|
|
GstVideoFormat format;
|
2016-02-01 13:02:13 +00:00
|
|
|
GstClockTime latency;
|
|
|
|
gint fps_d, fps_n;
|
2016-03-24 13:08:50 +00:00
|
|
|
guint width, height;
|
2016-04-05 11:37:40 +00:00
|
|
|
const gchar *format_str, *feature_str;
|
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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!decode->input_state)
|
|
|
|
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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
ref_state = decode->input_state;
|
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
|
|
|
|
2016-04-18 15:28:51 +00:00
|
|
|
format = GST_VIDEO_INFO_FORMAT (&decode->decoded_info);
|
2016-07-19 14:40:10 +00:00
|
|
|
allowed = gst_vaapidecode_get_allowed_srcpad_caps (decode);
|
|
|
|
feature = gst_vaapi_find_preferred_caps_feature (srcpad, allowed, &format);
|
|
|
|
gst_caps_unref (allowed);
|
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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (feature == GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED)
|
|
|
|
return FALSE;
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (!GST_VAAPI_USE_GLX && !GST_VAAPI_USE_EGL)
|
2016-04-05 11:07:14 +00:00
|
|
|
/* This is a very pathological situation. Should not happen. */
|
|
|
|
if (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META)
|
|
|
|
return FALSE;
|
|
|
|
#endif
|
|
|
|
|
2016-04-18 15:17:58 +00:00
|
|
|
if ((feature == GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY ||
|
|
|
|
feature == GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
|
|
|
|
&& format != GST_VIDEO_INFO_FORMAT (&decode->decoded_info)) {
|
|
|
|
GST_FIXME_OBJECT (decode, "validate if driver can convert from %s to %s",
|
|
|
|
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT
|
|
|
|
(&decode->decoded_info)), gst_video_format_to_string (format));
|
|
|
|
}
|
|
|
|
|
2016-04-14 14:43:07 +00:00
|
|
|
width = decode->display_width;
|
|
|
|
height = decode->display_height;
|
2016-03-24 13:08:50 +00:00
|
|
|
|
|
|
|
if (!width || !height) {
|
2016-03-31 14:39:08 +00:00
|
|
|
width = GST_VIDEO_INFO_WIDTH (&ref_state->info);
|
|
|
|
height = GST_VIDEO_INFO_HEIGHT (&ref_state->info);
|
2016-03-24 13:08:50 +00:00
|
|
|
}
|
|
|
|
|
2016-03-25 14:31:28 +00:00
|
|
|
state = gst_video_decoder_set_output_state (vdec, format, width, height,
|
|
|
|
ref_state);
|
2016-04-05 11:09:37 +00:00
|
|
|
if (!state)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (GST_VIDEO_INFO_WIDTH (&state->info) == 0
|
2016-03-31 14:39:08 +00:00
|
|
|
|| GST_VIDEO_INFO_HEIGHT (&state->info) == 0) {
|
2016-04-05 11:09:37 +00:00
|
|
|
gst_video_codec_state_unref (state);
|
2015-03-02 12:59:16 +00:00
|
|
|
return FALSE;
|
2016-02-15 23:48:43 +00:00
|
|
|
}
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
vi = &state->info;
|
|
|
|
state->caps = gst_video_info_to_caps (vi);
|
2016-04-05 11:37:40 +00:00
|
|
|
|
|
|
|
switch (feature) {
|
|
|
|
case GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META:
|
2017-06-01 17:42:20 +00:00
|
|
|
case GST_VAAPI_CAPS_FEATURE_DMABUF:
|
2016-04-05 11:37:40 +00:00
|
|
|
case GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE:{
|
2016-06-08 01:17:46 +00:00
|
|
|
GstStructure *structure = gst_caps_get_structure (state->caps, 0);
|
2019-08-18 11:53:53 +00:00
|
|
|
if (!structure)
|
|
|
|
break;
|
2016-04-05 11:37:40 +00:00
|
|
|
feature_str = gst_vaapi_caps_feature_to_string (feature);
|
|
|
|
features = gst_caps_features_new (feature_str, NULL);
|
|
|
|
gst_caps_set_features (state->caps, 0, features);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-04-14 13:46:32 +00:00
|
|
|
|
|
|
|
/* Allocation query is different from pad's caps */
|
|
|
|
allocation_caps = NULL;
|
2016-04-14 14:31:34 +00:00
|
|
|
if (GST_VIDEO_INFO_WIDTH (&decode->decoded_info) != width
|
|
|
|
|| GST_VIDEO_INFO_HEIGHT (&decode->decoded_info) != height) {
|
2016-04-14 13:46:32 +00:00
|
|
|
allocation_caps = gst_caps_copy (state->caps);
|
|
|
|
format_str = gst_video_format_to_string (format);
|
|
|
|
gst_caps_set_simple (allocation_caps,
|
2016-04-14 14:31:34 +00:00
|
|
|
"width", G_TYPE_INT, GST_VIDEO_INFO_WIDTH (&decode->decoded_info),
|
|
|
|
"height", G_TYPE_INT, GST_VIDEO_INFO_HEIGHT (&decode->decoded_info),
|
2016-04-14 13:46:32 +00:00
|
|
|
"format", G_TYPE_STRING, format_str, NULL);
|
|
|
|
GST_INFO_OBJECT (decode, "new alloc caps = %" GST_PTR_FORMAT,
|
|
|
|
allocation_caps);
|
|
|
|
}
|
|
|
|
gst_caps_replace (&state->allocation_caps, allocation_caps);
|
2016-06-20 10:53:26 +00:00
|
|
|
if (allocation_caps)
|
|
|
|
gst_caps_unref (allocation_caps);
|
2016-04-14 13:46:32 +00:00
|
|
|
|
2015-02-12 11:31:57 +00:00
|
|
|
GST_INFO_OBJECT (decode, "new src caps = %" GST_PTR_FORMAT, state->caps);
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_caps_replace (&decode->srcpad_caps, state->caps);
|
|
|
|
gst_video_codec_state_unref (state);
|
2015-05-21 17:38:33 +00:00
|
|
|
|
2016-02-01 13:02:13 +00:00
|
|
|
fps_n = GST_VIDEO_INFO_FPS_N (vi);
|
|
|
|
fps_d = GST_VIDEO_INFO_FPS_D (vi);
|
2015-05-21 17:38:33 +00:00
|
|
|
if (fps_n <= 0 || fps_d <= 0) {
|
|
|
|
GST_DEBUG_OBJECT (decode, "forcing 25/1 framerate for latency calculation");
|
2015-09-15 08:01:29 +00:00
|
|
|
fps_n = 25;
|
|
|
|
fps_d = 1;
|
2015-05-21 17:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* For parsing/preparation purposes we'd need at least 1 frame
|
|
|
|
* latency in general, with perfectly known unit boundaries (NALU,
|
|
|
|
* AU), and up to 2 frames when we need to wait for the second frame
|
|
|
|
* start to determine the first frame is complete */
|
2016-02-01 13:02:13 +00:00
|
|
|
latency = gst_util_uint64_scale (2 * GST_SECOND, fps_d, fps_n);
|
2015-05-21 17:38:33 +00:00
|
|
|
gst_video_decoder_set_latency (vdec, latency, latency);
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
return TRUE;
|
2011-07-22 13:39:51 +00:00
|
|
|
}
|
|
|
|
|
2016-03-24 13:08:50 +00:00
|
|
|
/* check whether the decoded surface size has changed */
|
2016-01-27 06:56:45 +00:00
|
|
|
static gboolean
|
2016-03-24 13:08:50 +00:00
|
|
|
is_surface_resolution_changed (GstVaapiDecode * decode,
|
2016-02-03 11:17:59 +00:00
|
|
|
GstVaapiSurface * surface)
|
2016-01-27 06:56:45 +00:00
|
|
|
{
|
2016-03-24 13:08:50 +00:00
|
|
|
GstVideoInfo *vinfo = &decode->decoded_info;
|
2016-04-14 14:22:25 +00:00
|
|
|
GstVideoFormat surface_format;
|
2016-01-27 06:56:45 +00:00
|
|
|
guint surface_width, surface_height;
|
2016-03-24 13:08:50 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (surface != NULL, FALSE);
|
2016-01-27 06:56:45 +00:00
|
|
|
|
2016-02-03 11:17:59 +00:00
|
|
|
gst_vaapi_surface_get_size (surface, &surface_width, &surface_height);
|
2016-01-27 06:56:45 +00:00
|
|
|
|
2016-03-24 13:08:50 +00:00
|
|
|
if (GST_VIDEO_INFO_WIDTH (vinfo) == surface_width
|
|
|
|
&& GST_VIDEO_INFO_HEIGHT (vinfo) == surface_height)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-04-14 14:22:25 +00:00
|
|
|
/* doing gst_vaapi_surface_get_format() only if necessary since it
|
|
|
|
* execute vaDeriveImage in the background. This will usually get
|
|
|
|
* executed only once */
|
|
|
|
surface_format = GST_VIDEO_INFO_FORMAT (vinfo);
|
|
|
|
if (surface_format == GST_VIDEO_FORMAT_UNKNOWN) {
|
|
|
|
surface_format = gst_vaapi_surface_get_format (surface);
|
|
|
|
|
|
|
|
/* if the VA context delivers a currently unrecognized format
|
2019-06-25 02:31:20 +00:00
|
|
|
* (ICM3, e.g.), we can assume one according surface chroma
|
|
|
|
* type. If fail, then use NV12 "safely" */
|
2016-04-14 14:22:25 +00:00
|
|
|
if (surface_format == GST_VIDEO_FORMAT_UNKNOWN
|
|
|
|
|| surface_format == GST_VIDEO_FORMAT_ENCODED)
|
2019-06-25 02:31:20 +00:00
|
|
|
surface_format =
|
|
|
|
gst_vaapi_video_format_from_chroma (gst_vaapi_surface_get_chroma_type
|
|
|
|
(surface));
|
|
|
|
if (surface_format == GST_VIDEO_FORMAT_UNKNOWN)
|
2016-04-14 14:22:25 +00:00
|
|
|
surface_format = GST_VIDEO_FORMAT_NV12;
|
|
|
|
}
|
2016-03-24 13:09:15 +00:00
|
|
|
|
2020-08-12 15:50:50 +00:00
|
|
|
/* reset allowed source caps since they are dependant of the decoded
|
|
|
|
* surface format */
|
|
|
|
gst_caps_replace (&decode->allowed_srcpad_caps, NULL);
|
|
|
|
|
2016-04-14 14:22:25 +00:00
|
|
|
gst_video_info_set_format (vinfo, surface_format, surface_width,
|
|
|
|
surface_height);
|
2016-01-27 06:56:45 +00:00
|
|
|
|
2016-03-24 13:08:50 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2016-01-27 06:56:45 +00:00
|
|
|
|
2016-03-24 13:08:50 +00:00
|
|
|
/* check whether display resolution changed */
|
|
|
|
static gboolean
|
|
|
|
is_display_resolution_changed (GstVaapiDecode * decode,
|
|
|
|
const GstVaapiRectangle * crop_rect)
|
|
|
|
{
|
|
|
|
GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
|
|
|
|
GstVideoCodecState *state;
|
2016-04-14 14:43:07 +00:00
|
|
|
guint display_width, display_height;
|
2016-04-14 15:02:23 +00:00
|
|
|
guint negotiated_width, negotiated_height;
|
2016-03-24 13:08:50 +00:00
|
|
|
|
2016-04-14 14:43:07 +00:00
|
|
|
display_width = GST_VIDEO_INFO_WIDTH (&decode->decoded_info);
|
|
|
|
display_height = GST_VIDEO_INFO_HEIGHT (&decode->decoded_info);
|
2016-03-24 13:08:50 +00:00
|
|
|
if (crop_rect) {
|
|
|
|
display_width = crop_rect->width;
|
|
|
|
display_height = crop_rect->height;
|
|
|
|
}
|
2016-04-14 14:43:07 +00:00
|
|
|
|
2016-03-24 13:08:50 +00:00
|
|
|
state = gst_video_decoder_get_output_state (vdec);
|
|
|
|
if (G_UNLIKELY (!state))
|
|
|
|
goto set_display_res;
|
|
|
|
|
2016-04-14 15:02:23 +00:00
|
|
|
negotiated_width = GST_VIDEO_INFO_WIDTH (&state->info);
|
|
|
|
negotiated_height = GST_VIDEO_INFO_HEIGHT (&state->info);
|
|
|
|
gst_video_codec_state_unref (state);
|
2016-03-24 13:08:50 +00:00
|
|
|
|
2016-04-14 15:02:23 +00:00
|
|
|
if ((display_width == negotiated_width && display_height == negotiated_height)
|
|
|
|
&& (decode->display_width == negotiated_width
|
|
|
|
&& decode->display_height == negotiated_height))
|
2016-03-24 13:08:50 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
set_display_res:
|
2016-04-14 14:43:07 +00:00
|
|
|
decode->display_width = display_width;
|
|
|
|
decode->display_height = display_height;
|
2016-03-24 13:08:50 +00:00
|
|
|
return TRUE;
|
2016-01-27 06:56:45 +00:00
|
|
|
}
|
|
|
|
|
2016-03-10 16:42:55 +00:00
|
|
|
static gboolean
|
2016-12-09 16:42:42 +00:00
|
|
|
gst_vaapidecode_negotiate (GstVaapiDecode * decode)
|
2016-03-10 16:42:55 +00:00
|
|
|
{
|
2016-12-09 16:42:42 +00:00
|
|
|
GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
|
2016-03-10 16:42:55 +00:00
|
|
|
GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (vdec);
|
|
|
|
|
2016-12-09 16:56:02 +00:00
|
|
|
GST_DEBUG_OBJECT (decode, "input codec state changed: renegotiating");
|
2016-12-09 16:42:42 +00:00
|
|
|
|
2016-12-09 16:56:02 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_LOCK (vdec);
|
2016-03-10 16:42:55 +00:00
|
|
|
if (!gst_vaapidecode_update_src_caps (decode))
|
2020-03-05 12:26:38 +00:00
|
|
|
goto caps_negotiation_failed;
|
2016-03-10 16:42:55 +00:00
|
|
|
if (!gst_vaapi_plugin_base_set_caps (plugin, NULL, decode->srcpad_caps))
|
2020-03-05 12:26:38 +00:00
|
|
|
goto caps_negotiation_failed;
|
2016-12-09 16:56:02 +00:00
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK (vdec);
|
|
|
|
|
2016-12-09 16:42:42 +00:00
|
|
|
if (!gst_video_decoder_negotiate (vdec))
|
2016-11-21 17:42:02 +00:00
|
|
|
return FALSE;
|
2016-03-10 16:42:55 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2020-03-05 12:26:38 +00:00
|
|
|
|
|
|
|
caps_negotiation_failed:
|
|
|
|
{
|
|
|
|
GST_VIDEO_DECODER_STREAM_UNLOCK (vdec);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2016-03-10 16:42:55 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 15:21:21 +00:00
|
|
|
static gboolean
|
|
|
|
is_src_allocator_dmabuf (GstVaapiDecode * decode)
|
|
|
|
{
|
|
|
|
GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (decode);
|
|
|
|
|
|
|
|
if (!GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAN_DMABUF (plugin))
|
|
|
|
return FALSE;
|
2019-10-29 22:13:44 +00:00
|
|
|
return
|
|
|
|
gst_vaapi_is_dmabuf_allocator (GST_VAAPI_PLUGIN_BASE_SRC_PAD_ALLOCATOR
|
|
|
|
(plugin));
|
2016-10-19 15:21:21 +00:00
|
|
|
}
|
|
|
|
|
2013-01-17 17:19:14 +00:00
|
|
|
static GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_push_decoded_frame (GstVideoDecoder * vdec,
|
|
|
|
GstVideoCodecFrame * out_frame)
|
2013-01-17 17:19:14 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
GstVaapiSurfaceProxy *proxy;
|
2016-03-25 14:31:28 +00:00
|
|
|
GstVaapiSurface *surface;
|
2015-03-02 12:59:16 +00:00
|
|
|
GstFlowReturn ret;
|
|
|
|
const GstVaapiRectangle *crop_rect;
|
|
|
|
GstVaapiVideoMeta *meta;
|
2016-10-19 15:21:21 +00:00
|
|
|
GstBufferPoolAcquireParams *params = NULL;
|
|
|
|
GstVaapiVideoBufferPoolAcquireParams vaapi_params = { {0,}, };
|
2015-06-24 11:48:46 +00:00
|
|
|
guint flags, out_flags = 0;
|
2016-03-28 13:30:28 +00:00
|
|
|
gboolean alloc_renegotiate, caps_renegotiate;
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (out_frame)) {
|
|
|
|
proxy = gst_video_codec_frame_get_user_data (out_frame);
|
2016-03-25 14:31:28 +00:00
|
|
|
surface = GST_VAAPI_SURFACE_PROXY_SURFACE (proxy);
|
2016-03-24 13:08:50 +00:00
|
|
|
crop_rect = gst_vaapi_surface_proxy_get_crop_rect (proxy);
|
|
|
|
|
|
|
|
/* in theory, we are not supposed to check the surface resolution
|
|
|
|
* change here since it should be advertised before from ligstvaapi.
|
|
|
|
* But there are issues with it especially for some vp9 streams where
|
|
|
|
* upstream element set un-cropped values in set_format() which make
|
|
|
|
* everything a mess. So better doing the explicit check here irrespective
|
2016-03-24 13:09:43 +00:00
|
|
|
* of what notification we get from upstream or libgstvaapi.Also, even if
|
|
|
|
* we received notification from libgstvaapi, the frame we are going to
|
|
|
|
* be pushed at this point might not have the notified resolution if there
|
|
|
|
* are queued frames in decoded picture buffer. */
|
2016-03-25 14:31:28 +00:00
|
|
|
alloc_renegotiate = is_surface_resolution_changed (decode, surface);
|
2016-03-28 13:30:28 +00:00
|
|
|
caps_renegotiate = is_display_resolution_changed (decode, crop_rect);
|
2016-03-24 13:08:50 +00:00
|
|
|
|
2016-03-28 13:30:28 +00:00
|
|
|
if (gst_pad_needs_reconfigure (GST_VIDEO_DECODER_SRC_PAD (vdec))
|
2017-01-13 20:26:15 +00:00
|
|
|
|| alloc_renegotiate || caps_renegotiate || decode->do_renego) {
|
2016-12-09 16:42:42 +00:00
|
|
|
|
2017-01-13 20:26:15 +00:00
|
|
|
g_atomic_int_set (&decode->do_renego, FALSE);
|
2016-12-09 16:42:42 +00:00
|
|
|
if (!gst_vaapidecode_negotiate (decode))
|
2016-03-24 13:08:27 +00:00
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2016-01-27 06:56:45 +00:00
|
|
|
|
2016-10-19 15:21:21 +00:00
|
|
|
if (is_src_allocator_dmabuf (decode)) {
|
|
|
|
vaapi_params.proxy = gst_vaapi_surface_proxy_ref (proxy);
|
|
|
|
params = (GstBufferPoolAcquireParams *) & vaapi_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = gst_video_decoder_allocate_output_frame_with_params (vdec, out_frame,
|
|
|
|
params);
|
|
|
|
if (params)
|
|
|
|
gst_vaapi_surface_proxy_unref (vaapi_params.proxy);
|
2015-03-02 12:59:16 +00:00
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto error_create_buffer;
|
|
|
|
|
2016-10-19 15:21:21 +00:00
|
|
|
/* if not dmabuf is negotiated set the vaapi video meta in the
|
|
|
|
* proxy */
|
|
|
|
if (!params) {
|
|
|
|
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);
|
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
|
|
|
|
flags = gst_vaapi_surface_proxy_get_flags (proxy);
|
2015-06-24 11:48:46 +00:00
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_CORRUPTED)
|
|
|
|
out_flags |= GST_BUFFER_FLAG_CORRUPTED;
|
2015-03-02 12:59:16 +00:00
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
|
2015-06-24 11:48:46 +00:00
|
|
|
out_flags |= GST_VIDEO_BUFFER_FLAG_INTERLACED;
|
2015-03-02 12:59:16 +00:00
|
|
|
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;
|
|
|
|
}
|
2015-06-24 11:48:46 +00:00
|
|
|
GST_BUFFER_FLAG_SET (out_frame->output_buffer, out_flags);
|
2013-07-15 11:41:00 +00:00
|
|
|
|
2015-06-12 15:39:31 +00:00
|
|
|
if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_FFB) {
|
|
|
|
GST_BUFFER_FLAG_SET (out_frame->output_buffer,
|
|
|
|
GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE);
|
|
|
|
}
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (GST_VAAPI_USE_GLX || GST_VAAPI_USE_EGL)
|
2015-03-02 12:59:16 +00:00
|
|
|
if (decode->has_texture_upload_meta)
|
|
|
|
gst_buffer_ensure_texture_upload_meta (out_frame->output_buffer);
|
2012-11-08 14:41:22 +00:00
|
|
|
#endif
|
2018-02-17 17:32:11 +00:00
|
|
|
|
|
|
|
/* Generate a system allocated output buffer if downstream doesn't
|
|
|
|
* support GstVideoMeta */
|
|
|
|
if (GST_VAAPI_PLUGIN_BASE_COPY_OUTPUT_FRAME (vdec)) {
|
|
|
|
GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (vdec);
|
|
|
|
GstBuffer *sys_buf, *va_buf;
|
|
|
|
|
|
|
|
va_buf = out_frame->output_buffer;
|
2019-10-29 22:13:44 +00:00
|
|
|
sys_buf =
|
|
|
|
gst_buffer_new_allocate (GST_VAAPI_PLUGIN_BASE_OTHER_ALLOCATOR
|
|
|
|
(plugin),
|
|
|
|
GST_VIDEO_INFO_SIZE (GST_VAAPI_PLUGIN_BASE_SRC_PAD_INFO (plugin)),
|
|
|
|
&GST_VAAPI_PLUGIN_BASE_OTHER_ALLOCATOR_PARAMS (plugin));
|
2018-02-17 17:32:11 +00:00
|
|
|
if (!sys_buf)
|
|
|
|
goto error_no_sys_buffer;
|
|
|
|
|
|
|
|
if (!gst_vaapi_plugin_copy_va_buffer (plugin, va_buf, sys_buf)) {
|
|
|
|
gst_buffer_unref (sys_buf);
|
|
|
|
goto error_cannot_copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
gst_buffer_replace (&out_frame->output_buffer, sys_buf);
|
|
|
|
gst_buffer_unref (sys_buf);
|
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
2010-04-30 15:50:19 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
ret = gst_video_decoder_finish_frame (vdec, out_frame);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
goto error_commit_buffer;
|
|
|
|
return GST_FLOW_OK;
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
/* ERRORS */
|
2010-04-29 17:55:58 +00:00
|
|
|
error_create_buffer:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
|
|
|
const GstVaapiID surface_id =
|
|
|
|
gst_vaapi_surface_get_id (GST_VAAPI_SURFACE_PROXY_SURFACE (proxy));
|
|
|
|
|
|
|
|
GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
|
|
|
|
("Failed to create sink buffer"),
|
|
|
|
("video sink failed to create video buffer for proxy'ed "
|
|
|
|
"surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)));
|
|
|
|
gst_video_decoder_drop_frame (vdec, out_frame);
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2012-11-08 14:41:22 +00:00
|
|
|
error_get_meta:
|
2015-03-02 12:59:16 +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"));
|
|
|
|
gst_video_decoder_drop_frame (vdec, out_frame);
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2018-02-17 17:32:11 +00:00
|
|
|
error_no_sys_buffer:
|
|
|
|
{
|
|
|
|
GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
|
|
|
|
("Failed to create system allocated buffer"),
|
|
|
|
("Failed to create system allocated buffer"));
|
|
|
|
gst_video_decoder_drop_frame (vdec, out_frame);
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
|
|
|
error_cannot_copy:
|
|
|
|
{
|
|
|
|
GST_ELEMENT_ERROR (vdec, STREAM, FAILED,
|
|
|
|
("Failed to copy system allocated buffer"),
|
|
|
|
("Failed to copy system allocated buffer"));
|
|
|
|
gst_video_decoder_drop_frame (vdec, out_frame);
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2010-04-29 17:55:58 +00:00
|
|
|
error_commit_buffer:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
2019-05-31 11:12:35 +00:00
|
|
|
GST_LOG_OBJECT (decode, "downstream element rejected the frame (%s [%d])",
|
2015-04-19 09:19:03 +00:00
|
|
|
gst_flow_get_name (ret), ret);
|
2015-03-02 12:59:16 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 12:46:38 +00:00
|
|
|
static GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_push_all_decoded_frames (GstVaapiDecode * decode)
|
2015-03-02 12:46:38 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
|
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
GstVideoCodecFrame *out_frame;
|
|
|
|
GstFlowReturn ret;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
status = gst_vaapi_decoder_get_frame (decode->decoder, &out_frame);
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
2016-07-10 17:33:14 +00:00
|
|
|
/* GstVaapiDecode's queue adds an extra reference */
|
|
|
|
gst_video_codec_frame_unref (out_frame);
|
2015-03-02 12:59:16 +00:00
|
|
|
ret = gst_vaapidecode_push_decoded_frame (vdec, out_frame);
|
|
|
|
if (ret != GST_FLOW_OK)
|
|
|
|
return ret;
|
|
|
|
break;
|
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
default:
|
2015-04-17 00:18:13 +00:00
|
|
|
GST_VIDEO_DECODER_ERROR (vdec, 1, STREAM, DECODE, ("Decoding failed"),
|
|
|
|
("Unknown decoding error"), ret);
|
|
|
|
return ret;
|
2015-03-02 12:46:38 +00:00
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
|
|
|
g_assert_not_reached ();
|
2015-03-02 12:46:38 +00:00
|
|
|
}
|
|
|
|
|
2013-01-17 17:19:14 +00:00
|
|
|
static GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_handle_frame (GstVideoDecoder * vdec,
|
|
|
|
GstVideoCodecFrame * frame)
|
2013-01-17 17:19:14 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
|
|
|
|
if (!decode->input_state)
|
|
|
|
goto not_negotiated;
|
|
|
|
|
|
|
|
/* Decode current frame */
|
|
|
|
for (;;) {
|
|
|
|
status = gst_vaapi_decoder_decode (decode->decoder, frame);
|
|
|
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
|
|
goto error_decode;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note that gst_vaapi_decoder_decode cannot return success without
|
|
|
|
completing the decode and pushing all decoded frames into the output
|
|
|
|
queue */
|
2015-04-19 09:19:03 +00:00
|
|
|
return gst_vaapidecode_push_all_decoded_frames (decode);
|
2015-03-02 12:59:16 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
2015-03-02 12:46:38 +00:00
|
|
|
error_decode:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
2019-05-31 11:12:35 +00:00
|
|
|
GstFlowReturn ret = GST_FLOW_OK;
|
|
|
|
|
|
|
|
GST_WARNING_OBJECT (decode, "decode error %d", status);
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
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-04-17 00:18:13 +00:00
|
|
|
GST_VIDEO_DECODER_ERROR (vdec, 1, STREAM, DECODE, ("Decoding error"),
|
|
|
|
("Decode error %d", status), ret);
|
2019-05-31 11:12:35 +00:00
|
|
|
GST_INFO_OBJECT (decode, "requesting upstream a key unit");
|
2018-09-01 01:56:13 +00:00
|
|
|
gst_pad_push_event (GST_VIDEO_DECODER_SINK_PAD (decode),
|
|
|
|
gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE,
|
2018-11-28 03:56:44 +00:00
|
|
|
FALSE, 0));
|
2015-03-02 12:59:16 +00:00
|
|
|
break;
|
2015-03-02 12:46:38 +00:00
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_video_decoder_drop_frame (vdec, frame);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-03-02 12:46:38 +00:00
|
|
|
not_negotiated:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
|
|
|
GST_ERROR_OBJECT (decode, "not negotiated");
|
|
|
|
gst_video_decoder_drop_frame (vdec, frame);
|
2019-05-31 11:12:35 +00:00
|
|
|
return GST_FLOW_NOT_NEGOTIATED;
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
2013-01-17 17:19:14 +00:00
|
|
|
}
|
|
|
|
|
2016-07-10 16:18:57 +00:00
|
|
|
/* If there is something in GstVideoDecoder's output adapter, then
|
|
|
|
submit the frame for decoding */
|
|
|
|
static inline void
|
|
|
|
gst_vaapidecode_flush_output_adapter (GstVaapiDecode * decode)
|
|
|
|
{
|
|
|
|
if (decode->current_frame_size == 0)
|
|
|
|
return;
|
|
|
|
gst_video_decoder_have_frame (GST_VIDEO_DECODER (decode));
|
|
|
|
decode->current_frame_size = 0;
|
|
|
|
}
|
|
|
|
|
2015-03-16 21:38:18 +00:00
|
|
|
static GstFlowReturn
|
|
|
|
gst_vaapidecode_drain (GstVideoDecoder * vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
|
|
|
|
if (!decode->decoder)
|
|
|
|
return GST_FLOW_NOT_NEGOTIATED;
|
|
|
|
|
2016-07-10 16:18:57 +00:00
|
|
|
GST_LOG_OBJECT (decode, "drain");
|
|
|
|
|
|
|
|
gst_vaapidecode_flush_output_adapter (decode);
|
2015-03-16 21:38:18 +00:00
|
|
|
return gst_vaapidecode_push_all_decoded_frames (decode);
|
|
|
|
}
|
|
|
|
|
2013-11-21 10:01:41 +00:00
|
|
|
static GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_finish (GstVideoDecoder * vdec)
|
2013-11-21 10:01:41 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
2016-07-10 17:01:17 +00:00
|
|
|
GstVaapiDecoderStatus status;
|
2015-04-21 08:00:36 +00:00
|
|
|
GstFlowReturn ret;
|
2013-11-21 10:01:41 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!decode->decoder)
|
|
|
|
return GST_FLOW_OK;
|
2014-08-11 14:14:53 +00:00
|
|
|
|
2016-07-10 17:01:17 +00:00
|
|
|
gst_vaapidecode_flush_output_adapter (decode);
|
|
|
|
status = gst_vaapi_decoder_flush (decode->decoder);
|
2015-04-21 08:00:36 +00:00
|
|
|
ret = gst_vaapidecode_push_all_decoded_frames (decode);
|
2016-07-10 17:01:17 +00:00
|
|
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
|
|
|
goto error_decoder_flush;
|
2015-04-21 08:00:36 +00:00
|
|
|
return ret;
|
2016-07-10 17:01:17 +00:00
|
|
|
|
|
|
|
/* ERRORS: */
|
|
|
|
error_decoder_flush:
|
|
|
|
{
|
|
|
|
GST_WARNING_OBJECT (decode, "failed to flush decoder (status %d)", status);
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2013-01-17 17:22:49 +00:00
|
|
|
}
|
|
|
|
|
2012-11-08 14:41:22 +00:00
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_decide_allocation (GstVideoDecoder * vdec, GstQuery * query)
|
2012-11-08 14:41:22 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
GstCaps *caps = NULL;
|
|
|
|
|
|
|
|
gst_query_parse_allocation (query, &caps, NULL);
|
2016-03-10 15:42:04 +00:00
|
|
|
if (!caps)
|
|
|
|
goto error_no_caps;
|
|
|
|
|
2016-05-23 20:21:15 +00:00
|
|
|
decode->has_texture_upload_meta = FALSE;
|
|
|
|
|
2022-12-10 13:11:08 +00:00
|
|
|
#if (GST_VAAPI_USE_GLX || GST_VAAPI_USE_EGL)
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->has_texture_upload_meta =
|
|
|
|
gst_query_find_allocation_meta (query,
|
2015-11-13 16:51:27 +00:00
|
|
|
GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL) &&
|
2015-10-14 18:30:30 +00:00
|
|
|
gst_vaapi_caps_feature_contains (caps,
|
2015-11-13 16:51:27 +00:00
|
|
|
GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META);
|
2014-07-28 16:00:19 +00:00
|
|
|
#endif
|
2014-06-13 20:45:04 +00:00
|
|
|
|
2016-04-14 13:46:32 +00:00
|
|
|
return gst_vaapi_plugin_base_decide_allocation (GST_VAAPI_PLUGIN_BASE (vdec),
|
2016-03-10 15:43:16 +00:00
|
|
|
query);
|
2016-03-10 15:42:04 +00:00
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
error_no_caps:
|
|
|
|
{
|
|
|
|
GST_ERROR_OBJECT (decode, "no caps specified");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-11-08 14:41:22 +00:00
|
|
|
}
|
|
|
|
|
2012-07-25 08:02:29 +00:00
|
|
|
static inline gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_ensure_display (GstVaapiDecode * decode)
|
2012-07-25 08:02:29 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
return gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (decode));
|
2012-07-25 08:02:29 +00:00
|
|
|
}
|
|
|
|
|
2010-05-05 15:36:25 +00:00
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_create (GstVaapiDecode * decode, GstCaps * caps)
|
2010-05-05 15:36:25 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDisplay *dpy;
|
2011-08-12 08:21:19 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!gst_vaapidecode_ensure_display (decode))
|
|
|
|
return FALSE;
|
|
|
|
dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2020-07-29 06:22:18 +00:00
|
|
|
switch (gst_vaapi_get_codec_from_caps (caps)) {
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_MPEG2:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_mpeg2_new (dpy, caps);
|
|
|
|
break;
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_MPEG4:
|
|
|
|
case GST_VAAPI_CODEC_H263:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_mpeg4_new (dpy, caps);
|
|
|
|
break;
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_H264:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_h264_new (dpy, caps);
|
|
|
|
|
|
|
|
/* Set the stream buffer alignment for better optimizations */
|
|
|
|
if (decode->decoder && caps) {
|
2017-07-06 18:00:15 +00:00
|
|
|
GstVaapiDecodeH264Private *priv =
|
|
|
|
gst_vaapi_decode_h264_get_instance_private (decode);
|
2015-03-02 12:59:16 +00:00
|
|
|
GstStructure *const structure = gst_caps_get_structure (caps, 0);
|
|
|
|
const gchar *str = NULL;
|
|
|
|
|
2019-08-18 11:53:53 +00:00
|
|
|
if (!structure)
|
|
|
|
break;
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
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;
|
2015-03-06 12:31:21 +00:00
|
|
|
gst_vaapi_decoder_h264_set_alignment (GST_VAAPI_DECODER_H264
|
|
|
|
(decode->decoder), alignment);
|
2014-02-06 06:30:10 +00:00
|
|
|
}
|
2017-07-06 18:00:15 +00:00
|
|
|
|
|
|
|
if (priv) {
|
|
|
|
gst_vaapi_decoder_h264_set_low_latency (GST_VAAPI_DECODER_H264
|
|
|
|
(decode->decoder), priv->is_low_latency);
|
2017-07-25 19:06:56 +00:00
|
|
|
gst_vaapi_decoder_h264_set_base_only (GST_VAAPI_DECODER_H264
|
|
|
|
(decode->decoder), priv->base_only);
|
2017-07-06 18:00:15 +00:00
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2015-04-13 12:43:30 +00:00
|
|
|
case GST_VAAPI_CODEC_H265:
|
|
|
|
decode->decoder = gst_vaapi_decoder_h265_new (dpy, caps);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2019-08-18 11:53:53 +00:00
|
|
|
if (!structure)
|
|
|
|
break;
|
|
|
|
|
2015-04-13 12:43:30 +00:00
|
|
|
if ((str = gst_structure_get_string (structure, "alignment"))) {
|
|
|
|
GstVaapiStreamAlignH265 alignment;
|
|
|
|
if (g_strcmp0 (str, "au") == 0)
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H265_AU;
|
|
|
|
else if (g_strcmp0 (str, "nal") == 0)
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H265_NALU;
|
|
|
|
else
|
|
|
|
alignment = GST_VAAPI_STREAM_ALIGN_H265_NONE;
|
|
|
|
gst_vaapi_decoder_h265_set_alignment (GST_VAAPI_DECODER_H265
|
|
|
|
(decode->decoder), alignment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_WMV3:
|
|
|
|
case GST_VAAPI_CODEC_VC1:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_vc1_new (dpy, caps);
|
|
|
|
break;
|
2012-09-11 14:41:32 +00:00
|
|
|
case GST_VAAPI_CODEC_JPEG:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_jpeg_new (dpy, caps);
|
|
|
|
break;
|
2013-12-26 23:18:24 +00:00
|
|
|
case GST_VAAPI_CODEC_VP8:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = gst_vaapi_decoder_vp8_new (dpy, caps);
|
|
|
|
break;
|
2015-11-06 13:19:38 +00:00
|
|
|
case GST_VAAPI_CODEC_VP9:
|
|
|
|
decode->decoder = gst_vaapi_decoder_vp9_new (dpy, caps);
|
|
|
|
break;
|
2022-12-10 13:11:08 +00:00
|
|
|
#if GST_VAAPI_USE_AV1_DECODER
|
2020-08-27 13:46:41 +00:00
|
|
|
case GST_VAAPI_CODEC_AV1:
|
|
|
|
decode->decoder = gst_vaapi_decoder_av1_new (dpy, caps);
|
|
|
|
break;
|
|
|
|
#endif
|
2012-09-11 14:41:32 +00:00
|
|
|
default:
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->decoder = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!decode->decoder)
|
|
|
|
return FALSE;
|
2010-05-12 08:32:34 +00:00
|
|
|
|
2015-03-02 12:59:16 +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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
return TRUE;
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-04-20 11:27:27 +00:00
|
|
|
gst_vaapidecode_purge (GstVaapiDecode * decode)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2015-04-20 11:27:27 +00:00
|
|
|
GstVaapiDecoderStatus status;
|
2015-04-16 16:53:18 +00:00
|
|
|
|
2015-04-20 11:27:27 +00:00
|
|
|
if (!decode->decoder)
|
|
|
|
return;
|
2015-04-16 16:53:18 +00:00
|
|
|
|
2015-04-20 11:27:27 +00:00
|
|
|
status = gst_vaapi_decoder_flush (decode->decoder);
|
|
|
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
2015-04-21 08:00:36 +00:00
|
|
|
GST_INFO_OBJECT (decode, "failed to flush decoder (status %d)", status);
|
2015-04-20 11:27:27 +00:00
|
|
|
|
|
|
|
/* Purge all decoded frames as we don't need them (e.g. flush and close)
|
|
|
|
* Releasing the frames is important, otherwise the frames are not
|
|
|
|
* freed. */
|
|
|
|
do {
|
|
|
|
GstVideoCodecFrame *frame = NULL;
|
|
|
|
|
|
|
|
status =
|
2015-06-01 16:39:18 +00:00
|
|
|
gst_vaapi_decoder_get_frame_with_timeout (decode->decoder, &frame, 0);
|
2015-04-20 11:27:27 +00:00
|
|
|
if (frame) {
|
|
|
|
gst_video_decoder_release_frame (GST_VIDEO_DECODER (decode), frame);
|
|
|
|
gst_video_codec_frame_unref (frame);
|
2015-04-16 16:53:18 +00:00
|
|
|
}
|
2015-04-20 11:27:27 +00:00
|
|
|
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_vaapidecode_destroy (GstVaapiDecode * decode)
|
|
|
|
{
|
|
|
|
gst_vaapidecode_purge (decode);
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_decoder_replace (&decode->decoder, NULL);
|
vaapidecode: build allowed srcpad caps from va context
Instead of generating allowed srcpad caps with generic information,
now it takes the size an formats limits from the decoder's context.
This is possible since srcpad caps are generated after the internal
decoder is created.
The patch replaces gst_vaapi_decoder_get_surface_formats() with
gst_vaapi_decoder_get_suface_attributes().
From these attributes, formats are only used for VASurface memory
caps feature. For system memory caps feature, the old
gst_vaapi_plugin_get_allowed_srcpad_caps() is still used, since
i965 jpeg decoder cannot deliver mappable format for gstreamer.
And for the other caps features (dmabuf and texture upload) the
same static list are used.
This patch also adds DMABuf caps feature only if the context
supports that memory type. Nonetheless, we keep the pre-defined
formats since they are the subset of common derive formats formats
supported either by amd/gallium and both intel drivers, since,
when exporting the fd through vaAcquireBufferHandle()/
vaReleaseBufferHandle(), the formats of the derivable image cannot
be retriebable from the driver. Later we'll use the attribute
formats for the DMABuf feature too, when the code be ported to
vaExportSurfaceHandle().
Finally, the allowed srcpad caps are removed if the internal decoder
is destroyed, since context attribues will change.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/366>
2020-01-22 16:41:28 +00:00
|
|
|
/* srcpad caps are decoder's context dependant */
|
|
|
|
gst_caps_replace (&decode->allowed_srcpad_caps, NULL);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2010-05-12 08:32:34 +00:00
|
|
|
static gboolean
|
2017-04-05 07:24:20 +00:00
|
|
|
gst_vaapidecode_reset (GstVaapiDecode * decode, GstCaps * caps,
|
|
|
|
gboolean force_reset)
|
2010-05-12 08:32:34 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
/* Reset tracked frame size */
|
|
|
|
decode->current_frame_size = 0;
|
2013-11-21 10:01:41 +00:00
|
|
|
|
2017-04-05 07:24:20 +00:00
|
|
|
if (decode->decoder) {
|
2017-04-07 16:05:21 +00:00
|
|
|
if (!gst_caps_is_equal (caps, gst_vaapi_decoder_get_caps (decode->decoder))) {
|
|
|
|
if (gst_vaapi_decoder_update_caps (decode->decoder, caps)) {
|
|
|
|
g_atomic_int_set (&decode->do_renego, TRUE);
|
|
|
|
if (!force_reset)
|
|
|
|
return TRUE;
|
|
|
|
}
|
2017-01-13 20:26:15 +00:00
|
|
|
}
|
2017-08-15 08:36:51 +00:00
|
|
|
return (gst_vaapi_decoder_reset (decode->decoder) ==
|
|
|
|
GST_VAAPI_DECODER_STATUS_SUCCESS);
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
2010-05-12 08:32:34 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
return gst_vaapidecode_create (decode, caps);
|
2010-05-12 08:32:34 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
static void
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_finalize (GObject * object)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_plugin_base_finalize (GST_VAAPI_PLUGIN_BASE (object));
|
2016-03-09 17:41:49 +00:00
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_open (GstVideoDecoder * vdec)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
|
|
|
|
if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (decode)))
|
|
|
|
return FALSE;
|
|
|
|
|
2016-04-14 14:43:07 +00:00
|
|
|
decode->display_width = 0;
|
|
|
|
decode->display_height = 0;
|
2016-04-14 14:10:02 +00:00
|
|
|
gst_video_info_init (&decode->decoded_info);
|
|
|
|
|
2016-07-12 15:54:26 +00:00
|
|
|
return TRUE;
|
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
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_close (GstVideoDecoder * vdec)
|
2012-12-04 13:45:29 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_destroy (decode);
|
2016-07-19 14:40:10 +00:00
|
|
|
gst_caps_replace (&decode->allowed_srcpad_caps, NULL);
|
2016-10-27 16:22:18 +00:00
|
|
|
gst_caps_replace (&decode->allowed_sinkpad_caps, NULL);
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_plugin_base_close (GST_VAAPI_PLUGIN_BASE (decode));
|
|
|
|
return TRUE;
|
2012-12-04 13:45:29 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 15:54:26 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_start (GstVideoDecoder * vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
GST_VAAPI_PLUGIN_BASE_DISPLAY (decode) = NULL;
|
|
|
|
success =
|
|
|
|
gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (decode));
|
|
|
|
if (old_display)
|
2018-06-13 15:54:23 +00:00
|
|
|
gst_object_unref (old_display);
|
2016-07-12 15:54:26 +00:00
|
|
|
|
2018-07-24 16:40:00 +00:00
|
|
|
/* Disable errors on decode errors */
|
|
|
|
gst_video_decoder_set_max_errors (vdec, -1);
|
|
|
|
|
2016-07-12 15:54:26 +00:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2016-03-18 23:00:52 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_stop (GstVideoDecoder * vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
|
|
|
|
gst_vaapidecode_purge (decode);
|
|
|
|
gst_vaapi_decode_input_state_replace (decode, NULL);
|
|
|
|
gst_vaapi_decoder_replace (&decode->decoder, NULL);
|
|
|
|
gst_caps_replace (&decode->sinkpad_caps, NULL);
|
|
|
|
gst_caps_replace (&decode->srcpad_caps, NULL);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2015-03-16 21:36:33 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_flush (GstVideoDecoder * vdec)
|
|
|
|
{
|
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
2016-07-10 11:46:25 +00:00
|
|
|
if (!decode->decoder)
|
2015-03-16 21:36:33 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2016-07-10 11:46:25 +00:00
|
|
|
GST_LOG_OBJECT (vdec, "flushing");
|
|
|
|
|
|
|
|
gst_vaapidecode_purge (decode);
|
|
|
|
|
2017-04-05 07:24:20 +00:00
|
|
|
/* There could be issues if we avoid the reset() while doing
|
2015-03-16 21:36:33 +00:00
|
|
|
* seeking: we have to reset the internal state */
|
2017-04-05 07:24:20 +00:00
|
|
|
return gst_vaapidecode_reset (decode, decode->sinkpad_caps, TRUE);
|
2015-03-16 21:36:33 +00:00
|
|
|
}
|
2013-01-23 22:49:17 +00:00
|
|
|
|
2012-12-04 13:45:29 +00:00
|
|
|
static gboolean
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_set_format (GstVideoDecoder * vdec, GstVideoCodecState * state)
|
2012-12-04 13:45:29 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (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
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!gst_vaapi_decode_input_state_replace (decode, state))
|
2012-12-04 13:45:29 +00:00
|
|
|
return TRUE;
|
2017-09-25 13:50:19 +00:00
|
|
|
if (gst_vaapidecode_drain (vdec) == GST_FLOW_ERROR)
|
|
|
|
return FALSE;
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!gst_vaapidecode_update_sink_caps (decode, state->caps))
|
|
|
|
return FALSE;
|
|
|
|
if (!gst_vaapi_plugin_base_set_caps (plugin, decode->sinkpad_caps, NULL))
|
|
|
|
return FALSE;
|
2017-04-05 07:24:20 +00:00
|
|
|
if (!gst_vaapidecode_reset (decode, decode->sinkpad_caps, FALSE))
|
2015-03-02 12:59:16 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
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 GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_parse_frame (GstVideoDecoder * vdec,
|
|
|
|
GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
|
2012-12-04 13:45:29 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
|
|
|
GstVaapiDecoderStatus status;
|
|
|
|
GstFlowReturn ret;
|
|
|
|
guint got_unit_size;
|
|
|
|
gboolean got_frame;
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
status = gst_vaapi_decoder_parse (decode->decoder, frame,
|
|
|
|
adapter, at_eos, &got_unit_size, &got_frame);
|
2012-12-04 13:45:29 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
switch (status) {
|
2012-12-04 13:45:29 +00:00
|
|
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
2015-03-02 12:59:16 +00:00
|
|
|
if (got_unit_size > 0) {
|
|
|
|
gst_video_decoder_add_to_frame (vdec, got_unit_size);
|
|
|
|
decode->current_frame_size += got_unit_size;
|
|
|
|
}
|
|
|
|
if (got_frame) {
|
|
|
|
ret = gst_video_decoder_have_frame (vdec);
|
|
|
|
decode->current_frame_size = 0;
|
|
|
|
} else
|
|
|
|
ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA;
|
|
|
|
break;
|
2012-12-04 13:45:29 +00:00
|
|
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
2015-03-02 12:59:16 +00:00
|
|
|
ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
|
|
|
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:
|
2015-03-02 12:59:16 +00:00
|
|
|
GST_WARNING ("parse error %d", status);
|
|
|
|
ret = GST_FLOW_NOT_SUPPORTED;
|
|
|
|
decode->current_frame_size = 0;
|
|
|
|
break;
|
2010-04-29 17:55:58 +00:00
|
|
|
default:
|
2018-09-01 01:56:13 +00:00
|
|
|
GST_WARNING ("parse error %d", status);
|
2018-07-25 17:50:23 +00:00
|
|
|
/* just keep parsing, the decoder should have flushed the broken unit */
|
|
|
|
ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA;
|
2015-03-02 12:59:16 +00:00
|
|
|
decode->current_frame_size = 0;
|
2018-09-01 01:56:13 +00:00
|
|
|
|
|
|
|
GST_INFO ("requesting upstream a key unit");
|
|
|
|
gst_pad_push_event (GST_VIDEO_DECODER_SINK_PAD (decode),
|
|
|
|
gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE,
|
|
|
|
FALSE, 0));
|
2015-03-02 12:59:16 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
|
|
|
|
2014-06-18 11:47:36 +00:00
|
|
|
static GstFlowReturn
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_parse (GstVideoDecoder * vdec,
|
|
|
|
GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
|
2014-06-18 11:47:36 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstFlowReturn ret;
|
2014-06-18 11:47:36 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
do {
|
|
|
|
ret = gst_vaapidecode_parse_frame (vdec, frame, adapter, at_eos);
|
|
|
|
} while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA);
|
|
|
|
return ret;
|
2014-06-18 11:47:36 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 19:25:10 +00:00
|
|
|
static gboolean
|
|
|
|
is_mvc_profile (GstVaapiProfile profile)
|
|
|
|
{
|
|
|
|
return profile == GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH;
|
|
|
|
}
|
|
|
|
|
2017-08-29 00:34:50 +00:00
|
|
|
static gboolean
|
|
|
|
is_svc_profile (GstVaapiProfile profile)
|
|
|
|
{
|
|
|
|
return profile == GST_VAAPI_PROFILE_H264_SCALABLE_BASELINE
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H264_SCALABLE_HIGH;
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
static void
|
|
|
|
find_mvc_and_svc (GArray * profiles, gboolean * have_mvc, gboolean * have_svc)
|
2017-07-25 19:25:10 +00:00
|
|
|
{
|
2020-07-21 18:14:57 +00:00
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < profiles->len; i++) {
|
|
|
|
const GstVaapiProfile profile =
|
|
|
|
g_array_index (profiles, GstVaapiProfile, i);
|
|
|
|
|
|
|
|
*have_mvc |= is_mvc_profile (profile);
|
|
|
|
*have_svc |= is_svc_profile (profile);
|
|
|
|
}
|
2017-07-25 19:25:10 +00:00
|
|
|
}
|
|
|
|
|
2010-05-12 09:22:49 +00:00
|
|
|
static gboolean
|
2016-07-19 15:00:23 +00:00
|
|
|
gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode)
|
2010-05-12 09:22:49 +00:00
|
|
|
{
|
2016-07-19 15:00:23 +00:00
|
|
|
GstCaps *caps, *allowed_sinkpad_caps;
|
plugin: decode: correct ensure_allowed_sinkpad_caps's caps.
The decode allowed caps returned by ensure_allowed_sinkpad_caps()
contains all profiles of the whole VAAPI, like:
image/jpeg, width=(int)[ 0, 1638 4 ], height=(int)[ 0, 16384 ];
video/mpeg, mpegversion=(int)2, profile=(string){ simple, main },
width=(int)[ 0, 2048 ], height=(int)[ 0, 2048 ]; video/x-h264,
profile=(string){ main, high, constrained-baseline }, width=(int)[ 0,
4096 ], height=(int)[ 0, 4096 ]; video/x-h264, profile=(string){
constrained-high, progressive-high, baseline }; video/x-h265,
profile=(string){ main, main-intra }, width=(int)[ 0, 8192 ],
height=(int)[ 0, 8192 ]; video/x-vp8, width=(int)[ 0, 4096 ],
height=(int)[ 0, 4096 ]; video/x-wmv, wmvversion=(int)3,
format=(string)WVC1, profile=(string)advanced, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]; video/x-wmv, wmvversion=(int)3,
profile=(string){ simple, main }, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]
Which is verbose and may have latent problems. It should only contains
the profiles belong to its codec type. For example, h265 should only
return:
video/x-h265, profile=(string){ main, main-intra },
width=(int)[ 0, 8192 ], height=(int)[ 0, 8192 ]
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/361>
2020-07-16 16:45:53 +00:00
|
|
|
GstPad *const sinkpad = GST_VIDEO_DECODER_SINK_PAD (decode);
|
2015-03-02 12:59:16 +00:00
|
|
|
GArray *profiles;
|
2019-08-05 17:47:30 +00:00
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);
|
2015-03-02 12:59:16 +00:00
|
|
|
guint i;
|
2017-08-08 15:34:12 +00:00
|
|
|
gboolean base_only = FALSE;
|
2017-07-25 19:25:10 +00:00
|
|
|
gboolean have_mvc = FALSE;
|
2017-08-29 00:34:50 +00:00
|
|
|
gboolean have_svc = FALSE;
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2019-08-05 17:47:30 +00:00
|
|
|
profiles = gst_vaapi_display_get_decode_profiles (display);
|
2015-03-02 12:59:16 +00:00
|
|
|
if (!profiles)
|
|
|
|
goto error_no_profiles;
|
|
|
|
|
2016-07-19 15:00:23 +00:00
|
|
|
allowed_sinkpad_caps = gst_caps_new_empty ();
|
|
|
|
if (!allowed_sinkpad_caps)
|
2015-03-02 12:59:16 +00:00
|
|
|
goto error_no_memory;
|
|
|
|
|
2017-07-25 19:25:10 +00:00
|
|
|
if (g_object_class_find_property (G_OBJECT_GET_CLASS (decode), "base-only")) {
|
|
|
|
g_object_get (decode, "base-only", &base_only, NULL);
|
|
|
|
}
|
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
find_mvc_and_svc (profiles, &have_mvc, &have_svc);
|
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
for (i = 0; i < profiles->len; i++) {
|
|
|
|
const GstVaapiProfile profile =
|
|
|
|
g_array_index (profiles, GstVaapiProfile, i);
|
|
|
|
const gchar *media_type_name;
|
|
|
|
const gchar *profile_name;
|
|
|
|
GstStructure *structure;
|
|
|
|
|
|
|
|
media_type_name = gst_vaapi_profile_get_media_type_name (profile);
|
|
|
|
if (!media_type_name)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
caps = gst_caps_from_string (media_type_name);
|
|
|
|
if (!caps)
|
|
|
|
continue;
|
|
|
|
structure = gst_caps_get_structure (caps, 0);
|
2019-08-18 11:53:53 +00:00
|
|
|
if (!structure)
|
|
|
|
continue;
|
2015-03-02 12:59:16 +00:00
|
|
|
|
|
|
|
profile_name = gst_vaapi_profile_get_name (profile);
|
2020-07-21 18:14:57 +00:00
|
|
|
if (!profile_name)
|
2020-07-28 18:00:09 +00:00
|
|
|
goto merge_caps;
|
2015-03-02 12:59:16 +00:00
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
/* Add all according -intra profile for HEVC */
|
|
|
|
if (profile == GST_VAAPI_PROFILE_H265_MAIN
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN10
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN_422_10
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN_444
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN_444_10
|
2020-07-30 15:21:06 +00:00
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN12
|
2020-07-17 10:00:30 +00:00
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN_444_12
|
|
|
|
|| profile == GST_VAAPI_PROFILE_H265_MAIN_422_12) {
|
2020-07-21 18:14:57 +00:00
|
|
|
gchar *profiles[3], *intra_name;
|
|
|
|
|
|
|
|
intra_name = g_strdup_printf ("%s-intra", profile_name);
|
|
|
|
|
|
|
|
profiles[0] = (gchar *) profile_name;
|
|
|
|
profiles[1] = intra_name;
|
|
|
|
profiles[2] = NULL;
|
|
|
|
|
|
|
|
gst_vaapi_structure_set_profiles (structure, profiles);
|
|
|
|
g_free (intra_name);
|
|
|
|
|
|
|
|
} else if (profile == GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE) {
|
|
|
|
/* XXX: artificially adding baseline if constrained_baseline is
|
|
|
|
* available. */
|
|
|
|
gchar *profiles[] = { (gchar *) profile_name, "baseline", NULL };
|
|
|
|
|
|
|
|
gst_vaapi_structure_set_profiles (structure, profiles);
|
|
|
|
} else if (profile == GST_VAAPI_PROFILE_H264_HIGH) {
|
|
|
|
gchar *profiles[11] = { (gchar *) profile_name, "progressive-high",
|
|
|
|
"constrained-high"
|
|
|
|
};
|
|
|
|
gint i = 3;
|
|
|
|
|
|
|
|
if (base_only && !have_mvc) {
|
|
|
|
GST_DEBUG ("base_only: force adding MVC profiles in caps");
|
|
|
|
|
|
|
|
profiles[i++] = "multiview-high";
|
|
|
|
profiles[i++] = "stereo-high";
|
|
|
|
}
|
2019-08-05 17:47:30 +00:00
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
if (base_only && !have_svc) {
|
|
|
|
GST_DEBUG ("base_only: force adding SVC profiles in caps");
|
2017-07-25 19:25:10 +00:00
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
profiles[i++] = "scalable-constrained-baseline";
|
|
|
|
profiles[i++] = "scalable-baseline";
|
|
|
|
profiles[i++] = "scalable-high-intra";
|
|
|
|
profiles[i++] = "scalable-constrained-high";
|
|
|
|
profiles[i++] = "scalable-high";
|
|
|
|
}
|
2018-04-28 08:10:46 +00:00
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
profiles[i++] = NULL;
|
2017-08-29 00:34:50 +00:00
|
|
|
|
2020-07-21 18:14:57 +00:00
|
|
|
gst_vaapi_structure_set_profiles (structure, profiles);
|
|
|
|
} else {
|
|
|
|
gst_structure_set (structure, "profile", G_TYPE_STRING,
|
|
|
|
profile_name, NULL);
|
2017-08-29 00:34:50 +00:00
|
|
|
}
|
2017-07-25 19:25:10 +00:00
|
|
|
|
2020-07-28 18:00:09 +00:00
|
|
|
merge_caps:
|
2020-07-21 18:14:57 +00:00
|
|
|
gst_vaapi_profile_caps_append_decoder (display, profile, structure);
|
|
|
|
allowed_sinkpad_caps = gst_caps_merge (allowed_sinkpad_caps, caps);
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
plugin: decode: correct ensure_allowed_sinkpad_caps's caps.
The decode allowed caps returned by ensure_allowed_sinkpad_caps()
contains all profiles of the whole VAAPI, like:
image/jpeg, width=(int)[ 0, 1638 4 ], height=(int)[ 0, 16384 ];
video/mpeg, mpegversion=(int)2, profile=(string){ simple, main },
width=(int)[ 0, 2048 ], height=(int)[ 0, 2048 ]; video/x-h264,
profile=(string){ main, high, constrained-baseline }, width=(int)[ 0,
4096 ], height=(int)[ 0, 4096 ]; video/x-h264, profile=(string){
constrained-high, progressive-high, baseline }; video/x-h265,
profile=(string){ main, main-intra }, width=(int)[ 0, 8192 ],
height=(int)[ 0, 8192 ]; video/x-vp8, width=(int)[ 0, 4096 ],
height=(int)[ 0, 4096 ]; video/x-wmv, wmvversion=(int)3,
format=(string)WVC1, profile=(string)advanced, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]; video/x-wmv, wmvversion=(int)3,
profile=(string){ simple, main }, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]
Which is verbose and may have latent problems. It should only contains
the profiles belong to its codec type. For example, h265 should only
return:
video/x-h265, profile=(string){ main, main-intra },
width=(int)[ 0, 8192 ], height=(int)[ 0, 8192 ]
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/361>
2020-07-16 16:45:53 +00:00
|
|
|
|
|
|
|
caps = gst_pad_get_pad_template_caps (sinkpad);
|
|
|
|
decode->allowed_sinkpad_caps =
|
|
|
|
gst_caps_intersect (allowed_sinkpad_caps, caps);
|
|
|
|
gst_caps_unref (caps);
|
2020-08-17 11:26:43 +00:00
|
|
|
gst_caps_unref (allowed_sinkpad_caps);
|
plugin: decode: correct ensure_allowed_sinkpad_caps's caps.
The decode allowed caps returned by ensure_allowed_sinkpad_caps()
contains all profiles of the whole VAAPI, like:
image/jpeg, width=(int)[ 0, 1638 4 ], height=(int)[ 0, 16384 ];
video/mpeg, mpegversion=(int)2, profile=(string){ simple, main },
width=(int)[ 0, 2048 ], height=(int)[ 0, 2048 ]; video/x-h264,
profile=(string){ main, high, constrained-baseline }, width=(int)[ 0,
4096 ], height=(int)[ 0, 4096 ]; video/x-h264, profile=(string){
constrained-high, progressive-high, baseline }; video/x-h265,
profile=(string){ main, main-intra }, width=(int)[ 0, 8192 ],
height=(int)[ 0, 8192 ]; video/x-vp8, width=(int)[ 0, 4096 ],
height=(int)[ 0, 4096 ]; video/x-wmv, wmvversion=(int)3,
format=(string)WVC1, profile=(string)advanced, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]; video/x-wmv, wmvversion=(int)3,
profile=(string){ simple, main }, width=(int)[ 0, 3840 ],
height=(int)[ 0, 3840 ]
Which is verbose and may have latent problems. It should only contains
the profiles belong to its codec type. For example, h265 should only
return:
video/x-h265, profile=(string){ main, main-intra },
width=(int)[ 0, 8192 ], height=(int)[ 0, 8192 ]
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/361>
2020-07-16 16:45:53 +00:00
|
|
|
decode->allowed_sinkpad_caps =
|
|
|
|
gst_caps_simplify (decode->allowed_sinkpad_caps);
|
2019-08-05 17:47:30 +00:00
|
|
|
GST_DEBUG_OBJECT (decode, "allowed sink caps %" GST_PTR_FORMAT,
|
|
|
|
decode->allowed_sinkpad_caps);
|
2015-03-02 12:59:16 +00:00
|
|
|
|
|
|
|
g_array_unref (profiles);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* ERRORS */
|
2013-12-20 14:31:14 +00:00
|
|
|
error_no_profiles:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
|
|
|
GST_ERROR ("failed to retrieve VA decode profiles");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-05-12 09:22:49 +00:00
|
|
|
error_no_memory:
|
2015-03-02 12:59:16 +00:00
|
|
|
{
|
|
|
|
GST_ERROR ("failed to allocate allowed-caps set");
|
|
|
|
g_array_unref (profiles);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-05-12 09:22:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static GstCaps *
|
2016-02-17 12:43:48 +00:00
|
|
|
gst_vaapidecode_sink_getcaps (GstVideoDecoder * vdec, GstCaps * filter)
|
2010-05-12 09:22:49 +00:00
|
|
|
{
|
2016-02-17 12:43:48 +00:00
|
|
|
GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
|
2016-03-08 09:47:56 +00:00
|
|
|
GstCaps *result;
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2016-07-19 15:00:23 +00:00
|
|
|
if (decode->allowed_sinkpad_caps)
|
2015-10-28 12:01:04 +00:00
|
|
|
goto bail;
|
|
|
|
|
|
|
|
/* if we haven't a display yet, return our pad's template caps */
|
2016-03-08 09:47:56 +00:00
|
|
|
if (!GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))
|
2016-03-01 10:35:49 +00:00
|
|
|
goto bail;
|
2015-10-28 12:01:04 +00:00
|
|
|
|
|
|
|
/* if the allowed caps calculation fails, return an empty caps, so
|
|
|
|
* the auto-plug can try other decoder */
|
2016-07-19 15:00:23 +00:00
|
|
|
if (!gst_vaapidecode_ensure_allowed_sinkpad_caps (decode))
|
2015-03-02 12:59:16 +00:00
|
|
|
return gst_caps_new_empty ();
|
2010-05-12 09:22:49 +00:00
|
|
|
|
2015-10-28 12:01:04 +00:00
|
|
|
bail:
|
2016-07-19 15:00:23 +00:00
|
|
|
result = gst_video_decoder_proxy_getcaps (vdec, decode->allowed_sinkpad_caps,
|
|
|
|
filter);
|
2016-03-01 10:35:49 +00:00
|
|
|
|
2016-03-08 09:47:56 +00:00
|
|
|
GST_DEBUG_OBJECT (decode, "Returning sink caps %" GST_PTR_FORMAT, result);
|
2016-03-01 10:35:49 +00:00
|
|
|
|
2016-03-08 09:47:56 +00:00
|
|
|
return result;
|
2010-05-12 09:22:49 +00:00
|
|
|
}
|
|
|
|
|
2015-03-06 12:09:22 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_sink_query (GstVideoDecoder * vdec, GstQuery * query)
|
|
|
|
{
|
|
|
|
gboolean ret = TRUE;
|
2017-01-27 11:10:54 +00:00
|
|
|
GstElement *const element = GST_ELEMENT (vdec);
|
2015-03-06 12:09:22 +00:00
|
|
|
|
|
|
|
switch (GST_QUERY_TYPE (query)) {
|
2015-11-04 20:38:42 +00:00
|
|
|
case GST_QUERY_CONTEXT:{
|
2017-01-27 11:10:54 +00:00
|
|
|
ret = gst_vaapi_handle_context_query (element, query);
|
2015-11-04 20:38:42 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-03-06 12:09:22 +00:00
|
|
|
default:{
|
2016-03-09 17:41:49 +00:00
|
|
|
ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_query (vdec, query);
|
2015-03-06 12:09:22 +00:00
|
|
|
break;
|
2013-04-02 14:12:16 +00:00
|
|
|
}
|
2015-03-06 12:09:22 +00:00
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
|
2015-03-06 12:09:22 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
|
2015-03-06 12:09:22 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_src_query (GstVideoDecoder * vdec, GstQuery * query)
|
|
|
|
{
|
|
|
|
gboolean ret = TRUE;
|
2017-01-27 11:10:54 +00:00
|
|
|
GstElement *const element = GST_ELEMENT (vdec);
|
2015-03-02 12:59:16 +00:00
|
|
|
|
2015-03-06 12:09:22 +00:00
|
|
|
switch (GST_QUERY_TYPE (query)) {
|
2020-09-20 07:56:40 +00:00
|
|
|
case GST_QUERY_CONTEXT:{
|
|
|
|
ret = gst_vaapi_handle_context_query (element, query);
|
|
|
|
break;
|
|
|
|
}
|
2015-03-06 12:09:22 +00:00
|
|
|
case GST_QUERY_CAPS:{
|
|
|
|
GstCaps *caps, *filter = NULL;
|
2020-09-20 07:56:40 +00:00
|
|
|
gboolean fixed_caps;
|
|
|
|
|
|
|
|
fixed_caps = GST_PAD_IS_FIXED_CAPS (GST_VIDEO_DECODER_SRC_PAD (vdec));
|
|
|
|
if (!fixed_caps) {
|
|
|
|
gst_query_parse_caps (query, &filter);
|
|
|
|
caps = gst_vaapidecode_get_allowed_srcpad_caps (GST_VAAPIDECODE (vdec));
|
|
|
|
|
|
|
|
if (filter) {
|
|
|
|
GstCaps *tmp = caps;
|
|
|
|
caps =
|
|
|
|
gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
|
|
|
|
gst_caps_unref (tmp);
|
|
|
|
}
|
2015-03-06 12:09:22 +00:00
|
|
|
|
2020-09-20 07:56:40 +00:00
|
|
|
gst_query_set_caps_result (query, caps);
|
|
|
|
gst_caps_unref (caps);
|
|
|
|
break;
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
2020-09-20 07:56:40 +00:00
|
|
|
/* else jump to default */
|
2015-11-04 20:38:42 +00:00
|
|
|
}
|
2015-03-06 12:09:22 +00:00
|
|
|
default:{
|
2016-03-09 17:41:49 +00:00
|
|
|
ret = GST_VIDEO_DECODER_CLASS (parent_class)->src_query (vdec, query);
|
2015-03-06 12:09:22 +00:00
|
|
|
break;
|
2015-02-18 11:36:16 +00:00
|
|
|
}
|
2015-03-02 12:59:16 +00:00
|
|
|
}
|
2011-11-04 20:50:15 +00:00
|
|
|
|
2015-03-06 12:09:22 +00:00
|
|
|
return ret;
|
2011-11-04 20:50:15 +00:00
|
|
|
}
|
|
|
|
|
2019-08-22 06:33:54 +00:00
|
|
|
static gboolean
|
|
|
|
gst_vaapidecode_transform_meta (GstVideoDecoder *
|
|
|
|
vdec, GstVideoCodecFrame * frame, GstMeta * meta)
|
|
|
|
{
|
|
|
|
const GstMetaInfo *info = meta->info;
|
|
|
|
|
|
|
|
if (GST_VIDEO_DECODER_CLASS (parent_class)->transform_meta (vdec, frame,
|
|
|
|
meta))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (!g_strcmp0 (g_type_name (info->type), "GstVideoRegionOfInterestMeta"))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-02-17 12:43:48 +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);
|
|
|
|
GstVideoDecoderClass *const vdec_class = GST_VIDEO_DECODER_CLASS (klass);
|
|
|
|
GstPadTemplate *pad_template;
|
2016-03-09 19:25:08 +00:00
|
|
|
GstVaapiDecoderMap *map;
|
2016-10-25 17:22:03 +00:00
|
|
|
gchar *name, *longname, *description;
|
2016-03-09 19:25:08 +00:00
|
|
|
GstCaps *caps;
|
2016-02-17 12:43:48 +00:00
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_debug_vaapidecode,
|
|
|
|
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
|
|
|
|
2016-03-09 17:41:49 +00:00
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
|
2016-02-17 12:43:48 +00:00
|
|
|
gst_vaapi_plugin_base_class_init (GST_VAAPI_PLUGIN_BASE_CLASS (klass));
|
|
|
|
|
|
|
|
object_class->finalize = gst_vaapidecode_finalize;
|
|
|
|
|
|
|
|
vdec_class->open = GST_DEBUG_FUNCPTR (gst_vaapidecode_open);
|
|
|
|
vdec_class->close = GST_DEBUG_FUNCPTR (gst_vaapidecode_close);
|
2016-07-12 15:54:26 +00:00
|
|
|
vdec_class->start = GST_DEBUG_FUNCPTR (gst_vaapidecode_start);
|
2016-03-18 23:00:52 +00:00
|
|
|
vdec_class->stop = GST_DEBUG_FUNCPTR (gst_vaapidecode_stop);
|
2016-02-17 12:43:48 +00:00
|
|
|
vdec_class->set_format = GST_DEBUG_FUNCPTR (gst_vaapidecode_set_format);
|
|
|
|
vdec_class->flush = GST_DEBUG_FUNCPTR (gst_vaapidecode_flush);
|
|
|
|
vdec_class->parse = GST_DEBUG_FUNCPTR (gst_vaapidecode_parse);
|
|
|
|
vdec_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vaapidecode_handle_frame);
|
|
|
|
vdec_class->finish = GST_DEBUG_FUNCPTR (gst_vaapidecode_finish);
|
|
|
|
vdec_class->drain = GST_DEBUG_FUNCPTR (gst_vaapidecode_drain);
|
|
|
|
vdec_class->decide_allocation =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_vaapidecode_decide_allocation);
|
|
|
|
vdec_class->src_query = GST_DEBUG_FUNCPTR (gst_vaapidecode_src_query);
|
|
|
|
vdec_class->sink_query = GST_DEBUG_FUNCPTR (gst_vaapidecode_sink_query);
|
|
|
|
vdec_class->getcaps = GST_DEBUG_FUNCPTR (gst_vaapidecode_sink_getcaps);
|
2019-08-22 06:33:54 +00:00
|
|
|
vdec_class->transform_meta =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_vaapidecode_transform_meta);
|
2016-02-17 12:43:48 +00:00
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
map = (GstVaapiDecoderMap *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
|
|
|
|
GST_VAAPI_DECODE_PARAMS_QDATA);
|
|
|
|
|
|
|
|
if (map->codec) {
|
|
|
|
name = g_ascii_strup (map->name, -1);
|
|
|
|
longname = g_strdup_printf ("VA-API %s decoder", name);
|
2016-10-25 17:22:03 +00:00
|
|
|
description = g_strdup_printf ("A VA-API based %s video decoder", name);
|
2016-03-09 19:25:08 +00:00
|
|
|
g_free (name);
|
|
|
|
} else {
|
|
|
|
longname = g_strdup ("VA-API decoder");
|
2016-10-25 17:22:03 +00:00
|
|
|
description = g_strdup (GST_PLUGIN_DESC);
|
2016-03-09 19:25:08 +00:00
|
|
|
}
|
|
|
|
|
2016-04-21 10:57:30 +00:00
|
|
|
element_class->set_context = gst_vaapi_base_set_context;
|
2016-03-09 19:25:08 +00:00
|
|
|
gst_element_class_set_static_metadata (element_class, longname,
|
2018-10-12 14:39:53 +00:00
|
|
|
"Codec/Decoder/Video/Hardware", description,
|
2016-02-17 12:43:48 +00:00
|
|
|
"Gwenole Beauchesne <gwenole.beauchesne@intel.com>, "
|
|
|
|
"Halley Zhao <halley.zhao@intel.com>, "
|
|
|
|
"Sreerenj Balachandran <sreerenj.balachandran@intel.com>, "
|
2020-08-27 13:46:41 +00:00
|
|
|
"Wind Yuan <feng.yuan@intel.com>, Junyan He <junyan.he@intel.com>");
|
2016-02-17 12:43:48 +00:00
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
g_free (longname);
|
2016-10-25 17:22:03 +00:00
|
|
|
g_free (description);
|
2016-03-09 19:25:08 +00:00
|
|
|
|
2017-06-14 15:07:30 +00:00
|
|
|
if (map->install_properties)
|
|
|
|
map->install_properties (object_class);
|
|
|
|
|
2016-02-17 12:43:48 +00:00
|
|
|
/* sink pad */
|
2021-12-01 11:26:11 +00:00
|
|
|
if (map->caps_str) {
|
|
|
|
caps = gst_caps_from_string (map->caps_str);
|
|
|
|
} else {
|
|
|
|
caps = gst_caps_from_string (gst_vaapidecode_sink_caps_str);
|
|
|
|
g_free (gst_vaapidecode_sink_caps_str);
|
|
|
|
}
|
2016-03-09 19:25:08 +00:00
|
|
|
pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
|
|
|
caps);
|
|
|
|
gst_caps_unref (caps);
|
2016-02-17 12:43:48 +00:00
|
|
|
gst_element_class_add_pad_template (element_class, pad_template);
|
|
|
|
|
|
|
|
/* src pad */
|
2016-03-04 07:35:11 +00:00
|
|
|
gst_element_class_add_static_pad_template (element_class,
|
|
|
|
&gst_vaapidecode_src_factory);
|
2016-02-17 12:43:48 +00:00
|
|
|
}
|
|
|
|
|
2010-04-29 17:55:58 +00:00
|
|
|
static void
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapidecode_init (GstVaapiDecode * decode)
|
2010-04-29 17:55:58 +00:00
|
|
|
{
|
2015-03-02 12:59:16 +00:00
|
|
|
GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
|
2010-04-29 17:55:58 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_vaapi_plugin_base_init (GST_VAAPI_PLUGIN_BASE (decode), GST_CAT_DEFAULT);
|
2013-12-13 09:24:26 +00:00
|
|
|
|
2015-03-02 12:59:16 +00:00
|
|
|
gst_video_decoder_set_packetized (vdec, FALSE);
|
2010-04-29 17:55:58 +00:00
|
|
|
}
|
2016-03-09 17:41:49 +00:00
|
|
|
|
|
|
|
gboolean
|
2016-07-12 21:47:41 +00:00
|
|
|
gst_vaapidecode_register (GstPlugin * plugin, GArray * decoders)
|
2016-03-09 17:41:49 +00:00
|
|
|
{
|
2016-03-09 19:25:08 +00:00
|
|
|
gboolean ret = FALSE;
|
|
|
|
guint i, codec, rank;
|
2021-12-01 11:26:11 +00:00
|
|
|
gchar *type_name, *element_name, *sink_caps_str;
|
2016-03-09 19:25:08 +00:00
|
|
|
const gchar *name;
|
2016-03-09 17:41:49 +00:00
|
|
|
GType type;
|
|
|
|
GTypeInfo typeinfo = {
|
|
|
|
sizeof (GstVaapiDecodeClass),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(GClassInitFunc) gst_vaapidecode_class_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
sizeof (GstVaapiDecode),
|
|
|
|
0,
|
|
|
|
(GInstanceInitFunc) gst_vaapidecode_init,
|
|
|
|
};
|
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (vaapi_decode_map); i++) {
|
|
|
|
codec = vaapi_decode_map[i].codec;
|
|
|
|
rank = vaapi_decode_map[i].rank;
|
|
|
|
name = vaapi_decode_map[i].name;
|
|
|
|
|
2016-07-12 21:47:41 +00:00
|
|
|
if (codec && !gst_vaapi_codecs_has_codec (decoders, codec))
|
|
|
|
continue;
|
|
|
|
|
2021-12-01 11:26:11 +00:00
|
|
|
if (!gst_vaapidecode_sink_caps_str) {
|
|
|
|
gst_vaapidecode_sink_caps_str = g_strdup (vaapi_decode_map[i].caps_str);
|
|
|
|
} else {
|
|
|
|
sink_caps_str = g_strconcat (gst_vaapidecode_sink_caps_str, "; ",
|
|
|
|
vaapi_decode_map[i].caps_str, NULL);
|
|
|
|
g_clear_pointer (&gst_vaapidecode_sink_caps_str, g_free);
|
2022-08-11 19:22:12 +00:00
|
|
|
if (!sink_caps_str)
|
|
|
|
break;
|
2021-12-01 11:26:11 +00:00
|
|
|
gst_vaapidecode_sink_caps_str = sink_caps_str;
|
|
|
|
}
|
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
if (codec) {
|
|
|
|
type_name = g_strdup_printf ("GstVaapiDecode_%s", name);
|
|
|
|
element_name = g_strdup_printf ("vaapi%sdec", name);
|
|
|
|
} else {
|
|
|
|
type_name = g_strdup ("GstVaapiDecode");
|
|
|
|
element_name = g_strdup_printf ("vaapidecode");
|
|
|
|
}
|
|
|
|
|
|
|
|
type = g_type_from_name (type_name);
|
|
|
|
if (!type) {
|
|
|
|
/* create the gtype now */
|
|
|
|
type = g_type_register_static (GST_TYPE_VIDEO_DECODER, type_name,
|
|
|
|
&typeinfo, 0);
|
|
|
|
gst_vaapi_plugin_base_init_interfaces (type);
|
|
|
|
g_type_set_qdata (type, GST_VAAPI_DECODE_PARAMS_QDATA,
|
|
|
|
(gpointer) & vaapi_decode_map[i]);
|
|
|
|
}
|
|
|
|
|
2016-06-07 14:28:07 +00:00
|
|
|
/* Register GstVaapiDecode as GObject type, but not in GStreamer, so
|
|
|
|
* vaapidecodebin can use it internally, but no exposed as a plugin
|
|
|
|
* feature */
|
|
|
|
if (codec)
|
|
|
|
ret |= gst_element_register (plugin, element_name, rank, type);
|
2016-03-09 19:25:08 +00:00
|
|
|
|
|
|
|
g_free (element_name);
|
|
|
|
g_free (type_name);
|
2016-03-09 17:41:49 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 19:25:08 +00:00
|
|
|
return ret;
|
2016-03-09 17:41:49 +00:00
|
|
|
}
|