diff options
Diffstat (limited to 'chromium/media/video')
18 files changed, 709 insertions, 76 deletions
diff --git a/chromium/media/video/BUILD.gn b/chromium/media/video/BUILD.gn index bda5d803cf4..9b7658a09b4 100644 --- a/chromium/media/video/BUILD.gn +++ b/chromium/media/video/BUILD.gn @@ -53,7 +53,7 @@ source_set("video") { "h265_nalu_parser.cc", "h265_nalu_parser.h", ] - if (enable_platform_hevc_decoding) { + if (enable_hevc_parser_and_hw_decoder) { sources += [ "h265_parser.cc", "h265_parser.h", @@ -150,8 +150,11 @@ source_set("unit_tests") { ] if (enable_platform_hevc) { sources += [ "h265_nalu_parser_unittest.cc" ] - if (enable_platform_hevc_decoding) { - sources += [ "h265_parser_unittest.cc" ] + if (enable_hevc_parser_and_hw_decoder) { + sources += [ + "h265_parser_unittest.cc", + "h265_poc_unittest.cc", + ] } } @@ -180,7 +183,7 @@ fuzzer_test("media_h264_parser_fuzzer") { ] } -if (enable_platform_hevc_decoding) { +if (enable_hevc_parser_and_hw_decoder) { fuzzer_test("media_h265_parser_fuzzer") { sources = [ "h265_parser_fuzzertest.cc" ] deps = [ diff --git a/chromium/media/video/av1_video_encoder.cc b/chromium/media/video/av1_video_encoder.cc index 368e7a47a5d..50121a0cbe9 100644 --- a/chromium/media/video/av1_video_encoder.cc +++ b/chromium/media/video/av1_video_encoder.cc @@ -380,7 +380,7 @@ void Av1VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, return; } - TRACE_EVENT0("media", "aom_codec_encode"); + TRACE_EVENT1("media", "aom_codec_encode", "timestamp", frame->timestamp()); // Use artificial timestamps, so the encoder will not be misled by frame's // fickle timestamps when doing rate control. auto error = diff --git a/chromium/media/video/fake_video_encode_accelerator.cc b/chromium/media/video/fake_video_encode_accelerator.cc index 3ea82727ceb..aee0e86a6ef 100644 --- a/chromium/media/video/fake_video_encode_accelerator.cc +++ b/chromium/media/video/fake_video_encode_accelerator.cc @@ -40,6 +40,7 @@ FakeVideoEncodeAccelerator::GetSupportedProfiles() { profile.max_resolution.SetSize(1920, 1088); profile.max_framerate_numerator = 30; profile.max_framerate_denominator = 1; + profile.rate_control_modes = media::VideoEncodeAccelerator::kConstantMode; profile.profile = media::H264PROFILE_MAIN; profiles.push_back(profile); diff --git a/chromium/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/chromium/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc index b619ccb44fa..a42246b1241 100644 --- a/chromium/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/chromium/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc @@ -6,6 +6,7 @@ #include <memory> #include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -237,10 +238,10 @@ class GpuMemoryBufferVideoFramePoolTest : public ::testing::Test { static constexpr uint8_t kUValue = 50; static constexpr uint8_t kVValue = 150; - uint8_t* y_data_ = nullptr; - uint8_t* u_data_ = nullptr; - uint8_t* v_data_ = nullptr; - uint8_t* uv_data_ = nullptr; + raw_ptr<uint8_t> y_data_ = nullptr; + raw_ptr<uint8_t> u_data_ = nullptr; + raw_ptr<uint8_t> v_data_ = nullptr; + raw_ptr<uint8_t> uv_data_ = nullptr; base::SimpleTestTickClock test_clock_; std::unique_ptr<MockGpuVideoAcceleratorFactories> mock_gpu_factories_; diff --git a/chromium/media/video/h264_level_limits.cc b/chromium/media/video/h264_level_limits.cc index f4f60c2bd97..6261632c9f1 100644 --- a/chromium/media/video/h264_level_limits.cc +++ b/chromium/media/video/h264_level_limits.cc @@ -5,6 +5,7 @@ #include "media/video/h264_level_limits.h" #include "base/logging.h" +#include "base/numerics/checked_math.h" #include "media/video/h264_parser.h" namespace media { diff --git a/chromium/media/video/h265_parser.cc b/chromium/media/video/h265_parser.cc index 4969e15163e..46e840fd3ee 100644 --- a/chromium/media/video/h265_parser.cc +++ b/chromium/media/video/h265_parser.cc @@ -650,40 +650,44 @@ H265Parser::Result H265Parser::ParseSPS(int* sps_id) { sps->pic_height_in_luma_samples); } - bool sps_extension_present_flag; - bool sps_range_extension_flag = false; - bool sps_multilayer_extension_flag = false; - bool sps_3d_extension_flag = false; - bool sps_scc_extension_flag = false; - READ_BOOL_OR_RETURN(&sps_extension_present_flag); - if (sps_extension_present_flag) { - READ_BOOL_OR_RETURN(&sps_range_extension_flag); - READ_BOOL_OR_RETURN(&sps_multilayer_extension_flag); - READ_BOOL_OR_RETURN(&sps_3d_extension_flag); - READ_BOOL_OR_RETURN(&sps_scc_extension_flag); + READ_BOOL_OR_RETURN(&sps->sps_extension_present_flag); + if (sps->sps_extension_present_flag) { + READ_BOOL_OR_RETURN(&sps->sps_range_extension_flag); + READ_BOOL_OR_RETURN(&sps->sps_multilayer_extension_flag); + READ_BOOL_OR_RETURN(&sps->sps_3d_extension_flag); + READ_BOOL_OR_RETURN(&sps->sps_scc_extension_flag); SKIP_BITS_OR_RETURN(4); // sps_extension_4bits } - if (sps_range_extension_flag) { - DVLOG(1) << "HEVC range extension not supported"; - return kInvalidStream; - } - if (sps_multilayer_extension_flag) { + if (sps->sps_range_extension_flag) { + READ_BOOL_OR_RETURN(&sps->transform_skip_rotation_enabled_flag); + READ_BOOL_OR_RETURN(&sps->transform_skip_context_enabled_flag); + READ_BOOL_OR_RETURN(&sps->implicit_rdpcm_enabled_flag); + READ_BOOL_OR_RETURN(&sps->explicit_rdpcm_enabled_flag); + READ_BOOL_OR_RETURN(&sps->extended_precision_processing_flag); + READ_BOOL_OR_RETURN(&sps->intra_smoothing_disabled_flag); + READ_BOOL_OR_RETURN(&sps->high_precision_offsets_enabled_flag); + READ_BOOL_OR_RETURN(&sps->persistent_rice_adaptation_enabled_flag); + READ_BOOL_OR_RETURN(&sps->cabac_bypass_alignment_enabled_flag); + } + if (sps->sps_multilayer_extension_flag) { DVLOG(1) << "HEVC multilayer extension not supported"; return kInvalidStream; } - if (sps_3d_extension_flag) { + if (sps->sps_3d_extension_flag) { DVLOG(1) << "HEVC 3D extension not supported"; return kInvalidStream; } - if (sps_scc_extension_flag) { + if (sps->sps_scc_extension_flag) { DVLOG(1) << "HEVC SCC extension not supported"; return kInvalidStream; } - // NOTE: The below 2 values are dependent upon the range extension if that is - // ever implemented. - sps->wp_offset_half_range_y = 1 << 7; - sps->wp_offset_half_range_c = 1 << 7; + sps->wp_offset_half_range_y = 1 << (sps->high_precision_offsets_enabled_flag + ? sps->bit_depth_luma_minus8 + 7 + : 7); + sps->wp_offset_half_range_c = 1 << (sps->high_precision_offsets_enabled_flag + ? sps->bit_depth_chroma_minus8 + 7 + : 7); // If an SPS with the same id already exists, replace it. *sps_id = sps->sps_seq_parameter_set_id; @@ -808,33 +812,51 @@ H265Parser::Result H265Parser::ParsePPS(const H265NALU& nalu, int* pps_id) { IN_RANGE_OR_RETURN(pps->log2_parallel_merge_level_minus2, 0, sps->ctb_log2_size_y - 2); READ_BOOL_OR_RETURN(&pps->slice_segment_header_extension_present_flag); - bool pps_extension_present_flag; - READ_BOOL_OR_RETURN(&pps_extension_present_flag); - bool pps_range_extension_flag = false; - bool pps_multilayer_extension_flag = false; - bool pps_3d_extension_flag = false; - bool pps_scc_extension_flag = false; - if (pps_extension_present_flag) { - READ_BOOL_OR_RETURN(&pps_range_extension_flag); - READ_BOOL_OR_RETURN(&pps_multilayer_extension_flag); - READ_BOOL_OR_RETURN(&pps_3d_extension_flag); - READ_BOOL_OR_RETURN(&pps_scc_extension_flag); + READ_BOOL_OR_RETURN(&pps->pps_extension_present_flag); + if (pps->pps_extension_present_flag) { + READ_BOOL_OR_RETURN(&pps->pps_range_extension_flag); + READ_BOOL_OR_RETURN(&pps->pps_multilayer_extension_flag); + READ_BOOL_OR_RETURN(&pps->pps_3d_extension_flag); + READ_BOOL_OR_RETURN(&pps->pps_scc_extension_flag); SKIP_BITS_OR_RETURN(4); // pps_extension_4bits } - if (pps_range_extension_flag) { - DVLOG(1) << "HEVC range extension not supported"; - return kInvalidStream; - } - if (pps_multilayer_extension_flag) { + if (pps->pps_range_extension_flag) { + if (pps->transform_skip_enabled_flag) { + READ_UE_OR_RETURN(&pps->log2_max_transform_skip_block_size_minus2); + IN_RANGE_OR_RETURN(pps->log2_max_transform_skip_block_size_minus2, 0, 3); + } + READ_BOOL_OR_RETURN(&pps->cross_component_prediction_enabled_flag); + READ_BOOL_OR_RETURN(&pps->chroma_qp_offset_list_enabled_flag); + if (pps->chroma_qp_offset_list_enabled_flag) { + READ_UE_OR_RETURN(&pps->diff_cu_chroma_qp_offset_depth); + IN_RANGE_OR_RETURN(pps->diff_cu_chroma_qp_offset_depth, 0, + sps->log2_diff_max_min_luma_coding_block_size); + READ_UE_OR_RETURN(&pps->chroma_qp_offset_list_len_minus1); + IN_RANGE_OR_RETURN(pps->chroma_qp_offset_list_len_minus1, 0, 5); + for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { + READ_SE_OR_RETURN(&pps->cb_qp_offset_list[i]); + IN_RANGE_OR_RETURN(pps->cb_qp_offset_list[i], -12, 12); + READ_SE_OR_RETURN(&pps->cr_qp_offset_list[i]); + IN_RANGE_OR_RETURN(pps->cr_qp_offset_list[i], -12, 12); + } + } + READ_UE_OR_RETURN(&pps->log2_sao_offset_scale_luma); + IN_RANGE_OR_RETURN(pps->log2_sao_offset_scale_luma, 0, + std::max(sps->bit_depth_luma_minus8 - 2, 0)); + READ_UE_OR_RETURN(&pps->log2_sao_offset_scale_chroma); + IN_RANGE_OR_RETURN(pps->log2_sao_offset_scale_chroma, 0, + std::max(sps->bit_depth_chroma_minus8 - 2, 0)); + } + if (pps->pps_multilayer_extension_flag) { DVLOG(1) << "HEVC multilayer extension not supported"; return kInvalidStream; } - if (pps_3d_extension_flag) { + if (pps->pps_3d_extension_flag) { DVLOG(1) << "HEVC 3D extension not supported"; return kInvalidStream; } - if (pps_scc_extension_flag) { + if (pps->pps_scc_extension_flag) { DVLOG(1) << "HEVC SCC extension not supported"; return kInvalidStream; } @@ -1136,8 +1158,8 @@ H265Parser::Result H265Parser::ParseSliceHeader(const H265NALU& nalu, // pps_slice_act_qp_offsets_present_flag is zero, we don't support SCC ext. - // chroma_qp_offset_list_enabled_flag is zero, we don't support range ext. - + if (pps->chroma_qp_offset_list_enabled_flag) + SKIP_BITS_OR_RETURN(1); // cu_chroma_qp_offset_enabled_flag bool deblocking_filter_override_flag = false; if (pps->deblocking_filter_override_enabled_flag) READ_BOOL_OR_RETURN(&deblocking_filter_override_flag); @@ -1229,6 +1251,22 @@ VideoCodecProfile H265Parser::ProfileIDCToVideoCodecProfile(int profile_idc) { return HEVCPROFILE_MAIN10; case H265ProfileTierLevel::kProfileIdcMainStill: return HEVCPROFILE_MAIN_STILL_PICTURE; + case H265ProfileTierLevel::kProfileIdcRangeExtensions: + return HEVCPROFILE_REXT; + case H265ProfileTierLevel::kProfileIdcHighThroughput: + return HEVCPROFILE_HIGH_THROUGHPUT; + case H265ProfileTierLevel::kProfileIdcMultiviewMain: + return HEVCPROFILE_MULTIVIEW_MAIN; + case H265ProfileTierLevel::kProfileIdcScalableMain: + return HEVCPROFILE_SCALABLE_MAIN; + case H265ProfileTierLevel::kProfileIdc3dMain: + return HEVCPROFILE_3D_MAIN; + case H265ProfileTierLevel::kProfileIdcScreenContentCoding: + return HEVCPROFILE_SCREEN_EXTENDED; + case H265ProfileTierLevel::kProfileIdcScalableRangeExtensions: + return HEVCPROFILE_SCALABLE_REXT; + case H265ProfileTierLevel::kProfileIdcHighThroughputScreenContentCoding: + return HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED; default: DVLOG(1) << "unknown video profile: " << profile_idc; return VIDEO_CODEC_PROFILE_UNKNOWN; diff --git a/chromium/media/video/h265_parser.h b/chromium/media/video/h265_parser.h index 3553ecaaaf8..0dce696e1cd 100644 --- a/chromium/media/video/h265_parser.h +++ b/chromium/media/video/h265_parser.h @@ -35,14 +35,17 @@ enum { struct MEDIA_EXPORT H265ProfileTierLevel { H265ProfileTierLevel(); - // From Annex A.3. enum H265ProfileIdc { kProfileIdcMain = 1, kProfileIdcMain10 = 2, kProfileIdcMainStill = 3, kProfileIdcRangeExtensions = 4, kProfileIdcHighThroughput = 5, + kProfileIdcMultiviewMain = 6, + kProfileIdcScalableMain = 7, + kProfileIdc3dMain = 8, kProfileIdcScreenContentCoding = 9, + kProfileIdcScalableRangeExtensions = 10, kProfileIdcHighThroughputScreenContentCoding = 11, }; @@ -179,6 +182,22 @@ struct MEDIA_EXPORT H265SPS { bool strong_intra_smoothing_enabled_flag; H265VUIParameters vui_parameters; + // Extension extra elements. + bool sps_extension_present_flag; + bool sps_range_extension_flag; + bool sps_multilayer_extension_flag; + bool sps_3d_extension_flag; + bool sps_scc_extension_flag; + bool transform_skip_rotation_enabled_flag; + bool transform_skip_context_enabled_flag; + bool implicit_rdpcm_enabled_flag; + bool explicit_rdpcm_enabled_flag; + bool extended_precision_processing_flag; + bool intra_smoothing_disabled_flag; + bool high_precision_offsets_enabled_flag; + bool persistent_rice_adaptation_enabled_flag; + bool cabac_bypass_alignment_enabled_flag; + // Calculated fields. int chroma_array_type; int sub_width_c; @@ -251,6 +270,22 @@ struct MEDIA_EXPORT H265PPS { int log2_parallel_merge_level_minus2; bool slice_segment_header_extension_present_flag; + // Extension extra elements. + bool pps_extension_present_flag; + bool pps_range_extension_flag; + bool pps_multilayer_extension_flag; + bool pps_3d_extension_flag; + bool pps_scc_extension_flag; + int log2_max_transform_skip_block_size_minus2; + bool cross_component_prediction_enabled_flag; + bool chroma_qp_offset_list_enabled_flag; + int diff_cu_chroma_qp_offset_depth; + int chroma_qp_offset_list_len_minus1; + int cb_qp_offset_list[6]; + int cr_qp_offset_list[6]; + int log2_sao_offset_scale_luma; + int log2_sao_offset_scale_chroma; + // Calculated fields. int qp_bd_offset_y; }; diff --git a/chromium/media/video/h265_poc_unittest.cc b/chromium/media/video/h265_poc_unittest.cc new file mode 100644 index 00000000000..85a856dc003 --- /dev/null +++ b/chromium/media/video/h265_poc_unittest.cc @@ -0,0 +1,393 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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/video/h265_parser.h" +#include "media/video/h265_poc.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class H265POCTest : public testing::Test { + public: + H265POCTest() : sps_(), pps_(), slice_hdr_() {} + + H265POCTest(const H265POCTest&) = delete; + H265POCTest& operator=(const H265POCTest&) = delete; + + protected: + void ComputePOC() { + poc_ = h265_poc_.ComputePicOrderCnt(&sps_, &pps_, slice_hdr_); + } + + int32_t poc_; + + H265SPS sps_; + H265PPS pps_; + H265SliceHeader slice_hdr_; + H265POC h265_poc_; +}; + +TEST_F(H265POCTest, PicOrderCnt) { + sps_.log2_max_pic_order_cnt_lsb_minus4 = 7; + pps_.temporal_id = 0; + + // Initial I frame with POC 0. + slice_hdr_.nal_unit_type = H265NALU::IDR_N_LP; + slice_hdr_.irap_pic = true; + slice_hdr_.slice_pic_order_cnt_lsb = 0; + ComputePOC(); + ASSERT_EQ(0, poc_); + + // P frame with POC lsb 4. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 4; + ComputePOC(); + ASSERT_EQ(4, poc_); + + // B frame with POC lsb 2. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 2; + ComputePOC(); + + ASSERT_EQ(2, poc_); + + // B frame with POC lsb 1. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 1; + ComputePOC(); + ASSERT_EQ(1, poc_); + + // B frame with POC lsb 3. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 3; + ComputePOC(); + ASSERT_EQ(3, poc_); + + // P frame with POC lsb 8. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 8; + ComputePOC(); + ASSERT_EQ(8, poc_); + + // B Ref frame with POC lsb 6. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 6; + ComputePOC(); + ASSERT_EQ(6, poc_); + + // B frame with POC lsb 5. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 5; + ComputePOC(); + ASSERT_EQ(5, poc_); + + // B frame with POC lsb 7. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 7; + ComputePOC(); + ASSERT_EQ(7, poc_); + + // P frame with POC lsb 12. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 12; + ComputePOC(); + ASSERT_EQ(12, poc_); + + // B frame with POC lsb 10. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 10; + ComputePOC(); + ASSERT_EQ(10, poc_); + + // B frame with POC lsb 9. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 9; + ComputePOC(); + ASSERT_EQ(9, poc_); + + // B frame with POC lsb 11. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 11; + ComputePOC(); + ASSERT_EQ(11, poc_); + + // P frame with POC lsb 16. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 16; + ComputePOC(); + ASSERT_EQ(16, poc_); + + // B frame with POC lsb 14. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 14; + ComputePOC(); + ASSERT_EQ(14, poc_); + + // B frame with POC lsb 13. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 13; + ComputePOC(); + ASSERT_EQ(13, poc_); + + // B frame with POC lsb 15. + slice_hdr_.nal_unit_type = H265NALU::TSA_N; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 15; + ComputePOC(); + ASSERT_EQ(15, poc_); +}; + +TEST_F(H265POCTest, PicOrderCntInOrder) { + sps_.log2_max_pic_order_cnt_lsb_minus4 = 12; + pps_.temporal_id = 0; + + // Initial I frame with POC 0. + slice_hdr_.nal_unit_type = H265NALU::IDR_W_RADL; + slice_hdr_.irap_pic = true; + slice_hdr_.slice_pic_order_cnt_lsb = 0; + ComputePOC(); + ASSERT_EQ(0, poc_); + + // P frame with POC lsb 1. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 1; + ComputePOC(); + ASSERT_EQ(1, poc_); + + // P frame with POC lsb 2. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 2; + ComputePOC(); + ASSERT_EQ(2, poc_); + + // P frame with POC lsb 3. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 3; + ComputePOC(); + ASSERT_EQ(3, poc_); + + // P frame with POC lsb 4. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 4; + ComputePOC(); + ASSERT_EQ(4, poc_); + + // P frame with POC lsb 5. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 5; + ComputePOC(); + ASSERT_EQ(5, poc_); + + // P frame with POC lsb 6. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 6; + ComputePOC(); + ASSERT_EQ(6, poc_); + + // P frame with POC lsb 7. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 7; + ComputePOC(); + ASSERT_EQ(7, poc_); + + // P frame with POC lsb 8. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 8; + ComputePOC(); + ASSERT_EQ(8, poc_); + + // P frame with POC lsb 9. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 9; + ComputePOC(); + ASSERT_EQ(9, poc_); + + // P frame with POC lsb 10. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 10; + ComputePOC(); + ASSERT_EQ(10, poc_); + + // P frame with POC lsb 11. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 11; + ComputePOC(); + ASSERT_EQ(11, poc_); + + // P frame with POC lsb 12. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 12; + ComputePOC(); + ASSERT_EQ(12, poc_); + + // P frame with POC lsb 13. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 13; + ComputePOC(); + ASSERT_EQ(13, poc_); + + // P frame with POC lsb 14. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 14; + ComputePOC(); + ASSERT_EQ(14, poc_); + + // P frame with POC lsb 15. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 15; + ComputePOC(); + ASSERT_EQ(15, poc_); + + // P frame with POC lsb 16. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 16; + ComputePOC(); + ASSERT_EQ(16, poc_); + + // P frame with POC lsb 17. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 17; + ComputePOC(); + ASSERT_EQ(17, poc_); + + // P frame with POC lsb 18. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 18; + ComputePOC(); + ASSERT_EQ(18, poc_); + + // P frame with POC lsb 19. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 19; + ComputePOC(); + ASSERT_EQ(19, poc_); + + // P frame with POC lsb 20. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 20; + ComputePOC(); + ASSERT_EQ(20, poc_); + + // P frame with POC lsb 21. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 21; + ComputePOC(); + ASSERT_EQ(21, poc_); + + // P frame with POC lsb 22. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 22; + ComputePOC(); + ASSERT_EQ(22, poc_); + + // P frame with POC lsb 23. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 23; + ComputePOC(); + ASSERT_EQ(23, poc_); + + // P frame with POC lsb 24. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 24; + ComputePOC(); + ASSERT_EQ(24, poc_); + + // P frame with POC lsb 25. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 25; + ComputePOC(); + ASSERT_EQ(25, poc_); + + // P frame with POC lsb 26. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 26; + ComputePOC(); + ASSERT_EQ(26, poc_); + + // P frame with POC lsb 27. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 27; + ComputePOC(); + ASSERT_EQ(27, poc_); + + // P frame with POC lsb 28. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 28; + ComputePOC(); + ASSERT_EQ(28, poc_); + + // P frame with POC lsb 29. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 29; + ComputePOC(); + ASSERT_EQ(29, poc_); + + // I frame with POC 0. + slice_hdr_.nal_unit_type = H265NALU::IDR_W_RADL; + slice_hdr_.irap_pic = true; + slice_hdr_.slice_pic_order_cnt_lsb = 0; + ComputePOC(); + ASSERT_EQ(0, poc_); + + // P frame with POC lsb 1. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 1; + ComputePOC(); + ASSERT_EQ(1, poc_); + + // P frame with POC lsb 2. + slice_hdr_.nal_unit_type = H265NALU::TRAIL_R; + slice_hdr_.irap_pic = false; + slice_hdr_.slice_pic_order_cnt_lsb = 2; + ComputePOC(); + ASSERT_EQ(2, poc_); +}; +} // namespace media
\ No newline at end of file diff --git a/chromium/media/video/openh264_video_encoder.cc b/chromium/media/video/openh264_video_encoder.cc index 92f45f7f43d..23142afbf48 100644 --- a/chromium/media/video/openh264_video_encoder.cc +++ b/chromium/media/video/openh264_video_encoder.cc @@ -328,7 +328,8 @@ void OpenH264VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, } SFrameBSInfo frame_info = {}; - TRACE_EVENT0("media", "OpenH264::EncodeFrame"); + TRACE_EVENT1("media", "OpenH264::EncodeFrame", "timestamp", + frame->timestamp()); if (int err = codec_->EncodeFrame(&picture, &frame_info)) { std::move(done_cb).Run( EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, diff --git a/chromium/media/video/picture.cc b/chromium/media/video/picture.cc index 046aeb195a4..216db308485 100644 --- a/chromium/media/video/picture.cc +++ b/chromium/media/video/picture.cc @@ -98,7 +98,8 @@ Picture::Picture(int32_t picture_buffer_id, read_lock_fences_enabled_(false), size_changed_(false), texture_owner_(false), - wants_promotion_hint_(false) {} + wants_promotion_hint_(false), + is_webgpu_compatible_(false) {} Picture::Picture(const Picture& other) = default; diff --git a/chromium/media/video/picture.h b/chromium/media/video/picture.h index 0b2173d5d0b..088a1c9817a 100644 --- a/chromium/media/video/picture.h +++ b/chromium/media/video/picture.h @@ -173,6 +173,12 @@ class MEDIA_EXPORT Picture { return scoped_shared_images_[plane]; } + void set_is_webgpu_compatible(bool is_webgpu_compatible) { + is_webgpu_compatible_ = is_webgpu_compatible; + } + + bool is_webgpu_compatible() { return is_webgpu_compatible_; } + private: int32_t picture_buffer_id_; int32_t bitstream_buffer_id_; @@ -183,6 +189,7 @@ class MEDIA_EXPORT Picture { bool size_changed_; bool texture_owner_; bool wants_promotion_hint_; + bool is_webgpu_compatible_; std::array<scoped_refptr<ScopedSharedImage>, VideoFrame::kMaxPlanes> scoped_shared_images_; }; diff --git a/chromium/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc b/chromium/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc index b714eb8fd44..dbf2b3e1f42 100644 --- a/chromium/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc +++ b/chromium/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc @@ -179,6 +179,8 @@ bool FrameResources::Initialize() { return false; } + gpu_memory_buffer_->SetColorSpace(color_space_); + // Bind SharedImages to each plane. constexpr size_t kNumPlanes = 2; constexpr gfx::BufferPlane kPlanes[kNumPlanes] = {gfx::BufferPlane::Y, diff --git a/chromium/media/video/software_video_encoder_test.cc b/chromium/media/video/software_video_encoder_test.cc index 4c8e81626dd..97eecc2dabe 100644 --- a/chromium/media/video/software_video_encoder_test.cc +++ b/chromium/media/video/software_video_encoder_test.cc @@ -8,6 +8,7 @@ #include <string> #include "base/callback_helpers.h" +#include "base/feature_list.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" #include "base/strings/string_number_conversions.h" @@ -19,7 +20,9 @@ #include "base/time/time.h" #include "build/build_config.h" #include "media/base/decoder_buffer.h" +#include "media/base/media_switches.h" #include "media/base/mock_media_log.h" +#include "media/base/video_decoder.h" #include "media/base/video_encoder.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" @@ -47,6 +50,10 @@ #include "media/filters/dav1d_video_decoder.h" #endif +#if BUILDFLAG(ENABLE_LIBGAV1_DECODER) +#include "media/filters/gav1_video_decoder.h" +#endif + namespace media { struct SwVideoTestParams { @@ -93,9 +100,16 @@ class SoftwareVideoEncoderTest decoder_ = std::make_unique<VpxVideoDecoder>(); #endif } else if (codec_ == VideoCodec::kAV1) { +#if BUILDFLAG(ENABLE_LIBGAV1_DECODER) + if (base::FeatureList::IsEnabled(kGav1VideoDecoder)) { + decoder_ = std::make_unique<Gav1VideoDecoder>(&media_log_); + } else +#endif + { #if BUILDFLAG(ENABLE_DAV1D_DECODER) - decoder_ = std::make_unique<Dav1dVideoDecoder>(&media_log_); + decoder_ = std::make_unique<Dav1dVideoDecoder>(&media_log_); #endif + } } EXPECT_NE(decoder_, nullptr); @@ -118,10 +132,10 @@ class SoftwareVideoEncoderTest frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), - 0, // left - 0, // top - frame->visible_rect().width(), // right - frame->visible_rect().height(), // bottom + frame->visible_rect().x(), // x + frame->visible_rect().y(), // y + frame->visible_rect().width(), // width + frame->visible_rect().height(), // height y, // Y color u, // U color v); // V color @@ -147,10 +161,10 @@ class SoftwareVideoEncoderTest libyuv::ARGBRect(frame->data(VideoFrame::kARGBPlane), frame->stride(VideoFrame::kARGBPlane), - 0, // left - 0, // top - frame->visible_rect().width(), // right - frame->visible_rect().height(), // bottom + frame->visible_rect().x(), // dst_x + frame->visible_rect().y(), // dst_y + frame->visible_rect().width(), // width + frame->visible_rect().height(), // height color); return frame; @@ -259,7 +273,7 @@ class SoftwareVideoEncoderTest uint8_t tolerance = 10; if (frame1.format() != frame2.format() || - frame1.visible_rect() != frame2.visible_rect()) { + frame1.visible_rect().size() != frame2.visible_rect().size()) { return frame1.coded_size().GetArea(); } @@ -470,7 +484,8 @@ TEST_P(SoftwareVideoEncoderTest, EncodeAndDecode) { auto original_frame = frames_to_encode[i]; auto decoded_frame = decoded_frames[i]; EXPECT_EQ(decoded_frame->timestamp(), original_frame->timestamp()); - EXPECT_EQ(decoded_frame->visible_rect(), original_frame->visible_rect()); + EXPECT_EQ(decoded_frame->visible_rect().size(), + original_frame->visible_rect().size()); EXPECT_EQ(decoded_frame->format(), PIXEL_FORMAT_I420); if (decoded_frame->format() == original_frame->format()) { EXPECT_LE(CountDifferentPixels(*decoded_frame, *original_frame), diff --git a/chromium/media/video/video_encode_accelerator.cc b/chromium/media/video/video_encode_accelerator.cc index 0d93cff2259..9c04460ab99 100644 --- a/chromium/media/video/video_encode_accelerator.cc +++ b/chromium/media/video/video_encode_accelerator.cc @@ -152,11 +152,13 @@ VideoEncodeAccelerator::SupportedProfile::SupportedProfile( const gfx::Size& max_resolution, uint32_t max_framerate_numerator, uint32_t max_framerate_denominator, + SupportedRateControlMode rc_modes, const std::vector<SVCScalabilityMode>& scalability_modes) : profile(profile), max_resolution(max_resolution), max_framerate_numerator(max_framerate_numerator), max_framerate_denominator(max_framerate_denominator), + rate_control_modes(rc_modes), scalability_modes(scalability_modes) {} VideoEncodeAccelerator::SupportedProfile::SupportedProfile( @@ -180,7 +182,7 @@ bool VideoEncodeAccelerator::IsFlushSupported() { } bool VideoEncodeAccelerator::IsGpuFrameResizeSupported() { -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) // TODO(crbug.com/1166889) Add proper method overrides in // MojoVideoEncodeAccelerator and other subclasses that might return true. return true; @@ -202,6 +204,7 @@ bool operator==(const VideoEncodeAccelerator::SupportedProfile& l, l.max_resolution == r.max_resolution && l.max_framerate_numerator == r.max_framerate_numerator && l.max_framerate_denominator == r.max_framerate_denominator && + l.rate_control_modes == r.rate_control_modes && l.scalability_modes == r.scalability_modes; } diff --git a/chromium/media/video/video_encode_accelerator.h b/chromium/media/video/video_encode_accelerator.h index 8c9e816b306..4711981843d 100644 --- a/chromium/media/video/video_encode_accelerator.h +++ b/chromium/media/video/video_encode_accelerator.h @@ -141,6 +141,13 @@ struct MEDIA_EXPORT BitstreamBufferMetadata final { // Video encoder interface. class MEDIA_EXPORT VideoEncodeAccelerator { public: + // Bitmask values for supported rate control modes. + enum SupportedRateControlMode : uint8_t { + kNoMode = 0, // for uninitialized profiles only + kConstantMode = 0b0001, + kVariableMode = 0b0010, + }; + // Specification of an encoding profile supported by an encoder. struct MEDIA_EXPORT SupportedProfile { SupportedProfile(); @@ -149,6 +156,7 @@ class MEDIA_EXPORT VideoEncodeAccelerator { const gfx::Size& max_resolution, uint32_t max_framerate_numerator = 0u, uint32_t max_framerate_denominator = 1u, + SupportedRateControlMode rc_modes = kConstantMode, const std::vector<SVCScalabilityMode>& scalability_modes = {}); SupportedProfile(const SupportedProfile& other); SupportedProfile& operator=(const SupportedProfile& other) = default; @@ -158,6 +166,7 @@ class MEDIA_EXPORT VideoEncodeAccelerator { gfx::Size max_resolution; uint32_t max_framerate_numerator{0}; uint32_t max_framerate_denominator{0}; + SupportedRateControlMode rate_control_modes = kNoMode; std::vector<SVCScalabilityMode> scalability_modes; }; using SupportedProfiles = std::vector<SupportedProfile>; @@ -445,6 +454,35 @@ MEDIA_EXPORT bool operator==( const VideoEncodeAccelerator::Config::SpatialLayer& r); MEDIA_EXPORT bool operator==(const VideoEncodeAccelerator::Config& l, const VideoEncodeAccelerator::Config& r); + +MEDIA_EXPORT inline VideoEncodeAccelerator::SupportedRateControlMode operator|( + VideoEncodeAccelerator::SupportedRateControlMode lhs, + VideoEncodeAccelerator::SupportedRateControlMode rhs) { + return static_cast<VideoEncodeAccelerator::SupportedRateControlMode>( + static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs)); +} + +MEDIA_EXPORT inline VideoEncodeAccelerator::SupportedRateControlMode& +operator|=(VideoEncodeAccelerator::SupportedRateControlMode& lhs, + VideoEncodeAccelerator::SupportedRateControlMode rhs) { + lhs = lhs | rhs; + return lhs; +} + +MEDIA_EXPORT inline VideoEncodeAccelerator::SupportedRateControlMode operator&( + VideoEncodeAccelerator::SupportedRateControlMode lhs, + VideoEncodeAccelerator::SupportedRateControlMode rhs) { + return static_cast<VideoEncodeAccelerator::SupportedRateControlMode>( + static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs)); +} + +MEDIA_EXPORT inline VideoEncodeAccelerator::SupportedRateControlMode& +operator&=(VideoEncodeAccelerator::SupportedRateControlMode& lhs, + VideoEncodeAccelerator::SupportedRateControlMode rhs) { + lhs = lhs & rhs; + return lhs; +} + } // namespace media namespace std { diff --git a/chromium/media/video/video_encoder_fallback.cc b/chromium/media/video/video_encoder_fallback.cc index 0197d62b32c..12c78924dfd 100644 --- a/chromium/media/video/video_encoder_fallback.cc +++ b/chromium/media/video/video_encoder_fallback.cc @@ -65,6 +65,7 @@ void VideoEncoderFallback::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!init_done_cb_); if (use_fallback_) { if (fallback_initialized_) { diff --git a/chromium/media/video/video_encoder_fallback_test.cc b/chromium/media/video/video_encoder_fallback_test.cc index 8787118373b..36cbecdf2cf 100644 --- a/chromium/media/video/video_encoder_fallback_test.cc +++ b/chromium/media/video/video_encoder_fallback_test.cc @@ -300,18 +300,19 @@ TEST_F(VideoEncoderFallbackTest, SecondaryFailureOnInitialize) { EncoderStatus::Codes::kEncoderUnsupportedCodec); })); - EXPECT_CALL(*main_video_encoder_, Encode(_, _, _)) - .WillRepeatedly( - Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::EncoderStatusCB done_cb) { - RunStatusCallbackAync( - std::move(done_cb), - EncoderStatus::Codes::kEncoderInitializeNeverCompleted); - })); - fallback_encoder_->Initialize( profile, options, std::move(output_cb), ValidatingStatusCB(EncoderStatus::Codes::kEncoderUnsupportedCodec)); + RunLoop(); + + EXPECT_CALL(*secondary_video_encoder_, Encode(_, _, _)) + .Times(kFrameCount) + .WillRepeatedly(Invoke([&, this](scoped_refptr<VideoFrame> frame, + bool key_frame, + VideoEncoder::EncoderStatusCB done_cb) { + RunStatusCallbackAync(std::move(done_cb), + EncoderStatus::Codes::kEncoderUnsupportedCodec); + })); for (int i = 0; i < kFrameCount; i++) { auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, kFrameSize, @@ -329,4 +330,96 @@ TEST_F(VideoEncoderFallbackTest, SecondaryFailureOnInitialize) { EXPECT_TRUE(FallbackHappened()); } +// Test how VideoEncoderFallback reports errors when encoding with the secondary +// encoder. +TEST_F(VideoEncoderFallbackTest, SecondaryFailureOnEncode) { + int outputs = 0; + VideoEncoder::Options options; + VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; + VideoEncoder::OutputCB output_cb = + BindToCurrentLoop(base::BindLambdaForTesting( + [&](VideoEncoderOutput, + absl::optional<VideoEncoder::CodecDescription>) { outputs++; })); + VideoEncoder::OutputCB primary_output_cb; + VideoEncoder::OutputCB secondary_output_cb; + + // Initialize() on the main encoder should succeed + EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _)) + .WillOnce(Invoke([&, this](VideoCodecProfile profile, + const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::EncoderStatusCB done_cb) { + primary_output_cb = std::move(output_cb); + RunStatusCallbackAync(std::move(done_cb)); + })); + + // Initialize() on the second encoder should succeed as well + EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _)) + .WillOnce(Invoke([&, this](VideoCodecProfile profile, + const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::EncoderStatusCB done_cb) { + secondary_output_cb = std::move(output_cb); + RunStatusCallbackAync(std::move(done_cb)); + })); + + // Start failing encodes after half of the frames. + auto encoder_switch_time = base::Seconds(kFrameCount / 2); + EXPECT_CALL(*main_video_encoder_, Encode(_, _, _)) + .WillRepeatedly(Invoke([&, this](scoped_refptr<VideoFrame> frame, + bool key_frame, + VideoEncoder::EncoderStatusCB done_cb) { + EXPECT_TRUE(frame); + EXPECT_TRUE(done_cb); + if (frame->timestamp() > encoder_switch_time) { + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderFailedEncode); + return; + } + + VideoEncoderOutput output; + output.timestamp = frame->timestamp(); + primary_output_cb.Run(std::move(output), {}); + RunStatusCallbackAync(std::move(done_cb)); + })); + + // All encodes should come to the secondary encoder. Again fail encoding + // once we reach 3/4 the total frame count. + auto second_encoder_fail_time = base::Seconds(3 * kFrameCount / 4); + LOG(ERROR) << second_encoder_fail_time << "!!!!"; + EXPECT_CALL(*secondary_video_encoder_, Encode(_, _, _)) + .WillRepeatedly(Invoke([&, this](scoped_refptr<VideoFrame> frame, + bool key_frame, + VideoEncoder::EncoderStatusCB done_cb) { + EXPECT_TRUE(frame); + EXPECT_TRUE(done_cb); + EXPECT_GT(frame->timestamp(), encoder_switch_time); + if (frame->timestamp() > second_encoder_fail_time) { + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderFailedEncode); + return; + } + VideoEncoderOutput output; + output.timestamp = frame->timestamp(); + secondary_output_cb.Run(std::move(output), {}); + RunStatusCallbackAync(std::move(done_cb)); + })); + + fallback_encoder_->Initialize(profile, options, std::move(output_cb), + ValidatingStatusCB()); + RunLoop(); + + for (int i = 1; i <= kFrameCount; i++) { + auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, kFrameSize, + gfx::Rect(kFrameSize), kFrameSize, + base::Seconds(i)); + auto done_cb = + ValidatingStatusCB((frame->timestamp() <= second_encoder_fail_time) + ? EncoderStatus::Codes::kOk + : EncoderStatus::Codes::kEncoderFailedEncode); + fallback_encoder_->Encode(frame, true, std::move(done_cb)); + } + RunLoop(); + EXPECT_TRUE(FallbackHappened()); + EXPECT_EQ(outputs, 3 * kFrameCount / 4); +} + } // namespace media diff --git a/chromium/media/video/vpx_video_encoder.cc b/chromium/media/video/vpx_video_encoder.cc index 5397f6a54b6..2ed71b09323 100644 --- a/chromium/media/video/vpx_video_encoder.cc +++ b/chromium/media/video/vpx_video_encoder.cc @@ -540,7 +540,7 @@ void VpxVideoEncoder::Encode(scoped_refptr<VideoFrame> frame, } } - TRACE_EVENT0("media", "vpx_codec_encode"); + TRACE_EVENT1("media", "vpx_codec_encode", "timestamp", frame->timestamp()); auto vpx_error = vpx_codec_encode(codec_.get(), &vpx_image_, timestamp_us, duration_us, flags, deadline); |