blob: b93e324da4cc08cc06cf940b8c77361904e752c3 [file] [log] [blame]
// Copyright 2015 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.
#include <stdint.h>
#include <vector>
#include "base/macros.h"
#include "media/gpu/android/avda_state_provider.h"
#include "media/gpu/android/avda_surface_bundle.h"
#include "media/gpu/android/surface_texture_gl_owner.h"
#include "media/gpu/media_gpu_export.h"
namespace gpu {
namespace gles2 {
class GLStreamTextureImage;
} // namespace gpu
namespace media {
class AVDACodecImage;
class AVDASharedState;
class MediaCodecBridge;
// AVDAPictureBufferManager is used by AVDA to associate its PictureBuffers with
// MediaCodec output buffers. It attaches AVDACodecImages to the PictureBuffer
// textures so that when they're used to draw the AVDACodecImage can release the
// MediaCodec buffer to the backing Surface. If the Surface is a TextureOwner,
// the front buffer can then be used to draw without needing to copy the pixels.
// If the Surface is a SurfaceView, the release causes the frame to be displayed
// immediately.
class MEDIA_GPU_EXPORT AVDAPictureBufferManager {
using PictureBufferMap = std::map<int32_t, PictureBuffer>;
explicit AVDAPictureBufferManager(AVDAStateProvider* state_provider);
virtual ~AVDAPictureBufferManager();
// Call Initialize, providing the surface bundle that holds the surface that
// will back the frames. If an overlay is present in the bundle, then this
// will set us up to render codec buffers at the appropriate time for display,
// but will assume that consuming the resulting buffers is handled elsewhere
// (e.g., SurfaceFlinger). We will ensure that any reference to the bundle
// is dropped if the overlay sends OnSurfaceDestroyed.
// Without an overlay, we will create a TextureOwner and add it (and its
// surface) to |surface_bundle|. We will arrange to consume the buffers at
// the right time, in addition to releasing the codec buffers for rendering.
// One may call these multiple times to change between overlay and ST.
// Picture buffers will be updated to reflect the new surface during the call
// to UseCodecBufferForPicture().
// Returns true on success.
bool Initialize(scoped_refptr<AVDASurfaceBundle> surface_bundle);
void Destroy(const PictureBufferMap& buffers);
// Sets up |picture_buffer| so that its texture will refer to the image that
// is represented by the decoded output buffer at codec_buffer_index.
void UseCodecBufferForPictureBuffer(int32_t codec_buffer_index,
const PictureBuffer& picture_buffer);
// Assigns a picture buffer and attaches an image to its texture.
void AssignOnePictureBuffer(const PictureBuffer& picture_buffer,
bool have_context);
// Reuses a picture buffer to hold a new frame.
void ReuseOnePictureBuffer(const PictureBuffer& picture_buffer);
// Release MediaCodec buffers.
void ReleaseCodecBuffers(const PictureBufferMap& buffers);
// Attempts to free up codec output buffers by rendering early.
void MaybeRenderEarly();
// Called when the MediaCodec instance changes. If |codec| is nullptr the
// MediaCodec is being destroyed. Previously provided codecs should no longer
// be referenced.
void CodecChanged(MediaCodecBridge* codec);
// Whether the pictures buffers are overlayable.
bool ArePicturesOverlayable();
// Are there any unrendered picture buffers oustanding?
bool HasUnrenderedPictures() const;
// Returns the GL texture target that the PictureBuffer textures use.
// Always use OES textures even though this will cause flickering in dev tools
// when inspecting a fullscreen video. See
static constexpr GLenum kTextureTarget = GL_TEXTURE_EXTERNAL_OES;
// Release any codec buffer that is associated with the given picture buffer
// back to the codec. It is okay if there is no such buffer.
void ReleaseCodecBufferForPicture(const PictureBuffer& picture_buffer);
// Sets up the texture references (as found by |picture_buffer|), for the
// specified |image|. If |image| is null, clears any ref on the texture
// associated with |picture_buffer|.
void SetImageForPicture(const PictureBuffer& picture_buffer,
gpu::gles2::GLStreamTextureImage* image);
AVDACodecImage* GetImageForPicture(int picture_buffer_id) const;
scoped_refptr<AVDASharedState> shared_state_;
AVDAStateProvider* const state_provider_;
// The texture owner to render to. Non-null after Initialize() if
// we're not rendering to a SurfaceView.
scoped_refptr<TextureOwner> texture_owner_;
MediaCodecBridge* media_codec_;
// Picture buffer IDs that are out for display. Stored in order of frames as
// they are returned from the decoder.
std::vector<int32_t> pictures_out_for_display_;
// Maps a picture buffer id to a AVDACodecImage.
std::map<int, scoped_refptr<AVDACodecImage>> codec_images_;
} // namespace media