Files
SubWave/src/engine/encoder/DecoderPipeline.h
T
rattatwinko 1a00e98661 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.
2026-07-01 09:56:37 +02:00

85 lines
2.5 KiB
C++

#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