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/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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 size.width(), size.height(), 1, 0, GL_RGBA, | 140 size.width(), size.height(), 1, 0, GL_RGBA, |
| 141 GL_UNSIGNED_BYTE, gfx::Rect()); | 141 GL_UNSIGNED_BYTE, gfx::Rect()); |
| 142 | 142 |
| 143 // Override the texture's service_id, so that it will use the one that | 143 // Override the texture's service_id, so that it will use the one that |
| 144 // will be / is attached to the SurfaceTexture. | 144 // will be / is attached to the SurfaceTexture. |
| 145 DCHECK(shared_state_->surface_texture_service_id()); | 145 DCHECK(shared_state_->surface_texture_service_id()); |
| 146 texture_ref->texture()->SetUnownedServiceId( | 146 texture_ref->texture()->SetUnownedServiceId( |
| 147 shared_state_->surface_texture_service_id()); | 147 shared_state_->surface_texture_service_id()); |
| 148 | 148 |
| 149 static_cast<AVDACodecImage*>(image.get()) | 149 static_cast<AVDACodecImage*>(image.get()) |
| 150 ->SetTexture(texture_ref->texture()); | 150 ->set_texture(texture_ref->texture()); |
| 151 } else { | 151 } else { |
| 152 // Clear the unowned service_id, so that this texture is no longer going | 152 // Clear the unowned service_id, so that this texture is no longer going |
| 153 // to depend on the surface texture at all. | 153 // to depend on the surface texture at all. |
| 154 texture_ref->texture()->SetUnownedServiceId(0); | 154 texture_ref->texture()->SetUnownedServiceId(0); |
| 155 } | 155 } |
| 156 | 156 |
| 157 // For SurfaceTexture we set the image to UNBOUND so that the implementation | 157 // For SurfaceTexture we set the image to UNBOUND so that the implementation |
| 158 // will call CopyTexImage, which is where AVDACodecImage updates the | 158 // will call CopyTexImage, which is where AVDACodecImage updates the |
| 159 // SurfaceTexture to the right frame. | 159 // SurfaceTexture to the right frame. |
| 160 // For SurfaceView we set the image to be BOUND because ScheduleOverlayPlane | 160 // For SurfaceView we set the image to be BOUND because ScheduleOverlayPlane |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 176 | 176 |
| 177 // Notify the AVDACodecImage for picture_buffer that it should use the | 177 // Notify the AVDACodecImage for picture_buffer that it should use the |
| 178 // decoded buffer codec_buf_index to render this frame. | 178 // decoded buffer codec_buf_index to render this frame. |
| 179 AVDACodecImage* avda_image = | 179 AVDACodecImage* avda_image = |
| 180 shared_state_->GetImageForPicture(picture_buffer.id()); | 180 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 181 RETURN_IF_NULL(avda_image); | 181 RETURN_IF_NULL(avda_image); |
| 182 | 182 |
| 183 // Note that this is not a race, since we do not re-use a PictureBuffer | 183 // Note that this is not a race, since we do not re-use a PictureBuffer |
| 184 // until after the CC is done drawing it. | 184 // until after the CC is done drawing it. |
| 185 pictures_out_for_display_.push_back(picture_buffer.id()); | 185 pictures_out_for_display_.push_back(picture_buffer.id()); |
| 186 avda_image->SetMediaCodecBufferIndex(codec_buf_index); | 186 avda_image->set_media_codec_buffer_index(codec_buf_index); |
| 187 avda_image->SetSize(state_provider_->GetSize()); | 187 avda_image->set_size(state_provider_->GetSize()); |
| 188 | 188 |
| 189 MaybeRenderEarly(); | 189 MaybeRenderEarly(); |
| 190 } | 190 } |
| 191 | 191 |
| 192 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( | 192 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( |
| 193 const media::PictureBuffer& picture_buffer, | 193 const media::PictureBuffer& picture_buffer, |
| 194 bool have_context) { | 194 bool have_context) { |
| 195 // Attach a GLImage to each texture that will use the surface texture. | 195 // Attach a GLImage to each texture that will use the surface texture. |
| 196 // We use a refptr here in case SetImageForPicture fails. | 196 // We use a refptr here in case SetImageForPicture fails. |
| 197 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 197 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 MaybeRenderEarly(); | 239 MaybeRenderEarly(); |
| 240 } | 240 } |
| 241 | 241 |
| 242 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBuffers( | 242 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBuffers( |
| 243 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | 243 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { |
| 244 for (const std::pair<int, media::PictureBuffer>& entry : buffers) | 244 for (const std::pair<int, media::PictureBuffer>& entry : buffers) |
| 245 ReleaseCodecBufferForPicture(entry.second); | 245 ReleaseCodecBufferForPicture(entry.second); |
| 246 } | 246 } |
| 247 | 247 |
| 248 void AndroidDeferredRenderingBackingStrategy::MaybeRenderEarly() { | 248 void AndroidDeferredRenderingBackingStrategy::MaybeRenderEarly() { |
| 249 // See if we can consume the front buffer / render to the SurfaceView. | 249 if (pictures_out_for_display_.empty()) |
| 250 if (pictures_out_for_display_.size() == 1u) { | |
| 251 AVDACodecImage* avda_image = | |
| 252 shared_state_->GetImageForPicture(*pictures_out_for_display_.begin()); | |
| 253 RETURN_IF_NULL(avda_image); | |
| 254 avda_image->UpdateSurface( | |
| 255 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 259 // Back buffer rendering is only available for surface textures. | |
| 260 if (!surface_texture_) | |
| 261 return; | 250 return; |
| 262 | 251 |
| 263 // See if the back buffer is free. If so, then render the earliest frame. The | 252 // See if we can consume the front buffer / render to the SurfaceView. Iterate |
| 264 // listing is in render order, so we can just use the first unrendered frame | 253 // in reverse to find the most recent front buffer. If none is found, the |
| 265 // if there is back buffer space. | 254 // |front_index| will point to the beginning of the array. |
| 255 size_t front_index = pictures_out_for_display_.size() - 1; | |
| 266 AVDACodecImage* first_renderable_image = nullptr; | 256 AVDACodecImage* first_renderable_image = nullptr; |
| 267 for (int id : pictures_out_for_display_) { | 257 for (int i = front_index; i >= 0; --i) { |
| 258 const int id = pictures_out_for_display_[i]; | |
| 268 AVDACodecImage* avda_image = shared_state_->GetImageForPicture(id); | 259 AVDACodecImage* avda_image = shared_state_->GetImageForPicture(id); |
| 269 if (!avda_image) | 260 if (!avda_image) |
| 270 continue; | 261 continue; |
| 271 | 262 |
| 272 // If the back buffer is unavailable, there's nothing left to do. | 263 // If we find a front buffer, stop and indicate that front buffer rendering |
| 273 if (avda_image->is_rendered_to_back_buffer()) | 264 // is not possible since another image is already in the front buffer. |
| 274 return; | 265 if (avda_image->was_rendered_to_front_buffer()) { |
| 266 first_renderable_image = nullptr; | |
| 267 break; | |
| 268 } | |
| 275 | 269 |
| 276 // If the image is rendered to the front buffer or has been dropped, it is | 270 // Update the front buffer index as we move along to shorten the number of |
| 277 // not valid for rendering. | 271 // candidate images we look at for back buffer rendering. |
| 278 if (avda_image->is_rendered()) | 272 front_index = i; |
| 279 continue; | 273 first_renderable_image = avda_image; |
| 280 | |
| 281 if (!first_renderable_image) | |
| 282 first_renderable_image = avda_image; | |
| 283 } | 274 } |
| 284 | 275 |
| 285 if (first_renderable_image) { | 276 if (first_renderable_image) { |
| 286 first_renderable_image->UpdateSurface( | 277 first_renderable_image->UpdateSurface( |
| 287 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); | 278 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); |
| 288 } | 279 } |
| 280 | |
| 281 // Back buffer rendering is only available for surface textures. We'll always | |
| 282 // have at least one front buffer, so the next buffer must be the backbuffer. | |
| 283 size_t backbuffer_index = front_index + 1; | |
| 284 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) | |
| 285 return; | |
| 286 | |
| 287 // See if the back buffer is free. If so, then render the frame adjacent to | |
| 288 // the front buffer. The listing is in render order, so we can just use the | |
| 289 // first unrendered frame if there is back buffer space. | |
| 290 first_renderable_image = shared_state_->GetImageForPicture( | |
| 291 pictures_out_for_display_[backbuffer_index]); | |
| 292 if (!first_renderable_image || | |
| 293 first_renderable_image->was_rendered_to_back_buffer()) { | |
| 294 return; | |
| 295 } | |
| 296 | |
| 297 // Due to the loop in the beginning this should never be true. | |
| 298 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); | |
| 299 first_renderable_image->UpdateSurface( | |
|
liberato (no reviews please)
2016/05/03 15:20:55
this will force a wait for frame available after y
DaleCurtis
2016/05/03 21:13:34
I don't follow. The render to front buffer above a
liberato (no reviews please)
2016/05/03 21:31:49
hrm, my comment was pretty jumbly. sorry about th
DaleCurtis
2016/05/04 00:01:33
So you're advocating that in the case where we hav
liberato (no reviews please)
2016/05/04 00:10:01
hrm, that's unexpected, since we're still releasin
| |
| 300 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); | |
| 289 } | 301 } |
| 290 | 302 |
| 291 void AndroidDeferredRenderingBackingStrategy::CodecChanged( | 303 void AndroidDeferredRenderingBackingStrategy::CodecChanged( |
| 292 media::VideoCodecBridge* codec) { | 304 media::VideoCodecBridge* codec) { |
| 293 media_codec_ = codec; | 305 media_codec_ = codec; |
| 294 shared_state_->CodecChanged(codec); | 306 shared_state_->CodecChanged(codec); |
| 295 } | 307 } |
| 296 | 308 |
| 297 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { | 309 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { |
| 298 shared_state_->SignalFrameAvailable(); | 310 shared_state_->SignalFrameAvailable(); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 return !feature_info->workarounds().avda_dont_copy_pictures; | 444 return !feature_info->workarounds().avda_dont_copy_pictures; |
| 433 } | 445 } |
| 434 } | 446 } |
| 435 } | 447 } |
| 436 | 448 |
| 437 // Assume so. | 449 // Assume so. |
| 438 return true; | 450 return true; |
| 439 } | 451 } |
| 440 | 452 |
| 441 } // namespace media | 453 } // namespace media |
| OLD | NEW |