summaryrefslogtreecommitdiff
path: root/chromium/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/video')
-rw-r--r--chromium/media/video/BUILD.gn11
-rw-r--r--chromium/media/video/av1_video_encoder.cc2
-rw-r--r--chromium/media/video/fake_video_encode_accelerator.cc1
-rw-r--r--chromium/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc9
-rw-r--r--chromium/media/video/h264_level_limits.cc1
-rw-r--r--chromium/media/video/h265_parser.cc122
-rw-r--r--chromium/media/video/h265_parser.h37
-rw-r--r--chromium/media/video/h265_poc_unittest.cc393
-rw-r--r--chromium/media/video/openh264_video_encoder.cc3
-rw-r--r--chromium/media/video/picture.cc3
-rw-r--r--chromium/media/video/picture.h7
-rw-r--r--chromium/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc2
-rw-r--r--chromium/media/video/software_video_encoder_test.cc37
-rw-r--r--chromium/media/video/video_encode_accelerator.cc5
-rw-r--r--chromium/media/video/video_encode_accelerator.h38
-rw-r--r--chromium/media/video/video_encoder_fallback.cc1
-rw-r--r--chromium/media/video/video_encoder_fallback_test.cc111
-rw-r--r--chromium/media/video/vpx_video_encoder.cc2
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);