From: gb Date: Wed, 28 Apr 2010 21:50:44 +0000 (+0000) Subject: Add "codec-data" property for additional codec data. X-Git-Tag: 0.2.0~73 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=89c094d659f909e0e5ed956382b68fcb14d8c4d8;p=platform%2Fupstream%2Fgstreamer-vaapi.git Add "codec-data" property for additional codec data. e.g. VC-1 sequence headers for elementary streams. --- diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c index d9e17eb..a2d9400 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder.c @@ -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; diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c index eae18eb..6361eaf 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.c @@ -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); } diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.h b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.h index 184759a..487a9a6 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_ffmpeg.h @@ -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 diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h index 146c760..e5f87e6 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h @@ -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; diff --git a/tests/test-decode.c b/tests/test-decode.c index 7702f60..f076ec1 100644 --- a/tests/test-decode.c +++ b/tests/test-decode.c @@ -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");