summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/common_video
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-04 14:17:57 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-05 10:05:06 +0000
commit39d357e3248f80abea0159765ff39554affb40db (patch)
treeaba0e6bfb76de0244bba0f5fdbd64b830dd6e621 /chromium/third_party/webrtc/common_video
parent87778abf5a1f89266f37d1321b92a21851d8244d (diff)
downloadqtwebengine-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')
-rw-r--r--chromium/third_party/webrtc/common_video/BUILD.gn41
-rw-r--r--chromium/third_party/webrtc/common_video/OWNERS9
-rw-r--r--chromium/third_party/webrtc/common_video/bitrate_adjuster_unittest.cc3
-rw-r--r--chromium/third_party/webrtc/common_video/common_video.gyp1
-rw-r--r--chromium/third_party/webrtc/common_video/common_video_unittests.gyp100
-rw-r--r--chromium/third_party/webrtc/common_video/common_video_unittests.isolate31
-rw-r--r--chromium/third_party/webrtc/common_video/common_video_unittests_apk.isolate26
-rw-r--r--chromium/third_party/webrtc/common_video/corevideo_frame_buffer.cc2
-rw-r--r--chromium/third_party/webrtc/common_video/h264/pps_parser.cc53
-rw-r--r--chromium/third_party/webrtc/common_video/h264/pps_parser.h13
-rw-r--r--chromium/third_party/webrtc/common_video/h264/pps_parser_unittest.cc32
-rw-r--r--chromium/third_party/webrtc/common_video/h264/sps_parser.cc4
-rw-r--r--chromium/third_party/webrtc/common_video/h264/sps_parser.h1
-rw-r--r--chromium/third_party/webrtc/common_video/h264/sps_parser_unittest.cc16
-rw-r--r--chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter.cc7
-rw-r--r--chromium/third_party/webrtc/common_video/h264/sps_vui_rewriter_unittest.cc13
-rw-r--r--chromium/third_party/webrtc/common_video/i420_buffer_pool.cc14
-rw-r--r--chromium/third_party/webrtc/common_video/i420_buffer_pool_unittest.cc11
-rw-r--r--chromium/third_party/webrtc/common_video/i420_video_frame_unittest.cc47
-rw-r--r--chromium/third_party/webrtc/common_video/include/i420_buffer_pool.h21
-rw-r--r--chromium/third_party/webrtc/common_video/include/incoming_video_stream.h2
-rw-r--r--chromium/third_party/webrtc/common_video/include/video_frame_buffer.h27
-rw-r--r--chromium/third_party/webrtc/common_video/incoming_video_stream.cc4
-rw-r--r--chromium/third_party/webrtc/common_video/libyuv/include/webrtc_libyuv.h31
-rw-r--r--chromium/third_party/webrtc/common_video/libyuv/libyuv_unittest.cc149
-rw-r--r--chromium/third_party/webrtc/common_video/libyuv/webrtc_libyuv.cc170
-rw-r--r--chromium/third_party/webrtc/common_video/video_frame.cc63
-rw-r--r--chromium/third_party/webrtc/common_video/video_frame_buffer.cc50
-rw-r--r--chromium/third_party/webrtc/common_video/video_render_frames.cc4
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());
}