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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // 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
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/base/ac3_util.h"
6
7 #include "base/logging.h"
8 #include "base/macros.h"
9
10 namespace media {
11
12 namespace {
13
14 // The size in byte of a (E-)AC3 syncframe header.
15 const int kHeaderSizeInByte = 8;
16 // The number of new samples per (E-)AC3 audio block.
17 const int kAudioSamplesPerAudioBlock = 256;
18 // Each syncframe has 6 blocks that provide 256 new audio samples. See ETSI TS
19 // 102 366 4.1.
20 const int kAc3SyncframeAudioSampleCount = 6 * kAudioSamplesPerAudioBlock;
21 // Number of audio blocks per E-AC3 syncframe, indexed by numblkscod.
22 const int kBlocksPerSyncframeByNumblkscod[] = {1, 2, 3, 6};
23 // Sample rates, indexed by fscod.
24 const int kSampleRateByFscod[] = {48000, 44100, 32000};
25 // Nominal bitrates in kbps, indexed by frmsizecod / 2. (See ETSI TS 102 366
26 // table 4.13.)
27 const int kBitrateByHalfFrmsizecod[] = {32, 40, 48, 56, 64, 80, 96,
28 112, 128, 160, 192, 224, 256, 320,
29 384, 448, 512, 576, 640};
30 // 16-bit words per syncframe, indexed by frmsizecod / 2. (See ETSI TS 102 366
31 // table 4.13.)
32 const int kSyncframeSizeWordsByHalfFrmsizecod441[] = {
33 69, 87, 104, 121, 139, 174, 208, 243, 278, 348,
34 417, 487, 557, 696, 835, 975, 1114, 1253, 1393};
35
36 // Search for next syncword, wihch is 0x0B-0x77.
37 const uint8_t* FindNextSync(const uint8_t* const begin,
38 const uint8_t* const end) {
39 DCHECK(begin);
40 DCHECK(end);
41 DCHECK_LE(begin, end);
42
43 const uint8_t* current = begin;
44
45 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.
46 if (current[0] == 0x0B && current[1] == 0x77) {
47 if (current != begin)
48 DVLOG(2) << __FUNCTION__ << " skip " << current - begin << " bytes.";
49
50 return current;
51 }
52 ++current;
53 }
54
55 return nullptr;
56 }
57
58 // Returns the number of audio samples represented by the given E-AC3 syncframe.
59 int ParseEac3SyncframeSampleCount(const uint8_t* const data,
60 const uint8_t* const end) {
61 DCHECK(data);
62 DCHECK(end);
63 DCHECK_GE(end - data, kHeaderSizeInByte);
64
65 return kAudioSamplesPerAudioBlock *
66 (((data[4] & 0xC0) >> 6) == 0x03
67 ? 6
68 : kBlocksPerSyncframeByNumblkscod[(data[4] & 0x30) >> 4]);
69 }
70
71 // Returns the size in bytes of the given E-AC3 syncframe.
72 int ParseEac3SyncframeSize(const uint8_t* const data,
73 const uint8_t* const end) {
74 DCHECK(data);
75 DCHECK(end);
76 DCHECK_GE(end - data, kHeaderSizeInByte);
77
78 return 2 * (((data[2] & 0x07) << 8) + (data[3] & 0xFF) + 1);
79 }
80
81 // Returns the number of audio samples in an AC3 syncframe.
82 int GetAc3SyncframeSampleCount() {
83 return kAc3SyncframeAudioSampleCount;
84 }
85
86 // Returns the size in bytes of the given AC3 syncframe.
87 int ParseAc3SyncframeSize(const uint8_t* const data, const uint8_t* const end) {
88 DCHECK(data);
89 DCHECK(end);
90 DCHECK_GE(end - data, kHeaderSizeInByte);
91
92 unsigned fscod = (data[4] & 0xC0) >> 6;
93 unsigned frmsizecod = data[4] & 0x3F;
94 unsigned half_frmsizecod = frmsizecod / 2;
95
96 if (fscod >= arraysize(kSampleRateByFscod) ||
97 half_frmsizecod >= arraysize(kSyncframeSizeWordsByHalfFrmsizecod441)) {
98 DVLOG(2) << __FUNCTION__ << " Invalid frame header."
99 << " fscod:" << fscod << " half_frmsizecod:" << half_frmsizecod;
100 return -1;
101 }
102
103 int sample_rate = kSampleRateByFscod[fscod];
104 if (sample_rate == 44100) {
105 return 2 * (kSyncframeSizeWordsByHalfFrmsizecod441[half_frmsizecod] +
106 (frmsizecod % 2));
107 }
108
109 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.
110 if (sample_rate == 32000) {
111 return 6 * bitrate;
112 } else { // sample_rate == 48000
113 return 4 * bitrate;
114 }
115 }
116
117 // Returns the total number of audio samples in the given buffer, which contains
118 // several complete (E-)AC3 syncframes.
119 int ParseTotalSampleCount(const uint8_t* data, size_t size, bool is_eac3) {
120 DCHECK(data);
121
122 if (size < kHeaderSizeInByte) {
123 return 0;
124 }
125
126 const uint8_t* const end = data + size;
127 const uint8_t* current = FindNextSync(data, end);
128 int total_sample_count = 0;
129
130 while (current && end - current > kHeaderSizeInByte) {
131 int frame_size = is_eac3 ? ParseEac3SyncframeSize(current, end)
132 : ParseAc3SyncframeSize(current, end);
133 int sample_count = is_eac3 ? ParseEac3SyncframeSampleCount(current, end)
134 : GetAc3SyncframeSampleCount();
135
136 if (frame_size > 0 && sample_count > 0) {
137 current += frame_size;
138 if (current > end) {
139 DVLOG(2) << __FUNCTION__ << " Incomplete frame, missing "
140 << current - end << " bytes.";
141 break;
142 }
143
144 total_sample_count += sample_count;
145 } else {
146 DVLOG(2) << __FUNCTION__
147 << " Invalid frame, skip 2 bytes to find next syncword.";
148 current += 2;
149 }
150
151 current = FindNextSync(current, end);
152 }
153
154 return total_sample_count;
155 }
156
157 } // namespace anonymous
158
159 // static
160 int Ac3Util::ParseTotalAc3SampleCount(const uint8_t* data, size_t size) {
161 return ParseTotalSampleCount(data, size, false);
162 }
163
164 // static
165 int Ac3Util::ParseTotalEac3SampleCount(const uint8_t* data, size_t size) {
166 return ParseTotalSampleCount(data, size, true);
167 }
168
169 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698