First steps on session recording conversion

This commit is contained in:
Gene Payne
2020-11-13 22:40:35 -07:00
parent 1525a0490d
commit e23e5cf16f
3 changed files with 561 additions and 87 deletions
@@ -33,9 +33,13 @@
namespace openspace::interaction {
struct ConversionError : public ghoul::RuntimeError {
explicit ConversionError(std::string msg);
};
class SessionRecording : public properties::PropertyOwner {
public:
inline static const std::string FileHeaderTitle = "OpenSpace_record/playback";
inline static const std::string HeaderCameraAscii = "camera";
inline static const std::string HeaderTimeAscii = "time";
@@ -66,19 +70,18 @@ public:
};
static const size_t FileHeaderVersionLength = 5;
static constexpr char FileHeaderVersion[FileHeaderVersionLength] = {
'0', '0', '.', '8', '5'
};
static constexpr char FileHeaderVersion[] = "00.85";
static const char DataFormatAsciiTag = 'A';
static const char DataFormatBinaryTag = 'B';
static const size_t keyframeHeaderSize_bytes = 33;
static const size_t saveBufferCameraSize_min = 82;
static const size_t saveBufferStringSize_max = 500;
static const size_t saveBufferStringSize_max = 1000;
static const size_t _saveBufferMaxSize_bytes = keyframeHeaderSize_bytes +
+ saveBufferCameraSize_min + saveBufferStringSize_max;
using CallbackHandle = int;
using StateChangeCallback = std::function<void()>;
SessionRecording* legacyVersion;
SessionRecording();
@@ -254,8 +257,10 @@ public:
* \param kf reference to a camera keyframe which contains camera details
* \param file an ifstream reference to the playback file being read
* \param lineN keyframe number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readCameraKeyframeBinary(Timestamps& times,
static bool readCameraKeyframeBinary(Timestamps& times,
datamessagestructures::CameraKeyframe& kf, std::ifstream& file, int lineN);
/**
@@ -266,8 +271,10 @@ public:
* \param kf reference to a camera keyframe which contains camera details
* \param currentParsingLine string containing the most current line that was read
* \param lineN line number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readCameraKeyframeAscii(Timestamps& times,
static bool readCameraKeyframeAscii(Timestamps& times,
datamessagestructures::CameraKeyframe& kf, std::string currentParsingLine,
int lineN);
@@ -279,8 +286,10 @@ public:
* \param kf reference to a time keyframe which contains time details
* \param file an ifstream reference to the playback file being read
* \param lineN keyframe number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readTimeKeyframeBinary(Timestamps& times,
static bool readTimeKeyframeBinary(Timestamps& times,
datamessagestructures::TimeKeyframe& kf, std::ifstream& file, int lineN);
/**
@@ -291,8 +300,10 @@ public:
* \param kf reference to a time keyframe which contains time details
* \param currentParsingLine string containing the most current line that was read
* \param lineN line number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readTimeKeyframeAscii(Timestamps& times,
static bool readTimeKeyframeAscii(Timestamps& times,
datamessagestructures::TimeKeyframe& kf, std::string currentParsingLine,
int lineN);
@@ -305,8 +316,10 @@ public:
* (in chars) and the text itself
* \param file an ifstream reference to the playback file being read
* \param lineN keyframe number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readScriptKeyframeBinary(Timestamps& times,
static bool readScriptKeyframeBinary(Timestamps& times,
datamessagestructures::ScriptMessage& kf, std::ifstream& file, int lineN);
/**
@@ -318,8 +331,10 @@ public:
* (in chars) and the text itself
* \param currentParsingLine string containing the most current line that was read
* \param lineN line number in playback file where this keyframe resides
*
* \return true if data read has no errors
*/
static void readScriptKeyframeAscii(Timestamps& times,
static bool readScriptKeyframeAscii(Timestamps& times,
datamessagestructures::ScriptMessage& kf, std::string currentParsingLine,
int lineN);
@@ -331,7 +346,7 @@ public:
* \param kfBuffer a buffer temporarily used for preparing data to be written
* \param file an ofstream reference to the recording file being written-to
*/
static void saveCameraKeyframeBinary(Timestamps times,
static void saveCameraKeyframeBinary(Timestamps& times,
datamessagestructures::CameraKeyframe& kf, unsigned char* kfBuffer,
std::ofstream& file);
@@ -342,7 +357,7 @@ public:
* \param kf reference to a camera keyframe which contains the camera details
* \param file an ofstream reference to the recording file being written-to
*/
static void saveCameraKeyframeAscii(Timestamps times,
static void saveCameraKeyframeAscii(Timestamps& times,
datamessagestructures::CameraKeyframe& kf, std::ofstream& file);
/**
@@ -353,7 +368,7 @@ public:
* \param kfBuffer a buffer temporarily used for preparing data to be written
* \param file an ofstream reference to the recording file being written-to
*/
static void saveTimeKeyframeBinary(Timestamps times,
static void saveTimeKeyframeBinary(Timestamps& times,
datamessagestructures::TimeKeyframe& kf, unsigned char* kfBuffer,
std::ofstream& file);
@@ -364,7 +379,7 @@ public:
* \param kf reference to a time keyframe which contains the time details
* \param file an ofstream reference to the recording file being written-to
*/
static void saveTimeKeyframeAscii(Timestamps times,
static void saveTimeKeyframeAscii(Timestamps& times,
datamessagestructures::TimeKeyframe& kf, std::ofstream& file);
/**
@@ -375,7 +390,7 @@ public:
* \param smBuffer a buffer temporarily used for preparing data to be written
* \param file an ofstream reference to the recording file being written-to
*/
static void saveScriptKeyframeBinary(Timestamps times,
static void saveScriptKeyframeBinary(Timestamps& times,
datamessagestructures::ScriptMessage& sm, unsigned char* smBuffer,
std::ofstream& file);
@@ -386,7 +401,7 @@ public:
* \param sm reference to a ScriptMessage which contains the script details
* \param file an ofstream reference to the recording file being written-to
*/
static void saveScriptKeyframeAscii(Timestamps times,
static void saveScriptKeyframeAscii(Timestamps& times,
datamessagestructures::ScriptMessage& sm, std::ofstream& file);
/**
@@ -406,7 +421,7 @@ public:
* \param kfBuffer the char buffer holding the recording info to be written
* \param idx index into write buffer (this is updated with the num of chars written)
*/
static void saveHeaderBinary(Timestamps times, char type, unsigned char* kfBuffer,
static void saveHeaderBinary(Timestamps& times, char type, unsigned char* kfBuffer,
size_t& idx);
/**
@@ -416,7 +431,7 @@ public:
* \param type string signifying the keyframe type
* \param line the stringstream buffer being written to
*/
static void saveHeaderAscii(Timestamps times, const std::string& type,
static void saveHeaderAscii(Timestamps& times, const std::string& type,
std::stringstream& line);
/**
@@ -435,6 +450,14 @@ public:
*/
static bool hasFileExtension(std::string filename, std::string extension);
/**
* Converts file format of a session recording file to the current format version
* (will determine the file format conversion to convert from based on the file's
* header version number).
*
*/
static bool convertFile(std::string filename);
private:
properties::BoolProperty _renderPlaybackInformation;
@@ -485,7 +508,21 @@ private:
bool findNextFutureCameraIndex(double currTime);
bool processCameraKeyframe(double now);
bool processScriptKeyframe();
//bool isDataModeBinary();
static bool readSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
Timestamps& times, DataMode mode, std::ifstream& file, std::string& inLine,
const int lineNum);
static void saveSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
static bool readSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
Timestamps& times, DataMode mode, std::ifstream& file, std::string& inLine,
const int lineNum);
static void saveSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
static bool readSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
Timestamps& times, DataMode mode, std::ifstream& file, std::string& inLine,
const int lineNum);
static void saveSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
unsigned int findIndexOfLastCameraKeyframeInTimeline();
bool doesTimelineEntryContainCamera(unsigned int index) const;
std::vector<std::pair<CallbackHandle, StateChangeCallback>> _stateChangeCallbacks;
@@ -495,6 +532,15 @@ private:
double getNextTimestamp();
double getPrevTimestamp();
void cleanUpPlayback();
static bool convertEntries(std::string& inFilename, std::ifstream& inFile,
DataMode mode, int lineNum, std::ofstream& outFile);
static bool convertCamera(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
static bool convertTimeChange(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
static bool convertScript(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
static std::string determineConversionOutFilename(const std::string filename);
static void writeToFileBuffer(unsigned char* buf, size_t& idx, double src);
static void writeToFileBuffer(unsigned char* buf, size_t& idx, std::vector<char>& cv);
@@ -541,6 +587,30 @@ private:
double _cameraFirstInTimeline_timestamp = 0;
int _nextCallbackHandle = 0;
DataMode _conversionDataMode = DataMode::Binary;
int _conversionLineNum = 1;
};
class SessionRecording_legacy_0085 : SessionRecording {
struct ScriptMessage_legacy_0085 : datamessagestructures::ScriptMessage {
void read(std::istream* in) {
size_t strLen;
//Read string length from file
in->read(reinterpret_cast<char*>(&strLen), sizeof(strLen));
//Read back full string
std::vector<char> temp(strLen + 1);
in->read(temp.data(), strLen);
temp[strLen] = '\0';
_script.erase();
_script = temp.data();
};
};
void convertUp(std::string header, std::string fileToConvert);
static constexpr char FileHeaderVersion[] = "01.00";
};
} // namespace openspace
@@ -370,6 +370,7 @@ struct ScriptMessage {
ScriptMessage(const std::vector<char>& buffer) {
deserialize(buffer);
}
virtual ~ScriptMessage() {};
std::string _script;
double _timestamp = 0.0;
@@ -429,8 +430,8 @@ struct ScriptMessage {
ss << _script;
}
void read(std::istream* in) {
size_t strLen;
virtual void read(std::istream* in) {
uint32_t strLen;
//Read string length from file
in->read(reinterpret_cast<char*>(&strLen), sizeof(strLen));
//Read back full string
+469 -66
View File
@@ -265,7 +265,8 @@ bool SessionRecording::startPlayback(const std::string& filename,
size_t headerSize = FileHeaderTitle.length() +
FileHeaderVersionLength +
sizeof(DataFormatBinaryTag) + sizeof('\n');
_playbackFile.read(reinterpret_cast<char*>(&_keyframeBuffer), headerSize);
char hBuffer[headerSize];
_playbackFile.read(reinterpret_cast<char*>(hBuffer), headerSize);
}
if (!_playbackFile.is_open() || !_playbackFile.good()) {
@@ -500,15 +501,10 @@ void SessionRecording::saveCameraKeyframe() {
kf._timestamp - _timestampRecordStarted,
global::timeManager.time().j2000Seconds()
};
if (_recordingDataMode == DataMode::Binary) {
saveCameraKeyframeBinary(times, kf, _keyframeBuffer, _recordFile);
}
else {
saveCameraKeyframeAscii(times, kf, _recordFile);
}
saveSingleKeyframeCamera(kf, times, _recordingDataMode, _recordFile, _keyframeBuffer);
}
void SessionRecording::saveHeaderBinary(Timestamps times,
void SessionRecording::saveHeaderBinary(Timestamps& times,
char type,
unsigned char* kfBuffer,
size_t& idx)
@@ -519,7 +515,7 @@ void SessionRecording::saveHeaderBinary(Timestamps times,
writeToFileBuffer(kfBuffer, idx, times.timeSim);
}
void SessionRecording::saveHeaderAscii(Timestamps times,
void SessionRecording::saveHeaderAscii(Timestamps& times,
const std::string& type,
std::stringstream& line)
{
@@ -529,7 +525,7 @@ void SessionRecording::saveHeaderAscii(Timestamps times,
line << std::fixed << std::setprecision(3) << times.timeSim << ' ';
}
void SessionRecording::saveCameraKeyframeBinary(Timestamps times,
void SessionRecording::saveCameraKeyframeBinary(Timestamps& times,
datamessagestructures::CameraKeyframe& kf,
unsigned char* kfBuffer,
std::ofstream& file)
@@ -544,7 +540,7 @@ void SessionRecording::saveCameraKeyframeBinary(Timestamps times,
saveKeyframeToFileBinary(kfBuffer, idx, file);
}
void SessionRecording::saveCameraKeyframeAscii(Timestamps times,
void SessionRecording::saveCameraKeyframeAscii(Timestamps& times,
datamessagestructures::CameraKeyframe& kf,
std::ofstream& file)
{
@@ -567,14 +563,10 @@ void SessionRecording::saveTimeKeyframe() {
kf._timestamp - _timestampRecordStarted,
global::timeManager.time().j2000Seconds()
};
if (_recordingDataMode == DataMode::Binary) {
saveTimeKeyframeBinary(times, kf, _keyframeBuffer, _recordFile);
} else {
saveTimeKeyframeAscii(times, kf, _recordFile);
}
saveSingleKeyframeTime(kf, times, _recordingDataMode, _recordFile, _keyframeBuffer);
}
void SessionRecording::saveTimeKeyframeBinary(Timestamps times,
void SessionRecording::saveTimeKeyframeBinary(Timestamps& times,
datamessagestructures::TimeKeyframe& kf,
unsigned char* kfBuffer,
std::ofstream& file)
@@ -587,7 +579,7 @@ void SessionRecording::saveTimeKeyframeBinary(Timestamps times,
saveKeyframeToFileBinary(kfBuffer, idx, file);
}
void SessionRecording::saveTimeKeyframeAscii(Timestamps times,
void SessionRecording::saveTimeKeyframeAscii(Timestamps& times,
datamessagestructures::TimeKeyframe& kf,
std::ofstream& file)
{
@@ -597,7 +589,8 @@ void SessionRecording::saveTimeKeyframeAscii(Timestamps times,
saveKeyframeToFile(keyframeLine.str(), file);
}
void SessionRecording::saveScriptKeyframe(std::string scriptToSave) {
void SessionRecording::saveScriptKeyframe(std::string scriptToSave)
{
if (_state != SessionState::Recording) {
return;
}
@@ -611,15 +604,16 @@ void SessionRecording::saveScriptKeyframe(std::string scriptToSave) {
global::timeManager.time().j2000Seconds()
};
if (_recordingDataMode == DataMode::Binary) {
saveScriptKeyframeBinary(times, sm, _keyframeBuffer, _recordFile);
}
else {
saveScriptKeyframeAscii(times, sm, _recordFile);
}
saveSingleKeyframeScript(
sm,
times,
_recordingDataMode,
_recordFile,
_keyframeBuffer
);
}
void SessionRecording::saveScriptKeyframeBinary(Timestamps times,
void SessionRecording::saveScriptKeyframeBinary(Timestamps& times,
datamessagestructures::ScriptMessage& sm,
unsigned char* smBuffer,
std::ofstream& file)
@@ -633,7 +627,7 @@ void SessionRecording::saveScriptKeyframeBinary(Timestamps times,
saveKeyframeToFileBinary(smBuffer, idx, file);
}
void SessionRecording::saveScriptKeyframeAscii(Timestamps times,
void SessionRecording::saveScriptKeyframeAscii(Timestamps& times,
datamessagestructures::ScriptMessage& sm,
std::ofstream& file)
{
@@ -871,12 +865,14 @@ bool SessionRecording::playbackCamera() {
Timestamps times;
datamessagestructures::CameraKeyframe kf;
if (_recordingDataMode == DataMode::Binary) {
readCameraKeyframeBinary(times, kf, _playbackFile, _playbackLineNum);
}
else {
readCameraKeyframeAscii(times, kf, _playbackLineParsing, _playbackLineNum);
}
bool success = readSingleKeyframeCamera(
kf,
times,
_recordingDataMode,
_playbackFile,
_playbackLineParsing,
_playbackLineNum
);
if (_setSimulationTimeWithNextCameraKeyframe) {
global::timeManager.setTimeNextFrame(Time(times.timeSim));
@@ -886,10 +882,65 @@ bool SessionRecording::playbackCamera() {
double timeRef = appropriateTimestamp(times.timeOs, times.timeRec, times.timeSim);
interaction::KeyframeNavigator::CameraPose pbFrame(std::move(kf));
return addKeyframe(timeRef, pbFrame, _playbackLineNum);
if (success) {
success = addKeyframe(timeRef, pbFrame, _playbackLineNum);
}
return success;
}
void SessionRecording::readCameraKeyframeBinary(Timestamps& times,
bool SessionRecording::convertCamera(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile,
unsigned char* buffer)
{
Timestamps times;
datamessagestructures::CameraKeyframe kf;
bool success = readSingleKeyframeCamera(
kf,
times,
mode,
inFile,
inputLine,
lineNum
);
if (success) {
saveSingleKeyframeCamera(
kf,
times,
mode,
outFile,
buffer
);
}
return success;
}
bool SessionRecording::readSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
Timestamps& times, DataMode mode,
std::ifstream& file, std::string& inLine,
const int lineNum)
{
if (mode == DataMode::Binary) {
return readCameraKeyframeBinary(times, kf, file, lineNum);
}
else {
return readCameraKeyframeAscii(times, kf, inLine, lineNum);
}
}
void SessionRecording::saveSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
Timestamps& times, DataMode mode,
std::ofstream& file, unsigned char* buffer)
{
if (mode == DataMode::Binary) {
saveCameraKeyframeBinary(times, kf, buffer, file);
}
else {
saveCameraKeyframeAscii(times, kf, file);
}
}
bool SessionRecording::readCameraKeyframeBinary(Timestamps& times,
datamessagestructures::CameraKeyframe& kf,
std::ifstream& file, int lineN)
{
@@ -904,14 +955,14 @@ void SessionRecording::readCameraKeyframeBinary(Timestamps& times,
"Allocation error with camera playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
catch (std::length_error&) {
LERROR(fmt::format(
"length_error with camera playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
times.timeOs = kf._timestamp;
@@ -920,11 +971,12 @@ void SessionRecording::readCameraKeyframeBinary(Timestamps& times,
"Error reading camera playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
return true;
}
void SessionRecording::readCameraKeyframeAscii(Timestamps& times,
bool SessionRecording::readCameraKeyframeAscii(Timestamps& times,
datamessagestructures::CameraKeyframe& kf,
std::string currentParsingLine,
int lineN)
@@ -941,28 +993,85 @@ void SessionRecording::readCameraKeyframeAscii(Timestamps& times,
if (iss.fail() || !iss.eof()) {
LERROR(fmt::format("Error parsing camera line {} of playback file", lineN));
return;
return false;
}
return true;
}
bool SessionRecording::playbackTimeChange() {
Timestamps times;
datamessagestructures::TimeKeyframe kf;
if (_recordingDataMode == DataMode::Binary) {
readTimeKeyframeBinary(times, kf, _playbackFile, _playbackLineNum);
} else {
readTimeKeyframeAscii(times, kf, _playbackLineParsing, _playbackLineNum);
}
bool success = readSingleKeyframeTime(
kf,
times,
_recordingDataMode,
_playbackFile,
_playbackLineParsing,
_playbackLineNum
);
kf._timestamp = equivalentApplicationTime(times.timeOs, times.timeRec, times.timeSim);
kf._time = kf._timestamp + _timestampApplicationStarted_simulation;
//global::timeManager.addKeyframe(timeRef, pbFrame._timestamp);
//_externInteract.timeInteraction(pbFrame);
return addKeyframe(kf._timestamp, kf, _playbackLineNum);
if (success) {
success = addKeyframe(kf._timestamp, kf, _playbackLineNum);
}
return success;
}
void SessionRecording::readTimeKeyframeBinary(Timestamps& times,
bool SessionRecording::convertTimeChange(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile,
unsigned char* buffer)
{
Timestamps times;
datamessagestructures::TimeKeyframe kf;
bool success = readSingleKeyframeTime(
kf,
times,
mode,
inFile,
inputLine,
lineNum
);
if (success) {
saveSingleKeyframeTime(
kf,
times,
mode,
outFile,
buffer
);
}
return success;
}
bool SessionRecording::readSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
Timestamps& times, DataMode mode,
std::ifstream& file, std::string& inLine,
const int lineNum)
{
if (mode == DataMode::Binary) {
return readTimeKeyframeBinary(times, kf, file, lineNum);
} else {
return readTimeKeyframeAscii(times, kf, inLine, lineNum);
}
}
void SessionRecording::saveSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
Timestamps& times, DataMode mode,
std::ofstream& file, unsigned char* buffer)
{
if (mode == DataMode::Binary) {
saveTimeKeyframeBinary(times, kf, buffer, file);
} else {
saveTimeKeyframeAscii(times, kf, file);
}
}
bool SessionRecording::readTimeKeyframeBinary(Timestamps& times,
datamessagestructures::TimeKeyframe& kf,
std::ifstream& file, int lineN)
{
@@ -978,25 +1087,26 @@ void SessionRecording::readTimeKeyframeBinary(Timestamps& times,
"Allocation error with time playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
catch (std::length_error&) {
LERROR(fmt::format(
"length_error with time playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
if (!file) {
LERROR(fmt::format(
"Error reading time playback from keyframe entry {}", lineN - 1
));
return;
return false;
}
return true;
}
void SessionRecording::readTimeKeyframeAscii(Timestamps& times,
bool SessionRecording::readTimeKeyframeAscii(Timestamps& times,
datamessagestructures::TimeKeyframe& kf,
std::string currentParsingLine,
int lineN)
@@ -1012,8 +1122,9 @@ void SessionRecording::readTimeKeyframeAscii(Timestamps& times,
LERROR(fmt::format(
"Error parsing time line {} of playback file", lineN
));
return;
return false;
}
return true;
}
std::string SessionRecording::readHeaderElement(std::ifstream& stream,
@@ -1028,17 +1139,75 @@ bool SessionRecording::playbackScript() {
Timestamps times;
datamessagestructures::ScriptMessage kf;
if (_recordingDataMode == DataMode::Binary) {
readScriptKeyframeBinary(times, kf, _playbackFile, _playbackLineNum);
} else {
readScriptKeyframeAscii(times, kf, _playbackLineParsing, _playbackLineNum);
}
bool success = readSingleKeyframeScript(
kf,
times,
_recordingDataMode,
_playbackFile,
_playbackLineParsing,
_playbackLineNum
);
double timeRef = appropriateTimestamp(times.timeOs, times.timeRec, times.timeSim);
return addKeyframe(timeRef, kf._script, _playbackLineNum);
if (success) {
success = addKeyframe(timeRef, kf._script, _playbackLineNum);
}
return success;
}
void SessionRecording::readScriptKeyframeBinary(Timestamps& times,
bool SessionRecording::convertScript(std::ifstream& inFile, DataMode mode, int lineNum,
std::string& inputLine, std::ofstream& outFile,
unsigned char* buffer)
{
Timestamps times;
datamessagestructures::ScriptMessage kf;
bool success = readSingleKeyframeScript(
kf,
times,
mode,
inFile,
inputLine,
lineNum
);
if (success) {
saveSingleKeyframeScript(
kf,
times,
mode,
outFile,
buffer
);
}
return success;
}
bool SessionRecording::readSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
Timestamps& times, DataMode mode,
std::ifstream& file, std::string& inLine,
const int lineNum)
{
if (mode == DataMode::Binary) {
return readScriptKeyframeBinary(times, kf, file, lineNum);
}
else {
return readScriptKeyframeAscii(times, kf, inLine, lineNum);
}
}
void SessionRecording::saveSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
Timestamps& times, DataMode mode,
std::ofstream& file, unsigned char* buffer)
{
if (mode == DataMode::Binary) {
saveScriptKeyframeBinary(times, kf, buffer, file);
}
else {
saveScriptKeyframeAscii(times, kf, file);
}
}
bool SessionRecording::readScriptKeyframeBinary(Timestamps& times,
datamessagestructures::ScriptMessage& kf,
std::ifstream& file, int lineN)
{
@@ -1054,14 +1223,14 @@ void SessionRecording::readScriptKeyframeBinary(Timestamps& times,
"Allocation error with script playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
catch (std::length_error&) {
LERROR(fmt::format(
"length_error with script playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
if (!file) {
@@ -1069,11 +1238,12 @@ void SessionRecording::readScriptKeyframeBinary(Timestamps& times,
"Error reading script playback from keyframe entry {}",
lineN - 1
));
return;
return false;
}
return true;
}
void SessionRecording::readScriptKeyframeAscii(Timestamps& times,
bool SessionRecording::readScriptKeyframeAscii(Timestamps& times,
datamessagestructures::ScriptMessage& kf,
std::string currentParsingLine,
int lineN)
@@ -1087,13 +1257,14 @@ void SessionRecording::readScriptKeyframeAscii(Timestamps& times,
LERROR(fmt::format(
"Error parsing script line {} of playback file", lineN
));
return;
return false;
} else if (!iss.eof()) {
LERROR(fmt::format(
"Did not find an EOL at line {} of playback file", lineN
));
return;
return false;
}
return true;
}
bool SessionRecording::addKeyframe(double timestamp,
@@ -1448,7 +1619,7 @@ void SessionRecording::saveKeyframeToFileBinary(unsigned char* buffer,
size_t size,
std::ofstream& file)
{
file.write(reinterpret_cast<char*>(buffer), size);
file.write(reinterpret_cast<unsigned char*>(buffer), size);
}
void SessionRecording::saveKeyframeToFile(std::string entry, std::ofstream& file) {
@@ -1588,4 +1759,236 @@ scripting::LuaLibrary SessionRecording::luaLibrary() {
};
}
bool SessionRecording::convertFile(std::string filename) {
bool success = true;
try {
if (filename.find("/") != std::string::npos) {
throw ConversionError("Playback filename musn't contain path (/) elements");
}
std::string conversionInFilename = absPath("${RECORDINGS}/" + filename);
if (!FileSys.fileExists(conversionInFilename)) {
throw ConversionError("Cannot find the specified playback file to convert.");
}
int conversionLineNum = 1;
// Open in ASCII first
std::ifstream conversionInFile;
conversionInFile.open(conversionInFilename, std::ifstream::in);
// Read header
std::string readBackHeaderString = readHeaderElement(
conversionInFile,
FileHeaderTitle.length()
);
if (readBackHeaderString != FileHeaderTitle) {
throw ConversionError("File to convert does not contain expected header.");
}
if (readBackHeaderString != FileHeaderTitle) {
throw ConversionError("File to convert does not contain expected header.");
}
readHeaderElement(conversionInFile, FileHeaderVersionLength);
std::string readDataMode = readHeaderElement(conversionInFile, 1);
DataMode mode;
if (readDataMode[0] == DataFormatAsciiTag) {
mode = DataMode::Ascii;
}
else if (readDataMode[0] == DataFormatBinaryTag) {
mode = DataMode::Binary;
}
else {
throw ConversionError("Unknown data type in header (needs Ascii or Binary)");
}
if (!conversionInFile.is_open() || !conversionInFile.good()) {
throw ConversionError(fmt::format(
"Unable to open file {} for conversion", conversionInFilename.c_str()
));
}
std::string conversionOutFilename = determineConversionOutFilename(filename);
std::ofstream conversionOutFile;
if (mode == DataMode::Binary) {
conversionOutFile.open(conversionOutFilename, std::ios::binary);
}
else {
conversionOutFile.open(conversionOutFilename);
}
if (!conversionOutFile.is_open() || !conversionOutFile.good()) {
LERROR(fmt::format(
"Unable to open file {} for conversion result",
conversionOutFilename.c_str()
));
return false;
}
success = convertEntries(
conversionInFilename,
conversionInFile,
mode,
conversionLineNum,
conversionOutFile
);
}
catch (ConversionError& c) {
LERROR(c.message);
success = false;
}
return success;
}
bool SessionRecording::convertEntries(std::string& inFilename, std::ifstream& inFile,
DataMode mode, int lineNum, std::ofstream& outFile)
{
bool conversionStatusOk = true;
std::string lineParsing;
std::shared_ptr<char[]> buffer(new char[_saveBufferMaxSize_bytes]);
if (mode == DataMode::Binary) {
unsigned char frameType;
bool fileReadOk = true;
while (conversionStatusOk && fileReadOk) {
frameType = readFromPlayback<unsigned char>(inFile);
// Check if have reached EOF
if (!inFile) {
LINFO(fmt::format(
"Finished converting {} entries from playback file {}",
lineNum - 1, inFilename
));
fileReadOk = false;
break;
}
if (frameType == HeaderCameraBinary) {
conversionStatusOk = convertCamera(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else if (frameType == HeaderTimeBinary) {
conversionStatusOk = convertTimeChange(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else if (frameType == HeaderScriptBinary) {
conversionStatusOk = convertScript(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else {
LERROR(fmt::format(
"Unknown frame type {} @ index {} of conversion file {}",
frameType, lineNum - 1, inFilename
));
conversionStatusOk = false;
break;
}
lineNum++;
}
}
else {
while (conversionStatusOk && std::getline(inFile, lineParsing)) {
lineNum++;
std::istringstream iss(lineParsing);
std::string entryType;
if (!(iss >> entryType)) {
LERROR(fmt::format(
"Error reading entry type @ line {} of conversion file {}",
lineNum, inFilename
));
break;
}
if (entryType == HeaderCameraAscii) {
conversionStatusOk = convertCamera(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else if (entryType == HeaderTimeAscii) {
conversionStatusOk = convertTimeChange(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else if (entryType == HeaderScriptAscii) {
conversionStatusOk = convertScript(
inFile,
mode,
lineNum,
lineParsing,
outFile,
buffer
);
}
else if (entryType.substr(0, 1) == HeaderCommentAscii) {
continue;
}
else {
LERROR(fmt::format(
"Unknown frame type {} @ line {} of conversion file {}",
entryType, lineNum, inFilename
));
conversionStatusOk = false;
break;
}
}
LINFO(fmt::format(
"Finished parsing {} entries from conversion file {}",
lineNum, inFilename
));
}
return conversionStatusOk;
}
std::string SessionRecording::determineConversionOutFilename(const std::string filename) {
std::string conversionOutFilename;
if (filename.substr(filename.find_last_of(".")) == FileExtensionBinary) {
conversionOutFilename = filename.substr(0, filename.find_last_of("."))
+ "_" + FileHeaderVersion + FileExtensionBinary;
}
else if (filename.substr(filename.find_last_of(".")) == FileExtensionAscii) {
conversionOutFilename = filename.substr(0, filename.find_last_of("."))
+ "_" + FileHeaderVersion + FileExtensionAscii;
}
else {
conversionOutFilename = filename + "_";
}
return absPath("${RECORDINGS}/convert/" + conversionOutFilename);
}
void SessionRecording_legacy_0085::convertUp(std::string header, std::string fileToConvert)
{
if (strcmp(legacyVersion->FileHeaderVersion, FileHeaderVersion) == 0) {
convertFile(fileToConvert);
}
else {
//Oldest known version
}
}
} // namespace openspace::interaction