MKVInfo.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "MKVInfo.h"
  2. #include "../nsmkv/global_elements.h"
  3. #include "../nsmkv/read.h"
  4. #include "../nsmkv/segment.h"
  5. #include "../nsmkv/tracks.h"
  6. #include "../nsmkv/file_mkv_reader.h"
  7. MKVInfo::MKVInfo()
  8. {
  9. segment_info_found = false;
  10. content_length = 0;
  11. tracks_found = false;
  12. }
  13. bool MKVInfo::Open(const wchar_t *filename)
  14. {
  15. FILE *f = _wfopen(filename, L"rb");
  16. if (!f)
  17. return false;
  18. MKVReaderFILE reader(f);
  19. content_length = reader.GetContentLength();
  20. ebml_node node;
  21. while (!segment_info_found)
  22. {
  23. if (read_ebml_node(&reader, &node) == 0)
  24. break;
  25. switch(node.id)
  26. {
  27. case mkv_header:
  28. if (nsmkv::ReadHeader(&reader, node.size, header) == 0)
  29. {
  30. return false;
  31. }
  32. break;
  33. case mkv_segment:
  34. if (ReadSegment(&reader, node.size) == 0)
  35. {
  36. return false;
  37. }
  38. break;
  39. default:
  40. nsmkv::SkipNode(&reader, node.id, node.size);
  41. }
  42. }
  43. return segment_info_found;
  44. }
  45. uint64_t MKVInfo::ReadSegment(nsmkv::MKVReader *reader, uint64_t size)
  46. {
  47. uint64_t total_bytes_read=0;
  48. while (size && (!segment_info_found || !tracks_found))
  49. {
  50. ebml_node node;
  51. uint64_t bytes_read = read_ebml_node(reader, &node);
  52. if (bytes_read == 0)
  53. return 0;
  54. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  55. if (bytes_read > size)
  56. return 0;
  57. total_bytes_read+=bytes_read;
  58. size-=bytes_read;
  59. if (node.size > size)
  60. return 0;
  61. total_bytes_read+=node.size;
  62. size-=node.size;
  63. switch(node.id)
  64. {
  65. case mkv_segment_segmentinfo:
  66. {
  67. if (ReadSegmentInfo(reader, node.size, segment_info) == 0)
  68. return 0;
  69. segment_info_found=true;
  70. }
  71. break;
  72. case mkv_segment_tracks:
  73. {
  74. if (ReadTracks(reader, node.size, tracks) == 0)
  75. return 0;
  76. tracks_found=true;
  77. }
  78. break;
  79. default:
  80. if (nsmkv::SkipNode(reader, node.id, node.size) == 0)
  81. return 0;
  82. }
  83. }
  84. return total_bytes_read;
  85. }
  86. int MKVInfo::GetLengthMilliseconds()
  87. {
  88. if (!segment_info_found)
  89. return -1000;
  90. else
  91. return segment_info.GetDurationMilliseconds();
  92. }
  93. const char *MKVInfo::GetTitle()
  94. {
  95. return segment_info.title;
  96. }
  97. int MKVInfo::GetBitrate()
  98. {
  99. if (segment_info_found)
  100. {
  101. int time_ms = segment_info.GetDurationMilliseconds();
  102. if (time_ms)
  103. return (int) (8ULL * content_length / (uint64_t)time_ms);
  104. }
  105. return 0;
  106. }
  107. bool MKVInfo::GetHeight(int &height)
  108. {
  109. if (tracks_found)
  110. {
  111. size_t i=0;
  112. const nsmkv::TrackEntry *track=0;
  113. while (track = tracks.EnumTrack(i++))
  114. {
  115. if (track->track_type == mkv_track_type_video)
  116. {
  117. height = (int)track->video.pixel_height;
  118. return true;
  119. }
  120. }
  121. }
  122. return false;
  123. }
  124. bool MKVInfo::GetWidth(int &width)
  125. {
  126. if (tracks_found)
  127. {
  128. size_t i=0;
  129. const nsmkv::TrackEntry *track=0;
  130. while (track = tracks.EnumTrack(i++))
  131. {
  132. if (track->track_type == mkv_track_type_video)
  133. {
  134. width = (int)track->video.pixel_width;
  135. return true;
  136. }
  137. }
  138. }
  139. return false;
  140. }
  141. const nsmkv::Tracks *MKVInfo::GetTracks()
  142. {
  143. if (tracks_found)
  144. return &tracks;
  145. else
  146. return 0;
  147. }