diff options
Diffstat (limited to 'Src/nsmkv/Cues.cpp')
-rw-r--r-- | Src/nsmkv/Cues.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/Src/nsmkv/Cues.cpp b/Src/nsmkv/Cues.cpp new file mode 100644 index 00000000..95b3b538 --- /dev/null +++ b/Src/nsmkv/Cues.cpp @@ -0,0 +1,205 @@ +#include "Cues.h" +#include "read.h" +#include "global_elements.h" + +nsmkv::CuePoint *nsmkv::Cues::GetCuePoint(uint64_t when, uint64_t current_time, int seek_direction) +{ + CuePoint *last=0; + CuePoints::iterator itr; + for (itr=cue_points.begin(); itr!=cue_points.end();itr++) + { + CuePoint *cue_point = itr->second; + if (cue_point->cue_time == when) + { + if (seek_direction != SEEK_FORWARD || current_time < cue_point->cue_time) + return cue_point; + } + else if (cue_point->cue_time > when) + { + if (last) + { + if (seek_direction != SEEK_FORWARD || current_time < last->cue_time) + return last; + } + else + return cue_point; + } + + last = cue_point; + } + return last; // will be 0 if we don't have any cue points, which is what we want. +} + +nsmkv::CueTrackPosition *nsmkv::CuePoint::GetPosition(uint64_t track) +{ + CueTrackPositions::iterator found = cue_track_positions.find(track); + if (found != cue_track_positions.end()) + return found->second; + else + return 0; +} + +// returns bytes read. 0 means EOF +static uint64_t ReadCueTrackPositions(nsmkv::MKVReader *reader, uint64_t size, nsmkv::CueTrackPosition &track_position) +{ + uint64_t total_bytes_read=0; + while (size) + { + ebml_node node; + uint64_t bytes_read = read_ebml_node(reader, &node); + + if (bytes_read == 0) + return 0; + + // benski> checking bytes_read and node.size separately prevents possible integer overflow attack + if (bytes_read > size) + return 0; + total_bytes_read+=bytes_read; + size-=bytes_read; + + if (node.size > size) + return 0; + total_bytes_read+=node.size; + size-=node.size; + + switch(node.id) + { + case mkv_cuetrackpositions_cuetrack: + { + uint64_t val; + if (read_unsigned(reader, node.size, &val) == 0) + return 0; + + track_position.track = val; +#ifdef WA_VALIDATE + printf(" Cue Track: %I64u\n", val); + track_position.track_found = true; +#endif + } + break; + case mkv_cuetrackpositions_cueclusterposition: + { + uint64_t val; + if (read_unsigned(reader, node.size, &val) == 0) + return 0; + + track_position.cluster_position = val; +#ifdef WA_VALIDATE + printf(" Cue Cluster Position: %I64u\n", val); + track_position.cluster_position_found = true; +#endif + } + break; + default: + nsmkv::ReadGlobal(reader, node.id, node.size); + } + } + return total_bytes_read; +} + +// returns bytes read. 0 means EOF +static uint64_t ReadCuePoint(nsmkv::MKVReader *reader, uint64_t size, nsmkv::CuePoint &cue_point) +{ + uint64_t total_bytes_read=0; + while (size) + { + ebml_node node; + uint64_t bytes_read = read_ebml_node(reader, &node); + + if (bytes_read == 0) + return 0; + + // benski> checking bytes_read and node.size separately prevents possible integer overflow attack + if (bytes_read > size) + return 0; + total_bytes_read+=bytes_read; + size-=bytes_read; + + if (node.size > size) + return 0; + total_bytes_read+=node.size; + size-=node.size; + + switch(node.id) + { + case mkv_cuepoint_cuetime: + { + uint64_t val; + if (read_unsigned(reader, node.size, &val) == 0) + return 0; + + cue_point.cue_time = val; + +#ifdef WA_VALIDATE + printf(" Cue Time: %I64u\n", val); + cue_point.cue_time_found = true; +#endif + } + break; + case mkv_cuepoint_cuetrackpositions: + { +#ifdef WA_VALIDATE + printf(" Cue Track Positions\n"); +#endif + nsmkv::CueTrackPosition *track_position = new nsmkv::CueTrackPosition; + if (ReadCueTrackPositions(reader, node.size, *track_position) == 0) + { + delete track_position; + return 0; + } + cue_point.cue_track_positions[track_position->track] = track_position; + } + break; + default: + nsmkv::ReadGlobal(reader, node.id, node.size); + } + } + return total_bytes_read; +} + +// returns bytes read. 0 means EOF +uint64_t nsmkv::ReadCues(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Cues &cues) +{ + uint64_t total_bytes_read=0; + while (size) + { + ebml_node node; + uint64_t bytes_read = read_ebml_node(reader, &node); + + if (bytes_read == 0) + return 0; + + // benski> checking bytes_read and node.size separately prevents possible integer overflow attack + if (bytes_read > size) + return 0; + total_bytes_read+=bytes_read; + size-=bytes_read; + + if (node.size > size) + return 0; + total_bytes_read+=node.size; + size-=node.size; + + switch(node.id) + { + case mkv_cues_cuepoint: + { +#ifdef WA_VALIDATE + printf(" Cue Point\n"); +#endif + CuePoint *cue_point = new CuePoint; + if (ReadCuePoint(reader, node.size, *cue_point) == 0) + { + delete cue_point; + return 0; + } + cues.cue_points[cue_point->cue_time] = cue_point; + } + break; + default: + ReadGlobal(reader, node.id, node.size); + } + } + return total_bytes_read; +} + |