Index: content/common/gpu/media/avda_codec_image.cc |
diff --git a/content/common/gpu/media/avda_codec_image.cc b/content/common/gpu/media/avda_codec_image.cc |
index 7efc0c690bb45c20784fe60ad559271c27a8b162..71bf4eba1771555c2704dd6d52b84a5c77ae00cd 100644 |
--- a/content/common/gpu/media/avda_codec_image.cc |
+++ b/content/common/gpu/media/avda_codec_image.cc |
@@ -84,7 +84,8 @@ bool AVDACodecImage::CopyTexImage(unsigned target) { |
// Make sure that we have the right image in the front buffer. Note that the |
// bound_service_id is guaranteed to be equal to the surface texture's client |
// texture id, so we can skip preserving it if the right context is current. |
- UpdateSurfaceTexture(kDontRestoreBindings); |
+ UpdateSurfaceInternal(UpdateMode::RENDER_TO_FRONT_BUFFER, |
+ kDontRestoreBindings); |
// By setting image state to UNBOUND instead of COPIED we ensure that |
// CopyTexImage() is called each time the surface texture is used for drawing. |
@@ -114,10 +115,7 @@ bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
return false; |
} |
- if (codec_buffer_index_ != kInvalidCodecBufferIndex) { |
- media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); |
- codec_buffer_index_ = kInvalidCodecBufferIndex; |
- } |
+ UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); |
return true; |
} |
@@ -127,20 +125,7 @@ void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { |
DCHECK(surface_texture_); |
- |
- // Render via the media codec if needed. |
- if (!IsCodecBufferOutstanding()) |
- return; |
- |
- // The decoder buffer is still pending. |
- // This must be synchronous, so wait for OnFrameAvailable. |
- media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); |
- { |
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame"); |
- shared_state_->WaitForFrameAvailable(); |
- } |
- |
- // Don't bother to check if we're rendered again. |
+ DCHECK_EQ(codec_buffer_index_, kUpdateOnly); |
codec_buffer_index_ = kInvalidCodecBufferIndex; |
// Swap the rendered image to the front. |
@@ -169,14 +154,14 @@ void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) { |
codec_buffer_index_ = buffer_index; |
} |
-int AVDACodecImage::GetMediaCodecBufferIndex() const { |
- return codec_buffer_index_; |
-} |
- |
void AVDACodecImage::SetSize(const gfx::Size& size) { |
size_ = size; |
} |
+void AVDACodecImage::UpdateSurface(UpdateMode update_mode) { |
+ UpdateSurfaceInternal(update_mode, kDoRestoreBindings); |
+} |
+ |
void AVDACodecImage::CodecChanged(media::MediaCodecBridge* codec) { |
media_codec_ = codec; |
codec_buffer_index_ = kInvalidCodecBufferIndex; |
@@ -186,6 +171,76 @@ void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) { |
texture_ = texture; |
} |
+void AVDACodecImage::UpdateSurfaceInternal( |
+ UpdateMode update_mode, |
+ RestoreBindingsMode attached_bindings_mode) { |
+ if (!IsCodecBufferOutstanding()) |
+ return; |
+ |
+ ReleaseOutputBuffer(update_mode); |
+ |
+ // SurfaceViews are updated implicitly, so no further steps are necessary. |
+ if (!surface_texture_) { |
liberato (no reviews please)
2016/04/22 20:25:08
DCHECK_NE(...BACK_BUFFER)?
DaleCurtis
2016/04/22 20:58:02
Done, though can't use DCHECK_NE with enum class f
|
+ codec_buffer_index_ = kInvalidCodecBufferIndex; |
liberato (no reviews please)
2016/04/22 20:25:08
this might be better in ReleaseOutputBuffer.
DaleCurtis
2016/04/22 20:58:02
Good point, done.
|
+ return; |
+ } |
+ |
+ // If front buffer rendering hasn't been requested, exit early. |
+ if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER) |
+ return; |
+ |
+ // Surface texture is already attached, so just update it. |
+ if (shared_state_->surface_texture_is_attached()) { |
+ UpdateSurfaceTexture(attached_bindings_mode); |
+ return; |
+ } |
+ |
+ // Don't attach the surface texture permanently. Perhaps we should just |
+ // attach the surface texture in avda and be done with it. |
+ GLuint service_id = 0; |
+ glGenTextures(1, &service_id); |
+ GLint bound_service_id = 0; |
+ glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); |
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); |
+ AttachSurfaceTextureToContext(); |
+ UpdateSurfaceTexture(kDontRestoreBindings); |
+ |
+ // Detach the surface texture, which deletes the generated texture. |
+ surface_texture_->DetachFromGLContext(); |
+ shared_state_->DidDetachSurfaceTexture(); |
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); |
+} |
+ |
+void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) { |
+ DCHECK(IsCodecBufferOutstanding()); |
+ |
+ // In case of discard, simply discard and clear our codec buffer index. |
+ if (update_mode == UpdateMode::DISCARD_CODEC_BUFFER) { |
+ if (codec_buffer_index_ != kUpdateOnly) |
+ media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false); |
+ codec_buffer_index_ = kInvalidCodecBufferIndex; |
+ return; |
+ } |
+ |
+ DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER || |
+ update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); |
+ |
+ // If we've already released to the back buffer, there's nothing left to do. |
+ if (codec_buffer_index_ == kUpdateOnly) |
+ return; |
+ |
+ media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); |
+ codec_buffer_index_ = kUpdateOnly; |
+ |
+ // If we're using a SurfaceView we're done! |
+ if (!surface_texture_) |
+ return; |
+ |
+ // This must be synchronous, so wait for OnFrameAvailable. |
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame"); |
+ shared_state_->WaitForFrameAvailable(); |
+} |
+ |
void AVDACodecImage::AttachSurfaceTextureToContext() { |
DCHECK(surface_texture_); |
@@ -217,28 +272,9 @@ std::unique_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() { |
} |
void AVDACodecImage::GetTextureMatrix(float matrix[16]) { |
- if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) { |
- // Our current matrix may be stale. Update it if possible. |
- if (!shared_state_->surface_texture_is_attached()) { |
- // Don't attach the surface texture permanently. Perhaps we should |
- // just attach the surface texture in avda and be done with it. |
- GLuint service_id = 0; |
- glGenTextures(1, &service_id); |
- GLint bound_service_id = 0; |
- glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); |
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); |
- AttachSurfaceTextureToContext(); |
- UpdateSurfaceTexture(kDontRestoreBindings); |
- // Detach the surface texture, which deletes the generated texture. |
- surface_texture_->DetachFromGLContext(); |
- shared_state_->DidDetachSurfaceTexture(); |
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); |
- } else { |
- // Surface texture is already attached, so just update it. |
- UpdateSurfaceTexture(kDoRestoreBindings); |
- } |
- } |
- |
+ // Our current matrix may be stale. Update it if possible. |
+ if (surface_texture_) |
+ UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); |
memcpy(matrix, gl_matrix_, sizeof(gl_matrix_)); |
} |