Improved seeking in DTSC::File, also, now tested working.
This commit is contained in:
parent
8c8bf628b9
commit
4a940f7514
2 changed files with 77 additions and 25 deletions
92
lib/dtsc.cpp
92
lib/dtsc.cpp
|
@ -222,7 +222,8 @@ DTSC::File::File(std::string filename, bool create){
|
||||||
}
|
}
|
||||||
fseek(F, 8+headerSize, SEEK_SET);
|
fseek(F, 8+headerSize, SEEK_SET);
|
||||||
currframe = 1;
|
currframe = 1;
|
||||||
frames[currframe] = ftell(F);
|
frames[1] = 8+headerSize;
|
||||||
|
msframes[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the header metadata for this file as a std::string.
|
/// Returns the header metadata for this file as a std::string.
|
||||||
|
@ -256,24 +257,27 @@ bool DTSC::File::writeHeader(std::string & header, bool force){
|
||||||
return (ret == 1);
|
return (ret == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads the packet available at the current file position, returning it as a std::string.
|
/// Reads the packet available at the current file position.
|
||||||
/// If the packet could not be read for any reason, the reason is printed to stderr and an empty string returned.
|
/// If the packet could not be read for any reason, the reason is printed to stderr.
|
||||||
/// Reading the packet means the file position is increased to the next packet.
|
/// Reading the packet means the file position is increased to the next packet.
|
||||||
std::string & DTSC::File::getPacket(){
|
void DTSC::File::seekNext(){
|
||||||
if (fread(buffer, 4, 1, F) != 1){
|
if (fread(buffer, 4, 1, F) != 1){
|
||||||
fprintf(stderr, "Could not read header\n");
|
fprintf(stderr, "Could not read header\n");
|
||||||
strbuffer = "";
|
strbuffer = "";
|
||||||
return strbuffer;
|
jsonbuffer.null();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (memcmp(buffer, DTSC::Magic_Packet, 4) != 0){
|
if (memcmp(buffer, DTSC::Magic_Packet, 4) != 0){
|
||||||
fprintf(stderr, "Invalid header\n");
|
fprintf(stderr, "Invalid header - %.4s != %.4s\n", buffer, DTSC::Magic_Packet);
|
||||||
strbuffer = "";
|
strbuffer = "";
|
||||||
return strbuffer;
|
jsonbuffer.null();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (fread(buffer, 4, 1, F) != 1){
|
if (fread(buffer, 4, 1, F) != 1){
|
||||||
fprintf(stderr, "Could not read size\n");
|
fprintf(stderr, "Could not read size\n");
|
||||||
strbuffer = "";
|
strbuffer = "";
|
||||||
return strbuffer;
|
jsonbuffer.null();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
uint32_t * ubuffer = (uint32_t *)buffer;
|
uint32_t * ubuffer = (uint32_t *)buffer;
|
||||||
long packSize = ntohl(ubuffer[0]);
|
long packSize = ntohl(ubuffer[0]);
|
||||||
|
@ -281,33 +285,49 @@ std::string & DTSC::File::getPacket(){
|
||||||
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
|
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
|
||||||
fprintf(stderr, "Could not read packet\n");
|
fprintf(stderr, "Could not read packet\n");
|
||||||
strbuffer = "";
|
strbuffer = "";
|
||||||
return strbuffer;
|
jsonbuffer.null();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
jsonbuffer = JSON::fromDTMI(strbuffer);
|
||||||
|
if (jsonbuffer.isMember("keyframe")){
|
||||||
|
long pos = ftell(F) - (packSize + 8);
|
||||||
|
if (frames[currframe] != pos){
|
||||||
currframe++;
|
currframe++;
|
||||||
frames[currframe] = ftell(F);
|
currtime = jsonbuffer["time"].asInt();
|
||||||
return strbuffer;
|
#if DEBUG >= 4
|
||||||
|
std::cerr << "Found a new frame " << currframe << " @ " << pos << "b/" << currtime << "s" << std::endl;
|
||||||
|
#endif
|
||||||
|
frames[currframe] = pos;
|
||||||
|
msframes[currframe] = currtime;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the internal buffer of the last read packet in raw binary format.
|
||||||
|
std::string & DTSC::File::getPacket(){return strbuffer;}
|
||||||
|
|
||||||
|
/// Returns the internal buffer of the last read packet in JSON format.
|
||||||
|
JSON::Value & DTSC::File::getJSON(){return jsonbuffer;}
|
||||||
|
|
||||||
/// Attempts to seek to the given frame number within the file.
|
/// Attempts to seek to the given frame number within the file.
|
||||||
/// Returns true if successful, false otherwise.
|
/// Returns true if successful, false otherwise.
|
||||||
bool DTSC::File::seek_frame(int frameno){
|
bool DTSC::File::seek_frame(int frameno){
|
||||||
std::map<int, long>::iterator it = frames.lower_bound(frameno);
|
if (frames.count(frameno) > 0){
|
||||||
if (it->first == frameno){
|
if (fseek(F, frames[frameno], SEEK_SET) == 0){
|
||||||
if (fseek(F, it->second, SEEK_SET) == 0){
|
|
||||||
currframe = frameno;
|
currframe = frameno;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if (fseek(F, it->second, SEEK_SET) == 0){
|
for (int i = frameno; i >= 1; --i){
|
||||||
currframe = it->first;
|
if (frames.count(i) > 0){currframe = i; break;}
|
||||||
|
}
|
||||||
|
if (fseek(F, frames[currframe], SEEK_SET) == 0){
|
||||||
|
#if DEBUG >= 4
|
||||||
|
std::cerr << "Seeking from frame " << currframe << " @ " << frames[currframe] << " to " << frameno << std::endl;
|
||||||
|
#endif
|
||||||
while (currframe < frameno){
|
while (currframe < frameno){
|
||||||
if (fread(buffer, 4, 1, F) != 1){return false;}//read header
|
seekNext();
|
||||||
if (memcmp(buffer, DTSC::Magic_Packet, 4) != 0){return false;}//check header
|
if (jsonbuffer.isNull()){return false;}
|
||||||
if (fread(buffer, 4, 1, F) != 1){return false;}//read size
|
|
||||||
uint32_t * ubuffer = (uint32_t *)buffer;
|
|
||||||
long packSize = ntohl(ubuffer[0]);
|
|
||||||
if (fseek(F, packSize, SEEK_CUR) != 0){return false;}//seek to next packet
|
|
||||||
currframe++;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -315,6 +335,32 @@ bool DTSC::File::seek_frame(int frameno){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to seek to the given time in ms within the file.
|
||||||
|
/// Returns true if successful, false otherwise.
|
||||||
|
bool DTSC::File::seek_time(int ms){
|
||||||
|
std::map<int, long>::iterator it;
|
||||||
|
currtime = 0;
|
||||||
|
currframe = 1;
|
||||||
|
for (it = msframes.begin(); it != msframes.end(); ++it){
|
||||||
|
if (it->second > ms){break;}
|
||||||
|
if (it->second > currtime){currtime = it->second; currframe = it->first;}
|
||||||
|
}
|
||||||
|
if (fseek(F, frames[currframe], SEEK_SET) == 0){
|
||||||
|
#if DEBUG >= 4
|
||||||
|
std::cerr << "Seeking from frame " << currframe << " @ " << msframes[currframe] << "ms to " << ms << "ms" << std::endl;
|
||||||
|
#endif
|
||||||
|
while (currtime < ms){
|
||||||
|
seekNext();
|
||||||
|
if (jsonbuffer.isNull()){return false;}
|
||||||
|
}
|
||||||
|
if (currtime > ms){
|
||||||
|
return seek_frame(currframe - 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Close the file if open
|
/// Close the file if open
|
||||||
DTSC::File::~File(){
|
DTSC::File::~File(){
|
||||||
if (F){
|
if (F){
|
||||||
|
|
|
@ -69,11 +69,17 @@ namespace DTSC{
|
||||||
~File();
|
~File();
|
||||||
std::string & getHeader();
|
std::string & getHeader();
|
||||||
bool writeHeader(std::string & header, bool force = false);
|
bool writeHeader(std::string & header, bool force = false);
|
||||||
|
void seekNext();
|
||||||
std::string & getPacket();
|
std::string & getPacket();
|
||||||
|
JSON::Value & getJSON();
|
||||||
bool seek_frame(int frameno);
|
bool seek_frame(int frameno);
|
||||||
|
bool seek_time(int seconds);
|
||||||
private:
|
private:
|
||||||
std::string strbuffer;
|
std::string strbuffer;
|
||||||
|
JSON::Value jsonbuffer;
|
||||||
std::map<int, long> frames;
|
std::map<int, long> frames;
|
||||||
|
std::map<int, long> msframes;
|
||||||
|
long long int currtime;
|
||||||
int currframe;
|
int currframe;
|
||||||
FILE * F;
|
FILE * F;
|
||||||
unsigned long headerSize;
|
unsigned long headerSize;
|
||||||
|
|
Loading…
Add table
Reference in a new issue