From 65d0fa3482f8d91de65d9bfb9a38903392b66877 Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Tue, 29 Jun 2021 23:13:22 +0200 Subject: [PATCH] AUDIO: Interface for the audio decoding/property getting should be OK --- src/Audio.hh | 133 ++++++++++++++++++++++++++++++++++++++++++++++ src/AudioUtils.cc | 1 + 2 files changed, 134 insertions(+) create mode 100644 src/Audio.hh diff --git a/src/Audio.hh b/src/Audio.hh new file mode 100644 index 00000000..67ef3315 --- /dev/null +++ b/src/Audio.hh @@ -0,0 +1,133 @@ +#ifndef VIVY_AUDIO_H +#define VIVY_AUDIO_H + +#ifndef __cplusplus +#error "This is a C++ header" +#endif + +extern "C" { +#include <libavutil/opt.h> +#include <libavcodec/avcodec.h> +#include <libavformat/avformat.h> +#include <libswresample/swresample.h> +#include <libavcodec/avfft.h> +} + +#include "Utils.hh" +#include <QtGlobal> +#include <QMap> +#include <QVector> +#include <memory.h> + +namespace Vivy +{ +/* Hold all the data for a stream in an audio file. Should only be owned by the + * AudioFormatCtx class. + */ +class AudioStreamCodec final { + VIVY_UNMOVABLE_OBJECT(AudioStreamCodec) + + // All the needed deleters + static inline constexpr auto codecContexteleter = [](AVCodecContext *ptr) noexcept -> void { + if (ptr) + avcodec_free_context(&ptr); + }; + static constexpr inline auto dataDeleter = [](double *ptr) noexcept -> void { + if (ptr) + av_free(ptr); + }; + static constexpr inline auto avFrameDeleter = [](AVFrame *ptr) noexcept -> void { + if (ptr) + av_frame_free(&ptr); + }; + + static constexpr inline auto swrContenxtDeleter = [](SwrContext *swr) noexcept -> void { + if (swr) + swr_free(&swr); + }; + + // All the used types + using AVCodecContextPtr = std::unique_ptr<AVCodecContext, decltype(codecContexteleter)>; + using DataPtr = std::shared_ptr<double[]>; + using DataWeakPtr = std::weak_ptr<double[]>; + using AVFramePtr = std::unique_ptr<AVFrame, decltype(avFrameDeleter)>; + using SwrContextPtr = std::unique_ptr<SwrContext, decltype(swrContenxtDeleter)>; + +public: + AudioStreamCodec(AVStream *); + ~AudioStreamCodec(); + + // Decode the stream + void decodeData(); + size_t getDecodedDataSize() const noexcept; + DataWeakPtr getDecodedData() const noexcept; + + // Some getters + int getChannels() const noexcept; + int getSampleRate() const noexcept; + const char *getName() const noexcept; + AVCodecID getCodecId() const noexcept; + qint64 getBitRate() const noexcept; + +private: + bool initFromStream() noexcept; // Init all the object + void cleanupForReuse() noexcept; // Free everything, can now use initFromStream again + + // Check if ready + bool isReadyForUse() const noexcept; + bool isResampled() const noexcept; + + // Codec related informations + AVCodecID codecId{ AV_CODEC_ID_NONE }; + AVCodecContextPtr codecContext{ nullptr }; + AVCodecParameters *codecParams{ nullptr }; + AVCodec *codec{ nullptr }; + + // Stream is held by AudioFormatCtx + AVStream *audioStream{ nullptr }; + bool isInitFromStream{ false }; + + // Resampled frame data + SwrContextPtr dataSwrContext{ nullptr, swrContenxtDeleter }; + AVFramePtr dataFrame{ nullptr, avFrameDeleter }; + DataPtr dataPtr{ nullptr, dataDeleter }; + size_t dataSize{ 0 }; +}; + +/* Facility for pointers to AudioStreamCodec objects */ +using AudioStreamCodecPtr = std::shared_ptr<AudioStreamCodec>; +using AudioStreamCodecWeakPtr = std::weak_ptr<AudioStreamCodec>; + +/* The memory representation of an audio file. It is created inplace and should + * not be moved around. It should be used to get the properties of an audio + * file and its streams. The user can use a stream from the file and get data + * from it. + */ +class AudioFormatCtx final { + VIVY_UNMOVABLE_OBJECT(AudioFormatCtx) + +public: + AudioFormatCtx(const QString &path); + ~AudioFormatCtx() noexcept; + + int getStreamCount() const noexcept; + AudioStreamCodecWeakPtr getStream(int) const noexcept; + +private: + /* Regarding the format */ + static inline constexpr auto avFormatContextDeleter = + [](AVFormatContext *ptr) noexcept -> void { + if (ptr) + avformat_free_context(ptr); + }; + using AVFormatContextPtr = std::unique_ptr<AVFormatContext, decltype(avFormatContextDeleter)>; + AVFormatContextPtr format{ nullptr }; + + /* Usefull information */ + QString filePath; + QVector<uint> audioStreamIndexes{}; + QMap<uint, AudioStreamCodecPtr> audioCodecs{}; +}; +} + +#endif // VIVY_AUDIO_H diff --git a/src/AudioUtils.cc b/src/AudioUtils.cc index cab709b2..fde8a4cc 100644 --- a/src/AudioUtils.cc +++ b/src/AudioUtils.cc @@ -1,4 +1,5 @@ #include "AudioUtils.hh" +#include "Audio.hh" // Will be renamed into AudioUtils.hh ... #define MAXPIXVALUE 7 /* Some magix AV magic stuff */ -- GitLab