Skip to content

Commit

Permalink
Audio: Add AC3/EAC3 support in EME on Windows platform (#4744)
Browse files Browse the repository at this point in the history
For AC3/EAC3 stream protected under DRM, we need to parse dac3 and dec3
box infomation in encryption box.

And if CDM support AC3/EAC3 codec, we also need to convert AC3/EAC3
AudioCodec to EME_CODEC.

This change is backported from m120+.

(cherry picked from commit 866e79517d2d4fb1aeccc7162c6c90833ed96bb2)

Bug: 388666932
Reviewed-on:
https://chromium-review.googlesource.com/c/chromium/src/+/4489383
  • Loading branch information
borongc authored Jan 23, 2025
2 parents c6cc9f2 + ac9671a commit b41df5f
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 16 deletions.
8 changes: 8 additions & 0 deletions components/cdm/renderer/key_system_support_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ SupportedCodecs GetSupportedCodecs(const media::CdmCapability& capability,
supported_codecs |= media::EME_CODEC_DTSXP2;
break;
#endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
case media::AudioCodec::kAC3:
supported_codecs |= media::EME_CODEC_AC3;
break;
case media::AudioCodec::kEAC3:
supported_codecs |= media::EME_CODEC_EAC3;
break;
#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
default:
DVLOG(1) << "Unexpected supported codec: " << GetCodecName(codec);
Expand Down
7 changes: 7 additions & 0 deletions media/formats/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,13 @@ source_set("unit_tests") {
]
}

if (enable_platform_ac3_eac3_audio) {
sources += [
"mp4/ac3_unittest.cc",
"mp4/eac3_unittest.cc",
]
}

if (enable_mse_mpeg2ts_stream_parser) {
sources += [
"mp2t/es_adapter_video_unittest.cc",
Expand Down
29 changes: 23 additions & 6 deletions media/formats/mp4/ac3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,41 @@ bool AC3::Parse(const std::vector<uint8_t>& data, MediaLog* media_log) {
return false;
}

// For AC3SpecificBox, Please refer to ETSI TS 102 366 V1.4.1
// https://www.etsi.org/deliver/etsi_ts/102300_102399/102366/01.03.01_60/ts_102366v010301p.pdf
// F.4 AC3SpecificBox
// fscod 2 bits
// bsid 5 bits
// bsmod 3 bits
// acmod 3 bits
// lfeon 1 bits
// bit_rate_code 5 bits
// reserved 5 bits

if (data.size() * 8 < (2 + 5 + 3 + 3 + 1 + 5 + 5)) {
return false;
}

// Parse dac3 box using reader.
BitReader reader(&data[0], data.size());

// Please refer to ETSI TS 102 366 V1.4.1
// https://www.etsi.org/deliver/etsi_ts/102300_102399/102366/01.03.01_60/ts_102366v010301p.pdf
// F.4 AC3SpecificBox
// fscod 2 bits
// bsid 5 bits
// bsmod 3 bits
// skip fscod, bsid, bsmod
RCHECK(reader.SkipBits(2 + 5 + 3));

int acmod;
RCHECK(reader.ReadBits(3, &acmod));
if (acmod >= static_cast<int>(sizeof(kGlobalChannelArray))) {
return false;
}

int lfeon;
RCHECK(reader.ReadBits(1, &lfeon));

channel_count_ = kGlobalChannelArray[acmod] + lfeon;
RCHECK(channel_count_ >= 1 && channel_count_ <= limits::kMaxChannels);

// skip bit_rate_code, reserved
RCHECK(reader.SkipBits(5 + 5));
return true;
}

Expand Down
53 changes: 53 additions & 0 deletions media/formats/mp4/ac3_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdint.h>

#include "media/base/mock_media_log.h"
#include "media/formats/mp4/ac3.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::AllOf;
using ::testing::HasSubstr;
using ::testing::InSequence;
using ::testing::StrictMock;

namespace media {

namespace mp4 {

class AC3Test : public testing::Test {
public:
AC3Test() = default;

bool Parse(const std::vector<uint8_t>& data) {
return ac3_.Parse(data, &media_log_);
}

StrictMock<MockMediaLog> media_log_;
AC3 ac3_;
};

TEST_F(AC3Test, NoInputTest) {
std::vector<uint8_t> data;
EXPECT_FALSE(Parse(data));
}

TEST_F(AC3Test, ShortInvalidInputTest) {
std::vector<uint8_t> data({0x50, 0x11});

EXPECT_FALSE(Parse(data));
}

TEST_F(AC3Test, NormalInputTest) {
std::vector<uint8_t> data({0x50, 0x11, 0x40});

EXPECT_TRUE(Parse(data));
EXPECT_EQ(ac3_.GetChannelCount(), 2u);
}

} // namespace mp4

} // namespace media
6 changes: 4 additions & 2 deletions media/formats/mp4/box_definitions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1624,11 +1624,13 @@ bool AudioSampleEntry::Parse(BoxReader* reader) {
#endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)

#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
if (format == FOURCC_AC3) {
if (format == FOURCC_AC3 ||
(format == FOURCC_ENCA && sinf.format.format == FOURCC_AC3)) {
RCHECK_MEDIA_LOGGED(reader->ReadChild(&ac3), reader->media_log(),
"Failure parsing AC3SpecificBox (dac3)");
}
if (format == FOURCC_EAC3) {
if (format == FOURCC_EAC3 ||
(format == FOURCC_ENCA && sinf.format.format == FOURCC_EAC3)) {
RCHECK_MEDIA_LOGGED(reader->ReadChild(&eac3), reader->media_log(),
"Failure parsing EC3SpecificBox (dec3)");
}
Expand Down
38 changes: 30 additions & 8 deletions media/formats/mp4/eac3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ bool EAC3::Parse(const std::vector<uint8_t>& data, MediaLog* media_log) {
return false;
}

// For EC3SpecificBox, please refer to ETSI TS 102 366 V1.4.1
// https://www.etsi.org/deliver/etsi_ts/102300_102399/102366/01.03.01_60/ts_102366v010301p.pdf
// F.6 EC3SpecificBox
// data_rate 13 bits
// num_ind_sub 3 bits
// {
// fscod 2 bits
// bsid 5 bits
// reserved 1 bits
// asvc 1 bits
// bsmod 3 bits
// acmod 3 bits
// lfeon 1 bits
// reserved 3 bits
// num_dep_sub 4 bits
// if num_dep_sub > 0 chan_loc 9 bits
// else reserved 1 bits
// }
// reserved variable bits

// At least one independent substreams exist without ndependent substream
if (data.size() * 8 < (13 + 3 + (2 + 5 + 1 + 1 + 3 + 3 + 1 + 3 + 4 + 1))) {
return false;
}

// Parse dec3 box using reader.
BitReader reader(&data[0], data.size());

Expand All @@ -41,18 +66,15 @@ bool EAC3::Parse(const std::vector<uint8_t>& data, MediaLog* media_log) {

int max_channel_count = 0;
for (int i = 0; i < num_ind_sub + 1; i++) {
// Please refer to ETSI TS 102 366 V1.4.1
// https://www.etsi.org/deliver/etsi_ts/102300_102399/102366/01.03.01_60/ts_102366v010301p.pdf
// F.4 AC3SpecificBox
// fscod 2 bits
// bsid 5 bits
// reserved 1 bits
// asvc 1 bits
// bsmod 3 bits
// skip fscod, bsid, reserved, asvc, bsmod
RCHECK(reader.SkipBits(2 + 5 + 1 + 1 + 3));

int acmod;
RCHECK(reader.ReadBits(3, &acmod));
if (acmod >= static_cast<int>(sizeof(kGlobalChannelArray))) {
return false;
}

int lfeon;
RCHECK(reader.ReadBits(1, &lfeon));

Expand Down
53 changes: 53 additions & 0 deletions media/formats/mp4/eac3_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdint.h>

#include "media/base/mock_media_log.h"
#include "media/formats/mp4/eac3.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::AllOf;
using ::testing::HasSubstr;
using ::testing::InSequence;
using ::testing::StrictMock;

namespace media {

namespace mp4 {

class EAC3Test : public testing::Test {
public:
EAC3Test() = default;

bool Parse(const std::vector<uint8_t>& data) {
return eac3_.Parse(data, &media_log_);
}

StrictMock<MockMediaLog> media_log_;
EAC3 eac3_;
};

TEST_F(EAC3Test, NoInputTest) {
std::vector<uint8_t> data;
EXPECT_FALSE(Parse(data));
}

TEST_F(EAC3Test, ShortInvalidInputTest) {
std::vector<uint8_t> data({0x06, 0xC8});

EXPECT_FALSE(Parse(data));
}

TEST_F(EAC3Test, NormalInputTest) {
std::vector<uint8_t> data({0x06, 0xC8, 0x60, 0x04, 0x00});

EXPECT_TRUE(Parse(data));
EXPECT_EQ(eac3_.GetChannelCount(), 2u);
}

} // namespace mp4

} // namespace media

0 comments on commit b41df5f

Please sign in to comment.