webmdec.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright (c) 2016, Alliance for Open Media. All rights reserved
  3. *
  4. * This source code is subject to the terms of the BSD 2 Clause License and
  5. * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
  6. * was not distributed with this source code in the LICENSE file, you can
  7. * obtain it at www.aomedia.org/license/software. If the Alliance for Open
  8. * Media Patent License 1.0 was not distributed with this source code in the
  9. * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  10. */
  11. #include "common/webmdec.h"
  12. #include <cassert>
  13. #include <cstring>
  14. #include <cstdio>
  15. #include "third_party/libwebm/mkvparser/mkvparser.h"
  16. #include "third_party/libwebm/mkvparser/mkvreader.h"
  17. namespace {
  18. void reset(struct WebmInputContext *const webm_ctx) {
  19. if (webm_ctx->reader != NULL) {
  20. mkvparser::MkvReader *const reader =
  21. reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
  22. delete reader;
  23. }
  24. if (webm_ctx->segment != NULL) {
  25. mkvparser::Segment *const segment =
  26. reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
  27. delete segment;
  28. }
  29. if (webm_ctx->buffer != NULL) {
  30. delete[] webm_ctx->buffer;
  31. }
  32. webm_ctx->reader = NULL;
  33. webm_ctx->segment = NULL;
  34. webm_ctx->buffer = NULL;
  35. webm_ctx->cluster = NULL;
  36. webm_ctx->block_entry = NULL;
  37. webm_ctx->block = NULL;
  38. webm_ctx->block_frame_index = 0;
  39. webm_ctx->video_track_index = 0;
  40. webm_ctx->timestamp_ns = 0;
  41. webm_ctx->is_key_frame = false;
  42. }
  43. void get_first_cluster(struct WebmInputContext *const webm_ctx) {
  44. mkvparser::Segment *const segment =
  45. reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
  46. const mkvparser::Cluster *const cluster = segment->GetFirst();
  47. webm_ctx->cluster = cluster;
  48. }
  49. void rewind_and_reset(struct WebmInputContext *const webm_ctx,
  50. struct AvxInputContext *const aom_ctx) {
  51. rewind(aom_ctx->file);
  52. reset(webm_ctx);
  53. }
  54. } // namespace
  55. int file_is_webm(struct WebmInputContext *webm_ctx,
  56. struct AvxInputContext *aom_ctx) {
  57. mkvparser::MkvReader *const reader = new mkvparser::MkvReader(aom_ctx->file);
  58. webm_ctx->reader = reader;
  59. webm_ctx->reached_eos = 0;
  60. mkvparser::EBMLHeader header;
  61. long long pos = 0;
  62. if (header.Parse(reader, pos) < 0) {
  63. rewind_and_reset(webm_ctx, aom_ctx);
  64. return 0;
  65. }
  66. mkvparser::Segment *segment;
  67. if (mkvparser::Segment::CreateInstance(reader, pos, segment)) {
  68. rewind_and_reset(webm_ctx, aom_ctx);
  69. return 0;
  70. }
  71. webm_ctx->segment = segment;
  72. if (segment->Load() < 0) {
  73. rewind_and_reset(webm_ctx, aom_ctx);
  74. return 0;
  75. }
  76. const mkvparser::Tracks *const tracks = segment->GetTracks();
  77. const mkvparser::VideoTrack *video_track = NULL;
  78. for (unsigned long i = 0; i < tracks->GetTracksCount(); ++i) {
  79. const mkvparser::Track *const track = tracks->GetTrackByIndex(i);
  80. if (track->GetType() == mkvparser::Track::kVideo) {
  81. video_track = static_cast<const mkvparser::VideoTrack *>(track);
  82. webm_ctx->video_track_index = static_cast<int>(track->GetNumber());
  83. break;
  84. }
  85. }
  86. if (video_track == NULL || video_track->GetCodecId() == NULL) {
  87. rewind_and_reset(webm_ctx, aom_ctx);
  88. return 0;
  89. }
  90. if (!strncmp(video_track->GetCodecId(), "V_AV1", 5)) {
  91. aom_ctx->fourcc = AV1_FOURCC;
  92. } else {
  93. rewind_and_reset(webm_ctx, aom_ctx);
  94. return 0;
  95. }
  96. aom_ctx->framerate.denominator = 0;
  97. aom_ctx->framerate.numerator = 0;
  98. aom_ctx->width = static_cast<uint32_t>(video_track->GetWidth());
  99. aom_ctx->height = static_cast<uint32_t>(video_track->GetHeight());
  100. get_first_cluster(webm_ctx);
  101. return 1;
  102. }
  103. int webm_read_frame(struct WebmInputContext *webm_ctx, uint8_t **buffer,
  104. size_t *bytes_read, size_t *buffer_size) {
  105. assert(webm_ctx->buffer == *buffer);
  106. // This check is needed for frame parallel decoding, in which case this
  107. // function could be called even after it has reached end of input stream.
  108. if (webm_ctx->reached_eos) {
  109. return 1;
  110. }
  111. mkvparser::Segment *const segment =
  112. reinterpret_cast<mkvparser::Segment *>(webm_ctx->segment);
  113. const mkvparser::Cluster *cluster =
  114. reinterpret_cast<const mkvparser::Cluster *>(webm_ctx->cluster);
  115. const mkvparser::Block *block =
  116. reinterpret_cast<const mkvparser::Block *>(webm_ctx->block);
  117. const mkvparser::BlockEntry *block_entry =
  118. reinterpret_cast<const mkvparser::BlockEntry *>(webm_ctx->block_entry);
  119. bool block_entry_eos = false;
  120. do {
  121. long status = 0;
  122. bool get_new_block = false;
  123. if (block_entry == NULL && !block_entry_eos) {
  124. status = cluster->GetFirst(block_entry);
  125. get_new_block = true;
  126. } else if (block_entry_eos || block_entry->EOS()) {
  127. cluster = segment->GetNext(cluster);
  128. if (cluster == NULL || cluster->EOS()) {
  129. *bytes_read = 0;
  130. webm_ctx->reached_eos = 1;
  131. return 1;
  132. }
  133. status = cluster->GetFirst(block_entry);
  134. block_entry_eos = false;
  135. get_new_block = true;
  136. } else if (block == NULL ||
  137. webm_ctx->block_frame_index == block->GetFrameCount() ||
  138. block->GetTrackNumber() != webm_ctx->video_track_index) {
  139. status = cluster->GetNext(block_entry, block_entry);
  140. if (block_entry == NULL || block_entry->EOS()) {
  141. block_entry_eos = true;
  142. continue;
  143. }
  144. get_new_block = true;
  145. }
  146. if (status || block_entry == NULL) {
  147. return -1;
  148. }
  149. if (get_new_block) {
  150. block = block_entry->GetBlock();
  151. if (block == NULL) return -1;
  152. webm_ctx->block_frame_index = 0;
  153. }
  154. } while (block_entry_eos ||
  155. block->GetTrackNumber() != webm_ctx->video_track_index);
  156. webm_ctx->cluster = cluster;
  157. webm_ctx->block_entry = block_entry;
  158. webm_ctx->block = block;
  159. const mkvparser::Block::Frame &frame =
  160. block->GetFrame(webm_ctx->block_frame_index);
  161. ++webm_ctx->block_frame_index;
  162. if (frame.len > static_cast<long>(*buffer_size)) {
  163. delete[] * buffer;
  164. *buffer = new uint8_t[frame.len];
  165. webm_ctx->buffer = *buffer;
  166. if (*buffer == NULL) {
  167. return -1;
  168. }
  169. *buffer_size = frame.len;
  170. }
  171. *bytes_read = frame.len;
  172. webm_ctx->timestamp_ns = block->GetTime(cluster);
  173. webm_ctx->is_key_frame = block->IsKey();
  174. mkvparser::MkvReader *const reader =
  175. reinterpret_cast<mkvparser::MkvReader *>(webm_ctx->reader);
  176. return frame.Read(reader, *buffer) ? -1 : 0;
  177. }
  178. // Calculate the greatest common divisor between two numbers.
  179. static int gcd(int a, int b) {
  180. int remainder;
  181. while (b > 0) {
  182. remainder = a % b;
  183. a = b;
  184. b = remainder;
  185. }
  186. return a;
  187. }
  188. int webm_guess_framerate(struct WebmInputContext *webm_ctx,
  189. struct AvxInputContext *aom_ctx) {
  190. uint32_t i = 0;
  191. uint8_t *buffer = NULL;
  192. size_t buffer_size = 0;
  193. size_t bytes_read = 0;
  194. assert(webm_ctx->buffer == NULL);
  195. while (webm_ctx->timestamp_ns < 1000000000 && i < 50) {
  196. if (webm_read_frame(webm_ctx, &buffer, &bytes_read, &buffer_size)) {
  197. break;
  198. }
  199. ++i;
  200. }
  201. aom_ctx->framerate.numerator = (i - 1) * 1000000;
  202. aom_ctx->framerate.denominator =
  203. static_cast<int>(webm_ctx->timestamp_ns / 1000);
  204. // Fraction might be represented in large numbers, like 49000000/980000
  205. // for 50fps. Simplify as much as possible.
  206. int g = gcd(aom_ctx->framerate.numerator, aom_ctx->framerate.denominator);
  207. if (g != 0) {
  208. aom_ctx->framerate.numerator /= g;
  209. aom_ctx->framerate.denominator /= g;
  210. }
  211. delete[] buffer;
  212. webm_ctx->buffer = NULL;
  213. get_first_cluster(webm_ctx);
  214. webm_ctx->block = NULL;
  215. webm_ctx->block_entry = NULL;
  216. webm_ctx->block_frame_index = 0;
  217. webm_ctx->timestamp_ns = 0;
  218. webm_ctx->reached_eos = 0;
  219. return 0;
  220. }
  221. void webm_free(struct WebmInputContext *webm_ctx) { reset(webm_ctx); }