mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
Add "codec-data" property for additional codec data.
e.g. VC-1 sequence headers for elementary streams.
This commit is contained in:
parent
664542fe2e
commit
89c094d659
5 changed files with 76 additions and 8 deletions
|
@ -42,6 +42,7 @@ enum {
|
||||||
|
|
||||||
PROP_DISPLAY,
|
PROP_DISPLAY,
|
||||||
PROP_CODEC,
|
PROP_CODEC,
|
||||||
|
PROP_CODEC_DATA
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -163,6 +164,20 @@ pop_buffer(GstVaapiDecoder *decoder)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_codec_data(GstVaapiDecoder *decoder, GstBuffer *codec_data)
|
||||||
|
{
|
||||||
|
GstVaapiDecoderPrivate * const priv = decoder->priv;
|
||||||
|
|
||||||
|
if (priv->codec_data) {
|
||||||
|
gst_buffer_unref(priv->codec_data);
|
||||||
|
priv->codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codec_data)
|
||||||
|
priv->codec_data = gst_buffer_ref(codec_data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_async_queue(GAsyncQueue *q)
|
clear_async_queue(GAsyncQueue *q)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +195,8 @@ gst_vaapi_decoder_finalize(GObject *object)
|
||||||
|
|
||||||
gst_vaapi_decoder_stop(decoder);
|
gst_vaapi_decoder_stop(decoder);
|
||||||
|
|
||||||
|
set_codec_data(decoder, NULL);
|
||||||
|
|
||||||
if (priv->context) {
|
if (priv->context) {
|
||||||
g_object_unref(priv->context);
|
g_object_unref(priv->context);
|
||||||
priv->context = NULL;
|
priv->context = NULL;
|
||||||
|
@ -222,6 +239,9 @@ gst_vaapi_decoder_set_property(
|
||||||
case PROP_CODEC:
|
case PROP_CODEC:
|
||||||
priv->codec = g_value_get_uint(value);
|
priv->codec = g_value_get_uint(value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CODEC_DATA:
|
||||||
|
set_codec_data(GST_VAAPI_DECODER(object), gst_value_get_buffer(value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -245,6 +265,9 @@ gst_vaapi_decoder_get_property(
|
||||||
case PROP_CODEC:
|
case PROP_CODEC:
|
||||||
g_value_set_uint(value, priv->codec);
|
g_value_set_uint(value, priv->codec);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CODEC_DATA:
|
||||||
|
gst_value_set_buffer(value, priv->codec_data);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -284,6 +307,15 @@ gst_vaapi_decoder_class_init(GstVaapiDecoderClass *klass)
|
||||||
"The codec handled by the decoder",
|
"The codec handled by the decoder",
|
||||||
0, G_MAXINT32, 0,
|
0, G_MAXINT32, 0,
|
||||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
|
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class,
|
||||||
|
PROP_CODEC_DATA,
|
||||||
|
gst_param_spec_mini_object("codec-data",
|
||||||
|
"Codec data",
|
||||||
|
"Extra codec data",
|
||||||
|
GST_TYPE_BUFFER,
|
||||||
|
G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -294,6 +326,7 @@ gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
|
||||||
decoder->priv = priv;
|
decoder->priv = priv;
|
||||||
priv->context = NULL;
|
priv->context = NULL;
|
||||||
priv->codec = 0;
|
priv->codec = 0;
|
||||||
|
priv->codec_data = NULL;
|
||||||
priv->fps_n = 1000;
|
priv->fps_n = 1000;
|
||||||
priv->fps_d = 30;
|
priv->fps_d = 30;
|
||||||
priv->next_ts = 0;
|
priv->next_ts = 0;
|
||||||
|
|
|
@ -234,6 +234,7 @@ gst_vaapi_decoder_ffmpeg_destroy(GstVaapiDecoderFfmpeg *ffdecoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->avctx) {
|
if (priv->avctx) {
|
||||||
|
av_freep(&priv->avctx->extradata);
|
||||||
avcodec_close(priv->avctx);
|
avcodec_close(priv->avctx);
|
||||||
priv->avctx = NULL;
|
priv->avctx = NULL;
|
||||||
}
|
}
|
||||||
|
@ -252,6 +253,7 @@ gst_vaapi_decoder_ffmpeg_create(GstVaapiDecoderFfmpeg *ffdecoder)
|
||||||
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(ffdecoder);
|
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(ffdecoder);
|
||||||
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
|
||||||
GstVaapiCodec codec = GST_VAAPI_DECODER_CODEC(decoder);
|
GstVaapiCodec codec = GST_VAAPI_DECODER_CODEC(decoder);
|
||||||
|
GstBuffer * const codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
|
||||||
enum CodecID codec_id;
|
enum CodecID codec_id;
|
||||||
AVCodec *ffcodec;
|
AVCodec *ffcodec;
|
||||||
|
|
||||||
|
@ -275,6 +277,18 @@ gst_vaapi_decoder_ffmpeg_create(GstVaapiDecoderFfmpeg *ffdecoder)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (codec_data) {
|
||||||
|
const guchar *data = GST_BUFFER_DATA(codec_data);
|
||||||
|
const guint size = GST_BUFFER_SIZE(codec_data);
|
||||||
|
av_freep(&priv->avctx->extradata);
|
||||||
|
priv->avctx->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!priv->avctx->extradata)
|
||||||
|
return FALSE;
|
||||||
|
priv->avctx->extradata_size = size;
|
||||||
|
memcpy(priv->avctx->extradata, data, size);
|
||||||
|
memset(priv->avctx->extradata + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
if (!priv->vactx) {
|
if (!priv->vactx) {
|
||||||
priv->vactx = g_new(GstVaapiContextFfmpeg, 1);
|
priv->vactx = g_new(GstVaapiContextFfmpeg, 1);
|
||||||
if (!priv->vactx)
|
if (!priv->vactx)
|
||||||
|
@ -436,21 +450,25 @@ gst_vaapi_decoder_ffmpeg_init(GstVaapiDecoderFfmpeg *decoder)
|
||||||
* gst_vaapi_decoder_ffmpeg_new:
|
* gst_vaapi_decoder_ffmpeg_new:
|
||||||
* @display: a #GstVaapiDisplay
|
* @display: a #GstVaapiDisplay
|
||||||
* @codec: a #GstVaapiCodec
|
* @codec: a #GstVaapiCodec
|
||||||
|
* @codec_data: an optional #GstBuffer holding extra codec data, or %NULL
|
||||||
*
|
*
|
||||||
* Creates a new #GstVaapiDecoder with the specified @codec bound to
|
* Creates a new #GstVaapiDecoder with the specified @codec bound to
|
||||||
* @display. If @codec is zero, the first video stream will be
|
* @display. @codec_data holds extra codec data like sequence headers.
|
||||||
* selected. Otherwise, the first video stream matching @codec is
|
|
||||||
* used, if any.
|
|
||||||
*
|
*
|
||||||
* Return value: the newly allocated #GstVaapiDecoder object
|
* Return value: the newly allocated #GstVaapiDecoder object
|
||||||
*/
|
*/
|
||||||
GstVaapiDecoder *
|
GstVaapiDecoder *
|
||||||
gst_vaapi_decoder_ffmpeg_new(GstVaapiDisplay *display, GstVaapiCodec codec)
|
gst_vaapi_decoder_ffmpeg_new(
|
||||||
|
GstVaapiDisplay *display,
|
||||||
|
GstVaapiCodec codec,
|
||||||
|
GstBuffer *codec_data
|
||||||
|
)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
|
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
|
||||||
|
|
||||||
return g_object_new(GST_VAAPI_TYPE_DECODER_FFMPEG,
|
return g_object_new(GST_VAAPI_TYPE_DECODER_FFMPEG,
|
||||||
"display", display,
|
"display", display,
|
||||||
"codec", codec,
|
"codec", codec,
|
||||||
|
"codec-data", codec_data,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,11 @@ GType
|
||||||
gst_vaapi_decoder_ffmpeg_get_type(void);
|
gst_vaapi_decoder_ffmpeg_get_type(void);
|
||||||
|
|
||||||
GstVaapiDecoder *
|
GstVaapiDecoder *
|
||||||
gst_vaapi_decoder_ffmpeg_new(GstVaapiDisplay *display, GstVaapiCodec codec);
|
gst_vaapi_decoder_ffmpeg_new(
|
||||||
|
GstVaapiDisplay *display,
|
||||||
|
GstVaapiCodec codec,
|
||||||
|
GstBuffer *codec_data
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,18 @@ G_BEGIN_DECLS
|
||||||
#define GST_VAAPI_DECODER_CODEC(decoder) \
|
#define GST_VAAPI_DECODER_CODEC(decoder) \
|
||||||
GST_VAAPI_DECODER_CAST(decoder)->priv->codec
|
GST_VAAPI_DECODER_CAST(decoder)->priv->codec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_VAAPI_DECODER_CODEC_DATA:
|
||||||
|
* @decoder: a #GstVaapiDecoder
|
||||||
|
*
|
||||||
|
* Macro that evaluates to the #GstBuffer holding optional codec data
|
||||||
|
* for @decoder.
|
||||||
|
* This is an internal macro that does not do any run-time type check.
|
||||||
|
*/
|
||||||
|
#undef GST_VAAPI_DECODER_CODEC_DATA
|
||||||
|
#define GST_VAAPI_DECODER_CODEC_DATA(decoder) \
|
||||||
|
GST_VAAPI_DECODER_CAST(decoder)->priv->codec_data
|
||||||
|
|
||||||
/* End-of-Stream buffer */
|
/* End-of-Stream buffer */
|
||||||
#define GST_BUFFER_FLAG_EOS (GST_BUFFER_FLAG_LAST + 0)
|
#define GST_BUFFER_FLAG_EOS (GST_BUFFER_FLAG_LAST + 0)
|
||||||
|
|
||||||
|
@ -78,6 +90,7 @@ struct _GstVaapiDecoderPrivate {
|
||||||
GstVaapiDisplay *display;
|
GstVaapiDisplay *display;
|
||||||
GstVaapiContext *context;
|
GstVaapiContext *context;
|
||||||
GstVaapiCodec codec;
|
GstVaapiCodec codec;
|
||||||
|
GstBuffer *codec_data;
|
||||||
guint fps_n;
|
guint fps_n;
|
||||||
guint fps_d;
|
guint fps_d;
|
||||||
GstClockTime next_ts;
|
GstClockTime next_ts;
|
||||||
|
|
|
@ -114,7 +114,7 @@ main(int argc, char *argv[])
|
||||||
g_error("could not create window");
|
g_error("could not create window");
|
||||||
|
|
||||||
codec->get_video_data(&vdata, &vdata_size);
|
codec->get_video_data(&vdata, &vdata_size);
|
||||||
decoder = gst_vaapi_decoder_ffmpeg_new(display, codec->codec);
|
decoder = gst_vaapi_decoder_ffmpeg_new(display, codec->codec, NULL);
|
||||||
if (!decoder)
|
if (!decoder)
|
||||||
g_error("could not create FFmpeg decoder");
|
g_error("could not create FFmpeg decoder");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue