Fix avc3 codec string problem

- Added wvm decryption and demuxing test
- Added avc3 test (not strip parameter set nal units)

Change-Id: I28ff4d7f9ef539eafe45cfadfc0912cd11c72b05
This commit is contained in:
Kongqun Yang 2017-03-23 11:36:47 -07:00 committed by KongQun Yang
parent 59f393779c
commit 4a47268f3d
18 changed files with 139 additions and 30 deletions

View File

@ -354,6 +354,34 @@ class PackagerAppTest(unittest.TestCase):
self._VerifyDecryption(self.output[0], 'bear-320x240-opus-golden.mp4')
self._VerifyDecryption(self.output[1], 'bear-320x240-vp9-golden.mp4')
def testPackageWvmInput(self):
self.packager.Package(
self._GetStreams(
['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']),
self._GetFlags(
decryption=True, encryption_key='9248d245390e0a49d483ba9b43fc69c3'))
# Output timescale is 90000.
self._DiffGold(self.output[0], 'bear-320x180-v-wvm-golden.mp4')
self._DiffGold(self.output[1], 'bear-320x180-a-wvm-golden.mp4')
self._DiffGold(self.output[2], 'bear-640x360-v-wvm-golden.mp4')
self._DiffGold(self.output[3], 'bear-640x360-a-wvm-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-wvm-golden.mpd')
def testPackageWvmInputWithoutStrippingParameterSetNalus(self):
self.packager.Package(
self._GetStreams(
['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']),
self._GetFlags(
strip_parameter_set_nalus=False,
decryption=True,
encryption_key='9248d245390e0a49d483ba9b43fc69c3'))
# Output timescale is 90000.
self._DiffGold(self.output[0], 'bear-320x180-avc3-wvm-golden.mp4')
self._DiffGold(self.output[1], 'bear-320x180-a-wvm-golden.mp4')
self._DiffGold(self.output[2], 'bear-640x360-avc3-wvm-golden.mp4')
self._DiffGold(self.output[3], 'bear-640x360-a-wvm-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-avc3-wvm-golden.mpd')
def testPackageWithEncryptionAndRandomIv(self):
self.packager.Package(
self._GetStreams(['audio', 'video']),
@ -582,6 +610,7 @@ class PackagerAppTest(unittest.TestCase):
return 'mp4'
def _GetFlags(self,
strip_parameter_set_nalus=True,
encryption=False,
protection_scheme=None,
vp9_subsample_encryption=True,
@ -598,6 +627,10 @@ class PackagerAppTest(unittest.TestCase):
generate_static_mpd=False,
use_fake_clock=True):
flags = []
if not strip_parameter_set_nalus:
flags += ['--strip_parameter_set_nalus=false']
if widevine_encryption:
widevine_server_url = ('https://license.uat.widevine.com/cenc'
'/getcontentkey/widevine_test')
@ -624,7 +657,7 @@ class PackagerAppTest(unittest.TestCase):
if decryption:
flags += ['--enable_fixed_key_decryption',
'--key_id=31323334353637383930313233343536',
'--key=32333435363738393021323334353637']
'--key=' + encryption_key]
if key_rotation:
flags.append('--crypto_period_duration=1')

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.73607S">
<Period id="0">
<AdaptationSet id="0" contentType="video" maxWidth="640" maxHeight="360" frameRate="90000/3003" subsegmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="354240" codecs="avc3.64000d" mimeType="video/mp4" sar="1:1" width="320" height="180">
<BaseURL>output_0.mp4</BaseURL>
<SegmentBase indexRange="818-885" timescale="90000">
<Initialization range="0-817"/>
</SegmentBase>
</Representation>
<Representation id="2" bandwidth="888442" codecs="avc3.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>output_2.mp4</BaseURL>
<SegmentBase indexRange="819-886" timescale="90000">
<Initialization range="0-818"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
<Representation id="1" bandwidth="132362" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>output_1.mp4</BaseURL>
<SegmentBase indexRange="757-824" timescale="90000">
<Initialization range="0-756"/>
</SegmentBase>
</Representation>
<Representation id="3" bandwidth="136806" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>output_3.mp4</BaseURL>
<SegmentBase indexRange="757-824" timescale="90000">
<Initialization range="0-756"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.73607S">
<Period id="0">
<AdaptationSet id="0" contentType="video" maxWidth="640" maxHeight="360" frameRate="90000/3003" subsegmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="353919" codecs="avc1.64000d" mimeType="video/mp4" sar="1:1" width="320" height="180">
<BaseURL>output_0.mp4</BaseURL>
<SegmentBase indexRange="822-889" timescale="90000">
<Initialization range="0-821"/>
</SegmentBase>
</Representation>
<Representation id="2" bandwidth="888108" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>output_2.mp4</BaseURL>
<SegmentBase indexRange="823-890" timescale="90000">
<Initialization range="0-822"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
<Representation id="1" bandwidth="132362" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>output_1.mp4</BaseURL>
<SegmentBase indexRange="757-824" timescale="90000">
<Initialization range="0-756"/>
</SegmentBase>
</Representation>
<Representation id="3" bandwidth="136806" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>output_3.mp4</BaseURL>
<SegmentBase indexRange="757-824" timescale="90000">
<Initialization range="0-756"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>

