// 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. #ifndef MEDIA_GPU_AVDA_CODEC_IMAGE_H_ #define MEDIA_GPU_AVDA_CODEC_IMAGE_H_ #include #include #include "base/macros.h" #include "gpu/command_buffer/service/gl_stream_texture_image.h" #include "media/gpu/avda_shared_state.h" namespace ui { class ScopedMakeCurrent; } namespace media { class MediaCodecBridge; // GLImage that renders MediaCodec buffers to a SurfaceTexture or SurfaceView as // needed in order to draw them. class AVDACodecImage : public gpu::gles2::GLStreamTextureImage { public: AVDACodecImage(const scoped_refptr& shared_state, MediaCodecBridge* codec); // gl::GLImage implementation gfx::Size GetSize() override; unsigned GetInternalFormat() override; bool BindTexImage(unsigned target) override; void ReleaseTexImage(unsigned target) override; bool CopyTexImage(unsigned target) override; bool CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) override; bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int z_order, gfx::OverlayTransform transform, const gfx::Rect& bounds_rect, const gfx::RectF& crop_rect) override; void Flush() override {} void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, uint64_t process_tracing_id, const std::string& dump_name) override; // gpu::gles2::GLStreamTextureMatrix implementation void GetTextureMatrix(float xform[16]) override; enum class UpdateMode { // Discards the codec buffer, no UpdateTexImage(). DISCARD_CODEC_BUFFER, // Renders to back buffer, no UpdateTexImage(); can only be used with a // valid |surface_texture_|. RENDER_TO_BACK_BUFFER, // Renders to the back buffer. When used with a SurfaceView, promotion to // the front buffer is automatic. When using a |surface_texture_|, // UpdateTexImage() is called to promote the back buffer into the front. RENDER_TO_FRONT_BUFFER }; // Releases the attached codec buffer (if not already released) indicated by // |codec_buffer_index_| and updates the surface if specified by the given // |update_mode|. See UpdateMode documentation for details. void UpdateSurface(UpdateMode update_mode); // Updates the MediaCodec for this image; clears |codec_buffer_index_|. void CodecChanged(MediaCodecBridge* codec); void set_texture(gpu::gles2::Texture* texture) { texture_ = texture; } // Sets up the properties necessary for the image to render. |buffer_index| is // supplied to ReleaseOutputBuffer(), |has_surface_texture| controls which // rendering path is used, and |size| is used by the compositor. void SetBufferMetadata(int buffer_index, bool has_surface_texture, const gfx::Size& size); bool SetSharedState(scoped_refptr shared_state); // Indicates if the codec buffer has been released to the back buffer. bool was_rendered_to_back_buffer() const { return codec_buffer_index_ == kUpdateOnly; } // Indicates if the codec buffer has been released to the front buffer. bool was_rendered_to_front_buffer() const { return codec_buffer_index_ == kRendered; } bool is_unrendered() const { return codec_buffer_index_ >= kUpdateOnly; } protected: ~AVDACodecImage() override; private: // Make sure that the surface texture's front buffer is current. This will // save / restore the current context. It will optionally restore the texture // bindings in the surface texture's context, based on |mode|. This is // intended as a hint if we don't need to change contexts. If we do need to // change contexts, then we'll always preserve the texture bindings in the // both contexts. In other words, the caller is telling us whether it's // okay to change the binding in the current context. enum RestoreBindingsMode { kDontRestoreBindings, kDoRestoreBindings }; void UpdateSurfaceTexture(RestoreBindingsMode mode); // Internal helper for UpdateSurface() that allows callers to specify the // RestoreBindingsMode when a SurfaceTexture is already attached prior to // calling this method. void UpdateSurfaceInternal(UpdateMode update_mode, RestoreBindingsMode attached_bindings_mode); // Releases the attached codec buffer (if not already released) indicated by // |codec_buffer_index_|. Never updates the actual surface. See UpdateMode // documentation for details. For the purposes of this function the values // RENDER_TO_FRONT_BUFFER and RENDER_TO_BACK_BUFFER do the same thing. void ReleaseOutputBuffer(UpdateMode update_mode); // Make shared_state_->context() current if it isn't already. std::unique_ptr MakeCurrentIfNeeded(); // Return whether there is a codec buffer that we haven't rendered yet. Will // return false also if there's no codec or we otherwise can't update. bool IsCodecBufferOutstanding() const; // Shared state between the AVDA and all AVDACodecImages. scoped_refptr shared_state_; // The MediaCodec buffer index that we should render. Must be >= 0 or one of // the enum values below. enum { kUpdateOnly = -1, kRendered = -2, kInvalidCodecBufferIndex = -3 }; int codec_buffer_index_; // Our image size. gfx::Size size_; // May be null. MediaCodecBridge* media_codec_; // Indicates if we're rendering to a SurfaceTexture or not. Set during the // call to SetBufferMetadata(). bool has_surface_texture_; // The texture that we're attached to. gpu::gles2::Texture* texture_; // Bounds that we last sent to our overlay. gfx::Rect most_recent_bounds_; DISALLOW_COPY_AND_ASSIGN(AVDACodecImage); }; } // namespace media #endif // MEDIA_GPU_AVDA_CODEC_IMAGE_H_