7 #include "packager/media/codecs/ec3_audio_util.h" 9 #include "packager/base/macros.h" 10 #include "packager/base/strings/string_number_conversions.h" 11 #include "packager/media/base/bit_reader.h" 12 #include "packager/media/base/rcheck.h" 37 enum kEC3AudioChannelMap {
41 kLeftSurround = 0x1000,
42 kRightSurround = 0x800,
45 kCenterSurround = 0x100,
46 kTopCenterSurround = 0x80,
50 kCenterVerticalHeight = 0x8,
57 const size_t kChannelCountArray[] = {
58 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1,
60 static_assert(arraysize(kChannelCountArray) == 16u,
61 "Channel count array should have 16 entries.");
66 const uint16_t kEC3AudioCodingModeMap[] = {
70 kLeft | kCenter | kRight,
71 kLeft | kRight | kLeftSurround | kRightSurround,
72 kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
73 kLeft | kRight | kLeftSurround | kRightSurround,
74 kLeft | kCenter | kRight | kLeftSurround | kRightSurround,
78 uint8_t ReverseBits8(uint8_t n) {
79 n = ((n >> 1) & 0x55) | ((n & 0x55) << 1);
80 n = ((n >> 2) & 0x33) | ((n & 0x33) << 2);
81 return ((n >> 4) & 0x0f) | ((n & 0x0f) << 4);
84 bool ExtractEc3Data(
const std::vector<uint8_t>& ec3_data,
85 uint8_t* audio_coding_mode,
87 uint16_t* dependent_substreams_layout) {
88 BitReader bit_reader(ec3_data.data(), ec3_data.size());
90 uint8_t number_independent_substreams;
91 RCHECK(bit_reader.SkipBits(13) &&
92 bit_reader.ReadBits(3, &number_independent_substreams));
95 ++number_independent_substreams;
113 RCHECK(bit_reader.SkipBits(12));
114 RCHECK(bit_reader.ReadBits(3, audio_coding_mode));
115 RCHECK(bit_reader.ReadBits(1, lfe_channel_on));
117 uint8_t number_dependent_substreams = 0;
118 RCHECK(bit_reader.SkipBits(3));
119 RCHECK(bit_reader.ReadBits(4, &number_dependent_substreams));
121 *dependent_substreams_layout = 0;
122 if (number_dependent_substreams > 0) {
123 RCHECK(bit_reader.ReadBits(9, dependent_substreams_layout));
131 bool CalculateEC3ChannelMap(
const std::vector<uint8_t>& ec3_data,
132 uint32_t* channel_map) {
133 uint8_t audio_coding_mode;
135 uint16_t dependent_substreams_layout;
136 if (!ExtractEc3Data(ec3_data, &audio_coding_mode, &lfe_channel_on,
137 &dependent_substreams_layout)) {
138 LOG(WARNING) <<
"Seeing invalid EC3 data: " 139 << base::HexEncode(ec3_data.data(), ec3_data.size());
156 const uint8_t reversed_dependent_substreams_layout =
157 ReverseBits8(dependent_substreams_layout & 0xFF);
159 *channel_map = kEC3AudioCodingModeMap[audio_coding_mode] |
160 (reversed_dependent_substreams_layout << 3);
161 if (dependent_substreams_layout & 0x100)
162 *channel_map |= kLFE2;
164 *channel_map |= kLFEScreen;
168 size_t GetEc3NumChannels(
const std::vector<uint8_t>& ec3_data) {
169 uint32_t channel_map;
170 if (!CalculateEC3ChannelMap(ec3_data, &channel_map))
173 size_t num_channels = 0;
175 for (
size_t channel_count : kChannelCountArray) {
176 if (channel_map & bit)
177 num_channels += channel_count;
All the methods that are virtual are virtual for mocking.