Fix bug in Output::seek() when seeking to a timestamp that is between the last part of a key and the first part of the next key
This commit is contained in:
parent
dd5ae98002
commit
4080d141f8
7 changed files with 44 additions and 26 deletions
41
lib/dtsc.cpp
41
lib/dtsc.cpp
|
@ -6,6 +6,7 @@
|
|||
#include "dtsc.h"
|
||||
#include "encode.h"
|
||||
#include "lib/shared_memory.h"
|
||||
#include "lib/util.h"
|
||||
#include <arpa/inet.h> //for htonl/ntohl
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
@ -3159,6 +3160,35 @@ namespace DTSC{
|
|||
return pages.getInt("firstkey", res);
|
||||
}
|
||||
|
||||
/// Returns the key number containing a given time.
|
||||
/// Or, closest key if given time is not available.
|
||||
/// Or, zero if no keys are available at all.
|
||||
/// If the time is in the gap before a key, returns that next key instead.
|
||||
size_t Meta::getKeyNumForTime(uint32_t idx, uint64_t time) const{
|
||||
const Track &trk = tracks.at(idx);
|
||||
const Util::RelAccX &keys = trk.keys;
|
||||
const Util::RelAccX &parts = trk.parts;
|
||||
if (!keys.getEndPos()){return 0;}
|
||||
size_t res = keys.getStartPos();
|
||||
for (size_t i = res; i < keys.getEndPos(); i++){
|
||||
if (keys.getInt(trk.keyTimeField, i) > time){
|
||||
//It's possible we overshot our timestamp, but the previous key does not contain it.
|
||||
//This happens when seeking to a timestamp past the last part of the previous key, but
|
||||
//before the first part of the next key.
|
||||
//In this case, we should _not_ return the previous key, but the current key.
|
||||
//That prevents getting stuck at the end of the page, waiting for a part to show up that never will.
|
||||
if (keys.getInt(trk.keyFirstPartField, i) > parts.getStartPos()){
|
||||
uint64_t dur = parts.getInt(trk.partDurationField, keys.getInt(trk.keyFirstPartField, i)-1);
|
||||
if (keys.getInt(trk.keyTimeField, i) - dur < time){res = i;}
|
||||
}
|
||||
break;
|
||||
}
|
||||
res = i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Parts::Parts(const Util::RelAccX &_parts) : parts(_parts){
|
||||
sizeField = parts.getFieldData("size");
|
||||
durationField = parts.getFieldData("duration");
|
||||
|
@ -3208,17 +3238,6 @@ namespace DTSC{
|
|||
}
|
||||
size_t Keys::getSize(size_t idx) const{return cKeys.getInt(sizeField, idx);}
|
||||
|
||||
/// Returns the key number containing a given timestamp.
|
||||
/// Returns the closest key number if the timestamp is not available.
|
||||
size_t Keys::getNumForTime(uint64_t time) const{
|
||||
size_t res = getFirstValid();
|
||||
for (size_t i = getFirstValid(); i < getEndValid(); i++){
|
||||
if (getTime(i) > time){break;}
|
||||
res = i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Fragments::Fragments(const Util::RelAccX &_fragments) : fragments(_fragments){}
|
||||
size_t Fragments::getFirstValid() const{return fragments.getDeleted();}
|
||||
size_t Fragments::getEndValid() const{return fragments.getEndPos();}
|
||||
|
|
|
@ -189,7 +189,6 @@ namespace DTSC{
|
|||
uint64_t getTime(size_t idx) const;
|
||||
void setSize(size_t idx, size_t _size);
|
||||
size_t getSize(size_t idx) const;
|
||||
size_t getNumForTime(uint64_t time) const;
|
||||
|
||||
private:
|
||||
bool isConst;
|
||||
|
@ -442,6 +441,7 @@ namespace DTSC{
|
|||
bool nextPageAvailable(uint32_t idx, size_t currentPage) const;
|
||||
size_t getPageNumberForTime(uint32_t idx, uint64_t time) const;
|
||||
size_t getPageNumberForKey(uint32_t idx, uint64_t keynumber) const;
|
||||
size_t getKeyNumForTime(uint32_t idx, uint64_t time) const;
|
||||
|
||||
const Util::RelAccX &parts(size_t idx) const;
|
||||
Util::RelAccX &keys(size_t idx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue