svn commit: r484697 - in head/multimedia/gstreamer1-libav: . files
Jan Beich
jbeich at FreeBSD.org
Sun Nov 11 15:39:44 UTC 2018
Author: jbeich
Date: Sun Nov 11 15:39:42 2018
New Revision: 484697
URL: https://svnweb.freebsd.org/changeset/ports/484697
Log:
multimedia/gstreamer1-libav: unbreak and enable system ffmpeg
PR: 227748
Obtained from: upstream
Security: CVE-2018-7557
Security: CVE-2018-7751
Security: CVE-2018-10001
Security: CVE-2018-12458
Security: CVE-2018-13300
Security: CVE-2018-13302
Security: CVE-2018-14394
Security: CVE-2018-14395
Security: CVE-2018-15822
Added:
head/multimedia/gstreamer1-libav/files/patch-ffmpeg4 (contents, props changed)
Modified:
head/multimedia/gstreamer1-libav/Makefile (contents, props changed)
Modified: head/multimedia/gstreamer1-libav/Makefile
==============================================================================
--- head/multimedia/gstreamer1-libav/Makefile Sun Nov 11 15:38:50 2018 (r484696)
+++ head/multimedia/gstreamer1-libav/Makefile Sun Nov 11 15:39:42 2018 (r484697)
@@ -3,7 +3,7 @@
PORTNAME= gstreamer1-libav
PORTVERSION= 1.14.4
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= multimedia
MASTER_SITES= http://gstreamer.freedesktop.org/src/gst-libav/
DISTNAME= gst-libav-${PORTVERSION}
@@ -29,9 +29,9 @@ INSTALL_TARGET= install-strip
CFLAGS_powerpc64= -mminimal-toc
OPTIONS_DEFINE= FFMPEG
+OPTIONS_DEFAULT=FFMPEG
FFMPEG_DESC?= Use system ffmpeg instead of internal libav
-FFMPEG_BROKEN= fails to build with ffmpeg 4.0, see bug 227748
FFMPEG_LIB_DEPENDS= libavcodec.so:multimedia/ffmpeg
FFMPEG_CONFIGURE_WITH= system-libav
FFMPEG_BUILD_DEPENDS_OFF=as:devel/binutils nasm:devel/nasm
Added: head/multimedia/gstreamer1-libav/files/patch-ffmpeg4
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/multimedia/gstreamer1-libav/files/patch-ffmpeg4 Sun Nov 11 15:39:42 2018 (r484697)
@@ -0,0 +1,4664 @@
+https://bugzilla.gnome.org/show_bug.cgi?id=792900
+
+--- configure.orig 2018-10-02 22:09:31 UTC
++++ configure
+@@ -18125,12 +18125,12 @@ if test -n "$PKG_CONFIG"; then
+ pkg_cv_LIBAV_CFLAGS="$LIBAV_CFLAGS"
+ else
+ if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavfilter libavformat libavcodec >= 57 libavutil\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libavfilter libavformat libavcodec >= 57 libavutil") 2>&5
++ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavfilter libavformat libavcodec >= 58 libavutil\""; } >&5
++ ($PKG_CONFIG --exists --print-errors "libavfilter libavformat libavcodec >= 58 libavutil") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+- pkg_cv_LIBAV_CFLAGS=`$PKG_CONFIG --cflags "libavfilter libavformat libavcodec >= 57 libavutil" 2>/dev/null`
++ pkg_cv_LIBAV_CFLAGS=`$PKG_CONFIG --cflags "libavfilter libavformat libavcodec >= 58 libavutil" 2>/dev/null`
+ else
+ pkg_failed=yes
+ fi
+@@ -18143,12 +18143,12 @@ if test -n "$PKG_CONFIG"; then
+ pkg_cv_LIBAV_LIBS="$LIBAV_LIBS"
+ else
+ if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavfilter libavformat libavcodec >= 57 libavutil\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libavfilter libavformat libavcodec >= 57 libavutil") 2>&5
++ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavfilter libavformat libavcodec >= 58 libavutil\""; } >&5
++ ($PKG_CONFIG --exists --print-errors "libavfilter libavformat libavcodec >= 58 libavutil") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+- pkg_cv_LIBAV_LIBS=`$PKG_CONFIG --libs "libavfilter libavformat libavcodec >= 57 libavutil" 2>/dev/null`
++ pkg_cv_LIBAV_LIBS=`$PKG_CONFIG --libs "libavfilter libavformat libavcodec >= 58 libavutil" 2>/dev/null`
+ else
+ pkg_failed=yes
+ fi
+@@ -18167,14 +18167,14 @@ else
+ _pkg_short_errors_supported=no
+ fi
+ if test $_pkg_short_errors_supported = yes; then
+- LIBAV_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libavfilter libavformat libavcodec >= 57 libavutil"`
++ LIBAV_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libavfilter libavformat libavcodec >= 58 libavutil"`
+ else
+- LIBAV_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libavfilter libavformat libavcodec >= 57 libavutil"`
++ LIBAV_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libavfilter libavformat libavcodec >= 58 libavutil"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBAV_PKG_ERRORS" >&5
+
+- as_fn_error $? "Package requirements (libavfilter libavformat libavcodec >= 57 libavutil) were not met:
++ as_fn_error $? "Package requirements (libavfilter libavformat libavcodec >= 58 libavutil) were not met:
+
+ $LIBAV_PKG_ERRORS
+
+@@ -18471,10 +18471,10 @@ fi
+ emblibav_configure_args="$emblibav_configure_args \
+ --enable-static --enable-pic \
+ --disable-avdevice --disable-postproc \
+- --disable-programs --disable-ffserver --disable-ffplay --disable-ffprobe --disable-ffmpeg \
++ --disable-programs --disable-ffplay --disable-ffprobe --disable-ffmpeg \
+ --disable-encoder=flac --disable-protocols --disable-devices \
+ --disable-network --disable-hwaccels --disable-dxva2 --disable-vdpau \
+- --disable-filters --enable-filter=yadif --disable-doc --disable-vda --disable-d3d11va --disable-dxva2 \
++ --disable-filters --enable-filter=yadif --disable-doc --disable-d3d11va --disable-dxva2 \
+ --disable-audiotoolbox --disable-videotoolbox --disable-vaapi --disable-crystalhd \
+ --disable-mediacodec --disable-nvenc --disable-mmal --disable-omx \
+ --disable-omx-rpi --disable-cuda --disable-cuvid --disable-libmfx \
+--- ext/libav/gstav.c.orig 2018-07-19 11:27:13 UTC
++++ ext/libav/gstav.c
+@@ -28,12 +28,9 @@
+ #include <string.h>
+ #include <gst/gst.h>
+
+-#include <libavcodec/avcodec.h>
+-#include <libavformat/avformat.h>
+-#include <libavfilter/avfiltergraph.h>
+-
+ #include "gstav.h"
+ #include "gstavutils.h"
++#include "gstavcfg.h"
+
+ #ifdef GST_LIBAV_ENABLE_GPL
+ #define LICENSE "GPL"
+@@ -155,8 +152,8 @@ plugin_init (GstPlugin * plugin)
+
+ gst_ffmpeg_init_pix_fmt_info ();
+
+- av_register_all ();
+- avfilter_register_all ();
++ /* build global ffmpeg param/property info */
++ gst_ffmpeg_cfg_init ();
+
+ gst_ffmpegaudenc_register (plugin);
+ gst_ffmpegvidenc_register (plugin);
+--- ext/libav/gstavauddec.c.orig 2018-07-19 11:29:22 UTC
++++ ext/libav/gstavauddec.c
+@@ -153,7 +153,7 @@ gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec)
+
+ ffmpegdec->frame = av_frame_alloc ();
+
+- GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_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
+ (ffmpegdec), TRUE);
+
+@@ -287,7 +287,7 @@ gst_ffmpegauddec_propose_allocation (GstAudioDecoder *
+ gst_allocation_params_init (¶ms);
+ params.flags = GST_MEMORY_FLAG_ZERO_PADDED;
+ params.align = 15;
+- params.padding = FF_INPUT_BUFFER_PADDING_SIZE;
++ params.padding = AV_INPUT_BUFFER_PADDING_SIZE;
+ /* we would like to have some padding so that we don't have to
+ * memcpy. We don't suggest an allocator. */
+ gst_query_add_allocation_param (query, NULL, ¶ms);
+@@ -360,15 +360,14 @@ static gboolean
+ settings_changed (GstFFMpegAudDec * ffmpegdec, AVFrame * frame)
+ {
+ GstAudioFormat format;
+- gint channels =
+- av_get_channel_layout_nb_channels (av_frame_get_channel_layout (frame));
++ gint channels = av_get_channel_layout_nb_channels (frame->channel_layout);
+
+ format = gst_ffmpeg_smpfmt_to_audioformat (frame->format);
+ if (format == GST_AUDIO_FORMAT_UNKNOWN)
+ return TRUE;
+
+ return !(ffmpegdec->info.rate ==
+- av_frame_get_sample_rate (frame) &&
++ frame->sample_rate &&
+ ffmpegdec->info.channels == channels &&
+ ffmpegdec->info.finfo->format == format);
+ }
+@@ -387,10 +386,9 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegde
+ format = gst_ffmpeg_smpfmt_to_audioformat (frame->format);
+ if (format == GST_AUDIO_FORMAT_UNKNOWN)
+ goto no_caps;
+- channels =
+- av_get_channel_layout_nb_channels (av_frame_get_channel_layout (frame));
++ channels = av_get_channel_layout_nb_channels (frame->channel_layout);
+ if (channels == 0)
+- channels = av_frame_get_channels (frame);
++ channels = frame->channels;
+ if (channels == 0)
+ goto no_caps;
+
+@@ -400,11 +398,9 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegde
+ GST_DEBUG_OBJECT (ffmpegdec,
+ "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
+ ffmpegdec->info.rate, ffmpegdec->info.channels,
+- ffmpegdec->info.finfo->format, av_frame_get_sample_rate (frame), channels,
+- format);
++ ffmpegdec->info.finfo->format, frame->sample_rate, channels, format);
+
+- gst_ffmpeg_channel_layout_to_gst (av_frame_get_channel_layout (frame),
+- channels, pos);
++ gst_ffmpeg_channel_layout_to_gst (frame->channel_layout, channels, pos);
+ memcpy (ffmpegdec->ffmpeg_layout, pos,
+ sizeof (GstAudioChannelPosition) * channels);
+
+@@ -413,7 +409,7 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegde
+ ffmpegdec->needs_reorder =
+ memcmp (pos, ffmpegdec->ffmpeg_layout, sizeof (pos[0]) * channels) != 0;
+ gst_audio_info_set_format (&ffmpegdec->info, format,
+- av_frame_get_sample_rate (frame), channels, pos);
++ frame->sample_rate, channels, pos);
+
+ if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec),
+ &ffmpegdec->info))
+@@ -461,25 +457,19 @@ gst_avpacket_init (AVPacket * packet, guint8 * data, g
+ packet->size = size;
+ }
+
+-static gint
++/*
++ * Returns: whether a frame was decoded
++ */
++static gboolean
+ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec,
+- AVCodec * in_plugin, guint8 * data, guint size, gint * have_data,
+- GstBuffer ** outbuf, GstFlowReturn * ret)
++ AVCodec * in_plugin, GstBuffer ** outbuf, GstFlowReturn * ret)
+ {
+- gint len = -1;
+- AVPacket packet;
++ gboolean got_frame = FALSE;
++ gint res;
+
+- GST_DEBUG_OBJECT (ffmpegdec, "size: %d", size);
++ res = avcodec_receive_frame (ffmpegdec->context, ffmpegdec->frame);
+
+- gst_avpacket_init (&packet, data, size);
+- len =
+- avcodec_decode_audio4 (ffmpegdec->context, ffmpegdec->frame, have_data,
+- &packet);
+-
+- GST_DEBUG_OBJECT (ffmpegdec,
+- "Decode audio: len=%d, have_data=%d", len, *have_data);
+-
+- if (len >= 0 && *have_data) {
++ if (res >= 0) {
+ gint nsamples, channels, byte_per_sample;
+ gsize output_size;
+
+@@ -487,10 +477,11 @@ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpeg
+ ffmpegdec->frame, FALSE)) {
+ *outbuf = NULL;
+ *ret = GST_FLOW_NOT_NEGOTIATED;
+- len = -1;
+ goto beach;
+ }
+
++ got_frame = TRUE;
++
+ channels = ffmpegdec->info.channels;
+ nsamples = ffmpegdec->frame->nb_samples;
+ byte_per_sample = ffmpegdec->info.finfo->width / 8;
+@@ -586,60 +577,46 @@ gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpeg
+ /* Mark corrupted frames as corrupted */
+ if (ffmpegdec->frame->flags & AV_FRAME_FLAG_CORRUPT)
+ GST_BUFFER_FLAG_SET (*outbuf, GST_BUFFER_FLAG_CORRUPTED);
+- } else {
++ } else if (res == AVERROR (EAGAIN)) {
+ *outbuf = NULL;
++ } else if (res == AVERROR_EOF) { /* Should not happen */
++ *ret = GST_FLOW_EOS;
++ GST_WARNING_OBJECT (ffmpegdec,
++ "Tried to receive frame on a flushed context");
++ } else if (res < 0) {
++ *ret = GST_FLOW_ERROR;
++ GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, ("Decoding problem"),
++ ("Legitimate decoding error"));
+ }
+
+ beach:
+ av_frame_unref (ffmpegdec->frame);
+- GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d",
+- *ret, *outbuf, len);
+- return len;
++ GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, got_frame %d",
++ *ret, *outbuf, got_frame);
++ return got_frame;
+ }
+
+-/* gst_ffmpegauddec_frame:
+- * ffmpegdec:
+- * data: pointer to the data to decode
+- * size: size of data in bytes
+- * got_data: 0 if no data was decoded, != 0 otherwise.
+- * in_time: timestamp of data
+- * in_duration: duration of data
+- * ret: GstFlowReturn to return in the chain function
+- *
+- * Decode the given frame and pushes it downstream.
+- *
+- * Returns: Number of bytes used in decoding, -1 on error/failure.
++/*
++ * Returns: whether a frame was decoded
+ */
+-
+-static gint
+-gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec,
+- guint8 * data, guint size, gint * have_data, GstFlowReturn * ret)
++static gboolean
++gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec, GstFlowReturn * ret)
+ {
+ GstFFMpegAudDecClass *oclass;
+ GstBuffer *outbuf = NULL;
+- gint len = 0;
++ gboolean got_frame = FALSE;
+
+ if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
+ goto no_codec;
+
+- GST_LOG_OBJECT (ffmpegdec, "data:%p, size:%d", data, size);
+-
+ *ret = GST_FLOW_OK;
+ ffmpegdec->context->frame_number++;
+
+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
+
+- len =
+- gst_ffmpegauddec_audio_frame (ffmpegdec, oclass->in_plugin, data, size,
+- have_data, &outbuf, ret);
++ got_frame =
++ gst_ffmpegauddec_audio_frame (ffmpegdec, oclass->in_plugin, &outbuf, ret);
+
+- if (len < 0) {
+- GST_WARNING_OBJECT (ffmpegdec,
+- "avdec_%s: decoding error (len: %d, have_data: %d)",
+- oclass->in_plugin->name, len, *have_data);
+- goto beach;
+- }
+-
+ if (outbuf) {
+ GST_LOG_OBJECT (ffmpegdec, "Decoded data, now storing buffer %p", outbuf);
+
+@@ -652,13 +629,13 @@ gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec,
+ }
+
+ beach:
+- return len;
++ return got_frame;
+
+ /* ERRORS */
+ no_codec:
+ {
+ GST_ERROR_OBJECT (ffmpegdec, "no codec context");
+- return -1;
++ goto beach;
+ }
+ }
+
+@@ -669,8 +646,8 @@ gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec)
+
+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
+
+- if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
+- gint have_data, len;
++ 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");
+@@ -678,9 +655,8 @@ gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec)
+ do {
+ GstFlowReturn ret;
+
+- len = gst_ffmpegauddec_frame (ffmpegdec, NULL, 0, &have_data, &ret);
+-
+- } while (len >= 0 && have_data == 1);
++ got_frame = gst_ffmpegauddec_frame (ffmpegdec, &ret);
++ } while (got_frame);
+ avcodec_flush_buffers (ffmpegdec->context);
+ }
+
+@@ -705,11 +681,13 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decod
+ {
+ GstFFMpegAudDec *ffmpegdec;
+ GstFFMpegAudDecClass *oclass;
+- guint8 *data, *bdata;
++ guint8 *data;
+ GstMapInfo map;
+- gint size, bsize, len, have_data;
++ gint size;
++ gboolean got_frame;
+ GstFlowReturn ret = GST_FLOW_OK;
+- gboolean do_padding, is_header;
++ gboolean is_header;
++ AVPacket packet;
+
+ ffmpegdec = (GstFFMpegAudDec *) decoder;
+
+@@ -744,82 +722,47 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decod
+
+ gst_buffer_map (inbuf, &map, GST_MAP_READ);
+
+- bdata = map.data;
+- bsize = map.size;
++ data = map.data;
++ size = map.size;
+
+- if (bsize > 0 && (!GST_MEMORY_IS_ZERO_PADDED (map.memory)
+- || (map.maxsize - map.size) < FF_INPUT_BUFFER_PADDING_SIZE)) {
++ if (size > 0 && (!GST_MEMORY_IS_ZERO_PADDED (map.memory)
++ || (map.maxsize - map.size) < AV_INPUT_BUFFER_PADDING_SIZE)) {
+ /* add padding */
+- if (ffmpegdec->padded_size < bsize + FF_INPUT_BUFFER_PADDING_SIZE) {
+- ffmpegdec->padded_size = bsize + FF_INPUT_BUFFER_PADDING_SIZE;
++ if (ffmpegdec->padded_size < size + AV_INPUT_BUFFER_PADDING_SIZE) {
++ ffmpegdec->padded_size = size + AV_INPUT_BUFFER_PADDING_SIZE;
+ ffmpegdec->padded = g_realloc (ffmpegdec->padded, ffmpegdec->padded_size);
+ GST_LOG_OBJECT (ffmpegdec, "resized padding buffer to %d",
+ ffmpegdec->padded_size);
+ }
+ GST_CAT_TRACE_OBJECT (GST_CAT_PERFORMANCE, ffmpegdec,
+ "Copy input to add padding");
+- memcpy (ffmpegdec->padded, bdata, bsize);
+- memset (ffmpegdec->padded + bsize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
++ memcpy (ffmpegdec->padded, data, size);
++ memset (ffmpegdec->padded + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+- bdata = ffmpegdec->padded;
+- do_padding = TRUE;
+- } else {
+- do_padding = FALSE;
++ data = ffmpegdec->padded;
+ }
+
+- do {
+- guint8 tmp_padding[FF_INPUT_BUFFER_PADDING_SIZE];
++ gst_avpacket_init (&packet, data, size);
+
+- data = bdata;
+- size = bsize;
++ if (!packet.size)
++ goto done;
+
+- if (do_padding) {
+- /* add temporary padding */
+- GST_CAT_TRACE_OBJECT (GST_CAT_PERFORMANCE, ffmpegdec,
+- "Add temporary input padding");
+- memcpy (tmp_padding, data + size, FF_INPUT_BUFFER_PADDING_SIZE);
+- memset (data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+- }
++ if (avcodec_send_packet (ffmpegdec->context, &packet) < 0) {
++ goto send_packet_failed;
++ }
+
++ do {
+ /* decode a frame of audio now */
+- len = gst_ffmpegauddec_frame (ffmpegdec, data, size, &have_data, &ret);
++ got_frame = gst_ffmpegauddec_frame (ffmpegdec, &ret);
+
+- if (do_padding) {
+- memcpy (data + size, tmp_padding, FF_INPUT_BUFFER_PADDING_SIZE);
+- }
+-
+ if (ret != GST_FLOW_OK) {
+ GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s",
+ gst_flow_get_name (ret));
+ /* bad flow return, make sure we discard all data and exit */
+- bsize = 0;
+ break;
+ }
++ } while (got_frame);
+
+- if (len == 0 && have_data == 0) {
+- /* nothing was decoded, this could be because no data was available or
+- * because we were skipping frames.
+- * If we have no context we must exit and wait for more data, we keep the
+- * data we tried. */
+- GST_LOG_OBJECT (ffmpegdec, "Decoding didn't return any data, breaking");
+- break;
+- } else if (len < 0) {
+- /* a decoding error happened, we must break and try again with next data. */
+- GST_LOG_OBJECT (ffmpegdec, "Decoding error, breaking");
+- bsize = 0;
+- break;
+- }
+- /* prepare for the next round, for codecs with a context we did this
+- * already when using the parser. */
+- bsize -= len;
+- bdata += len;
+-
+- do_padding = TRUE;
+-
+- GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0). bsize:%d , bdata:%p",
+- bsize, bdata);
+- } while (bsize > 0);
+-
+ gst_buffer_unmap (inbuf, &map);
+ gst_buffer_unref (inbuf);
+
+@@ -827,15 +770,12 @@ gst_ffmpegauddec_handle_frame (GstAudioDecoder * decod
+ ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec),
+ ffmpegdec->outbuf, 1);
+- else if (len < 0 || is_header)
++ else if (is_header)
+ ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), NULL, 1);
+ ffmpegdec->outbuf = NULL;
+
+- if (bsize > 0) {
+- GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize);
+- }
+-
++done:
+ return ret;
+
+ /* ERRORS */
+@@ -845,8 +785,15 @@ not_negotiated:
+ GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
+ ("avdec_%s: input format was not set before data start",
+ oclass->in_plugin->name));
+- return GST_FLOW_NOT_NEGOTIATED;
++ ret = GST_FLOW_NOT_NEGOTIATED;
++ goto done;
+ }
++
++send_packet_failed:
++ {
++ GST_WARNING_OBJECT (ffmpegdec, "decoding error");
++ goto done;
++ }
+ }
+
+ gboolean
+@@ -865,19 +812,18 @@ gst_ffmpegauddec_register (GstPlugin * plugin)
+ };
+ GType type;
+ AVCodec *in_plugin;
++ void *i = 0;
+ gint rank;
+
+- in_plugin = av_codec_next (NULL);
+-
+ GST_LOG ("Registering decoders");
+
+- while (in_plugin) {
++ while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
+ gchar *type_name;
+
+ /* only decoders */
+ if (!av_codec_is_decoder (in_plugin)
+ || in_plugin->type != AVMEDIA_TYPE_AUDIO) {
+- goto next;
++ continue;
+ }
+
+ /* no quasi codecs, please */
+@@ -885,15 +831,8 @@ gst_ffmpegauddec_register (GstPlugin * plugin)
+ (in_plugin->id >= AV_CODEC_ID_PCM_S16LE &&
+ in_plugin->id <= AV_CODEC_ID_PCM_BLURAY) ||
+ (in_plugin->id >= AV_CODEC_ID_PCM_S8_PLANAR &&
+-#if AV_VERSION_INT (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) >= AV_VERSION_INT (57,69,0)
+- in_plugin->id <= AV_CODEC_ID_PCM_F24LE)) {
+-#elif AV_VERSION_INT (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) >= AV_VERSION_INT (57,54,0)
+- in_plugin->id <= AV_CODEC_ID_PCM_S64BE)) {
+-#else
+- in_plugin->id <= AV_CODEC_ID_PCM_S16BE_PLANAR)) {
+-#endif
+- goto next;
+- }
++ in_plugin->id <= AV_CODEC_ID_PCM_F24LE))
++ continue;
+
+ /* No decoders depending on external libraries (we don't build them, but
+ * people who build against an external ffmpeg might have them.
+@@ -902,7 +841,7 @@ gst_ffmpegauddec_register (GstPlugin * plugin)
+ GST_DEBUG
+ ("Not using external library decoder %s. Use the gstreamer-native ones instead.",
+ in_plugin->name);
+- goto next;
++ continue;
+ }
+
+ GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
+@@ -923,7 +862,7 @@ gst_ffmpegauddec_register (GstPlugin * plugin)
+ !strcmp (in_plugin->name, "dvdsub") ||
+ !strcmp (in_plugin->name, "dvbsub")) {
+ GST_LOG ("Ignoring decoder %s", in_plugin->name);
+- goto next;
++ continue;
+ }
+
+ /* construct the type */
+@@ -967,9 +906,6 @@ gst_ffmpegauddec_register (GstPlugin * plugin)
+ }
+
+ g_free (type_name);
+-
+- next:
+- in_plugin = av_codec_next (in_plugin);
+ }
+
+ GST_LOG ("Finished Registering decoders");
+--- ext/libav/gstavauddec.h.orig 2018-03-23 20:45:20 UTC
++++ ext/libav/gstavauddec.h
+@@ -19,6 +19,8 @@
+ #ifndef __GST_FFMPEGAUDDEC_H__
+ #define __GST_FFMPEGAUDDEC_H__
+
++#include <glib.h>
++
+ G_BEGIN_DECLS
+
+ #include <gst/gst.h>
+@@ -38,7 +40,7 @@ struct _GstFFMpegAudDec
+ AVFrame *frame;
+
+ guint8 *padded;
+- guint padded_size;
++ gint padded_size;
+
+ /* prevent reopening the decoder on GST_EVENT_CAPS when caps are same as last time. */
+ GstCaps *last_caps;
+--- ext/libav/gstavaudenc.c.orig 2018-03-23 20:45:20 UTC
++++ ext/libav/gstavaudenc.c
+@@ -31,31 +31,22 @@
+ #include <errno.h>
+
+ #include <libavcodec/avcodec.h>
++#include <libavutil/opt.h>
+
+ #include <gst/gst.h>
+
+ #include "gstav.h"
++#include "gstavcfg.h"
+ #include "gstavcodecmap.h"
+ #include "gstavutils.h"
+ #include "gstavaudenc.h"
+
+-#define DEFAULT_AUDIO_BITRATE 128000
+-
+ enum
+ {
+- /* FILL ME */
+- LAST_SIGNAL
+-};
+-
+-enum
+-{
+ PROP_0,
+- PROP_BIT_RATE,
+- PROP_RTP_PAYLOAD_SIZE,
+- PROP_COMPLIANCE,
++ PROP_CFG_BASE,
+ };
+
+-/* A number of function prototypes are given so we can refer to them later. */
+ static void gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass);
+ static void gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass);
+ static void gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc);
+@@ -78,8 +69,6 @@ static void gst_ffmpegaudenc_get_property (GObject * o
+
+ static GstElementClass *parent_class = NULL;
+
+-/*static guint gst_ffmpegaudenc_signals[LAST_SIGNAL] = { 0 }; */
+-
+ static void
+ gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass)
+ {
+@@ -148,16 +137,8 @@ gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * kl
+ gobject_class->set_property = gst_ffmpegaudenc_set_property;
+ gobject_class->get_property = gst_ffmpegaudenc_get_property;
+
+- /* FIXME: could use -1 for a sensible per-codec defaults */
+- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE,
+- g_param_spec_int ("bitrate", "Bit Rate",
+- "Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE,
+- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE,
+- g_param_spec_enum ("compliance", "Compliance",
+- "Adherence of the encoder to the specifications",
+- GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE,
+- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++ gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
++ PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM);
+
+ gobject_class->finalize = gst_ffmpegaudenc_finalize;
+
+@@ -180,11 +161,10 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc)
+
+ /* ffmpeg objects */
+ ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin);
++ ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
+ ffmpegaudenc->opened = FALSE;
+ ffmpegaudenc->frame = av_frame_alloc ();
+
+- ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE;
+-
+ gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
+ }
+
+@@ -197,6 +177,7 @@ gst_ffmpegaudenc_finalize (GObject * object)
+ av_frame_free (&ffmpegaudenc->frame);
+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
+ av_free (ffmpegaudenc->context);
++ av_free (ffmpegaudenc->refcontext);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+@@ -262,33 +243,8 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder
+ }
+ }
+
+- /* if we set it in _getcaps we should set it also in _link */
+- ffmpegaudenc->context->strict_std_compliance = ffmpegaudenc->compliance;
++ gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
+
+- /* user defined properties */
+- if (ffmpegaudenc->bitrate > 0) {
+- GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d",
+- ffmpegaudenc->bitrate);
+- ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate;
+- ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate;
+- } else {
+- GST_INFO_OBJECT (ffmpegaudenc,
+- "Using avcontext default bitrate %" G_GINT64_FORMAT,
+- (gint64) ffmpegaudenc->context->bit_rate);
+- }
+-
+- /* RTP payload used for GOB production (for Asterisk) */
+- if (ffmpegaudenc->rtp_payload_size) {
+- ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size;
+- }
+-
+- /* some other defaults */
+- ffmpegaudenc->context->rc_strategy = 2;
+- ffmpegaudenc->context->b_frame_strategy = 0;
+- ffmpegaudenc->context->coder_type = 0;
+- ffmpegaudenc->context->context_model = 0;
+- ffmpegaudenc->context->scenechange_threshold = 0;
+-
+ /* fetch pix_fmt and so on */
+ gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
+ if (!ffmpegaudenc->context->time_base.den) {
+@@ -330,8 +286,9 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder
+ oclass->in_plugin) < 0)
+ GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+
+- if ((oclass->in_plugin->capabilities & CODEC_CAP_EXPERIMENTAL) &&
+- ffmpegaudenc->compliance != GST_FFMPEG_EXPERIMENTAL) {
++ if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
++ ffmpegaudenc->context->strict_std_compliance !=
++ GST_FFMPEG_EXPERIMENTAL) {
+ GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS,
+ ("Codec is experimental, but settings don't allow encoders to "
+ "produce output of experimental quality"),
+@@ -445,15 +402,13 @@ buffer_info_free (void *opaque, guint8 * data)
+ }
+
+ static GstFlowReturn
+-gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
+- GstBuffer * buffer, gint * have_data)
++gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
+ {
+ GstAudioEncoder *enc;
+ AVCodecContext *ctx;
+- gint res;
+ GstFlowReturn ret;
++ gint res;
+ GstAudioInfo *info;
+- AVPacket *pkt;
+ AVFrame *frame = ffmpegaudenc->frame;
+ gboolean planar;
+ gint nsamples = -1;
+@@ -462,8 +417,6 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpe
+
+ ctx = ffmpegaudenc->context;
+
+- pkt = g_slice_new0 (AVPacket);
+-
+ if (buffer != NULL) {
+ BufferInfo *buffer_info = g_slice_new0 (BufferInfo);
+ guint8 *audio_in;
+@@ -572,28 +525,47 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpe
+ }
+
+ /* we have a frame to feed the encoder */
+- res = avcodec_encode_audio2 (ctx, pkt, frame, have_data);
++ res = avcodec_send_frame (ctx, frame);
+
+ av_frame_unref (frame);
+ } else {
+ GST_LOG_OBJECT (ffmpegaudenc, "draining");
+ /* flushing the encoder */
+- res = avcodec_encode_audio2 (ctx, pkt, NULL, have_data);
++ res = avcodec_send_frame (ctx, NULL);
+ }
+
+- if (res < 0) {
+- char error_str[128] = { 0, };
+-
+- g_slice_free (AVPacket, pkt);
+- av_strerror (res, error_str, sizeof (error_str));
+- GST_ERROR_OBJECT (enc, "Failed to encode buffer: %d - %s", res, error_str);
+- return GST_FLOW_OK;
++ if (res == 0) {
++ ret = GST_FLOW_OK;
++ } else if (res == AVERROR_EOF) {
++ ret = GST_FLOW_EOS;
++ } else { /* Any other return value is an error in our context */
++ ret = GST_FLOW_OK;
++ GST_WARNING_OBJECT (ffmpegaudenc, "Failed to encode buffer");
+ }
+- GST_LOG_OBJECT (ffmpegaudenc, "got output size %d", res);
+
+- if (*have_data) {
++ return ret;
++}
++
++static GstFlowReturn
++gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
++ gboolean * got_packet)
++{
++ GstAudioEncoder *enc;
++ AVCodecContext *ctx;
++ gint res;
++ GstFlowReturn ret;
++ AVPacket *pkt;
++
++ enc = GST_AUDIO_ENCODER (ffmpegaudenc);
++
++ ctx = ffmpegaudenc->context;
++
++ pkt = g_slice_new0 (AVPacket);
++
++ res = avcodec_receive_packet (ctx, pkt);
++
++ if (res == 0) {
+ GstBuffer *outbuf;
+- const AVCodec *codec;
+
+ GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt->size);
+
+@@ -601,45 +573,39 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpe
+ gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
+ pkt->size, 0, pkt->size, pkt, gst_ffmpegaudenc_free_avpacket);
+
+- codec = ffmpegaudenc->context->codec;
+- if ((codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) || !buffer) {
+- /* FIXME: Not really correct, as -1 means "all the samples we got
+- given so far", which may not be true depending on the codec,
+- but we have no way to know AFAICT */
+- ret = gst_audio_encoder_finish_frame (enc, outbuf, -1);
+- } else {
+- ret = gst_audio_encoder_finish_frame (enc, outbuf, nsamples);
+- }
++ ret =
++ gst_audio_encoder_finish_frame (enc, outbuf,
++ pkt->duration > 0 ? pkt->duration : -1);
++ *got_packet = TRUE;
+ } else {
+ GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
+ g_slice_free (AVPacket, pkt);
+ ret = GST_FLOW_OK;
++ *got_packet = FALSE;
+ }
+
+ return ret;
+ }
+
+-static void
++static GstFlowReturn
+ gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
+ {
+- GstFFMpegAudEncClass *oclass;
++ GstFlowReturn ret = GST_FLOW_OK;
++ gboolean got_packet;
+
+- oclass = (GstFFMpegAudEncClass *) (G_OBJECT_GET_CLASS (ffmpegaudenc));
++ ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
+
+- if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
+- gint have_data, try = 0;
+-
+- GST_LOG_OBJECT (ffmpegaudenc,
+- "codec has delay capabilities, calling until libav has drained everything");
+-
++ if (ret == GST_FLOW_OK) {
+ do {
+- GstFlowReturn ret;
+-
+- ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, NULL, &have_data);
+- if (ret != GST_FLOW_OK || have_data == 0)
++ ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
++ if (ret != GST_FLOW_OK)
+ break;
+- } while (try++ < 10);
++ } while (got_packet);
+ }
++
++ avcodec_flush_buffers (ffmpegaudenc->context);
++
++ return ret;
+ }
+
+ static GstFlowReturn
+@@ -647,17 +613,15 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encod
+ {
+ GstFFMpegAudEnc *ffmpegaudenc;
+ GstFlowReturn ret;
+- gint have_data;
++ gboolean got_packet;
+
+ ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
+
+ if (G_UNLIKELY (!ffmpegaudenc->opened))
+ goto not_negotiated;
+
+- if (!inbuf) {
+- gst_ffmpegaudenc_drain (ffmpegaudenc);
+- return GST_FLOW_OK;
+- }
++ if (!inbuf)
++ return gst_ffmpegaudenc_drain (ffmpegaudenc);
+
+ inbuf = gst_buffer_ref (inbuf);
+
+@@ -675,11 +639,15 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encod
+ info->channels, info->position, ffmpegaudenc->ffmpeg_layout);
+ }
+
+- ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, inbuf, &have_data);
++ ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, inbuf);
+
+ if (ret != GST_FLOW_OK)
+- goto push_failed;
++ goto send_frame_failed;
+
++ do {
++ ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
++ } while (got_packet);
++
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+@@ -690,9 +658,9 @@ not_negotiated:
+ gst_buffer_unref (inbuf);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+-push_failed:
++send_frame_failed:
+ {
+- GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to push buffer %d (%s)", ret,
++ GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to send frame %d (%s)", ret,
+ gst_flow_get_name (ret));
+ return ret;
+ }
+@@ -704,55 +672,34 @@ gst_ffmpegaudenc_set_property (GObject * object,
+ {
+ GstFFMpegAudEnc *ffmpegaudenc;
+
+- /* Get a pointer of the right type. */
+ ffmpegaudenc = (GstFFMpegAudEnc *) (object);
+
+ if (ffmpegaudenc->opened) {
+ GST_WARNING_OBJECT (ffmpegaudenc,
+- "Can't change properties once decoder is setup !");
++ "Can't change properties once encoder is setup !");
+ return;
+ }
+
+- /* Check the argument id to see which argument we're setting. */
+ switch (prop_id) {
+- case PROP_BIT_RATE:
+- ffmpegaudenc->bitrate = g_value_get_int (value);
+- break;
+- case PROP_RTP_PAYLOAD_SIZE:
+- ffmpegaudenc->rtp_payload_size = g_value_get_int (value);
+- break;
+- case PROP_COMPLIANCE:
+- ffmpegaudenc->compliance = g_value_get_enum (value);
+- break;
+ default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec))
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+
+-/* The set function is simply the inverse of the get fuction. */
+ static void
+ gst_ffmpegaudenc_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+ {
+ GstFFMpegAudEnc *ffmpegaudenc;
+
+- /* It's not null if we got it, but it might not be ours */
+ ffmpegaudenc = (GstFFMpegAudEnc *) (object);
+
+ switch (prop_id) {
+- case PROP_BIT_RATE:
+- g_value_set_int (value, ffmpegaudenc->bitrate);
+- break;
+- break;
+- case PROP_RTP_PAYLOAD_SIZE:
+- g_value_set_int (value, ffmpegaudenc->rtp_payload_size);
+- break;
+- case PROP_COMPLIANCE:
+- g_value_set_enum (value, ffmpegaudenc->compliance);
+- break;
+ default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec))
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+@@ -773,32 +720,26 @@ gst_ffmpegaudenc_register (GstPlugin * plugin)
+ };
+ GType type;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-ports-head
mailing list