View File

@ -88,18 +88,21 @@ bool AVCDecoderConfigurationRecord::ParseInternal() {
return true;
}
std::string AVCDecoderConfigurationRecord::GetCodecString() const {
return GetCodecString(profile_indication_, profile_compatibility_,
avc_level_);
std::string AVCDecoderConfigurationRecord::GetCodecString(
FourCC codec_fourcc) const {
return GetCodecString(codec_fourcc, profile_indication_,
profile_compatibility_, avc_level_);
}
std::string AVCDecoderConfigurationRecord::GetCodecString(
FourCC codec_fourcc,
uint8_t profile_indication,
uint8_t profile_compatibility,
uint8_t avc_level) {
const uint8_t bytes[] = {profile_indication, profile_compatibility,
avc_level};
return "avc1." + base::ToLowerASCII(base::HexEncode(bytes, arraysize(bytes)));
return FourCCToString(codec_fourcc) + "." +
base::ToLowerASCII(base::HexEncode(bytes, arraysize(bytes)));
}
} // namespace media

View File

@ -12,6 +12,7 @@
#include <vector>
#include "packager/base/macros.h"
#include "packager/media/base/fourccs.h"
#include "packager/media/codecs/decoder_configuration_record.h"
namespace shaka {
@ -24,7 +25,7 @@ class AVCDecoderConfigurationRecord : public DecoderConfigurationRecord {
~AVCDecoderConfigurationRecord() override;
/// @return The codec string.
std::string GetCodecString() const;
std::string GetCodecString(FourCC codec_fourcc) const;
uint8_t version() const { return version_; }
uint8_t profile_indication() const { return profile_indication_; }
@ -37,7 +38,8 @@ class AVCDecoderConfigurationRecord : public DecoderConfigurationRecord {
/// Static version of GetCodecString.
/// @return The codec string.
static std::string GetCodecString(uint8_t profile_indication,
static std::string GetCodecString(FourCC codec_fourcc,
uint8_t profile_indication,
uint8_t profile_compatibility,
uint8_t avc_level);

View File

@ -32,7 +32,8 @@ TEST(AVCDecoderConfigurationRecordTest, Success) {
EXPECT_EQ(8u, avc_config.pixel_width());
EXPECT_EQ(9u, avc_config.pixel_height());
EXPECT_EQ("avc1.64001e", avc_config.GetCodecString());
EXPECT_EQ("avc1.64001e", avc_config.GetCodecString(FOURCC_avc1));
EXPECT_EQ("avc3.64001e", avc_config.GetCodecString(FOURCC_avc3));
}
TEST(AVCDecoderConfigurationRecordTest, FailsOnInvalidNaluLengthSize) {
@ -56,8 +57,8 @@ TEST(AVCDecoderConfigurationRecordTest, FailOnInsufficientData) {
}
TEST(AVCDecoderConfigurationRecordTest, GetCodecString) {
EXPECT_EQ("avc1.123456",
AVCDecoderConfigurationRecord::GetCodecString(0x12, 0x34, 0x56));
EXPECT_EQ("avc1.123456", AVCDecoderConfigurationRecord::GetCodecString(
FOURCC_avc1, 0x12, 0x34, 0x56));
}
} // namespace media

View File

@ -148,11 +148,15 @@ bool EsParserH264::UpdateVideoDecoderConfig(int pps_id) {
const uint8_t nalu_length_size =
H26xByteToUnitStreamConverter::kUnitStreamNaluLengthSize;
const H26xStreamFormat stream_format = stream_converter()->stream_format();
const FourCC codec_fourcc =
stream_format == H26xStreamFormat::kNalUnitStreamWithParameterSetNalus
? FOURCC_avc3
: FOURCC_avc1;
last_video_decoder_config_ = std::make_shared<VideoStreamInfo>(
pid(), kMpeg2Timescale, kInfiniteDuration, kCodecH264,
stream_converter()->stream_format(),
AVCDecoderConfigurationRecord::GetCodecString(decoder_config_record[1],
decoder_config_record[2],
pid(), kMpeg2Timescale, kInfiniteDuration, kCodecH264, stream_format,
AVCDecoderConfigurationRecord::GetCodecString(
codec_fourcc, decoder_config_record[1], decoder_config_record[2],
decoder_config_record[3]),
decoder_config_record.data(), decoder_config_record.size(), coded_width,
coded_height, pixel_width, pixel_height, 0, nalu_length_size,

View File

@ -520,7 +520,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
LOG(ERROR) << "Failed to parse avcc.";
return false;
}
codec_string = avc_config.GetCodecString();
codec_string = avc_config.GetCodecString(actual_format);
nalu_length_size = avc_config.nalu_length_size();
if (coded_width != avc_config.coded_width() ||

View File

@ -861,7 +861,13 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
return false;
}
}
video_stream_info->set_codec_string(avc_config.GetCodecString());
const FourCC codec_fourcc =
byte_to_unit_stream_converter_.stream_format() ==
H26xStreamFormat::kNalUnitStreamWithParameterSetNalus
? FOURCC_avc3
: FOURCC_avc1;
video_stream_info->set_codec_string(
avc_config.GetCodecString(codec_fourcc));
if (avc_config.pixel_width() != video_stream_info->pixel_width() ||
avc_config.pixel_height() !=

View File

@ -215,7 +215,7 @@ TEST_F(WvmMediaParserTest, ParseMultiConfigWvm) {
EXPECT_CALL(*key_source_, GetKey(_, _))
.WillOnce(DoAll(SetArgPointee<1>(encryption_key_), Return(Status::OK)));
Parse(kMultiConfigWvmFile);
EXPECT_EQ(6u, stream_map_.size());
ASSERT_EQ(4u, stream_map_.size());
ASSERT_EQ(kStreamVideo, stream_map_[0]->stream_type());
VideoStreamInfo* video_info = reinterpret_cast<VideoStreamInfo*>(
@ -242,18 +242,6 @@ TEST_F(WvmMediaParserTest, ParseMultiConfigWvm) {
EXPECT_EQ("mp4a.40.2", audio_info->codec_string());
EXPECT_EQ(2u, audio_info->num_channels());
EXPECT_EQ(44100u, audio_info->sampling_frequency());
ASSERT_EQ(kStreamVideo, stream_map_[4]->stream_type());
video_info = reinterpret_cast<VideoStreamInfo*>(stream_map_[4].get());
EXPECT_EQ("avc1.64001f", video_info->codec_string());
EXPECT_EQ(1280u, video_info->width());
EXPECT_EQ(720u, video_info->height());
ASSERT_EQ(kStreamAudio, stream_map_[5]->stream_type());
audio_info = reinterpret_cast<AudioStreamInfo*>(stream_map_[5].get());
EXPECT_EQ("mp4a.40.2", audio_info->codec_string());
EXPECT_EQ(2u, audio_info->num_channels());
EXPECT_EQ(48000u, audio_info->sampling_frequency());
}
} // namespace wvm