Add "codec-data" property for additional codec data.

e.g. VC-1 sequence headers for elementary streams.
This commit is contained in:
gb 2010-04-28 21:50:44 +00:00 committed by Gwenole Beauchesne
parent 664542fe2e
commit 89c094d659
5 changed files with 76 additions and 8 deletions

View file

@ -42,6 +42,7 @@ enum {
PROP_DISPLAY,
PROP_CODEC,
PROP_CODEC_DATA
};
static gboolean
@ -163,6 +164,20 @@ pop_buffer(GstVaapiDecoder *decoder)
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
clear_async_queue(GAsyncQueue *q)
{
@ -180,6 +195,8 @@ gst_vaapi_decoder_finalize(GObject *object)
gst_vaapi_decoder_stop(decoder);
set_codec_data(decoder, NULL);
if (priv->context) {
g_object_unref(priv->context);
priv->context = NULL;
@ -222,6 +239,9 @@ gst_vaapi_decoder_set_property(
case PROP_CODEC:
priv->codec = g_value_get_uint(value);
break;
case PROP_CODEC_DATA:
set_codec_data(GST_VAAPI_DECODER(object), gst_value_get_buffer(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -245,6 +265,9 @@ gst_vaapi_decoder_get_property(
case PROP_CODEC:
g_value_set_uint(value, priv->codec);
break;
case PROP_CODEC_DATA:
gst_value_set_buffer(value, priv->codec_data);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -284,6 +307,15 @@ gst_vaapi_decoder_class_init(GstVaapiDecoderClass *klass)
"The codec handled by the decoder",
0, G_MAXINT32, 0,
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
@ -294,6 +326,7 @@ gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
decoder->priv = priv;
priv->context = NULL;
priv->codec = 0;
priv->codec_data = NULL;
priv->fps_n = 1000;
priv->fps_d = 30;
priv->next_ts = 0;

View file

@ -234,6 +234,7 @@ gst_vaapi_decoder_ffmpeg_destroy(GstVaapiDecoderFfmpeg *ffdecoder)
}
if (priv->avctx) {
av_freep(&priv->avctx->extradata);
avcodec_close(priv->avctx);
priv->avctx = NULL;
}
@ -252,6 +253,7 @@ gst_vaapi_decoder_ffmpeg_create(GstVaapiDecoderFfmpeg *ffdecoder)
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(ffdecoder);
GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv;
GstVaapiCodec codec = GST_VAAPI_DECODER_CODEC(decoder);
GstBuffer * const codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
enum CodecID codec_id;
AVCodec *ffcodec;
@ -275,6 +277,18 @@ gst_vaapi_decoder_ffmpeg_create(GstVaapiDecoderFfmpeg *ffdecoder)
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) {
priv->vactx = g_new(GstVaapiContextFfmpeg, 1);
if (!priv->vactx)
@ -436,21 +450,25 @@ gst_vaapi_decoder_ffmpeg_init(GstVaapiDecoderFfmpeg *decoder)
* gst_vaapi_decoder_ffmpeg_new:
* @display: a #GstVaapiDisplay
* @codec: a #GstVaapiCodec
* @codec_data: an optional #GstBuffer holding extra codec data, or %NULL
*
* Creates a new #GstVaapiDecoder with the specified @codec bound to
* @display. If @codec is zero, the first video stream will be
* selected. Otherwise, the first video stream matching @codec is
* used, if any.
* @display. @codec_data holds extra codec data like sequence headers.
*
* Return value: the newly allocated #GstVaapiDecoder object
*/
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);
return g_object_new(GST_VAAPI_TYPE_DECODER_FFMPEG,
"display", display,
"codec", codec,
"display", display,
"codec", codec,
"codec-data", codec_data,
NULL);
}

View file

@ -79,7 +79,11 @@ GType
gst_vaapi_decoder_ffmpeg_get_type(void);
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

View file

@ -63,6 +63,18 @@ G_BEGIN_DECLS
#define GST_VAAPI_DECODER_CODEC(decoder) \
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 */
#define GST_BUFFER_FLAG_EOS (GST_BUFFER_FLAG_LAST + 0)
@ -78,6 +90,7 @@ struct _GstVaapiDecoderPrivate {
GstVaapiDisplay *display;
GstVaapiContext *context;
GstVaapiCodec codec;
GstBuffer *codec_data;
guint fps_n;
guint fps_d;
GstClockTime next_ts;

View file

@ -114,7 +114,7 @@ main(int argc, char *argv[])
g_error("could not create window");
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)
g_error("could not create FFmpeg decoder");