Date: Sun, 11 Nov 2018 15:39:42 +0000 (UTC) From: Jan Beich <jbeich@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r484697 - in head/multimedia/gstreamer1-libav: . files Message-ID: <201811111539.wABFdglc047334@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811111539.wABFdglc047334>