[go: nahoru, domu]

blob: 2122eaddca9e8672ff6dc910cc91832bb783c02b [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_WEBRTC_VIDEO_FRAME_ADAPTER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_WEBRTC_VIDEO_FRAME_ADAPTER_H_
#include <vector>
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_pool.h"
#include "media/base/video_types.h"
#include "media/capture/video/video_capture_feedback.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "media/video/renderable_gpu_memory_buffer_video_frame_pool.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/webrtc/api/scoped_refptr.h"
#include "third_party/webrtc/api/video/video_frame_buffer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
// The WebRtcVideoFrameAdapter implements webrtc::VideoFrameBuffer and is backed
// by one or more media::VideoFrames.
// * Upon CropAndScale(), the crop and scale values are soft-applied.
// * Upon GetMappedFrameBuffer(), any outstanding crop and scale is hard-applied
// before returning the resulting buffer. This also happens on ToI420().
//
// This eliminates any intermediary downscales by only hard-applying what
// actually needs to be mapped.
//
// When crop and scale is hard-applied, the media::VideoFrame of closest size
// that is greater than or equal the requested size is chosen, minimizing
// scaling costs. If a media::VideoFrame exists in the desired size, no scaling
// is needed.
//
// WebRtcVideoFrameAdapter keeps track of which crops and scales were
// hard-applied during its lifetime.
// TODO(https://crbug.com/webrtc/12469): Expose this information to the caller
// or to the frame feeddback so that we may optionally use this information to
// optimize future captured frames for these sizes.
class PLATFORM_EXPORT WebRtcVideoFrameAdapter
: public webrtc::VideoFrameBuffer {
public:
class VectorBufferPool {
public:
VectorBufferPool();
~VectorBufferPool() = default;
// Allocate will return any available buffer and the vector buffer size
// needs to be resized manually by the user.
std::unique_ptr<std::vector<uint8_t>> Allocate();
void Return(std::unique_ptr<std::vector<uint8_t>> buffer);
private:
struct BufferEntry {
base::TimeTicks last_use_time;
std::unique_ptr<std::vector<uint8_t>> buffer;
};
base::Lock buffer_lock_;
std::vector<BufferEntry> free_buffers_ GUARDED_BY(buffer_lock_);
const base::TickClock* tick_clock_;
};
class PLATFORM_EXPORT SharedResources
: public base::RefCountedThreadSafe<SharedResources> {
public:
explicit SharedResources(
media::GpuVideoAcceleratorFactories* gpu_factories);
// Create frames for requested output format and resolution.
virtual scoped_refptr<media::VideoFrame> CreateFrame(
media::VideoPixelFormat format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
base::TimeDelta timestamp);
// Temporary vector buffers used in the video pre-processing for the input
// frame before encoding, e.g. scaling the input frame to natural size for
// encoding. Buffer needs manually release after using.
virtual std::unique_ptr<std::vector<uint8_t>> CreateTemporaryVectorBuffer();
virtual void ReleaseTemporaryVectorBuffer(
std::unique_ptr<std::vector<uint8_t>> buffer);
virtual scoped_refptr<viz::RasterContextProvider>
GetRasterContextProvider();
// Constructs a VideoFrame from a texture by invoking RasterInterface,
// which would perform a blocking call to a GPU process.
// The pixel data is copied and may be in ARGB pixel format in some cases,
// So additional conversion to I420 would be needed.
virtual scoped_refptr<media::VideoFrame> ConstructVideoFrameFromTexture(
scoped_refptr<media::VideoFrame> source_frame);
// Constructs a VideoFrame from a GMB. Unless it's a Windows DXGI GMB,
// the buffer is mapped to the memory and wrapped by a VideoFrame with no
// copies. For DXGI buffers a blocking call to GPU process is made to
// copy pixel data.
virtual scoped_refptr<media::VideoFrame> ConstructVideoFrameFromGpu(
scoped_refptr<media::VideoFrame> source_frame);
// Used to report feedback from an adapter upon destruction.
void SetFeedback(const media::VideoCaptureFeedback& feedback);
// Returns the most recently stored feedback.
media::VideoCaptureFeedback GetFeedback();
protected:
friend class base::RefCountedThreadSafe<SharedResources>;
virtual ~SharedResources();
private:
media::VideoFramePool pool_;
media::VideoFramePool pool_for_mapped_frames_;
VectorBufferPool pool_for_tmp_vectors_;
std::unique_ptr<media::RenderableGpuMemoryBufferVideoFramePool>
accelerated_frame_pool_;
bool disable_gmb_frames_ = false;
base::Lock context_provider_lock_;
scoped_refptr<viz::RasterContextProvider> raster_context_provider_
GUARDED_BY(context_provider_lock_);
media::GpuVideoAcceleratorFactories* gpu_factories_;
base::Lock feedback_lock_;
// Contains feedback from the most recently destroyed Adapter.
media::VideoCaptureFeedback last_feedback_ GUARDED_BY(feedback_lock_);
};
struct PLATFORM_EXPORT ScaledBufferSize {
ScaledBufferSize(gfx::Rect visible_rect, gfx::Size natural_size);
bool operator==(const ScaledBufferSize& rhs) const;
bool operator!=(const ScaledBufferSize& rhs) const;
// Applies crop-and-scale relative to the current natural size.
ScaledBufferSize CropAndScale(int offset_x,
int offset_y,
int crop_width,
int crop_height,
int scaled_width,
int scaled_height) const;
// Cropping relative to the original image.
gfx::Rect visible_rect;
// The size (after scaling) of the visible rect.
gfx::Size natural_size;
};
// Implements a soft-applied "view" of the parent WebRtcVideoFrameAdapter. Its
// size only gets hard-applied if GetMappedFrameBuffer() or ToI420() is
// called, in which case the result is cached inside the parent.
class ScaledBuffer : public webrtc::VideoFrameBuffer {
public:
ScaledBuffer(scoped_refptr<WebRtcVideoFrameAdapter> parent,
ScaledBufferSize size);
// Regardless of the pixel format used internally, kNative is returned
// indicating that GetMappedFrameBuffer() or ToI420() is required to obtain
// the pixels.
webrtc::VideoFrameBuffer::Type type() const override {
return webrtc::VideoFrameBuffer::Type::kNative;
}
int width() const override { return size_.natural_size.width(); }
int height() const override { return size_.natural_size.height(); }
// Obtains a mapped I420 buffer with this ScaledBuffer's size hard-applied.
// If I420 is not used internally, a conversion happens.
rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override;
// Obtains a mapped buffer of this ScaledBuffer's size hard-applied. The
// resulting buffer's type is the non-kNative type used internally.
rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetMappedFrameBuffer(
rtc::ArrayView<webrtc::VideoFrameBuffer::Type> types) override;
// Soft-applies cropping and scaling. The result is another ScaledBuffer.
rtc::scoped_refptr<webrtc::VideoFrameBuffer> CropAndScale(
int offset_x,
int offset_y,
int crop_width,
int crop_height,
int scaled_width,
int scaled_height) override;
const ScaledBufferSize& size() const { return size_; }
private:
scoped_refptr<WebRtcVideoFrameAdapter> parent_;
ScaledBufferSize size_;
};
explicit WebRtcVideoFrameAdapter(scoped_refptr<media::VideoFrame> frame);
WebRtcVideoFrameAdapter(
scoped_refptr<media::VideoFrame> frame,
std::vector<scoped_refptr<media::VideoFrame>> scaled_frames,
scoped_refptr<SharedResources> shared_resources);
scoped_refptr<media::VideoFrame> getMediaVideoFrame() const { return frame_; }
// Regardless of the pixel format used internally, kNative is returned
// indicating that GetMappedFrameBuffer() or ToI420() is required to obtain
// the pixels.
webrtc::VideoFrameBuffer::Type type() const override {
return webrtc::VideoFrameBuffer::Type::kNative;
}
int width() const override { return frame_->natural_size().width(); }
int height() const override { return frame_->natural_size().height(); }
rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override;
rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetMappedFrameBuffer(
rtc::ArrayView<webrtc::VideoFrameBuffer::Type> types) override;
// Soft-applies cropping and scaling. The result is a ScaledBuffer.
rtc::scoped_refptr<webrtc::VideoFrameBuffer> CropAndScale(
int offset_x,
int offset_y,
int crop_width,
int crop_height,
int scaled_width,
int scaled_height) override;
// If this exact size has been hard-applied by wrapping or using a pre-scaled
// media::VideoFrame, the associated media::VideoFrame is returned (the
// wrapping or original). If this size has not been hard-applied, or it was
// hard-applied by scaling a previously adapted webrtc::VideoFrameBuffer, then
// null is returned.
scoped_refptr<media::VideoFrame> GetAdaptedVideoBufferForTesting(
const ScaledBufferSize& size);
protected:
~WebRtcVideoFrameAdapter() override;
private:
struct AdaptedFrame {
AdaptedFrame(ScaledBufferSize size,
scoped_refptr<media::VideoFrame> video_frame,
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer)
: size(std::move(size)),
video_frame(std::move(video_frame)),
frame_buffer(std::move(frame_buffer)) {}
ScaledBufferSize size;
// If |frame_buffer| was produced without a media::VideoFrame this is null.
scoped_refptr<media::VideoFrame> video_frame;
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer;
};
rtc::scoped_refptr<webrtc::VideoFrameBuffer> GetOrCreateFrameBufferForSize(
const ScaledBufferSize& size);
AdaptedFrame AdaptBestFrame(const ScaledBufferSize& size) const
EXCLUSIVE_LOCKS_REQUIRED(adapted_frames_lock_);
base::Lock adapted_frames_lock_;
const scoped_refptr<media::VideoFrame> frame_;
const std::vector<scoped_refptr<media::VideoFrame>> scaled_frames_;
const scoped_refptr<SharedResources> shared_resources_;
const ScaledBufferSize full_size_;
// Frames that have been adapted, i.e. that were "hard-applied" and mapped.
std::vector<AdaptedFrame> adapted_frames_ GUARDED_BY(adapted_frames_lock_);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBRTC_WEBRTC_VIDEO_FRAME_ADAPTER_H_