Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/gpu/android_deferred_rendering_backing_strategy.h" | 5 #include "media/gpu/avda_picture_buffer_manager.h" |
| 6 | 6 |
| 7 #include <EGL/egl.h> | 7 #include <EGL/egl.h> |
| 8 #include <EGL/eglext.h> | 8 #include <EGL/eglext.h> |
| 9 | 9 |
| 10 #include "base/android/build_info.h" | 10 #include "base/android/build_info.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "gpu/command_buffer/service/context_group.h" | 15 #include "gpu/command_buffer/service/context_group.h" |
| 16 #include "gpu/command_buffer/service/gl_stream_texture_image.h" | 16 #include "gpu/command_buffer/service/gl_stream_texture_image.h" |
| 17 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" | 17 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" |
| 18 #include "gpu/command_buffer/service/texture_manager.h" | 18 #include "gpu/command_buffer/service/texture_manager.h" |
| 19 #include "gpu/ipc/common/gpu_surface_lookup.h" | 19 #include "gpu/ipc/common/gpu_surface_lookup.h" |
| 20 #include "gpu/ipc/service/gpu_channel.h" | 20 #include "gpu/ipc/service/gpu_channel.h" |
| 21 #include "media/base/android/sdk_media_codec_bridge.h" | |
| 21 #include "media/gpu/avda_codec_image.h" | 22 #include "media/gpu/avda_codec_image.h" |
| 22 #include "media/gpu/avda_return_on_failure.h" | |
| 23 #include "media/gpu/avda_shared_state.h" | 23 #include "media/gpu/avda_shared_state.h" |
| 24 #include "ui/gl/android/surface_texture.h" | 24 #include "ui/gl/android/surface_texture.h" |
| 25 #include "ui/gl/egl_util.h" | 25 #include "ui/gl/egl_util.h" |
| 26 #include "ui/gl/gl_bindings.h" | 26 #include "ui/gl/gl_bindings.h" |
| 27 #include "ui/gl/gl_surface_egl.h" | 27 #include "ui/gl/gl_surface_egl.h" |
| 28 #include "ui/gl/scoped_binders.h" | 28 #include "ui/gl/scoped_binders.h" |
| 29 #include "ui/gl/scoped_make_current.h" | 29 #include "ui/gl/scoped_make_current.h" |
| 30 | 30 |
| 31 // If !|ptr|, log a message, post an error to |state_provider_|, and | |
| 32 // return an optional value. | |
| 33 #define RETURN_IF_NULL(ptr, ...) \ | |
| 34 do { \ | |
| 35 if (!(ptr)) { \ | |
| 36 DLOG(ERROR) << "Got null for " << #ptr; \ | |
| 37 state_provider_->PostError(FROM_HERE, \ | |
| 38 VideoDecodeAccelerator::ILLEGAL_STATE); \ | |
| 39 return __VA_ARGS__; \ | |
| 40 } \ | |
| 41 } while (0) | |
| 42 | |
| 43 // Return nullptr if !|ptr|. | |
| 44 #define RETURN_NULL_IF_NULL(ptr) RETURN_IF_NULL(ptr, nullptr) | |
| 45 | |
| 31 namespace media { | 46 namespace media { |
| 47 namespace { | |
| 32 | 48 |
| 33 AndroidDeferredRenderingBackingStrategy:: | 49 // Creates a SurfaceTexture and attaches a new gl texture to it. |*service_id| |
| 34 AndroidDeferredRenderingBackingStrategy(AVDAStateProvider* state_provider) | 50 // is set to the new texture id. |
| 35 : state_provider_(state_provider), media_codec_(nullptr) {} | 51 scoped_refptr<gl::SurfaceTexture> CreateAttachedSurfaceTexture( |
| 52 base::WeakPtr<gpu::gles2::GLES2Decoder> gl_decoder, | |
| 53 GLuint* service_id) { | |
| 54 GLuint texture_id; | |
| 55 glGenTextures(1, &texture_id); | |
| 36 | 56 |
| 37 AndroidDeferredRenderingBackingStrategy:: | 57 glActiveTexture(GL_TEXTURE0); |
| 38 ~AndroidDeferredRenderingBackingStrategy() {} | 58 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); |
| 59 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 60 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 61 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 62 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 39 | 63 |
| 40 gl::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize( | 64 gl_decoder->RestoreTextureUnitBindings(0); |
| 65 gl_decoder->RestoreActiveTexture(); | |
| 66 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 67 | |
| 68 *service_id = texture_id; | |
| 69 // Previously, to reduce context switching, we used to create an unattached | |
| 70 // SurfaceTexture and attach it lazily in the compositor's context. But that | |
| 71 // was flaky because SurfaceTexture#detachFromGLContext() is buggy on a lot of | |
| 72 // devices. Now we attach it to the current context, which means we might have | |
| 73 // to context switch later to call updateTexImage(). Fortunately, if virtual | |
| 74 // contexts are in use, we won't have to context switch. | |
| 75 return gl::SurfaceTexture::Create(texture_id); | |
| 76 } | |
| 77 | |
| 78 } // namespace | |
| 79 | |
| 80 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, | |
| 81 // we take care that the object that wants them still exists. WeakPtrs cannot | |
| 82 // be used because OnFrameAvailable callbacks can occur on any thread. We also | |
| 83 // can't guarantee when the SurfaceTexture will quit sending callbacks to | |
| 84 // coordinate with the destruction of the AVDA and PictureBufferManager, so we | |
| 85 // have a separate object that the callback can own. | |
| 86 class AVDAPictureBufferManager::OnFrameAvailableHandler | |
| 87 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> { | |
| 88 public: | |
| 89 // We do not retain ownership of |listener|. It must remain valid until after | |
| 90 // ClearListener() is called. This will register with |surface_texture| to | |
| 91 // receive OnFrameAvailable callbacks. | |
| 92 OnFrameAvailableHandler(AVDASharedState* listener, | |
| 93 gl::SurfaceTexture* surface_texture) | |
| 94 : listener_(listener) { | |
| 95 surface_texture->SetFrameAvailableCallbackOnAnyThread( | |
| 96 base::Bind(&OnFrameAvailableHandler::OnFrameAvailable, | |
| 97 scoped_refptr<OnFrameAvailableHandler>(this))); | |
| 98 } | |
| 99 | |
| 100 // Forget about |listener_|, which is required before one deletes it. | |
| 101 // No further callbacks will happen once this completes. | |
| 102 void ClearListener() { | |
| 103 base::AutoLock lock(lock_); | |
| 104 listener_ = nullptr; | |
| 105 } | |
| 106 | |
| 107 // Notify the listener if there is one. | |
| 108 void OnFrameAvailable() { | |
| 109 base::AutoLock auto_lock(lock_); | |
| 110 if (listener_) | |
| 111 listener_->SignalFrameAvailable(); | |
| 112 } | |
| 113 | |
| 114 private: | |
| 115 friend class base::RefCountedThreadSafe<OnFrameAvailableHandler>; | |
| 116 | |
| 117 ~OnFrameAvailableHandler() { DCHECK(!listener_); } | |
| 118 | |
| 119 // Protects changes to listener_. | |
| 120 base::Lock lock_; | |
| 121 | |
| 122 // The AVDASharedState that wants the OnFrameAvailable callback. | |
| 123 AVDASharedState* listener_; | |
| 124 | |
| 125 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler); | |
| 126 }; | |
| 127 | |
| 128 AVDAPictureBufferManager::AVDAPictureBufferManager() | |
| 129 : state_provider_(nullptr), media_codec_(nullptr) {} | |
| 130 | |
| 131 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} | |
| 132 | |
| 133 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize( | |
| 134 AVDAStateProvider* state_provider, | |
| 41 int surface_view_id) { | 135 int surface_view_id) { |
| 136 state_provider_ = state_provider; | |
| 42 shared_state_ = new AVDASharedState(); | 137 shared_state_ = new AVDASharedState(); |
| 43 | 138 |
| 44 bool using_virtual_context = false; | 139 bool using_virtual_context = false; |
| 45 if (gl::GLContext* context = gl::GLContext::GetCurrent()) { | 140 if (gl::GLContext* context = gl::GLContext::GetCurrent()) { |
| 46 if (gl::GLShareGroup* share_group = context->share_group()) | 141 if (gl::GLShareGroup* share_group = context->share_group()) |
| 47 using_virtual_context = !!share_group->GetSharedContext(); | 142 using_virtual_context = !!share_group->GetSharedContext(); |
| 48 } | 143 } |
| 49 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context); | 144 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context); |
| 50 | 145 |
| 51 // Acquire the SurfaceView surface if given a valid id. | 146 // Acquire the SurfaceView surface if given a valid id. |
| 52 if (surface_view_id != VideoDecodeAccelerator::Config::kNoSurfaceID) { | 147 if (surface_view_id != VideoDecodeAccelerator::Config::kNoSurfaceID) { |
| 53 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( | 148 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( |
| 54 surface_view_id); | 149 surface_view_id); |
| 55 } | 150 } |
| 56 | 151 |
| 57 // Create a SurfaceTexture. | 152 // Otherwise create a SurfaceTexture. |
| 58 GLuint service_id = 0; | 153 GLuint service_id = 0; |
| 59 surface_texture_ = state_provider_->CreateAttachedSurfaceTexture(&service_id); | 154 surface_texture_ = CreateAttachedSurfaceTexture( |
| 155 state_provider_->GetGlDecoder(), &service_id); | |
| 156 if (surface_texture_) { | |
| 157 on_frame_available_handler_ = new OnFrameAvailableHandler( | |
| 158 shared_state_.get(), surface_texture_.get()); | |
| 159 } | |
| 60 shared_state_->SetSurfaceTexture(surface_texture_, service_id); | 160 shared_state_->SetSurfaceTexture(surface_texture_, service_id); |
| 61 return gl::ScopedJavaSurface(surface_texture_.get()); | 161 return gl::ScopedJavaSurface(surface_texture_.get()); |
| 62 } | 162 } |
| 63 | 163 |
| 64 void AndroidDeferredRenderingBackingStrategy::BeginCleanup( | 164 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { |
| 65 bool have_context, | 165 // If we have an OnFrameAvailable handler, tell it that we no longer want |
| 66 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | 166 // callbacks. |
| 67 // If we failed before Initialize, then do nothing. | 167 if (on_frame_available_handler_) |
| 68 if (!shared_state_) | 168 on_frame_available_handler_->ClearListener(); |
|
liberato (no reviews please)
2016/08/30 14:45:58
was the deletion of the |shared_state_| check inte
watk
2016/08/31 20:35:35
Oh, I don't think so, no. Thanks for catching that
| |
| 69 return; | |
| 70 | 169 |
| 71 // TODO(liberato): we should release all codec buffers here without rendering. | 170 ReleaseCodecBuffers(buffers); |
| 72 // CodecChanged() will drop them, but is expected to be called after the codec | 171 CodecChanged(nullptr); |
| 73 // is no longer accessible. It's unclear that VP8 flush in AVDA can't hang | |
| 74 // waiting for our buffers. | |
| 75 | 172 |
| 76 CodecChanged(nullptr); | |
| 77 } | |
| 78 | |
| 79 void AndroidDeferredRenderingBackingStrategy::EndCleanup() { | |
| 80 // Release the surface texture and any back buffers. This will preserve the | 173 // Release the surface texture and any back buffers. This will preserve the |
| 81 // front buffer, if any. | 174 // front buffer, if any. |
| 82 if (surface_texture_) | 175 if (surface_texture_) |
| 83 surface_texture_->ReleaseSurfaceTexture(); | 176 surface_texture_->ReleaseSurfaceTexture(); |
| 84 } | 177 } |
| 85 | 178 |
| 86 scoped_refptr<gl::SurfaceTexture> | 179 uint32_t AVDAPictureBufferManager::GetTextureTarget() const { |
| 87 AndroidDeferredRenderingBackingStrategy::GetSurfaceTexture() const { | |
| 88 return surface_texture_; | |
| 89 } | |
| 90 | |
| 91 uint32_t AndroidDeferredRenderingBackingStrategy::GetTextureTarget() const { | |
| 92 // If we're using a surface texture, then we need an external texture target | 180 // If we're using a surface texture, then we need an external texture target |
| 93 // to sample from it. If not, then we'll use 2D transparent textures to draw | 181 // to sample from it. If not, then we'll use 2D transparent textures to draw |
| 94 // a transparent hole through which to see the SurfaceView. This is normally | 182 // a transparent hole through which to see the SurfaceView. This is normally |
| 95 // needed only for the devtools inspector, since the overlay mechanism handles | 183 // needed only for the devtools inspector, since the overlay mechanism handles |
| 96 // it otherwise. | 184 // it otherwise. |
| 97 return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | 185 return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
| 98 } | 186 } |
| 99 | 187 |
| 100 gfx::Size AndroidDeferredRenderingBackingStrategy::GetPictureBufferSize() | 188 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { |
| 101 const { | |
| 102 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 189 // For SurfaceView, request a 1x1 2D texture to reduce memory during |
| 103 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 190 // initialization. For SurfaceTexture, allocate a picture buffer that is the |
| 104 // actual frame size. Note that it will be an external texture anyway, so it | 191 // actual frame size. Note that it will be an external texture anyway, so it |
| 105 // doesn't allocate an image of that size. However, it's still important to | 192 // doesn't allocate an image of that size. However, it's still important to |
| 106 // get the coded size right, so that VideoLayerImpl doesn't try to scale the | 193 // get the coded size right, so that VideoLayerImpl doesn't try to scale the |
| 107 // texture when building the quad for it. | 194 // texture when building the quad for it. |
| 108 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | 195 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); |
| 109 } | 196 } |
| 110 | 197 |
| 111 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( | 198 gpu::gles2::TextureRef* AVDAPictureBufferManager::GetTextureForPicture( |
| 199 const PictureBuffer& picture_buffer) { | |
| 200 auto gles_decoder = state_provider_->GetGlDecoder(); | |
| 201 RETURN_NULL_IF_NULL(gles_decoder); | |
| 202 RETURN_NULL_IF_NULL(gles_decoder->GetContextGroup()); | |
| 203 | |
| 204 gpu::gles2::TextureManager* texture_manager = | |
| 205 gles_decoder->GetContextGroup()->texture_manager(); | |
| 206 RETURN_NULL_IF_NULL(texture_manager); | |
| 207 | |
| 208 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size()); | |
| 209 gpu::gles2::TextureRef* texture_ref = | |
| 210 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]); | |
| 211 RETURN_NULL_IF_NULL(texture_ref); | |
| 212 | |
| 213 return texture_ref; | |
| 214 } | |
| 215 | |
| 216 void AVDAPictureBufferManager::SetImageForPicture( | |
| 112 const PictureBuffer& picture_buffer, | 217 const PictureBuffer& picture_buffer, |
| 113 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { | 218 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { |
| 114 gpu::gles2::TextureRef* texture_ref = | 219 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer); |
| 115 state_provider_->GetTextureForPicture(picture_buffer); | |
| 116 RETURN_IF_NULL(texture_ref); | 220 RETURN_IF_NULL(texture_ref); |
| 117 | 221 |
| 118 gpu::gles2::TextureManager* texture_manager = | 222 gpu::gles2::TextureManager* texture_manager = |
| 119 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); | 223 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); |
| 120 RETURN_IF_NULL(texture_manager); | 224 RETURN_IF_NULL(texture_manager); |
| 121 | 225 |
| 122 // Default to zero which will clear the stream texture service id if one was | 226 // Default to zero which will clear the stream texture service id if one was |
| 123 // previously set. | 227 // previously set. |
| 124 GLuint stream_texture_service_id = 0; | 228 GLuint stream_texture_service_id = 0; |
| 125 if (image) { | 229 if (image) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 148 // requires it. If something tries to sample from this texture it won't work, | 252 // requires it. If something tries to sample from this texture it won't work, |
| 149 // but there's no way to sample from a SurfaceView anyway, so it doesn't | 253 // but there's no way to sample from a SurfaceView anyway, so it doesn't |
| 150 // matter. | 254 // matter. |
| 151 if (image && !surface_texture_) | 255 if (image && !surface_texture_) |
| 152 image_state = gpu::gles2::Texture::BOUND; | 256 image_state = gpu::gles2::Texture::BOUND; |
| 153 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), | 257 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), |
| 154 0, image.get(), image_state, | 258 0, image.get(), image_state, |
| 155 stream_texture_service_id); | 259 stream_texture_service_id); |
| 156 } | 260 } |
| 157 | 261 |
| 158 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( | 262 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( |
| 159 int32_t codec_buf_index, | 263 int32_t codec_buf_index, |
| 160 const PictureBuffer& picture_buffer) { | 264 const PictureBuffer& picture_buffer) { |
| 161 // Make sure that the decoder is available. | 265 // Make sure that the decoder is available. |
| 162 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | 266 RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
| 163 | 267 |
| 164 // Notify the AVDACodecImage for picture_buffer that it should use the | 268 // Notify the AVDACodecImage for picture_buffer that it should use the |
| 165 // decoded buffer codec_buf_index to render this frame. | 269 // decoded buffer codec_buf_index to render this frame. |
| 166 AVDACodecImage* avda_image = | 270 AVDACodecImage* avda_image = |
| 167 shared_state_->GetImageForPicture(picture_buffer.id()); | 271 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 168 RETURN_IF_NULL(avda_image); | 272 RETURN_IF_NULL(avda_image); |
| 169 | 273 |
| 170 // Note that this is not a race, since we do not re-use a PictureBuffer | 274 // Note that this is not a race, since we do not re-use a PictureBuffer |
| 171 // until after the CC is done drawing it. | 275 // until after the CC is done drawing it. |
| 172 pictures_out_for_display_.push_back(picture_buffer.id()); | 276 pictures_out_for_display_.push_back(picture_buffer.id()); |
| 173 avda_image->set_media_codec_buffer_index(codec_buf_index); | 277 avda_image->set_media_codec_buffer_index(codec_buf_index); |
| 174 avda_image->set_size(state_provider_->GetSize()); | 278 avda_image->set_size(state_provider_->GetSize()); |
| 175 | 279 |
| 176 MaybeRenderEarly(); | 280 MaybeRenderEarly(); |
| 177 } | 281 } |
| 178 | 282 |
| 179 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( | 283 void AVDAPictureBufferManager::AssignOnePictureBuffer( |
| 180 const PictureBuffer& picture_buffer, | 284 const PictureBuffer& picture_buffer, |
| 181 bool have_context) { | 285 bool have_context) { |
| 182 // Attach a GLImage to each texture that will use the surface texture. | 286 // Attach a GLImage to each texture that will use the surface texture. |
| 183 // We use a refptr here in case SetImageForPicture fails. | 287 // We use a refptr here in case SetImageForPicture fails. |
| 184 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 288 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
| 185 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, | 289 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, |
| 186 state_provider_->GetGlDecoder(), surface_texture_); | 290 state_provider_->GetGlDecoder(), surface_texture_); |
| 187 SetImageForPicture(picture_buffer, gl_image); | 291 SetImageForPicture(picture_buffer, gl_image); |
| 188 | 292 |
| 189 if (!surface_texture_ && have_context) { | 293 if (!surface_texture_ && have_context) { |
| 190 // To make devtools work, we're using a 2D texture. Make it transparent, | 294 // To make devtools work, we're using a 2D texture. Make it transparent, |
| 191 // so that it draws a hole for the SV to show through. This is only | 295 // so that it draws a hole for the SV to show through. This is only |
| 192 // because devtools draws and reads back, which skips overlay processing. | 296 // because devtools draws and reads back, which skips overlay processing. |
| 193 // It's unclear why devtools renders twice -- once normally, and once | 297 // It's unclear why devtools renders twice -- once normally, and once |
| 194 // including a readback layer. The result is that the device screen | 298 // including a readback layer. The result is that the device screen |
| 195 // flashes as we alternately draw the overlay hole and this texture, | 299 // flashes as we alternately draw the overlay hole and this texture, |
| 196 // unless we make the texture transparent. | 300 // unless we make the texture transparent. |
| 197 static const uint8_t rgba[] = {0, 0, 0, 0}; | 301 static const uint8_t rgba[] = {0, 0, 0, 0}; |
| 198 const gfx::Size size(1, 1); | 302 const gfx::Size size(1, 1); |
| 199 DCHECK_LE(1u, picture_buffer.texture_ids().size()); | 303 DCHECK_LE(1u, picture_buffer.texture_ids().size()); |
| 200 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); | 304 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); |
| 201 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 305 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 202 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | 306 GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
| 203 } | 307 } |
| 204 } | 308 } |
| 205 | 309 |
| 206 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( | 310 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( |
| 207 const PictureBuffer& picture_buffer) { | 311 const PictureBuffer& picture_buffer) { |
| 208 AVDACodecImage* avda_image = | 312 AVDACodecImage* avda_image = |
| 209 shared_state_->GetImageForPicture(picture_buffer.id()); | 313 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 210 RETURN_IF_NULL(avda_image); | 314 RETURN_IF_NULL(avda_image); |
| 211 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); | 315 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
| 212 } | 316 } |
| 213 | 317 |
| 214 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( | 318 void AVDAPictureBufferManager::ReuseOnePictureBuffer( |
| 215 const PictureBuffer& picture_buffer) { | 319 const PictureBuffer& picture_buffer) { |
| 216 pictures_out_for_display_.erase( | 320 pictures_out_for_display_.erase( |
| 217 std::remove(pictures_out_for_display_.begin(), | 321 std::remove(pictures_out_for_display_.begin(), |
| 218 pictures_out_for_display_.end(), picture_buffer.id()), | 322 pictures_out_for_display_.end(), picture_buffer.id()), |
| 219 pictures_out_for_display_.end()); | 323 pictures_out_for_display_.end()); |
| 220 | 324 |
| 221 // At this point, the CC must be done with the picture. We can't really | 325 // At this point, the CC must be done with the picture. We can't really |
| 222 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, | 326 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, |
| 223 // when it waits on the sync point before releasing the mailbox. That sync | 327 // when it waits on the sync point before releasing the mailbox. That sync |
| 224 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. | 328 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. |
| 225 ReleaseCodecBufferForPicture(picture_buffer); | 329 ReleaseCodecBufferForPicture(picture_buffer); |
| 226 MaybeRenderEarly(); | 330 MaybeRenderEarly(); |
| 227 } | 331 } |
| 228 | 332 |
| 229 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBuffers( | 333 void AVDAPictureBufferManager::ReleaseCodecBuffers( |
| 230 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | 334 const PictureBufferMap& buffers) { |
| 231 for (const std::pair<int, PictureBuffer>& entry : buffers) | 335 for (const std::pair<int, PictureBuffer>& entry : buffers) |
| 232 ReleaseCodecBufferForPicture(entry.second); | 336 ReleaseCodecBufferForPicture(entry.second); |
| 233 } | 337 } |
| 234 | 338 |
| 235 void AndroidDeferredRenderingBackingStrategy::MaybeRenderEarly() { | 339 void AVDAPictureBufferManager::MaybeRenderEarly() { |
| 236 if (pictures_out_for_display_.empty()) | 340 if (pictures_out_for_display_.empty()) |
| 237 return; | 341 return; |
| 238 | 342 |
| 239 // See if we can consume the front buffer / render to the SurfaceView. Iterate | 343 // See if we can consume the front buffer / render to the SurfaceView. Iterate |
| 240 // in reverse to find the most recent front buffer. If none is found, the | 344 // in reverse to find the most recent front buffer. If none is found, the |
| 241 // |front_index| will point to the beginning of the array. | 345 // |front_index| will point to the beginning of the array. |
| 242 size_t front_index = pictures_out_for_display_.size() - 1; | 346 size_t front_index = pictures_out_for_display_.size() - 1; |
| 243 AVDACodecImage* first_renderable_image = nullptr; | 347 AVDACodecImage* first_renderable_image = nullptr; |
| 244 for (int i = front_index; i >= 0; --i) { | 348 for (int i = front_index; i >= 0; --i) { |
| 245 const int id = pictures_out_for_display_[i]; | 349 const int id = pictures_out_for_display_[i]; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 first_renderable_image->was_rendered_to_back_buffer()) { | 384 first_renderable_image->was_rendered_to_back_buffer()) { |
| 281 return; | 385 return; |
| 282 } | 386 } |
| 283 | 387 |
| 284 // Due to the loop in the beginning this should never be true. | 388 // Due to the loop in the beginning this should never be true. |
| 285 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); | 389 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); |
| 286 first_renderable_image->UpdateSurface( | 390 first_renderable_image->UpdateSurface( |
| 287 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); | 391 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); |
| 288 } | 392 } |
| 289 | 393 |
| 290 void AndroidDeferredRenderingBackingStrategy::CodecChanged( | 394 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { |
| 291 VideoCodecBridge* codec) { | |
| 292 media_codec_ = codec; | 395 media_codec_ = codec; |
| 293 shared_state_->CodecChanged(codec); | 396 shared_state_->CodecChanged(codec); |
| 294 } | 397 } |
| 295 | 398 |
| 296 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { | 399 bool AVDAPictureBufferManager::ArePicturesOverlayable() { |
| 297 shared_state_->SignalFrameAvailable(); | |
| 298 } | |
| 299 | |
| 300 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { | |
| 301 // SurfaceView frames are always overlayable because that's the only way to | 400 // SurfaceView frames are always overlayable because that's the only way to |
| 302 // display them. | 401 // display them. |
| 303 return !surface_texture_; | 402 return !surface_texture_; |
| 304 } | 403 } |
| 305 | 404 |
| 306 void AndroidDeferredRenderingBackingStrategy::UpdatePictureBufferSize( | |
| 307 PictureBuffer* picture_buffer, | |
| 308 const gfx::Size& new_size) { | |
| 309 // This strategy uses EGL images which manage the texture size for us. We | |
| 310 // simply update the PictureBuffer meta-data and leave the texture as-is. | |
| 311 picture_buffer->set_size(new_size); | |
| 312 } | |
| 313 | |
| 314 } // namespace media | 405 } // namespace media |
| OLD | NEW |