blob: 9337f72264415ea37fdf5219ada9bacd2c6380e6 [file] [log] [blame]
// Copyright 2017 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 COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_INTERPROCESS_FRAME_POOL_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_INTERPROCESS_FRAME_POOL_H_
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/viz/service/viz_service_export.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
// A pool of VideoFrames backed by shared memory that can be transported
// efficiently across mojo service boundaries.
class VIZ_SERVICE_EXPORT InterprocessFramePool {
public:
// |capacity| is the maximum number of pooled VideoFrames; but they can be of
// any byte size.
explicit InterprocessFramePool(int capacity);
~InterprocessFramePool();
// Reserves a buffer from the pool and creates a VideoFrame to wrap its shared
// memory. When the ref-count of the returned VideoFrame goes to zero, the
// reservation is released and the frame becomes available for re-use. Returns
// null if the pool is fully utilized.
scoped_refptr<media::VideoFrame> ReserveVideoFrame(
media::VideoPixelFormat format,
const gfx::Size& size);
// Finds the last VideoFrame delivered, and if it has been returned back to
// this pool already, re-materializes it. Otherwise, null is returned. This is
// used when the client knows the content of the video frame has not changed
// and is trying to avoid having to re-populate a new VideoFrame with the same
// content.
scoped_refptr<media::VideoFrame> ResurrectLastVideoFrame(
media::VideoPixelFormat expected_format,
const gfx::Size& expected_size);
// Returns a cloned handle to the shared memory backing |frame| and its size
// in bytes. Note that the client should not allow the ref-count of the
// VideoFrame to reach zero until downstream consumers are finished using it,
// as this would allow the shared memory to be re-used for a later frame.
//
// Calling this method is a signal that |frame| should be considered the
// last-delivered frame, for the purposes of ResurrectLastVideoFrame().
base::ReadOnlySharedMemoryRegion CloneHandleForDelivery(
const media::VideoFrame* frame);
// Returns the current pool utilization, based on the number of VideoFrames
// being held by the client.
float GetUtilization() const;
private:
using PooledBuffer = base::MappedReadOnlyRegion;
// Creates a media::VideoFrame backed by a specific pooled buffer.
scoped_refptr<media::VideoFrame> WrapBuffer(PooledBuffer pooled_buffer,
media::VideoPixelFormat format,
const gfx::Size& size);
// Called when a reserved/resurrected VideoFrame goes out of scope, to remove
// the entry from |utilized_buffers_| and place the PooledBuffer back into
// |available_buffers_|.
void OnFrameWrapperDestroyed(const media::VideoFrame* frame,
base::WritableSharedMemoryMapping mapping);
// Returns true if a shared memory failure can be logged. This is a rate
// throttle, to ensure the logs aren't spammed in chronically low-memory
// environments.
bool CanLogSharedMemoryFailure();
// The maximum number of buffers. However, the buffers themselves can be of
// any byte size.
const size_t capacity_;
// Buffers available for immediate re-use. Generally, it is best to push and
// pop from the back of this vector so that the most-recently-used buffers are
// re-used. This will help prevent excessive operating system paging in low-
// memory situations.
std::vector<PooledBuffer> available_buffers_;
// A map of externally-owned VideoFrames and the tracking information about
// the shared memory buffer backing them.
base::flat_map<const media::VideoFrame*, base::ReadOnlySharedMemoryRegion>
utilized_buffers_;
// The pointer to the mapped memory of the buffer that was last delivered,
// along with its format and size. ResurrectLastVideoFrame() uses this
// information to locate and confirm that a prior frame can be resurrected.
const void* resurrectable_buffer_memory_ = nullptr;
media::VideoPixelFormat last_delivered_format_ = media::PIXEL_FORMAT_UNKNOWN;
gfx::Size last_delivered_size_;
gfx::ColorSpace last_delivered_color_space_;
// The time at which the last shared memory allocation or mapping failed.
base::TimeTicks last_fail_log_time_;
// The amount of time that should elapsed between log warnings about shared
// memory allocation/mapping failures.
static constexpr base::TimeDelta kMinLoggingPeriod =
base::TimeDelta::FromSeconds(10);
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<InterprocessFramePool> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(InterprocessFramePool);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_INTERPROCESS_FRAME_POOL_H_