blob: 80f96c7ad3f94687cac74e6a96dccab5ccaf631d [file] [log] [blame]
// Copyright 2016 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 CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_WRAPPER_IMPL_H_
#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_WRAPPER_IMPL_H_
#include <memory>
#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/media/android/stream_texture_factory.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "media/base/android/stream_texture_wrapper.h"
#include "media/base/video_frame.h"
namespace content {
// Concrete implementation of StreamTextureWrapper. Any method can be called on
// any thread, but additional threading considerations are listed in the
// comments of individual methods.
//
// The StreamTexture is an abstraction allowing Chrome to wrap a SurfaceTexture
// living in the GPU process. It allows VideoFrames to be created from the
// SurfaceTexture's texture, in the Renderer process.
//
// The general idea behind our use of StreamTexture is as follows:
// - We create a client GL texture in the Renderer process.
// - We request the creation of a StreamTexture via the StreamTextureFactory,
// passing the client texture ID. The call is sent to the GPU process via the
// CommandBuffer. The "platform" GL texture reference associated with the client
// texture ID is looked up in the TextureManager. A StreamTexture is then
// created, wrapping a SurfaceTexture created from the texture reference. The
// SurfaceTexture's OnFrameAvailable() callback is tied to StreamTexture's
// OnFrameAvailable(), which fires an IPC accross the GPU channel.
// - We create a StreamTextureProxy in the Renderer process which listens for
// the IPC fired by the StreamTexture's OnFrameAvailable() callback.
// - We bind the StreamTextureProxy's lifetime to the |compositor_task_runner_|.
// - We wrap the client texture into a VideoFrame.
// - When the SurfaceTexture's OnFrameAvailable() callback is fired (and routed
// to the StreamTextureProxy living on the compositor thread), we notify
// |client_| that a new frame is available, via the DidReceiveFrame() callback.
class CONTENT_EXPORT StreamTextureWrapperImpl
: public media::StreamTextureWrapper {
public:
// |enable_texture_copy| controls the VideoFrameMetadata::COPY_REQUIRED flag,
// making sure it is correctly set on |current_frame_|, for webview scenarios.
static media::ScopedStreamTextureWrapper Create(
bool enable_texture_copy,
scoped_refptr<StreamTextureFactory> factory,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
// Creates the underlying StreamTexture, and binds |stream_texture_proxy_| to
// |compositor_task_runner|.
//
// Additional threading considerations:
// - Can be called from any thread.
// - Initialization will be posted to |main_task_runner_|.
// - |init_cb| will be run on the calling thread, and will be passed a bool
// indicating whether the initialization was successful.
// - New frames will be signaled on |compositor_task_runner| via |client|'s
// DidReceiveFrame() method.
void Initialize(
const base::Closure& received_frame_cb,
const gfx::Size& natural_size,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
const StreamTextureWrapperInitCB& init_cb) override;
// Should be called when the Video size changes.
// Can be called from any thread, but runs on |main_task_runner_|.
void UpdateTextureSize(const gfx::Size& natural_size) override;
// Returns the latest frame.
// N.B: We create a single VideoFrame at initialization time (and update it
// in UpdateTextureSize()), and repeatedly return it here. The underlying
// texture's changes are signalled via |client|'s DidReceiveFrame() callback.
scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
// Sends the StreamTexture to the browser process, to fulfill the request
// identified by |request_token|.
// Uses the gpu::ScopedSurfaceRequestConduit to forward the underlying
// SurfaceTexture to the ScopedSurfaceRequestManager.
void ForwardStreamTextureForSurfaceRequest(
const base::UnguessableToken& request_token) override;
// Clears the |received_frame_cb| passed in Initialize().
// Should be safe to call from any thread.
void ClearReceivedFrameCBOnAnyThread() override;
private:
StreamTextureWrapperImpl(
bool enable_texture_copy,
scoped_refptr<StreamTextureFactory> factory,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
~StreamTextureWrapperImpl() override;
// Destroys |this| safely on |main_task_runner_|.
void Destroy() override;
void InitializeOnMainThread(const base::Closure& received_frame_cb,
const StreamTextureWrapperInitCB& init_cb);
void ReallocateVideoFrame(const gfx::Size& natural_size);
void SetCurrentFrameInternal(
const scoped_refptr<media::VideoFrame>& video_frame);
bool enable_texture_copy_;
// Client GL texture ID allocated to the StreamTexture.
unsigned texture_id_;
// GL texture mailbox for |texture_id_|.
gpu::Mailbox texture_mailbox_;
// Object for calling back the compositor thread to repaint the video when a
// frame is available. It should be bound to |compositor_task_runner_|.
ScopedStreamTextureProxy stream_texture_proxy_;
// Size of the video frames.
gfx::Size natural_size_;
scoped_refptr<StreamTextureFactory> factory_;
base::Lock current_frame_lock_;
scoped_refptr<media::VideoFrame> current_frame_;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
base::WeakPtrFactory<StreamTextureWrapperImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(StreamTextureWrapperImpl);
};
} // namespace media
#endif // CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_WRAPPER_IMPL_H_