mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 05:52:38 +02:00
Add recording classes
This commit is contained in:
parent
5713f19fa4
commit
0bf29a441f
20 changed files with 832 additions and 3 deletions
|
@ -102,7 +102,7 @@ endif()
|
|||
|
||||
# link required hifi libraries
|
||||
link_hifi_libraries(shared octree environment gpu gl procedural model render
|
||||
fbx networking model-networking entities avatars
|
||||
recording fbx networking model-networking entities avatars
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer ui auto-updater
|
||||
controllers plugins display-plugins input-plugins )
|
||||
|
|
48
libraries/recording/src/recording/Clip.cpp
Normal file
48
libraries/recording/src/recording/Clip.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Clip.h"
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
#include "impl/FileClip.h"
|
||||
#include "impl/BufferClip.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
Clip::Pointer Clip::fromFile(const QString& filePath) {
|
||||
return std::make_shared<FileClip>(filePath);
|
||||
}
|
||||
|
||||
void Clip::toFile(Clip::Pointer clip, const QString& filePath) {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
Clip::Pointer Clip::duplicate() {
|
||||
Clip::Pointer result = std::make_shared<BufferClip>();
|
||||
|
||||
float currentPosition = position();
|
||||
seek(0);
|
||||
|
||||
Frame::Pointer frame = nextFrame();
|
||||
while (frame) {
|
||||
result->appendFrame(frame);
|
||||
}
|
||||
|
||||
seek(currentPosition);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Clip::Pointer Clip::fromIODevice(QIODevice * device) {
|
||||
return std::make_shared<IOClip>(device);
|
||||
}
|
||||
|
||||
void Clip::fromIODevice(Clip::Pointer clip, QIODevice * device) {
|
||||
}
|
||||
#endif
|
48
libraries/recording/src/recording/Clip.h
Normal file
48
libraries/recording/src/recording/Clip.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Clip_h
|
||||
#define hifi_Recording_Clip_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace recording {
|
||||
|
||||
class Clip : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Clip>;
|
||||
|
||||
Clip(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Clip() {}
|
||||
|
||||
Pointer duplicate();
|
||||
|
||||
virtual void seek(float offset) = 0;
|
||||
virtual float position() const = 0;
|
||||
|
||||
virtual FramePointer peekFrame() const = 0;
|
||||
virtual FramePointer nextFrame() = 0;
|
||||
virtual void skipFrame() = 0;
|
||||
virtual void appendFrame(FramePointer) = 0;
|
||||
|
||||
|
||||
static Pointer fromFile(const QString& filePath);
|
||||
static void toFile(Pointer clip, const QString& filePath);
|
||||
|
||||
protected:
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
9
libraries/recording/src/recording/Deck.cpp
Normal file
9
libraries/recording/src/recording/Deck.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Deck.h"
|
37
libraries/recording/src/recording/Deck.h
Normal file
37
libraries/recording/src/recording/Deck.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Deck_h
|
||||
#define hifi_Recording_Deck_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace recording {
|
||||
|
||||
class Deck : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Deck>;
|
||||
|
||||
Deck(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Deck();
|
||||
|
||||
// Place a clip on the deck for recording or playback
|
||||
void queueClip(ClipPointer clip, float timeOffset = 0.0f);
|
||||
void play(float timeOffset = 0.0f);
|
||||
void reposition(float timeOffsetDelta);
|
||||
void setPlaybackSpeed(float rate);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,14 +15,28 @@
|
|||
|
||||
namespace recording {
|
||||
|
||||
using FrameType = uint16_t;
|
||||
|
||||
struct Frame;
|
||||
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
// A recording of some set of state from the application, usually avatar
|
||||
// data + audio for a single person
|
||||
class Clip;
|
||||
|
||||
// An interface for interacting with clips, creating them by recording or
|
||||
// playing them back. Also serialization to and from files / network sources
|
||||
using ClipPointer = std::shared_ptr<Clip>;
|
||||
|
||||
// An interface for playing back clips
|
||||
class Deck;
|
||||
|
||||
using DeckPointer = std::shared_ptr<Deck>;
|
||||
|
||||
// An interface for recording a single clip
|
||||
class Recorder;
|
||||
|
||||
using RecorderPointer = std::shared_ptr<Recorder>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
103
libraries/recording/src/recording/Frame.cpp
Normal file
103
libraries/recording/src/recording/Frame.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QMap>
|
||||
|
||||
using namespace recording;
|
||||
|
||||
// FIXME move to shared
|
||||
template <typename Key, typename Value>
|
||||
class Registry {
|
||||
public:
|
||||
using ForwardMap = QMap<Value, Key>;
|
||||
using BackMap = QMap<Key, Value>;
|
||||
static const Key INVALID_KEY = static_cast<Key>(-1);
|
||||
|
||||
Key registerValue(const Value& value) {
|
||||
Locker lock(_mutex);
|
||||
Key result = INVALID_KEY;
|
||||
if (_forwardMap.contains(value)) {
|
||||
result = _forwardMap[value];
|
||||
} else {
|
||||
_forwardMap[value] = result = _nextKey++;
|
||||
_backMap[result] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Key getKey(const Value& value) {
|
||||
Locker lock(_mutex);
|
||||
Key result = INVALID_KEY;
|
||||
if (_forwardMap.contains(value)) {
|
||||
result = _forwardMap[value];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ForwardMap getKeysByValue() {
|
||||
Locker lock(_mutex);
|
||||
ForwardMap result = _forwardMap;
|
||||
return result;
|
||||
}
|
||||
|
||||
BackMap getValuesByKey() {
|
||||
Locker lock(_mutex);
|
||||
BackMap result = _backMap;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
Mutex _mutex;
|
||||
|
||||
ForwardMap _forwardMap;
|
||||
BackMap _backMap;
|
||||
Key _nextKey { 0 };
|
||||
};
|
||||
|
||||
static Registry<FrameType, QString> frameTypes;
|
||||
static QMap<FrameType, Frame::Handler> handlerMap;
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
static Mutex mutex;
|
||||
static std::once_flag once;
|
||||
|
||||
|
||||
|
||||
FrameType Frame::registerFrameType(const QString& frameTypeName) {
|
||||
Locker lock(mutex);
|
||||
std::call_once(once, [&] {
|
||||
auto headerType = frameTypes.registerValue("com.highfidelity.recording.Header");
|
||||
Q_ASSERT(headerType == Frame::TYPE_HEADER);
|
||||
});
|
||||
return frameTypes.registerValue(frameTypeName);
|
||||
}
|
||||
|
||||
QMap<QString, FrameType> Frame::getFrameTypes() {
|
||||
return frameTypes.getKeysByValue();
|
||||
}
|
||||
|
||||
QMap<FrameType, QString> Frame::getFrameTypeNames() {
|
||||
return frameTypes.getValuesByKey();
|
||||
}
|
||||
|
||||
Frame::Handler Frame::registerFrameHandler(FrameType type, Handler handler) {
|
||||
Locker lock(mutex);
|
||||
Handler result;
|
||||
if (handlerMap.contains(type)) {
|
||||
result = handlerMap[type];
|
||||
}
|
||||
handlerMap[type] = handler;
|
||||
return result;
|
||||
}
|
40
libraries/recording/src/recording/Frame.h
Normal file
40
libraries/recording/src/recording/Frame.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Frame_h
|
||||
#define hifi_Recording_Frame_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace recording {
|
||||
|
||||
struct Frame {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Frame>;
|
||||
using Handler = std::function<void(Frame::Pointer frame)>;
|
||||
|
||||
static const FrameType TYPE_INVALID = 0xFFFF;
|
||||
static const FrameType TYPE_HEADER = 0x0;
|
||||
FrameType type { TYPE_INVALID };
|
||||
float timeOffset { 0 };
|
||||
QByteArray data;
|
||||
|
||||
static FrameType registerFrameType(const QString& frameTypeName);
|
||||
static QMap<QString, FrameType> getFrameTypes();
|
||||
static QMap<FrameType, QString> getFrameTypeNames();
|
||||
static Handler registerFrameHandler(FrameType type, Handler handler);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
62
libraries/recording/src/recording/Recorder.cpp
Normal file
62
libraries/recording/src/recording/Recorder.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Recorder.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "impl/BufferClip.h"
|
||||
#include "Frame.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
void Recorder::start() {
|
||||
if (!_recording) {
|
||||
_recording = true;
|
||||
if (!_clip) {
|
||||
_clip = std::make_shared<BufferClip>();
|
||||
}
|
||||
_timer.start();
|
||||
emit recordingStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Recorder::stop() {
|
||||
if (!_recording) {
|
||||
_recording = false;
|
||||
_elapsed = _timer.elapsed();
|
||||
emit recordingStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Recorder::isRecording() {
|
||||
return _recording;
|
||||
}
|
||||
|
||||
void Recorder::clear() {
|
||||
_clip.reset();
|
||||
}
|
||||
|
||||
void Recorder::recordFrame(FrameType type, QByteArray frameData) {
|
||||
if (!_recording || !_clip) {
|
||||
return;
|
||||
}
|
||||
|
||||
Frame::Pointer frame = std::make_shared<Frame>();
|
||||
frame->type = type;
|
||||
frame->data = frameData;
|
||||
frame->timeOffset = (float)(_elapsed + _timer.elapsed()) / MSECS_PER_SECOND;
|
||||
_clip->appendFrame(frame);
|
||||
}
|
||||
|
||||
ClipPointer Recorder::getClip() {
|
||||
auto result = _clip;
|
||||
_clip.reset();
|
||||
return result;
|
||||
}
|
||||
|
55
libraries/recording/src/recording/Recorder.h
Normal file
55
libraries/recording/src/recording/Recorder.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Recorder_h
|
||||
#define hifi_Recording_Recorder_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
namespace recording {
|
||||
|
||||
// An interface for interacting with clips, creating them by recording or
|
||||
// playing them back. Also serialization to and from files / network sources
|
||||
class Recorder : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Recorder>;
|
||||
|
||||
Recorder(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Recorder();
|
||||
|
||||
// Start recording frames
|
||||
void start();
|
||||
// Stop recording
|
||||
void stop();
|
||||
// Test if recording is active
|
||||
bool isRecording();
|
||||
// Erase the currently recorded content
|
||||
void clear();
|
||||
|
||||
void recordFrame(FrameType type, QByteArray frameData);
|
||||
|
||||
// Return the currently recorded content
|
||||
ClipPointer getClip();
|
||||
|
||||
signals:
|
||||
void recordingStateChanged();
|
||||
|
||||
private:
|
||||
QElapsedTimer _timer;
|
||||
ClipPointer _clip;
|
||||
quint64 _elapsed;
|
||||
bool _recording { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
74
libraries/recording/src/recording/impl/BufferClip.cpp
Normal file
74
libraries/recording/src/recording/impl/BufferClip.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "BufferClip.h"
|
||||
|
||||
#include "../Frame.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
|
||||
void BufferClip::seek(float offset) {
|
||||
Locker lock(_mutex);
|
||||
auto itr = std::lower_bound(_frames.begin(), _frames.end(), offset,
|
||||
[](Frame::Pointer a, float b)->bool{
|
||||
return a->timeOffset < b;
|
||||
}
|
||||
);
|
||||
_frameIndex = itr - _frames.begin();
|
||||
}
|
||||
|
||||
float BufferClip::position() const {
|
||||
Locker lock(_mutex);
|
||||
float result = std::numeric_limits<float>::max();
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex]->timeOffset;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer BufferClip::peekFrame() const {
|
||||
Locker lock(_mutex);
|
||||
FramePointer result;
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer BufferClip::nextFrame() {
|
||||
Locker lock(_mutex);
|
||||
FramePointer result;
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex];
|
||||
++_frameIndex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void BufferClip::appendFrame(FramePointer newFrame) {
|
||||
auto currentPosition = position();
|
||||
seek(newFrame->timeOffset);
|
||||
{
|
||||
Locker lock(_mutex);
|
||||
_frames.insert(_frames.begin() + _frameIndex, newFrame);
|
||||
}
|
||||
seek(currentPosition);
|
||||
}
|
||||
|
||||
void BufferClip::skipFrame() {
|
||||
Locker lock(_mutex);
|
||||
if (_frameIndex < _frames.size()) {
|
||||
++_frameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void BufferClip::reset() {
|
||||
Locker lock(_mutex);
|
||||
_frameIndex = 0;
|
||||
}
|
47
libraries/recording/src/recording/impl/BufferClip.h
Normal file
47
libraries/recording/src/recording/impl/BufferClip.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Impl_BufferClip_h
|
||||
#define hifi_Recording_Impl_BufferClip_h
|
||||
|
||||
#include "../Clip.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace recording {
|
||||
|
||||
class BufferClip : public Clip {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<BufferClip>;
|
||||
|
||||
BufferClip(QObject* parent = nullptr) : Clip(parent) {}
|
||||
virtual ~BufferClip() {}
|
||||
|
||||
virtual void seek(float offset) override;
|
||||
virtual float position() const override;
|
||||
|
||||
virtual FramePointer peekFrame() const override;
|
||||
virtual FramePointer nextFrame() override;
|
||||
virtual void skipFrame() override;
|
||||
virtual void appendFrame(FramePointer) override;
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
std::vector<FramePointer> _frames;
|
||||
mutable Mutex _mutex;
|
||||
mutable size_t _frameIndex { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
105
libraries/recording/src/recording/impl/FileClip.cpp
Normal file
105
libraries/recording/src/recording/impl/FileClip.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "FileClip.h"
|
||||
|
||||
#include "../Frame.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace recording;
|
||||
|
||||
static const qint64 MINIMUM_FRAME_SIZE = sizeof(FrameType) + sizeof(float) + sizeof(uint16_t) + 1;
|
||||
|
||||
FileClip::FileClip(const QString& fileName, QObject* parent) : Clip(parent), _file(fileName) {
|
||||
auto size = _file.size();
|
||||
_map = _file.map(0, size, QFile::MapPrivateOption);
|
||||
|
||||
auto current = _map;
|
||||
auto end = current + size;
|
||||
// Read all the frame headers
|
||||
while (end - current < MINIMUM_FRAME_SIZE) {
|
||||
FrameHeader header;
|
||||
memcpy(&(header.type), current, sizeof(FrameType));
|
||||
current += sizeof(FrameType);
|
||||
memcpy(&(header.timeOffset), current, sizeof(FrameType));
|
||||
current += sizeof(float);
|
||||
memcpy(&(header.size), current, sizeof(uint16_t));
|
||||
current += sizeof(uint16_t);
|
||||
header.fileOffset = current - _map;
|
||||
if (end - current < header.size) {
|
||||
break;
|
||||
}
|
||||
|
||||
_frameHeaders.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
FileClip::~FileClip() {
|
||||
Locker lock(_mutex);
|
||||
_file.unmap(_map);
|
||||
_map = nullptr;
|
||||
}
|
||||
|
||||
void FileClip::seek(float offset) {
|
||||
Locker lock(_mutex);
|
||||
auto itr = std::lower_bound(_frameHeaders.begin(), _frameHeaders.end(), offset,
|
||||
[](const FrameHeader& a, float b)->bool {
|
||||
return a.timeOffset < b;
|
||||
}
|
||||
);
|
||||
_frameIndex = itr - _frameHeaders.begin();
|
||||
}
|
||||
|
||||
float FileClip::position() const {
|
||||
Locker lock(_mutex);
|
||||
float result = std::numeric_limits<float>::max();
|
||||
if (_frameIndex < _frameHeaders.size()) {
|
||||
result = _frameHeaders[_frameIndex].timeOffset;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer FileClip::readFrame(uint32_t frameIndex) const {
|
||||
FramePointer result;
|
||||
if (frameIndex < _frameHeaders.size()) {
|
||||
result = std::make_shared<Frame>();
|
||||
const FrameHeader& header = _frameHeaders[frameIndex];
|
||||
result->type = header.type;
|
||||
result->timeOffset = header.timeOffset;
|
||||
result->data.insert(0, reinterpret_cast<char*>(_map)+header.fileOffset, header.size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer FileClip::peekFrame() const {
|
||||
Locker lock(_mutex);
|
||||
return readFrame(_frameIndex);
|
||||
}
|
||||
|
||||
FramePointer FileClip::nextFrame() {
|
||||
Locker lock(_mutex);
|
||||
auto result = readFrame(_frameIndex);
|
||||
if (_frameIndex < _frameHeaders.size()) {
|
||||
++_frameIndex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileClip::skipFrame() {
|
||||
++_frameIndex;
|
||||
}
|
||||
|
||||
void FileClip::reset() {
|
||||
_frameIndex = 0;
|
||||
}
|
||||
|
||||
void FileClip::appendFrame(FramePointer) {
|
||||
throw std::runtime_error("File clips are read only");
|
||||
}
|
||||
|
62
libraries/recording/src/recording/impl/FileClip.h
Normal file
62
libraries/recording/src/recording/impl/FileClip.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Impl_FileClip_h
|
||||
#define hifi_Recording_Impl_FileClip_h
|
||||
|
||||
#include "../Clip.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace recording {
|
||||
|
||||
class FileClip : public Clip {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<FileClip>;
|
||||
|
||||
FileClip(const QString& file, QObject* parent = nullptr);
|
||||
virtual ~FileClip();
|
||||
|
||||
virtual void seek(float offset) override;
|
||||
virtual float position() const override;
|
||||
|
||||
virtual FramePointer peekFrame() const override;
|
||||
virtual FramePointer nextFrame() override;
|
||||
virtual void appendFrame(FramePointer) override;
|
||||
virtual void skipFrame() override;
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
struct FrameHeader {
|
||||
FrameType type;
|
||||
float timeOffset;
|
||||
uint16_t size;
|
||||
quint64 fileOffset;
|
||||
};
|
||||
|
||||
using FrameHeaders = std::vector<FrameHeader>;
|
||||
|
||||
FramePointer readFrame(uint32_t frameIndex) const;
|
||||
|
||||
mutable Mutex _mutex;
|
||||
QFile _file;
|
||||
uint32_t _frameIndex { 0 };
|
||||
uchar* _map;
|
||||
FrameHeaders _frameHeaders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
10
tests/recording/CMakeLists.txt
Normal file
10
tests/recording/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
# Declare dependencies
|
||||
macro (setup_testcase_dependencies)
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(shared recording)
|
||||
|
||||
copy_dlls_beside_windows_executable()
|
||||
endmacro ()
|
||||
|
||||
setup_hifi_testcase()
|
19
tests/recording/src/Constants.h
Normal file
19
tests/recording/src/Constants.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef hifi_Constants_h
|
||||
#define hifi_Constants_h
|
||||
|
||||
static const QString HEADER_NAME = "com.highfidelity.recording.Header";
|
||||
static const QString TEST_NAME = "com.highfidelity.recording.Test";
|
||||
|
||||
#endif // hifi_FrameTests_h
|
||||
|
||||
|
29
tests/recording/src/FrameTests.cpp
Normal file
29
tests/recording/src/FrameTests.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "FrameTests.h"
|
||||
#include "Constants.h"
|
||||
#include "../QTestExtensions.h"
|
||||
|
||||
#include <recording/Frame.h>
|
||||
|
||||
QTEST_MAIN(FrameTests)
|
||||
|
||||
void FrameTests::registerFrameTypeTest() {
|
||||
auto result = recording::Frame::registerFrameType(TEST_NAME);
|
||||
QCOMPARE(result, (recording::FrameType)1);
|
||||
auto forwardMap = recording::Frame::getFrameTypes();
|
||||
QCOMPARE(forwardMap.count(TEST_NAME), 1);
|
||||
QCOMPARE(forwardMap[TEST_NAME], result);
|
||||
QCOMPARE(forwardMap[HEADER_NAME], recording::Frame::TYPE_HEADER);
|
||||
auto backMap = recording::Frame::getFrameTypeNames();
|
||||
QCOMPARE(backMap.count(result), 1);
|
||||
QCOMPARE(backMap[result], TEST_NAME);
|
||||
QCOMPARE(backMap[recording::Frame::TYPE_HEADER], HEADER_NAME);
|
||||
}
|
||||
|
21
tests/recording/src/FrameTests.h
Normal file
21
tests/recording/src/FrameTests.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_FrameTests_h
|
||||
#define hifi_FrameTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class FrameTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void registerFrameTypeTest();
|
||||
};
|
||||
|
||||
#endif // hifi_FrameTests_h
|
25
tests/recording/src/RecorderTests.cpp
Normal file
25
tests/recording/src/RecorderTests.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "RecorderTests.h"
|
||||
#include "Constants.h"
|
||||
#include "../QTestExtensions.h"
|
||||
|
||||
#include <recording/Recorder.h>
|
||||
|
||||
QTEST_MAIN(RecorderTests)
|
||||
|
||||
void RecorderTests::recorderTest() {
|
||||
//auto recorder = std::make_shared<recording::Recorder>();
|
||||
//QCOMPARE(recoreder.isRecording(), false);
|
||||
//recorder.start();
|
||||
//QCOMPARE(recoreder.isRecording(), true);
|
||||
//recorder.stop();
|
||||
//QCOMPARE(recoreder.isRecording(), false);
|
||||
}
|
||||
|
21
tests/recording/src/RecorderTests.h
Normal file
21
tests/recording/src/RecorderTests.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_RecorderTests_h
|
||||
#define hifi_RecorderTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class RecorderTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void recorderTest();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue