Cues.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "Cues.h"
  2. #include "read.h"
  3. #include "global_elements.h"
  4. nsmkv::CuePoint *nsmkv::Cues::GetCuePoint(uint64_t when, uint64_t current_time, int seek_direction)
  5. {
  6. CuePoint *last=0;
  7. CuePoints::iterator itr;
  8. for (itr=cue_points.begin(); itr!=cue_points.end();itr++)
  9. {
  10. CuePoint *cue_point = itr->second;
  11. if (cue_point->cue_time == when)
  12. {
  13. if (seek_direction != SEEK_FORWARD || current_time < cue_point->cue_time)
  14. return cue_point;
  15. }
  16. else if (cue_point->cue_time > when)
  17. {
  18. if (last)
  19. {
  20. if (seek_direction != SEEK_FORWARD || current_time < last->cue_time)
  21. return last;
  22. }
  23. else
  24. return cue_point;
  25. }
  26. last = cue_point;
  27. }
  28. return last; // will be 0 if we don't have any cue points, which is what we want.
  29. }
  30. nsmkv::CueTrackPosition *nsmkv::CuePoint::GetPosition(uint64_t track)
  31. {
  32. CueTrackPositions::iterator found = cue_track_positions.find(track);
  33. if (found != cue_track_positions.end())
  34. return found->second;
  35. else
  36. return 0;
  37. }
  38. // returns bytes read. 0 means EOF
  39. static uint64_t ReadCueTrackPositions(nsmkv::MKVReader *reader, uint64_t size, nsmkv::CueTrackPosition &track_position)
  40. {
  41. uint64_t total_bytes_read=0;
  42. while (size)
  43. {
  44. ebml_node node;
  45. uint64_t bytes_read = read_ebml_node(reader, &node);
  46. if (bytes_read == 0)
  47. return 0;
  48. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  49. if (bytes_read > size)
  50. return 0;
  51. total_bytes_read+=bytes_read;
  52. size-=bytes_read;
  53. if (node.size > size)
  54. return 0;
  55. total_bytes_read+=node.size;
  56. size-=node.size;
  57. switch(node.id)
  58. {
  59. case mkv_cuetrackpositions_cuetrack:
  60. {
  61. uint64_t val;
  62. if (read_unsigned(reader, node.size, &val) == 0)
  63. return 0;
  64. track_position.track = val;
  65. #ifdef WA_VALIDATE
  66. printf(" Cue Track: %I64u\n", val);
  67. track_position.track_found = true;
  68. #endif
  69. }
  70. break;
  71. case mkv_cuetrackpositions_cueclusterposition:
  72. {
  73. uint64_t val;
  74. if (read_unsigned(reader, node.size, &val) == 0)
  75. return 0;
  76. track_position.cluster_position = val;
  77. #ifdef WA_VALIDATE
  78. printf(" Cue Cluster Position: %I64u\n", val);
  79. track_position.cluster_position_found = true;
  80. #endif
  81. }
  82. break;
  83. default:
  84. nsmkv::ReadGlobal(reader, node.id, node.size);
  85. }
  86. }
  87. return total_bytes_read;
  88. }
  89. // returns bytes read. 0 means EOF
  90. static uint64_t ReadCuePoint(nsmkv::MKVReader *reader, uint64_t size, nsmkv::CuePoint &cue_point)
  91. {
  92. uint64_t total_bytes_read=0;
  93. while (size)
  94. {
  95. ebml_node node;
  96. uint64_t bytes_read = read_ebml_node(reader, &node);
  97. if (bytes_read == 0)
  98. return 0;
  99. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  100. if (bytes_read > size)
  101. return 0;
  102. total_bytes_read+=bytes_read;
  103. size-=bytes_read;
  104. if (node.size > size)
  105. return 0;
  106. total_bytes_read+=node.size;
  107. size-=node.size;
  108. switch(node.id)
  109. {
  110. case mkv_cuepoint_cuetime:
  111. {
  112. uint64_t val;
  113. if (read_unsigned(reader, node.size, &val) == 0)
  114. return 0;
  115. cue_point.cue_time = val;
  116. #ifdef WA_VALIDATE
  117. printf(" Cue Time: %I64u\n", val);
  118. cue_point.cue_time_found = true;
  119. #endif
  120. }
  121. break;
  122. case mkv_cuepoint_cuetrackpositions:
  123. {
  124. #ifdef WA_VALIDATE
  125. printf(" Cue Track Positions\n");
  126. #endif
  127. nsmkv::CueTrackPosition *track_position = new nsmkv::CueTrackPosition;
  128. if (ReadCueTrackPositions(reader, node.size, *track_position) == 0)
  129. {
  130. delete track_position;
  131. return 0;
  132. }
  133. cue_point.cue_track_positions[track_position->track] = track_position;
  134. }
  135. break;
  136. default:
  137. nsmkv::ReadGlobal(reader, node.id, node.size);
  138. }
  139. }
  140. return total_bytes_read;
  141. }
  142. // returns bytes read. 0 means EOF
  143. uint64_t nsmkv::ReadCues(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Cues &cues)
  144. {
  145. uint64_t total_bytes_read=0;
  146. while (size)
  147. {
  148. ebml_node node;
  149. uint64_t bytes_read = read_ebml_node(reader, &node);
  150. if (bytes_read == 0)
  151. return 0;
  152. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  153. if (bytes_read > size)
  154. return 0;
  155. total_bytes_read+=bytes_read;
  156. size-=bytes_read;
  157. if (node.size > size)
  158. return 0;
  159. total_bytes_read+=node.size;
  160. size-=node.size;
  161. switch(node.id)
  162. {
  163. case mkv_cues_cuepoint:
  164. {
  165. #ifdef WA_VALIDATE
  166. printf(" Cue Point\n");
  167. #endif
  168. CuePoint *cue_point = new CuePoint;
  169. if (ReadCuePoint(reader, node.size, *cue_point) == 0)
  170. {
  171. delete cue_point;
  172. return 0;
  173. }
  174. cues.cue_points[cue_point->cue_time] = cue_point;
  175. }
  176. break;
  177. default:
  178. ReadGlobal(reader, node.id, node.size);
  179. }
  180. }
  181. return total_bytes_read;
  182. }