diff --git a/libraries/recording/src/recording/Clip.cpp b/libraries/recording/src/recording/Clip.cpp index abe66ccb2e..1451724f23 100644 --- a/libraries/recording/src/recording/Clip.cpp +++ b/libraries/recording/src/recording/Clip.cpp @@ -13,6 +13,11 @@ #include "impl/FileClip.h" #include "impl/BufferClip.h" +#include +#include +#include +#include + using namespace recording; Clip::Pointer Clip::fromFile(const QString& filePath) { @@ -27,6 +32,15 @@ void Clip::toFile(const QString& filePath, const Clip::ConstPointer& clip) { FileClip::write(filePath, clip->duplicate()); } +QByteArray Clip::toBuffer(const Clip::ConstPointer& clip) { + QBuffer buffer; + if (buffer.open(QFile::Truncate | QFile::WriteOnly)) { + clip->duplicate()->write(buffer); + buffer.close(); + } + return buffer.data(); +} + Clip::Pointer Clip::newClip() { return std::make_shared(); } @@ -37,4 +51,70 @@ void Clip::seek(float offset) { float Clip::position() const { return Frame::frameTimeToSeconds(positionFrameTime()); -}; +} + +// FIXME move to frame? +bool writeFrame(QIODevice& output, const Frame& frame, bool compressed = true) { + if (frame.type == Frame::TYPE_INVALID) { + qWarning() << "Attempting to write invalid frame"; + return true; + } + + auto written = output.write((char*)&(frame.type), sizeof(FrameType)); + if (written != sizeof(FrameType)) { + return false; + } + //qDebug() << "Writing frame with time offset " << frame.timeOffset; + written = output.write((char*)&(frame.timeOffset), sizeof(Frame::Time)); + if (written != sizeof(Frame::Time)) { + return false; + } + QByteArray frameData = frame.data; + if (compressed) { + frameData = qCompress(frameData); + } + + uint16_t dataSize = frameData.size(); + written = output.write((char*)&dataSize, sizeof(FrameSize)); + if (written != sizeof(uint16_t)) { + return false; + } + + if (dataSize != 0) { + written = output.write(frameData); + if (written != dataSize) { + return false; + } + } + return true; +} + +const QString Clip::FRAME_TYPE_MAP = QStringLiteral("frameTypes"); +const QString Clip::FRAME_COMREPSSION_FLAG = QStringLiteral("compressed"); + +bool Clip::write(QIODevice& output) { + auto frameTypes = Frame::getFrameTypes(); + QJsonObject frameTypeObj; + for (const auto& frameTypeName : frameTypes.keys()) { + frameTypeObj[frameTypeName] = frameTypes[frameTypeName]; + } + + QJsonObject rootObject; + rootObject.insert(FRAME_TYPE_MAP, frameTypeObj); + // Always mark new files as compressed + rootObject.insert(FRAME_COMREPSSION_FLAG, true); + QByteArray headerFrameData = QJsonDocument(rootObject).toBinaryData(); + // Never compress the header frame + if (!writeFrame(output, Frame({ Frame::TYPE_HEADER, 0, headerFrameData }), false)) { + return false; + } + + seek(0); + + for (auto frame = nextFrame(); frame; frame = nextFrame()) { + if (!writeFrame(output, *frame)) { + return false; + } + } + return true; +} diff --git a/libraries/recording/src/recording/Clip.h b/libraries/recording/src/recording/Clip.h index 722fadf0b2..1fdad39da7 100644 --- a/libraries/recording/src/recording/Clip.h +++ b/libraries/recording/src/recording/Clip.h @@ -47,10 +47,16 @@ public: virtual void skipFrame() = 0; virtual void addFrame(FrameConstPointer) = 0; + bool write(QIODevice& output); + static Pointer fromFile(const QString& filePath); static void toFile(const QString& filePath, const ConstPointer& clip); + static QByteArray toBuffer(const ConstPointer& clip); static Pointer newClip(); + static const QString FRAME_TYPE_MAP; + static const QString FRAME_COMREPSSION_FLAG; + protected: friend class WrapperClip; using Mutex = std::recursive_mutex; diff --git a/libraries/recording/src/recording/impl/FileClip.cpp b/libraries/recording/src/recording/impl/FileClip.cpp index ce2705a76c..b153f5aa4a 100644 --- a/libraries/recording/src/recording/impl/FileClip.cpp +++ b/libraries/recording/src/recording/impl/FileClip.cpp @@ -11,8 +11,6 @@ #include #include -#include -#include #include @@ -40,41 +38,7 @@ QString FileClip::getName() const { return _file.fileName(); } -// FIXME move to frame? -bool writeFrame(QIODevice& output, const Frame& frame, bool compressed = true) { - if (frame.type == Frame::TYPE_INVALID) { - qWarning() << "Attempting to write invalid frame"; - return true; - } - auto written = output.write((char*)&(frame.type), sizeof(FrameType)); - if (written != sizeof(FrameType)) { - return false; - } - //qDebug() << "Writing frame with time offset " << frame.timeOffset; - written = output.write((char*)&(frame.timeOffset), sizeof(Frame::Time)); - if (written != sizeof(Frame::Time)) { - return false; - } - QByteArray frameData = frame.data; - if (compressed) { - frameData = qCompress(frameData); - } - - uint16_t dataSize = frameData.size(); - written = output.write((char*)&dataSize, sizeof(FrameSize)); - if (written != sizeof(uint16_t)) { - return false; - } - - if (dataSize != 0) { - written = output.write(frameData); - if (written != dataSize) { - return false; - } - } - return true; -} bool FileClip::write(const QString& fileName, Clip::Pointer clip) { // FIXME need to move this to a different thread @@ -90,33 +54,7 @@ bool FileClip::write(const QString& fileName, Clip::Pointer clip) { } Finally closer([&] { outputFile.close(); }); - { - auto frameTypes = Frame::getFrameTypes(); - QJsonObject frameTypeObj; - for (const auto& frameTypeName : frameTypes.keys()) { - frameTypeObj[frameTypeName] = frameTypes[frameTypeName]; - } - - QJsonObject rootObject; - rootObject.insert(FRAME_TYPE_MAP, frameTypeObj); - // Always mark new files as compressed - rootObject.insert(FRAME_COMREPSSION_FLAG, true); - QByteArray headerFrameData = QJsonDocument(rootObject).toBinaryData(); - // Never compress the header frame - if (!writeFrame(outputFile, Frame({ Frame::TYPE_HEADER, 0, headerFrameData }), false)) { - return false; - } - - } - - clip->seek(0); - for (auto frame = clip->nextFrame(); frame; frame = clip->nextFrame()) { - if (!writeFrame(outputFile, *frame)) { - return false; - } - } - outputFile.close(); - return true; + return clip->write(outputFile); } FileClip::~FileClip() { diff --git a/libraries/recording/src/recording/impl/PointerClip.cpp b/libraries/recording/src/recording/impl/PointerClip.cpp index 48132c066d..6f74391b4b 100644 --- a/libraries/recording/src/recording/impl/PointerClip.cpp +++ b/libraries/recording/src/recording/impl/PointerClip.cpp @@ -23,16 +23,13 @@ using namespace recording; -const QString PointerClip::FRAME_TYPE_MAP = QStringLiteral("frameTypes"); -const QString PointerClip::FRAME_COMREPSSION_FLAG = QStringLiteral("compressed"); - using FrameTranslationMap = QMap; FrameTranslationMap parseTranslationMap(const QJsonDocument& doc) { FrameTranslationMap results; auto headerObj = doc.object(); - if (headerObj.contains(PointerClip::FRAME_TYPE_MAP)) { - auto frameTypeObj = headerObj[PointerClip::FRAME_TYPE_MAP].toObject(); + if (headerObj.contains(Clip::FRAME_TYPE_MAP)) { + auto frameTypeObj = headerObj[Clip::FRAME_TYPE_MAP].toObject(); auto currentFrameTypes = Frame::getFrameTypes(); for (auto frameTypeName : frameTypeObj.keys()) { qDebug() << frameTypeName; diff --git a/libraries/recording/src/recording/impl/PointerClip.h b/libraries/recording/src/recording/impl/PointerClip.h index 5a7a3499fe..f5c0dd6bc4 100644 --- a/libraries/recording/src/recording/impl/PointerClip.h +++ b/libraries/recording/src/recording/impl/PointerClip.h @@ -44,9 +44,6 @@ public: // FIXME move to frame? static const qint64 MINIMUM_FRAME_SIZE = sizeof(FrameType) + sizeof(Frame::Time) + sizeof(FrameSize); - static const QString FRAME_TYPE_MAP; - static const QString FRAME_COMREPSSION_FLAG; - protected: void reset(); virtual FrameConstPointer readFrame(size_t index) const override;