diff options
-rw-r--r-- | .SRCINFO | 61 | ||||
-rw-r--r-- | PKGBUILD | 76 | ||||
-rw-r--r-- | ffmpeg5.patch | 890 |
3 files changed, 1027 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..820ce87903b0 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,61 @@ +pkgbase = mlt6 + pkgdesc = An open source multimedia framework + pkgver = 6.26.1 + pkgrel = 11 + url = https://www.mltframework.org + arch = x86_64 + license = GPL + makedepends = cmake + makedepends = ladspa + makedepends = frei0r-plugins + makedepends = libdv + makedepends = sdl_image + makedepends = libsamplerate + makedepends = sox + makedepends = ffmpeg + makedepends = vid.stab + makedepends = qt5-svg + makedepends = jack + makedepends = libexif + makedepends = python + makedepends = swig + makedepends = movit + makedepends = eigen + makedepends = opencv + makedepends = rubberband + makedepends = gdk-pixbuf2 + makedepends = pango + makedepends = rtaudio + makedepends = imagemagick + depends = libebur128 + optdepends = sdl_image: SDL1 plugin + optdepends = sdl2: SDL2 plugin + optdepends = libsamplerate: libavresample plugin + optdepends = sox: SOX (Audio Swiss Army Knife) plugin + optdepends = ffmpeg: ffmpeg plugin + optdepends = vid.stab: video stabilize plugin + optdepends = qt5-svg: Qt5 plugins + optdepends = jack: JACK sound output plugin + optdepends = ladspa: LADSPA plugins + optdepends = libexif: auto rotate plugin + optdepends = frei0r-plugins: for additional effects + optdepends = movit: opengl plugin + optdepends = opencv: openCV plugin + optdepends = rubberband: audio pitch plugin + optdepends = gdk-pixbuf2: gdk plugin + optdepends = pango: gdk plugin + optdepends = rtaudio: rtaudio plugin + optdepends = python: python bindings + provides = python-mlt + conflicts = python-mlt + replaces = python-mlt + source = mlt6-6.26.1.tar.gz::https://github.com/mltframework/mlt/archive/v6.26.1.tar.gz + source = https://github.com/mltframework/mlt/commit/7063e88e.patch + source = https://github.com/mltframework/mlt/commit/a87229bc.patch + source = ffmpeg5.patch + sha256sums = 8a484bbbf51f33e25312757531f3ad2ce20607149d20fcfcb40a3c1e60b20b4e + sha256sums = 8c2f537e46089ac165da12988aecf49e24d20ec33c1b88c6301f3d2640b8d8f3 + sha256sums = fc08a5cefb9e164966d5a6514196866dc96bb33719b5b7c069e0b8910e8f8fa5 + sha256sums = 7e21d494dbd5d5fe4627b82fbbfe63b52cbda316ad24ed995f8cbe60019566a0 + +pkgname = mlt6 diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..948bc7e0b9f3 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,76 @@ +# Maintainer: +# Contributor: Antonio Rojas <arojas@archlinux.org> +# Contributor: Sergej Pupykin <pupykin.s+arch@gmail.com> +# Contributor: Fabian Schoelzel <myfirstname.mylastname@googlemail.com> +# Contributor: funkyou <spamopfer@nickname.berlin.de> +# Contributor: tardo <tardo@nagi-fanboi.net> +# Contributor: Stefan Husmann <stefan-husmann@t-online.de> +# Contributor: Gustavo Alvarez <sl1pkn07@gmail.com> + +pkgname=mlt6 +pkgver=6.26.1 +pkgrel=11 +pkgdesc="An open source multimedia framework" +arch=(x86_64) +url="https://www.mltframework.org" +license=(GPL) +depends=(libebur128) +optdepends=('sdl_image: SDL1 plugin' + 'sdl2: SDL2 plugin' + 'libsamplerate: libavresample plugin' + 'sox: SOX (Audio Swiss Army Knife) plugin' + 'ffmpeg: ffmpeg plugin' + 'vid.stab: video stabilize plugin' + 'qt5-svg: Qt5 plugins' + 'jack: JACK sound output plugin' + 'ladspa: LADSPA plugins' + 'libexif: auto rotate plugin' + 'frei0r-plugins: for additional effects' + 'movit: opengl plugin' + 'opencv: openCV plugin' + 'rubberband: audio pitch plugin' + 'gdk-pixbuf2: gdk plugin' + 'pango: gdk plugin' + 'rtaudio: rtaudio plugin' + 'python: python bindings') +makedepends=(cmake ladspa frei0r-plugins libdv sdl_image libsamplerate sox ffmpeg vid.stab qt5-svg + jack libexif python swig movit eigen opencv rubberband gdk-pixbuf2 pango rtaudio imagemagick) +conflicts=(python-mlt) +provides=(python-mlt) +replaces=(python-mlt) +source=($pkgname-$pkgver.tar.gz::https://github.com/mltframework/mlt/archive/v$pkgver.tar.gz + https://github.com/mltframework/mlt/commit/7063e88e.patch + https://github.com/mltframework/mlt/commit/a87229bc.patch + ffmpeg5.patch) +sha256sums=('8a484bbbf51f33e25312757531f3ad2ce20607149d20fcfcb40a3c1e60b20b4e' + '8c2f537e46089ac165da12988aecf49e24d20ec33c1b88c6301f3d2640b8d8f3' + 'fc08a5cefb9e164966d5a6514196866dc96bb33719b5b7c069e0b8910e8f8fa5' + '7e21d494dbd5d5fe4627b82fbbfe63b52cbda316ad24ed995f8cbe60019566a0') + +prepare() { +# Backport fixes for kdenlive crashes + patch -d mlt-$pkgver -p1 < 7063e88e.patch + patch -d mlt-$pkgver -p1 < a87229bc.patch +# Fix build with FFmpeg 5 + patch -d mlt-$pkgver -p1 < ffmpeg5.patch +} + +build() { + cmake -B build -S mlt-$pkgver \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DMOD_OPENCV=ON \ + -DMOD_GTK2=OFF \ + -DSWIG_PYTHON=ON + cmake --build build +} + +package() { + DESTDIR="$pkgdir" cmake --install build + mv "$pkgdir"/usr/bin/melt{,6} # Fix conflicts with mlt 7 + +# Compress lumas + for pgm in "$pkgdir"/usr/share/mlt/lumas/*/*.pgm; do + convert $pgm{,.png} + rm -f $pgm + done +} diff --git a/ffmpeg5.patch b/ffmpeg5.patch new file mode 100644 index 000000000000..3727b18e0b60 --- /dev/null +++ b/ffmpeg5.patch @@ -0,0 +1,890 @@ +From a426473bc8c5e477e305557d5cbd40eaecab33f0 Mon Sep 17 00:00:00 2001 +From: Dan Dennedy <dan@dennedy.org> +Date: Wed, 1 Sep 2021 21:45:17 -0700 +Subject: [PATCH] fix build against FFmpeg master branch + +--- + setenv | 6 +- + src/modules/avformat/consumer_avformat.c | 152 +++++++++++------------ + src/modules/avformat/factory.c | 67 +++------- + src/modules/avformat/filter_avfilter.c | 32 ++--- + src/modules/avformat/producer_avformat.c | 105 ++++++++++------ + 5 files changed, 175 insertions(+), 187 deletions(-) + +diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c +index efd29b29e..cc4da13a6 100644 +--- a/src/modules/avformat/consumer_avformat.c ++++ b/src/modules/avformat/consumer_avformat.c +@@ -34,9 +34,11 @@ + #include <pthread.h> + #include <sys/time.h> + #include <unistd.h> ++#include <time.h> + + // avformat header files + #include <libavformat/avformat.h> ++#include <libavcodec/avcodec.h> + #include <libavformat/avio.h> + #include <libswscale/swscale.h> + #include <libavutil/pixdesc.h> +@@ -45,6 +47,7 @@ + #include <libavutil/opt.h> + #include <libavutil/imgutils.h> + #include <libavutil/version.h> ++#include <libavutil/channel_layout.h> + #ifdef AVFILTER + #include <libavfilter/avfilter.h> + #include <libavfilter/buffersink.h> +@@ -423,11 +426,12 @@ static int consumer_start( mlt_consumer consumer ) + mlt_properties doc = mlt_properties_new(); + mlt_properties formats = mlt_properties_new(); + char key[20]; +- AVOutputFormat *format = NULL; ++ const AVOutputFormat *format = NULL; ++ void *iterator = NULL; + + mlt_properties_set_data( properties, "f", formats, 0, (mlt_destructor) mlt_properties_close, NULL ); + mlt_properties_set_data( doc, "formats", formats, 0, NULL, NULL ); +- while ( ( format = av_oformat_next( format ) ) ) ++ while ( ( format = av_muxer_iterate( &iterator ) ) ) + { + snprintf( key, sizeof(key), "%d", mlt_properties_count( formats ) ); + mlt_properties_set( formats, key, format->name ); +@@ -444,11 +448,12 @@ static int consumer_start( mlt_consumer consumer ) + mlt_properties doc = mlt_properties_new(); + mlt_properties codecs = mlt_properties_new(); + char key[20]; +- AVCodec *codec = NULL; ++ const AVCodec *codec = NULL; + + mlt_properties_set_data( properties, "acodec", codecs, 0, (mlt_destructor) mlt_properties_close, NULL ); + mlt_properties_set_data( doc, "audio_codecs", codecs, 0, NULL, NULL ); +- while ( ( codec = av_codec_next( codec ) ) ) ++ void *iterator = NULL; ++ while ( ( codec = av_codec_iterate( &iterator ) ) ) + #if LIBAVCODEC_VERSION_INT >= ((57<<16)+(37<<8)+0) + if ( av_codec_is_encoder(codec) && codec->type == AVMEDIA_TYPE_AUDIO ) + #else +@@ -470,11 +475,12 @@ static int consumer_start( mlt_consumer consumer ) + mlt_properties doc = mlt_properties_new(); + mlt_properties codecs = mlt_properties_new(); + char key[20]; +- AVCodec *codec = NULL; ++ const AVCodec *codec = NULL; ++ void *iterator = NULL; + + mlt_properties_set_data( properties, "vcodec", codecs, 0, (mlt_destructor) mlt_properties_close, NULL ); + mlt_properties_set_data( doc, "video_codecs", codecs, 0, NULL, NULL ); +- while ( ( codec = av_codec_next( codec ) ) ) ++ while ( ( codec = av_codec_iterate( &iterator ) ) ) + #if LIBAVCODEC_VERSION_INT >= ((57<<16)+(37<<8)+0) + if ( av_codec_is_encoder(codec) && codec->type == AVMEDIA_TYPE_VIDEO ) + #else +@@ -616,7 +622,7 @@ static int get_mlt_audio_format( int av_sample_fmt ) + } + } + +-static int pick_sample_fmt( mlt_properties properties, AVCodec *codec ) ++static int pick_sample_fmt( mlt_properties properties, const AVCodec *codec ) + { + int sample_fmt = AV_SAMPLE_FMT_S16; + const char *format = mlt_properties_get( properties, "mlt_audio_format" ); +@@ -693,7 +699,7 @@ static uint8_t* interleaved_to_planar( int samples, int channels, uint8_t* audio + /** Add an audio output stream + */ + +-static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, AVCodec *codec, int channels, int64_t channel_layout ) ++static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, const AVCodec *codec, AVCodecContext **codec_context, int channels, int64_t channel_layout ) + { + // Get the properties + mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); +@@ -704,10 +710,11 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A + // If created, then initialise from properties + if ( st != NULL ) + { +- AVCodecContext *c = st->codec; +- +- // Establish defaults from AVOptions +- avcodec_get_context_defaults3( c, codec ); ++ AVCodecContext *c = *codec_context = avcodec_alloc_context3(codec); ++ if (!c) { ++ mlt_log_fatal(MLT_CONSUMER_SERVICE(consumer), "Failed to allocate the audio encoder context\n"); ++ return NULL; ++ } + + c->codec_id = codec->id; + c->codec_type = AVMEDIA_TYPE_AUDIO; +@@ -770,21 +777,11 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A + return st; + } + +-static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream *st, int audio_outbuf_size, const char *codec_name ) ++static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream *st, const AVCodec *codec, AVCodecContext *c ) + { + // We will return the audio input size from here + int audio_input_frame_size = 0; + +- // Get the context +- AVCodecContext *c = st->codec; +- +- // Find the encoder +- AVCodec *codec; +- if ( codec_name ) +- codec = avcodec_find_encoder_by_name( codec_name ); +- else +- codec = avcodec_find_encoder( c->codec_id ); +- + // Process properties as AVOptions on the AVCodec + if ( codec && codec->priv_class ) + { +@@ -807,6 +804,11 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream + // Continue if codec found and we can open it + if ( codec && avcodec_open2( c, codec, NULL ) >= 0 ) + { ++ if (avcodec_parameters_from_context(st->codecpar, c) < 0) { ++ mlt_log_warning(NULL, "Failed to copy encoder parameters to output audio stream\n"); ++ return 0; ++ } ++ + // ugly hack for PCM codecs (will be removed ASAP with new PCM + // support to compute the input frame size in samples + if ( c->frame_size <= 1 ) +@@ -829,16 +831,10 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream + return audio_input_frame_size; + } + +-static void close_audio( AVFormatContext *oc, AVStream *st ) +-{ +- if ( st && st->codec ) +- avcodec_close( st->codec ); +-} +- + /** Add a video output stream + */ + +-static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, AVCodec *codec ) ++static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, const AVCodec *codec, AVCodecContext **codec_context ) + { + // Get the properties + mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); +@@ -849,10 +845,12 @@ static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, A + if ( st != NULL ) + { + char *pix_fmt = mlt_properties_get( properties, "pix_fmt" ); +- AVCodecContext *c = st->codec; + +- // Establish defaults from AVOptions +- avcodec_get_context_defaults3( c, codec ); ++ AVCodecContext *c = *codec_context = avcodec_alloc_context3(codec); ++ if (!c) { ++ mlt_log_fatal(MLT_CONSUMER_SERVICE(consumer), "Failed to allocate the video encoder context\n"); ++ return NULL; ++ } + + c->codec_id = codec->id; + c->codec_type = AVMEDIA_TYPE_VIDEO; +@@ -1121,18 +1119,8 @@ static AVFrame *alloc_picture( int pix_fmt, int width, int height ) + return picture; + } + +-static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream *st, const char *codec_name ) ++static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream *st, const AVCodec *codec, AVCodecContext *video_enc ) + { +- // Get the codec +- AVCodecContext *video_enc = st->codec; +- +- // find the video encoder +- AVCodec *codec; +- if ( codec_name ) +- codec = avcodec_find_encoder_by_name( codec_name ); +- else +- codec = avcodec_find_encoder( video_enc->codec_id ); +- + // Process properties as AVOptions on the AVCodec + if ( codec && codec->priv_class ) + { +@@ -1166,21 +1154,22 @@ static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream + + const AVPixFmtDescriptor* srcDesc = av_pix_fmt_desc_get(video_enc->pix_fmt); + if (srcDesc->flags & AV_PIX_FMT_FLAG_RGB) { +- st->codec->colorspace = AVCOL_SPC_RGB; ++ video_enc->colorspace = AVCOL_SPC_RGB; + } + + int result = codec && avcodec_open2( video_enc, codec, NULL ) >= 0; +- +- return result; +-} + +-void close_video(AVFormatContext *oc, AVStream *st) +-{ +- if ( st && st->codec ) +- { +- av_freep( &st->codec->stats_in ); +- avcodec_close(st->codec); ++ if (result >= 0) { ++ result = avcodec_parameters_from_context(st->codecpar, video_enc) >= 0; ++ if (!result) { ++ mlt_log_warning(NULL, "Failed to copy encoder parameters to output video stream\n"); ++ } ++ } else { ++ mlt_log_warning( NULL, "%s: Unable to encode video - disabling video output.\n", __FILE__ ); + } ++ ++ ++ return result; + } + + static inline long time_difference( struct timeval *time1 ) +@@ -1219,7 +1208,9 @@ typedef struct encode_ctx_desc + + AVFormatContext *oc; + AVStream *video_st; ++ AVCodecContext *vcodec_ctx; + AVStream *audio_st[ MAX_AUDIO_STREAMS ]; ++ AVCodecContext *acodec_ctx[MAX_AUDIO_STREAMS]; + int64_t sample_count[ MAX_AUDIO_STREAMS ]; + + // Used to store and override codec ids +@@ -1279,7 +1270,7 @@ static int encode_audio(encode_ctx_t* ctx) + for ( i = 0; i < MAX_AUDIO_STREAMS && ctx->audio_st[i] && j < ctx->total_channels; i++ ) + { + AVStream *stream = ctx->audio_st[i]; +- AVCodecContext *codec = stream->codec; ++ AVCodecContext *codec = ctx->acodec_ctx[i]; + AVPacket pkt; + + av_init_packet( &pkt ); +@@ -1452,7 +1443,7 @@ static int encode_audio(encode_ctx_t* ctx) + + if ( i == 0 ) + { +- ctx->audio_pts = (double) ctx->sample_count[0] * av_q2d( stream->codec->time_base ); ++ ctx->audio_pts = (double) ctx->sample_count[0] * av_q2d( codec->time_base ); + } + } + +@@ -1531,14 +1522,13 @@ static void *consumer_thread( void *arg ) + long int total_time = 0; + + // Determine the format +- AVOutputFormat *fmt = NULL; ++ const AVOutputFormat *fmt = NULL; + const char *filename = mlt_properties_get( properties, "target" ); + char *format = mlt_properties_get( properties, "f" ); + char *vcodec = mlt_properties_get( properties, "vcodec" ); + char *acodec = mlt_properties_get( properties, "acodec" ); +- AVCodec *audio_codec = NULL; +- AVCodec *video_codec = NULL; +- ++ const AVCodec *audio_codec = NULL; ++ const AVCodec *video_codec = NULL; + + // Misc + char key[27]; +@@ -1657,7 +1647,7 @@ static void *consumer_thread( void *arg ) + // Add audio and video streams + if ( enc_ctx->video_codec_id != AV_CODEC_ID_NONE ) + { +- if ( ( enc_ctx->video_st = add_video_stream( consumer, enc_ctx->oc, video_codec ) ) ) ++ if ( ( enc_ctx->video_st = add_video_stream( consumer, enc_ctx->oc, video_codec, &enc_ctx->vcodec_ctx ) ) ) + { + const char* img_fmt_name = mlt_properties_get( properties, "mlt_image_format" ); + if ( img_fmt_name ) +@@ -1670,7 +1660,7 @@ static void *consumer_thread( void *arg ) + else + { + // Set the mlt_image_format from the selected pix_fmt. +- const char *pix_fmt_name = av_get_pix_fmt_name( enc_ctx->video_st->codec->pix_fmt ); ++ const char *pix_fmt_name = av_get_pix_fmt_name( enc_ctx->vcodec_ctx->pix_fmt ); + if ( !strcmp( pix_fmt_name, "rgba" ) || + !strcmp( pix_fmt_name, "argb" ) || + !strcmp( pix_fmt_name, "bgra" ) ) { +@@ -1698,7 +1688,7 @@ static void *consumer_thread( void *arg ) + { + is_multi = 1; + enc_ctx->total_channels += j; +- enc_ctx->audio_st[i] = add_audio_stream( consumer, enc_ctx->oc, audio_codec, j, av_get_default_channel_layout( j ) ); ++ enc_ctx->audio_st[i] = add_audio_stream( consumer, enc_ctx->oc, audio_codec, &enc_ctx->acodec_ctx[i], j, av_get_default_channel_layout( j ) ); + } + } + // single track +@@ -1711,7 +1701,7 @@ static void *consumer_thread( void *arg ) + { + layout = mlt_audio_channel_layout_default( enc_ctx->channels ); + } +- enc_ctx->audio_st[0] = add_audio_stream( consumer, enc_ctx->oc, audio_codec, enc_ctx->channels, mlt_to_av_channel_layout( layout ) ); ++ enc_ctx->audio_st[0] = add_audio_stream( consumer, enc_ctx->oc, audio_codec, &enc_ctx->acodec_ctx[0], enc_ctx->channels, mlt_to_av_channel_layout( layout ) ); + enc_ctx->total_channels = enc_ctx->channels; + } + } +@@ -1720,7 +1710,7 @@ static void *consumer_thread( void *arg ) + // Audio format is determined when adding the audio stream + mlt_audio_format aud_fmt = mlt_audio_none; + if ( enc_ctx->audio_st[0] ) +- aud_fmt = get_mlt_audio_format( enc_ctx->audio_st[0]->codec->sample_fmt ); ++ aud_fmt = get_mlt_audio_format( enc_ctx->acodec_ctx[0]->sample_fmt ); + enc_ctx->sample_bytes = mlt_audio_format_size( aud_fmt, 1, 1 ); + enc_ctx->sample_bytes = enc_ctx->sample_bytes ? enc_ctx->sample_bytes : 1; // prevent divide by zero + +@@ -1744,16 +1734,15 @@ static void *consumer_thread( void *arg ) + if ( enc_ctx->oc->oformat && enc_ctx->oc->oformat->priv_class && enc_ctx->oc->priv_data ) + apply_properties( enc_ctx->oc->priv_data, properties, AV_OPT_FLAG_ENCODING_PARAM ); + +- if ( enc_ctx->video_st && !open_video( properties, enc_ctx->oc, enc_ctx->video_st, vcodec? vcodec : NULL ) ) ++ if ( enc_ctx->video_st && !open_video( properties, enc_ctx->oc, enc_ctx->video_st, video_codec, enc_ctx->vcodec_ctx ) ) + enc_ctx->video_st = NULL; + for ( i = 0; i < MAX_AUDIO_STREAMS && enc_ctx->audio_st[i]; i++ ) + { +- enc_ctx->audio_input_frame_size = open_audio( properties, enc_ctx->oc, enc_ctx->audio_st[i], enc_ctx->audio_outbuf_size, +- acodec? acodec : NULL ); ++ enc_ctx->audio_input_frame_size = open_audio( properties, enc_ctx->oc, enc_ctx->audio_st[i], audio_codec, enc_ctx->acodec_ctx[i] ); + if ( !enc_ctx->audio_input_frame_size ) + { + // Remove the audio stream from the output context +- int j; ++ unsigned int j; + for ( j = 0; j < enc_ctx->oc->nb_streams; j++ ) + { + if ( enc_ctx->oc->streams[j] == enc_ctx->audio_st[i] ) +@@ -1808,10 +1797,10 @@ static void *consumer_thread( void *arg ) + enum AVPixelFormat pix_fmt; + if ( enc_ctx->video_st ) { + #if defined(AVFILTER) && LIBAVUTIL_VERSION_MAJOR >= 56 +- pix_fmt = enc_ctx->video_st->codec->pix_fmt == AV_PIX_FMT_VAAPI ? +- AV_PIX_FMT_NV12 : enc_ctx->video_st->codec->pix_fmt; ++ pix_fmt = enc_ctx->vcodec_ctx->pix_fmt == AV_PIX_FMT_VAAPI ? ++ AV_PIX_FMT_NV12 : enc_ctx->vcodec_ctx->pix_fmt; + #else +- pix_fmt = enc_ctx->video_st->codec->pix_fmt; ++ pix_fmt = enc_ctx->vcodec_ctx->pix_fmt; + #endif + converted_avframe = alloc_picture( pix_fmt, width, height ); + if ( !converted_avframe ) { +@@ -1826,7 +1815,7 @@ static void *consumer_thread( void *arg ) + { + enc_ctx->audio_avframe = av_frame_alloc(); + if ( enc_ctx->audio_avframe ) { +- AVCodecContext *c = enc_ctx->audio_st[0]->codec; ++ AVCodecContext *c = enc_ctx->acodec_ctx[0]; + enc_ctx->audio_avframe->format = c->sample_fmt; + enc_ctx->audio_avframe->nb_samples = enc_ctx->audio_input_frame_size; + enc_ctx->audio_avframe->channel_layout = c->channel_layout; +@@ -1957,7 +1946,7 @@ static void *consumer_thread( void *arg ) + if ( mlt_deque_count( queue ) ) + { + int ret = 0; +- AVCodecContext *c = enc_ctx->video_st->codec; ++ AVCodecContext *c = enc_ctx->vcodec_ctx; + + frame = mlt_deque_pop_front( queue ); + frame_properties = MLT_FRAME_PROPERTIES( frame ); +@@ -2156,7 +2145,7 @@ static void *consumer_thread( void *arg ) + } + } + enc_ctx->frame_count++; +- enc_ctx->video_pts = (double) enc_ctx->frame_count * av_q2d( enc_ctx->video_st->codec->time_base ); ++ enc_ctx->video_pts = (double) enc_ctx->frame_count * av_q2d( enc_ctx->vcodec_ctx->time_base ); + if ( ret ) + { + mlt_log_fatal( MLT_CONSUMER_SERVICE(consumer), "error writing video frame: %d\n", ret ); +@@ -2222,7 +2211,7 @@ static void *consumer_thread( void *arg ) + if ( enc_ctx->video_st ) for (;;) + #endif + { +- AVCodecContext *c = enc_ctx->video_st->codec; ++ AVCodecContext *c = enc_ctx->vcodec_ctx; + AVPacket pkt; + av_init_packet( &pkt ); + if ( c->codec->id == AV_CODEC_ID_RAWVIDEO ) { +@@ -2290,20 +2279,19 @@ static void *consumer_thread( void *arg ) + av_free( converted_avframe->data[0] ); + av_free( converted_avframe ); + #if defined(AVFILTER) && LIBAVUTIL_VERSION_MAJOR >= 56 +- if (enc_ctx->video_st && enc_ctx->video_st->codec && AV_PIX_FMT_VAAPI == enc_ctx->video_st->codec->pix_fmt) ++ if (enc_ctx->video_st && enc_ctx->vcodec_ctx && AV_PIX_FMT_VAAPI == enc_ctx->vcodec_ctx->pix_fmt) + av_frame_free(&avframe); + #endif + av_free( video_outbuf ); + av_free( enc_ctx->audio_avframe ); + + // close each codec +- if ( enc_ctx->video_st ) +- close_video(enc_ctx->oc, enc_ctx->video_st); +- for ( i = 0; i < MAX_AUDIO_STREAMS && enc_ctx->audio_st[i]; i++ ) +- close_audio( enc_ctx->oc, enc_ctx->audio_st[i] ); ++ avcodec_free_context(&enc_ctx->vcodec_ctx); ++ for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) ++ avcodec_free_context(&enc_ctx->acodec_ctx[i]); + + // Free the streams +- for ( i = 0; i < enc_ctx->oc->nb_streams; i++ ) ++ for ( unsigned int i = 0; i < enc_ctx->oc->nb_streams; i++ ) + av_freep( &enc_ctx->oc->streams[i] ); + + // Close the output file +diff --git a/src/modules/avformat/factory.c b/src/modules/avformat/factory.c +index cf80385a4..b142b6327 100644 +--- a/src/modules/avformat/factory.c ++++ b/src/modules/avformat/factory.c +@@ -34,6 +34,7 @@ extern mlt_filter filter_avfilter_init( mlt_profile, mlt_service_type, const cha + + // ffmpeg Header files + #include <libavformat/avformat.h> ++#include <libavcodec/avcodec.h> + #ifdef AVDEVICE + #include <libavdevice/avdevice.h> + #endif +@@ -46,56 +47,19 @@ extern mlt_filter filter_avfilter_init( mlt_profile, mlt_service_type, const cha + // A static flag used to determine if avformat has been initialised + static int avformat_initialised = 0; + +-static int avformat_lockmgr(void **mutex, enum AVLockOp op) +-{ +- pthread_mutex_t** pmutex = (pthread_mutex_t**) mutex; +- +- switch (op) +- { +- case AV_LOCK_CREATE: +- *pmutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t)); +- if (!*pmutex) return -1; +- pthread_mutex_init(*pmutex, NULL); +- break; +- case AV_LOCK_OBTAIN: +- if (!*pmutex) return -1; +- pthread_mutex_lock(*pmutex); +- break; +- case AV_LOCK_RELEASE: +- if (!*pmutex) return -1; +- pthread_mutex_unlock(*pmutex); +- break; +- case AV_LOCK_DESTROY: +- if (!*pmutex) return -1; +- pthread_mutex_destroy(*pmutex); +- free(*pmutex); +- *pmutex = NULL; +- break; +- } +- +- return 0; +-} +- +-static void unregister_lockmgr( void *p ) +-{ +- av_lockmgr_register( NULL ); +-} +- + static void avformat_init( ) + { + // Initialise avformat if necessary + if ( avformat_initialised == 0 ) + { + avformat_initialised = 1; +- av_lockmgr_register( &avformat_lockmgr ); +- mlt_factory_register_for_clean_up( &avformat_lockmgr, unregister_lockmgr ); +- av_register_all( ); ++// av_register_all( ); + #ifdef AVDEVICE + avdevice_register_all(); + #endif +-#ifdef AVFILTER +- avfilter_register_all(); +-#endif ++//#ifdef AVFILTER ++// avfilter_register_all(); ++//#endif + avformat_network_init(); + av_log_set_level( mlt_log_get_level() ); + if ( getenv("MLT_AVFORMAT_PRODUCER_CACHE") ) +@@ -330,22 +294,25 @@ static mlt_properties avformat_metadata( mlt_service_type type, const char *id, + avformat_init(); + if ( type == mlt_service_producer_type ) + { +- AVInputFormat *f = NULL; +- while ( ( f = av_iformat_next( f ) ) ) ++ const AVInputFormat *f = NULL; ++ void *iterator = NULL; ++ while ( ( f = av_demuxer_iterate( &iterator ) ) ) + if ( f->priv_class ) + add_parameters( params, &f->priv_class, flags, NULL, f->name, NULL ); + } + else + { +- AVOutputFormat *f = NULL; +- while ( ( f = av_oformat_next( f ) ) ) ++ const AVOutputFormat *f = NULL; ++ void *iterator = NULL; ++ while ( ( f = av_muxer_iterate( &iterator ) ) ) + if ( f->priv_class ) + add_parameters( params, &f->priv_class, flags, NULL, f->name, NULL ); + } + + add_parameters( params, avcodec, flags, NULL, NULL, NULL ); +- AVCodec *c = NULL; +- while ( ( c = av_codec_next( c ) ) ) ++ const AVCodec *c = NULL; ++ void *iterator = NULL; ++ while ( ( c = av_codec_iterate( &iterator ) ) ) + if ( c->priv_class ) + add_parameters( params, &c->priv_class, flags, NULL, c->name, NULL ); + +@@ -452,9 +419,9 @@ MLT_REPOSITORY + mlt_properties_set_data(mlt_global_properties(), "avfilter.resolution_scale", + mlt_properties_parse_yaml(dirname), 0, (mlt_destructor) mlt_properties_close, NULL); + +- avfilter_register_all(); +- AVFilter *f = NULL; +- while ( ( f = (AVFilter*)avfilter_next( f ) ) ) { ++ const AVFilter *f = NULL; ++ void *iterator = NULL; ++ while ( ( f = (AVFilter*) av_filter_iterate( &iterator ) ) ) { + // Support filters that have one input and one output of the same type. + if ( avfilter_pad_count( f->inputs ) == 1 && + avfilter_pad_count( f->outputs ) == 1 && +diff --git a/src/modules/avformat/filter_avfilter.c b/src/modules/avformat/filter_avfilter.c +index 12d37936f..f78b6c5f2 100644 +--- a/src/modules/avformat/filter_avfilter.c ++++ b/src/modules/avformat/filter_avfilter.c +@@ -17,6 +17,11 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 700 ++# undef _XOPEN_SOURCE ++# define _XOPEN_SOURCE 700 ++#endif ++ + #include "common.h" + + #include <framework/mlt.h> +@@ -148,8 +153,8 @@ static void set_avfilter_options( mlt_filter filter, double scale) + static void init_audio_filtergraph( mlt_filter filter, mlt_audio_format format, int frequency, int channels ) + { + private_data* pdata = (private_data*)filter->child; +- AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); +- AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); ++ const AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); ++ const AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); + int sample_fmts[] = { -1, -1 }; + int sample_rates[] = { -1, -1 }; + int channel_counts[] = { -1, -1 }; +@@ -289,10 +294,10 @@ static void init_image_filtergraph( mlt_filter filter, mlt_image_format format, + { + private_data* pdata = (private_data*)filter->child; + mlt_profile profile = mlt_service_profile(MLT_FILTER_SERVICE(filter)); +- AVFilter *buffersrc = avfilter_get_by_name("buffer"); +- AVFilter *buffersink = avfilter_get_by_name("buffersink"); +- AVFilter *scale = avfilter_get_by_name("scale"); +- AVFilter *pad = avfilter_get_by_name("pad"); ++ const AVFilter *buffersrc = avfilter_get_by_name("buffer"); ++ const AVFilter *buffersink = avfilter_get_by_name("buffersink"); ++ const AVFilter *scale = avfilter_get_by_name("scale"); ++ const AVFilter *pad = avfilter_get_by_name("pad"); + mlt_properties p = mlt_properties_new(); + enum AVPixelFormat pixel_fmts[] = { -1, -1 }; + AVRational sar = (AVRational){ profile->sample_aspect_num, profile->frame_rate_den }; +@@ -706,25 +711,24 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format + pdata->avinframe->top_field_first = mlt_properties_get_int( frame_properties, "top_field_first" ); + pdata->avinframe->color_primaries = mlt_properties_get_int( frame_properties, "color_primaries" ); + pdata->avinframe->color_trc = mlt_properties_get_int( frame_properties, "color_trc" ); +- av_frame_set_color_range( pdata->avinframe, +- mlt_properties_get_int( frame_properties, "full_luma" )? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG ); ++ pdata->avinframe->color_range = mlt_properties_get_int( frame_properties, "full_luma" )? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + switch (mlt_properties_get_int( frame_properties, "colorspace" )) + { + case 240: +- av_frame_set_colorspace( pdata->avinframe, AVCOL_SPC_SMPTE240M ); ++ pdata->avinframe->colorspace = AVCOL_SPC_SMPTE240M; + break; + case 601: +- av_frame_set_colorspace( pdata->avinframe, AVCOL_SPC_BT470BG ); ++ pdata->avinframe->colorspace = AVCOL_SPC_BT470BG; + break; + case 709: +- av_frame_set_colorspace( pdata->avinframe, AVCOL_SPC_BT709 ); ++ pdata->avinframe->colorspace = AVCOL_SPC_BT709; + break; + case 2020: +- av_frame_set_colorspace( pdata->avinframe, AVCOL_SPC_BT2020_NCL ); ++ pdata->avinframe->colorspace = AVCOL_SPC_BT2020_NCL; + break; + case 2021: +- av_frame_set_colorspace( pdata->avinframe, AVCOL_SPC_BT2020_CL ); ++ pdata->avinframe->colorspace = AVCOL_SPC_BT2020_CL; + break; + } + +@@ -874,8 +878,6 @@ mlt_filter filter_avfilter_init( mlt_profile profile, mlt_service_type type, con + mlt_filter filter = mlt_filter_new(); + private_data* pdata = (private_data*)calloc( 1, sizeof(private_data) ); + +- avfilter_register_all(); +- + if( pdata && id ) + { + id += 9; // Move past "avfilter." +diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c +index aee393dbc..8d2542114 100644 +--- a/src/modules/avformat/producer_avformat.c ++++ b/src/modules/avformat/producer_avformat.c +@@ -40,6 +40,7 @@ + + // ffmpeg Header files + #include <libavformat/avformat.h> ++#include <libavcodec/avcodec.h> + #include <libswscale/swscale.h> + #include <libavutil/samplefmt.h> + #include <libavutil/pixdesc.h> +@@ -382,10 +383,8 @@ static mlt_properties find_default_streams( producer_avformat self ) + // Get the codec context + AVStream *stream = context->streams[ i ]; + if ( ! stream ) continue; +- AVCodecContext *codec_context = stream->codec; +- if ( ! codec_context ) continue; + AVCodecParameters *codec_params = stream->codecpar; +- AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); ++ const AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); + if ( ! codec ) continue; + + snprintf( key, sizeof(key), "meta.media.%u.stream.type", i ); +@@ -421,9 +420,9 @@ static mlt_properties find_default_streams( producer_avformat self ) + mlt_properties_set_int( meta_media, key, codec_params->height ); + snprintf( key, sizeof(key), "meta.media.%u.codec.rotate", i ); + mlt_properties_set_int( meta_media, key, get_rotation(context->streams[i]) ); +- snprintf( key, sizeof(key), "meta.media.%u.codec.frame_rate", i ); +- AVRational frame_rate = { codec_context->time_base.den, codec_context->time_base.num * codec_context->ticks_per_frame }; +- mlt_properties_set_double( meta_media, key, av_q2d( frame_rate ) ); ++// snprintf( key, sizeof(key), "meta.media.%u.codec.frame_rate", i ); ++// AVRational frame_rate = { codec_context->time_base.den, codec_context->time_base.num * codec_context->ticks_per_frame }; ++// mlt_properties_set_double( meta_media, key, av_q2d( frame_rate ) ); + snprintf( key, sizeof(key), "meta.media.%u.codec.pix_fmt", i ); + mlt_properties_set( meta_media, key, av_get_pix_fmt_name( codec_params->format ) ); + snprintf( key, sizeof(key), "meta.media.%u.codec.sample_aspect_ratio", i ); +@@ -447,7 +446,7 @@ static mlt_properties find_default_streams( producer_avformat self ) + mlt_properties_set_int( meta_media, key, codec_params->width * codec_params->height > 750000 ? 709 : 601 ); + break; + default: +- mlt_properties_set_int( meta_media, key, codec_context->colorspace ); ++// mlt_properties_set_int( meta_media, key, codec_context->colorspace ); + break; + } + if ( codec_params->color_trc && codec_params->color_trc != AVCOL_TRC_UNSPECIFIED ) +@@ -474,8 +473,8 @@ static mlt_properties find_default_streams( producer_avformat self ) + default: + break; + } +-// snprintf( key, sizeof(key), "meta.media.%u.stream.time_base", i ); +-// mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->time_base ) ); ++// snprintf( key, sizeof(key), "meta.media.%u.stream.time_base", i ); ++// mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->time_base ) ); + snprintf( key, sizeof(key), "meta.media.%u.codec.name", i ); + mlt_properties_set( meta_media, key, codec->name ); + snprintf( key, sizeof(key), "meta.media.%u.codec.long_name", i ); +@@ -532,7 +531,7 @@ static void get_aspect_ratio( mlt_properties properties, AVStream *stream, AVCod + mlt_properties_set_double( properties, "aspect_ratio", av_q2d( sar ) ); + } + +-static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **format, AVDictionary **params ) ++static char* parse_url( mlt_profile profile, const char* URL, const AVInputFormat **format, AVDictionary **params ) + { + (void) profile; // unused + if ( !URL ) return NULL; +@@ -817,7 +816,7 @@ static int producer_open(producer_avformat self, mlt_profile profile, const char + mlt_events_block( properties, self->parent ); + + // Parse URL +- AVInputFormat *format = NULL; ++ const AVInputFormat *format = NULL; + AVDictionary *params = NULL; + char *filename = parse_url( profile, URL, &format, ¶ms ); + +@@ -1140,12 +1139,6 @@ static int seek_video( producer_avformat self, mlt_position position, + // Fetch the video format context + AVFormatContext *context = self->video_format; + +- // Get the video stream +- AVStream *stream = context->streams[ self->video_index ]; +- +- // Get codec context +- AVCodecContext *codec_context = stream->codec; +- + // We may want to use the source fps if available + double source_fps = mlt_properties_get_double( properties, "meta.media.frame_rate_num" ) / + mlt_properties_get_double( properties, "meta.media.frame_rate_den" ); +@@ -1176,11 +1169,11 @@ static int seek_video( producer_avformat self, mlt_position position, + timestamp, position, self->video_expected, self->last_position ); + + // Seek to the timestamp +- codec_context->skip_loop_filter = AVDISCARD_NONREF; ++ self->video_codec->skip_loop_filter = AVDISCARD_NONREF; + av_seek_frame( context, self->video_index, timestamp, AVSEEK_FLAG_BACKWARD ); + + // flush any pictures still in decode buffer +- avcodec_flush_buffers( codec_context ); ++ avcodec_flush_buffers( self->video_codec ); + self->video_send_result = 0; + + // Remove the cached info relating to the previous position +@@ -1216,11 +1209,23 @@ static void get_audio_streams_info( producer_avformat self ) + if ( context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ) + { + AVCodecParameters *codec_params = context->streams[i]->codecpar; +- AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); ++ const AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); ++ ++ // Setup the codec context ++ AVCodecContext *codec_context = avcodec_alloc_context3(codec); ++ if (!codec_context) { ++ mlt_log_info(MLT_PRODUCER_SERVICE(self->parent), "Failed to allocate the decoder context for stream #%d\n", i); ++ continue; ++ } ++ int ret = avcodec_parameters_to_context(codec_context, codec_params); ++ if (ret < 0) { ++ mlt_log_info(MLT_PRODUCER_SERVICE(self->parent), "Failed to copy decoder parameters to input decoder context for stream #%d\n", i); ++ continue; ++ } + + // If we don't have a codec and we can't initialise it, we can't do much more... + pthread_mutex_lock( &self->open_mutex ); +- if ( codec && avcodec_open2( context->streams[i]->codec, codec, NULL ) >= 0 ) ++ if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 ) + { + self->audio_streams++; + self->audio_max_stream = i; +@@ -1229,7 +1234,7 @@ static void get_audio_streams_info( producer_avformat self ) + self->max_channel = codec_params->channels; + if ( codec_params->sample_rate > self->max_frequency ) + self->max_frequency = codec_params->sample_rate; +- avcodec_close( context->streams[i]->codec ); ++ avcodec_close( codec_context ); + } + pthread_mutex_unlock( &self->open_mutex ); + } +@@ -1673,9 +1678,6 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form + + // Get the video stream + AVStream *stream = context->streams[ self->video_index ]; +- +- // Get codec context +- AVCodecContext *codec_context = stream->codec; + codec_params = stream->codecpar; + + // Always use the image cache for album art. +@@ -1746,13 +1748,12 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form + + // Seek if necessary + double speed = mlt_producer_get_speed(producer); +- int preseek = must_decode && codec_context->has_b_frames && speed >= 0.0 && speed <= 1.0; ++ int preseek = must_decode && self->video_codec->has_b_frames && speed >= 0.0 && speed <= 1.0; + int paused = seek_video( self, position, req_position, preseek ); + + // Seek might have reopened the file + context = self->video_format; + stream = context->streams[ self->video_index ]; +- codec_context = stream->codec; + codec_params = stream->codecpar; + if ( *format == mlt_image_none || *format == mlt_image_movit || + codec_params->format == AV_PIX_FMT_ARGB || +@@ -1897,10 +1898,10 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form + // Decode the image + if ( must_decode || int_position >= req_position || !self->pkt.data ) + { +- codec_context->reordered_opaque = int_position; ++ self->video_codec->reordered_opaque = int_position; + if ( int_position >= req_position ) +- codec_context->skip_loop_filter = AVDISCARD_NONE; +- self->video_send_result = avcodec_send_packet( codec_context, &self->pkt ); ++ self->video_codec->skip_loop_filter = AVDISCARD_NONE; ++ self->video_send_result = avcodec_send_packet( self->video_codec, &self->pkt ); + mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "decoded video packet with size %d => %d\n", self->pkt.size, self->video_send_result ); + // Note: decode may fail at the beginning of MPEGfile (B-frames referencing before first I-frame), so allow a few errors. + if (!ignore_send_packet_result(self->video_send_result)) +@@ -1909,7 +1910,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form + } + else + { +- int error = avcodec_receive_frame( codec_context, self->video_frame ); ++ int error = avcodec_receive_frame( self->video_codec, self->video_frame ); + if ( error < 0 ) + { + if ( error != AVERROR( EAGAIN ) && ++decode_errors > 10 ) +@@ -1969,7 +1970,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form + if ( int_position < req_position ) + got_picture = 0; + else if ( int_position >= req_position ) +- codec_context->skip_loop_filter = AVDISCARD_NONE; ++ self->video_codec->skip_loop_filter = AVDISCARD_NONE; + } + else if ( !self->pkt.data ) // draining decoder with null packets + { +@@ -2137,11 +2138,10 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p + AVStream *stream = self->video_format->streams[ index ]; + + // Get codec context +- AVCodecContext *codec_context = stream->codec; + AVCodecParameters *codec_params = stream->codecpar; + + // Find the codec +- AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); ++ const AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); + if ( mlt_properties_get( properties, "vcodec" ) ) { + if ( !( codec = avcodec_find_decoder_by_name( mlt_properties_get( properties, "vcodec" ) ) ) ) + codec = avcodec_find_decoder( codec_params->codec_id ); +@@ -2153,6 +2153,20 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p + codec = avcodec_find_decoder( codec_params->codec_id ); + } + ++ // Setup the codec context ++ AVCodecContext *codec_context = avcodec_alloc_context3(codec); ++ if (!codec_context) { ++ mlt_log_error( MLT_PRODUCER_SERVICE( self->parent ), "Failed to allocate the decoder context for video stream #%d\n", index); ++ self->video_index = -1; ++ return 0; ++ } ++ int ret = avcodec_parameters_to_context(codec_context, codec_params); ++ if (ret < 0) { ++ mlt_log_error( MLT_PRODUCER_SERVICE( self->parent ), "Failed to copy decoder parameters to input decoder context for video stream #%d\n", index); ++ self->video_index = -1; ++ return 0; ++ } ++ + // Initialise multi-threading + int thread_count = mlt_properties_get_int( properties, "threads" ); + if ( thread_count == 0 && getenv( "MLT_AVFORMAT_THREADS" ) ) +@@ -2924,15 +2938,32 @@ static int audio_codec_init( producer_avformat self, int index, mlt_properties p + // Initialise the codec if necessary + if ( !self->audio_codec[ index ] ) + { ++ // Get the video stream ++ AVStream *stream = self->audio_format->streams[ index ]; ++ + // Get codec context +- AVCodecContext *codec_context = self->audio_format->streams[index]->codec; ++ AVCodecParameters *codec_params = stream->codecpar; + + // Find the codec +- AVCodec *codec = avcodec_find_decoder( codec_context->codec_id ); ++ const AVCodec *codec = avcodec_find_decoder( codec_params->codec_id ); + if ( mlt_properties_get( properties, "acodec" ) ) + { + if ( !( codec = avcodec_find_decoder_by_name( mlt_properties_get( properties, "acodec" ) ) ) ) +- codec = avcodec_find_decoder( codec_context->codec_id ); ++ codec = avcodec_find_decoder( codec_params->codec_id ); ++ } ++ ++ // Setup the codec context ++ AVCodecContext *codec_context = avcodec_alloc_context3(codec); ++ if (!codec_context) { ++ mlt_log_error( MLT_PRODUCER_SERVICE( self->parent ), "Failed to allocate the decoder context for audio stream #%d\n", index); ++ self->audio_index = -1; ++ return 0; ++ } ++ int ret = avcodec_parameters_to_context(codec_context, codec_params); ++ if (ret < 0) { ++ mlt_log_error( MLT_PRODUCER_SERVICE( self->parent ), "Failed to copy decoder parameters to input decoder context for audio stream #%d\n", index); ++ self->audio_index = -1; ++ return 0; + } + + // If we don't have a codec and we can't initialise it, we can't do much more... |