Skip to content

Commit

Permalink
Unit test to read Insta360 information using telemetry reader instead…
Browse files Browse the repository at this point in the history
… of file creation time
  • Loading branch information
sergei committed Jun 11, 2024
1 parent 948c2ce commit 7b259d3
Show file tree
Hide file tree
Showing 22 changed files with 638 additions and 67 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ set (NAV_SRC
magnetic/wmm.c
magnetic/GeomagnetismLibrary.c
magnetic/mem_file.c
adobe_premiere/insta360/MarkerReaderInsta360.cpp adobe_premiere/insta360/MarkerReaderInsta360.h adobe_premiere/ClipMarker.cpp adobe_premiere/ClipMarker.h)
adobe_premiere/insta360/MarkerReaderInsta360.cpp adobe_premiere/insta360/MarkerReaderInsta360.h adobe_premiere/ClipMarker.cpp adobe_premiere/ClipMarker.h Insta360/Insta360.cpp Insta360/Insta360.h cameras/CameraBase.cpp cameras/CameraBase.h)

qt_add_executable(sailvue WIN32 MACOSX_BUNDLE
main.cpp
Expand Down
122 changes: 122 additions & 0 deletions Insta360/Insta360.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include <iostream>
#include <ctime>
#include <codecvt>
#include <unistd.h>
#include <csignal>
#include <QJsonDocument>
#include <QJsonObject>

#include "Insta360.h"

Insta360::Insta360(InstrDataReader &rInstrDataReader, IProgressListener &rProgressListener):
CameraBase("insta360", ".insv", rInstrDataReader, rProgressListener)
{
}


#define READ 0
#define WRITE 1

static pid_t
popen2(const char *command, int *infp, int *outfp)
{
int p_stdin[2], p_stdout[2];
pid_t pid;

if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
return -1;

pid = fork();

if (pid < 0)
return pid;
else if (pid == 0)
{
close(p_stdin[WRITE]);
dup2(p_stdin[READ], READ);
close(p_stdout[READ]);
dup2(p_stdout[WRITE], WRITE);

execl("/bin/sh", "sh", "-c", command, NULL);
perror("execl");
exit(1);
}

if (infp == nullptr)
close(p_stdin[WRITE]);
else
*infp = p_stdin[WRITE];

if (outfp == nullptr)
close(p_stdout[READ]);
else
*outfp = p_stdout[READ];

return pid;
}

std::tuple<int, int> Insta360::readClipFile(const std::string &clipFileName, std::list<InstrumentInput> &listInputs) {
std::string telemetryParserArgs("/Users/sergei/github/telemetry-parser/bin/gyro2bb/target/release/gyro2bb -d ");
telemetryParserArgs += clipFileName;


int outfp;
int pid = popen2((const char *)telemetryParserArgs.c_str(), nullptr, &outfp);
if (pid == -1) {
throw std::runtime_error("popen2() failed!");
}
std::cout << "gyro2bb started with PID " << pid << std::endl;

FILE *outStream = fdopen(outfp, "r");

std::string out;
try {
std::array<char, 64*1024> buffer{};

int lineCount = 0;
while ( fgets(buffer.data(), sizeof(buffer), outStream) != nullptr ) {
out = std::string(buffer.data());
if ( lineCount == 1 ){
kill(pid, SIGABRT);
int status;
waitpid(pid, &status, WNOHANG);
if (WIFEXITED(status)){
std::cout << "gyro2bb with PID " << pid << " stopped." << std::endl;
}
break;
}
lineCount ++;
}
} catch (...) {
fclose(outStream);
throw;
}

int64_t createTimeUtcMs = -1;
int totalTimeSec = -1;
int width=-1;
int height=-1;
if ( out.find("Metadata") !=std::string::npos ){
std::size_t jsonStart = out.find('{');
std::string jsonString = out.substr(jsonStart);
std::cout << "gyro2bbPID " << pid << std::endl;
QJsonDocument loadDoc(QJsonDocument::fromJson(QByteArray::fromStdString(jsonString)));
QJsonObject json = loadDoc.object();
if( QJsonValue v = json["first_gps_timestamp"]; v.isDouble()){
createTimeUtcMs = int64_t(v.toDouble());
}
if( QJsonValue v = json["total_time"]; v.isDouble()){
totalTimeSec = v.toInt();
}


auto dimension = json.value("dimension");
width = dimension["x"].toInt();
height = dimension["y"].toInt();

m_ulClipStartUtcMs = createTimeUtcMs;
m_ulClipEndUtcMs = m_ulClipStartUtcMs + totalTimeSec * 1000;
}

return {width,height};
}
18 changes: 18 additions & 0 deletions Insta360/Insta360.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef SAILVUE_INSTA360_H
#define SAILVUE_INSTA360_H

#include <string>
#include "../InstrDataReader.h"
#include "navcomputer/IProgressListener.h"
#include "cameras/CameraBase.h"


class Insta360 : public CameraBase{
public:
Insta360(InstrDataReader& rInstrDataReader, IProgressListener& rProgressListener);
private:
std::tuple<int , int > readClipFile(const std::string &clipFileName, std::list<InstrumentInput> &listInputs) override;
};


#endif //SAILVUE_INSTA360_H
4 changes: 4 additions & 0 deletions adobe_premiere/ClipMarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define SAILVUE_CLIPMARKER_H

#include <string>
#include "cameras/CameraBase.h"


class ClipMarker {
Expand All @@ -18,13 +19,16 @@ class ClipMarker {
void setName(const std::string &makerName) { m_name = makerName; }
void setInTimeSec(u_int64_t mInTimeSec) { m_inTimeSec = mInTimeSec; }
void setOutTimeSec(u_int64_t mOutTimeSec) { m_outTimeSec = mOutTimeSec; }
CameraClipInfo *getClipInfo() const { return m_pClipInfo; }
void setClipInfo(CameraClipInfo *mPClipInfo) { m_pClipInfo = mPClipInfo; }

private:
std::string m_name="Untitled Marker";
u_int64_t m_inTimeSec=0;
u_int64_t m_outTimeSec=0;
u_int64_t m_UtcMsIn=0;
u_int64_t m_UtcMsOut=0;
CameraClipInfo *m_pClipInfo = nullptr;
};


Expand Down
60 changes: 39 additions & 21 deletions adobe_premiere/insta360/MarkerReaderInsta360.cpp
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
#include <iostream>
#include <sys/stat.h>
#include <ctime>
#include <fstream>
#include <codecvt>
#include <QJsonDocument>

#include "MarkerReaderInsta360.h"

void MarkerReaderInsta360::read(std::filesystem::path &markersDir, std::filesystem::path &insta360Dir) {
void MarkerReaderInsta360::read(const std::filesystem::path &markersDir, const std::list<CameraClipInfo *> &cameraClips) {

auto markerFiles = std::filesystem::recursive_directory_iterator(markersDir);

for( const auto& markerFile : markerFiles ) {
std::cout << "Reading marker file " << markerFile.path() << std::endl;

if (markerFile.path().extension() == ".csv") {
// Find corresponding .insv file
std::filesystem::path insvBaseName = markerFile.path().filename().stem();
std::filesystem::path insvPath = insta360Dir / insvBaseName;
std::filesystem::path clipBaseName = markerFile.path().filename().stem().string();

// Find corresponding clip

std::cout << insvPath << std::endl;
u_int64_t createTimeUtcMs = 0;
CameraClipInfo *pClipInfo;

const char *fname = insvPath.c_str();
for( auto clip : cameraClips){
if( clip->getFileName().find(clipBaseName) != std::string::npos){
std::cout << " Marker for clip " << clip->getFileName() << std::endl;
createTimeUtcMs = clip->getClipStartUtcMs();
pClipInfo = clip;
break;
}
}

// Get file creation time
struct stat t_stat{};
stat(fname, &t_stat);
u_int64_t createTimeUtcMs = t_stat.st_birthtimespec.tv_sec * 1000 +
t_stat.st_birthtimespec.tv_nsec / 1000 / 1000 ;
if ( createTimeUtcMs == 0 ){
std::cerr << "Failed to find clip for marker file " << markerFile.path() << std::endl;
continue;
}

// Read marker file line by line
// Marker file is encoded as UTF-16LE
Expand Down Expand Up @@ -59,24 +69,32 @@ void MarkerReaderInsta360::read(std::filesystem::path &markersDir, std::filesyst
int outSec = timeCodeToSec(item);
marker->setOutTimeSec(outSec);

marker->setClipStartUtc(createTimeUtcMs);
marker->setClipStartUtc(createTimeUtcMs + m_timeAdjustmentMs);

marker->setClipInfo(pClipInfo);

m_markersList.push_back(*marker);
}
std::cout << " Added marker " << marker->getName() << std::endl;
}
}
}

// Sort Markers by start UTC time
m_markersList.sort( [] (const ClipMarker &c1, const ClipMarker &c2) {return c1.getUtcMsIn() < c2.getUtcMsIn();});

}


int MarkerReaderInsta360::timeCodeToSec(const std::string &item) {
return stoi(item.substr(0, 2)) * 3600
+ stoi(item.substr(3, 2)) * 60
+ stoi(item.substr(6, 2));
}

void MarkerReaderInsta360::makeChapters(std::vector<InstrumentInput> &instrDataVector, std::list<Chapter> &chapters) {
void MarkerReaderInsta360::makeChapters(std::list<Chapter *> &chapters, std::vector<InstrumentInput> &instrDataVector) {

for( auto marker: m_markersList){
for( const auto& marker: m_markersList){
// Find index of the clip in

auto inIter = std::lower_bound(instrDataVector.begin(), instrDataVector.end(), marker.getUtcMsIn(),
[](const InstrumentInput& ii, u_int64_t utcMs)
{ return ii.utc.getUnixTimeMs() <= utcMs;}
Expand All @@ -88,18 +106,18 @@ void MarkerReaderInsta360::makeChapters(std::vector<InstrumentInput> &instrDataV
);

if ( inIter != instrDataVector.end() && outIter != instrDataVector.end()){
u_int64_t startIdx = inIter - instrDataVector.begin();
u_int64_t endIdx = outIter - instrDataVector.begin();
u_int64_t startIdx = std::distance(instrDataVector.begin(), inIter);
u_int64_t endIdx = std::distance(instrDataVector.begin(), outIter);

auto chapter = new Chapter(startIdx, endIdx);
chapter->SetName(marker.getName());
chapters.push_back(*chapter);
chapters.push_back(chapter);
}else{
std::cerr << "Could not timestamp marker " << marker.getName() << std::endl;
}
}

// Sort chapters by index
chapters.sort( [] (const Chapter &c1, const Chapter &c2) {return c1.getStartIdx() < c2.getStartIdx();});
chapters.sort( [] (const Chapter *c1, const Chapter *c2) {return c1->getStartIdx() < c2->getStartIdx();});

}
11 changes: 8 additions & 3 deletions adobe_premiere/insta360/MarkerReaderInsta360.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
#ifndef SAILVUE_MARKERREADERINSTA360_H
#define SAILVUE_MARKERREADERINSTA360_H


#include <filesystem>
#include <list>
#include "adobe_premiere/ClipMarker.h"
#include "navcomputer/Chapter.h"
#include "cameras/CameraBase.h"


class MarkerReaderInsta360 {
public:
void read(std::filesystem::path &markersDir, std::filesystem::path &insta360Dir);
void makeChapters(std::vector<InstrumentInput> &instrDataVector, std::list<Chapter> &chapters);
void setTimeAdjustmentMs(int64_t timeAdjustmentMs){m_timeAdjustmentMs = timeAdjustmentMs;};
void read(const std::filesystem::path &markersDir, const std::list<CameraClipInfo *> &cameraClips);
void makeChapters(std::list<Chapter *> &chapters, std::vector<InstrumentInput> &instrDataVector);
const std::list<ClipMarker> &getMarkersList() const { return m_markersList; }
private:
std::list<ClipMarker> m_markersList;

private:
int64_t m_timeAdjustmentMs = 0;

static int timeCodeToSec(const std::string &item) ;
};

Expand Down
Loading

0 comments on commit 7b259d3

Please sign in to comment.