aboutsummaryrefslogtreecommitdiff
path: root/Src/nsmkv/Cues.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nsmkv/Cues.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/nsmkv/Cues.cpp')
-rw-r--r--Src/nsmkv/Cues.cpp205
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;
+}
+