diff --git a/packager/hls/base/media_playlist.cc b/packager/hls/base/media_playlist.cc index c25c8845aa..215baa6bf9 100644 --- a/packager/hls/base/media_playlist.cc +++ b/packager/hls/base/media_playlist.cc @@ -37,6 +37,29 @@ uint32_t GetTimeScale(const MediaInfo& media_info) { return 0u; } +std::string AdjustVideoCodec(const std::string& codec) { + // Apple does not like video formats with the parameter sets stored in the + // samples. It also fails mediastreamvalidator checks and some Apple devices / + // platforms refused to play. + // See https://apple.co/30n90DC 1.10 and + // https://github.com/google/shaka-packager/issues/587#issuecomment-489182182. + // Replaced with the corresponding formats with the parameter sets stored in + // the sample descriptions instead. + std::string adjusted_codec = codec; + std::string fourcc = codec.substr(0, 4); + if (fourcc == "avc3") + adjusted_codec = "avc1" + codec.substr(4); + else if (fourcc == "hev1") + adjusted_codec = "hvc1" + codec.substr(4); + else if (fourcc == "dvhe") + adjusted_codec = "dvh1" + codec.substr(4); + if (adjusted_codec != codec) { + VLOG(1) << "Adusting video codec string from " << codec << " to " + << adjusted_codec; + } + return adjusted_codec; +} + // Duplicated from MpdUtils because: // 1. MpdUtils header depends on libxml header, which is not in the deps here // 2. GetLanguage depends on MediaInfo from packager/mpd/ @@ -349,7 +372,7 @@ bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) { if (media_info.has_video_info()) { stream_type_ = MediaPlaylistStreamType::kVideo; - codec_ = media_info.video_info().codec(); + codec_ = AdjustVideoCodec(media_info.video_info().codec()); } else if (media_info.has_audio_info()) { stream_type_ = MediaPlaylistStreamType::kAudio; codec_ = media_info.audio_info().codec(); diff --git a/packager/hls/base/media_playlist_unittest.cc b/packager/hls/base/media_playlist_unittest.cc index 74100ec6cd..46f00e678a 100644 --- a/packager/hls/base/media_playlist_unittest.cc +++ b/packager/hls/base/media_playlist_unittest.cc @@ -20,6 +20,8 @@ namespace hls { using ::testing::_; using ::testing::ElementsAreArray; using ::testing::ReturnArg; +using ::testing::Values; +using ::testing::WithParamInterface; namespace { @@ -1012,5 +1014,31 @@ TEST_F(MediaPlaylistDeleteSegmentsTest, ManySegments) { kStringPrintTemplate, last_available_segment_index - 1))); } +class MediaPlaylistCodecTest + : public MediaPlaylistTest, + public WithParamInterface> {}; + +TEST_P(MediaPlaylistCodecTest, AdjustVideoCodec) { + std::string input_codec, expected_output_codec; + std::tie(input_codec, expected_output_codec) = GetParam(); + + valid_video_media_info_.mutable_video_info()->set_codec(input_codec); + ASSERT_TRUE(media_playlist_->SetMediaInfo(valid_video_media_info_)); + ASSERT_EQ(media_playlist_->codec(), expected_output_codec); +} + +INSTANTIATE_TEST_CASE_P( + Codecs, + MediaPlaylistCodecTest, + Values(std::make_pair("avc1.4d401e", "avc1.4d401e"), + // Replace avc3 with avc1. + std::make_pair("avc3.4d401e", "avc1.4d401e"), + std::make_pair("hvc1.2.4.L63.90", "hvc1.2.4.L63.90"), + // Replace hev1 with hvc1. + std::make_pair("hev1.2.4.L63.90", "hvc1.2.4.L63.90"), + std::make_pair("dvh1.2.4.L63.90", "dvh1.2.4.L63.90"), + // Replace dvhe with dvh1. + std::make_pair("dvhe.2.4.L63.90", "dvh1.2.4.L63.90"))); + } // namespace hls } // namespace shaka