Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Unified Diff: media/base/ac3_util.cc

Issue 2572573007: Use passthrough decoder for (E)AC3 formats (Closed)
Patch Set: Fix AudioBuffer Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/ac3_util.cc
diff --git a/media/base/ac3_util.cc b/media/base/ac3_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..849e2b94a6a8eae6800c6b39323bd846e32c9258
--- /dev/null
+++ b/media/base/ac3_util.cc
@@ -0,0 +1,169 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
DaleCurtis 2016/12/14 20:00:03 Probably want to use a BitReader here instead. Syn
AndyWu 2016/12/15 22:20:02 Done, thanks. I still keep the weird abbreviations
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/ac3_util.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace media {
+
+namespace {
+
+// The size in byte of a (E-)AC3 syncframe header.
+const int kHeaderSizeInByte = 8;
+// The number of new samples per (E-)AC3 audio block.
+const int kAudioSamplesPerAudioBlock = 256;
+// Each syncframe has 6 blocks that provide 256 new audio samples. See ETSI TS
+// 102 366 4.1.
+const int kAc3SyncframeAudioSampleCount = 6 * kAudioSamplesPerAudioBlock;
+// Number of audio blocks per E-AC3 syncframe, indexed by numblkscod.
+const int kBlocksPerSyncframeByNumblkscod[] = {1, 2, 3, 6};
+// Sample rates, indexed by fscod.
+const int kSampleRateByFscod[] = {48000, 44100, 32000};
+// Nominal bitrates in kbps, indexed by frmsizecod / 2. (See ETSI TS 102 366
+// table 4.13.)
+const int kBitrateByHalfFrmsizecod[] = {32, 40, 48, 56, 64, 80, 96,
+ 112, 128, 160, 192, 224, 256, 320,
+ 384, 448, 512, 576, 640};
+// 16-bit words per syncframe, indexed by frmsizecod / 2. (See ETSI TS 102 366
+// table 4.13.)
+const int kSyncframeSizeWordsByHalfFrmsizecod441[] = {
+ 69, 87, 104, 121, 139, 174, 208, 243, 278, 348,
+ 417, 487, 557, 696, 835, 975, 1114, 1253, 1393};
+
+// Search for next syncword, wihch is 0x0B-0x77.
+const uint8_t* FindNextSync(const uint8_t* const begin,
+ const uint8_t* const end) {
+ DCHECK(begin);
+ DCHECK(end);
+ DCHECK_LE(begin, end);
+
+ const uint8_t* current = begin;
+
+ while (current < end - 1) {
DaleCurtis 2016/12/14 20:00:03 You can scan two bytes at a time by check current[
AndyWu 2016/12/15 22:20:02 Done.
+ if (current[0] == 0x0B && current[1] == 0x77) {
+ if (current != begin)
+ DVLOG(2) << __FUNCTION__ << " skip " << current - begin << " bytes.";
+
+ return current;
+ }
+ ++current;
+ }
+
+ return nullptr;
+}
+
+// Returns the number of audio samples represented by the given E-AC3 syncframe.
+int ParseEac3SyncframeSampleCount(const uint8_t* const data,
+ const uint8_t* const end) {
+ DCHECK(data);
+ DCHECK(end);
+ DCHECK_GE(end - data, kHeaderSizeInByte);
+
+ return kAudioSamplesPerAudioBlock *
+ (((data[4] & 0xC0) >> 6) == 0x03
+ ? 6
+ : kBlocksPerSyncframeByNumblkscod[(data[4] & 0x30) >> 4]);
+}
+
+// Returns the size in bytes of the given E-AC3 syncframe.
+int ParseEac3SyncframeSize(const uint8_t* const data,
+ const uint8_t* const end) {
+ DCHECK(data);
+ DCHECK(end);
+ DCHECK_GE(end - data, kHeaderSizeInByte);
+
+ return 2 * (((data[2] & 0x07) << 8) + (data[3] & 0xFF) + 1);
+}
+
+// Returns the number of audio samples in an AC3 syncframe.
+int GetAc3SyncframeSampleCount() {
+ return kAc3SyncframeAudioSampleCount;
+}
+
+// Returns the size in bytes of the given AC3 syncframe.
+int ParseAc3SyncframeSize(const uint8_t* const data, const uint8_t* const end) {
+ DCHECK(data);
+ DCHECK(end);
+ DCHECK_GE(end - data, kHeaderSizeInByte);
+
+ unsigned fscod = (data[4] & 0xC0) >> 6;
+ unsigned frmsizecod = data[4] & 0x3F;
+ unsigned half_frmsizecod = frmsizecod / 2;
+
+ if (fscod >= arraysize(kSampleRateByFscod) ||
+ half_frmsizecod >= arraysize(kSyncframeSizeWordsByHalfFrmsizecod441)) {
+ DVLOG(2) << __FUNCTION__ << " Invalid frame header."
+ << " fscod:" << fscod << " half_frmsizecod:" << half_frmsizecod;
+ return -1;
+ }
+
+ int sample_rate = kSampleRateByFscod[fscod];
+ if (sample_rate == 44100) {
+ return 2 * (kSyncframeSizeWordsByHalfFrmsizecod441[half_frmsizecod] +
+ (frmsizecod % 2));
+ }
+
+ int bitrate = kBitrateByHalfFrmsizecod[half_frmsizecod];
DaleCurtis 2016/12/14 20:00:03 Don't use else blocks with return.
AndyWu 2016/12/15 22:20:03 Done.
+ if (sample_rate == 32000) {
+ return 6 * bitrate;
+ } else { // sample_rate == 48000
+ return 4 * bitrate;
+ }
+}
+
+// Returns the total number of audio samples in the given buffer, which contains
+// several complete (E-)AC3 syncframes.
+int ParseTotalSampleCount(const uint8_t* data, size_t size, bool is_eac3) {
+ DCHECK(data);
+
+ if (size < kHeaderSizeInByte) {
+ return 0;
+ }
+
+ const uint8_t* const end = data + size;
+ const uint8_t* current = FindNextSync(data, end);
+ int total_sample_count = 0;
+
+ while (current && end - current > kHeaderSizeInByte) {
+ int frame_size = is_eac3 ? ParseEac3SyncframeSize(current, end)
+ : ParseAc3SyncframeSize(current, end);
+ int sample_count = is_eac3 ? ParseEac3SyncframeSampleCount(current, end)
+ : GetAc3SyncframeSampleCount();
+
+ if (frame_size > 0 && sample_count > 0) {
+ current += frame_size;
+ if (current > end) {
+ DVLOG(2) << __FUNCTION__ << " Incomplete frame, missing "
+ << current - end << " bytes.";
+ break;
+ }
+
+ total_sample_count += sample_count;
+ } else {
+ DVLOG(2) << __FUNCTION__
+ << " Invalid frame, skip 2 bytes to find next syncword.";
+ current += 2;
+ }
+
+ current = FindNextSync(current, end);
+ }
+
+ return total_sample_count;
+}
+
+} // namespace anonymous
+
+// static
+int Ac3Util::ParseTotalAc3SampleCount(const uint8_t* data, size_t size) {
+ return ParseTotalSampleCount(data, size, false);
+}
+
+// static
+int Ac3Util::ParseTotalEac3SampleCount(const uint8_t* data, size_t size) {
+ return ParseTotalSampleCount(data, size, true);
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698