Support writing a clip to a qbytearray

This commit is contained in:
Brad Davis 2015-11-19 20:23:50 -08:00
parent e6db72c887
commit 5adcbcaf5f
5 changed files with 90 additions and 72 deletions

View file

@ -13,6 +13,11 @@
#include "impl/FileClip.h"
#include "impl/BufferClip.h"
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QBuffer>
#include <QtCore/QDebug>
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<BufferClip>();
}
@ -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;
}

View file

@ -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;

View file

@ -11,8 +11,6 @@
#include <algorithm>
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <Finally.h>
@ -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() {

View file

@ -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<FrameType, FrameType>;
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;

View file

@ -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;