...
 
Commits (29)
include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"
include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/1.16/gitlab/ci_template.yml"
This diff is collapsed.
This diff is collapsed.
This is GStreamer gst-libav 1.16.0.
This is GStreamer gst-libav 1.16.3.
The GStreamer team is thrilled to announce a new major feature release in the
stable 1.0 API series of your favourite cross-platform multimedia framework!
As always, this release is again packed with new features, bug fixes and
other improvements.
The GStreamer team is pleased to announce another bug-fix release in the
stable 1.x API series of your favourite cross-platform multimedia framework!
The 1.16 release series adds new features on top of the 1.14 series and is
part of the API and ABI-stable 1.x release series of the GStreamer multimedia
framework.
Full release notes will one day be found at:
Full release notes can be found at:
https://gstreamer.freedesktop.org/releases/1.16/
......@@ -60,7 +57,7 @@ You can find source releases of gstreamer in the download
directory: https://gstreamer.freedesktop.org/src/gstreamer/
The git repository and details how to clone it can be found at
https://cgit.freedesktop.org/gstreamer/gstreamer/
https://gitlab.freedesktop.org/gstreamer/
==== Homepage ====
......
Subproject commit 59cb678164719ff59dcf6c8b93df4617a1075d11
Subproject commit a825d2773adaeec23369d0770098b2c44ca7377a
......@@ -3,7 +3,7 @@ AC_PREREQ(2.69)
dnl initialize autoconf
dnl when going to/from release please set the nano (fourth number) right !
dnl releases only do Wall, cvs and prerelease does Werror too
AC_INIT(GStreamer libav, 1.16.0,
AC_INIT(GStreamer libav, 1.16.3,
http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer,
gst-libav)
......@@ -42,11 +42,11 @@ AC_SUBST(GST_API_VERSION)
dnl *** Check for external $AS vs detected by AS_LIBTOOL
orig_AS="$AS"
AG_GST_LIBTOOL_PREPARE
AS_LIBTOOL(GST, 1600, 0, 1600)
AS_LIBTOOL(GST, 1603, 0, 1603)
dnl *** required versions of GStreamer stuff ***
GST_REQ=1.16.0
GST_PBREQ=1.16.0
GST_REQ=1.16.3
GST_PBREQ=1.16.3
ORC_REQ=0.4.16
ORC_CHECK([$ORC_REQ])
......@@ -375,7 +375,7 @@ else
case $host_os in
mingw32*)
WIN32_LIBS="-lws2_32"
WIN32_LIBS="-lws2_32 -lbcrypt"
;;
*)
WIN32_LIBS=
......
......@@ -32,9 +32,4 @@
<title>gst-libav Plugins</title>
<xi:include href="xml/plugin-libav.xml" />
</chapter>
<chapter>
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml" />
</chapter>
</book>
......@@ -3,7 +3,7 @@
<description>All libav codecs and formats (local snapshot)</description>
<filename>../../ext/libav/.libs/libgstlibav.so</filename>
<basename>libgstlibav.so</basename>
<version>1.16.0</version>
<version>1.16.3</version>
<license>LGPL</license>
<source>gst-libav</source>
<package>GStreamer libav source release</package>
......
......@@ -48,7 +48,7 @@ static GMutex gst_avcodec_mutex;
static inline gboolean
gst_ffmpeg_avcodec_is_ffmpeg (void)
{
guint av_version = avutil_version ();
guint av_version = avcodec_version ();
GST_DEBUG ("Using libavcodec version %d.%d.%d",
av_version >> 16, (av_version & 0x00ff00) >> 8, av_version & 0xff);
......
......@@ -57,7 +57,7 @@ static GstFlowReturn gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder,
static gboolean gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
AVCodecContext * context, AVFrame * frame, gboolean force);
static void gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec);
static GstFlowReturn gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec);
#define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("avdec-params")
......@@ -594,38 +594,45 @@ no_codec:
}
}
static void
static GstFlowReturn
gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec)
{
GstFFMpegAudDecClass *oclass;
GstFlowReturn ret = GST_FLOW_OK;
gboolean got_any_frames = FALSE;
gboolean got_frame;
oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
if (oclass->in_plugin->capabilities & AV_CODEC_CAP_DELAY) {
gboolean got_frame;
GST_LOG_OBJECT (ffmpegdec,
"codec has delay capabilities, calling until libav has drained everything");
if (avcodec_send_packet (ffmpegdec->context, NULL))
goto send_packet_failed;
if (avcodec_send_packet (ffmpegdec->context, NULL))
goto send_packet_failed;
do {
GstFlowReturn ret;
do {
got_frame = gst_ffmpegauddec_frame (ffmpegdec, &ret);
if (got_frame)
got_any_frames = TRUE;
} while (got_frame);
avcodec_flush_buffers (ffmpegdec->context);
/* FFMpeg will return AVERROR_EOF if it's internal was fully drained
* then we are translating it to GST_FLOW_EOS. However, because this behavior
* is fully internal stuff of this implementation and gstaudiodecoder
* baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
* convert this flow returned here */
if (ret == GST_FLOW_EOS)
ret = GST_FLOW_OK;
if (got_any_frames) {
GstFlowReturn new_ret =
gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), NULL, 1);
got_frame = gst_ffmpegauddec_frame (ffmpegdec, &ret);
if (got_frame)
got_any_frames = TRUE;
} while (got_frame);
avcodec_flush_buffers (ffmpegdec->context);
if (ret == GST_FLOW_OK)
ret = new_ret;
}
if (got_any_frames)
gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), NULL, 1);
done:
return ret;
send_packet_failed:
GST_WARNING_OBJECT (ffmpegdec, "send packet failed, could not drain decoder");
goto done;
}
static void
......@@ -658,8 +665,7 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
goto not_negotiated;
if (inbuf == NULL) {
gst_ffmpegauddec_drain (ffmpegdec);
return GST_FLOW_OK;
return gst_ffmpegauddec_drain (ffmpegdec);
}
inbuf = gst_buffer_ref (inbuf);
......@@ -708,7 +714,7 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
gst_avpacket_init (&packet, data, size);
if (!packet.size)
goto done;
goto unmap;
if (avcodec_send_packet (ffmpegdec->context, &packet) < 0) {
goto send_packet_failed;
......@@ -729,14 +735,25 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
}
} while (got_frame);
gst_buffer_unmap (inbuf, &map);
gst_buffer_unref (inbuf);
if (is_header || got_any_frames) {
ret =
/* Even if previous return wasn't GST_FLOW_OK, we need to call
* _finish_frame() since baseclass is expecting that _finish_frame()
* is followed by _finish_subframe()
*/
GstFlowReturn new_ret =
gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), NULL, 1);
/* Only override the flow return value if previously did have a GST_FLOW_OK.
* Failure to do this would result in skipping downstream issues caught in
* earlier steps. */
if (ret == GST_FLOW_OK)
ret = new_ret;
}
unmap:
gst_buffer_unmap (inbuf, &map);
gst_buffer_unref (inbuf);
done:
return ret;
......@@ -754,7 +771,7 @@ not_negotiated:
send_packet_failed:
{
GST_WARNING_OBJECT (ffmpegdec, "decoding error");
goto done;
goto unmap;
}
}
......
......@@ -189,6 +189,9 @@ gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
GstFFMpegAudEncClass *oclass =
(GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
ffmpegaudenc->opened = FALSE;
ffmpegaudenc->need_reopen = FALSE;
gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
oclass->in_plugin) < 0) {
......@@ -207,6 +210,7 @@ gst_ffmpegaudenc_stop (GstAudioEncoder * encoder)
/* close old session */
gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
ffmpegaudenc->opened = FALSE;
ffmpegaudenc->need_reopen = FALSE;
return TRUE;
}
......@@ -232,6 +236,8 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
GstFFMpegAudEncClass *oclass =
(GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
ffmpegaudenc->need_reopen = FALSE;
/* close old session */
if (ffmpegaudenc->opened) {
gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
......@@ -367,6 +373,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
/* success! */
ffmpegaudenc->opened = TRUE;
ffmpegaudenc->need_reopen = FALSE;
return TRUE;
}
......@@ -529,9 +536,21 @@ gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
av_frame_unref (frame);
} else {
GstFFMpegAudEncClass *oclass =
(GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
GST_LOG_OBJECT (ffmpegaudenc, "draining");
/* flushing the encoder */
res = avcodec_send_frame (ctx, NULL);
/* If AV_CODEC_CAP_ENCODER_FLUSH wasn't set, we need to re-open
* encoder */
if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)) {
GST_DEBUG_OBJECT (ffmpegaudenc, "Encoder needs reopen later");
/* we will reopen later handle_frame() */
ffmpegaudenc->need_reopen = TRUE;
}
}
if (res == 0) {
......@@ -603,8 +622,17 @@ gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
} while (got_packet);
}
/* NOTE: this may or may not work depending on capability */
avcodec_flush_buffers (ffmpegaudenc->context);
/* FFMpeg will return AVERROR_EOF if it's internal was fully drained
* then we are translating it to GST_FLOW_EOS. However, because this behavior
* is fully internal stuff of this implementation and gstaudioencoder
* baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
* convert this flow returned here */
if (ret == GST_FLOW_EOS)
ret = GST_FLOW_OK;
return ret;
}
......@@ -623,6 +651,18 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
if (!inbuf)
return gst_ffmpegaudenc_drain (ffmpegaudenc);
/* endoder was drained or flushed, and ffmpeg encoder doesn't support
* flushing. We need to re-open encoder then */
if (ffmpegaudenc->need_reopen) {
GST_DEBUG_OBJECT (ffmpegaudenc, "Open encoder again");
if (!gst_ffmpegaudenc_set_format (encoder,
gst_audio_encoder_get_audio_info (encoder))) {
GST_ERROR_OBJECT (ffmpegaudenc, "Couldn't re-open encoder");
return GST_FLOW_NOT_NEGOTIATED;
}
}
inbuf = gst_buffer_ref (inbuf);
GST_DEBUG_OBJECT (ffmpegaudenc,
......
......@@ -39,6 +39,7 @@ struct _GstFFMpegAudEnc
AVCodecContext *context;
AVCodecContext *refcontext;
gboolean opened;
gboolean need_reopen;
AVFrame *frame;
......
......@@ -1994,9 +1994,14 @@ gst_ffmpegdemux_register (GstPlugin * plugin)
in_plugin->name, in_plugin->long_name);
/* no emulators */
if (!strncmp (in_plugin->long_name, "raw ", 4) ||
!strncmp (in_plugin->long_name, "pcm ", 4) ||
!strcmp (in_plugin->name, "audio_device") ||
if (in_plugin->long_name != NULL) {
if (!strncmp (in_plugin->long_name, "raw ", 4) ||
!strncmp (in_plugin->long_name, "pcm ", 4)
)
continue;
}
if (!strcmp (in_plugin->name, "audio_device") ||
!strncmp (in_plugin->name, "image", 5) ||
!strcmp (in_plugin->name, "mpegvideo") ||
!strcmp (in_plugin->name, "mjpeg") ||
......
......@@ -29,6 +29,26 @@
#include <gst/gst.h>
/* Introduced since ffmpeg version 4.3
*
* Note: Not all ffmpeg encoders seem to be reusable after flushing/draining.
* So if ffmpeg encoder doesn't support it, we should reopen encoding session.
*
* Before ffmpeg 4.3, avcodec_flush_buffers() was implemented in
* libavcodec/decodec.c but it was moved to libavcodec/utils.c and it would be
* accepted if encoder supports AV_CODEC_CAP_ENCODER_FLUSH flag.
* That implies that avcodec_flush_buffers() wasn't intended to be working
* properly for encoders.
*/
#ifndef AV_CODEC_CAP_ENCODER_FLUSH
/*
* This encoder can be flushed using avcodec_flush_buffers(). If this flag is
* not set, the encoder must be closed and reopened to ensure that no frames
* remain pending.
*/
#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21)
#endif
/*
*Get the size of an picture
*/
......@@ -79,7 +99,7 @@ gst_ffmpeg_time_gst_to_ff (guint64 time, AVRational base)
return out;
}
void
void
gst_ffmpeg_init_pix_fmt_info(void);
int
......
......@@ -494,7 +494,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
if (ffmpegdec->max_threads == 0) {
if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_AUTO_THREADS))
ffmpegdec->context->thread_count = gst_ffmpeg_auto_max_threads ();
ffmpegdec->context->thread_count =
MIN (gst_ffmpeg_auto_max_threads (), 16);
else
ffmpegdec->context->thread_count = 0;
} else
......@@ -741,6 +742,7 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
GstFFMpegVidDec *ffmpegdec;
guint c;
GstFlowReturn ret;
int create_buffer_flags = 0;
ffmpegdec = (GstFFMpegVidDec *) context->opaque;
......@@ -822,7 +824,16 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
picture->data[c]);
}
picture->buf[0] = av_buffer_create (NULL, 0, dummy_free_buffer, dframe, 0);
if ((flags & AV_GET_BUFFER_FLAG_REF) == AV_GET_BUFFER_FLAG_REF) {
/* decoder might reuse this AVFrame and it would result to no more
* get_buffer() call if the AVFrame's AVBuffer is writable
* (meaning that the refcount of AVBuffer == 1).
* To enforce get_buffer() for the every output frame, set read-only flag here
*/
create_buffer_flags = AV_BUFFER_FLAG_READONLY;
}
picture->buf[0] = av_buffer_create (NULL,
0, dummy_free_buffer, dframe, create_buffer_flags);
GST_LOG_OBJECT (ffmpegdec, "returned frame %p", dframe->buffer);
......@@ -1729,31 +1740,30 @@ static GstFlowReturn
gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
{
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder;
GstFFMpegVidDecClass *oclass;
GstFlowReturn ret = GST_FLOW_OK;
gboolean got_frame = FALSE;
if (!ffmpegdec->opened)
return GST_FLOW_OK;
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
if (oclass->in_plugin->capabilities & AV_CODEC_CAP_DELAY) {
GstFlowReturn ret;
gboolean got_frame = FALSE;
GST_LOG_OBJECT (ffmpegdec,
"codec has delay capabilities, calling until ffmpeg has drained everything");
if (avcodec_send_packet (ffmpegdec->context, NULL))
goto send_packet_failed;
if (avcodec_send_packet (ffmpegdec->context, NULL))
goto send_packet_failed;
do {
got_frame = gst_ffmpegviddec_frame (ffmpegdec, NULL, &ret);
} while (got_frame && ret == GST_FLOW_OK);
avcodec_flush_buffers (ffmpegdec->context);
}
do {
got_frame = gst_ffmpegviddec_frame (ffmpegdec, NULL, &ret);
} while (got_frame && ret == GST_FLOW_OK);
avcodec_flush_buffers (ffmpegdec->context);
/* FFMpeg will return AVERROR_EOF if it's internal was fully drained
* then we are translating it to GST_FLOW_EOS. However, because this behavior
* is fully internal stuff of this implementation and gstvideodecoder
* baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
* convert this flow returned here */
if (ret == GST_FLOW_EOS)
ret = GST_FLOW_OK;
done:
return GST_FLOW_OK;
return ret;
send_packet_failed:
GST_WARNING_OBJECT (ffmpegdec, "send packet failed, could not drain decoder");
......@@ -1931,12 +1941,15 @@ gst_ffmpegviddec_stop (GstVideoDecoder * decoder)
static GstFlowReturn
gst_ffmpegviddec_finish (GstVideoDecoder * decoder)
{
gst_ffmpegviddec_drain (decoder);
GstFlowReturn flow_ret;
flow_ret = gst_ffmpegviddec_drain (decoder);
/* note that finish can and should clean up more drastically,
* but drain is also invoked on e.g. packet loss in GAP handling */
gst_ffmpegviddec_flush (decoder);
return GST_FLOW_OK;
return flow_ret;
}
static gboolean
......
......@@ -240,6 +240,8 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
GstFFMpegVidEncClass *oclass =
(GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
ffmpegenc->need_reopen = FALSE;
/* close old session */
if (ffmpegenc->opened) {
gst_ffmpeg_avcodec_close (ffmpegenc->context);
......@@ -254,6 +256,10 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
/* additional avcodec settings */
gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegenc), ffmpegenc->context);
if (GST_VIDEO_INFO_IS_INTERLACED (&state->info))
ffmpegenc->context->flags |=
AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME;
/* and last but not least the pass; CBR, 2-pass, etc */
ffmpegenc->context->flags |= ffmpegenc->pass;
switch (ffmpegenc->pass) {
......@@ -554,12 +560,14 @@ gst_ffmpegvidenc_send_frame (GstFFMpegVidEnc * ffmpegenc,
gst_ffmpegvidenc_add_cc (frame->input_buffer, picture);
if (ffmpegenc->context->flags & (AV_CODEC_FLAG_INTERLACED_DCT |
AV_CODEC_FLAG_INTERLACED_ME)) {
if (GST_VIDEO_INFO_IS_INTERLACED (&ffmpegenc->input_state->info)) {
picture->interlaced_frame = TRUE;
/* if this is not the case, a filter element should be used to swap fields */
picture->top_field_first =
GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_VIDEO_BUFFER_FLAG_TFF)
|| GST_VIDEO_INFO_FIELD_ORDER (&ffmpegenc->input_state->info) ==
GST_VIDEO_FIELD_ORDER_TOP_FIELD_FIRST;
picture->repeat_pict =
GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_VIDEO_BUFFER_FLAG_RFF);
}
if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
......@@ -610,6 +618,20 @@ gst_ffmpegvidenc_send_frame (GstFFMpegVidEnc * ffmpegenc,
ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base);
send_frame:
if (!picture) {
GstFFMpegVidEncClass *oclass =
(GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
/* If AV_CODEC_CAP_ENCODER_FLUSH wasn't set, we need to re-open
* encoder */
if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)) {
GST_DEBUG_OBJECT (ffmpegenc, "Encoder needs reopen later");
/* we will reopen later handle_frame() */
ffmpegenc->need_reopen = TRUE;
}
}
res = avcodec_send_frame (ffmpegenc->context, picture);
if (picture)
......@@ -647,7 +669,7 @@ gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc,
ret = GST_FLOW_EOS;
goto done;
} else if (res < 0) {
res = GST_FLOW_ERROR;
ret = GST_FLOW_ERROR;
goto done;
}
......@@ -689,6 +711,30 @@ gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
GstFlowReturn ret;
gboolean got_packet;
/* endoder was drained or flushed, and ffmpeg encoder doesn't support
* flushing. We need to re-open encoder then */
if (ffmpegenc->need_reopen) {
gboolean reopen_ret;
GstVideoCodecState *input_state;
GST_DEBUG_OBJECT (ffmpegenc, "Open encoder again");
if (!ffmpegenc->input_state) {
GST_ERROR_OBJECT (ffmpegenc,
"Cannot re-open encoder without input state");
return GST_FLOW_NOT_NEGOTIATED;
}
input_state = gst_video_codec_state_ref (ffmpegenc->input_state);
reopen_ret = gst_ffmpegvidenc_set_format (encoder, input_state);
gst_video_codec_state_unref (input_state);
if (!reopen_ret) {
GST_ERROR_OBJECT (ffmpegenc, "Couldn't re-open encoder");
return GST_FLOW_NOT_NEGOTIATED;
}
}
ret = gst_ffmpegvidenc_send_frame (ffmpegenc, frame);
if (ret != GST_FLOW_OK)
......@@ -742,8 +788,17 @@ gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
if (ret != GST_FLOW_OK)
break;
} while (got_packet);
avcodec_flush_buffers (ffmpegenc->context);
done:
/* FFMpeg will return AVERROR_EOF if it's internal was fully drained
* then we are translating it to GST_FLOW_EOS. However, because this behavior
* is fully internal stuff of this implementation and gstvideoencoder
* baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
* convert this flow returned here */
if (ret == GST_FLOW_EOS)
ret = GST_FLOW_OK;
return ret;
}
......@@ -822,6 +877,9 @@ gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
GstFFMpegVidEncClass *oclass =
(GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
ffmpegenc->opened = FALSE;
ffmpegenc->need_reopen = FALSE;
/* close old session */
gst_ffmpeg_avcodec_close (ffmpegenc->context);
if (avcodec_get_context_defaults3 (ffmpegenc->context, oclass->in_plugin) < 0) {
......@@ -840,6 +898,7 @@ gst_ffmpegvidenc_stop (GstVideoEncoder * encoder)
gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE);
gst_ffmpeg_avcodec_close (ffmpegenc->context);
ffmpegenc->opened = FALSE;
ffmpegenc->need_reopen = FALSE;
if (ffmpegenc->input_state) {
gst_video_codec_state_unref (ffmpegenc->input_state);
......
......@@ -41,6 +41,7 @@ struct _GstFFMpegVidEnc
AVCodecContext *context;
AVFrame *picture;
gboolean opened;
gboolean need_reopen;
gboolean discont;
guint pass;
gfloat quantizer;
......
......@@ -32,6 +32,36 @@ colorspace conversion elements.
</GitRepository>
</repository>
<release>
<Version>
<revision>1.16.3</revision>
<branch>1.16</branch>
<name></name>
<created>2020-10-21</created>
<file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.16.3.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.16.2</revision>
<branch>1.16</branch>
<name></name>
<created>2019-12-03</created>
<file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.16.2.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.16.1</revision>
<branch>1.16</branch>
<name></name>
<created>2019-09-23</created>
<file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.16.1.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.16.0</revision>
......
project('gst-libav', 'c', 'cpp',
version : '1.16.0',
version : '1.16.3',
meson_version : '>= 0.46.0',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized' ])
......