This reverts commit 3babb8af238a531cbff27951604b09bb78b762cd. Reason for revert: - Causes regressions to transceivers, see https://crbug.com/1291956 for more information, including tests to reproduce the issue. This CL is not a pure revert. While it reverts everything else, it does keep the new enum value (kProfilePredictiveHigh444). This is as to not break Chromium which already depend on it. It is not listed in the kProfilePatterns though so the enum value should never be applicable. Original change's description: > Added support for H264 YUV444 (I444) decoding. > > Added Nutanix Inc. to the AUTHORS file. > > PS#1 is a reland of "Added support for H264 YUV444 (I444) decoding." https://webrtc-review.googlesource.com/c/src/+/234540 > > Bug: chromium:1251096 > Change-Id: I99a1b1e4d8b60192ff96f92334a430240875c66c > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/235340 > Reviewed-by: Niels Moller <nisse@webrtc.org> > Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> > Reviewed-by: Harald Alvestrand <hta@webrtc.org> > Commit-Queue: Harald Alvestrand <hta@webrtc.org> > Cr-Commit-Position: refs/heads/main@{#35684} # Not skipping CQ checks because original CL landed > 1 day ago. Bug: chromium:1251096, chromium:1291956 Change-Id: Ib4d8ea4898f9832914d88e7076e6b39da0c804ca Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/249791 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Auto-Submit: Henrik Boström <hbos@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35835}
179 lines
5.8 KiB
C++
179 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2015 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.
|
|
*/
|
|
|
|
#include "common_video/include/video_frame_buffer_pool.h"
|
|
|
|
#include <limits>
|
|
|
|
#include "rtc_base/checks.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
bool HasOneRef(const rtc::scoped_refptr<VideoFrameBuffer>& buffer) {
|
|
// Cast to rtc::RefCountedObject is safe because this function is only called
|
|
// on locally created VideoFrameBuffers, which are either
|
|
// `rtc::RefCountedObject<I420Buffer>` or `rtc::RefCountedObject<NV12Buffer>`.
|
|
switch (buffer->type()) {
|
|
case VideoFrameBuffer::Type::kI420: {
|
|
return static_cast<rtc::RefCountedObject<I420Buffer>*>(buffer.get())
|
|
->HasOneRef();
|
|
}
|
|
case VideoFrameBuffer::Type::kNV12: {
|
|
return static_cast<rtc::RefCountedObject<NV12Buffer>*>(buffer.get())
|
|
->HasOneRef();
|
|
}
|
|
default:
|
|
RTC_DCHECK_NOTREACHED();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
VideoFrameBufferPool::VideoFrameBufferPool() : VideoFrameBufferPool(false) {}
|
|
|
|
VideoFrameBufferPool::VideoFrameBufferPool(bool zero_initialize)
|
|
: VideoFrameBufferPool(zero_initialize,
|
|
std::numeric_limits<size_t>::max()) {}
|
|
|
|
VideoFrameBufferPool::VideoFrameBufferPool(bool zero_initialize,
|
|
size_t max_number_of_buffers)
|
|
: zero_initialize_(zero_initialize),
|
|
max_number_of_buffers_(max_number_of_buffers) {}
|
|
|
|
VideoFrameBufferPool::~VideoFrameBufferPool() = default;
|
|
|
|
void VideoFrameBufferPool::Release() {
|
|
buffers_.clear();
|
|
}
|
|
|
|
bool VideoFrameBufferPool::Resize(size_t max_number_of_buffers) {
|
|
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
|
|
size_t used_buffers_count = 0;
|
|
for (const rtc::scoped_refptr<VideoFrameBuffer>& buffer : buffers_) {
|
|
// If the buffer is in use, the ref count will be >= 2, one from the list we
|
|
// are looping over and one from the application. If the ref count is 1,
|
|
// then the list we are looping over holds the only reference and it's safe
|
|
// to reuse.
|
|
if (!HasOneRef(buffer)) {
|
|
used_buffers_count++;
|
|
}
|
|
}
|
|
if (used_buffers_count > max_number_of_buffers) {
|
|
return false;
|
|
}
|
|
max_number_of_buffers_ = max_number_of_buffers;
|
|
|
|
size_t buffers_to_purge = buffers_.size() - max_number_of_buffers_;
|
|
auto iter = buffers_.begin();
|
|
while (iter != buffers_.end() && buffers_to_purge > 0) {
|
|
if (HasOneRef(*iter)) {
|
|
iter = buffers_.erase(iter);
|
|
buffers_to_purge--;
|
|
} else {
|
|
++iter;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
rtc::scoped_refptr<I420Buffer> VideoFrameBufferPool::CreateI420Buffer(
|
|
int width,
|
|
int height) {
|
|
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
|
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> existing_buffer =
|
|
GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI420);
|
|
if (existing_buffer) {
|
|
// Cast is safe because the only way kI420 buffer is created is
|
|
// in the same function below, where `RefCountedObject<I420Buffer>` is
|
|
// created.
|
|
rtc::RefCountedObject<I420Buffer>* raw_buffer =
|
|
static_cast<rtc::RefCountedObject<I420Buffer>*>(existing_buffer.get());
|
|
// Creates a new scoped_refptr, which is also pointing to the same
|
|
// RefCountedObject as buffer, increasing ref count.
|
|
return rtc::scoped_refptr<I420Buffer>(raw_buffer);
|
|
}
|
|
|
|
if (buffers_.size() >= max_number_of_buffers_)
|
|
return nullptr;
|
|
// Allocate new buffer.
|
|
rtc::scoped_refptr<I420Buffer> buffer =
|
|
rtc::make_ref_counted<I420Buffer>(width, height);
|
|
|
|
if (zero_initialize_)
|
|
buffer->InitializeData();
|
|
|
|
buffers_.push_back(buffer);
|
|
return buffer;
|
|
}
|
|
|
|
rtc::scoped_refptr<NV12Buffer> VideoFrameBufferPool::CreateNV12Buffer(
|
|
int width,
|
|
int height) {
|
|
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
|
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> existing_buffer =
|
|
GetExistingBuffer(width, height, VideoFrameBuffer::Type::kNV12);
|
|
if (existing_buffer) {
|
|
// Cast is safe because the only way kI420 buffer is created is
|
|
// in the same function below, where `RefCountedObject<I420Buffer>` is
|
|
// created.
|
|
rtc::RefCountedObject<NV12Buffer>* raw_buffer =
|
|
static_cast<rtc::RefCountedObject<NV12Buffer>*>(existing_buffer.get());
|
|
// Creates a new scoped_refptr, which is also pointing to the same
|
|
// RefCountedObject as buffer, increasing ref count.
|
|
return rtc::scoped_refptr<NV12Buffer>(raw_buffer);
|
|
}
|
|
|
|
if (buffers_.size() >= max_number_of_buffers_)
|
|
return nullptr;
|
|
// Allocate new buffer.
|
|
rtc::scoped_refptr<NV12Buffer> buffer =
|
|
rtc::make_ref_counted<NV12Buffer>(width, height);
|
|
|
|
if (zero_initialize_)
|
|
buffer->InitializeData();
|
|
|
|
buffers_.push_back(buffer);
|
|
return buffer;
|
|
}
|
|
|
|
rtc::scoped_refptr<VideoFrameBuffer> VideoFrameBufferPool::GetExistingBuffer(
|
|
int width,
|
|
int height,
|
|
VideoFrameBuffer::Type type) {
|
|
// Release buffers with wrong resolution or different type.
|
|
for (auto it = buffers_.begin(); it != buffers_.end();) {
|
|
const auto& buffer = *it;
|
|
if (buffer->width() != width || buffer->height() != height ||
|
|
buffer->type() != type) {
|
|
it = buffers_.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
// Look for a free buffer.
|
|
for (const rtc::scoped_refptr<VideoFrameBuffer>& buffer : buffers_) {
|
|
// If the buffer is in use, the ref count will be >= 2, one from the list we
|
|
// are looping over and one from the application. If the ref count is 1,
|
|
// then the list we are looping over holds the only reference and it's safe
|
|
// to reuse.
|
|
if (HasOneRef(buffer)) {
|
|
RTC_CHECK(buffer->type() == type);
|
|
return buffer;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace webrtc
|