1
0

Tracks.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. #include "Tracks.h"
  2. #include "read.h"
  3. #include "global_elements.h"
  4. // returns bytes read. 0 means EOF
  5. static uint64_t ReadTracksVideo(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Video &video)
  6. {
  7. uint64_t total_bytes_read=0;
  8. while (size)
  9. {
  10. ebml_node node;
  11. uint64_t bytes_read = read_ebml_node(reader, &node);
  12. if (bytes_read == 0)
  13. return 0;
  14. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  15. if (bytes_read > size)
  16. return 0;
  17. total_bytes_read+=bytes_read;
  18. size-=bytes_read;
  19. if (node.size > size)
  20. return 0;
  21. total_bytes_read+=node.size;
  22. size-=node.size;
  23. switch(node.id)
  24. {
  25. case mkv_video_pixelwidth:
  26. {
  27. uint64_t val;
  28. if (read_unsigned(reader, node.size, &val) == 0)
  29. return 0;
  30. #ifdef WA_VALIDATE
  31. printf(" Pixel Width: %I64u\n", val);
  32. video.pixel_width_found=true;
  33. #endif
  34. video.pixel_width=val;
  35. }
  36. break;
  37. case mkv_video_pixelheight:
  38. {
  39. uint64_t val;
  40. if (read_unsigned(reader, node.size, &val) == 0)
  41. return 0;
  42. #ifdef WA_VALIDATE
  43. printf(" Pixel Height: %I64u\n", val);
  44. video.pixel_height_found=true;
  45. #endif
  46. video.pixel_height=val;
  47. }
  48. break;
  49. case mkv_video_flaginterlaced:
  50. {
  51. uint64_t val;
  52. if (read_unsigned(reader, node.size, &val) == 0)
  53. return 0;
  54. #ifdef WA_VALIDATE
  55. printf(" Flag Interlaced: 0x%I64x\n", val);
  56. video.flag_interlaced_found=true;
  57. #endif
  58. video.flag_interlaced = !!val;
  59. }
  60. break;
  61. case mkv_video_displaywidth:
  62. {
  63. uint64_t val;
  64. if (read_unsigned(reader, node.size, &val) == 0)
  65. return 0;
  66. #ifdef WA_VALIDATE
  67. printf(" Display Width: %I64u\n", val);
  68. video.display_width_found = true;
  69. #endif
  70. video.display_width = val;
  71. }
  72. break;
  73. case mkv_video_displayheight:
  74. {
  75. uint64_t val;
  76. if (read_unsigned(reader, node.size, &val) == 0)
  77. return 0;
  78. #ifdef WA_VALIDATE
  79. printf(" Display Height: %I64u\n", val);
  80. video.display_height_found = true;
  81. #endif
  82. video.display_height = val;
  83. }
  84. break;
  85. case mkv_video_pixelcropleft:
  86. {
  87. uint64_t val;
  88. if (read_unsigned(reader, node.size, &val) == 0)
  89. return 0;
  90. #ifdef WA_VALIDATE
  91. printf(" Pixel Crop Left: %I64u\n", val);
  92. video.pixel_crop_left_found = true;
  93. #endif
  94. video.pixel_crop_left = val;
  95. }
  96. break;
  97. case mkv_video_pixelcroptop:
  98. {
  99. uint64_t val;
  100. if (read_unsigned(reader, node.size, &val) == 0)
  101. return 0;
  102. #ifdef WA_VALIDATE
  103. printf(" Pixel Crop Top: %I64u\n", val);
  104. video.pixel_crop_top_found = true;
  105. #endif
  106. video.pixel_crop_top = val;
  107. }
  108. break;
  109. case mkv_video_pixelcropbottom:
  110. {
  111. uint64_t val;
  112. if (read_unsigned(reader, node.size, &val) == 0)
  113. return 0;
  114. #ifdef WA_VALIDATE
  115. printf(" Pixel Crop Bottom: %I64u\n", val);
  116. video.pixel_crop_bottom_found = true;
  117. #endif
  118. video.pixel_crop_bottom = val;
  119. }
  120. break;
  121. case mkv_video_pixelcropright:
  122. {
  123. uint64_t val;
  124. if (read_unsigned(reader, node.size, &val) == 0)
  125. return 0;
  126. #ifdef WA_VALIDATE
  127. printf(" Pixel Crop Right: %I64u\n", val);
  128. video.pixel_crop_right_found = true;
  129. #endif
  130. video.pixel_crop_right = val;
  131. }
  132. break;
  133. default:
  134. nsmkv::ReadGlobal(reader, node.id, node.size);
  135. }
  136. }
  137. return total_bytes_read;
  138. }
  139. // returns bytes read. 0 means EOF
  140. static uint64_t ReadTracksAudio(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Audio &audio)
  141. {
  142. uint64_t total_bytes_read=0;
  143. while (size)
  144. {
  145. ebml_node node;
  146. uint64_t bytes_read = read_ebml_node(reader, &node);
  147. if (bytes_read == 0)
  148. return 0;
  149. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  150. if (bytes_read > size)
  151. return 0;
  152. total_bytes_read+=bytes_read;
  153. size-=bytes_read;
  154. if (node.size > size)
  155. return 0;
  156. total_bytes_read+=node.size;
  157. size-=node.size;
  158. switch(node.id)
  159. {
  160. case mkv_audio_samplingfrequency:
  161. {
  162. double val;
  163. if (read_float(reader, node.size, &val) == 0)
  164. return 0;
  165. #ifdef WA_VALIDATE
  166. printf(" Sampling Frequency: %g\n", val);
  167. audio.sampling_frequency_found = true;
  168. #endif
  169. audio.sampling_frequency = (uint64_t)val;
  170. }
  171. break;
  172. case mkv_audio_channels:
  173. {
  174. uint64_t val;
  175. if (read_unsigned(reader, node.size, &val) == 0)
  176. return 0;
  177. #ifdef WA_VALIDATE
  178. printf(" Channels: %I64u\n", val);
  179. audio.channels_found = true;
  180. #endif
  181. audio.channels = val;
  182. }
  183. break;
  184. case mkv_audio_output_samplingfrequency:
  185. {
  186. uint64_t val;
  187. if (read_unsigned(reader, node.size, &val) == 0)
  188. return 0;
  189. #ifdef WA_VALIDATE
  190. printf(" Output Sampling Frequency: %I64u\n", val);
  191. audio.output_sampling_frequency_found = true;
  192. #endif
  193. audio.output_sampling_frequency = val;
  194. }
  195. break;
  196. default:
  197. nsmkv::ReadGlobal(reader, node.id, node.size);
  198. }
  199. }
  200. return total_bytes_read;
  201. }
  202. static uint64_t ReadTrackEntry(nsmkv::MKVReader *reader, uint64_t size, nsmkv::TrackEntry &track_entry)
  203. {
  204. uint64_t total_bytes_read=0;
  205. while (size)
  206. {
  207. ebml_node node;
  208. uint64_t bytes_read = read_ebml_node(reader, &node);
  209. if (bytes_read == 0)
  210. return 0;
  211. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  212. if (bytes_read > size)
  213. return 0;
  214. total_bytes_read+=bytes_read;
  215. size-=bytes_read;
  216. if (node.size > size)
  217. return 0;
  218. total_bytes_read+=node.size;
  219. size-=node.size;
  220. switch(node.id)
  221. {
  222. case mkv_tracks_tracknumber:
  223. {
  224. uint64_t val;
  225. if (read_unsigned(reader, node.size, &val) == 0)
  226. return 0;
  227. #ifdef WA_VALIDATE
  228. printf(" Track Number: %I64u\n", val);
  229. track_entry.track_number_found = true;
  230. #endif
  231. track_entry.track_number = val;
  232. }
  233. break;
  234. case mkv_tracks_trackuid:
  235. {
  236. uint64_t val;
  237. if (read_unsigned(reader, node.size, &val) == 0)
  238. return 0;
  239. #ifdef WA_VALIDATE
  240. printf(" Track UID: %I64u\n", val);
  241. track_entry.track_uid_found = true;
  242. #endif
  243. track_entry.track_uid = val;
  244. }
  245. break;
  246. case mkv_tracks_tracktype:
  247. {
  248. uint64_t val;
  249. if (read_unsigned(reader, node.size, &val) == 0)
  250. return 0;
  251. #ifdef WA_VALIDATE
  252. printf(" Track Type: 0x%I64x\n", val);
  253. track_entry.track_type_found = true;
  254. #endif
  255. track_entry.track_type = val;
  256. }
  257. break;
  258. case mkv_tracks_flagenabled:
  259. {
  260. uint64_t val;
  261. if (read_unsigned(reader, node.size, &val) == 0)
  262. return 0;
  263. #ifdef WA_VALIDATE
  264. printf(" Flag Enabled: 0x%I64x\n", val);
  265. track_entry.flag_enabled_found = true;
  266. #endif
  267. track_entry.flag_enabled = !!val;
  268. }
  269. break;
  270. case mkv_tracks_flagdefault:
  271. {
  272. uint64_t val;
  273. if (read_unsigned(reader, node.size, &val) == 0)
  274. return 0;
  275. #ifdef WA_VALIDATE
  276. printf(" Flag Default: 0x%I64x\n", val);
  277. track_entry.flag_default_found = true;
  278. #endif
  279. track_entry.flag_default = !!val;
  280. }
  281. break;
  282. case mkv_tracks_flagforced:
  283. {
  284. uint64_t val;
  285. if (read_unsigned(reader, node.size, &val) == 0)
  286. return 0;
  287. #ifdef WA_VALIDATE
  288. printf(" Flag Forced: 0x%I64x\n", val);
  289. track_entry.flag_forced_found = true;
  290. #endif
  291. track_entry.flag_forced = !!val;
  292. }
  293. break;
  294. case mkv_tracks_flaglacing:
  295. {
  296. uint64_t val;
  297. if (read_unsigned(reader, node.size, &val) == 0)
  298. return 0;
  299. #ifdef WA_VALIDATE
  300. printf(" Flag Lacing: 0x%I64x\n", val);
  301. track_entry.flag_lacing_found = true;
  302. #endif
  303. track_entry.flag_lacing = !!val;
  304. }
  305. break;
  306. case mkv_tracks_mincache:
  307. {
  308. uint64_t val;
  309. if (read_unsigned(reader, node.size, &val) == 0)
  310. return 0;
  311. #ifdef WA_VALIDATE
  312. printf(" Min Cache: %I64u\n", val);
  313. track_entry.min_cache_found = true;
  314. #endif
  315. track_entry.min_cache = !!val;
  316. }
  317. break;
  318. case mkv_tracks_tracktimecodescale:
  319. {
  320. double val;
  321. if (read_float(reader, node.size, &val) == 0)
  322. return 0;
  323. #ifdef WA_VALIDATE
  324. printf(" Track Time Code Scale: %g\n", val);
  325. track_entry.track_timecode_scale_found = true;
  326. #endif
  327. track_entry.track_timecode_scale = val;
  328. }
  329. break;
  330. case mkv_tracks_maxblockadditionid:
  331. {
  332. uint64_t val;
  333. if (read_unsigned(reader, node.size, &val) == 0)
  334. return 0;
  335. #ifdef WA_VALIDATE
  336. printf(" Max Block Addition ID: %I64u\n", val);
  337. track_entry.max_block_additional_id_found=true;
  338. #endif
  339. track_entry.max_block_additional_id=val;
  340. }
  341. break;
  342. case mkv_tracks_codecid:
  343. {
  344. char *utf8=0;
  345. if (read_utf8(reader, node.size, &utf8) == 0)
  346. return 0;
  347. #ifdef WA_VALIDATE
  348. if (utf8)
  349. printf(" Codec ID: %s\n", utf8);
  350. track_entry.codec_id_found = true;
  351. #endif
  352. track_entry.Own(track_entry.codec_id, utf8);
  353. }
  354. break;
  355. case mkv_tracks_codecdecodeall:
  356. {
  357. uint64_t val;
  358. if (read_unsigned(reader, node.size, &val) == 0)
  359. return 0;
  360. #ifdef WA_VALIDATE
  361. printf(" Codec Decode All: %I64u\n", val);
  362. track_entry.decode_all_found = true;
  363. #endif
  364. track_entry.decode_all = !!val;
  365. }
  366. break;
  367. case mkv_tracks_defaultduration:
  368. {
  369. uint64_t val;
  370. if (read_unsigned(reader, node.size, &val) == 0)
  371. return 0;
  372. #ifdef WA_VALIDATE
  373. printf(" Default Duration: %I64u\n", val);
  374. track_entry.default_duration_found = true;
  375. #endif
  376. track_entry.default_duration = val;
  377. }
  378. break;
  379. case mkv_tracks_codecprivate:
  380. {
  381. #ifdef WA_VALIDATE
  382. printf(" Codec Private: binary size %I64u\n", node.size);
  383. #endif
  384. void *codec_private = malloc((size_t)node.size);
  385. if (!codec_private)
  386. return 0;
  387. size_t bytes_read;
  388. reader->Read(codec_private, (size_t)node.size, &bytes_read);
  389. if (bytes_read != node.size)
  390. {
  391. free(codec_private);
  392. return 0;
  393. }
  394. track_entry.OwnCodecPrivate(codec_private, (size_t)node.size);
  395. #ifdef WA_VALIDATE
  396. track_entry.codec_private_found = true;
  397. #endif
  398. }
  399. break;
  400. case mkv_tracks_language:
  401. {
  402. char *utf8=0;
  403. if (read_utf8(reader, node.size, &utf8) == 0)
  404. return 0;
  405. #ifdef WA_VALIDATE
  406. if (utf8)
  407. printf(" Codec Language: %s\n", utf8);
  408. track_entry.language_found = true;
  409. #endif
  410. track_entry.Own(track_entry.language, utf8);
  411. }
  412. break;
  413. case mkv_tracks_video:
  414. {
  415. #ifdef WA_VALIDATE
  416. printf(" Video Settings\n");
  417. #endif
  418. if (ReadTracksVideo(reader, node.size, track_entry.video) == 0)
  419. return 0;
  420. }
  421. break;
  422. case mkv_tracks_audio:
  423. {
  424. #ifdef WA_VALIDATE
  425. printf(" Audio Settings\n");
  426. #endif
  427. if (ReadTracksAudio(reader, node.size, track_entry.audio) == 0)
  428. return 0;
  429. }
  430. break;
  431. case mkv_tracks_name:
  432. {
  433. char *utf8=0;
  434. if (read_utf8(reader, node.size, &utf8) == 0)
  435. return 0;
  436. #ifdef WA_VALIDATE
  437. if (utf8)
  438. printf(" Track Name: %s\n", utf8);
  439. track_entry.name_found = true;
  440. #endif
  441. track_entry.Own(track_entry.name, utf8);
  442. }
  443. break;
  444. case mkv_tracks_maxcache:
  445. {
  446. uint64_t val;
  447. if (read_unsigned(reader, node.size, &val) == 0)
  448. return 0;
  449. #ifdef WA_VALIDATE
  450. printf(" Max Cache: %I64u\n", val);
  451. track_entry.max_cache_found = true;
  452. #endif
  453. track_entry.max_cache = val;
  454. }
  455. break;
  456. default:
  457. nsmkv::ReadGlobal(reader, node.id, node.size);
  458. }
  459. }
  460. return total_bytes_read;
  461. }
  462. // returns bytes read. 0 means EOF
  463. uint64_t nsmkv::ReadTracks(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Tracks &tracks)
  464. {
  465. uint64_t total_bytes_read=0;
  466. while (size)
  467. {
  468. ebml_node node;
  469. uint64_t bytes_read = read_ebml_node(reader, &node);
  470. if (bytes_read == 0)
  471. return 0;
  472. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  473. if (bytes_read > size)
  474. return 0;
  475. total_bytes_read+=bytes_read;
  476. size-=bytes_read;
  477. if (node.size > size)
  478. return 0;
  479. total_bytes_read+=node.size;
  480. size-=node.size;
  481. switch(node.id)
  482. {
  483. case mkv_tracks_trackentry:
  484. {
  485. #ifdef WA_VALIDATE
  486. printf(" Track Entry\n");
  487. #endif
  488. TrackEntry *track_entry = new TrackEntry;
  489. if (ReadTrackEntry(reader, node.size, *track_entry) == 0)
  490. {
  491. delete track_entry;
  492. return 0;
  493. }
  494. tracks.tracks.push_back(track_entry);
  495. }
  496. break;
  497. default:
  498. ReadGlobal(reader, node.id, node.size);
  499. }
  500. }
  501. return total_bytes_read;
  502. }
  503. const nsmkv::TrackEntry *nsmkv::Tracks::EnumTrack(size_t i) const
  504. {
  505. if (tracks.size() > i)
  506. {
  507. return tracks[i];
  508. }
  509. return 0;
  510. }