Sélectionner une révision Git
-
Kubat a rédigé
The error was that passing to threads the pointer to a variable that will be copied then destroyed before the end of the thread is a really bad idea
Kubat a rédigéThe error was that passing to threads the pointer to a variable that will be copied then destroyed before the end of the thread is a really bad idea
Audio.hh 4,84 Kio
#pragma once
#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 <memory.h>
}
#include "Utils.hh"
#include <QtGlobal>
#include <QMap>
#include <QVector>
#include <QString>
namespace Vivy
{
class AudioContext;
// 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 AudioContext final {
VIVY_UNMOVABLE_OBJECT(AudioContext)
public:
// Hold all the data for a stream in an audio file. Should only be owned by
// the AudioContext class.
class Stream final {
VIVY_UNMOVABLE_OBJECT(Stream)
static inline Utils::DeleterFunctionType<double> dataDeleter =
std::bind_front(Utils::freePtrIfNotNull<double>, av_free);
static inline Utils::DeleterFunctionType<AVCodecContext> codecContexteleter =
std::bind_front(Utils::freePPtrIfNotNull<AVCodecContext>, avcodec_free_context);
static inline Utils::DeleterFunctionType<AVFrame> avFrameDeleter =
std::bind_front(Utils::freePPtrIfNotNull<AVFrame>, av_frame_free);
static inline Utils::DeleterFunctionType<SwrContext> swrContenxtDeleter =
std::bind_front(Utils::freePPtrIfNotNull<SwrContext>, swr_free);
// All the used types
using AVCodecContextPtr = std::unique_ptr<AVCodecContext, decltype(codecContexteleter)>;
using DataPtr = std::shared_ptr<double[]>;
using AVFramePtr = std::unique_ptr<AVFrame, decltype(avFrameDeleter)>;
using SwrContextPtr = std::unique_ptr<SwrContext, decltype(swrContenxtDeleter)>;
public:
Stream(AVCodec *, AVFormatContext *, AVStream *, int index);
~Stream() noexcept;
// The non-owning view of the stream's data
using DataWeakPtr = std::weak_ptr<double[]>;
// Decode the stream
void decodeData();
void cleanUpData() noexcept;
bool isDecoded() const noexcept;
int getDataSampleRate() const noexcept;
size_t getDecodedDataSize() const noexcept;
size_t getDecodedChunkSize() const noexcept;
size_t getDecodedDecalage() const noexcept;
double *getDecodedData() const noexcept;
// Some getters
int getChannels() const noexcept;
int getSampleRate() const noexcept;
QString getName() const noexcept;
AVCodecID getCodecId() const noexcept;
qint64 getBitRate() const noexcept;
// Get the index from the audio context
int getStreamIndex() const noexcept;
QJsonObject getProperties() const noexcept;
private:
// Codec related informations
AVCodecID codecId{ AV_CODEC_ID_NONE };
AVCodec *codec{ nullptr };
AVCodecParameters *codecParams{ nullptr };
AVCodecContextPtr codecContext{ nullptr };
// Stream is held by AudioContext
AVStream *audioStream{ nullptr };
// Store the index of this stream
int streamIndexInAudioContext;
// Resampled frame data
AVFormatContext *dataFormat;
SwrContextPtr dataSwrContext{ swr_alloc(), swrContenxtDeleter };
AVFramePtr dataFrame{ av_frame_alloc(), avFrameDeleter };
double *dataPtr{ nullptr };
size_t dataSize{ 0 };
// Constants for the resampler
static constexpr uint resamplerChunkSize = 512;
static constexpr uint resamplerOverlap = 128;
static constexpr uint resamplerDecalage = resamplerChunkSize - resamplerOverlap;
static constexpr uint resamplerSampleRate = 44100;
};
using StreamPtr = std::shared_ptr<Stream>;
using StreamWeakPtr = std::weak_ptr<Stream>;
public:
AudioContext(const QString &path);
StreamWeakPtr getStream(int) const noexcept;
StreamWeakPtr getDefaultStream() const noexcept;
QString getElementName() const noexcept;
QJsonDocument getProperties() const noexcept;
private:
// Regarding the format
static inline Utils::DeleterFunctionType<AVFormatContext> avFormatContextDeleter =
std::bind_front(Utils::freePtrIfNotNull<AVFormatContext>, avformat_free_context);
using AVFormatContextPtr = std::unique_ptr<AVFormatContext, decltype(avFormatContextDeleter)>;
AVFormatContextPtr format{ avformat_alloc_context(), avFormatContextDeleter };
const QString filePath; // Usefull information
QMap<uint, StreamPtr> audioStreams{}; // THe audio streams of the file
int defaultStreamIndex{ -1 };
// Spare always null shared pointer, to be used when the audioStream[i] was
// not found.
StreamPtr spareNullSreamPtr{ nullptr };
};
}