Files
subtitlecomposer/0001-Replaced-deprecated-FFmpeg-channel-layout-code.patch
Christophe Marin 7e2072f1f1 - Add patch to fix build with pocketsphinx 5.0.3 in TW since
the API changed in the 5.0.0 release. Also, removed some
  parameters that don't seem to be configurable by pocketsphinx
  anymore:
  * use-pocketsphinx-5.0.0-api.patch

OBS-URL: https://build.opensuse.org/package/show/KDE:Extra/subtitlecomposer?expand=0&rev=47
2024-12-24 11:58:10 +00:00

438 lines
17 KiB
Diff

From bc9f0507df17c42746ef5acc06313a7a058391d4 Mon Sep 17 00:00:00 2001
From: Mladen Milinkovic <maxrd2@smoothware.net>
Date: Fri, 18 Nov 2022 15:59:10 +0100
Subject: [PATCH 01/11] Replaced deprecated FFmpeg channel layout code
---
src/CMakeLists.txt | 8 ++++
src/streamprocessor/streamprocessor.cpp | 48 ++++++++++++-------
src/streamprocessor/streamprocessor.h | 17 +++----
src/videoplayer/backend/audiodecoder.cpp | 57 ++++++++++++-----------
src/videoplayer/backend/audiodecoder.h | 5 +-
src/videoplayer/backend/streamdemuxer.cpp | 22 +++++----
src/videoplayer/backend/videostate.cpp | 2 +-
7 files changed, 92 insertions(+), 67 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bf0043ea..bacf025f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,14 @@ endif()
if(CMAKE_COMPILER_IS_GNUCC)
message(STATUS "GNU C compiler detected")
+ if(SC_NO_DEPRECATED)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-deprecated-declarations")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-deprecated-declarations")
+ endif()
+ if(SC_WARN_ERRORS)
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror")
+ endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Og -g")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Og -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O3")
diff --git a/src/streamprocessor/streamprocessor.cpp b/src/streamprocessor/streamprocessor.cpp
index 1e883780..aa27a66e 100644
--- a/src/streamprocessor/streamprocessor.cpp
+++ b/src/streamprocessor/streamprocessor.cpp
@@ -35,13 +35,15 @@ StreamProcessor::StreamProcessor(QObject *parent)
m_avFormat(nullptr),
m_avStream(nullptr),
m_codecCtx(nullptr),
- m_swResample(nullptr)
+ m_swResample(nullptr),
+ m_audioChLayout(new AVChannelLayout{})
{
}
StreamProcessor::~StreamProcessor()
{
close();
+ delete m_audioChLayout;
}
bool
@@ -81,7 +83,7 @@ StreamProcessor::open(const QString &filename)
m_opened = true;
- return true;
+ return true;
}
void
@@ -92,6 +94,7 @@ StreamProcessor::close()
wait();
}
+ av_channel_layout_uninit(m_audioChLayout);
if(m_swResample)
swr_free(&m_swResample);
if(m_codecCtx)
@@ -273,28 +276,40 @@ StreamProcessor::initAudio(int streamIndex, const WaveFormat &waveFormat)
return false;
}
+ av_channel_layout_uninit(m_audioChLayout);
+
// figure channel layout or update stream format
- if(!m_codecCtx->channel_layout)
- m_codecCtx->channel_layout = av_get_default_channel_layout(m_codecCtx->channels);;
+ if(m_codecCtx->ch_layout.order != AV_CHANNEL_ORDER_NATIVE) {
+ const int cc = m_codecCtx->ch_layout.nb_channels;
+ av_channel_layout_uninit(&m_codecCtx->ch_layout);
+ av_channel_layout_default(&m_codecCtx->ch_layout, cc);
+ }
if(m_audioStreamFormat.channels() == 0) {
- m_audioStreamFormat.setChannels(m_codecCtx->channels);
- m_audioChannelLayout = m_codecCtx->channel_layout;
+ m_audioStreamFormat.setChannels(m_codecCtx->ch_layout.nb_channels);
+ av_channel_layout_copy(m_audioChLayout, &m_codecCtx->ch_layout);
} else {
- m_audioChannelLayout = av_get_default_channel_layout(m_audioStreamFormat.channels());
+ av_channel_layout_default(m_audioChLayout, m_audioStreamFormat.channels());
}
// setup resampler if needed
- const bool convChannels = m_codecCtx->channel_layout != m_audioChannelLayout;
+ const bool convChannels = av_channel_layout_compare(&m_codecCtx->ch_layout, m_audioChLayout) != 0;
const bool convSampleRate = m_codecCtx->sample_rate != m_audioStreamFormat.sampleRate();
const bool convSampleFormat = m_codecCtx->sample_fmt != m_audioSampleFormat;
if(convChannels || convSampleRate || convSampleFormat) {
- m_swResample = swr_alloc_set_opts(nullptr,
- m_audioChannelLayout, static_cast<AVSampleFormat>(m_audioSampleFormat), m_audioStreamFormat.sampleRate(),
- m_codecCtx->channel_layout, m_codecCtx->sample_fmt, m_codecCtx->sample_rate,
- 0, nullptr);
+ swr_alloc_set_opts2(&m_swResample,
+ m_audioChLayout, AVSampleFormat(m_audioSampleFormat), m_audioStreamFormat.sampleRate(),
+ &m_codecCtx->ch_layout, m_codecCtx->sample_fmt, m_codecCtx->sample_rate,
+ 0, nullptr);
// NOTE: swr_convert_frame() will call swr_init() and swr_config_frame() which is better as it seems m_codecCtx can
- // end up with different config that what is actually in the stream
+ // end up with different config than what is actually in the stream
+ if(!m_swResample) {
+ av_log(nullptr, AV_LOG_ERROR,
+ "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
+ m_codecCtx->sample_rate, av_get_sample_fmt_name(m_codecCtx->sample_fmt), m_codecCtx->ch_layout.nb_channels,
+ m_audioStreamFormat.sampleRate(), av_get_sample_fmt_name(AVSampleFormat(m_audioSampleFormat)), m_audioChLayout->nb_channels);
+ return false;
+ }
}
return true;
@@ -363,7 +378,8 @@ StreamProcessor::processAudio()
if(m_swResample) {
frameResampled = av_frame_alloc();
Q_ASSERT(frameResampled != nullptr);
- frameResampled->channel_layout = m_audioChannelLayout;
+ av_channel_layout_uninit(&frameResampled->ch_layout);
+ av_channel_layout_copy(&frameResampled->ch_layout, m_audioChLayout);
frameResampled->sample_rate = m_audioStreamFormat.sampleRate();
frameResampled->format = m_audioSampleFormat;
}
@@ -448,12 +464,12 @@ StreamProcessor::processAudio()
if(m_swResample) {
Q_ASSERT(frameResampled != nullptr);
- emit audioDataAvailable(frameResampled->data[0], qint32(frameSize * frameResampled->channels),
+ emit audioDataAvailable(frameResampled->data[0], qint32(frameSize * frameResampled->ch_layout.nb_channels),
&m_audioStreamFormat, qint64(timeFrameStart + timeResampleDelay), qint64(timeFrameDuration));
drainSampleBuffer = swr_get_out_samples(m_swResample, 0) > 1000;
} else {
- emit audioDataAvailable(frame->data[0], qint32(frameSize * frame->channels),
+ emit audioDataAvailable(frame->data[0], qint32(frameSize * frame->ch_layout.nb_channels),
&m_audioStreamFormat, qint64(timeFrameStart), qint64(timeFrameDuration));
}
} while(!conversionComplete && !isInterruptionRequested() && drainSampleBuffer);
diff --git a/src/streamprocessor/streamprocessor.h b/src/streamprocessor/streamprocessor.h
index 152a985a..02e7f3b1 100644
--- a/src/streamprocessor/streamprocessor.h
+++ b/src/streamprocessor/streamprocessor.h
@@ -16,14 +16,11 @@
QT_FORWARD_DECLARE_CLASS(QTimer)
-QT_FORWARD_DECLARE_STRUCT(AVFormatContext)
-typedef struct AVFormatContext AVFormatContext;
-QT_FORWARD_DECLARE_STRUCT(AVCodecContext)
-typedef struct AVCodecContext AVCodecContext;
-QT_FORWARD_DECLARE_STRUCT(AVStream)
-typedef struct AVStream AVStream;
-QT_FORWARD_DECLARE_STRUCT(SwrContext)
-typedef struct SwrContext SwrContext;
+struct AVFormatContext;
+struct AVCodecContext;
+struct AVStream;
+struct SwrContext;
+struct AVChannelLayout;
namespace SubtitleComposer {
@@ -59,7 +56,7 @@ protected:
int findStream(int streamType, int streamIndex, bool imageSub);
void processAudio();
void processText();
- virtual void run() override;
+ virtual void run() override;
private:
bool m_opened;
@@ -86,7 +83,7 @@ private:
AVCodecContext *m_codecCtx;
SwrContext *m_swResample;
int m_audioSampleFormat;
- uint64_t m_audioChannelLayout;
+ AVChannelLayout *m_audioChLayout;
};
}
diff --git a/src/videoplayer/backend/audiodecoder.cpp b/src/videoplayer/backend/audiodecoder.cpp
index c0c99bb3..8c0b943e 100644
--- a/src/videoplayer/backend/audiodecoder.cpp
+++ b/src/videoplayer/backend/audiodecoder.cpp
@@ -37,6 +37,8 @@ using namespace SubtitleComposer;
AudioDecoder::AudioDecoder(VideoState *state, QObject *parent)
: Decoder(parent),
m_vs(state),
+ m_fmtSrc({}),
+ m_fmtTgt({}),
m_swrCtx(nullptr),
m_audioBuf(nullptr),
m_bufSize(0),
@@ -147,7 +149,7 @@ AudioDecoder::close()
}
bool
-AudioDecoder::open(int64_t wantChLayout, int wantNbChan, int wantSampleRate)
+AudioDecoder::open(AVChannelLayout *wantChLayout, int wantSampleRate)
{
const static QMap<int, const char *> bufFmtMap = {
{ 4, "AL_FORMAT_QUAD16" },
@@ -158,12 +160,12 @@ AudioDecoder::open(int64_t wantChLayout, int wantNbChan, int wantSampleRate)
int err;
- if(wantSampleRate <= 0 || wantNbChan <= 0) {
+ if(wantSampleRate <= 0 || !wantChLayout || wantChLayout->nb_channels <= 0) {
av_log(nullptr, AV_LOG_ERROR, "openal: invalid sample rate or channel count!\n");
return false;
}
- int availNbChan = wantNbChan;
+ int availNbChan = wantChLayout->nb_channels;
for(;;) {
while(availNbChan > 2 && !bufFmtMap.contains(availNbChan))
availNbChan--;
@@ -171,15 +173,15 @@ AudioDecoder::open(int64_t wantChLayout, int wantNbChan, int wantSampleRate)
m_bufFmt = availNbChan == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
break;
}
- m_bufFmt = alGetEnumValue(bufFmtMap[wantNbChan]);
+ m_bufFmt = alGetEnumValue(bufFmtMap[wantChLayout->nb_channels]);
if(m_bufFmt)
break;
availNbChan--;
}
- if(!wantChLayout || wantNbChan != availNbChan || wantNbChan != av_get_channel_layout_nb_channels(wantChLayout)) {
- wantChLayout = av_get_default_channel_layout(availNbChan);
- wantChLayout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
+ if(wantChLayout->nb_channels != availNbChan || wantChLayout->order != AV_CHANNEL_ORDER_NATIVE) {
+ av_channel_layout_uninit(wantChLayout);
+ av_channel_layout_default(wantChLayout, availNbChan);
}
m_alDev = alcOpenDevice(nullptr);
@@ -212,10 +214,14 @@ AudioDecoder::open(int64_t wantChLayout, int wantNbChan, int wantSampleRate)
m_fmtTgt.fmt = AV_SAMPLE_FMT_S16;
m_fmtTgt.freq = wantSampleRate;
- m_fmtTgt.channelLayout = wantChLayout;
- m_fmtTgt.channels = availNbChan;
- m_fmtTgt.frameSize = av_samples_get_buffer_size(nullptr, m_fmtTgt.channels, 1, m_fmtTgt.fmt, 1);
- m_fmtTgt.bytesPerSec = av_samples_get_buffer_size(nullptr, m_fmtTgt.channels, m_fmtTgt.freq, m_fmtTgt.fmt, 1);
+ if((err = av_channel_layout_copy(&m_fmtTgt.chLayout, wantChLayout)) < 0) {
+ av_log(nullptr, AV_LOG_ERROR, "av_channel_layout_copy() failed (errL %d).\n", err);
+ close();
+ return false;
+ }
+
+ m_fmtTgt.frameSize = av_samples_get_buffer_size(nullptr, m_fmtTgt.chLayout.nb_channels, 1, m_fmtTgt.fmt, 1);
+ m_fmtTgt.bytesPerSec = av_samples_get_buffer_size(nullptr, m_fmtTgt.chLayout.nb_channels, m_fmtTgt.freq, m_fmtTgt.fmt, 1);
if(m_fmtTgt.bytesPerSec <= 0 || m_fmtTgt.frameSize <= 0) {
av_log(nullptr, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n");
close();
@@ -349,47 +355,44 @@ AudioDecoder::syncAudio(int nbSamples)
int
AudioDecoder::decodeFrame(Frame *af)
{
+ // CONVERTED maxrd2
if(af->serial != m_queue->serial())
return -1;
- int dataSize = av_samples_get_buffer_size(nullptr, af->frame->channels,
+ int dataSize = av_samples_get_buffer_size(nullptr, af->frame->ch_layout.nb_channels,
af->frame->nb_samples,
(AVSampleFormat)af->frame->format, 1);
int resampledDataSize;
- uint64_t decChannelLayout =
- (af->frame->channel_layout &&
- af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
- af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels);
int wantedNbSamples = syncAudio(af->frame->nb_samples);
if(af->frame->format != m_fmtSrc.fmt
- || decChannelLayout != m_fmtSrc.channelLayout
+ || av_channel_layout_compare(&af->frame->ch_layout, &m_fmtSrc.chLayout)
|| af->frame->sample_rate != m_fmtSrc.freq
|| (wantedNbSamples != af->frame->nb_samples && !m_swrCtx)) {
swr_free(&m_swrCtx);
- m_swrCtx = swr_alloc_set_opts(nullptr,
- m_fmtTgt.channelLayout, m_fmtTgt.fmt, m_fmtTgt.freq,
- decChannelLayout, (AVSampleFormat)af->frame->format, af->frame->sample_rate,
- 0, nullptr);
+ swr_alloc_set_opts2(&m_swrCtx,
+ &m_fmtTgt.chLayout, m_fmtTgt.fmt, m_fmtTgt.freq,
+ &af->frame->ch_layout, AVSampleFormat(af->frame->format), af->frame->sample_rate,
+ 0, nullptr);
if(!m_swrCtx || swr_init(m_swrCtx) < 0) {
av_log(nullptr, AV_LOG_ERROR,
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
af->frame->sample_rate, av_get_sample_fmt_name((AVSampleFormat)af->frame->format),
- af->frame->channels,
- m_fmtTgt.freq, av_get_sample_fmt_name(m_fmtTgt.fmt), m_fmtTgt.channels);
+ af->frame->ch_layout.nb_channels,
+ m_fmtTgt.freq, av_get_sample_fmt_name(m_fmtTgt.fmt), m_fmtTgt.chLayout.nb_channels);
swr_free(&m_swrCtx);
return -1;
}
- m_fmtSrc.channelLayout = decChannelLayout;
- m_fmtSrc.channels = af->frame->channels;
+ if(av_channel_layout_copy(&m_fmtSrc.chLayout, &af->frame->ch_layout) < 0)
+ return -1;
m_fmtSrc.freq = af->frame->sample_rate;
m_fmtSrc.fmt = (AVSampleFormat)af->frame->format;
}
if(m_swrCtx) {
const int outCount = (int64_t)wantedNbSamples * m_fmtTgt.freq / af->frame->sample_rate + 256;
- const int outSize = av_samples_get_buffer_size(nullptr, m_fmtTgt.channels, outCount, m_fmtTgt.fmt, 0);
+ const int outSize = av_samples_get_buffer_size(nullptr, m_fmtTgt.chLayout.nb_channels, outCount, m_fmtTgt.fmt, 0);
if(outSize < 0) {
av_log(nullptr, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
return -1;
@@ -417,7 +420,7 @@ AudioDecoder::decodeFrame(Frame *af)
swr_free(&m_swrCtx);
}
m_audioBuf = m_audioBuf1;
- resampledDataSize = outSamplesPerChannel * m_fmtTgt.channels * av_get_bytes_per_sample(m_fmtTgt.fmt);
+ resampledDataSize = outSamplesPerChannel * m_fmtTgt.chLayout.nb_channels * av_get_bytes_per_sample(m_fmtTgt.fmt);
} else {
m_audioBuf = af->frame->data[0];
resampledDataSize = dataSize;
diff --git a/src/videoplayer/backend/audiodecoder.h b/src/videoplayer/backend/audiodecoder.h
index ae579078..5b32b9a3 100644
--- a/src/videoplayer/backend/audiodecoder.h
+++ b/src/videoplayer/backend/audiodecoder.h
@@ -37,8 +37,7 @@ private:
struct Params {
int freq;
- int channels;
- uint64_t channelLayout;
+ AVChannelLayout chLayout;
AVSampleFormat fmt;
int frameSize;
int bytesPerSec;
@@ -50,7 +49,7 @@ private:
void queueBuffer(uint8_t *data, int len);
int syncAudio(int nbSamples);
- bool open(int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate);
+ bool open(AVChannelLayout *wantChLayout, int wantSampleRate);
void close();
void flush();
void play();
diff --git a/src/videoplayer/backend/streamdemuxer.cpp b/src/videoplayer/backend/streamdemuxer.cpp
index 72d21896..2eb59af1 100644
--- a/src/videoplayer/backend/streamdemuxer.cpp
+++ b/src/videoplayer/backend/streamdemuxer.cpp
@@ -233,9 +233,9 @@ StreamDemuxer::componentOpen(int streamIndex)
AVCodecContext *avCtx;
const AVCodec *codec;
AVDictionary *opts = nullptr;
- AVDictionaryEntry *t = nullptr;
- int sampleRate, nbChannels;
- int64_t channelLayout;
+ const AVDictionaryEntry *t = nullptr;
+ int sampleRate;
+ AVChannelLayout chLayout = {};
int ret = 0;
int stream_lowres = m_vs->lowres;
@@ -301,19 +301,21 @@ StreamDemuxer::componentOpen(int streamIndex)
switch(avCtx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
sampleRate = avCtx->sample_rate;
- nbChannels = avCtx->channels;
- channelLayout = avCtx->channel_layout;
+ if((ret = av_channel_layout_copy(&chLayout, &avCtx->ch_layout)) < 0) {
+ av_log(nullptr, AV_LOG_ERROR, "av_channel_layout_copy() failed (errL %d).\n", ret);
+ goto fail;
+ }
// prepare audio output
- if(!m_vs->audDec.open(channelLayout, nbChannels, sampleRate))
+ if(!m_vs->audDec.open(&chLayout, sampleRate))
goto fail;
m_vs->audStreamIdx = streamIndex;
m_vs->audStream = ic->streams[streamIndex];
m_vs->audDec.init(avCtx, &m_vs->audPQ, nullptr, m_vs->continueReadThread);
- if((m_vs->fmtContext->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) &&
- !m_vs->fmtContext->iformat->read_seek) {
+ if((m_vs->fmtContext->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK))
+ && !m_vs->fmtContext->iformat->read_seek) {
m_vs->audDec.startPts(m_vs->audStream->start_time, m_vs->audStream->time_base);
}
m_vs->audDec.start();
@@ -342,6 +344,7 @@ StreamDemuxer::componentOpen(int streamIndex)
fail:
avcodec_free_context(&avCtx);
out:
+ av_channel_layout_uninit(&chLayout);
av_dict_free(&opts);
return ret;
@@ -397,8 +400,7 @@ StreamDemuxer::cycleStream(int codecType)
/* check that parameters are OK */
switch(codecType) {
case AVMEDIA_TYPE_AUDIO:
- if(st->codecpar->sample_rate != 0 &&
- st->codecpar->channels != 0)
+ if(st->codecpar->sample_rate != 0 && st->codecpar->ch_layout.nb_channels != 0)
goto the_end;
break;
case AVMEDIA_TYPE_VIDEO:
diff --git a/src/videoplayer/backend/videostate.cpp b/src/videoplayer/backend/videostate.cpp
index e34399df..a09f2466 100644
--- a/src/videoplayer/backend/videostate.cpp
+++ b/src/videoplayer/backend/videostate.cpp
@@ -131,7 +131,7 @@ VideoState::notifyLoaded()
continue;
*streamName += QStringLiteral(": ");
- AVDictionaryEntry *tag = av_dict_get(stream->metadata, "lang", nullptr, AV_DICT_IGNORE_SUFFIX);
+ const AVDictionaryEntry *tag = av_dict_get(stream->metadata, "lang", nullptr, AV_DICT_IGNORE_SUFFIX);
*streamName += tag ? QString("%2 (%3)").arg(LanguageCode::nameFromIso(tag->value)).arg(tag->value) : QStringLiteral("Unknown");
if((tag = av_dict_get(stream->metadata, "title", nullptr, 0)) != nullptr)
--
2.46.0