libav: Update AVCodecContext lifetime to work properly with ffmpeg 7
avcodec_close() is deprecated and it's not supported anymore to re-open a codec, so we only ever allocate the codec in set_format() now and always free it after usage. As part of this, also fix various memory leaks in related code paths. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6505>
This commit is contained in:
parent
0871a55c8a
commit
73d0cac16c
@ -72,18 +72,6 @@ gst_ffmpeg_avcodec_open (AVCodecContext * avctx, const AVCodec * codec)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
gst_ffmpeg_avcodec_close (AVCodecContext * avctx)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
g_mutex_lock (&gst_avcodec_mutex);
|
|
||||||
ret = avcodec_close (avctx);
|
|
||||||
g_mutex_unlock (&gst_avcodec_mutex);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gst_ffmpeg_av_find_stream_info (AVFormatContext * ic)
|
gst_ffmpeg_av_find_stream_info (AVFormatContext * ic)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,6 @@ extern gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin);
|
|||||||
extern gboolean gst_ffmpegvidcmp_register (GstPlugin * plugin);
|
extern gboolean gst_ffmpegvidcmp_register (GstPlugin * plugin);
|
||||||
|
|
||||||
int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, const AVCodec *codec);
|
int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, const AVCodec *codec);
|
||||||
int gst_ffmpeg_avcodec_close (AVCodecContext *avctx);
|
|
||||||
int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic);
|
int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -145,16 +145,6 @@ gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass)
|
|||||||
static void
|
static void
|
||||||
gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec)
|
gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec)
|
||||||
{
|
{
|
||||||
GstFFMpegAudDecClass *klass =
|
|
||||||
(GstFFMpegAudDecClass *) G_OBJECT_GET_CLASS (ffmpegdec);
|
|
||||||
|
|
||||||
/* some ffmpeg data */
|
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin);
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
ffmpegdec->opened = FALSE;
|
|
||||||
|
|
||||||
ffmpegdec->frame = av_frame_alloc ();
|
|
||||||
|
|
||||||
GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (ffmpegdec));
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (ffmpegdec));
|
||||||
gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
|
gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
|
||||||
(ffmpegdec), TRUE);
|
(ffmpegdec), TRUE);
|
||||||
@ -175,60 +165,24 @@ gst_ffmpegauddec_finalize (GObject * object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* With LOCK */
|
/* With LOCK */
|
||||||
static gboolean
|
static void
|
||||||
gst_ffmpegauddec_close (GstFFMpegAudDec * ffmpegdec, gboolean reset)
|
gst_ffmpegauddec_close (GstFFMpegAudDec * ffmpegdec)
|
||||||
{
|
{
|
||||||
GstFFMpegAudDecClass *oclass;
|
|
||||||
|
|
||||||
oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegdec, "closing libav codec");
|
GST_LOG_OBJECT (ffmpegdec, "closing libav codec");
|
||||||
|
|
||||||
gst_caps_replace (&ffmpegdec->last_caps, NULL);
|
gst_caps_replace (&ffmpegdec->last_caps, NULL);
|
||||||
|
|
||||||
gst_ffmpeg_avcodec_close (ffmpegdec->context);
|
|
||||||
ffmpegdec->opened = FALSE;
|
|
||||||
|
|
||||||
av_freep (&ffmpegdec->context->extradata);
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
if (reset) {
|
|
||||||
avcodec_free_context (&ffmpegdec->context);
|
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegdec->context == NULL) {
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ffmpegauddec_start (GstAudioDecoder * decoder)
|
gst_ffmpegauddec_start (GstAudioDecoder * decoder)
|
||||||
{
|
{
|
||||||
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
||||||
GstFFMpegAudDecClass *oclass;
|
|
||||||
|
|
||||||
oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
|
ffmpegdec->frame = av_frame_alloc ();
|
||||||
avcodec_free_context (&ffmpegdec->context);
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegdec->context == NULL) {
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
|
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
|
|
||||||
/* FIXME: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1474 */
|
|
||||||
if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_DELAY) != 0
|
|
||||||
&& (oclass->in_plugin->id == AV_CODEC_ID_WMAV1
|
|
||||||
|| oclass->in_plugin->id == AV_CODEC_ID_WMAV2)) {
|
|
||||||
ffmpegdec->context->flags2 |= AV_CODEC_FLAG2_SKIP_MANUAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -240,8 +194,9 @@ gst_ffmpegauddec_stop (GstAudioDecoder * decoder)
|
|||||||
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
gst_ffmpegauddec_close (ffmpegdec, FALSE);
|
av_frame_free (&ffmpegdec->frame);
|
||||||
g_free (ffmpegdec->padded);
|
g_free (ffmpegdec->padded);
|
||||||
|
gst_ffmpegauddec_close (ffmpegdec);
|
||||||
ffmpegdec->padded = NULL;
|
ffmpegdec->padded = NULL;
|
||||||
ffmpegdec->padded_size = 0;
|
ffmpegdec->padded_size = 0;
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
@ -262,8 +217,6 @@ gst_ffmpegauddec_open (GstFFMpegAudDec * ffmpegdec)
|
|||||||
if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0)
|
if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0)
|
||||||
goto could_not_open;
|
goto could_not_open;
|
||||||
|
|
||||||
ffmpegdec->opened = TRUE;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d",
|
GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d",
|
||||||
oclass->in_plugin->name, oclass->in_plugin->id);
|
oclass->in_plugin->name, oclass->in_plugin->id);
|
||||||
|
|
||||||
@ -274,7 +227,7 @@ gst_ffmpegauddec_open (GstFFMpegAudDec * ffmpegdec)
|
|||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
could_not_open:
|
could_not_open:
|
||||||
{
|
{
|
||||||
gst_ffmpegauddec_close (ffmpegdec, TRUE);
|
gst_ffmpegauddec_close (ffmpegdec);
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec",
|
GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec",
|
||||||
oclass->in_plugin->name);
|
oclass->in_plugin->name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -321,14 +274,26 @@ gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
|
|||||||
gst_caps_replace (&ffmpegdec->last_caps, caps);
|
gst_caps_replace (&ffmpegdec->last_caps, caps);
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
if (ffmpegdec->opened) {
|
if (ffmpegdec->context) {
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
gst_ffmpegauddec_drain (ffmpegdec, FALSE);
|
gst_ffmpegauddec_drain (ffmpegdec, FALSE);
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
if (!gst_ffmpegauddec_close (ffmpegdec, TRUE)) {
|
gst_ffmpegauddec_close (ffmpegdec);
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
}
|
||||||
return FALSE;
|
|
||||||
}
|
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
||||||
|
if (ffmpegdec->context == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "Failed to allocate context");
|
||||||
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ffmpegdec->context->opaque = ffmpegdec;
|
||||||
|
|
||||||
|
/* FIXME: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1474 */
|
||||||
|
if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_DELAY) != 0
|
||||||
|
&& (oclass->in_plugin->id == AV_CODEC_ID_WMAV1
|
||||||
|
|| oclass->in_plugin->id == AV_CODEC_ID_WMAV2)) {
|
||||||
|
ffmpegdec->context->flags2 |= AV_CODEC_FLAG2_SKIP_MANUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get size and so */
|
/* get size and so */
|
||||||
@ -586,7 +551,7 @@ gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec, GstFlowReturn * ret,
|
|||||||
GstBuffer *outbuf = NULL;
|
GstBuffer *outbuf = NULL;
|
||||||
gboolean got_frame = FALSE;
|
gboolean got_frame = FALSE;
|
||||||
|
|
||||||
if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
|
if (G_UNLIKELY (!ffmpegdec->context))
|
||||||
goto no_codec;
|
goto no_codec;
|
||||||
|
|
||||||
*ret = GST_FLOW_OK;
|
*ret = GST_FLOW_OK;
|
||||||
@ -630,6 +595,9 @@ gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec, gboolean force)
|
|||||||
gboolean need_more_data = FALSE;
|
gboolean need_more_data = FALSE;
|
||||||
gboolean got_frame;
|
gboolean got_frame;
|
||||||
|
|
||||||
|
if (!ffmpegdec->context)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
if (avcodec_send_packet (ffmpegdec->context, NULL))
|
if (avcodec_send_packet (ffmpegdec->context, NULL))
|
||||||
goto send_packet_failed;
|
goto send_packet_failed;
|
||||||
|
|
||||||
@ -672,7 +640,7 @@ gst_ffmpegauddec_flush (GstAudioDecoder * decoder, gboolean hard)
|
|||||||
{
|
{
|
||||||
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
|
||||||
|
|
||||||
if (ffmpegdec->opened) {
|
if (ffmpegdec->context) {
|
||||||
avcodec_flush_buffers (ffmpegdec->context);
|
avcodec_flush_buffers (ffmpegdec->context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -697,7 +665,7 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
|
|||||||
|
|
||||||
ffmpegdec = (GstFFMpegAudDec *) decoder;
|
ffmpegdec = (GstFFMpegAudDec *) decoder;
|
||||||
|
|
||||||
if (G_UNLIKELY (!ffmpegdec->opened))
|
if (G_UNLIKELY (!ffmpegdec->context))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (inbuf == NULL) {
|
if (inbuf == NULL) {
|
||||||
|
@ -34,7 +34,6 @@ struct _GstFFMpegAudDec
|
|||||||
|
|
||||||
/* decoding */
|
/* decoding */
|
||||||
AVCodecContext *context;
|
AVCodecContext *context;
|
||||||
gboolean opened;
|
|
||||||
|
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
|
|
||||||
|
@ -161,10 +161,7 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc)
|
|||||||
GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (ffmpegaudenc));
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (ffmpegaudenc));
|
||||||
|
|
||||||
/* ffmpeg objects */
|
/* ffmpeg objects */
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin);
|
|
||||||
ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
|
ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
|
||||||
ffmpegaudenc->opened = FALSE;
|
|
||||||
ffmpegaudenc->frame = av_frame_alloc ();
|
|
||||||
|
|
||||||
gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
|
gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
|
||||||
}
|
}
|
||||||
@ -186,18 +183,12 @@ static gboolean
|
|||||||
gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
|
gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
|
||||||
{
|
{
|
||||||
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
||||||
GstFFMpegAudEncClass *oclass =
|
|
||||||
(GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
|
|
||||||
|
|
||||||
ffmpegaudenc->opened = FALSE;
|
|
||||||
ffmpegaudenc->need_reopen = FALSE;
|
|
||||||
|
|
||||||
avcodec_free_context (&ffmpegaudenc->context);
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
av_frame_free (&ffmpegaudenc->frame);
|
||||||
if (ffmpegaudenc->context == NULL) {
|
ffmpegaudenc->need_reopen = FALSE;
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
ffmpegaudenc->frame = av_frame_alloc ();
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -208,8 +199,8 @@ gst_ffmpegaudenc_stop (GstAudioEncoder * encoder)
|
|||||||
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
ffmpegaudenc->opened = FALSE;
|
av_frame_free (&ffmpegaudenc->frame);
|
||||||
ffmpegaudenc->need_reopen = FALSE;
|
ffmpegaudenc->need_reopen = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -220,7 +211,7 @@ gst_ffmpegaudenc_flush (GstAudioEncoder * encoder)
|
|||||||
{
|
{
|
||||||
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
||||||
|
|
||||||
if (ffmpegaudenc->opened) {
|
if (ffmpegaudenc->context) {
|
||||||
avcodec_flush_buffers (ffmpegaudenc->context);
|
avcodec_flush_buffers (ffmpegaudenc->context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,14 +230,11 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
ffmpegaudenc->need_reopen = FALSE;
|
ffmpegaudenc->need_reopen = FALSE;
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
if (ffmpegaudenc->opened) {
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
avcodec_free_context (&ffmpegaudenc->context);
|
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
||||||
ffmpegaudenc->opened = FALSE;
|
if (ffmpegaudenc->context == NULL) {
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
||||||
if (ffmpegaudenc->context == NULL) {
|
return FALSE;
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
|
gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
|
||||||
@ -298,12 +286,8 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
/* open codec */
|
/* open codec */
|
||||||
if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
|
if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
|
||||||
gst_caps_unref (allowed_caps);
|
gst_caps_unref (allowed_caps);
|
||||||
avcodec_free_context (&ffmpegaudenc->context);
|
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
|
GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
|
||||||
oclass->in_plugin->name);
|
oclass->in_plugin->name);
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegaudenc->context == NULL)
|
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
|
||||||
|
|
||||||
if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
|
if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
|
||||||
ffmpegaudenc->context->strict_std_compliance !=
|
ffmpegaudenc->context->strict_std_compliance !=
|
||||||
@ -315,6 +299,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
"or of good quality. If you must use it anyway, set the "
|
"or of good quality. If you must use it anyway, set the "
|
||||||
"compliance property to experimental"));
|
"compliance property to experimental"));
|
||||||
}
|
}
|
||||||
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,9 +311,6 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
gst_caps_unref (allowed_caps);
|
gst_caps_unref (allowed_caps);
|
||||||
avcodec_free_context (&ffmpegaudenc->context);
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
GST_DEBUG ("Unsupported codec - no caps found");
|
GST_DEBUG ("Unsupported codec - no caps found");
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegaudenc->context == NULL)
|
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +319,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
gst_caps_unref (other_caps);
|
gst_caps_unref (other_caps);
|
||||||
if (gst_caps_is_empty (icaps)) {
|
if (gst_caps_is_empty (icaps)) {
|
||||||
gst_caps_unref (icaps);
|
gst_caps_unref (icaps);
|
||||||
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
icaps = gst_caps_fixate (icaps);
|
icaps = gst_caps_fixate (icaps);
|
||||||
@ -345,9 +328,6 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
icaps)) {
|
icaps)) {
|
||||||
avcodec_free_context (&ffmpegaudenc->context);
|
avcodec_free_context (&ffmpegaudenc->context);
|
||||||
gst_caps_unref (icaps);
|
gst_caps_unref (icaps);
|
||||||
ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegaudenc->context == NULL)
|
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
gst_caps_unref (icaps);
|
gst_caps_unref (icaps);
|
||||||
@ -385,8 +365,6 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* success! */
|
/* success! */
|
||||||
ffmpegaudenc->opened = TRUE;
|
|
||||||
ffmpegaudenc->need_reopen = FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -394,8 +372,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
|
|||||||
static void
|
static void
|
||||||
gst_ffmpegaudenc_free_avpacket (gpointer pkt)
|
gst_ffmpegaudenc_free_avpacket (gpointer pkt)
|
||||||
{
|
{
|
||||||
av_packet_unref ((AVPacket *) pkt);
|
av_packet_free ((AVPacket **) & pkt);
|
||||||
g_free (pkt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -596,8 +573,7 @@ gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
|
|||||||
|
|
||||||
ctx = ffmpegaudenc->context;
|
ctx = ffmpegaudenc->context;
|
||||||
|
|
||||||
pkt = g_new0 (AVPacket, 1);
|
pkt = av_packet_alloc ();
|
||||||
|
|
||||||
res = avcodec_receive_packet (ctx, pkt);
|
res = avcodec_receive_packet (ctx, pkt);
|
||||||
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
@ -636,7 +612,7 @@ gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
|
|||||||
*got_packet = TRUE;
|
*got_packet = TRUE;
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
|
GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
|
||||||
g_free (pkt);
|
av_packet_free (&pkt);
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
*got_packet = FALSE;
|
*got_packet = FALSE;
|
||||||
}
|
}
|
||||||
@ -650,6 +626,9 @@ gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
|
|||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gboolean got_packet;
|
gboolean got_packet;
|
||||||
|
|
||||||
|
if (!ffmpegaudenc->context)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
|
ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
|
||||||
|
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
@ -683,7 +662,7 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
|
|||||||
|
|
||||||
ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
||||||
|
|
||||||
if (G_UNLIKELY (!ffmpegaudenc->opened))
|
if (G_UNLIKELY (!ffmpegaudenc->context))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (!inbuf)
|
if (!inbuf)
|
||||||
@ -752,7 +731,7 @@ gst_ffmpegaudenc_set_property (GObject * object,
|
|||||||
|
|
||||||
ffmpegaudenc = (GstFFMpegAudEnc *) (object);
|
ffmpegaudenc = (GstFFMpegAudEnc *) (object);
|
||||||
|
|
||||||
if (ffmpegaudenc->opened) {
|
if (ffmpegaudenc->context) {
|
||||||
GST_WARNING_OBJECT (ffmpegaudenc,
|
GST_WARNING_OBJECT (ffmpegaudenc,
|
||||||
"Can't change properties once encoder is setup !");
|
"Can't change properties once encoder is setup !");
|
||||||
return;
|
return;
|
||||||
|
@ -38,7 +38,6 @@ struct _GstFFMpegAudEnc
|
|||||||
|
|
||||||
AVCodecContext *context;
|
AVCodecContext *context;
|
||||||
AVCodecContext *refcontext;
|
AVCodecContext *refcontext;
|
||||||
gboolean opened;
|
|
||||||
gboolean need_reopen;
|
gboolean need_reopen;
|
||||||
|
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
|
@ -488,10 +488,8 @@ gst_ffmpeg_cfg_install_properties (GObjectClass * klass, AVCodec * in_plugin,
|
|||||||
install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, flags,
|
install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, flags,
|
||||||
" (Generic codec option, might have no effect)", generic_overrides);
|
" (Generic codec option, might have no effect)", generic_overrides);
|
||||||
|
|
||||||
if (ctx) {
|
if (ctx)
|
||||||
gst_ffmpeg_avcodec_close (ctx);
|
avcodec_free_context (&ctx);
|
||||||
av_free (ctx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
|
@ -225,14 +225,13 @@ gst_ffmpegdeinterlace_sink_setcaps (GstPad * pad, GstObject * parent,
|
|||||||
ctx->pix_fmt = AV_PIX_FMT_NB;
|
ctx->pix_fmt = AV_PIX_FMT_NB;
|
||||||
gst_ffmpeg_caps_with_codectype (AVMEDIA_TYPE_VIDEO, caps, ctx);
|
gst_ffmpeg_caps_with_codectype (AVMEDIA_TYPE_VIDEO, caps, ctx);
|
||||||
if (ctx->pix_fmt == AV_PIX_FMT_NB) {
|
if (ctx->pix_fmt == AV_PIX_FMT_NB) {
|
||||||
gst_ffmpeg_avcodec_close (ctx);
|
avcodec_free_context (&ctx);
|
||||||
av_free (ctx);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
deinterlace->pixfmt = ctx->pix_fmt;
|
deinterlace->pixfmt = ctx->pix_fmt;
|
||||||
|
|
||||||
av_free (ctx);
|
avcodec_free_context (&ctx);
|
||||||
|
|
||||||
deinterlace->to_size =
|
deinterlace->to_size =
|
||||||
av_image_get_buffer_size (deinterlace->pixfmt, deinterlace->width,
|
av_image_get_buffer_size (deinterlace->pixfmt, deinterlace->width,
|
||||||
|
@ -337,14 +337,7 @@ gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec)
|
|||||||
static void
|
static void
|
||||||
gst_ffmpegviddec_subinit (GstFFMpegVidDec * ffmpegdec)
|
gst_ffmpegviddec_subinit (GstFFMpegVidDec * ffmpegdec)
|
||||||
{
|
{
|
||||||
GstFFMpegVidDecClass *klass =
|
|
||||||
(GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec);
|
|
||||||
|
|
||||||
/* some ffmpeg data */
|
/* some ffmpeg data */
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin);
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
ffmpegdec->picture = av_frame_alloc ();
|
|
||||||
ffmpegdec->opened = FALSE;
|
|
||||||
ffmpegdec->skip_frame = ffmpegdec->lowres = 0;
|
ffmpegdec->skip_frame = ffmpegdec->lowres = 0;
|
||||||
ffmpegdec->direct_rendering = DEFAULT_DIRECT_RENDERING;
|
ffmpegdec->direct_rendering = DEFAULT_DIRECT_RENDERING;
|
||||||
ffmpegdec->max_threads = DEFAULT_MAX_THREADS;
|
ffmpegdec->max_threads = DEFAULT_MAX_THREADS;
|
||||||
@ -365,6 +358,8 @@ gst_ffmpegviddec_finalize (GObject * object)
|
|||||||
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
|
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
|
||||||
|
|
||||||
av_frame_free (&ffmpegdec->picture);
|
av_frame_free (&ffmpegdec->picture);
|
||||||
|
if (ffmpegdec->context)
|
||||||
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
avcodec_free_context (&ffmpegdec->context);
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
@ -395,37 +390,23 @@ gst_ffmpegviddec_context_set_flags2 (AVCodecContext * context, guint flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* with LOCK */
|
/* with LOCK */
|
||||||
static gboolean
|
static void
|
||||||
gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec, gboolean reset)
|
gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec)
|
||||||
{
|
{
|
||||||
GstFFMpegVidDecClass *oclass;
|
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec");
|
GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec");
|
||||||
|
|
||||||
gst_caps_replace (&ffmpegdec->last_caps, NULL);
|
gst_caps_replace (&ffmpegdec->last_caps, NULL);
|
||||||
|
|
||||||
gst_ffmpeg_avcodec_close (ffmpegdec->context);
|
if (ffmpegdec->context)
|
||||||
ffmpegdec->opened = FALSE;
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
|
for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
|
||||||
ffmpegdec->stride[i] = -1;
|
ffmpegdec->stride[i] = -1;
|
||||||
|
|
||||||
gst_buffer_replace (&ffmpegdec->palette, NULL);
|
gst_buffer_replace (&ffmpegdec->palette, NULL);
|
||||||
|
|
||||||
av_freep (&ffmpegdec->context->extradata);
|
|
||||||
if (reset) {
|
|
||||||
avcodec_free_context (&ffmpegdec->context);
|
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegdec->context == NULL) {
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* with LOCK */
|
/* with LOCK */
|
||||||
@ -443,8 +424,6 @@ gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec)
|
|||||||
for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
|
for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
|
||||||
ffmpegdec->stride[i] = -1;
|
ffmpegdec->stride[i] = -1;
|
||||||
|
|
||||||
ffmpegdec->opened = TRUE;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d",
|
GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d",
|
||||||
oclass->in_plugin->name, oclass->in_plugin->id);
|
oclass->in_plugin->name, oclass->in_plugin->id);
|
||||||
|
|
||||||
@ -460,7 +439,7 @@ gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec)
|
|||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
could_not_open:
|
could_not_open:
|
||||||
{
|
{
|
||||||
gst_ffmpegviddec_close (ffmpegdec, TRUE);
|
gst_ffmpegviddec_close (ffmpegdec);
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec",
|
GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec",
|
||||||
oclass->in_plugin->name);
|
oclass->in_plugin->name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -537,14 +516,11 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
if (ffmpegdec->opened) {
|
if (ffmpegdec->context) {
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
gst_ffmpegviddec_finish (decoder);
|
gst_ffmpegviddec_finish (decoder);
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
if (!gst_ffmpegviddec_close (ffmpegdec, TRUE)) {
|
gst_ffmpegviddec_close (ffmpegdec);
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ffmpegdec->pic_pix_fmt = 0;
|
ffmpegdec->pic_pix_fmt = 0;
|
||||||
ffmpegdec->pic_width = 0;
|
ffmpegdec->pic_width = 0;
|
||||||
ffmpegdec->pic_height = 0;
|
ffmpegdec->pic_height = 0;
|
||||||
@ -560,6 +536,14 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
|||||||
ffmpegdec->cur_multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
|
ffmpegdec->cur_multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
||||||
|
if (ffmpegdec->context == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "Failed to allocate context");
|
||||||
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ffmpegdec->context->opaque = ffmpegdec;
|
||||||
|
|
||||||
gst_caps_replace (&ffmpegdec->last_caps, state->caps);
|
gst_caps_replace (&ffmpegdec->last_caps, state->caps);
|
||||||
|
|
||||||
/* set buffer functions */
|
/* set buffer functions */
|
||||||
@ -718,12 +702,18 @@ done:
|
|||||||
open_failed:
|
open_failed:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Failed to open");
|
GST_DEBUG_OBJECT (ffmpegdec, "Failed to open");
|
||||||
|
if (ffmpegdec->context)
|
||||||
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
nal_only_slice:
|
nal_only_slice:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (ffmpegdec,
|
GST_ERROR_OBJECT (ffmpegdec,
|
||||||
"Can't do NAL aligned H.264 with frame threading.");
|
"Can't do NAL aligned H.264 with frame threading.");
|
||||||
|
if (ffmpegdec->context)
|
||||||
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1848,7 +1838,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
|
|||||||
GstFFMpegVidDecVideoFrame *out_dframe;
|
GstFFMpegVidDecVideoFrame *out_dframe;
|
||||||
GstBufferPool *pool;
|
GstBufferPool *pool;
|
||||||
|
|
||||||
if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
|
if (G_UNLIKELY (!ffmpegdec->context))
|
||||||
goto no_codec;
|
goto no_codec;
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_MAJOR >= 60
|
#if LIBAVCODEC_VERSION_MAJOR >= 60
|
||||||
@ -2141,7 +2131,7 @@ gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
|
|||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gboolean got_frame = FALSE;
|
gboolean got_frame = FALSE;
|
||||||
|
|
||||||
if (!ffmpegdec->opened)
|
if (!ffmpegdec->context)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
|
||||||
@ -2187,6 +2177,12 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
|
|||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
AVPacket *packet;
|
AVPacket *packet;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!ffmpegdec->context)) {
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
GST_ERROR_OBJECT (ffmpegdec, "no codec context");
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegdec,
|
GST_LOG_OBJECT (ffmpegdec,
|
||||||
"Received new data of size %" G_GSIZE_FORMAT ", dts %" GST_TIME_FORMAT
|
"Received new data of size %" G_GSIZE_FORMAT ", dts %" GST_TIME_FORMAT
|
||||||
", pts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT,
|
", pts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT,
|
||||||
@ -2196,6 +2192,7 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
|
|||||||
if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) {
|
if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) {
|
||||||
GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, ("Decoding problem"),
|
GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, ("Decoding problem"),
|
||||||
("Failed to map buffer for reading"));
|
("Failed to map buffer for reading"));
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2304,19 +2301,13 @@ static gboolean
|
|||||||
gst_ffmpegviddec_start (GstVideoDecoder * decoder)
|
gst_ffmpegviddec_start (GstVideoDecoder * decoder)
|
||||||
{
|
{
|
||||||
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
||||||
GstFFMpegVidDecClass *oclass;
|
|
||||||
|
|
||||||
oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
|
av_frame_free (&ffmpegdec->picture);
|
||||||
|
if (ffmpegdec->context)
|
||||||
|
av_freep (&ffmpegdec->context->extradata);
|
||||||
avcodec_free_context (&ffmpegdec->context);
|
avcodec_free_context (&ffmpegdec->context);
|
||||||
ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
|
ffmpegdec->picture = av_frame_alloc ();
|
||||||
if (ffmpegdec->context == NULL) {
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
|
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2328,7 +2319,8 @@ gst_ffmpegviddec_stop (GstVideoDecoder * decoder)
|
|||||||
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (ffmpegdec);
|
GST_OBJECT_LOCK (ffmpegdec);
|
||||||
gst_ffmpegviddec_close (ffmpegdec, FALSE);
|
av_frame_free (&ffmpegdec->picture);
|
||||||
|
gst_ffmpegviddec_close (ffmpegdec);
|
||||||
GST_OBJECT_UNLOCK (ffmpegdec);
|
GST_OBJECT_UNLOCK (ffmpegdec);
|
||||||
g_free (ffmpegdec->padded);
|
g_free (ffmpegdec->padded);
|
||||||
ffmpegdec->padded = NULL;
|
ffmpegdec->padded = NULL;
|
||||||
@ -2382,7 +2374,7 @@ gst_ffmpegviddec_flush (GstVideoDecoder * decoder)
|
|||||||
{
|
{
|
||||||
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
|
||||||
|
|
||||||
if (ffmpegdec->opened) {
|
if (ffmpegdec->context) {
|
||||||
GST_LOG_OBJECT (decoder, "flushing buffers");
|
GST_LOG_OBJECT (decoder, "flushing buffers");
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
|
||||||
avcodec_flush_buffers (ffmpegdec->context);
|
avcodec_flush_buffers (ffmpegdec->context);
|
||||||
@ -2571,11 +2563,10 @@ gst_ffmpegviddec_set_property (GObject * object,
|
|||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_LOWRES:
|
case PROP_LOWRES:
|
||||||
ffmpegdec->lowres = ffmpegdec->context->lowres = g_value_get_enum (value);
|
ffmpegdec->lowres = g_value_get_enum (value);
|
||||||
break;
|
break;
|
||||||
case PROP_SKIPFRAME:
|
case PROP_SKIPFRAME:
|
||||||
ffmpegdec->skip_frame = ffmpegdec->context->skip_frame =
|
ffmpegdec->skip_frame = g_value_get_enum (value);
|
||||||
g_value_get_enum (value);
|
|
||||||
break;
|
break;
|
||||||
case PROP_DIRECT_RENDERING:
|
case PROP_DIRECT_RENDERING:
|
||||||
ffmpegdec->direct_rendering = g_value_get_boolean (value);
|
ffmpegdec->direct_rendering = g_value_get_boolean (value);
|
||||||
|
@ -54,7 +54,6 @@ struct _GstFFMpegVidDec
|
|||||||
GstVideoMultiviewMode picture_multiview_mode;
|
GstVideoMultiviewMode picture_multiview_mode;
|
||||||
GstVideoMultiviewFlags picture_multiview_flags;
|
GstVideoMultiviewFlags picture_multiview_flags;
|
||||||
gint stride[AV_NUM_DATA_POINTERS];
|
gint stride[AV_NUM_DATA_POINTERS];
|
||||||
gboolean opened;
|
|
||||||
|
|
||||||
/* current output pictures */
|
/* current output pictures */
|
||||||
enum AVPixelFormat pic_pix_fmt;
|
enum AVPixelFormat pic_pix_fmt;
|
||||||
|
@ -208,10 +208,7 @@ gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc)
|
|||||||
|
|
||||||
GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (ffmpegenc));
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (ffmpegenc));
|
||||||
|
|
||||||
ffmpegenc->context = avcodec_alloc_context3 (klass->in_plugin);
|
|
||||||
ffmpegenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
|
ffmpegenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
|
||||||
ffmpegenc->picture = av_frame_alloc ();
|
|
||||||
ffmpegenc->opened = FALSE;
|
|
||||||
ffmpegenc->file = NULL;
|
ffmpegenc->file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,10 +219,8 @@ gst_ffmpegvidenc_finalize (GObject * object)
|
|||||||
|
|
||||||
/* clean up remaining allocated data */
|
/* clean up remaining allocated data */
|
||||||
av_frame_free (&ffmpegenc->picture);
|
av_frame_free (&ffmpegenc->picture);
|
||||||
gst_ffmpeg_avcodec_close (ffmpegenc->context);
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
gst_ffmpeg_avcodec_close (ffmpegenc->refcontext);
|
avcodec_free_context (&ffmpegenc->refcontext);
|
||||||
av_freep (&ffmpegenc->context);
|
|
||||||
av_freep (&ffmpegenc->refcontext);
|
|
||||||
g_free (ffmpegenc->filename);
|
g_free (ffmpegenc->filename);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
@ -247,14 +242,11 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
|
|||||||
ffmpegenc->need_reopen = FALSE;
|
ffmpegenc->need_reopen = FALSE;
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
if (ffmpegenc->opened) {
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
avcodec_free_context (&ffmpegenc->context);
|
ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
||||||
ffmpegenc->opened = FALSE;
|
if (ffmpegenc->context == NULL) {
|
||||||
ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
GST_DEBUG_OBJECT (ffmpegenc, "Failed to allocate context");
|
||||||
if (ffmpegenc->context == NULL) {
|
return FALSE;
|
||||||
GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* additional avcodec settings */
|
/* additional avcodec settings */
|
||||||
@ -402,7 +394,6 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
|
|||||||
|
|
||||||
/* success! */
|
/* success! */
|
||||||
ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
|
ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
|
||||||
ffmpegenc->opened = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -412,6 +403,7 @@ open_file_err:
|
|||||||
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, OPEN_WRITE,
|
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, OPEN_WRITE,
|
||||||
(("Could not open file \"%s\" for writing."), ffmpegenc->filename),
|
(("Could not open file \"%s\" for writing."), ffmpegenc->filename),
|
||||||
GST_ERROR_SYSTEM);
|
GST_ERROR_SYSTEM);
|
||||||
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
file_read_err:
|
file_read_err:
|
||||||
@ -419,6 +411,7 @@ file_read_err:
|
|||||||
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, READ,
|
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, READ,
|
||||||
(("Could not get contents of file \"%s\"."), ffmpegenc->filename),
|
(("Could not get contents of file \"%s\"."), ffmpegenc->filename),
|
||||||
GST_ERROR_SYSTEM);
|
GST_ERROR_SYSTEM);
|
||||||
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,12 +419,12 @@ insane_timebase:
|
|||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (ffmpegenc, "Rejecting time base %d/%d",
|
GST_ERROR_OBJECT (ffmpegenc, "Rejecting time base %d/%d",
|
||||||
ffmpegenc->context->time_base.den, ffmpegenc->context->time_base.num);
|
ffmpegenc->context->time_base.den, ffmpegenc->context->time_base.num);
|
||||||
goto cleanup_stats_in;
|
goto close_codec;
|
||||||
}
|
}
|
||||||
unsupported_codec:
|
unsupported_codec:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("Unsupported codec - no caps found");
|
GST_DEBUG ("Unsupported codec - no caps found");
|
||||||
goto cleanup_stats_in;
|
goto close_codec;
|
||||||
}
|
}
|
||||||
open_codec_fail:
|
open_codec_fail:
|
||||||
{
|
{
|
||||||
@ -456,15 +449,13 @@ bad_input_fmt:
|
|||||||
}
|
}
|
||||||
close_codec:
|
close_codec:
|
||||||
{
|
{
|
||||||
|
if (ffmpegenc->context)
|
||||||
|
g_free (ffmpegenc->context->stats_in);
|
||||||
|
if (ffmpegenc->file) {
|
||||||
|
fclose (ffmpegenc->file);
|
||||||
|
ffmpegenc->file = NULL;
|
||||||
|
}
|
||||||
avcodec_free_context (&ffmpegenc->context);
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
|
||||||
if (ffmpegenc->context == NULL)
|
|
||||||
GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
|
|
||||||
goto cleanup_stats_in;
|
|
||||||
}
|
|
||||||
cleanup_stats_in:
|
|
||||||
{
|
|
||||||
g_free (ffmpegenc->context->stats_in);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,8 +474,7 @@ gst_ffmpegvidenc_propose_allocation (GstVideoEncoder * encoder,
|
|||||||
static void
|
static void
|
||||||
gst_ffmpegvidenc_free_avpacket (gpointer pkt)
|
gst_ffmpegvidenc_free_avpacket (gpointer pkt)
|
||||||
{
|
{
|
||||||
av_packet_unref ((AVPacket *) pkt);
|
av_packet_free ((AVPacket **) & pkt);
|
||||||
g_free (pkt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -692,18 +682,18 @@ gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc,
|
|||||||
|
|
||||||
*got_packet = FALSE;
|
*got_packet = FALSE;
|
||||||
|
|
||||||
pkt = g_new0 (AVPacket, 1);
|
pkt = av_packet_alloc ();
|
||||||
|
|
||||||
res = avcodec_receive_packet (ffmpegenc->context, pkt);
|
res = avcodec_receive_packet (ffmpegenc->context, pkt);
|
||||||
|
|
||||||
if (res == AVERROR (EAGAIN)) {
|
if (res == AVERROR (EAGAIN)) {
|
||||||
g_free (pkt);
|
av_packet_free (&pkt);
|
||||||
goto done;
|
goto done;
|
||||||
} else if (res == AVERROR_EOF) {
|
} else if (res == AVERROR_EOF) {
|
||||||
g_free (pkt);
|
av_packet_free (&pkt);
|
||||||
ret = GST_FLOW_EOS;
|
ret = GST_FLOW_EOS;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (res < 0) {
|
} else if (res < 0) {
|
||||||
|
av_packet_free (&pkt);
|
||||||
ret = GST_FLOW_ERROR;
|
ret = GST_FLOW_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -767,7 +757,7 @@ gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
|
|||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
gboolean got_packet;
|
gboolean got_packet;
|
||||||
|
|
||||||
/* endoder was drained or flushed, and ffmpeg encoder doesn't support
|
/* encoder was drained or flushed, and ffmpeg encoder doesn't support
|
||||||
* flushing. We need to re-open encoder then */
|
* flushing. We need to re-open encoder then */
|
||||||
if (ffmpegenc->need_reopen) {
|
if (ffmpegenc->need_reopen) {
|
||||||
gboolean reopen_ret;
|
gboolean reopen_ret;
|
||||||
@ -778,6 +768,7 @@ gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
|
|||||||
if (!ffmpegenc->input_state) {
|
if (!ffmpegenc->input_state) {
|
||||||
GST_ERROR_OBJECT (ffmpegenc,
|
GST_ERROR_OBJECT (ffmpegenc,
|
||||||
"Cannot re-open encoder without input state");
|
"Cannot re-open encoder without input state");
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,6 +778,7 @@ gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
|
|||||||
|
|
||||||
if (!reopen_ret) {
|
if (!reopen_ret) {
|
||||||
GST_ERROR_OBJECT (ffmpegenc, "Couldn't re-open encoder");
|
GST_ERROR_OBJECT (ffmpegenc, "Couldn't re-open encoder");
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,7 +823,7 @@ gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
|
|||||||
GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send);
|
GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send);
|
||||||
|
|
||||||
/* no need to empty codec if there is none */
|
/* no need to empty codec if there is none */
|
||||||
if (!ffmpegenc->opened)
|
if (!ffmpegenc->context)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
ret = gst_ffmpegvidenc_send_frame (ffmpegenc, NULL);
|
ret = gst_ffmpegvidenc_send_frame (ffmpegenc, NULL);
|
||||||
@ -867,7 +859,7 @@ gst_ffmpegvidenc_set_property (GObject * object,
|
|||||||
|
|
||||||
ffmpegenc = (GstFFMpegVidEnc *) (object);
|
ffmpegenc = (GstFFMpegVidEnc *) (object);
|
||||||
|
|
||||||
if (ffmpegenc->opened) {
|
if (ffmpegenc->context) {
|
||||||
GST_WARNING_OBJECT (ffmpegenc,
|
GST_WARNING_OBJECT (ffmpegenc,
|
||||||
"Can't change properties once decoder is setup !");
|
"Can't change properties once decoder is setup !");
|
||||||
return;
|
return;
|
||||||
@ -921,7 +913,7 @@ gst_ffmpegvidenc_flush (GstVideoEncoder * encoder)
|
|||||||
{
|
{
|
||||||
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
||||||
|
|
||||||
if (ffmpegenc->opened) {
|
if (ffmpegenc->context) {
|
||||||
avcodec_flush_buffers (ffmpegenc->context);
|
avcodec_flush_buffers (ffmpegenc->context);
|
||||||
ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
|
ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
@ -933,20 +925,19 @@ static gboolean
|
|||||||
gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
|
gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
|
||||||
{
|
{
|
||||||
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
||||||
GstFFMpegVidEncClass *oclass =
|
|
||||||
(GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
|
|
||||||
|
|
||||||
ffmpegenc->opened = FALSE;
|
|
||||||
ffmpegenc->need_reopen = FALSE;
|
|
||||||
|
|
||||||
/* close old session */
|
/* close old session */
|
||||||
avcodec_free_context (&ffmpegenc->context);
|
if (ffmpegenc->file) {
|
||||||
ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
|
fclose (ffmpegenc->file);
|
||||||
if (ffmpegenc->context == NULL) {
|
ffmpegenc->file = NULL;
|
||||||
GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
if (ffmpegenc->context)
|
||||||
|
g_free (ffmpegenc->context->stats_in);
|
||||||
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
|
av_frame_free (&ffmpegenc->picture);
|
||||||
|
ffmpegenc->need_reopen = FALSE;
|
||||||
|
|
||||||
|
ffmpegenc->picture = av_frame_alloc ();
|
||||||
gst_video_encoder_set_min_pts (encoder, GST_SECOND * 60 * 60 * 1000);
|
gst_video_encoder_set_min_pts (encoder, GST_SECOND * 60 * 60 * 1000);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -958,8 +949,14 @@ gst_ffmpegvidenc_stop (GstVideoEncoder * encoder)
|
|||||||
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
|
||||||
|
|
||||||
gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE);
|
gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE);
|
||||||
gst_ffmpeg_avcodec_close (ffmpegenc->context);
|
if (ffmpegenc->context)
|
||||||
ffmpegenc->opened = FALSE;
|
g_free (ffmpegenc->context->stats_in);
|
||||||
|
if (ffmpegenc->file) {
|
||||||
|
fclose (ffmpegenc->file);
|
||||||
|
ffmpegenc->file = NULL;
|
||||||
|
}
|
||||||
|
avcodec_free_context (&ffmpegenc->context);
|
||||||
|
av_frame_free (&ffmpegenc->picture);
|
||||||
ffmpegenc->need_reopen = FALSE;
|
ffmpegenc->need_reopen = FALSE;
|
||||||
|
|
||||||
if (ffmpegenc->input_state) {
|
if (ffmpegenc->input_state) {
|
||||||
|
@ -41,7 +41,6 @@ struct _GstFFMpegVidEnc
|
|||||||
AVCodecContext *context;
|
AVCodecContext *context;
|
||||||
AVFrame *picture;
|
AVFrame *picture;
|
||||||
GstClockTime pts_offset;
|
GstClockTime pts_offset;
|
||||||
gboolean opened;
|
|
||||||
gboolean need_reopen;
|
gboolean need_reopen;
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
guint pass;
|
guint pass;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user