Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 89dfcec5 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

AUDIO: Get the streams from the AudioSubDocument

parent 387c7be5
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!5Add AudioContext to AudioSubDocument
#include "CRTPSubDocument.hh"
using namespace Vivy;
// AudioSubDocument implementation
// Get the default stream index or -1 if not possible
int
AudioSubDocument::getDefaultStreamIndex() const noexcept
{
if (auto ptr = getDefaultStream()) {
return ptr->getStreamIndex();
} else {
return -1;
}
}
// Get a pointer to the default stream, nullptr if not possible
AudioContext::StreamPtr
AudioSubDocument::getDefaultStream() const noexcept
{
if (auto ptr = contextPtr->getDefaultStream().lock()) {
return ptr;
} else {
return nullptr;
}
}
// Get the stream count, may be 0
int
AudioSubDocument::getStreamCount() const noexcept
{
return contextPtr->getStreamCount();
}
// Get the stream asked for, nullptr if no stream or if the index is invalid
AudioContext::StreamPtr
AudioSubDocument::getStream(int index) const noexcept
{
if (auto ptr = contextPtr->getStream(index).lock()) {
return ptr;
} else {
return nullptr;
}
}
// Init an audio sub-document from a file
void
AudioSubDocument::initFromPath(const QString &path)
{
if (contextPtr)
qDebug() << "Replacing the audio contetx by a new one for file" << path;
contextPtr.reset(new AudioContext(path)); // May throw
qDebug() << "Audio OK for" << path;
}
// VideoSubDocument implementation
// Init a video sub-document from a file
void
VideoSubDocument::initFromPath(const QString &)
{
}
// AssSubDocument implementation
void
AssSubDocument::initFromPath(const QString &path)
{
Ass::AssFactory factory(path);
factory.getStyles(styles);
factory.getLines(lines);
}
......@@ -64,20 +64,19 @@ class AudioSubDocument final : public CRTPSubDocument<AudioDocumentType, AudioSu
private:
const QStringList &suffixList = Vivy::Utils::audioFileSuffix;
inline void initFromPath(const QString &path)
{
if (contextPtr)
qDebug() << "Replacing the audio contetx by a new one for file" << path;
contextPtr.reset(new AudioContext(path)); // May throw
qDebug() << "Audio OK for" << path;
}
void initFromPath(const QString &);
explicit AudioSubDocument() = default;
friend CRTPSubDocument<AudioDocumentType, AudioSubDocument>;
private:
std::unique_ptr<AudioContext> contextPtr;
public:
int getDefaultStreamIndex() const noexcept;
AudioContext::StreamPtr getDefaultStream() const noexcept;
int getStreamCount() const noexcept;
AudioContext::StreamPtr getStream(int index) const noexcept;
};
// Video document
......@@ -85,9 +84,7 @@ class VideoSubDocument final : public CRTPSubDocument<VideoDocumentType, VideoSu
private:
const QStringList &suffixList = Vivy::Utils::videoFileSuffix;
inline void initFromPath([[maybe_unused]] const QString &path)
{
}
void initFromPath(const QString &);
explicit VideoSubDocument() noexcept = default;
friend CRTPSubDocument<VideoDocumentType, VideoSubDocument>;
......@@ -97,12 +94,7 @@ private:
class AssSubDocument final : public CRTPSubDocument<AssDocumentType, AssSubDocument> {
const QStringList &suffixList = Vivy::Utils::assFileSuffix;
inline void initFromPath(const QString &path)
{
Ass::AssFactory factory(path);
factory.getStyles(styles);
factory.getLines(lines);
}
void initFromPath(const QString &);
explicit AssSubDocument() noexcept = default;
friend CRTPSubDocument<AssDocumentType, AssSubDocument>;
......
......@@ -39,6 +39,12 @@ AudioContext::AudioContext(const QString &path)
}
}
// Get the default stream
defaultStreamIndex = av_find_best_stream(formatPtr, AVMEDIA_TYPE_AUDIO,
-1, // Let AV find one stream
-1, // We don't want related streams
nullptr, 0);
qDebug() << "Opened audio context for" << path << "with duration" << formatPtr->duration;
}
......@@ -67,6 +73,16 @@ AudioContext::getStream(int index) const noexcept
return StreamWeakPtr{ spareNullSreamPtr };
}
// Get the default stream of this audio context. If no default audio stream is
// present you won't be able to lock the weak pointer.
AudioContext::StreamWeakPtr
AudioContext::getDefaultStream() const noexcept
{
if (defaultStreamIndex < 0)
return StreamWeakPtr{ spareNullSreamPtr };
return getStream(defaultStreamIndex);
}
QString
AudioContext::getElementName() const noexcept
{
......@@ -136,6 +152,12 @@ AudioContext::Stream::Stream(AVCodec *streamCodec, AVFormatContext *format, AVSt
qDebug() << "[Stream] channels: " << codecParams->channels;
}
AudioContext::Stream::~Stream() noexcept
{
if (dataPtr)
free(dataPtr);
}
QJsonObject
AudioContext::Stream::getProperties() const noexcept
{
......@@ -153,6 +175,7 @@ AudioContext::Stream::decodeData()
{
if (isDecoded())
throw std::logic_error("audio stream is already resampled");
qDebug() << "Launch decoding of stream" << streamIndexInAudioContext;
AVPacket packet;
av_init_packet(&packet);
......@@ -160,7 +183,7 @@ AudioContext::Stream::decodeData()
// Iterate through frames
while (av_read_frame(dataFormat, &packet) >= 0) {
// Only decode audio
if (packet.stream_index == streamIndexInAudioContext) {
if (packet.stream_index != streamIndexInAudioContext) {
av_packet_unref(&packet);
continue;
}
......@@ -208,9 +231,9 @@ AudioContext::Stream::decodeData()
// Append resampled frames to data
else [[likely]] {
const size_t frame_count = static_cast<size_t>(frame_count_int);
dataRealPtr = (double *)realloc(
dataRealPtr, (dataSize + (size_t)dataFrame->nb_samples) * sizeof(double));
memcpy(dataRealPtr + dataSize, buffer, frame_count * sizeof(double));
dataPtr = reinterpret_cast<double *>(
realloc(dataPtr, (dataSize + (size_t)dataFrame->nb_samples) * sizeof(double)));
memcpy(dataPtr + dataSize, buffer, frame_count * sizeof(double));
dataSize += frame_count;
}
}
......@@ -218,14 +241,17 @@ AudioContext::Stream::decodeData()
dataDeleter(buffer);
av_packet_unref(&packet);
}
qDebug() << "Decoding data finished for stream" << streamIndexInAudioContext
<< "dataPtr =" << dataPtr << "with dataSize =" << dataSize;
}
// Delete decoded data, clean up thing
void
AudioContext::Stream::cleanUpData() noexcept
{
dataPtr.reset();
dataRealPtr = nullptr;
free(dataPtr);
dataPtr = nullptr;
dataSize = 0;
}
......@@ -276,7 +302,7 @@ AudioContext::Stream::getBitRate() const noexcept
bool
AudioContext::Stream::isDecoded() const noexcept
{
return dataPtr != nullptr && dataRealPtr != nullptr;
return dataPtr != nullptr;
}
// Get the decoded data's size, will return 0 if the data is not decoded. Don't
......@@ -288,11 +314,30 @@ AudioContext::Stream::getDecodedDataSize() const noexcept
}
// Get the decoded data, safe to call even if the data is not decoded has the
// weak pointer will be marked as already deleted (use_count will be 0 and
// `(auto ptr = res.lock())` will be evaluated to false if inside an `if`
// statement).
AudioContext::Stream::DataWeakPtr
// pointer will be null. You must check it with an `if` statement.
double *
AudioContext::Stream::getDecodedData() const noexcept
{
return DataWeakPtr{ dataPtr };
return dataPtr;
}
// Get the chunk size of the decoded data
size_t
AudioContext::Stream::getDecodedChunkSize() const noexcept
{
return 512;
}
// Get the decalage of the decoded data
size_t
AudioContext::Stream::getDecodedDecalage() const noexcept
{
constexpr size_t overlap = 128; // The overlap
return getDecodedChunkSize() - overlap;
}
int
AudioContext::Stream::getStreamIndex() const noexcept
{
return streamIndexInAudioContext;
}
......@@ -64,7 +64,7 @@ public:
public:
Stream(AVCodec *, AVFormatContext *, AVStream *, int index);
~Stream() = default;
~Stream() noexcept;
// The non-owning view of the stream's data
using DataWeakPtr = std::weak_ptr<double[]>;
......@@ -75,7 +75,9 @@ public:
bool isDecoded() const noexcept;
int getDataSampleRate() const noexcept;
size_t getDecodedDataSize() const noexcept;
DataWeakPtr getDecodedData() const noexcept;
size_t getDecodedChunkSize() const noexcept;
size_t getDecodedDecalage() const noexcept;
double *getDecodedData() const noexcept;
// Some getters
int getChannels() const noexcept;
......@@ -84,6 +86,9 @@ public:
AVCodecID getCodecId() const noexcept;
qint64 getBitRate() const noexcept;
// Get the index from the audio context
int getStreamIndex() const noexcept;
QJsonObject getProperties() const noexcept;
private:
......@@ -103,8 +108,7 @@ public:
AVFormatContext *dataFormat;
SwrContextPtr dataSwrContext{ swr_alloc(), swrContenxtDeleter };
AVFramePtr dataFrame{ av_frame_alloc(), avFrameDeleter };
DataPtr dataPtr{ nullptr, dataDeleter }; // Holds dataRealPtr
double *dataRealPtr{ nullptr };
double *dataPtr{ nullptr };
size_t dataSize{ 0 };
// Constants for the resampler
......@@ -125,6 +129,7 @@ public:
int getStreamCount() const noexcept;
StreamWeakPtr getStream(int) const noexcept;
StreamWeakPtr getDefaultStream() const noexcept;
QString getElementName() const noexcept;
QJsonDocument getProperties() const noexcept;
......@@ -143,6 +148,8 @@ private:
QVector<uint> audioStreamIndexes{}; // Index all the audio streams of the file
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 };
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter