MKVDuration.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "MKVDuration.h"
  2. #include "../nsmkv/global_elements.h"
  3. #include "../nsmkv/read.h"
  4. #include "../nsmkv/segment.h"
  5. #include "../nsmkv/file_mkv_reader.h"
  6. MKVDuration::MKVDuration()
  7. {
  8. segment_info_found = false;
  9. content_length = 0;
  10. }
  11. bool MKVDuration::Open(const wchar_t *filename)
  12. {
  13. FILE *f = _wfopen(filename, L"rb");
  14. if (!f)
  15. return false;
  16. MKVReaderFILE reader(f);
  17. content_length = reader.GetContentLength();
  18. ebml_node node;
  19. while (!segment_info_found)
  20. {
  21. if (read_ebml_node(&reader, &node) == 0)
  22. break;
  23. switch(node.id)
  24. {
  25. case mkv_header:
  26. if (nsmkv::ReadHeader(&reader, node.size, header) == 0)
  27. {
  28. return false;
  29. }
  30. break;
  31. case mkv_segment:
  32. if (ReadSegment(&reader, node.size) == 0)
  33. {
  34. return false;
  35. }
  36. break;
  37. default:
  38. nsmkv::SkipNode(&reader, node.id, node.size);
  39. }
  40. }
  41. return segment_info_found;
  42. }
  43. uint64_t MKVDuration::ReadSegment(nsmkv::MKVReader *reader, uint64_t size)
  44. {
  45. uint64_t total_bytes_read=0;
  46. while (size && !segment_info_found)
  47. {
  48. ebml_node node;
  49. uint64_t bytes_read = read_ebml_node(reader, &node);
  50. if (bytes_read == 0)
  51. return 0;
  52. // benski> checking bytes_read and node.size separately prevents possible integer overflow attack
  53. if (bytes_read > size)
  54. return 0;
  55. total_bytes_read+=bytes_read;
  56. size-=bytes_read;
  57. if (node.size > size)
  58. return 0;
  59. total_bytes_read+=node.size;
  60. size-=node.size;
  61. switch(node.id)
  62. {
  63. case mkv_segment_segmentinfo:
  64. {
  65. printf("SegmentInfo\n");
  66. if (ReadSegmentInfo(reader, node.size, segment_info) == 0)
  67. return 0;
  68. segment_info_found=true;
  69. }
  70. break;
  71. default:
  72. if (nsmkv::SkipNode(reader, node.id, node.size) == 0)
  73. return 0;
  74. }
  75. }
  76. return total_bytes_read;
  77. }
  78. int MKVDuration::GetLengthMilliseconds()
  79. {
  80. if (!segment_info_found)
  81. return -1000;
  82. else
  83. return segment_info.GetDurationMilliseconds();
  84. }
  85. const char *MKVDuration::GetTitle()
  86. {
  87. return segment_info.title;
  88. }
  89. int MKVDuration::GetBitrate()
  90. {
  91. if (segment_info_found)
  92. {
  93. int time_ms = segment_info.GetDurationMilliseconds();
  94. if (time_ms)
  95. return (int) (8ULL * content_length / (uint64_t)time_ms);
  96. }
  97. return 0;
  98. }