diff --git a/packager/media/codecs/codecs.gyp b/packager/media/codecs/codecs.gyp index 824853bf64..ae4537ba4a 100644 --- a/packager/media/codecs/codecs.gyp +++ b/packager/media/codecs/codecs.gyp @@ -39,6 +39,8 @@ 'h26x_byte_to_unit_stream_converter.h', 'hevc_decoder_configuration_record.cc', 'hevc_decoder_configuration_record.h', + 'hls_audio_util.cc', + 'hls_audio_util.h', 'nal_unit_to_byte_stream_converter.cc', 'nal_unit_to_byte_stream_converter.h', 'nalu_reader.cc', @@ -73,6 +75,7 @@ 'h265_parser_unittest.cc', 'h26x_bit_reader_unittest.cc', 'hevc_decoder_configuration_record_unittest.cc', + 'hls_audio_util_unittest.cc', 'nal_unit_to_byte_stream_converter_unittest.cc', 'nalu_reader_unittest.cc', 'video_slice_header_parser_unittest.cc', diff --git a/packager/media/codecs/hls_audio_util.cc b/packager/media/codecs/hls_audio_util.cc new file mode 100644 index 0000000000..6cac069ed5 --- /dev/null +++ b/packager/media/codecs/hls_audio_util.cc @@ -0,0 +1,84 @@ +// Copyright 2018 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "packager/media/codecs/hls_audio_util.h" + +#include "packager/media/base/buffer_writer.h" +#include "packager/media/base/fourccs.h" +#include "packager/media/codecs/aac_audio_specific_config.h" + +namespace shaka { +namespace media { + +bool WriteAudioSetupInformation(Codec codec, + const uint8_t* audio_specific_config, + size_t audio_specific_config_size, + BufferWriter* audio_setup_information) { + uint32_t audio_type = FOURCC_NULL; + switch (codec) { + case kCodecAAC: { + AACAudioSpecificConfig config; + const bool result = config.Parse(std::vector( + audio_specific_config, + audio_specific_config + audio_specific_config_size)); + + AACAudioSpecificConfig::AudioObjectType audio_object_type; + if (!result) { + LOG(WARNING) << "Failed to parse config. Assuming AAC-LC."; + audio_object_type = AACAudioSpecificConfig::AOT_AAC_LC; + } else { + audio_object_type = config.GetAudioObjectType(); + } + + switch (audio_object_type) { + case AACAudioSpecificConfig::AOT_AAC_LC: + audio_type = FOURCC_zaac; + break; + case AACAudioSpecificConfig::AOT_SBR: + audio_type = FOURCC_zach; + break; + case AACAudioSpecificConfig::AOT_PS: + audio_type = FOURCC_zacp; + break; + default: + LOG(ERROR) << "Unknown object type for aac " << audio_object_type; + return false; + } + } break; + case kCodecAC3: + audio_type = FOURCC_zac3; + break; + case kCodecEAC3: + audio_type = FOURCC_zec3; + break; + default: + LOG(ERROR) << "Codec " << codec << " is not supported in encrypted TS."; + return false; + } + + DCHECK_NE(audio_type, FOURCC_NULL); + audio_setup_information->AppendInt(audio_type); + // Priming. Since no info from encoder, set it to 0x0000. + audio_setup_information->AppendInt(static_cast(0x0000)); + // Version is always 0x01. + audio_setup_information->AppendInt(static_cast(0x01)); + + // Size is one byte. + if (audio_specific_config_size > 0xFF) { + LOG(ERROR) << "Audio specific config should not be larger than one byte " + << audio_specific_config_size; + return false; + } + audio_setup_information->AppendInt( + static_cast(audio_specific_config_size)); + + audio_setup_information->AppendArray(audio_specific_config, + audio_specific_config_size); + return true; +} + +} // namespace media +} // namespace shaka diff --git a/packager/media/codecs/hls_audio_util.h b/packager/media/codecs/hls_audio_util.h new file mode 100644 index 0000000000..1f17f279f7 --- /dev/null +++ b/packager/media/codecs/hls_audio_util.h @@ -0,0 +1,29 @@ +// Copyright 2018 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#ifndef PACKAGER_MEDIA_CODECS_HLS_AUDIO_UTIL_H_ +#define PACKAGER_MEDIA_CODECS_HLS_AUDIO_UTIL_H_ + +#include "packager/media/base/stream_info.h" + +namespace shaka { +namespace media { + +class BufferWriter; + +/// Write "Audio Setup Information" according to the specification at +/// https://goo.gl/X35ZRE MPEG-2 Stream Encryption Format for HTTP Live +/// Streaming 2.3.2. +/// @return true on success. +bool WriteAudioSetupInformation(Codec codec, + const uint8_t* audio_specific_config, + size_t audio_specific_config_size, + BufferWriter* audio_setup_information); + +} // namespace media +} // namespace shaka + +#endif // PACKAGER_MEDIA_CODECS_HLS_AUDIO_UTIL_H_ diff --git a/packager/media/codecs/hls_audio_util_unittest.cc b/packager/media/codecs/hls_audio_util_unittest.cc new file mode 100644 index 0000000000..6420b8531a --- /dev/null +++ b/packager/media/codecs/hls_audio_util_unittest.cc @@ -0,0 +1,100 @@ +// Copyright 2018 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "packager/media/codecs/hls_audio_util.h" + +#include + +#include "packager/media/base/buffer_writer.h" + +namespace shaka { +namespace media { + +TEST(HlsAudioUtilAudioSetupTest, AacAudioConfigLcProfile) { + const uint8_t kAacLcConfig[] = {12, 10}; + const uint8_t kExpectedAudioSetupInformation[]{ + 'z', 'a', 'a', 'c', 0, 0, 1, 2, 12, 10, + }; + + BufferWriter buffer_writer; + ASSERT_TRUE(WriteAudioSetupInformation(kCodecAAC, kAacLcConfig, + sizeof(kAacLcConfig), &buffer_writer)); + EXPECT_EQ( + std::vector(std::begin(kExpectedAudioSetupInformation), + std::end(kExpectedAudioSetupInformation)), + std::vector(buffer_writer.Buffer(), + buffer_writer.Buffer() + buffer_writer.Size())); +} + +TEST(HlsAudioUtilAudioSetupTest, AacAudioConfigHeProfile) { + const uint8_t kAacHeConfig[] = {0x2B, 0x92, 8, 0}; + const uint8_t kExpectedAudioSetupInformation[]{ + 'z', 'a', 'c', 'h', 0, 0, 1, 4, 0x2B, 0x92, 8, 0, + }; + + BufferWriter buffer_writer; + ASSERT_TRUE(WriteAudioSetupInformation(kCodecAAC, kAacHeConfig, + sizeof(kAacHeConfig), &buffer_writer)); + EXPECT_EQ( + std::vector(std::begin(kExpectedAudioSetupInformation), + std::end(kExpectedAudioSetupInformation)), + std::vector(buffer_writer.Buffer(), + buffer_writer.Buffer() + buffer_writer.Size())); +} + +TEST(HlsAudioUtilAudioSetupTest, AC3) { + const uint8_t kAudioSpecificConfig[] = { + 'a', 'u', 'd', 'i', 'o', '_', 'c', 'o', 'n', 'f', + }; + const uint8_t kExpectedAudioSetupInformation[]{ + 'z', 'a', 'c', '3', 0, 0, 1, 10, 'a', + 'u', 'd', 'i', 'o', '_', 'c', 'o', 'n', 'f', + }; + + BufferWriter buffer_writer; + ASSERT_TRUE(WriteAudioSetupInformation(kCodecAC3, kAudioSpecificConfig, + sizeof(kAudioSpecificConfig), + &buffer_writer)); + EXPECT_EQ( + std::vector(std::begin(kExpectedAudioSetupInformation), + std::end(kExpectedAudioSetupInformation)), + std::vector(buffer_writer.Buffer(), + buffer_writer.Buffer() + buffer_writer.Size())); +} + +TEST(HlsAudioUtilAudioSetupTest, EAC3) { + const uint8_t kAudioSpecificConfig[] = { + 'a', 'u', 'd', 'i', 'o', '_', 'c', 'o', 'n', 'f', + }; + const uint8_t kExpectedAudioSetupInformation[]{ + 'z', 'e', 'c', '3', 0, 0, 1, 10, 'a', + 'u', 'd', 'i', 'o', '_', 'c', 'o', 'n', 'f', + }; + + BufferWriter buffer_writer; + ASSERT_TRUE(WriteAudioSetupInformation(kCodecEAC3, kAudioSpecificConfig, + sizeof(kAudioSpecificConfig), + &buffer_writer)); + EXPECT_EQ( + std::vector(std::begin(kExpectedAudioSetupInformation), + std::end(kExpectedAudioSetupInformation)), + std::vector(buffer_writer.Buffer(), + buffer_writer.Buffer() + buffer_writer.Size())); +} + +TEST(HlsAudioUtilAudioSetupTest, FLAC_NotSupported) { + const uint8_t kAudioSpecificConfig[] = { + 'a', 'u', 'd', 'i', 'o', '_', 'c', 'o', 'n', 'f', + }; + + BufferWriter buffer_writer; + ASSERT_FALSE(WriteAudioSetupInformation(kCodecFlac, kAudioSpecificConfig, + sizeof(kAudioSpecificConfig), + &buffer_writer)); +} + +} // namespace media +} // namespace shaka diff --git a/packager/media/formats/mp2t/program_map_table_writer.cc b/packager/media/formats/mp2t/program_map_table_writer.cc index c150241b4b..83b1e1f9a0 100644 --- a/packager/media/formats/mp2t/program_map_table_writer.cc +++ b/packager/media/formats/mp2t/program_map_table_writer.cc @@ -11,7 +11,7 @@ #include "packager/base/logging.h" #include "packager/media/base/buffer_writer.h" #include "packager/media/base/fourccs.h" -#include "packager/media/codecs/aac_audio_specific_config.h" +#include "packager/media/codecs/hls_audio_util.h" #include "packager/media/formats/mp2t/ts_packet_writer_util.h" #include "packager/media/formats/mp2t/ts_stream_type.h" @@ -130,65 +130,6 @@ void WritePrivateDataIndicatorDescriptor(FourCC fourcc, BufferWriter* output) { output->AppendInt(fourcc); } -bool WriteAudioSetupInformation(Codec codec, - const uint8_t* audio_specific_config, - size_t audio_specific_config_size, - BufferWriter* audio_setup_information) { - uint32_t audio_type = FOURCC_NULL; - switch (codec) { - case kCodecAAC: { - AACAudioSpecificConfig config; - const bool result = config.Parse(std::vector( - audio_specific_config, - audio_specific_config + audio_specific_config_size)); - - AACAudioSpecificConfig::AudioObjectType audio_object_type; - if (!result) { - LOG(WARNING) << "Failed to parse config. Assuming AAC-LC."; - audio_object_type = AACAudioSpecificConfig::AOT_AAC_LC; - } else { - audio_object_type = config.GetAudioObjectType(); - } - - switch (audio_object_type) { - case AACAudioSpecificConfig::AOT_AAC_LC: - audio_type = FOURCC_zaac; - break; - case AACAudioSpecificConfig::AOT_SBR: - audio_type = FOURCC_zach; - break; - case AACAudioSpecificConfig::AOT_PS: - audio_type = FOURCC_zacp; - break; - default: - LOG(ERROR) << "Unknown object type for aac " << audio_object_type; - return false; - } - } break; - case kCodecAC3: - audio_type = FOURCC_zac3; - break; - case kCodecEAC3: - audio_type = FOURCC_zec3; - break; - default: - LOG(ERROR) << "Codec " << codec << " is not supported in encrypted TS."; - return false; - } - - DCHECK_NE(audio_type, FOURCC_NULL); - audio_setup_information->AppendInt(audio_type); - // Priming. Since no info from encoder, set it to 0x0000. - audio_setup_information->AppendInt(static_cast(0x0000)); - // Version is always 0x01. - audio_setup_information->AppendInt(static_cast(0x01)); - audio_setup_information->AppendInt( - static_cast(audio_specific_config_size)); - audio_setup_information->AppendArray(audio_specific_config, - audio_specific_config_size); - return true; -} - bool WriteRegistrationDescriptorForEncryptedAudio(Codec codec, const uint8_t* setup_data, size_t setup_data_size,