diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-01-04 14:17:57 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-01-05 10:05:06 +0000 |
commit | 39d357e3248f80abea0159765ff39554affb40db (patch) | |
tree | aba0e6bfb76de0244bba0f5fdbd64b830dd6e621 /chromium/third_party/webrtc/common_video | |
parent | 87778abf5a1f89266f37d1321b92a21851d8244d (diff) | |
download | qtwebengine-chromium-39d357e3248f80abea0159765ff39554affb40db.tar.gz |
BASELINE: Update Chromium to 55.0.2883.105
And updates ninja to 1.7.2
Change-Id: I20d43c737f82764d857ada9a55586901b18b9243
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/webrtc/common_video')
29 files changed, 480 insertions, 465 deletions
diff --git a/chromium/third_party/webrtc/common_video/BUILD.gn b/chromium/third_party/webrtc/common_video/BUILD.gn index d8e6bbfe0fe..845a5eb8af7 100644 --- a/chromium/third_party/webrtc/common_video/BUILD.gn +++ b/chromium/third_party/webrtc/common_video/BUILD.gn @@ -7,7 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. import("../build/webrtc.gni") -import("//testing/test.gni") config("common_video_config") { include_dirs = [ @@ -16,7 +15,7 @@ config("common_video_config") { ] } -source_set("common_video") { +rtc_static_library("common_video") { sources = [ "bitrate_adjuster.cc", "h264/h264_common.cc", @@ -44,20 +43,17 @@ source_set("common_video") { include_dirs = [ "../modules/interface" ] - configs += [ "..:common_config" ] - public_configs = [ - "..:common_inherited_config", - ":common_video_config", - ] + public_configs = [ ":common_video_config" ] if (is_clang) { # Suppress warnings from Chrome's Clang plugins. # See http://code.google.com/p/webrtc/issues/detail?id=163 for details. - configs -= [ "//build/config/clang:find_bad_constructs" ] + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] } deps = [ "..:webrtc_common", + "../base:rtc_task_queue", "../system_wrappers", ] @@ -81,7 +77,19 @@ source_set("common_video") { } if (rtc_include_tests) { - test("common_video_unittests") { + common_video_resources = [ "//resources/foreman_cif.yuv" ] + + if (is_ios) { + bundle_data("common_video_unittests_bundle_data") { + testonly = true + sources = common_video_resources + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] + } + } + + rtc_test("common_video_unittests") { testonly = true sources = [ @@ -94,16 +102,13 @@ if (rtc_include_tests) { "libyuv/libyuv_unittest.cc", ] - configs += [ "..:common_config" ] - public_configs = [ "..:common_inherited_config" ] - # TODO(jschuh): Bug 1348: fix this warning. configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] if (is_clang) { # Suppress warnings from the Chromium Clang plugin. # See http://code.google.com/p/webrtc/issues/detail?id=163 for details. - configs -= [ "//build/config/clang:find_bad_constructs" ] + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] } deps = [ @@ -115,14 +120,14 @@ if (rtc_include_tests) { "//testing/gtest", ] + data = common_video_resources if (is_android) { deps += [ "//testing/android/native_test:native_test_support" ] + shard_timeout = 900 + } - # This needs to be kept in sync with the .isolate file. - # TODO(kjellander); Move this to android_assets targets instead. - data = [ - "//resources/foreman_cif.yuv", - ] + if (is_ios) { + deps += [ ":common_video_unittests_bundle_data" ] } } } diff --git a/chromium/third_party/webrtc/common_video/OWNERS b/chromium/third_party/webrtc/common_video/OWNERS index dbce641933c..caafb35fe20 100644 --- a/chromium/third_party/webrtc/common_video/OWNERS +++ b/chromium/third_party/webrtc/common_video/OWNERS @@ -1,13 +1,14 @@ -stefan@webrtc.org -marpan@webrtc.org henrik.lundin@webrtc.org +magjed@webrtc.org +marpan@webrtc.org pbos@webrtc.org +stefan@webrtc.org per-file *.isolate=kjellander@webrtc.org # These are for the common case of adding or renaming files. If you're doing # structural changes, please get a review from a reviewer in this file. +per-file *.gn=* +per-file *.gni=* per-file *.gyp=* per-file *.gypi=* - -per-file BUILD.gn=kjellander@webrtc.org diff --git a/chromium/third_party/webrtc/common_video/bitrate_adjuster_unittest.cc b/chromium/third_party/webrtc/common_video/bitrate_adjuster_unittest.cc index d0517e4fcb3..b6152ac8444 100644 --- a/chromium/third_party/webrtc/common_video/bitrate_adjuster_unittest.cc +++ b/chromium/third_party/webrtc/common_video/bitrate_adjuster_unittest.cc @@ -8,10 +8,9 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "testing/gtest/include/gtest/gtest.h" - #include "webrtc/common_video/include/bitrate_adjuster.h" #include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/test/gtest.h" namespace webrtc { diff --git a/chromium/third_party/webrtc/common_video/common_video.gyp b/chromium/third_party/webrtc/common_video/common_video.gyp index b1f460418a6..eee0c048e73 100644 --- a/chromium/third_party/webrtc/common_video/common_video.gyp +++ b/chromium/third_party/webrtc/common_video/common_video.gyp @@ -18,6 +18,7 @@ 'libyuv/include', ], 'dependencies': [ + '<(webrtc_root)/base/base.gyp:rtc_task_queue', '<(webrtc_root)/common.gyp:webrtc_common', '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], diff --git a/chromium/third_party/webrtc/common_video/common_video_unittests.gyp b/chromium/third_party/webrtc/common_video/common_video_unittests.gyp deleted file mode 100644 index fb7a7431a05..00000000000 --- a/chromium/third_party/webrtc/common_video/common_video_unittests.gyp +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. -# -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file in the root of the source -# tree. An additional intellectual property rights grant can be found -# in the file PATENTS. All contributing project authors may -# be found in the AUTHORS file in the root of the source tree. - -{ - 'includes': ['../build/common.gypi'], - 'targets': [ - { - 'target_name': 'common_video_unittests', - 'type': '<(gtest_target_type)', - 'dependencies': [ - '<(webrtc_root)/common_video/common_video.gyp:common_video', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/test/test.gyp:test_support_main', - '<(webrtc_root)/test/test.gyp:video_test_common', - ], - 'sources': [ - 'bitrate_adjuster_unittest.cc', - 'h264/pps_parser_unittest.cc', - 'h264/sps_parser_unittest.cc', - 'h264/sps_vui_rewriter_unittest.cc', - 'i420_buffer_pool_unittest.cc', - 'i420_video_frame_unittest.cc', - 'libyuv/libyuv_unittest.cc', - ], - # Disable warnings to enable Win64 build, issue 1323. - 'msvs_disabled_warnings': [ - 4267, # size_t to int truncation. - ], - 'conditions': [ - ['OS=="android"', { - 'dependencies': [ - '<(DEPTH)/testing/android/native_test.gyp:native_test_native_code', - ], - }], - ['OS=="ios"', { - 'mac_bundle_resources': [ - '<(DEPTH)/resources/foreman_cif.yuv', - ], - }], - ], - }, - ], # targets - 'conditions': [ - ['OS=="android"', { - 'targets': [ - { - 'target_name': 'common_video_unittests_apk_target', - 'type': 'none', - 'dependencies': [ - '<(android_tests_path):common_video_unittests_apk', - ], - }, - ], - 'conditions': [ - ['test_isolation_mode != "noop"', - { - 'targets': [ - { - 'target_name': 'common_video_unittests_apk_run', - 'type': 'none', - 'dependencies': [ - '<(android_tests_path):common_video_unittests_apk', - ], - 'includes': [ - '../build/isolate.gypi', - ], - 'sources': [ - 'common_video_unittests_apk.isolate', - ], - }, - ], - }, - ], - ], - }], # OS=="android" - ['test_isolation_mode != "noop"', { - 'targets': [ - { - 'target_name': 'common_video_unittests_run', - 'type': 'none', - 'dependencies': [ - 'common_video_unittests', - ], - 'includes': [ - '../build/isolate.gypi', - ], - 'sources': [ - 'common_video_unittests.isolate', - ], - }, - ], - }], - ], -} diff --git a/chromium/third_party/webrtc/common_video/common_video_unittests.isolate b/chromium/third_party/webrtc/common_video/common_video_unittests.isolate deleted file mode 100644 index 72018835008..00000000000 --- a/chromium/third_party/webrtc/common_video/common_video_unittests.isolate +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. -# -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file in the root of the source -# tree. An additional intellectual property rights grant can be found -# in the file PATENTS. All contributing project authors may -# be found in the AUTHORS file in the root of the source tree. -{ - 'conditions': [ - ['OS=="linux" or OS=="mac" or OS=="win" or OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/resources/foreman_cif.yuv', - ], - }, - }], - ['OS=="linux" or OS=="mac" or OS=="win"', { - 'variables': { - 'command': [ - '<(DEPTH)/testing/test_env.py', - '<(PRODUCT_DIR)/common_video_unittests<(EXECUTABLE_SUFFIX)', - ], - 'files': [ - '<(DEPTH)/DEPS', - '<(DEPTH)/testing/test_env.py', - '<(PRODUCT_DIR)/common_video_unittests<(EXECUTABLE_SUFFIX)', - ], - }, - }], - ], -} diff --git a/chromium/third_party/webrtc/common_video/common_video_unittests_apk.isolate b/chromium/third_party/webrtc/common_video/common_video_unittests_apk.isolate deleted file mode 100644 index 36514cdb61c..00000000000 --- a/chromium/third_party/webrtc/common_video/common_video_unittests_apk.isolate +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. -# -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file in the root of the source -# tree. An additional intellectual property rights grant can be found -# in the file PATENTS. All contributing project authors may -# be found in the AUTHORS file in the root of the source tree. -{ - 'includes': [ - '../../build/android/android.isolate', - 'common_video_unittests.isolate', - ], - 'variables': { - 'command': [ - '<(PRODUCT_DIR)/bin/run_common_video_unittests', - '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats', - ], - 'files': [ - '../../build/config/', - '../../third_party/instrumented_libraries/instrumented_libraries.isolate', - '<(PRODUCT_DIR)/common_video_unittests_apk/', - '<(PRODUCT_DIR)/bin/run_common_video_unittests', - 'common_video_unittests.isolate', - ] - } -} diff --git a/chromium/third_party/webrtc/common_video/corevideo_frame_buffer.cc b/chromium/third_party/webrtc/common_video/corevideo_frame_buffer.cc index a58ddc7fbb9..3245bf5e498 100644 --- a/chromium/third_party/webrtc/common_video/corevideo_frame_buffer.cc +++ b/chromium/third_party/webrtc/common_video/corevideo_frame_buffer.cc @@ -35,7 +35,7 @@ CoreVideoFrameBuffer::NativeToI420Buffer() { size_t width = CVPixelBufferGetWidthOfPlane(pixel_buffer_, 0); size_t height = CVPixelBufferGetHeightOfPlane(pixel_buffer_, 0); // TODO(tkchin): Use a frame buffer pool. - rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = + rtc::scoped_refptr<webrtc::I420Buffer> buffer = new rtc::RefCountedObject<webrtc::I420Buffer>(width, height); CVPixelBufferLockBaseAddress(pixel_buffer_, kCVPixelBufferLock_ReadOnly); const uint8_t* src_y = static_cast<const uint8_t*>( diff --git a/chromium/third_party/webrtc/common_video/h264/pps_parser.cc b/chromium/third_party/webrtc/common_video/h264/pps_parser.cc index dd5d63d2461..a48d27bfc7f 100644 --- a/chromium/third_party/webrtc/common_video/h264/pps_parser.cc +++ b/chromium/third_party/webrtc/common_video/h264/pps_parser.cc @@ -10,6 +10,8 @@ #include "webrtc/common_video/h264/pps_parser.h" +#include <memory> + #include "webrtc/common_video/h264/h264_common.h" #include "webrtc/base/bitbuffer.h" #include "webrtc/base/buffer.h" @@ -36,16 +38,47 @@ rtc::Optional<PpsParser::PpsState> PpsParser::ParsePps(const uint8_t* data, return ParseInternal(&bit_buffer); } +bool PpsParser::ParsePpsIds(const uint8_t* data, + size_t length, + uint32_t* pps_id, + uint32_t* sps_id) { + RTC_DCHECK(pps_id); + RTC_DCHECK(sps_id); + // First, parse out rbsp, which is basically the source buffer minus emulation + // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in + // section 7.3.1 of the H.264 standard. + std::unique_ptr<rtc::Buffer> unpacked_buffer = H264::ParseRbsp(data, length); + rtc::BitBuffer bit_buffer(unpacked_buffer->data(), unpacked_buffer->size()); + return ParsePpsIdsInternal(&bit_buffer, pps_id, sps_id); +} + +rtc::Optional<uint32_t> PpsParser::ParsePpsIdFromSlice(const uint8_t* data, + size_t length) { + std::unique_ptr<rtc::Buffer> slice_rbsp(H264::ParseRbsp(data, length)); + rtc::BitBuffer slice_reader(slice_rbsp->data(), slice_rbsp->size()); + + uint32_t golomb_tmp; + // first_mb_in_slice: ue(v) + if (!slice_reader.ReadExponentialGolomb(&golomb_tmp)) + return rtc::Optional<uint32_t>(); + // slice_type: ue(v) + if (!slice_reader.ReadExponentialGolomb(&golomb_tmp)) + return rtc::Optional<uint32_t>(); + // pic_parameter_set_id: ue(v) + uint32_t slice_pps_id; + if (!slice_reader.ReadExponentialGolomb(&slice_pps_id)) + return rtc::Optional<uint32_t>(); + return rtc::Optional<uint32_t>(slice_pps_id); +} + rtc::Optional<PpsParser::PpsState> PpsParser::ParseInternal( rtc::BitBuffer* bit_buffer) { PpsState pps; + RETURN_EMPTY_ON_FAIL(ParsePpsIdsInternal(bit_buffer, &pps.id, &pps.sps_id)); + uint32_t bits_tmp; uint32_t golomb_ignored; - // pic_parameter_set_id: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); - // seq_parameter_set_id: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored)); // entropy_coding_mode_flag: u(1) uint32_t entropy_coding_mode_flag; RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(&entropy_coding_mode_flag, 1)); @@ -145,4 +178,16 @@ rtc::Optional<PpsParser::PpsState> PpsParser::ParseInternal( return rtc::Optional<PpsParser::PpsState>(pps); } +bool PpsParser::ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, + uint32_t* pps_id, + uint32_t* sps_id) { + // pic_parameter_set_id: ue(v) + if (!bit_buffer->ReadExponentialGolomb(pps_id)) + return false; + // seq_parameter_set_id: ue(v) + if (!bit_buffer->ReadExponentialGolomb(sps_id)) + return false; + return true; +} + } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/h264/pps_parser.h b/chromium/third_party/webrtc/common_video/h264/pps_parser.h index f91b65d932f..6c896fe8ea2 100644 --- a/chromium/third_party/webrtc/common_video/h264/pps_parser.h +++ b/chromium/third_party/webrtc/common_video/h264/pps_parser.h @@ -33,15 +33,28 @@ class PpsParser { uint32_t weighted_bipred_idc = false; uint32_t redundant_pic_cnt_present_flag = 0; int pic_init_qp_minus26 = 0; + uint32_t id = 0; + uint32_t sps_id = 0; }; // Unpack RBSP and parse PPS state from the supplied buffer. static rtc::Optional<PpsState> ParsePps(const uint8_t* data, size_t length); + static bool ParsePpsIds(const uint8_t* data, + size_t length, + uint32_t* pps_id, + uint32_t* sps_id); + + static rtc::Optional<uint32_t> ParsePpsIdFromSlice(const uint8_t* data, + size_t length); + protected: // Parse the PPS state, for a bit buffer where RBSP decoding has already been // performed. static rtc::Optional<PpsState> ParseInternal(rtc::BitBuffer* bit_buffer); + static bool ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, + uint32_t* pps_id, + uint32_t* sps_id); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/h264/pps_parser_unittest.cc b/chromium/third_party/webrtc/common_video/h264/pps_parser_unittest.cc index 19834390836..9a650e8be0f 100644 --- a/chromium/third_party/webrtc/common_video/h264/pps_parser_unittest.cc +++ b/chromium/third_party/webrtc/common_video/h264/pps_parser_unittest.cc @@ -11,17 +11,26 @@ #include "webrtc/common_video/h264/pps_parser.h" #include <limits> - -#include "testing/gtest/include/gtest/gtest.h" +#include <memory> #include "webrtc/base/bitbuffer.h" #include "webrtc/base/buffer.h" #include "webrtc/common_video/h264/h264_common.h" +#include "webrtc/test/gtest.h" namespace webrtc { -static const size_t kPpsBufferMaxSize = 256; -static const uint32_t kIgnored = 0; +namespace { +// Contains enough of the image slice to contain slice QP. +const uint8_t kH264BitstreamChunk[] = { + 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x20, 0xda, 0x01, 0x40, 0x16, + 0xe8, 0x06, 0xd0, 0xa1, 0x35, 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x06, + 0xe2, 0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x40, 0xf0, 0x8c, 0x03, 0xf2, + 0x75, 0x67, 0xad, 0x41, 0x64, 0x24, 0x0e, 0xa0, 0xb2, 0x12, 0x1e, 0xf8, +}; +const size_t kPpsBufferMaxSize = 256; +const uint32_t kIgnored = 0; +} // namespace void WritePps(const PpsParser::PpsState& pps, int slice_group_map_type, @@ -32,9 +41,9 @@ void WritePps(const PpsParser::PpsState& pps, rtc::BitBufferWriter bit_buffer(data, kPpsBufferMaxSize); // pic_parameter_set_id: ue(v) - bit_buffer.WriteExponentialGolomb(kIgnored); + bit_buffer.WriteExponentialGolomb(pps.id); // seq_parameter_set_id: ue(v) - bit_buffer.WriteExponentialGolomb(kIgnored); + bit_buffer.WriteExponentialGolomb(pps.sps_id); // entropy_coding_mode_flag: u(1) bit_buffer.WriteBits(kIgnored, 1); // bottom_field_pic_order_in_frame_present_flag: u(1) @@ -175,6 +184,8 @@ class PpsParserTest : public ::testing::Test { EXPECT_EQ(pps.redundant_pic_cnt_present_flag, parsed_pps_->redundant_pic_cnt_present_flag); EXPECT_EQ(pps.pic_init_qp_minus26, parsed_pps_->pic_init_qp_minus26); + EXPECT_EQ(pps.id, parsed_pps_->id); + EXPECT_EQ(pps.sps_id, parsed_pps_->sps_id); } PpsParser::PpsState generated_pps_; @@ -192,10 +203,19 @@ TEST_F(PpsParserTest, MaxPps) { generated_pps_.redundant_pic_cnt_present_flag = 1; // 1 bit value. generated_pps_.weighted_bipred_idc = (1 << 2) - 1; // 2 bit value. generated_pps_.weighted_pred_flag = true; + generated_pps_.id = 2; + generated_pps_.sps_id = 1; RunTest(); generated_pps_.pic_init_qp_minus26 = std::numeric_limits<int32_t>::min() + 1; RunTest(); } +TEST_F(PpsParserTest, PpsIdFromSlice) { + rtc::Optional<uint32_t> pps_id = PpsParser::ParsePpsIdFromSlice( + kH264BitstreamChunk, sizeof(kH264BitstreamChunk)); + ASSERT_TRUE(pps_id); + EXPECT_EQ(2u, *pps_id); +} + } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/h264/sps_parser.cc b/chromium/third_party/webrtc/common_video/h264/sps_parser.cc index cf4b36d1238..86a39de83f5 100644 --- a/chromium/third_party/webrtc/common_video/h264/sps_parser.cc +++ b/chromium/third_party/webrtc/common_video/h264/sps_parser.cc @@ -10,6 +10,8 @@ #include "webrtc/common_video/h264/sps_parser.h" +#include <memory> + #include "webrtc/common_video/h264/h264_common.h" #include "webrtc/base/bitbuffer.h" #include "webrtc/base/bytebuffer.h" @@ -68,7 +70,7 @@ rtc::Optional<SpsParser::SpsState> SpsParser::ParseSpsUpToVui( // level_idc: u(8) RETURN_EMPTY_ON_FAIL(buffer->ConsumeBytes(1)); // seq_parameter_set_id: ue(v) - RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&golomb_ignored)); + RETURN_EMPTY_ON_FAIL(buffer->ReadExponentialGolomb(&sps.id)); sps.separate_colour_plane_flag = 0; // See if profile_idc has chroma format information. if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || diff --git a/chromium/third_party/webrtc/common_video/h264/sps_parser.h b/chromium/third_party/webrtc/common_video/h264/sps_parser.h index d04d9a0f1c8..8b0fff53ce3 100644 --- a/chromium/third_party/webrtc/common_video/h264/sps_parser.h +++ b/chromium/third_party/webrtc/common_video/h264/sps_parser.h @@ -38,6 +38,7 @@ class SpsParser { uint32_t pic_order_cnt_type = 0; uint32_t max_num_ref_frames = 0; uint32_t vui_params_present = 0; + uint32_t id = 0; }; // Unpack RBSP and parse SPS state from the supplied buffer. diff --git a/chromium/third_party/webrtc/common_video/h264/sps_parser_unittest.cc b/chromium/third_party/webrtc/common_video/h264/sps_parser_unittest.cc index 60e55d2c622..958ddc05eb3 100644 --- a/chromium/third_party/webrtc/common_video/h264/sps_parser_unittest.cc +++ b/chromium/third_party/webrtc/common_video/h264/sps_parser_unittest.cc @@ -10,12 +10,11 @@ #include "webrtc/common_video/h264/sps_parser.h" -#include "testing/gtest/include/gtest/gtest.h" - #include "webrtc/base/arraysize.h" #include "webrtc/base/bitbuffer.h" #include "webrtc/base/buffer.h" #include "webrtc/common_video/h264/h264_common.h" +#include "webrtc/test/gtest.h" namespace webrtc { @@ -41,7 +40,10 @@ static const size_t kSpsBufferMaxSize = 256; // The fake SPS that this generates also always has at least one emulation byte // at offset 2, since the first two bytes are always 0, and has a 0x3 as the // level_idc, to make sure the parser doesn't eat all 0x3 bytes. -void GenerateFakeSps(uint16_t width, uint16_t height, rtc::Buffer* out_buffer) { +void GenerateFakeSps(uint16_t width, + uint16_t height, + int id, + rtc::Buffer* out_buffer) { uint8_t rbsp[kSpsBufferMaxSize] = {0}; rtc::BitBufferWriter writer(rbsp, kSpsBufferMaxSize); // Profile byte. @@ -51,7 +53,7 @@ void GenerateFakeSps(uint16_t width, uint16_t height, rtc::Buffer* out_buffer) { // level_idc. writer.WriteUInt8(0x3u); // seq_paramter_set_id. - writer.WriteExponentialGolomb(0); + writer.WriteExponentialGolomb(id); // Profile is not special, so we skip all the chroma format settings. // Now some bit magic. @@ -151,20 +153,22 @@ TEST_F(H264SpsParserTest, TestSampleSPSWeirdResolution) { TEST_F(H264SpsParserTest, TestSyntheticSPSQvgaLandscape) { rtc::Buffer buffer; - GenerateFakeSps(320u, 180u, &buffer); + GenerateFakeSps(320u, 180u, 1, &buffer); EXPECT_TRUE(static_cast<bool>( sps_ = SpsParser::ParseSps(buffer.data(), buffer.size()))); EXPECT_EQ(320u, sps_->width); EXPECT_EQ(180u, sps_->height); + EXPECT_EQ(1u, sps_->id); } TEST_F(H264SpsParserTest, TestSyntheticSPSWeirdResolution) { rtc::Buffer buffer; - GenerateFakeSps(156u, 122u, &buffer); + GenerateFakeSps(156u, 122u, 2, &buffer); EXPECT_TRUE(static_cast<bool>( sps_ = SpsParser::ParseSps(buffer.data(), buffer.size()))); EXPECT_EQ(156u, sps_->width); EXPECT_EQ(122u, sps_->height); + EXPECT_EQ(2u, sps_->id); } } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter.cc b/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter.cc index 447221327d4..c5b9b706dff 100644 --- a/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter.cc +++ b/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter.cc @@ -72,7 +72,10 @@ SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( size_t length, rtc::Optional<SpsParser::SpsState>* sps, rtc::Buffer* destination) { - rtc::BitBuffer source_buffer(buffer, length); + // Create temporary RBSP decoded buffer of the payload (exlcuding the + // leading nalu type header byte (the SpsParser uses only the payload). + std::unique_ptr<rtc::Buffer> rbsp_buffer = H264::ParseRbsp(buffer, length); + rtc::BitBuffer source_buffer(rbsp_buffer->data(), rbsp_buffer->size()); rtc::Optional<SpsParser::SpsState> sps_state = SpsParser::ParseSpsUpToVui(&source_buffer); if (!sps_state) @@ -94,7 +97,7 @@ SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( size_t byte_offset; size_t bit_offset; source_buffer.GetCurrentOffset(&byte_offset, &bit_offset); - memcpy(out_buffer.data(), buffer, + memcpy(out_buffer.data(), rbsp_buffer->data(), byte_offset + (bit_offset > 0 ? 1 : 0)); // OK to copy the last bits. // SpsParser will have read the vui_params_present flag, which we want to diff --git a/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter_unittest.cc b/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter_unittest.cc index 6c8baee9018..711a8365df9 100644 --- a/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter_unittest.cc +++ b/chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter_unittest.cc @@ -10,17 +10,15 @@ #include <vector> -#include "testing/gtest/include/gtest/gtest.h" - #include "webrtc/base/bitbuffer.h" #include "webrtc/base/buffer.h" #include "webrtc/base/fileutils.h" #include "webrtc/base/logging.h" #include "webrtc/base/pathutils.h" #include "webrtc/base/stream.h" - -#include "webrtc/common_video/h264/sps_vui_rewriter.h" #include "webrtc/common_video/h264/h264_common.h" +#include "webrtc/common_video/h264/sps_vui_rewriter.h" +#include "webrtc/test/gtest.h" namespace webrtc { @@ -164,12 +162,11 @@ void TestSps(SpsMode mode, SpsVuiRewriter::ParseResult expected_parse_result) { index.payload_start_offset += H264::kNaluTypeSize; index.payload_size -= H264::kNaluTypeSize; - std::unique_ptr<rtc::Buffer> rbsp_decoded = - H264::ParseRbsp(&buffer[index.payload_start_offset], index.payload_size); rtc::Optional<SpsParser::SpsState> sps; rtc::Buffer out_buffer; - SpsVuiRewriter::ParseResult result = SpsVuiRewriter::ParseAndRewriteSps( - rbsp_decoded->data(), rbsp_decoded->size(), &sps, &out_buffer); + SpsVuiRewriter::ParseResult result = + SpsVuiRewriter::ParseAndRewriteSps(&buffer[index.payload_start_offset], + index.payload_size, &sps, &out_buffer); EXPECT_EQ(expected_parse_result, result); } diff --git a/chromium/third_party/webrtc/common_video/i420_buffer_pool.cc b/chromium/third_party/webrtc/common_video/i420_buffer_pool.cc index bdc0e821c60..aa9c32ecd04 100644 --- a/chromium/third_party/webrtc/common_video/i420_buffer_pool.cc +++ b/chromium/third_party/webrtc/common_video/i420_buffer_pool.cc @@ -14,19 +14,18 @@ namespace webrtc { -I420BufferPool::I420BufferPool(bool zero_initialize) - : zero_initialize_(zero_initialize) { - thread_checker_.DetachFromThread(); -} +I420BufferPool::I420BufferPool(bool zero_initialize, + size_t max_number_of_buffers) + : zero_initialize_(zero_initialize), + max_number_of_buffers_(max_number_of_buffers) {} void I420BufferPool::Release() { - thread_checker_.DetachFromThread(); buffers_.clear(); } rtc::scoped_refptr<I420Buffer> I420BufferPool::CreateBuffer(int width, int height) { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); + RTC_DCHECK_RUNS_SERIALIZED(&race_checker_); // Release buffers with wrong resolution. for (auto it = buffers_.begin(); it != buffers_.end();) { if ((*it)->width() != width || (*it)->height() != height) @@ -43,6 +42,9 @@ rtc::scoped_refptr<I420Buffer> I420BufferPool::CreateBuffer(int width, if (buffer->HasOneRef()) return buffer; } + + if (buffers_.size() >= max_number_of_buffers_) + return nullptr; // Allocate new buffer. rtc::scoped_refptr<PooledI420Buffer> buffer = new PooledI420Buffer(width, height); diff --git a/chromium/third_party/webrtc/common_video/i420_buffer_pool_unittest.cc b/chromium/third_party/webrtc/common_video/i420_buffer_pool_unittest.cc index 3e795dbdc4b..a4dda0c60e8 100644 --- a/chromium/third_party/webrtc/common_video/i420_buffer_pool_unittest.cc +++ b/chromium/third_party/webrtc/common_video/i420_buffer_pool_unittest.cc @@ -10,8 +10,8 @@ #include <string> -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_video/include/i420_buffer_pool.h" +#include "webrtc/test/gtest.h" namespace webrtc { @@ -52,7 +52,7 @@ TEST(TestI420BufferPool, FailToReuse) { } TEST(TestI420BufferPool, FrameValidAfterPoolDestruction) { - rtc::scoped_refptr<VideoFrameBuffer> buffer; + rtc::scoped_refptr<I420Buffer> buffer; { I420BufferPool pool; buffer = pool.CreateBuffer(16, 16); @@ -63,4 +63,11 @@ TEST(TestI420BufferPool, FrameValidAfterPoolDestruction) { memset(buffer->MutableDataY(), 0xA5, 16 * buffer->StrideY()); } +TEST(TestI420BufferPool, MaxNumberOfBuffers) { + I420BufferPool pool(false, 1); + rtc::scoped_refptr<VideoFrameBuffer> buffer1 = pool.CreateBuffer(16, 16); + EXPECT_NE(nullptr, buffer1.get()); + EXPECT_EQ(nullptr, pool.CreateBuffer(16, 16).get()); +} + } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/i420_video_frame_unittest.cc b/chromium/third_party/webrtc/common_video/i420_video_frame_unittest.cc index 406dbd3b9e8..a0146e5455e 100644 --- a/chromium/third_party/webrtc/common_video/i420_video_frame_unittest.cc +++ b/chromium/third_party/webrtc/common_video/i420_video_frame_unittest.cc @@ -11,22 +11,16 @@ #include <math.h> #include <string.h> -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/bind.h" #include "webrtc/test/fake_texture_frame.h" #include "webrtc/test/frame_utils.h" +#include "webrtc/test/gtest.h" #include "webrtc/video_frame.h" namespace webrtc { namespace { -int ExpectedSize(int plane_stride, int image_height, PlaneType type) { - if (type == kYPlane) - return plane_stride * image_height; - return plane_stride * ((image_height + 1) / 2); -} - rtc::scoped_refptr<I420Buffer> CreateGradient(int width, int height) { rtc::scoped_refptr<I420Buffer> buffer( I420Buffer::Create(width, height)); @@ -110,22 +104,6 @@ TEST(TestVideoFrame, WidthHeightValues) { EXPECT_EQ(789, frame.render_time_ms()); } -TEST(TestVideoFrame, SizeAllocation) { - VideoFrame frame; - frame. CreateEmptyFrame(10, 10, 12, 14, 220); - int height = frame.height(); - int stride_y = frame.video_frame_buffer()->StrideY(); - int stride_u = frame.video_frame_buffer()->StrideU(); - int stride_v = frame.video_frame_buffer()->StrideV(); - // Verify that allocated size was computed correctly. - EXPECT_EQ(ExpectedSize(stride_y, height, kYPlane), - frame.allocated_size(kYPlane)); - EXPECT_EQ(ExpectedSize(stride_u, height, kUPlane), - frame.allocated_size(kUPlane)); - EXPECT_EQ(ExpectedSize(stride_v, height, kVPlane), - frame.allocated_size(kVPlane)); -} - TEST(TestVideoFrame, CopyFrame) { uint32_t timestamp = 1; int64_t ntp_time_ms = 2; @@ -162,16 +140,14 @@ TEST(TestVideoFrame, CopyFrame) { EXPECT_EQ(kRotation, small_frame.rotation()); // Frame of larger dimensions. - small_frame.CreateEmptyFrame(width, height, - stride_y, stride_u, stride_v); - memset(small_frame.video_frame_buffer()->MutableDataY(), 1, - small_frame.allocated_size(kYPlane)); - memset(small_frame.video_frame_buffer()->MutableDataU(), 2, - small_frame.allocated_size(kUPlane)); - memset(small_frame.video_frame_buffer()->MutableDataV(), 3, - small_frame.allocated_size(kVPlane)); - big_frame.CopyFrame(small_frame); - EXPECT_TRUE(test::FramesEqual(small_frame, big_frame)); + rtc::scoped_refptr<I420Buffer> buffer = + I420Buffer::Create(width, height, stride_y, stride_u, stride_v); + memset(buffer->MutableDataY(), 1, width * height); + memset(buffer->MutableDataU(), 2, ((height + 1) / 2) * stride_u); + memset(buffer->MutableDataV(), 3, ((height + 1) / 2) * stride_u); + VideoFrame other_frame(buffer, 0, 0, webrtc::kVideoRotation_0); + big_frame.CopyFrame(other_frame); + EXPECT_TRUE(test::FramesEqual(other_frame, big_frame)); } TEST(TestVideoFrame, ShallowCopy) { @@ -256,11 +232,6 @@ TEST(TestVideoFrame, CopyBuffer) { stride_uv, 8, 8)); EXPECT_TRUE(test::EqualPlane(buffer_v, frame2.video_frame_buffer()->DataV(), stride_uv, 8, 8)); - - // Compare size. - EXPECT_LE(kSizeY, frame2.allocated_size(kYPlane)); - EXPECT_LE(kSizeUv, frame2.allocated_size(kUPlane)); - EXPECT_LE(kSizeUv, frame2.allocated_size(kVPlane)); } TEST(TestVideoFrame, FailToReuseAllocation) { diff --git a/chromium/third_party/webrtc/common_video/include/i420_buffer_pool.h b/chromium/third_party/webrtc/common_video/include/i420_buffer_pool.h index 1465ddf4ecd..53950945c2b 100644 --- a/chromium/third_party/webrtc/common_video/include/i420_buffer_pool.h +++ b/chromium/third_party/webrtc/common_video/include/i420_buffer_pool.h @@ -12,8 +12,9 @@ #define WEBRTC_COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_ #include <list> +#include <limits> -#include "webrtc/base/thread_checker.h" +#include "webrtc/base/race_checker.h" #include "webrtc/common_video/include/video_frame_buffer.h" namespace webrtc { @@ -23,13 +24,19 @@ namespace webrtc { // When the I420Buffer is destructed, the memory is returned to the pool for use // by subsequent calls to CreateBuffer. If the resolution passed to CreateBuffer // changes, old buffers will be purged from the pool. +// Note that CreateBuffer will crash if more than kMaxNumberOfFramesBeforeCrash +// are created. This is to prevent memory leaks where frames are not returned. class I420BufferPool { public: - I420BufferPool() : I420BufferPool(false) {} - explicit I420BufferPool(bool zero_initialize); + I420BufferPool() + : I420BufferPool(false, std::numeric_limits<size_t>::max()) {} + explicit I420BufferPool(bool zero_initialize) + : I420BufferPool(zero_initialize, std::numeric_limits<size_t>::max()) {} + I420BufferPool(bool zero_initialze, size_t max_number_of_buffers); - // Returns a buffer from the pool, or creates a new buffer if no suitable - // buffer exists in the pool. + // Returns a buffer from the pool. If no suitable buffer exist in the pool + // and there are less than |max_number_of_buffers| pending, a buffer is + // created. Returns null otherwise. rtc::scoped_refptr<I420Buffer> CreateBuffer(int width, int height); // Clears buffers_ and detaches the thread checker so that it can be reused // later from another thread. @@ -40,7 +47,7 @@ class I420BufferPool { // needed by the pool to check exclusive access. using PooledI420Buffer = rtc::RefCountedObject<I420Buffer>; - rtc::ThreadChecker thread_checker_; + rtc::RaceChecker race_checker_; std::list<rtc::scoped_refptr<PooledI420Buffer>> buffers_; // If true, newly allocated buffers are zero-initialized. Note that recycled // buffers are not zero'd before reuse. This is required of buffers used by @@ -48,6 +55,8 @@ class I420BufferPool { // initial allocation (as shown by FFmpeg's own buffer allocation code). It // has to do with "Use-of-uninitialized-value" on "Linux_msan_chrome". bool zero_initialize_; + // Max number of buffers this pool can have pending. + size_t max_number_of_buffers_; }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/include/incoming_video_stream.h b/chromium/third_party/webrtc/common_video/include/incoming_video_stream.h index a23ac05e9d5..250bed8dbfa 100644 --- a/chromium/third_party/webrtc/common_video/include/incoming_video_stream.h +++ b/chromium/third_party/webrtc/common_video/include/incoming_video_stream.h @@ -15,6 +15,7 @@ #include "webrtc/base/criticalsection.h" #include "webrtc/base/platform_thread.h" +#include "webrtc/base/race_checker.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/base/thread_checker.h" #include "webrtc/common_video/video_render_frames.h" @@ -42,6 +43,7 @@ class IncomingVideoStream : public rtc::VideoSinkInterface<VideoFrame> { rtc::ThreadChecker main_thread_checker_; rtc::ThreadChecker render_thread_checker_; + rtc::RaceChecker decoder_race_checker_; rtc::CriticalSection buffer_critsect_; rtc::PlatformThread incoming_render_thread_; diff --git a/chromium/third_party/webrtc/common_video/include/video_frame_buffer.h b/chromium/third_party/webrtc/common_video/include/video_frame_buffer.h index 94b3d5d8330..fb867bc4282 100644 --- a/chromium/third_party/webrtc/common_video/include/video_frame_buffer.h +++ b/chromium/third_party/webrtc/common_video/include/video_frame_buffer.h @@ -18,17 +18,11 @@ #include "webrtc/base/callback.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/common_video/rotation.h" #include "webrtc/system_wrappers/include/aligned_malloc.h" namespace webrtc { -enum PlaneType { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kNumOfPlanes = 3, -}; - // Interface of a simple frame buffer containing pixel data. This interface does // not contain any frame metadata such as rotation, timestamp, pixel_width, etc. class VideoFrameBuffer : public rtc::RefCountInterface { @@ -44,12 +38,6 @@ class VideoFrameBuffer : public rtc::RefCountInterface { virtual const uint8_t* DataU() const = 0; virtual const uint8_t* DataV() const = 0; - // TODO(nisse): Move MutableData methods to the I420Buffer subclass. - // Non-const data access. - virtual uint8_t* MutableDataY(); - virtual uint8_t* MutableDataU(); - virtual uint8_t* MutableDataV(); - // Returns the number of bytes between successive rows for a given plane. virtual int StrideY() const = 0; virtual int StrideU() const = 0; @@ -97,9 +85,9 @@ class I420Buffer : public VideoFrameBuffer { const uint8_t* DataU() const override; const uint8_t* DataV() const override; - uint8_t* MutableDataY() override; - uint8_t* MutableDataU() override; - uint8_t* MutableDataV() override; + uint8_t* MutableDataY(); + uint8_t* MutableDataU(); + uint8_t* MutableDataV(); int StrideY() const override; int StrideU() const override; int StrideV() const override; @@ -130,6 +118,13 @@ class I420Buffer : public VideoFrameBuffer { static rtc::scoped_refptr<I420Buffer> CopyKeepStride( const rtc::scoped_refptr<VideoFrameBuffer>& buffer); + // Returns a rotated versions of |src|. Native buffers are not + // supported. The reason this function doesn't return an I420Buffer, + // is that it returns |src| unchanged in case |rotation| is zero. + static rtc::scoped_refptr<VideoFrameBuffer> Rotate( + const rtc::scoped_refptr<VideoFrameBuffer>& src, + VideoRotation rotation); + protected: ~I420Buffer() override; diff --git a/chromium/third_party/webrtc/common_video/incoming_video_stream.cc b/chromium/third_party/webrtc/common_video/incoming_video_stream.cc index 2ab3e84453a..ed7b9ea29d8 100644 --- a/chromium/third_party/webrtc/common_video/incoming_video_stream.cc +++ b/chromium/third_party/webrtc/common_video/incoming_video_stream.cc @@ -49,9 +49,7 @@ IncomingVideoStream::~IncomingVideoStream() { } void IncomingVideoStream::OnFrame(const VideoFrame& video_frame) { - // Most of the time we'll be on a decoder thread here, but when using - // VideoToolbox on iOS, we'll get called on a thread from a thread pool. - + RTC_CHECK_RUNS_SERIALIZED(&decoder_race_checker_); // Hand over or insert frame. rtc::CritScope csB(&buffer_critsect_); if (render_buffers_->AddFrame(video_frame) == 1) { diff --git a/chromium/third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h b/chromium/third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h index ec3720e442b..f8cd4702099 100644 --- a/chromium/third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h +++ b/chromium/third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h @@ -16,6 +16,7 @@ #define WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_ #include <stdio.h> +#include <vector> #include "webrtc/common_types.h" // RawVideoTypes. #include "webrtc/common_video/rotation.h" @@ -68,6 +69,7 @@ size_t CalcBufferSize(VideoType type, int width, int height); // already open for writing. // Return value: 0 if OK, < 0 otherwise. int PrintVideoFrame(const VideoFrame& frame, FILE* file); +int PrintVideoFrame(const VideoFrameBuffer& frame, FILE* file); // Extract buffer from VideoFrame or VideoFrameBuffer (consecutive // planes, no stride) @@ -91,9 +93,13 @@ int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer); // - sample_size : Required only for the parsing of MJPG (set to 0 else). // - rotate : Rotation mode of output image. // Output: -// - dst_frame : Reference to a destination frame. +// - dst_buffer : Reference to a destination frame buffer. // Return value: 0 if OK, < 0 otherwise. +// TODO(nisse): Delete this wrapper, and let users call libyuv directly. Most +// calls pass |src_video_type| == kI420, and should use libyuv::I420Copy. The +// only exception at the time of this writing is +// VideoCaptureImpl::IncomingFrame, which still needs libyuv::ConvertToI420. int ConvertToI420(VideoType src_video_type, const uint8_t* src_frame, int crop_x, @@ -102,7 +108,7 @@ int ConvertToI420(VideoType src_video_type, int src_height, size_t sample_size, VideoRotation rotation, - VideoFrame* dst_frame); + I420Buffer* dst_buffer); // Convert From I420 // Input: @@ -120,8 +126,29 @@ int ConvertFromI420(const VideoFrame& src_frame, // Compute PSNR for an I420 frame (all planes). // Returns the PSNR in decibel, to a maximum of kInfinitePSNR. double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame); +double I420PSNR(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer); + // Compute SSIM for an I420 frame (all planes). double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame); +double I420SSIM(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer); + +// Helper class for directly converting and scaling NV12 to I420. The Y-plane +// will be scaled directly to the I420 destination, which makes this faster +// than separate NV12->I420 + I420->I420 scaling. +class NV12ToI420Scaler { + public: + void NV12ToI420Scale(const uint8_t* src_y, int src_stride_y, + const uint8_t* src_uv, int src_stride_uv, + int src_width, int src_height, + uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_u, int dst_stride_u, + uint8_t* dst_v, int dst_stride_v, + int dst_width, int dst_height); + private: + std::vector<uint8_t> tmp_uv_planes_; +}; } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/libyuv/libyuv_unittest.cc b/chromium/third_party/webrtc/common_video/libyuv/libyuv_unittest.cc index ab36559ba55..1ed72df584f 100644 --- a/chromium/third_party/webrtc/common_video/libyuv/libyuv_unittest.cc +++ b/chromium/third_party/webrtc/common_video/libyuv/libyuv_unittest.cc @@ -13,8 +13,9 @@ #include <memory> -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" +#include "webrtc/test/frame_utils.h" +#include "webrtc/test/gtest.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/video_frame.h" @@ -35,8 +36,7 @@ class TestLibYuv : public ::testing::Test { virtual void TearDown(); FILE* source_file_; - VideoFrame orig_frame_; - std::unique_ptr<uint8_t[]> orig_buffer_; + std::unique_ptr<VideoFrame> orig_frame_; const int width_; const int height_; const int size_y_; @@ -51,9 +51,7 @@ TestLibYuv::TestLibYuv() height_(288), size_y_(width_ * height_), size_uv_(((width_ + 1) / 2) * ((height_ + 1) / 2)), - frame_length_(CalcBufferSize(kI420, 352, 288)) { - orig_buffer_.reset(new uint8_t[frame_length_]); -} + frame_length_(CalcBufferSize(kI420, 352, 288)) {} void TestLibYuv::SetUp() { const std::string input_file_name = webrtc::test::ResourcePath("foreman_cif", @@ -62,16 +60,10 @@ void TestLibYuv::SetUp() { ASSERT_TRUE(source_file_ != NULL) << "Cannot read file: "<< input_file_name << "\n"; - EXPECT_EQ(frame_length_, - fread(orig_buffer_.get(), 1, frame_length_, source_file_)); - orig_frame_.CreateFrame(orig_buffer_.get(), - orig_buffer_.get() + size_y_, - orig_buffer_.get() + - size_y_ + size_uv_, - width_, height_, - width_, (width_ + 1) / 2, - (width_ + 1) / 2, - kVideoRotation_0); + rtc::scoped_refptr<VideoFrameBuffer> buffer( + test::ReadI420Buffer(width_, height_, source_file_)); + + orig_frame_.reset(new VideoFrame(buffer, kVideoRotation_0, 0)); } void TestLibYuv::TearDown() { @@ -95,21 +87,20 @@ TEST_F(TestLibYuv, ConvertTest) { double psnr = 0.0; - VideoFrame res_i420_frame; - res_i420_frame.CreateEmptyFrame(width_, height_, width_, - (width_ + 1) / 2, - (width_ + 1) / 2); + rtc::scoped_refptr<I420Buffer> res_i420_buffer = I420Buffer::Create( + width_, height_, width_, (width_ + 1) / 2, (width_ + 1) / 2); + printf("\nConvert #%d I420 <-> I420 \n", j); std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kI420, 0, - out_i420_buffer.get())); + EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kI420, 0, out_i420_buffer.get())); EXPECT_EQ(0, ConvertToI420(kI420, out_i420_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); + height_, 0, kVideoRotation_0, + res_i420_buffer.get())); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); EXPECT_EQ(48.0, psnr); j++; @@ -119,17 +110,18 @@ TEST_F(TestLibYuv, ConvertTest) { int stride_y = 0; int stride_uv = 0; Calc16ByteAlignedStride(width_, &stride_y, &stride_uv); - res_i420_frame.CreateEmptyFrame(width_, height_, stride_y, - stride_uv, stride_uv); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kRGB24, 0, res_rgb_buffer2.get())); + res_i420_buffer = + I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv); + EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kRGB24, 0, res_rgb_buffer2.get())); EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); + height_, 0, kVideoRotation_0, + res_i420_buffer.get())); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); // Optimization Speed- quality trade-off => 45 dB only (platform dependant). EXPECT_GT(ceil(psnr), 44); @@ -137,44 +129,47 @@ TEST_F(TestLibYuv, ConvertTest) { printf("\nConvert #%d I420 <-> UYVY\n", j); std::unique_ptr<uint8_t[]> out_uyvy_buffer(new uint8_t[width_ * height_ * 2]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kUYVY, 0, out_uyvy_buffer.get())); + EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kUYVY, 0, out_uyvy_buffer.get())); EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + height_, 0, kVideoRotation_0, + res_i420_buffer.get())); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); EXPECT_EQ(48.0, psnr); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } j++; printf("\nConvert #%d I420 <-> YUY2\n", j); std::unique_ptr<uint8_t[]> out_yuy2_buffer(new uint8_t[width_ * height_ * 2]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kYUY2, 0, out_yuy2_buffer.get())); + EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kYUY2, 0, out_yuy2_buffer.get())); EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); + height_, 0, + kVideoRotation_0, res_i420_buffer.get())); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); EXPECT_EQ(48.0, psnr); + printf("\nConvert #%d I420 <-> RGB565\n", j); std::unique_ptr<uint8_t[]> out_rgb565_buffer( new uint8_t[width_ * height_ * 2]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kRGB565, 0, - out_rgb565_buffer.get())); + EXPECT_EQ(0, + ConvertFromI420(*orig_frame_, kRGB565, 0, out_rgb565_buffer.get())); EXPECT_EQ(0, ConvertToI420(kRGB565, out_rgb565_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); - - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + height_, 0, + kVideoRotation_0, res_i420_buffer.get())); + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } j++; - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); // TODO(leozwang) Investigate the right psnr should be set for I420ToRGB565, // Another example is I420ToRGB24, the psnr is 44 // TODO(mikhal): Add psnr for RGB565, 1555, 4444, convert to ARGB. @@ -183,18 +178,20 @@ TEST_F(TestLibYuv, ConvertTest) { printf("\nConvert #%d I420 <-> ARGB8888\n", j); std::unique_ptr<uint8_t[]> out_argb8888_buffer( new uint8_t[width_ * height_ * 4]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kARGB, 0, - out_argb8888_buffer.get())); + EXPECT_EQ(0, + ConvertFromI420(*orig_frame_, kARGB, 0, out_argb8888_buffer.get())); EXPECT_EQ(0, ConvertToI420(kARGB, out_argb8888_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); + height_, 0, kVideoRotation_0, + res_i420_buffer.get())); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } - psnr = I420PSNR(&orig_frame_, &res_i420_frame); - // TODO(leozwang) Investigate the right psnr should be set for I420ToARGB8888, + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); + // TODO(leozwang) Investigate the right psnr should be set for + // I420ToARGB8888, EXPECT_GT(ceil(psnr), 42); ASSERT_EQ(0, fclose(output_file)); @@ -209,49 +206,51 @@ TEST_F(TestLibYuv, ConvertAlignedFrame) { double psnr = 0.0; - VideoFrame res_i420_frame; int stride_y = 0; int stride_uv = 0; Calc16ByteAlignedStride(width_, &stride_y, &stride_uv); - res_i420_frame.CreateEmptyFrame(width_, height_, - stride_y, stride_uv, stride_uv); + + rtc::scoped_refptr<I420Buffer> res_i420_buffer = + I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv); std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]); - EXPECT_EQ(0, ConvertFromI420(orig_frame_, kI420, 0, + EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kI420, 0, out_i420_buffer.get())); EXPECT_EQ(0, ConvertToI420(kI420, out_i420_buffer.get(), 0, 0, width_, - height_, 0, kVideoRotation_0, &res_i420_frame)); + height_, 0, kVideoRotation_0, + res_i420_buffer.get())); - if (PrintVideoFrame(res_i420_frame, output_file) < 0) { + if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { return; } - psnr = I420PSNR(&orig_frame_, &res_i420_frame); + psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); EXPECT_EQ(48.0, psnr); } - TEST_F(TestLibYuv, RotateTest) { - // Use ConvertToI420 for multiple roatations - see that nothing breaks, all + // Use ConvertToI420 for multiple rotations - see that nothing breaks, all // memory is properly allocated and end result is equal to the starting point. - VideoFrame rotated_res_i420_frame; int rotated_width = height_; int rotated_height = width_; int stride_y; int stride_uv; + + // Assume compact layout, no padding. + const uint8_t *orig_buffer = orig_frame_->video_frame_buffer()->DataY(); + Calc16ByteAlignedStride(rotated_width, &stride_y, &stride_uv); - rotated_res_i420_frame.CreateEmptyFrame(rotated_width, - rotated_height, - stride_y, - stride_uv, - stride_uv); - EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer_.get(), 0, 0, width_, height_, - 0, kVideoRotation_90, &rotated_res_i420_frame)); - EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer_.get(), 0, 0, width_, height_, - 0, kVideoRotation_270, &rotated_res_i420_frame)); - rotated_res_i420_frame.CreateEmptyFrame(width_, height_, - width_, (width_ + 1) / 2, - (width_ + 1) / 2); - EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer_.get(), 0, 0, width_, height_, - 0, kVideoRotation_180, &rotated_res_i420_frame)); + rtc::scoped_refptr<I420Buffer> rotated_res_i420_buffer = I420Buffer::Create( + rotated_width, rotated_height, stride_y, stride_uv, stride_uv); + EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, + 0, kVideoRotation_90, + rotated_res_i420_buffer.get())); + EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, + 0, kVideoRotation_270, + rotated_res_i420_buffer.get())); + rotated_res_i420_buffer = I420Buffer::Create( + width_, height_, width_, (width_ + 1) / 2, (width_ + 1) / 2); + EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, + 0, kVideoRotation_180, + rotated_res_i420_buffer.get())); } } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/libyuv/webrtc_libyuv.cc b/chromium/third_party/webrtc/common_video/libyuv/webrtc_libyuv.cc index 44577e9ac8e..6a7ba15dd2d 100644 --- a/chromium/third_party/webrtc/common_video/libyuv/webrtc_libyuv.cc +++ b/chromium/third_party/webrtc/common_video/libyuv/webrtc_libyuv.cc @@ -103,33 +103,35 @@ static int PrintPlane(const uint8_t* buf, } // TODO(nisse): Belongs with the test code? -int PrintVideoFrame(const VideoFrame& frame, FILE* file) { - if (file == NULL) - return -1; - if (frame.IsZeroSize()) - return -1; - int width = frame.video_frame_buffer()->width(); - int height = frame.video_frame_buffer()->height(); +int PrintVideoFrame(const VideoFrameBuffer& frame, FILE* file) { + int width = frame.width(); + int height = frame.height(); int chroma_width = (width + 1) / 2; int chroma_height = (height + 1) / 2; - if (PrintPlane(frame.video_frame_buffer()->DataY(), width, height, - frame.video_frame_buffer()->StrideY(), file) < 0) { + if (PrintPlane(frame.DataY(), width, height, + frame.StrideY(), file) < 0) { return -1; } - if (PrintPlane(frame.video_frame_buffer()->DataU(), + if (PrintPlane(frame.DataU(), chroma_width, chroma_height, - frame.video_frame_buffer()->StrideU(), file) < 0) { + frame.StrideU(), file) < 0) { return -1; } - if (PrintPlane(frame.video_frame_buffer()->DataV(), + if (PrintPlane(frame.DataV(), chroma_width, chroma_height, - frame.video_frame_buffer()->StrideV(), file) < 0) { + frame.StrideV(), file) < 0) { return -1; } return 0; } +int PrintVideoFrame(const VideoFrame& frame, FILE* file) { + if (frame.IsZeroSize()) + return -1; + return PrintVideoFrame(*frame.video_frame_buffer(), file); +} + int ExtractBuffer(const rtc::scoped_refptr<VideoFrameBuffer>& input_frame, size_t size, uint8_t* buffer) { @@ -249,23 +251,19 @@ int ConvertToI420(VideoType src_video_type, int src_height, size_t sample_size, VideoRotation rotation, - VideoFrame* dst_frame) { - int dst_width = dst_frame->width(); - int dst_height = dst_frame->height(); + I420Buffer* dst_buffer) { + int dst_width = dst_buffer->width(); + int dst_height = dst_buffer->height(); // LibYuv expects pre-rotation values for dst. // Stride values should correspond to the destination values. if (rotation == kVideoRotation_90 || rotation == kVideoRotation_270) { - dst_width = dst_frame->height(); - dst_height = dst_frame->width(); + std::swap(dst_width, dst_height); } return libyuv::ConvertToI420( src_frame, sample_size, - dst_frame->video_frame_buffer()->MutableDataY(), - dst_frame->video_frame_buffer()->StrideY(), - dst_frame->video_frame_buffer()->MutableDataU(), - dst_frame->video_frame_buffer()->StrideU(), - dst_frame->video_frame_buffer()->MutableDataV(), - dst_frame->video_frame_buffer()->StrideV(), + dst_buffer->MutableDataY(), dst_buffer->StrideY(), + dst_buffer->MutableDataU(), dst_buffer->StrideU(), + dst_buffer->MutableDataV(), dst_buffer->StrideV(), crop_x, crop_y, src_width, src_height, dst_width, dst_height, @@ -290,55 +288,105 @@ int ConvertFromI420(const VideoFrame& src_frame, } // Compute PSNR for an I420 frame (all planes) -double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame) { - if (!ref_frame || !test_frame) - return -1; - else if ((ref_frame->width() != test_frame->width()) || - (ref_frame->height() != test_frame->height())) +double I420PSNR(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer) { + if ((ref_buffer.width() != test_buffer.width()) || + (ref_buffer.height() != test_buffer.height())) return -1; - else if (ref_frame->width() < 0 || ref_frame->height() < 0) + else if (ref_buffer.width() < 0 || ref_buffer.height() < 0) return -1; - double psnr = libyuv::I420Psnr(ref_frame->video_frame_buffer()->DataY(), - ref_frame->video_frame_buffer()->StrideY(), - ref_frame->video_frame_buffer()->DataU(), - ref_frame->video_frame_buffer()->StrideU(), - ref_frame->video_frame_buffer()->DataV(), - ref_frame->video_frame_buffer()->StrideV(), - test_frame->video_frame_buffer()->DataY(), - test_frame->video_frame_buffer()->StrideY(), - test_frame->video_frame_buffer()->DataU(), - test_frame->video_frame_buffer()->StrideU(), - test_frame->video_frame_buffer()->DataV(), - test_frame->video_frame_buffer()->StrideV(), - test_frame->width(), test_frame->height()); + double psnr = libyuv::I420Psnr(ref_buffer.DataY(), ref_buffer.StrideY(), + ref_buffer.DataU(), ref_buffer.StrideU(), + ref_buffer.DataV(), ref_buffer.StrideV(), + test_buffer.DataY(), test_buffer.StrideY(), + test_buffer.DataU(), test_buffer.StrideU(), + test_buffer.DataV(), test_buffer.StrideV(), + test_buffer.width(), test_buffer.height()); // LibYuv sets the max psnr value to 128, we restrict it here. // In case of 0 mse in one frame, 128 can skew the results significantly. return (psnr > kPerfectPSNR) ? kPerfectPSNR : psnr; } -// Compute SSIM for an I420 frame (all planes) -double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame) { +// Compute PSNR for an I420 frame (all planes) +double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame) { if (!ref_frame || !test_frame) return -1; - else if ((ref_frame->width() != test_frame->width()) || - (ref_frame->height() != test_frame->height())) + return I420PSNR(*ref_frame->video_frame_buffer(), + *test_frame->video_frame_buffer()); +} + +// Compute SSIM for an I420 frame (all planes) +double I420SSIM(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer) { + if ((ref_buffer.width() != test_buffer.width()) || + (ref_buffer.height() != test_buffer.height())) return -1; - else if (ref_frame->width() < 0 || ref_frame->height() < 0) + else if (ref_buffer.width() < 0 || ref_buffer.height() < 0) return -1; - return libyuv::I420Ssim(ref_frame->video_frame_buffer()->DataY(), - ref_frame->video_frame_buffer()->StrideY(), - ref_frame->video_frame_buffer()->DataU(), - ref_frame->video_frame_buffer()->StrideU(), - ref_frame->video_frame_buffer()->DataV(), - ref_frame->video_frame_buffer()->StrideV(), - test_frame->video_frame_buffer()->DataY(), - test_frame->video_frame_buffer()->StrideY(), - test_frame->video_frame_buffer()->DataU(), - test_frame->video_frame_buffer()->StrideU(), - test_frame->video_frame_buffer()->DataV(), - test_frame->video_frame_buffer()->StrideV(), - test_frame->width(), test_frame->height()); + return libyuv::I420Ssim(ref_buffer.DataY(), ref_buffer.StrideY(), + ref_buffer.DataU(), ref_buffer.StrideU(), + ref_buffer.DataV(), ref_buffer.StrideV(), + test_buffer.DataY(), test_buffer.StrideY(), + test_buffer.DataU(), test_buffer.StrideU(), + test_buffer.DataV(), test_buffer.StrideV(), + test_buffer.width(), test_buffer.height()); +} +double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame) { + if (!ref_frame || !test_frame) + return -1; + return I420SSIM(*ref_frame->video_frame_buffer(), + *test_frame->video_frame_buffer()); } + +void NV12ToI420Scaler::NV12ToI420Scale( + const uint8_t* src_y, int src_stride_y, + const uint8_t* src_uv, int src_stride_uv, + int src_width, int src_height, + uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_u, int dst_stride_u, + uint8_t* dst_v, int dst_stride_v, + int dst_width, int dst_height) { + if (src_width == dst_width && src_height == dst_height) { + // No scaling. + tmp_uv_planes_.clear(); + tmp_uv_planes_.shrink_to_fit(); + libyuv::NV12ToI420( + src_y, src_stride_y, + src_uv, src_stride_uv, + dst_y, dst_stride_y, + dst_u, dst_stride_u, + dst_v, dst_stride_v, + src_width, src_height); + return; + } + + // Scaling. + // Allocate temporary memory for spitting UV planes. + const int src_uv_width = (src_width + 1) / 2; + const int src_uv_height = (src_height + 1) / 2; + tmp_uv_planes_.resize(src_uv_width * src_uv_height * 2); + tmp_uv_planes_.shrink_to_fit(); + + // Split source UV plane into separate U and V plane using the temporary data. + uint8_t* const src_u = tmp_uv_planes_.data(); + uint8_t* const src_v = tmp_uv_planes_.data() + src_uv_width * src_uv_height; + libyuv::SplitUVPlane(src_uv, src_stride_uv, + src_u, src_uv_width, + src_v, src_uv_width, + src_uv_width, src_uv_height); + + // Scale the planes into the destination. + libyuv::I420Scale(src_y, src_stride_y, + src_u, src_uv_width, + src_v, src_uv_width, + src_width, src_height, + dst_y, dst_stride_y, + dst_u, dst_stride_u, + dst_v, dst_stride_v, + dst_width, dst_height, + libyuv::kFilterBox); +} + } // namespace webrtc diff --git a/chromium/third_party/webrtc/common_video/video_frame.cc b/chromium/third_party/webrtc/common_video/video_frame.cc index b1721b4bc4a..a9f0b4d295e 100644 --- a/chromium/third_party/webrtc/common_video/video_frame.cc +++ b/chromium/third_party/webrtc/common_video/video_frame.cc @@ -25,19 +25,28 @@ const size_t EncodedImage::kBufferPaddingBytesH264 = 8; VideoFrame::VideoFrame() : video_frame_buffer_(nullptr), - timestamp_(0), + timestamp_rtp_(0), ntp_time_ms_(0), - render_time_ms_(0), + timestamp_us_(0), rotation_(kVideoRotation_0) {} VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + webrtc::VideoRotation rotation, + int64_t timestamp_us) + : video_frame_buffer_(buffer), + timestamp_rtp_(0), + ntp_time_ms_(0), + timestamp_us_(timestamp_us), + rotation_(rotation) {} + +VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, uint32_t timestamp, int64_t render_time_ms, VideoRotation rotation) : video_frame_buffer_(buffer), - timestamp_(timestamp), + timestamp_rtp_(timestamp), ntp_time_ms_(0), - render_time_ms_(render_time_ms), + timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec), rotation_(rotation) { RTC_DCHECK(buffer); } @@ -55,9 +64,9 @@ void VideoFrame::CreateEmptyFrame(int width, RTC_DCHECK_GE(stride_v, half_width); // Creating empty frame - reset all values. - timestamp_ = 0; + timestamp_rtp_ = 0; ntp_time_ms_ = 0; - render_time_ms_ = 0; + timestamp_us_ = 0; rotation_ = kVideoRotation_0; // Allocate a new buffer. @@ -78,10 +87,18 @@ void VideoFrame::CreateFrame(const uint8_t* buffer_y, const int expected_size_y = height * stride_y; const int expected_size_u = half_height * stride_u; const int expected_size_v = half_height * stride_v; - CreateEmptyFrame(width, height, stride_y, stride_u, stride_v); - memcpy(video_frame_buffer_->MutableDataY(), buffer_y, expected_size_y); - memcpy(video_frame_buffer_->MutableDataU(), buffer_u, expected_size_u); - memcpy(video_frame_buffer_->MutableDataV(), buffer_v, expected_size_v); + // Allocate a new buffer. + rtc::scoped_refptr<I420Buffer> buffer_ = + I420Buffer::Create(width, height, stride_y, stride_u, stride_v); + + memcpy(buffer_->MutableDataY(), buffer_y, expected_size_y); + memcpy(buffer_->MutableDataU(), buffer_u, expected_size_u); + memcpy(buffer_->MutableDataV(), buffer_v, expected_size_v); + + video_frame_buffer_ = buffer_; + timestamp_rtp_ = 0; + ntp_time_ms_ = 0; + timestamp_us_ = 0; rotation_ = rotation; } @@ -110,34 +127,12 @@ void VideoFrame::CopyFrame(const VideoFrame& videoFrame) { void VideoFrame::ShallowCopy(const VideoFrame& videoFrame) { video_frame_buffer_ = videoFrame.video_frame_buffer(); - timestamp_ = videoFrame.timestamp_; + timestamp_rtp_ = videoFrame.timestamp_rtp_; ntp_time_ms_ = videoFrame.ntp_time_ms_; - render_time_ms_ = videoFrame.render_time_ms_; + timestamp_us_ = videoFrame.timestamp_us_; rotation_ = videoFrame.rotation_; } -// TODO(nisse): Delete. Besides test code, only one use, in -// webrtcvideoengine2.cc:CreateBlackFrame. -int VideoFrame::allocated_size(PlaneType type) const { - const int plane_height = (type == kYPlane) ? height() : (height() + 1) / 2; - int stride; - switch (type) { - case kYPlane: - stride = video_frame_buffer_->StrideY(); - break; - case kUPlane: - stride = video_frame_buffer_->StrideU(); - break; - case kVPlane: - stride = video_frame_buffer_->StrideV(); - break; - default: - RTC_NOTREACHED(); - return 0; - } - return plane_height * stride; -} - int VideoFrame::width() const { return video_frame_buffer_ ? video_frame_buffer_->width() : 0; } diff --git a/chromium/third_party/webrtc/common_video/video_frame_buffer.cc b/chromium/third_party/webrtc/common_video/video_frame_buffer.cc index 23643c4bfd5..dbb2743db12 100644 --- a/chromium/third_party/webrtc/common_video/video_frame_buffer.cc +++ b/chromium/third_party/webrtc/common_video/video_frame_buffer.cc @@ -15,6 +15,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/keep_ref_until_done.h" #include "libyuv/convert.h" +#include "libyuv/planar_functions.h" #include "libyuv/scale.h" // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. @@ -30,19 +31,6 @@ int I420DataSize(int height, int stride_y, int stride_u, int stride_v) { } // namespace -uint8_t* VideoFrameBuffer::MutableDataY() { - RTC_NOTREACHED(); - return nullptr; -} -uint8_t* VideoFrameBuffer::MutableDataU() { - RTC_NOTREACHED(); - return nullptr; -} -uint8_t* VideoFrameBuffer::MutableDataV() { - RTC_NOTREACHED(); - return nullptr; -} - VideoFrameBuffer::~VideoFrameBuffer() {} I420Buffer::I420Buffer(int width, int height) @@ -215,6 +203,7 @@ void I420Buffer::ScaleFrom(const rtc::scoped_refptr<VideoFrameBuffer>& src) { CropAndScaleFrom(src, 0, 0, src->width(), src->height()); } +// static rtc::scoped_refptr<I420Buffer> I420Buffer::CopyKeepStride( const rtc::scoped_refptr<VideoFrameBuffer>& source) { int width = source->width(); @@ -235,6 +224,41 @@ rtc::scoped_refptr<I420Buffer> I420Buffer::CopyKeepStride( return target; } +// static +rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::Rotate( + const rtc::scoped_refptr<VideoFrameBuffer>& src, + VideoRotation rotation) { + RTC_DCHECK(src->DataY()); + RTC_DCHECK(src->DataU()); + RTC_DCHECK(src->DataV()); + + if (rotation == webrtc::kVideoRotation_0) { + return src; + } + + int rotated_width = src->width(); + int rotated_height = src->height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I420Buffer> buffer = + I420Buffer::Create(rotated_width, rotated_height); + + int res = libyuv::I420Rotate( + src->DataY(), src->StrideY(), + src->DataU(), src->StrideU(), + src->DataV(), src->StrideV(), + buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(), + src->width(), src->height(), + static_cast<libyuv::RotationMode>(rotation)); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + NativeHandleBuffer::NativeHandleBuffer(void* native_handle, int width, int height) diff --git a/chromium/third_party/webrtc/common_video/video_render_frames.cc b/chromium/third_party/webrtc/common_video/video_render_frames.cc index b818512acb1..5cec386bb2f 100644 --- a/chromium/third_party/webrtc/common_video/video_render_frames.cc +++ b/chromium/third_party/webrtc/common_video/video_render_frames.cc @@ -12,6 +12,7 @@ #include <assert.h> +#include "webrtc/base/logging.h" #include "webrtc/base/timeutils.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/trace.h" @@ -22,6 +23,7 @@ namespace { const uint32_t kEventMaxWaitTimeMs = 200; const uint32_t kMinRenderDelayMs = 10; const uint32_t kMaxRenderDelayMs = 500; +const size_t kMaxIncomingFramesBeforeLogged = 100; uint32_t EnsureValidRenderDelay(uint32_t render_delay) { return (render_delay < kMinRenderDelayMs || render_delay > kMaxRenderDelayMs) @@ -57,6 +59,8 @@ int32_t VideoRenderFrames::AddFrame(const VideoFrame& new_frame) { } incoming_frames_.push_back(new_frame); + if (incoming_frames_.size() > kMaxIncomingFramesBeforeLogged) + LOG(LS_WARNING) << "Stored incoming frames: " << incoming_frames_.size(); return static_cast<int32_t>(incoming_frames_.size()); } |