blob: a6e8a569283ef2ba3e3f0de05b895d720c0542b3 [file] [log] [blame]
// Copyright 2018 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 MEDIA_GPU_V4L2_V4L2_DECODE_SURFACE_H_
#define MEDIA_GPU_V4L2_V4L2_DECODE_SURFACE_H_
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "media/gpu/v4l2/v4l2_device.h"
#include "ui/gfx/geometry/rect.h"
struct v4l2_ext_controls;
struct v4l2_buffer;
namespace media {
// A V4L2-specific decode surface generated by V4L2DecodeSurfaceHandler.
// It is used to store common picture metadata (e.g. visible_rect) and
// platform-specific metadata (e.g. {input,output}_record).
class V4L2DecodeSurface : public base::RefCounted<V4L2DecodeSurface> {
public:
// V4L2DecodeSurfaceHandler maintains a list of InputRecords, which records
// the status and metadata of input buffers.
// |input_buffer| and |output_buffer| are the buffers to be used as input and
// output in this transaction.
// |frame| is optional, and allows the caller to keep a reference to a
// VideoFrame for as long as this decode surface exists.
V4L2DecodeSurface(V4L2WritableBufferRef input_buffer,
V4L2WritableBufferRef output_buffer,
scoped_refptr<VideoFrame> frame);
// Mark the surface as decoded. This will also release all surfaces used for
// reference, as they are not needed anymore and execute the done callback,
// if not null.
void SetDecoded();
void SetVisibleRect(const gfx::Rect& visible_rect);
// Take references to each reference surface and keep them until the
// target surface is decoded.
void SetReferenceSurfaces(
std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces);
// If provided via this method, |done_cb| callback will be executed after
// decoding into this surface is finished. The callback is reset afterwards,
// so it needs to be set again before each decode operation.
void SetDecodeDoneCallback(base::OnceClosure done_cb);
void SetReleaseCallback(base::OnceClosure release_cb);
// Update the passed v4l2_ext_controls structure to add the request or
// config store information.
virtual void PrepareSetCtrls(struct v4l2_ext_controls* ctrls) const = 0;
// Update the passed v4l2_buffer structure to add the request or
// config store information.
virtual void PrepareQueueBuffer(struct v4l2_buffer* buffer) const = 0;
// Return the ID to use in order to reference this frame.
virtual uint64_t GetReferenceID() const = 0;
// Submit the request corresponding to this surface once all controls have
// been set and all buffers queued.
virtual bool Submit() const = 0;
bool decoded() const { return decoded_; }
int input_record() const { return input_record_; }
V4L2WritableBufferRef& input_buffer() {
DCHECK(input_buffer_.IsValid());
return input_buffer_;
}
int output_record() const { return output_record_; }
V4L2WritableBufferRef& output_buffer() {
DCHECK(output_buffer_.IsValid());
return output_buffer_;
}
scoped_refptr<VideoFrame> video_frame() const { return video_frame_; }
gfx::Rect visible_rect() const { return visible_rect_; }
std::string ToString() const;
protected:
virtual ~V4L2DecodeSurface();
friend class base::RefCounted<V4L2DecodeSurface>;
SEQUENCE_CHECKER(sequence_checker_);
private:
// The index of the corresponding input record.
const int input_record_;
V4L2WritableBufferRef input_buffer_;
// The index of the corresponding output record.
const int output_record_;
V4L2WritableBufferRef output_buffer_;
scoped_refptr<VideoFrame> video_frame_;
// The visible size of the buffer.
gfx::Rect visible_rect_;
// Indicate whether the surface is decoded or not.
bool decoded_;
// Callback function which is called when the instance is destroyed.
base::OnceClosure release_cb_;
// Callback function which is called after the surface has been decoded.
base::OnceClosure done_cb_;
// The decoded surfaces of the reference frames, which is kept until the
// surface has been decoded.
std::vector<scoped_refptr<V4L2DecodeSurface>> reference_surfaces_;
DISALLOW_COPY_AND_ASSIGN(V4L2DecodeSurface);
};
// An implementation of V4L2DecodeSurface that uses the config store to
// associate controls/buffers to frames.
class V4L2ConfigStoreDecodeSurface : public V4L2DecodeSurface {
public:
V4L2ConfigStoreDecodeSurface(V4L2WritableBufferRef input_buffer,
V4L2WritableBufferRef output_buffer,
scoped_refptr<VideoFrame> frame)
: V4L2DecodeSurface(std::move(input_buffer),
std::move(output_buffer),
std::move(frame)),
// config store IDs are arbitrarily defined to be buffer ID + 1
config_store_(this->input_buffer().BufferId() + 1) {}
void PrepareSetCtrls(struct v4l2_ext_controls* ctrls) const override;
void PrepareQueueBuffer(struct v4l2_buffer* buffer) const override;
uint64_t GetReferenceID() const override;
bool Submit() const override;
private:
~V4L2ConfigStoreDecodeSurface() override = default;
// The configuration store of the input buffer.
uint32_t config_store_;
};
// An implementation of V4L2DecodeSurface that uses requests to associate
// controls/buffers to frames
class V4L2RequestDecodeSurface : public V4L2DecodeSurface {
public:
// Constructor method for V4L2RequestDecodeSurface. It will return
// base::nullopt if a runtime error occurred when creating the decode surface.
//
// request_fd is the FD of the request to use for decoding this frame.
// Note that it will not be closed after the request is submitted - the caller
// is responsible for managing its lifetime.
static base::Optional<scoped_refptr<V4L2RequestDecodeSurface>> Create(
V4L2WritableBufferRef input_buffer,
V4L2WritableBufferRef output_buffer,
scoped_refptr<VideoFrame> frame,
int request_fd);
void PrepareSetCtrls(struct v4l2_ext_controls* ctrls) const override;
void PrepareQueueBuffer(struct v4l2_buffer* buffer) const override;
uint64_t GetReferenceID() const override;
bool Submit() const override;
private:
// FD of the request to use.
const int request_fd_;
V4L2RequestDecodeSurface(V4L2WritableBufferRef input_buffer,
V4L2WritableBufferRef output_buffer,
scoped_refptr<VideoFrame> frame,
int request_fd)
: V4L2DecodeSurface(std::move(input_buffer),
std::move(output_buffer),
std::move(frame)),
request_fd_(request_fd) {}
};
} // namespace media
#endif // MEDIA_GPU_V4L2_V4L2_DECODE_SURFACE_H_