SegmentInfo.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "SegmentInfo.h"
  2. #include "read.h"
  3. #include "global_elements.h"
  4. #include <time.h>
  5. #include <TCHAR.h>
  6. #include <sys/stat.h>
  7. int FileExists(const char * filename);
  8. // returns bytes read. 0 means EOF
  9. uint64_t nsmkv::ReadSegmentInfo(nsmkv::MKVReader *reader, uint64_t size, nsmkv::SegmentInfo &segment_info)
  10. {
  11. uint64_t total_bytes_read=0;
  12. while (size)
  13. {
  14. ebml_node node;
  15. uint64_t bytes_read = read_ebml_node(reader, &node);
  16. if (bytes_read == 0)
  17. return 0;
  18. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  19. if (bytes_read > size)
  20. return 0;
  21. total_bytes_read+=bytes_read;
  22. size-=bytes_read;
  23. if (node.size > size)
  24. return 0;
  25. total_bytes_read+=node.size;
  26. size-=node.size;
  27. switch(node.id)
  28. {
  29. case mkv_segmentinfo_timecodescale:
  30. {
  31. uint64_t val;
  32. if (read_unsigned(reader, node.size, &val) == 0)
  33. return 0;
  34. #ifdef WA_VALIDATE
  35. printf(" Time Code Scale: %I64u\n", val);
  36. segment_info.time_code_scale_found = true;
  37. #endif
  38. segment_info.time_code_scale = val;
  39. }
  40. break;
  41. case mkv_segmentinfo_muxingapp:
  42. {
  43. char *utf8 = 0;
  44. if (node.size && read_utf8(reader, node.size, &utf8) == 0)
  45. return 0;
  46. if (utf8)
  47. #ifdef WA_VALIDATE
  48. printf(" Muxing App: %s\n", utf8);
  49. segment_info.muxing_app_found = true;
  50. #endif
  51. segment_info.Own(segment_info.muxing_app, utf8);
  52. }
  53. break;
  54. case mkv_segmentinfo_writingapp:
  55. {
  56. char *utf8 = 0;
  57. if (node.size && read_utf8(reader, node.size, &utf8) == 0)
  58. return 0;
  59. if (utf8)
  60. #ifdef WA_VALIDATE
  61. printf(" Writing App: %s\n", utf8);
  62. segment_info.writing_app_found = true;
  63. #endif
  64. segment_info.Own(segment_info.writing_app, utf8);
  65. }
  66. break;
  67. case mkv_segmentinfo_duration:
  68. {
  69. double val;
  70. if (read_float(reader, node.size, &val) == 0)
  71. return 0;
  72. #ifdef WA_VALIDATE
  73. printf(" Duration: %g\n", val);
  74. segment_info.duration_found = true;
  75. #endif
  76. segment_info.duration = val;
  77. }
  78. break;
  79. case mkv_segmentinfo_dateutc:
  80. {
  81. uint64_t val;
  82. if (read_unsigned(reader, node.size, &val) == 0)
  83. return 0;
  84. segment_info.production_date = val;
  85. // value is in nanoseconds, relative to jan 01, 2001. ugh
  86. __time64_t val_time = mkv_date_as_time_t(val);
  87. #ifdef WA_VALIDATE
  88. printf(" Date UTC: %s", _ctime64(&val_time));
  89. segment_info.production_date_found = true;
  90. #endif
  91. }
  92. break;
  93. case mkv_segmentinfo_segmentuid:
  94. {
  95. #ifdef WA_VALIDATE
  96. printf(" Segment UID: binary size %I64u\n", node.size);
  97. segment_info.segment_uid_found = true;
  98. #endif
  99. if (node.size == 16)
  100. {
  101. size_t bytes_read;
  102. reader->Read(&segment_info.segment_uid, (size_t)node.size, &bytes_read);
  103. if (bytes_read != node.size)
  104. return 0;
  105. }
  106. else // bad size, let's just skip it
  107. {
  108. reader->Skip(node.size);
  109. }
  110. }
  111. break;
  112. case mkv_segmentinfo_prevuid:
  113. {
  114. #ifdef WA_VALIDATE
  115. printf(" Previous UID: binary size %I64u\n", node.size);
  116. segment_info.prev_uid_found = true;
  117. #endif
  118. if (node.size == 16)
  119. {
  120. size_t bytes_read;
  121. reader->Read(&segment_info.prev_uid, (size_t)node.size, &bytes_read);
  122. if (bytes_read != node.size)
  123. return 0;
  124. }
  125. else // bad size, let's just skip it
  126. {
  127. reader->Skip(node.size);
  128. }
  129. }
  130. break;
  131. case mkv_segmentinfo_nextuid:
  132. {
  133. #ifdef WA_VALIDATE
  134. printf(" Next Segment UID: binary size %I64u\n", node.size);
  135. segment_info.next_uid_found = true;
  136. #endif
  137. if (node.size == 16)
  138. {
  139. size_t bytes_read;
  140. reader->Read(&segment_info.next_uid, (size_t)node.size, &bytes_read);
  141. if (bytes_read != node.size)
  142. return 0;
  143. }
  144. else // bad size, let's just skip it
  145. {
  146. reader->Skip(node.size);
  147. }
  148. }
  149. break;
  150. case mkv_segmentinfo_title:
  151. {
  152. char *utf8 = 0;
  153. if (read_utf8(reader, node.size, &utf8) == 0)
  154. return 0;
  155. if (utf8)
  156. #ifdef WA_VALIDATE
  157. printf(" Title: %s\n", utf8);
  158. segment_info.title_found = true;
  159. #endif
  160. segment_info.Own(segment_info.title, utf8);
  161. }
  162. break;
  163. case mkv_segmentinfo_prevfilename:
  164. {
  165. char *utf8 = 0;
  166. if (read_utf8(reader, node.size, &utf8) == 0)
  167. return 0;
  168. if (utf8)
  169. #ifdef WA_VALIDATE
  170. printf(" Previous Filename: %s\n", utf8);
  171. segment_info.prev_filename_found = true;
  172. if (FileExists(segment_info.prev_filename) != 0)
  173. {
  174. printf("****Specified previous filename not found");
  175. }
  176. #endif
  177. segment_info.Own(segment_info.prev_filename,utf8);
  178. }
  179. break;
  180. case mkv_segmentinfo_nextfilename:
  181. {
  182. char *utf8 = 0;
  183. if (read_utf8(reader, node.size, &utf8) == 0)
  184. return 0;
  185. if (utf8)
  186. #ifdef WA_VALIDATE
  187. printf(" Next Filename: %s\n", utf8);
  188. segment_info.next_filename_found = true;
  189. if (FileExists(segment_info.next_filename) != 0)
  190. {
  191. printf("****Specified next filename not found");
  192. }
  193. #endif
  194. segment_info.Own(segment_info.next_filename, utf8);
  195. }
  196. break;
  197. default:
  198. nsmkv::ReadGlobal(reader, node.id, node.size);
  199. }
  200. }
  201. return total_bytes_read;
  202. }
  203. int nsmkv::SegmentInfo::GetDurationMilliseconds() const
  204. {
  205. double nanoseconds = (double)time_code_scale * duration;
  206. double microseconds = nanoseconds / 1000.0;
  207. double milliseconds = microseconds / 1000.0;
  208. return (int)milliseconds;
  209. }
  210. uint64_t nsmkv::SegmentInfo::ConvertMillisecondsToTime(int milliseconds) const
  211. {
  212. double time_code = (double)milliseconds * 1000000.0 / (double)time_code_scale;
  213. return (uint64_t)time_code;
  214. }
  215. int FileExists(const char * filename) {
  216. int iStat;
  217. struct _stat64 fileInfo;
  218. // get the file attributes
  219. return (iStat = _stat64(filename,&fileInfo));
  220. }