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/avda_picture_buffer_manager.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" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 // SurfaceTexture and attach it lazily in the compositor's context. But that | 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 | 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 | 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 | 73 // to context switch later to call updateTexImage(). Fortunately, if virtual |
| 74 // contexts are in use, we won't have to context switch. | 74 // contexts are in use, we won't have to context switch. |
| 75 return gl::SurfaceTexture::Create(texture_id); | 75 return gl::SurfaceTexture::Create(texture_id); |
| 76 } | 76 } |
| 77 | 77 |
| 78 } // namespace | 78 } // namespace |
| 79 | 79 |
| 80 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, | 80 AVDAPictureBufferManager::AVDAPictureBufferManager( |
| 81 // we take care that the object that wants them still exists. WeakPtrs cannot | 81 AVDAStateProvider* state_provider) |
| 82 // be used because OnFrameAvailable callbacks can occur on any thread. We also | 82 : state_provider_(state_provider), media_codec_(nullptr) {} |
| 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 | 83 |
| 131 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} | 84 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} |
| 132 | 85 |
| 133 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize( | 86 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize(int surface_id) { |
| 134 AVDAStateProvider* state_provider, | |
| 135 int surface_view_id) { | |
| 136 state_provider_ = state_provider; | |
| 137 shared_state_ = new AVDASharedState(); | 87 shared_state_ = new AVDASharedState(); |
| 138 | 88 |
| 139 // Acquire the SurfaceView surface if given a valid id. | 89 // Acquire the SurfaceView surface if given a valid id. |
| 140 if (surface_view_id != VideoDecodeAccelerator::Config::kNoSurfaceID) { | 90 if (surface_id != SurfaceManager::kNoSurfaceID) { |
| 141 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( | 91 if (surface_texture_) { |
| 142 surface_view_id); | 92 surface_texture_->ReleaseSurfaceTexture(); |
| 93 surface_texture_ = nullptr; | |
| 94 } | |
| 95 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_id); | |
| 143 } | 96 } |
| 144 | 97 |
| 145 // Otherwise create a SurfaceTexture. | 98 // Always create a SurfaceTexture, we'll use it for entering and exiting from |
| 146 GLuint service_id = 0; | 99 // fullscreen mode. |
| 100 GLuint service_id; | |
| 147 surface_texture_ = CreateAttachedSurfaceTexture( | 101 surface_texture_ = CreateAttachedSurfaceTexture( |
| 148 state_provider_->GetGlDecoder(), &service_id); | 102 state_provider_->GetGlDecoder(), &service_id); |
| 149 if (surface_texture_) { | |
| 150 on_frame_available_handler_ = new OnFrameAvailableHandler( | |
| 151 shared_state_.get(), surface_texture_.get()); | |
| 152 } | |
| 153 shared_state_->SetSurfaceTexture(surface_texture_, service_id); | 103 shared_state_->SetSurfaceTexture(surface_texture_, service_id); |
| 154 return gl::ScopedJavaSurface(surface_texture_.get()); | 104 return gl::ScopedJavaSurface(surface_texture_.get()); |
| 155 } | 105 } |
| 156 | 106 |
| 157 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { | 107 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { |
| 158 // Do nothing if Initialize() has not been called. | 108 // Do nothing if Initialize() has not been called. |
| 159 if (!shared_state_) | 109 if (!shared_state_) |
| 160 return; | 110 return; |
| 161 | 111 |
| 162 // If we have an OnFrameAvailable handler, tell it that we no longer want | |
| 163 // callbacks. | |
| 164 if (on_frame_available_handler_) | |
| 165 on_frame_available_handler_->ClearListener(); | |
| 166 | |
| 167 ReleaseCodecBuffers(buffers); | 112 ReleaseCodecBuffers(buffers); |
| 168 CodecChanged(nullptr); | 113 CodecChanged(nullptr); |
| 169 | 114 |
| 170 // Release the surface texture and any back buffers. This will preserve the | 115 // Release the surface texture and any back buffers. This will preserve the |
| 171 // front buffer, if any. | 116 // front buffer, if any. |
| 172 if (surface_texture_) | 117 if (surface_texture_) |
| 173 surface_texture_->ReleaseSurfaceTexture(); | 118 surface_texture_->ReleaseSurfaceTexture(); |
| 174 } | 119 } |
| 175 | 120 |
| 176 uint32_t AVDAPictureBufferManager::GetTextureTarget() const { | 121 uint32_t AVDAPictureBufferManager::GetTextureTarget() const { |
| 177 // If we're using a surface texture, then we need an external texture target | 122 // Always use OES textures even though this will cause flickering in dev tools |
| 178 // to sample from it. If not, then we'll use 2D transparent textures to draw | 123 // when inspecting a fullscreen video. See http://crbug.com/592798 |
| 179 // a transparent hole through which to see the SurfaceView. This is normally | 124 return GL_TEXTURE_EXTERNAL_OES; |
| 180 // needed only for the devtools inspector, since the overlay mechanism handles | |
| 181 // it otherwise. | |
| 182 return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | |
| 183 } | 125 } |
| 184 | 126 |
| 185 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { | 127 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { |
| 186 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 128 // Allocate a picture buffer that is the actual frame size. Note that it will |
| 187 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 129 // be an external texture anyway, so it doesn't allocate an image of that |
| 188 // actual frame size. Note that it will be an external texture anyway, so it | 130 // size. It's important to get the coded size right, so that VideoLayerImpl |
| 189 // doesn't allocate an image of that size. However, it's still important to | 131 // doesn't try to scale the texture when building the quad for it. |
| 190 // get the coded size right, so that VideoLayerImpl doesn't try to scale the | 132 return state_provider_->GetSize(); |
| 191 // texture when building the quad for it. | |
| 192 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | |
| 193 } | 133 } |
| 194 | 134 |
| 195 gpu::gles2::TextureRef* AVDAPictureBufferManager::GetTextureForPicture( | 135 gpu::gles2::TextureRef* AVDAPictureBufferManager::GetTextureForPicture( |
| 196 const PictureBuffer& picture_buffer) { | 136 const PictureBuffer& picture_buffer) { |
| 197 auto gles_decoder = state_provider_->GetGlDecoder(); | 137 auto gles_decoder = state_provider_->GetGlDecoder(); |
| 198 RETURN_NULL_IF_NULL(gles_decoder); | 138 RETURN_NULL_IF_NULL(gles_decoder); |
| 199 RETURN_NULL_IF_NULL(gles_decoder->GetContextGroup()); | 139 RETURN_NULL_IF_NULL(gles_decoder->GetContextGroup()); |
| 200 | 140 |
| 201 gpu::gles2::TextureManager* texture_manager = | 141 gpu::gles2::TextureManager* texture_manager = |
| 202 gles_decoder->GetContextGroup()->texture_manager(); | 142 gles_decoder->GetContextGroup()->texture_manager(); |
| 203 RETURN_NULL_IF_NULL(texture_manager); | 143 RETURN_NULL_IF_NULL(texture_manager); |
| 204 | 144 |
| 205 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); | 145 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); |
| 206 gpu::gles2::TextureRef* texture_ref = | 146 gpu::gles2::TextureRef* texture_ref = |
| 207 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); | 147 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); |
| 208 RETURN_NULL_IF_NULL(texture_ref); | 148 RETURN_NULL_IF_NULL(texture_ref); |
| 209 | 149 |
| 210 return texture_ref; | 150 return texture_ref; |
| 211 } | 151 } |
| 212 | 152 |
| 213 void AVDAPictureBufferManager::SetImageForPicture( | 153 void AVDAPictureBufferManager::SetImageForPicture( |
| 214 const PictureBuffer& picture_buffer, | 154 const PictureBuffer& picture_buffer, |
| 215 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { | 155 gpu::gles2::GLStreamTextureImage* image) { |
| 216 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer); | 156 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer); |
| 217 RETURN_IF_NULL(texture_ref); | 157 RETURN_IF_NULL(texture_ref); |
| 218 | 158 |
| 219 gpu::gles2::TextureManager* texture_manager = | 159 gpu::gles2::TextureManager* texture_manager = |
| 220 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); | 160 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); |
| 221 RETURN_IF_NULL(texture_manager); | 161 RETURN_IF_NULL(texture_manager); |
| 222 | 162 |
| 223 // Default to zero which will clear the stream texture service id if one was | 163 // Default to zero which will clear the stream texture service id if one was |
| 224 // previously set. | 164 // previously set. |
| 225 GLuint stream_texture_service_id = 0; | 165 GLuint stream_texture_service_id = 0; |
| 226 if (image) { | 166 if (image) { |
| 227 if (shared_state_->surface_texture_service_id() != 0) { | 167 if (shared_state_->surface_texture_service_id() != 0) { |
| 228 // Override the Texture's service id, so that it will use the one that is | 168 // Override the Texture's service id, so that it will use the one that is |
| 229 // attached to the SurfaceTexture. | 169 // attached to the SurfaceTexture. |
| 230 stream_texture_service_id = shared_state_->surface_texture_service_id(); | 170 stream_texture_service_id = shared_state_->surface_texture_service_id(); |
| 231 } | 171 } |
| 232 | 172 |
| 233 // Also set the parameters for the level if we're not clearing the image. | 173 // Also set the parameters for the level if we're not clearing the image. |
| 234 const gfx::Size size = state_provider_->GetSize(); | 174 const gfx::Size size = state_provider_->GetSize(); |
| 235 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, | 175 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, |
| 236 size.width(), size.height(), 1, 0, GL_RGBA, | 176 size.width(), size.height(), 1, 0, GL_RGBA, |
| 237 GL_UNSIGNED_BYTE, gfx::Rect()); | 177 GL_UNSIGNED_BYTE, gfx::Rect()); |
| 238 | 178 |
| 239 static_cast<AVDACodecImage*>(image.get()) | 179 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture()); |
| 240 ->set_texture(texture_ref->texture()); | |
| 241 } | 180 } |
| 242 | 181 |
| 243 // If we're clearing the image, or setting a SurfaceTexture backed image, we | 182 // If we're clearing the image, or setting a SurfaceTexture backed image, we |
| 244 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the | 183 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the |
| 245 // implementation will call CopyTexImage, which is where AVDACodecImage | 184 // implementation will call CopyTexImage, which is where AVDACodecImage |
| 246 // updates the SurfaceTexture to the right frame. | 185 // updates the SurfaceTexture to the right frame. |
| 247 auto image_state = gpu::gles2::Texture::UNBOUND; | 186 auto image_state = gpu::gles2::Texture::UNBOUND; |
| 248 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane | 187 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane |
| 249 // requires it. If something tries to sample from this texture it won't work, | 188 // requires it. If something tries to sample from this texture it won't work, |
| 250 // but there's no way to sample from a SurfaceView anyway, so it doesn't | 189 // but there's no way to sample from a SurfaceView anyway, so it doesn't |
| 251 // matter. | 190 // matter. |
| 252 if (image && !surface_texture_) | 191 if (image && !shared_state_->surface_texture_service_id()) |
| 253 image_state = gpu::gles2::Texture::BOUND; | 192 image_state = gpu::gles2::Texture::BOUND; |
| 254 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), | 193 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), |
| 255 0, image.get(), image_state, | 194 0, image, image_state, |
| 256 stream_texture_service_id); | 195 stream_texture_service_id); |
| 257 } | 196 } |
| 258 | 197 |
| 198 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture( | |
| 199 int picture_buffer_id) const { | |
| 200 auto it = codec_images_.find(picture_buffer_id); | |
| 201 return it == codec_images_.end() ? nullptr : it->second; | |
| 202 } | |
| 203 | |
| 259 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( | 204 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( |
| 260 int32_t codec_buf_index, | 205 int32_t codec_buf_index, |
| 261 const PictureBuffer& picture_buffer) { | 206 const PictureBuffer& picture_buffer) { |
| 262 // Make sure that the decoder is available. | 207 // Make sure that the decoder is available. |
| 263 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | 208 RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
| 264 | 209 |
| 265 // Notify the AVDACodecImage for picture_buffer that it should use the | 210 // Notify the AVDACodecImage for picture_buffer that it should use the |
| 266 // decoded buffer codec_buf_index to render this frame. | 211 // decoded buffer codec_buf_index to render this frame. |
| 267 AVDACodecImage* avda_image = | 212 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); |
| 268 shared_state_->GetImageForPicture(picture_buffer.id()); | |
| 269 RETURN_IF_NULL(avda_image); | 213 RETURN_IF_NULL(avda_image); |
| 270 | 214 |
| 271 // Note that this is not a race, since we do not re-use a PictureBuffer | 215 // Note that this is not a race, since we do not re-use a PictureBuffer |
| 272 // until after the CC is done drawing it. | 216 // until after the CC is done drawing it. |
| 273 pictures_out_for_display_.push_back(picture_buffer.id()); | 217 pictures_out_for_display_.push_back(picture_buffer.id()); |
| 274 avda_image->set_media_codec_buffer_index(codec_buf_index); | 218 avda_image->SetBufferMetadata(codec_buf_index, |
| 275 avda_image->set_size(state_provider_->GetSize()); | 219 !!shared_state_->surface_texture_service_id(), |
| 220 state_provider_->GetSize()); | |
| 221 | |
| 222 // If the shared state has changed for this image, retarget its texture. | |
| 223 if (avda_image->SetSharedState(shared_state_)) { | |
| 224 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer); | |
| 225 RETURN_IF_NULL(texture_ref); | |
| 226 texture_ref->texture()->SetStreamTextureServiceId( | |
| 227 shared_state_->surface_texture_service_id()); | |
| 228 | |
| 229 // TODO(dalecurtis): What about ImageState? For ST we set UNBOUND while we | |
| 230 // always set BOUND for SV. | |
|
liberato (no reviews please)
2016/11/03 20:51:04
we should do that here too, i think.
actually, i
DaleCurtis
2016/11/03 20:59:35
Originally tried this, but there are some restrict
DaleCurtis
2016/11/03 23:25:05
Ah, this was because the last ref to the GLImage w
| |
| 231 } | |
| 276 | 232 |
| 277 MaybeRenderEarly(); | 233 MaybeRenderEarly(); |
| 278 } | 234 } |
| 279 | 235 |
| 280 void AVDAPictureBufferManager::AssignOnePictureBuffer( | 236 void AVDAPictureBufferManager::AssignOnePictureBuffer( |
| 281 const PictureBuffer& picture_buffer, | 237 const PictureBuffer& picture_buffer, |
| 282 bool have_context) { | 238 bool have_context) { |
| 283 // Attach a GLImage to each texture that will use the surface texture. | 239 // Attach a GLImage to each texture that will use the surface texture. |
| 284 // We use a refptr here in case SetImageForPicture fails. | 240 // We use a refptr here in case SetImageForPicture fails. |
| 285 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 241 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = new AVDACodecImage( |
| 286 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, | 242 shared_state_, media_codec_, state_provider_->GetGlDecoder()); |
| 287 state_provider_->GetGlDecoder()); | 243 SetImageForPicture(picture_buffer, gl_image.get()); |
| 288 SetImageForPicture(picture_buffer, gl_image); | 244 codec_images_[picture_buffer.id()] = |
| 245 static_cast<AVDACodecImage*>(gl_image.get()); | |
| 289 | 246 |
| 290 if (!surface_texture_ && have_context) { | 247 // if (!shared_state_->surface_texture_service_id() && have_context) { |
| 291 // To make devtools work, we're using a 2D texture. Make it transparent, | 248 // // To make devtools work, we're using a 2D texture. Make it transparent, |
| 292 // so that it draws a hole for the SV to show through. This is only | 249 // // so that it draws a hole for the SV to show through. This is only |
| 293 // because devtools draws and reads back, which skips overlay processing. | 250 // // because devtools draws and reads back, which skips overlay processing. |
| 294 // It's unclear why devtools renders twice -- once normally, and once | 251 // // It's unclear why devtools renders twice -- once normally, and once |
| 295 // including a readback layer. The result is that the device screen | 252 // // including a readback layer. The result is that the device screen |
| 296 // flashes as we alternately draw the overlay hole and this texture, | 253 // // flashes as we alternately draw the overlay hole and this texture, |
| 297 // unless we make the texture transparent. | 254 // // unless we make the texture transparent. |
| 298 static const uint8_t rgba[] = {0, 0, 0, 0}; | 255 // static const uint8_t rgba[] = {0, 0, 0, 0}; |
| 299 const gfx::Size size(1, 1); | 256 // const gfx::Size size(1, 1); |
| 300 DCHECK_LE(1u, picture_buffer.service_texture_ids().size()); | 257 // DCHECK_LE(1u, picture_buffer.service_texture_ids().size()); |
| 301 glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]); | 258 // glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]); |
| 302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 259 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 303 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | 260 // GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
| 304 } | 261 // } |
| 305 } | 262 } |
| 306 | 263 |
| 307 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( | 264 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( |
| 308 const PictureBuffer& picture_buffer) { | 265 const PictureBuffer& picture_buffer) { |
| 309 AVDACodecImage* avda_image = | 266 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); |
| 310 shared_state_->GetImageForPicture(picture_buffer.id()); | |
| 311 RETURN_IF_NULL(avda_image); | 267 RETURN_IF_NULL(avda_image); |
| 312 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); | 268 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
| 313 } | 269 } |
| 314 | 270 |
| 315 void AVDAPictureBufferManager::ReuseOnePictureBuffer( | 271 void AVDAPictureBufferManager::ReuseOnePictureBuffer( |
| 316 const PictureBuffer& picture_buffer) { | 272 const PictureBuffer& picture_buffer) { |
| 317 pictures_out_for_display_.erase( | 273 pictures_out_for_display_.erase( |
| 318 std::remove(pictures_out_for_display_.begin(), | 274 std::remove(pictures_out_for_display_.begin(), |
| 319 pictures_out_for_display_.end(), picture_buffer.id()), | 275 pictures_out_for_display_.end(), picture_buffer.id()), |
| 320 pictures_out_for_display_.end()); | 276 pictures_out_for_display_.end()); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 337 if (pictures_out_for_display_.empty()) | 293 if (pictures_out_for_display_.empty()) |
| 338 return; | 294 return; |
| 339 | 295 |
| 340 // See if we can consume the front buffer / render to the SurfaceView. Iterate | 296 // See if we can consume the front buffer / render to the SurfaceView. Iterate |
| 341 // in reverse to find the most recent front buffer. If none is found, the | 297 // in reverse to find the most recent front buffer. If none is found, the |
| 342 // |front_index| will point to the beginning of the array. | 298 // |front_index| will point to the beginning of the array. |
| 343 size_t front_index = pictures_out_for_display_.size() - 1; | 299 size_t front_index = pictures_out_for_display_.size() - 1; |
| 344 AVDACodecImage* first_renderable_image = nullptr; | 300 AVDACodecImage* first_renderable_image = nullptr; |
| 345 for (int i = front_index; i >= 0; --i) { | 301 for (int i = front_index; i >= 0; --i) { |
| 346 const int id = pictures_out_for_display_[i]; | 302 const int id = pictures_out_for_display_[i]; |
| 347 AVDACodecImage* avda_image = shared_state_->GetImageForPicture(id); | 303 AVDACodecImage* avda_image = GetImageForPicture(id); |
| 348 if (!avda_image) | 304 if (!avda_image) |
| 349 continue; | 305 continue; |
| 350 | 306 |
| 351 // Update the front buffer index as we move along to shorten the number of | 307 // Update the front buffer index as we move along to shorten the number of |
| 352 // candidate images we look at for back buffer rendering. | 308 // candidate images we look at for back buffer rendering. |
| 353 front_index = i; | 309 front_index = i; |
| 354 first_renderable_image = avda_image; | 310 first_renderable_image = avda_image; |
| 355 | 311 |
| 356 // If we find a front buffer, stop and indicate that front buffer rendering | 312 // If we find a front buffer, stop and indicate that front buffer rendering |
| 357 // is not possible since another image is already in the front buffer. | 313 // is not possible since another image is already in the front buffer. |
| 358 if (avda_image->was_rendered_to_front_buffer()) { | 314 if (avda_image->was_rendered_to_front_buffer()) { |
| 359 first_renderable_image = nullptr; | 315 first_renderable_image = nullptr; |
| 360 break; | 316 break; |
| 361 } | 317 } |
| 362 } | 318 } |
| 363 | 319 |
| 364 if (first_renderable_image) { | 320 if (first_renderable_image) { |
| 365 first_renderable_image->UpdateSurface( | 321 first_renderable_image->UpdateSurface( |
| 366 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); | 322 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); |
| 367 } | 323 } |
| 368 | 324 |
| 369 // Back buffer rendering is only available for surface textures. We'll always | 325 // Back buffer rendering is only available for surface textures. We'll always |
| 370 // have at least one front buffer, so the next buffer must be the backbuffer. | 326 // have at least one front buffer, so the next buffer must be the backbuffer. |
| 371 size_t backbuffer_index = front_index + 1; | 327 size_t backbuffer_index = front_index + 1; |
| 372 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) | 328 if (!shared_state_->surface_texture_service_id() || |
| 329 backbuffer_index >= pictures_out_for_display_.size()) { | |
| 373 return; | 330 return; |
| 331 } | |
| 374 | 332 |
| 375 // See if the back buffer is free. If so, then render the frame adjacent to | 333 // See if the back buffer is free. If so, then render the frame adjacent to |
| 376 // the front buffer. The listing is in render order, so we can just use the | 334 // the front buffer. The listing is in render order, so we can just use the |
| 377 // first unrendered frame if there is back buffer space. | 335 // first unrendered frame if there is back buffer space. |
| 378 first_renderable_image = shared_state_->GetImageForPicture( | 336 first_renderable_image = |
| 379 pictures_out_for_display_[backbuffer_index]); | 337 GetImageForPicture(pictures_out_for_display_[backbuffer_index]); |
| 380 if (!first_renderable_image || | 338 if (!first_renderable_image || |
| 381 first_renderable_image->was_rendered_to_back_buffer()) { | 339 first_renderable_image->was_rendered_to_back_buffer()) { |
| 382 return; | 340 return; |
| 383 } | 341 } |
| 384 | 342 |
| 385 // Due to the loop in the beginning this should never be true. | 343 // Due to the loop in the beginning this should never be true. |
| 386 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); | 344 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); |
| 387 first_renderable_image->UpdateSurface( | 345 first_renderable_image->UpdateSurface( |
| 388 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); | 346 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); |
| 389 } | 347 } |
| 390 | 348 |
| 391 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { | 349 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { |
| 392 media_codec_ = codec; | 350 media_codec_ = codec; |
| 393 shared_state_->CodecChanged(codec); | 351 for (auto& image_kv : codec_images_) |
| 352 image_kv.second->CodecChanged(codec); | |
| 353 shared_state_->clear_release_time(); | |
| 394 } | 354 } |
| 395 | 355 |
| 396 bool AVDAPictureBufferManager::ArePicturesOverlayable() { | 356 bool AVDAPictureBufferManager::ArePicturesOverlayable() { |
| 397 // SurfaceView frames are always overlayable because that's the only way to | 357 // SurfaceView frames are always overlayable because that's the only way to |
| 398 // display them. | 358 // display them. |
| 399 return !surface_texture_; | 359 return !shared_state_->surface_texture_service_id(); |
| 360 } | |
| 361 | |
| 362 bool AVDAPictureBufferManager::ArePicturesOutstanding() const { | |
| 363 for (int id : pictures_out_for_display_) { | |
| 364 AVDACodecImage* avda_image = GetImageForPicture(id); | |
| 365 if (avda_image && avda_image->has_unrendered_frame()) | |
| 366 return true; | |
| 367 } | |
| 368 return false; | |
| 400 } | 369 } |
| 401 | 370 |
| 402 } // namespace media | 371 } // namespace media |
| OLD | NEW |