rather large commit, it now handles memory and threading properly.
--- more thorough commit message which was generated by the wonderful copilot AI tool: Refactor and enhance audio encoding and decoding pipelines - Introduced CodecUtils.h for utility functions related to audio codec selection, including sample format and bitrate clamping. - Added DecoderPipeline.h to manage audio decoding, including opening files and retrieving audio stream information. - Implemented EncoderPipeline.h to handle audio encoding, including encoder setup, resampling, and writing output files. - Created OutputPathBuilder.h to generate output file paths based on reencode job specifications. - Refactored SpectrogramWidget to improve OpenGL handling and ensure safe context usage. - Updated ReencodeDialog.h to enhance code readability and maintainability. - Improved error handling and logging throughout the audio processing components.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "FfmpegGuards.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
namespace engine {
|
||||
|
||||
|
||||
struct DecoderPipeline
|
||||
{
|
||||
FmtCtxIn fmtCtx; // owns AVFormatContext*
|
||||
CodecCtxGuard ctx; // owns AVCodecContext*
|
||||
AVStream *stream = nullptr; // non-owning; lifetime == fmtCtx
|
||||
|
||||
// open filelPath find audiostream and open decoder for it, returns false and sets errorout on any failure
|
||||
bool open(const QString &filePath, QString *errorOut)
|
||||
{
|
||||
AVDictionary *opts = nullptr;
|
||||
av_dict_set(&opts, "probesize", "5000000", 0);
|
||||
av_dict_set(&opts, "analyzeduration", "5000000", 0);
|
||||
int err = avformat_open_input(&fmtCtx.p,
|
||||
filePath.toUtf8().constData(),
|
||||
nullptr, &opts);
|
||||
av_dict_free(&opts);
|
||||
if (err < 0) {
|
||||
if (errorOut) *errorOut = "Cannot open input file";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (avformat_find_stream_info(fmtCtx.p, nullptr) < 0) {
|
||||
if (errorOut) *errorOut = "Cannot read stream info";
|
||||
return false;
|
||||
}
|
||||
|
||||
const int audioIdx = av_find_best_stream(
|
||||
fmtCtx.p, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
|
||||
if (audioIdx < 0) {
|
||||
if (errorOut) *errorOut = "No audio stream found";
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = fmtCtx.p->streams[audioIdx];
|
||||
|
||||
const AVCodec *decoder =
|
||||
avcodec_find_decoder(stream->codecpar->codec_id);
|
||||
if (!decoder) {
|
||||
if (errorOut) *errorOut = "No decoder for input codec";
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx.p = avcodec_alloc_context3(decoder);
|
||||
if (!ctx.p) {
|
||||
if (errorOut) *errorOut = "OOM: decoder context";
|
||||
return false;
|
||||
}
|
||||
|
||||
avcodec_parameters_to_context(ctx.p, stream->codecpar);
|
||||
ctx.p->pkt_timebase = stream->time_base;
|
||||
|
||||
if (avcodec_open2(ctx.p, decoder, nullptr) < 0) {
|
||||
if (errorOut) *errorOut = "Cannot open decoder";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// accessors after successful open()
|
||||
int audioStreamIndex() const
|
||||
{
|
||||
return stream ? static_cast<int>(stream - fmtCtx.p->streams[0]) : -1;
|
||||
}
|
||||
|
||||
int channels() const { return ctx.p ? ctx.p->ch_layout.nb_channels : 0; }
|
||||
int sampleRate() const { return ctx.p ? ctx.p->sample_rate : 0; }
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
Reference in New Issue
Block a user