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 "content/common/gpu/media/android_deferred_rendering_backing_strategy.h " | 5 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 const { | 112 const { |
| 113 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 113 // For SurfaceView, request a 1x1 2D texture to reduce memory during |
| 114 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 114 // initialization. For SurfaceTexture, allocate a picture buffer that is the |
| 115 // actual frame size. Note that it will be an external texture anyway, so it | 115 // actual frame size. Note that it will be an external texture anyway, so it |
| 116 // doesn't allocate an image of that size. However, it's still important to | 116 // doesn't allocate an image of that size. However, it's still important to |
| 117 // get the coded size right, so that VideoLayerImpl doesn't try to scale the | 117 // get the coded size right, so that VideoLayerImpl doesn't try to scale the |
| 118 // texture when building the quad for it. | 118 // texture when building the quad for it. |
| 119 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | 119 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); |
| 120 } | 120 } |
| 121 | 121 |
| 122 AVDACodecImage* AndroidDeferredRenderingBackingStrategy::GetImageForPicture( | |
| 123 const media::PictureBuffer& picture_buffer) { | |
| 124 gpu::gles2::TextureRef* texture_ref = | |
| 125 state_provider_->GetTextureForPicture(picture_buffer); | |
| 126 RETURN_NULL_IF_NULL(texture_ref); | |
| 127 gl::GLImage* image = | |
| 128 texture_ref->texture()->GetLevelImage(GetTextureTarget(), 0); | |
| 129 return static_cast<AVDACodecImage*>(image); | |
| 130 } | |
| 131 | |
| 132 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( | 122 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( |
| 133 const media::PictureBuffer& picture_buffer, | 123 const media::PictureBuffer& picture_buffer, |
| 134 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { | 124 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { |
| 135 gpu::gles2::TextureRef* texture_ref = | 125 gpu::gles2::TextureRef* texture_ref = |
| 136 state_provider_->GetTextureForPicture(picture_buffer); | 126 state_provider_->GetTextureForPicture(picture_buffer); |
| 137 RETURN_IF_NULL(texture_ref); | 127 RETURN_IF_NULL(texture_ref); |
| 138 | 128 |
| 139 gpu::gles2::TextureManager* texture_manager = | 129 gpu::gles2::TextureManager* texture_manager = |
| 140 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); | 130 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); |
| 141 RETURN_IF_NULL(texture_manager); | 131 RETURN_IF_NULL(texture_manager); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 } | 167 } |
| 178 | 168 |
| 179 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( | 169 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( |
| 180 int32_t codec_buf_index, | 170 int32_t codec_buf_index, |
| 181 const media::PictureBuffer& picture_buffer) { | 171 const media::PictureBuffer& picture_buffer) { |
| 182 // Make sure that the decoder is available. | 172 // Make sure that the decoder is available. |
| 183 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | 173 RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
| 184 | 174 |
| 185 // Notify the AVDACodecImage for picture_buffer that it should use the | 175 // Notify the AVDACodecImage for picture_buffer that it should use the |
| 186 // decoded buffer codec_buf_index to render this frame. | 176 // decoded buffer codec_buf_index to render this frame. |
| 187 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 177 AVDACodecImage* avda_image = |
| 178 shared_state_->GetImageForPicture(picture_buffer.id()); | |
| 188 RETURN_IF_NULL(avda_image); | 179 RETURN_IF_NULL(avda_image); |
| 189 DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1); | 180 DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1); |
| 190 // Note that this is not a race, since we do not re-use a PictureBuffer | 181 // Note that this is not a race, since we do not re-use a PictureBuffer |
| 191 // until after the CC is done drawing it. | 182 // until after the CC is done drawing it. |
| 192 avda_image->SetMediaCodecBufferIndex(codec_buf_index); | 183 avda_image->SetMediaCodecBufferIndex(codec_buf_index); |
| 193 avda_image->SetSize(state_provider_->GetSize()); | 184 avda_image->SetSize(state_provider_->GetSize()); |
| 194 } | 185 } |
| 195 | 186 |
| 196 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( | 187 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( |
| 197 const media::PictureBuffer& picture_buffer, | 188 const media::PictureBuffer& picture_buffer, |
| 198 bool have_context) { | 189 bool have_context) { |
| 199 // Attach a GLImage to each texture that will use the surface texture. | 190 // Attach a GLImage to each texture that will use the surface texture. |
| 200 // We use a refptr here in case SetImageForPicture fails. | 191 // We use a refptr here in case SetImageForPicture fails. |
| 201 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 192 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
| 202 new AVDACodecImage(shared_state_, media_codec_, | 193 new AVDACodecImage(shared_state_, media_codec_, |
| 203 state_provider_->GetGlDecoder(), surface_texture_); | 194 state_provider_->GetGlDecoder(), surface_texture_); |
| 204 SetImageForPicture(picture_buffer, gl_image); | 195 SetImageForPicture(picture_buffer, gl_image); |
| 196 shared_state_->SetImageForPicture( | |
|
liberato (no reviews please)
2016/04/21 23:39:54
perhaps pass in the picture buffer id into the cod
DaleCurtis
2016/04/22 00:11:19
Yup looks much better. Also removed Erase() entire
| |
| 197 picture_buffer.id(), static_cast<AVDACodecImage*>(gl_image.get())); | |
| 205 | 198 |
| 206 if (!surface_texture_ && have_context) { | 199 if (!surface_texture_ && have_context) { |
| 207 // To make devtools work, we're using a 2D texture. Make it transparent, | 200 // To make devtools work, we're using a 2D texture. Make it transparent, |
| 208 // so that it draws a hole for the SV to show through. This is only | 201 // so that it draws a hole for the SV to show through. This is only |
| 209 // because devtools draws and reads back, which skips overlay processing. | 202 // because devtools draws and reads back, which skips overlay processing. |
| 210 // It's unclear why devtools renders twice -- once normally, and once | 203 // It's unclear why devtools renders twice -- once normally, and once |
| 211 // including a readback layer. The result is that the device screen | 204 // including a readback layer. The result is that the device screen |
| 212 // flashes as we alternately draw the overlay hole and this texture, | 205 // flashes as we alternately draw the overlay hole and this texture, |
| 213 // unless we make the texture transparent. | 206 // unless we make the texture transparent. |
| 214 static const uint8_t rgba[] = {0, 0, 0, 0}; | 207 static const uint8_t rgba[] = {0, 0, 0, 0}; |
| 215 const gfx::Size size(1, 1); | 208 const gfx::Size size(1, 1); |
| 216 DCHECK_LE(1u, picture_buffer.texture_ids().size()); | 209 DCHECK_LE(1u, picture_buffer.texture_ids().size()); |
| 217 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); | 210 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); |
| 218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 211 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 219 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | 212 GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
| 220 } | 213 } |
| 221 } | 214 } |
| 222 | 215 |
| 223 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( | 216 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( |
| 224 const media::PictureBuffer& picture_buffer) { | 217 const media::PictureBuffer& picture_buffer) { |
| 225 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 218 AVDACodecImage* avda_image = |
| 219 shared_state_->GetImageForPicture(picture_buffer.id()); | |
| 220 RETURN_IF_NULL(avda_image); | |
| 226 | 221 |
| 227 // See if there is a media codec buffer still attached to this image. | 222 // See if there is a media codec buffer still attached to this image. |
| 228 const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex(); | 223 const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex(); |
| 229 | 224 |
| 230 if (codec_buffer >= 0) { | 225 if (codec_buffer >= 0) { |
| 231 // PictureBuffer wasn't displayed, so release the buffer. | 226 // PictureBuffer wasn't displayed, so release the buffer. |
| 232 media_codec_->ReleaseOutputBuffer(codec_buffer, false); | 227 media_codec_->ReleaseOutputBuffer(codec_buffer, false); |
| 233 avda_image->SetMediaCodecBufferIndex(-1); | 228 avda_image->SetMediaCodecBufferIndex(-1); |
| 234 } | 229 } |
| 235 } | 230 } |
| 236 | 231 |
| 237 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( | 232 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( |
| 238 const media::PictureBuffer& picture_buffer) { | 233 const media::PictureBuffer& picture_buffer) { |
| 239 // At this point, the CC must be done with the picture. We can't really | 234 // At this point, the CC must be done with the picture. We can't really |
| 240 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, | 235 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, |
| 241 // when it waits on the sync point before releasing the mailbox. That sync | 236 // when it waits on the sync point before releasing the mailbox. That sync |
| 242 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. | 237 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. |
| 243 ReleaseCodecBufferForPicture(picture_buffer); | 238 ReleaseCodecBufferForPicture(picture_buffer); |
| 244 } | 239 } |
| 245 | 240 |
| 246 void AndroidDeferredRenderingBackingStrategy::CodecChanged( | 241 void AndroidDeferredRenderingBackingStrategy::CodecChanged( |
| 247 media::VideoCodecBridge* codec, | 242 media::VideoCodecBridge* codec) { |
| 248 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | |
| 249 // Clear any outstanding codec buffer indices, since the new codec (if any) | |
| 250 // doesn't know about them. | |
| 251 media_codec_ = codec; | 243 media_codec_ = codec; |
| 252 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { | 244 shared_state_->CodecChanged(codec); |
| 253 AVDACodecImage* avda_image = GetImageForPicture(entry.second); | |
| 254 avda_image->SetMediaCodec(codec); | |
| 255 avda_image->SetMediaCodecBufferIndex(-1); | |
| 256 } | |
| 257 } | 245 } |
| 258 | 246 |
| 259 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { | 247 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { |
| 260 shared_state_->SignalFrameAvailable(); | 248 shared_state_->SignalFrameAvailable(); |
| 261 } | 249 } |
| 262 | 250 |
| 263 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { | 251 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { |
| 264 // SurfaceView frames are always overlayable because that's the only way to | 252 // SurfaceView frames are always overlayable because that's the only way to |
| 265 // display them. | 253 // display them. |
| 266 return !surface_texture_; | 254 return !surface_texture_; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 296 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); | 284 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); |
| 297 // The target texture's size will exactly match the source. | 285 // The target texture's size will exactly match the source. |
| 298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 289 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 290 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 303 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); | 291 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
| 304 } | 292 } |
| 305 | 293 |
| 306 | |
| 307 | |
| 308 float transform_matrix[16]; | 294 float transform_matrix[16]; |
| 309 surface_texture_->GetTransformMatrix(transform_matrix); | 295 surface_texture_->GetTransformMatrix(transform_matrix); |
| 310 | 296 |
| 311 gpu::CopyTextureCHROMIUMResourceManager copier; | 297 gpu::CopyTextureCHROMIUMResourceManager copier; |
| 312 copier.Initialize( | 298 copier.Initialize( |
| 313 gl_decoder, | 299 gl_decoder, |
| 314 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); | 300 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); |
| 315 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, | 301 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, |
| 316 shared_state_->surface_texture_service_id(), | 302 shared_state_->surface_texture_service_id(), |
| 317 GL_TEXTURE_2D, tmp_texture_id, size.width(), | 303 GL_TEXTURE_2D, tmp_texture_id, size.width(), |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 return !feature_info->workarounds().avda_dont_copy_pictures; | 383 return !feature_info->workarounds().avda_dont_copy_pictures; |
| 398 } | 384 } |
| 399 } | 385 } |
| 400 } | 386 } |
| 401 | 387 |
| 402 // Assume so. | 388 // Assume so. |
| 403 return true; | 389 return true; |
| 404 } | 390 } |
| 405 | 391 |
| 406 } // namespace content | 392 } // namespace content |
| OLD | NEW |