diff --git a/packager/media/base/fourccs.h b/packager/media/base/fourccs.h index 4f4c94b67a..c2dcf409f9 100644 --- a/packager/media/base/fourccs.h +++ b/packager/media/base/fourccs.h @@ -22,6 +22,7 @@ enum FourCC : uint32_t { FOURCC_ac_3 = 0x61632d33, // "ac-3" FOURCC_apad = 0x61706164, FOURCC_avc1 = 0x61766331, + FOURCC_avc3 = 0x61766333, FOURCC_avcC = 0x61766343, FOURCC_bloc = 0x626C6F63, FOURCC_cbc1 = 0x63626331, diff --git a/packager/media/base/stream_info.h b/packager/media/base/stream_info.h index 20e4e15a13..16274812a0 100644 --- a/packager/media/base/stream_info.h +++ b/packager/media/base/stream_info.h @@ -25,17 +25,14 @@ enum StreamType { enum Codec { kUnknownCodec = 0, kCodecH264, - kCodecHEV1, - kCodecHVC1, - kCodecVC1, - kCodecMPEG2, - kCodecMPEG4, - kCodecTheora, + kCodecH265, kCodecVP8, kCodecVP9, kCodecVP10, kCodecAAC, kCodecAC3, + // TODO(kqyang): Use kCodecDTS and a kDtsStreamFormat for the various DTS + // streams. kCodecDTSC, kCodecDTSE, kCodecDTSH, diff --git a/packager/media/base/video_stream_info.cc b/packager/media/base/video_stream_info.cc index 81678c1ceb..2e3ee259a5 100644 --- a/packager/media/base/video_stream_info.cc +++ b/packager/media/base/video_stream_info.cc @@ -20,18 +20,8 @@ std::string VideoCodecToString(Codec codec) { switch (codec) { case kCodecH264: return "H264"; - case kCodecHEV1: - return "HEV1"; - case kCodecHVC1: - return "HVC1"; - case kCodecVC1: - return "VC1"; - case kCodecMPEG2: - return "MPEG2"; - case kCodecMPEG4: - return "MPEG4"; - case kCodecTheora: - return "Theora"; + case kCodecH265: + return "H265"; case kCodecVP8: return "VP8"; case kCodecVP9: @@ -46,15 +36,33 @@ std::string VideoCodecToString(Codec codec) { } // namespace -VideoStreamInfo::VideoStreamInfo( - int track_id, uint32_t time_scale, uint64_t duration, Codec codec, - const std::string& codec_string, const uint8_t* codec_config, - size_t codec_config_size, uint16_t width, uint16_t height, - uint32_t pixel_width, uint32_t pixel_height, int16_t trick_play_rate, - uint8_t nalu_length_size, const std::string& language, bool is_encrypted) - : StreamInfo(kStreamVideo, track_id, time_scale, duration, codec, - codec_string, codec_config, codec_config_size, language, +VideoStreamInfo::VideoStreamInfo(int track_id, + uint32_t time_scale, + uint64_t duration, + Codec codec, + H26xStreamFormat h26x_stream_format, + const std::string& codec_string, + const uint8_t* codec_config, + size_t codec_config_size, + uint16_t width, + uint16_t height, + uint32_t pixel_width, + uint32_t pixel_height, + int16_t trick_play_rate, + uint8_t nalu_length_size, + const std::string& language, + bool is_encrypted) + : StreamInfo(kStreamVideo, + track_id, + time_scale, + duration, + codec, + codec_string, + codec_config, + codec_config_size, + language, is_encrypted), + h26x_stream_format_(h26x_stream_format), width_(width), height_(height), pixel_width_(pixel_width), diff --git a/packager/media/base/video_stream_info.h b/packager/media/base/video_stream_info.h index b375689b94..8989a65f89 100644 --- a/packager/media/base/video_stream_info.h +++ b/packager/media/base/video_stream_info.h @@ -12,18 +12,34 @@ namespace shaka { namespace media { +enum class H26xStreamFormat { + kUnSpecified, + kAnnexbByteStream, + kNalUnitStreamWithParameterSetNalus, + kNalUnitStreamWithoutParameterSetNalus, +}; + /// Holds video stream information. class VideoStreamInfo : public StreamInfo { public: /// Construct an initialized video stream info object. /// @param pixel_width is the width of the pixel. 0 if unknown. /// @param pixel_height is the height of the pixels. 0 if unknown. - VideoStreamInfo(int track_id, uint32_t time_scale, uint64_t duration, - Codec codec, const std::string& codec_string, - const uint8_t* codec_config, size_t codec_config_size, - uint16_t width, uint16_t height, uint32_t pixel_width, - uint32_t pixel_height, int16_t trick_play_rate, - uint8_t nalu_length_size, const std::string& language, + VideoStreamInfo(int track_id, + uint32_t time_scale, + uint64_t duration, + Codec codec, + H26xStreamFormat h26x_stream_format, + const std::string& codec_string, + const uint8_t* codec_config, + size_t codec_config_size, + uint16_t width, + uint16_t height, + uint32_t pixel_width, + uint32_t pixel_height, + int16_t trick_play_rate, + uint8_t nalu_length_size, + const std::string& language, bool is_encrypted); /// @name StreamInfo implementation overrides. @@ -32,6 +48,7 @@ class VideoStreamInfo : public StreamInfo { std::string ToString() const override; /// @} + H26xStreamFormat h26x_stream_format() const { return h26x_stream_format_; } uint16_t width() const { return width_; } uint16_t height() const { return height_; } /// Returns the pixel width. @@ -56,6 +73,7 @@ class VideoStreamInfo : public StreamInfo { private: ~VideoStreamInfo() override; + H26xStreamFormat h26x_stream_format_; uint16_t width_; uint16_t height_; diff --git a/packager/media/codecs/codecs.gyp b/packager/media/codecs/codecs.gyp index 477e2a295a..f4c9b313b7 100644 --- a/packager/media/codecs/codecs.gyp +++ b/packager/media/codecs/codecs.gyp @@ -53,6 +53,7 @@ ], 'dependencies': [ '../../base/base.gyp:base', + '../../third_party/gflags/gflags.gyp:gflags', ], }, { diff --git a/packager/media/codecs/h264_byte_to_unit_stream_converter.cc b/packager/media/codecs/h264_byte_to_unit_stream_converter.cc index 9de79e9a79..cdf54928b1 100644 --- a/packager/media/codecs/h264_byte_to_unit_stream_converter.cc +++ b/packager/media/codecs/h264_byte_to_unit_stream_converter.cc @@ -17,6 +17,11 @@ namespace media { H264ByteToUnitStreamConverter::H264ByteToUnitStreamConverter() : H26xByteToUnitStreamConverter(Nalu::kH264) {} + +H264ByteToUnitStreamConverter::H264ByteToUnitStreamConverter( + H26xStreamFormat stream_format) + : H26xByteToUnitStreamConverter(Nalu::kH264, stream_format) {} + H264ByteToUnitStreamConverter::~H264ByteToUnitStreamConverter() {} bool H264ByteToUnitStreamConverter::GetDecoderConfigurationRecord( @@ -60,13 +65,17 @@ bool H264ByteToUnitStreamConverter::ProcessNalu(const Nalu& nalu) { switch (nalu.type()) { case Nalu::H264_SPS: + if (strip_parameter_set_nalus()) + WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_sps_); // Grab SPS NALU. last_sps_.assign(nalu_ptr, nalu_ptr + nalu_size); - return true; + return strip_parameter_set_nalus(); case Nalu::H264_PPS: + if (strip_parameter_set_nalus()) + WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_pps_); // Grab PPS NALU. last_pps_.assign(nalu_ptr, nalu_ptr + nalu_size); - return true; + return strip_parameter_set_nalus(); case Nalu::H264_AUD: // Ignore AUD NALU. return true; diff --git a/packager/media/codecs/h264_byte_to_unit_stream_converter.h b/packager/media/codecs/h264_byte_to_unit_stream_converter.h index 5b177eeee2..79074eadf8 100644 --- a/packager/media/codecs/h264_byte_to_unit_stream_converter.h +++ b/packager/media/codecs/h264_byte_to_unit_stream_converter.h @@ -21,7 +21,14 @@ namespace media { /// Annex B) into H.264 NAL unit streams (as specified in ISO/IEC 14496-15). class H264ByteToUnitStreamConverter : public H26xByteToUnitStreamConverter { public: + /// Create a H264 byte to unit stream converter. + /// The setting of @a KeepParameterSetNalus is defined by a gflag. H264ByteToUnitStreamConverter(); + + /// Create a H264 byte to unit stream converter with desired output stream + /// format (whether to include parameter set nal units). + explicit H264ByteToUnitStreamConverter(H26xStreamFormat stream_format); + ~H264ByteToUnitStreamConverter() override; /// @name H26xByteToUnitStreamConverter implementation override. diff --git a/packager/media/codecs/h264_byte_to_unit_stream_converter_unittest.cc b/packager/media/codecs/h264_byte_to_unit_stream_converter_unittest.cc index eeb54c3ded..5fcfeb324d 100644 --- a/packager/media/codecs/h264_byte_to_unit_stream_converter_unittest.cc +++ b/packager/media/codecs/h264_byte_to_unit_stream_converter_unittest.cc @@ -20,16 +20,17 @@ const char kExpectedConfigRecord[] = namespace shaka { namespace media { -TEST(H264ByteToUnitStreamConverter, ConversionSuccess) { +TEST(H264ByteToUnitStreamConverter, StripParameterSetsNalu) { std::vector input_frame = ReadTestDataFile("avc-byte-stream-frame.h264"); ASSERT_FALSE(input_frame.empty()); std::vector expected_output_frame = - ReadTestDataFile("avc-unit-stream-frame.h264"); + ReadTestDataFile("avc1-unit-stream-frame.h264"); ASSERT_FALSE(expected_output_frame.empty()); - H264ByteToUnitStreamConverter converter; + H264ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus); std::vector output_frame; ASSERT_TRUE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), input_frame.size(), @@ -44,10 +45,29 @@ TEST(H264ByteToUnitStreamConverter, ConversionSuccess) { EXPECT_EQ(expected_decoder_config, decoder_config); } +TEST(H264ByteToUnitStreamConverter, KeepParameterSetsNalu) { + std::vector input_frame = + ReadTestDataFile("avc-byte-stream-frame.h264"); + ASSERT_FALSE(input_frame.empty()); + + std::vector expected_output_frame = + ReadTestDataFile("avc3-unit-stream-frame.h264"); + ASSERT_FALSE(expected_output_frame.empty()); + + H264ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus); + std::vector output_frame; + ASSERT_TRUE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), + input_frame.size(), + &output_frame)); + EXPECT_EQ(expected_output_frame, output_frame); +} + TEST(H264ByteToUnitStreamConverter, ConversionFailure) { std::vector input_frame(100, 0); - H264ByteToUnitStreamConverter converter; + H264ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus); std::vector output_frame; EXPECT_FALSE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), 0, diff --git a/packager/media/codecs/h265_byte_to_unit_stream_converter.cc b/packager/media/codecs/h265_byte_to_unit_stream_converter.cc index 17da8f37f6..5c62547cc0 100644 --- a/packager/media/codecs/h265_byte_to_unit_stream_converter.cc +++ b/packager/media/codecs/h265_byte_to_unit_stream_converter.cc @@ -18,6 +18,11 @@ namespace media { H265ByteToUnitStreamConverter::H265ByteToUnitStreamConverter() : H26xByteToUnitStreamConverter(Nalu::kH265) {} + +H265ByteToUnitStreamConverter::H265ByteToUnitStreamConverter( + H26xStreamFormat stream_format) + : H26xByteToUnitStreamConverter(Nalu::kH265, stream_format) {} + H265ByteToUnitStreamConverter::~H265ByteToUnitStreamConverter() {} bool H265ByteToUnitStreamConverter::GetDecoderConfigurationRecord( @@ -100,17 +105,23 @@ bool H265ByteToUnitStreamConverter::ProcessNalu(const Nalu& nalu) { switch (nalu.type()) { case Nalu::H265_SPS: + if (strip_parameter_set_nalus()) + WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_sps_); // Grab SPS NALU. last_sps_.assign(nalu_ptr, nalu_ptr + nalu_size); - return true; + return strip_parameter_set_nalus(); case Nalu::H265_PPS: + if (strip_parameter_set_nalus()) + WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_pps_); // Grab PPS NALU. last_pps_.assign(nalu_ptr, nalu_ptr + nalu_size); - return true; + return strip_parameter_set_nalus(); case Nalu::H265_VPS: + if (strip_parameter_set_nalus()) + WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_vps_); // Grab VPS NALU. last_vps_.assign(nalu_ptr, nalu_ptr + nalu_size); - return true; + return strip_parameter_set_nalus(); case Nalu::H265_AUD: // Ignore AUD NALU. return true; diff --git a/packager/media/codecs/h265_byte_to_unit_stream_converter.h b/packager/media/codecs/h265_byte_to_unit_stream_converter.h index d9f87966ad..889e86bd2c 100644 --- a/packager/media/codecs/h265_byte_to_unit_stream_converter.h +++ b/packager/media/codecs/h265_byte_to_unit_stream_converter.h @@ -21,7 +21,14 @@ namespace media { /// Annex B) into H.265 NAL unit streams (as specified in ISO/IEC 14496-15). class H265ByteToUnitStreamConverter : public H26xByteToUnitStreamConverter { public: + /// Create a H265 byte to unit stream converter. + /// The setting of @a KeepParameterSetNalus is defined by a gflag. H265ByteToUnitStreamConverter(); + + /// Create a H265 byte to unit stream converter with desired output stream + /// format (whether to include parameter set nal units). + explicit H265ByteToUnitStreamConverter(H26xStreamFormat stream_format); + ~H265ByteToUnitStreamConverter() override; /// @name H26xByteToUnitStreamConverter implementation override. diff --git a/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc b/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc index bfa9976d01..682085fae3 100644 --- a/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc +++ b/packager/media/codecs/h265_byte_to_unit_stream_converter_unittest.cc @@ -23,16 +23,17 @@ const char kExpectedConfigRecord[] = namespace shaka { namespace media { -TEST(H265ByteToUnitStreamConverter, ConversionSuccess) { +TEST(H265ByteToUnitStreamConverter, StripParameterSetsNalu) { std::vector input_frame = ReadTestDataFile("hevc-byte-stream-frame.h265"); ASSERT_FALSE(input_frame.empty()); std::vector expected_output_frame = - ReadTestDataFile("hevc-unit-stream-frame.h265"); + ReadTestDataFile("hvc1-unit-stream-frame.h265"); ASSERT_FALSE(expected_output_frame.empty()); - H265ByteToUnitStreamConverter converter; + H265ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus); std::vector output_frame; ASSERT_TRUE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), input_frame.size(), @@ -56,10 +57,29 @@ TEST(H265ByteToUnitStreamConverter, ConversionSuccess) { EXPECT_EQ(Nalu::H265_VPS, config.nalu(2).type()); } +TEST(H265ByteToUnitStreamConverter, KeepParameterSetsNalu) { + std::vector input_frame = + ReadTestDataFile("hevc-byte-stream-frame.h265"); + ASSERT_FALSE(input_frame.empty()); + + std::vector expected_output_frame = + ReadTestDataFile("hev1-unit-stream-frame.h265"); + ASSERT_FALSE(expected_output_frame.empty()); + + H265ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus); + std::vector output_frame; + ASSERT_TRUE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), + input_frame.size(), + &output_frame)); + EXPECT_EQ(expected_output_frame, output_frame); +} + TEST(H265ByteToUnitStreamConverter, ConversionFailure) { std::vector input_frame(100, 0); - H265ByteToUnitStreamConverter converter; + H265ByteToUnitStreamConverter converter( + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus); std::vector output_frame; EXPECT_FALSE(converter.ConvertByteStreamToNalUnitStream(input_frame.data(), 0, diff --git a/packager/media/codecs/h26x_byte_to_unit_stream_converter.cc b/packager/media/codecs/h26x_byte_to_unit_stream_converter.cc index 98b7169872..ffceee182b 100644 --- a/packager/media/codecs/h26x_byte_to_unit_stream_converter.cc +++ b/packager/media/codecs/h26x_byte_to_unit_stream_converter.cc @@ -6,8 +6,21 @@ #include "packager/media/codecs/h26x_byte_to_unit_stream_converter.h" +#include #include +#include "packager/base/strings/string_number_conversions.h" + +// TODO(kqyang): Move byte to unit stream convertion to muxer and make it a +// muxer option. +DEFINE_bool(strip_parameter_set_nalus, + true, + "When converting from NAL byte stream (AnnexB stream) to NAL unit " + "stream, this flag determines whether to strip parameter sets NAL " + "units, i.e. SPS/PPS for H264 and SPS/PPS/VPS for H265, from the " + "frames. Note that avc1/hvc1 is generated if this flag is enabled; " + "otherwise avc3/hev1 is generated."); + #include "packager/base/logging.h" #include "packager/media/base/buffer_writer.h" @@ -22,7 +35,17 @@ const size_t kStreamConversionOverhead = 100; H26xByteToUnitStreamConverter::H26xByteToUnitStreamConverter( Nalu::CodecType type) - : type_(type) {} + : type_(type), + stream_format_( + FLAGS_strip_parameter_set_nalus + ? H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus + : H26xStreamFormat::kNalUnitStreamWithParameterSetNalus) {} + +H26xByteToUnitStreamConverter::H26xByteToUnitStreamConverter( + Nalu::CodecType type, + H26xStreamFormat stream_format) + : type_(type), stream_format_(stream_format) {} + H26xByteToUnitStreamConverter::~H26xByteToUnitStreamConverter() {} bool H26xByteToUnitStreamConverter::ConvertByteStreamToNalUnitStream( @@ -57,6 +80,22 @@ bool H26xByteToUnitStreamConverter::ConvertByteStreamToNalUnitStream( return true; } +void H26xByteToUnitStreamConverter::WarnIfNotMatch( + int nalu_type, + const uint8_t* nalu_ptr, + size_t nalu_size, + const std::vector& vector) { + if (vector.empty()) + return; + if (vector.size() != nalu_size || + memcmp(vector.data(), nalu_ptr, nalu_size) != 0) { + LOG(WARNING) << "Seeing varying NAL unit of type " << nalu_type + << ". You may need to set --strip_parameter_set_nalus=false " + "during packaging to generate a playable stream."; + VLOG(1) << "Old: " << base::HexEncode(vector.data(), vector.size()); + VLOG(1) << "New: " << base::HexEncode(nalu_ptr, nalu_size); + } +} + } // namespace media } // namespace shaka - diff --git a/packager/media/codecs/h26x_byte_to_unit_stream_converter.h b/packager/media/codecs/h26x_byte_to_unit_stream_converter.h index b43da69528..5762e9bd6f 100644 --- a/packager/media/codecs/h26x_byte_to_unit_stream_converter.h +++ b/packager/media/codecs/h26x_byte_to_unit_stream_converter.h @@ -11,6 +11,7 @@ #include +#include "packager/media/base/video_stream_info.h" #include "packager/media/codecs/nalu_reader.h" namespace shaka { @@ -23,7 +24,15 @@ class H26xByteToUnitStreamConverter { public: static const size_t kUnitStreamNaluLengthSize = 4; - H26xByteToUnitStreamConverter(Nalu::CodecType type); + /// Create a byte to unit stream converter with specified codec type. + /// The setting of @a KeepParameterSetNalus is defined by a gflag. + explicit H26xByteToUnitStreamConverter(Nalu::CodecType type); + + /// Create a byte to unit stream converter with specified codec type and + /// desired output stream format (whether to include parameter set nal units). + H26xByteToUnitStreamConverter(Nalu::CodecType type, + H26xStreamFormat stream_format); + virtual ~H26xByteToUnitStreamConverter(); /// Converts a whole byte stream encoded video frame to NAL unit stream @@ -47,12 +56,27 @@ class H26xByteToUnitStreamConverter { virtual bool GetDecoderConfigurationRecord( std::vector* decoder_config) const = 0; + H26xStreamFormat stream_format() const { return stream_format_; } + + protected: + bool strip_parameter_set_nalus() const { + return stream_format_ == + H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus; + } + + // Warn if (nalu_ptr, nalu_size) does not match with |vector|. + void WarnIfNotMatch(int nalu_type, + const uint8_t* nalu_ptr, + size_t nalu_size, + const std::vector& vector); + private: // Process the given Nalu. If this returns true, it was handled and should // not be copied to the buffer. virtual bool ProcessNalu(const Nalu& nalu) = 0; Nalu::CodecType type_; + H26xStreamFormat stream_format_; DISALLOW_COPY_AND_ASSIGN(H26xByteToUnitStreamConverter); }; diff --git a/packager/media/codecs/hevc_decoder_configuration_record.cc b/packager/media/codecs/hevc_decoder_configuration_record.cc index 43ba8e0bc2..c6037a4f43 100644 --- a/packager/media/codecs/hevc_decoder_configuration_record.cc +++ b/packager/media/codecs/hevc_decoder_configuration_record.cc @@ -59,18 +59,6 @@ std::string ReverseBitsAndHexEncode(uint32_t x) { return TrimLeadingZeros(base::HexEncode(bytes, arraysize(bytes))); } -std::string CodecAsString(Codec codec) { - switch (codec) { - case kCodecHEV1: - return "hev1"; - case kCodecHVC1: - return "hvc1"; - default: - LOG(WARNING) << "Unknown codec: " << codec; - return std::string(); - } -} - } // namespace HEVCDecoderConfigurationRecord::HEVCDecoderConfigurationRecord() @@ -132,10 +120,11 @@ bool HEVCDecoderConfigurationRecord::ParseInternal() { return true; } -std::string HEVCDecoderConfigurationRecord::GetCodecString(Codec codec) const { +std::string HEVCDecoderConfigurationRecord::GetCodecString( + FourCC codec_fourcc) const { // ISO/IEC 14496-15:2014 Annex E. std::vector fields; - fields.push_back(CodecAsString(codec)); + fields.push_back(FourCCToString(codec_fourcc)); fields.push_back(GeneralProfileSpaceAsString(general_profile_space_) + base::IntToString(general_profile_idc_)); fields.push_back( diff --git a/packager/media/codecs/hevc_decoder_configuration_record.h b/packager/media/codecs/hevc_decoder_configuration_record.h index 6f3c3e64ce..5b94f77645 100644 --- a/packager/media/codecs/hevc_decoder_configuration_record.h +++ b/packager/media/codecs/hevc_decoder_configuration_record.h @@ -12,6 +12,7 @@ #include #include "packager/base/macros.h" +#include "packager/media/base/fourccs.h" #include "packager/media/base/video_stream_info.h" #include "packager/media/codecs/decoder_configuration_record.h" @@ -25,7 +26,7 @@ class HEVCDecoderConfigurationRecord : public DecoderConfigurationRecord { ~HEVCDecoderConfigurationRecord() override; /// @return The codec string. - std::string GetCodecString(Codec codec) const; + std::string GetCodecString(FourCC codec_fourcc) const; private: bool ParseInternal() override; diff --git a/packager/media/codecs/hevc_decoder_configuration_record_unittest.cc b/packager/media/codecs/hevc_decoder_configuration_record_unittest.cc index 722a89f8cb..fededbca84 100644 --- a/packager/media/codecs/hevc_decoder_configuration_record_unittest.cc +++ b/packager/media/codecs/hevc_decoder_configuration_record_unittest.cc @@ -45,8 +45,8 @@ TEST(HEVCDecoderConfigurationRecordTest, Success) { EXPECT_EQ(4u, hevc_config.nalu_length_size()); - EXPECT_EQ("hev1.2.4.L63.90", hevc_config.GetCodecString(kCodecHEV1)); - EXPECT_EQ("hvc1.2.4.L63.90", hevc_config.GetCodecString(kCodecHVC1)); + EXPECT_EQ("hev1.2.4.L63.90", hevc_config.GetCodecString(FOURCC_hev1)); + EXPECT_EQ("hvc1.2.4.L63.90", hevc_config.GetCodecString(FOURCC_hvc1)); EXPECT_EQ(2u, hevc_config.nalu_count()); EXPECT_EQ(0x16u, hevc_config.nalu(0).payload_size()); diff --git a/packager/media/event/muxer_listener_test_helper.cc b/packager/media/event/muxer_listener_test_helper.cc index 38b0f83f06..e22209799b 100644 --- a/packager/media/event/muxer_listener_test_helper.cc +++ b/packager/media/event/muxer_listener_test_helper.cc @@ -18,8 +18,9 @@ scoped_refptr CreateVideoStreamInfo( const VideoStreamInfoParameters& param) { return scoped_refptr(new VideoStreamInfo( param.track_id, param.time_scale, param.duration, param.codec, - param.codec_string, param.codec_config.data(), param.codec_config.size(), - param.width, param.height, param.pixel_width, param.pixel_height, + H26xStreamFormat::kUnSpecified, param.codec_string, + param.codec_config.data(), param.codec_config.size(), param.width, + param.height, param.pixel_width, param.pixel_height, 0, // trick_play_rate param.nalu_length_size, param.language, param.is_encrypted)); } diff --git a/packager/media/formats/mp2t/es_parser_h264.cc b/packager/media/formats/mp2t/es_parser_h264.cc index ccc8da4493..1a84ba7daf 100644 --- a/packager/media/formats/mp2t/es_parser_h264.cc +++ b/packager/media/formats/mp2t/es_parser_h264.cc @@ -148,6 +148,7 @@ bool EsParserH264::UpdateVideoDecoderConfig(int pps_id) { last_video_decoder_config_ = scoped_refptr(new VideoStreamInfo( pid(), kMpeg2Timescale, kInfiniteDuration, kCodecH264, + stream_converter()->stream_format(), AVCDecoderConfigurationRecord::GetCodecString(decoder_config_record[1], decoder_config_record[2], decoder_config_record[3]), diff --git a/packager/media/formats/mp2t/es_parser_h265.cc b/packager/media/formats/mp2t/es_parser_h265.cc index 6318700fc2..1e38740b2b 100644 --- a/packager/media/formats/mp2t/es_parser_h265.cc +++ b/packager/media/formats/mp2t/es_parser_h265.cc @@ -151,9 +151,14 @@ bool EsParserH265::UpdateVideoDecoderConfig(int pps_id) { return false; } + const H26xStreamFormat stream_format = stream_converter()->stream_format(); + const FourCC codec_fourcc = + stream_format == H26xStreamFormat::kNalUnitStreamWithParameterSetNalus + ? FOURCC_hev1 + : FOURCC_hvc1; last_video_decoder_config_ = scoped_refptr(new VideoStreamInfo( - pid(), kMpeg2Timescale, kInfiniteDuration, kCodecHVC1, - decoder_config.GetCodecString(kCodecHVC1), decoder_config_record.data(), + pid(), kMpeg2Timescale, kInfiniteDuration, kCodecH265, stream_format, + decoder_config.GetCodecString(codec_fourcc), decoder_config_record.data(), decoder_config_record.size(), coded_width, coded_height, pixel_width, pixel_height, 0, H26xByteToUnitStreamConverter::kUnitStreamNaluLengthSize, std::string(), false)); diff --git a/packager/media/formats/mp2t/pes_packet_generator_unittest.cc b/packager/media/formats/mp2t/pes_packet_generator_unittest.cc index 94fc32bdaf..dcef7a0a02 100644 --- a/packager/media/formats/mp2t/pes_packet_generator_unittest.cc +++ b/packager/media/formats/mp2t/pes_packet_generator_unittest.cc @@ -104,7 +104,8 @@ class MockAACAudioSpecificConfig : public AACAudioSpecificConfig { scoped_refptr CreateVideoStreamInfo(Codec codec) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, codec, kCodecString, kVideoExtraData, + kTrackId, kTimeScale, kDuration, codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kVideoExtraData, arraysize(kVideoExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); return stream_info; @@ -363,9 +364,10 @@ TEST_F(PesPacketGeneratorTest, AddAudioSampleFailedToConvert) { TEST_F(PesPacketGeneratorTest, TimeStampScaling) { const uint32_t kTestTimescale = 1000; scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTestTimescale, kDuration, kH264Codec, kCodecString, - kVideoExtraData, arraysize(kVideoExtraData), kWidth, kHeight, kPixelWidth, - kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); + kTrackId, kTestTimescale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kVideoExtraData, + arraysize(kVideoExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, + kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(generator_.Initialize(*stream_info)); EXPECT_EQ(0u, generator_.NumberOfReadyPesPackets()); diff --git a/packager/media/formats/mp2t/ts_segmenter_unittest.cc b/packager/media/formats/mp2t/ts_segmenter_unittest.cc index d2f1e240de..3c705ab014 100644 --- a/packager/media/formats/mp2t/ts_segmenter_unittest.cc +++ b/packager/media/formats/mp2t/ts_segmenter_unittest.cc @@ -109,7 +109,8 @@ class TsSegmenterTest : public ::testing::Test { TEST_F(TsSegmenterTest, Initialize) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -129,7 +130,8 @@ TEST_F(TsSegmenterTest, Initialize) { TEST_F(TsSegmenterTest, AddSample) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -184,9 +186,10 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) { // done correctly in the segmenter. const uint32_t kInputTimescale = 1001; scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kInputTimescale, kDuration, kH264Codec, kCodecString, - kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, - kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); + kTrackId, kInputTimescale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, + arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, + kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; options.segment_duration = 10.0; options.segment_template = "file$Number$.ts"; @@ -283,7 +286,8 @@ TEST_F(TsSegmenterTest, PassedSegmentDuration) { // Finalize right after Initialize(). The writer will not be initialized. TEST_F(TsSegmenterTest, InitializeThenFinalize) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -312,7 +316,8 @@ TEST_F(TsSegmenterTest, InitializeThenFinalize) { // writer with a mock. TEST_F(TsSegmenterTest, Finalize) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -341,7 +346,8 @@ TEST_F(TsSegmenterTest, Finalize) { // Verify that it won't finish a segment if the sample is not a key frame. TEST_F(TsSegmenterTest, SegmentOnlyBeforeKeyFrame) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -447,7 +453,8 @@ TEST_F(TsSegmenterTest, SegmentOnlyBeforeKeyFrame) { TEST_F(TsSegmenterTest, WithEncryptionNoClearLead) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -490,7 +497,8 @@ TEST_F(TsSegmenterTest, WithEncryptionNoClearLead) { // not null. TEST_F(TsSegmenterTest, WithEncryptionNoClearLeadNoMuxerListener) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; @@ -530,7 +538,8 @@ TEST_F(TsSegmenterTest, WithEncryptionNoClearLeadNoMuxerListener) { // Verify that encryption notification is sent to objects after clear lead. TEST_F(TsSegmenterTest, WithEncryptionWithClearLead) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); MuxerOptions options; diff --git a/packager/media/formats/mp2t/ts_writer_unittest.cc b/packager/media/formats/mp2t/ts_writer_unittest.cc index b632d7bec9..a2a8330c29 100644 --- a/packager/media/formats/mp2t/ts_writer_unittest.cc +++ b/packager/media/formats/mp2t/ts_writer_unittest.cc @@ -158,7 +158,8 @@ class TsWriterTest : public ::testing::Test { TEST_F(TsWriterTest, InitializeVideoH264) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -166,9 +167,10 @@ TEST_F(TsWriterTest, InitializeVideoH264) { TEST_F(TsWriterTest, InitializeVideoNonH264) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, Codec::kCodecVP9, kCodecString, - kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, - kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); + kTrackId, kTimeScale, kDuration, Codec::kCodecVP9, + H26xStreamFormat::kUnSpecified, kCodecString, kExtraData, + arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, + kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_FALSE(ts_writer_.Initialize(*stream_info)); } @@ -199,7 +201,8 @@ TEST_F(TsWriterTest, ClearH264Psi) { EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(WriteOnePmt()); scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -281,7 +284,8 @@ TEST_F(TsWriterTest, ClearLeadH264Pmt) { .WillOnce(WriteTwoPmts()); scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -310,7 +314,8 @@ TEST_F(TsWriterTest, EncryptedSegmentsH264Pmt) { EXPECT_CALL(*mock_pmt_writer, EncryptedSegmentPmt(_)).WillOnce(WriteOnePmt()); scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -398,7 +403,8 @@ TEST_F(TsWriterTest, EncryptedSegmentsAacPmt) { TEST_F(TsWriterTest, AddPesPacket) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -463,7 +469,8 @@ TEST_F(TsWriterTest, AddPesPacket) { // Verify that PES packet > 64KiB can be handled. TEST_F(TsWriterTest, BigPesPacket) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -499,7 +506,8 @@ TEST_F(TsWriterTest, BigPesPacket) { // PTS (implicilty) cast to bool is true. TEST_F(TsWriterTest, PesPtsZeroNoDts) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); @@ -559,7 +567,8 @@ TEST_F(TsWriterTest, PesPtsZeroNoDts) { // adaptation_field_length should be 0. TEST_F(TsWriterTest, TsPacketPayload183Bytes) { scoped_refptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, kH264Codec, kCodecString, kExtraData, + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, kIsEncrypted)); EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index 99d08c0caa..9b5332ed5d 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -1509,6 +1509,7 @@ bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) { const FourCC actual_format = GetActualFormat(); switch (actual_format) { case FOURCC_avc1: + case FOURCC_avc3: compressor_name.assign( kAvcCompressorName, kAvcCompressorName + arraysize(kAvcCompressorName)); @@ -1595,6 +1596,7 @@ size_t VideoSampleEntry::ComputeSizeInternal() { FourCC VideoSampleEntry::GetCodecConfigurationBoxType(FourCC format) const { switch (format) { case FOURCC_avc1: + case FOURCC_avc3: return FOURCC_avcC; case FOURCC_hev1: case FOURCC_hvc1: diff --git a/packager/media/formats/mp4/encrypting_fragmenter.cc b/packager/media/formats/mp4/encrypting_fragmenter.cc index 859ec8104c..15a2fd2911 100644 --- a/packager/media/formats/mp4/encrypting_fragmenter.cc +++ b/packager/media/formats/mp4/encrypting_fragmenter.cc @@ -88,9 +88,7 @@ EncryptingFragmenter::EncryptingFragmenter( case kCodecH264: header_parser_.reset(new H264VideoSliceHeaderParser); break; - case kCodecHVC1: - FALLTHROUGH_INTENDED; - case kCodecHEV1: + case kCodecH265: header_parser_.reset(new H265VideoSliceHeaderParser); break; default: @@ -304,9 +302,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr sample) { } } else { const Nalu::CodecType nalu_type = - (video_codec_ == kCodecHVC1 || video_codec_ == kCodecHEV1) - ? Nalu::kH265 - : Nalu::kH264; + (video_codec_ == kCodecH265) ? Nalu::kH265 : Nalu::kH264; NaluReader reader(nalu_type, nalu_length_size_, data, sample->data_size()); diff --git a/packager/media/formats/mp4/mp4_media_parser.cc b/packager/media/formats/mp4/mp4_media_parser.cc index 6147328404..06e1c65015 100644 --- a/packager/media/formats/mp4/mp4_media_parser.cc +++ b/packager/media/formats/mp4/mp4_media_parser.cc @@ -41,14 +41,29 @@ uint64_t Rescale(uint64_t time_in_old_scale, return (static_cast(time_in_old_scale) / old_scale) * new_scale; } +H26xStreamFormat GetH26xStreamFormat(FourCC fourcc) { + switch (fourcc) { + case FOURCC_avc1: + return H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus; + case FOURCC_avc3: + return H26xStreamFormat::kNalUnitStreamWithParameterSetNalus; + case FOURCC_hev1: + return H26xStreamFormat::kNalUnitStreamWithParameterSetNalus; + case FOURCC_hvc1: + return H26xStreamFormat::kNalUnitStreamWithoutParameterSetNalus; + default: + return H26xStreamFormat::kUnSpecified; + } +} + Codec FourCCToCodec(FourCC fourcc) { switch (fourcc) { case FOURCC_avc1: + case FOURCC_avc3: return kCodecH264; case FOURCC_hev1: - return kCodecHEV1; case FOURCC_hvc1: - return kCodecHVC1; + return kCodecH265; case FOURCC_vp08: return kCodecVP8; case FOURCC_vp09: @@ -495,7 +510,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { const FourCC actual_format = entry.GetActualFormat(); const Codec video_codec = FourCCToCodec(actual_format); switch (actual_format) { - case FOURCC_avc1: { + case FOURCC_avc1: + case FOURCC_avc3: { AVCDecoderConfigurationRecord avc_config; if (!avc_config.Parse(entry.codec_configuration.data)) { LOG(ERROR) << "Failed to parse avcc."; @@ -538,7 +554,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { LOG(ERROR) << "Failed to parse hevc."; return false; } - codec_string = hevc_config.GetCodecString(video_codec); + codec_string = hevc_config.GetCodecString(actual_format); nalu_length_size = hevc_config.nalu_length_size(); break; } @@ -564,7 +580,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted; scoped_refptr video_stream_info(new VideoStreamInfo( track->header.track_id, timescale, duration, video_codec, - codec_string, entry.codec_configuration.data.data(), + GetH26xStreamFormat(actual_format), codec_string, + entry.codec_configuration.data.data(), entry.codec_configuration.data.size(), coded_width, coded_height, pixel_width, pixel_height, 0, // trick_play_rate diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index 58fbbdb554..cbd9ed5ffb 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -40,14 +40,18 @@ void SetStartAndEndFromOffsetAndSize(size_t offset, *end = *start + static_cast(size) - 1; } -FourCC CodecToFourCC(Codec codec) { +FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) { switch (codec) { case kCodecH264: - return FOURCC_avc1; - case kCodecHEV1: - return FOURCC_hev1; - case kCodecHVC1: - return FOURCC_hvc1; + return h26x_stream_format == + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus + ? FOURCC_avc3 + : FOURCC_avc1; + case kCodecH265: + return h26x_stream_format == + H26xStreamFormat::kNalUnitStreamWithParameterSetNalus + ? FOURCC_hev1 + : FOURCC_hvc1; case kCodecVP8: return FOURCC_vp08; case kCodecVP9: @@ -93,8 +97,10 @@ Status MP4Muxer::Initialize() { ftyp->compatible_brands.push_back(FOURCC_mp41); if (streams().size() == 1 && streams()[0]->info()->stream_type() == kStreamVideo) { - const FourCC codec_fourcc = CodecToFourCC( - static_cast(streams()[0]->info().get())->codec()); + const FourCC codec_fourcc = + CodecToFourCC(streams()[0]->info()->codec(), + static_cast(streams()[0]->info().get()) + ->h26x_stream_format()); if (codec_fourcc != FOURCC_NULL) ftyp->compatible_brands.push_back(codec_fourcc); } @@ -220,7 +226,8 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info, trak->header.height = video_info->height() * 0x10000; VideoSampleEntry video; - video.format = CodecToFourCC(video_info->codec()); + video.format = + CodecToFourCC(video_info->codec(), video_info->h26x_stream_format()); video.width = video_info->width(); video.height = video_info->height(); video.codec_configuration.data = video_info->codec_config(); @@ -243,7 +250,8 @@ void MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info, trak->header.volume = 0x100; AudioSampleEntry audio; - audio.format = CodecToFourCC(audio_info->codec()); + audio.format = + CodecToFourCC(audio_info->codec(), H26xStreamFormat::kUnSpecified); switch(audio_info->codec()){ case kCodecAAC: audio.esds.es_descriptor.set_object_type(kISO_14496_3); // MPEG4 AAC. diff --git a/packager/media/formats/webm/segmenter_test_base.cc b/packager/media/formats/webm/segmenter_test_base.cc index c8573ada70..f5198248c8 100644 --- a/packager/media/formats/webm/segmenter_test_base.cc +++ b/packager/media/formats/webm/segmenter_test_base.cc @@ -87,9 +87,9 @@ MuxerOptions SegmentTestBase::CreateMuxerOptions() const { VideoStreamInfo* SegmentTestBase::CreateVideoStreamInfo() const { return new VideoStreamInfo(kTrackId, kTimeScale, kDuration, kCodec, - kCodecString, NULL, 0, kWidth, kHeight, - kPixelWidth, kPixelHeight, kTrickPlayRate, - kNaluLengthSize, kLanguage, false); + H26xStreamFormat::kUnSpecified, kCodecString, NULL, + 0, kWidth, kHeight, kPixelWidth, kPixelHeight, + kTrickPlayRate, kNaluLengthSize, kLanguage, false); } std::string SegmentTestBase::OutputFileName() const { diff --git a/packager/media/formats/webm/webm_cluster_parser_unittest.cc b/packager/media/formats/webm/webm_cluster_parser_unittest.cc index c145dfb5b4..1ef86b3d29 100644 --- a/packager/media/formats/webm/webm_cluster_parser_unittest.cc +++ b/packager/media/formats/webm/webm_cluster_parser_unittest.cc @@ -322,16 +322,38 @@ bool VerifyTextBuffers(const BlockInfo* block_info_ptr, class WebMClusterParserTest : public testing::Test { public: WebMClusterParserTest() - : audio_stream_info_(new AudioStreamInfo( - kAudioTrackNum, kTimeScale, kDuration, kUnknownCodec, kCodecString, - kExtraData, kExtraDataSize, kBitsPerSample, kNumChannels, - kSamplingFrequency, kSeekPreroll, kCodecDelay, 0, 0, kLanguage, - !kEncrypted)), - video_stream_info_(new VideoStreamInfo( - kVideoTrackNum, kTimeScale, kDuration, kCodecVP8, kCodecString, - kExtraData, kExtraDataSize, kWidth, kHeight, kPixelWidth, - kPixelHeight, kTrickPlayRate, kNaluLengthSize, kLanguage, - !kEncrypted)), + : audio_stream_info_(new AudioStreamInfo(kAudioTrackNum, + kTimeScale, + kDuration, + kUnknownCodec, + kCodecString, + kExtraData, + kExtraDataSize, + kBitsPerSample, + kNumChannels, + kSamplingFrequency, + kSeekPreroll, + kCodecDelay, + 0, + 0, + kLanguage, + !kEncrypted)), + video_stream_info_(new VideoStreamInfo(kVideoTrackNum, + kTimeScale, + kDuration, + kCodecVP8, + H26xStreamFormat::kUnSpecified, + kCodecString, + kExtraData, + kExtraDataSize, + kWidth, + kHeight, + kPixelWidth, + kPixelHeight, + kTrickPlayRate, + kNaluLengthSize, + kLanguage, + !kEncrypted)), parser_(CreateDefaultParser()) {} protected: diff --git a/packager/media/formats/webm/webm_video_client.cc b/packager/media/formats/webm/webm_video_client.cc index 9e2f9fd06d..d6c6147424 100644 --- a/packager/media/formats/webm/webm_video_client.cc +++ b/packager/media/formats/webm/webm_video_client.cc @@ -109,9 +109,10 @@ scoped_refptr WebMVideoClient::GetVideoStreamInfo( sar_y /= gcd; return scoped_refptr(new VideoStreamInfo( - track_num, kWebMTimeScale, 0, video_codec, std::string(), - codec_private.data(), codec_private.size(), width_after_crop, - height_after_crop, sar_x, sar_y, 0, 0, std::string(), is_encrypted)); + track_num, kWebMTimeScale, 0, video_codec, H26xStreamFormat::kUnSpecified, + std::string(), codec_private.data(), codec_private.size(), + width_after_crop, height_after_crop, sar_x, sar_y, 0, 0, std::string(), + is_encrypted)); } bool WebMVideoClient::OnUInt(int id, int64_t val) { diff --git a/packager/media/formats/wvm/wvm_media_parser.cc b/packager/media/formats/wvm/wvm_media_parser.cc index 19206a87a3..aa4ca37693 100644 --- a/packager/media/formats/wvm/wvm_media_parser.cc +++ b/packager/media/formats/wvm/wvm_media_parser.cc @@ -108,8 +108,7 @@ WvmMediaParser::WvmMediaParser() media_sample_(NULL), crypto_unit_start_pos_(0), stream_id_count_(0), - decryption_key_source_(NULL) { -} + decryption_key_source_(NULL) {} WvmMediaParser::~WvmMediaParser() {} @@ -250,6 +249,7 @@ bool WvmMediaParser::Parse(const uint8_t* buf, int size) { if (HAS_HEADER_EXTENSION(pes_stream_id_)) { parse_state_ = PesExtension1; } else { + prev_pes_flags_1_ = pes_flags_1_; pes_flags_1_ = pes_flags_2_ = 0; pes_header_data_bytes_ = 0; parse_state_ = PesPayload; @@ -738,11 +738,11 @@ bool WvmMediaParser::ParseIndexEntry() { index_size = read_ptr - index_data_.data(); if (has_video) { - Codec video_codec = kCodecH264; - stream_infos_.push_back(new VideoStreamInfo( - stream_id_count_, time_scale, track_duration, video_codec, - std::string(), video_codec_config.data(), video_codec_config.size(), - video_width, video_height, pixel_width, pixel_height, trick_play_rate, + stream_infos_.emplace_back(new VideoStreamInfo( + stream_id_count_, time_scale, track_duration, kCodecH264, + byte_to_unit_stream_converter_.stream_format(), std::string(), + video_codec_config.data(), video_codec_config.size(), video_width, + video_height, pixel_width, pixel_height, trick_play_rate, nalu_length_size, std::string(), true)); program_demux_stream_map_[base::UintToString(index_program_id_) + ":" + base::UintToString( diff --git a/packager/media/test/data/avc-unit-stream-frame.h264 b/packager/media/test/data/avc1-unit-stream-frame.h264 similarity index 100% rename from packager/media/test/data/avc-unit-stream-frame.h264 rename to packager/media/test/data/avc1-unit-stream-frame.h264 diff --git a/packager/media/test/data/avc3-unit-stream-frame.h264 b/packager/media/test/data/avc3-unit-stream-frame.h264 new file mode 100644 index 0000000000..357edaf317 Binary files /dev/null and b/packager/media/test/data/avc3-unit-stream-frame.h264 differ diff --git a/packager/media/test/data/hev1-unit-stream-frame.h265 b/packager/media/test/data/hev1-unit-stream-frame.h265 new file mode 100644 index 0000000000..fdcb347edd Binary files /dev/null and b/packager/media/test/data/hev1-unit-stream-frame.h265 differ diff --git a/packager/media/test/data/hevc-unit-stream-frame.h265 b/packager/media/test/data/hvc1-unit-stream-frame.h265 similarity index 100% rename from packager/media/test/data/hevc-unit-stream-frame.h265 rename to packager/media/test/data/hvc1-unit-stream-frame.h265