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/avda_codec_image.h" | 5 #include "content/common/gpu/media/avda_codec_image.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 gfx::OverlayTransform transform, | 104 gfx::OverlayTransform transform, |
| 105 const gfx::Rect& bounds_rect, | 105 const gfx::Rect& bounds_rect, |
| 106 const gfx::RectF& crop_rect) { | 106 const gfx::RectF& crop_rect) { |
| 107 // This should only be called when we're rendering to a SurfaceView. | 107 // This should only be called when we're rendering to a SurfaceView. |
| 108 if (surface_texture_) { | 108 if (surface_texture_) { |
| 109 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " | 109 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " |
| 110 "SurfaceTexture backed."; | 110 "SurfaceTexture backed."; |
| 111 return false; | 111 return false; |
| 112 } | 112 } |
| 113 | 113 |
| 114 if (codec_buffer_index_ != kInvalidCodecBufferIndex) { | 114 ReleaseOutputBuffer(ReleaseMode::RENDER_ONLY); |
|
liberato (no reviews please)
2016/04/22 00:51:06
RENDER_AND_UPDATE, else it will try to wait for fr
DaleCurtis
2016/04/22 01:33:58
Done.
| |
| 115 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); | 115 codec_buffer_index_ = kInvalidCodecBufferIndex; |
| 116 codec_buffer_index_ = kInvalidCodecBufferIndex; | |
| 117 } | |
| 118 return true; | 116 return true; |
| 119 } | 117 } |
| 120 | 118 |
| 121 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, | 119 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
| 122 uint64_t process_tracing_id, | 120 uint64_t process_tracing_id, |
| 123 const std::string& dump_name) {} | 121 const std::string& dump_name) {} |
| 124 | 122 |
| 125 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { | 123 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { |
| 126 DCHECK(surface_texture_); | 124 DCHECK(surface_texture_); |
| 127 | 125 |
| 128 // Render via the media codec if needed. | |
| 129 if (!IsCodecBufferOutstanding()) | 126 if (!IsCodecBufferOutstanding()) |
| 130 return; | 127 return; |
| 131 | 128 |
| 132 // The decoder buffer is still pending. | 129 ReleaseOutputBuffer(ReleaseMode::RENDER_ONLY); |
| 133 // This must be synchronous, so wait for OnFrameAvailable. | 130 DCHECK_EQ(codec_buffer_index_, kUpdateOnly); |
| 134 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); | |
| 135 { | |
| 136 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame"); | |
| 137 shared_state_->WaitForFrameAvailable(); | |
| 138 } | |
| 139 | |
| 140 // Don't bother to check if we're rendered again. | |
| 141 codec_buffer_index_ = kInvalidCodecBufferIndex; | 131 codec_buffer_index_ = kInvalidCodecBufferIndex; |
| 142 | 132 |
| 143 // Swap the rendered image to the front. | 133 // Swap the rendered image to the front. |
| 144 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = | 134 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = |
| 145 MakeCurrentIfNeeded(); | 135 MakeCurrentIfNeeded(); |
| 146 | 136 |
| 147 // If we changed contexts, then we always want to restore it, since the caller | 137 // If we changed contexts, then we always want to restore it, since the caller |
| 148 // doesn't know that we're switching contexts. | 138 // doesn't know that we're switching contexts. |
| 149 if (scoped_make_current) | 139 if (scoped_make_current) |
| 150 mode = kDoRestoreBindings; | 140 mode = kDoRestoreBindings; |
| 151 | 141 |
| 152 // Save the current binding if requested. | 142 // Save the current binding if requested. |
| 153 GLint bound_service_id = 0; | 143 GLint bound_service_id = 0; |
| 154 if (mode == kDoRestoreBindings) | 144 if (mode == kDoRestoreBindings) |
| 155 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); | 145 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); |
| 156 | 146 |
| 157 surface_texture_->UpdateTexImage(); | 147 surface_texture_->UpdateTexImage(); |
| 158 if (mode == kDoRestoreBindings) | 148 if (mode == kDoRestoreBindings) |
| 159 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); | 149 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); |
| 160 | 150 |
| 161 // Helpfully, this is already column major. | 151 // Helpfully, this is already column major. |
| 162 surface_texture_->GetTransformMatrix(gl_matrix_); | 152 surface_texture_->GetTransformMatrix(gl_matrix_); |
| 163 } | 153 } |
| 164 | 154 |
| 165 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) { | 155 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) { |
| 166 codec_buffer_index_ = buffer_index; | 156 codec_buffer_index_ = buffer_index; |
| 167 } | 157 } |
| 168 | 158 |
| 169 int AVDACodecImage::GetMediaCodecBufferIndex() const { | |
| 170 return codec_buffer_index_; | |
| 171 } | |
| 172 | |
| 173 void AVDACodecImage::SetSize(const gfx::Size& size) { | 159 void AVDACodecImage::SetSize(const gfx::Size& size) { |
| 174 size_ = size; | 160 size_ = size; |
| 175 } | 161 } |
| 176 | 162 |
| 163 void AVDACodecImage::ReleaseOutputBuffer(ReleaseMode release_mode) { | |
| 164 if (!IsCodecBufferOutstanding()) | |
| 165 return; | |
| 166 | |
| 167 DCHECK_NE(codec_buffer_index_, kInvalidCodecBufferIndex); | |
| 168 | |
| 169 if (release_mode == ReleaseMode::SKIP_RENDER) { | |
| 170 if (codec_buffer_index_ != kUpdateOnly) | |
| 171 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false); | |
| 172 codec_buffer_index_ = kInvalidCodecBufferIndex; | |
| 173 return; | |
| 174 } | |
| 175 | |
| 176 if (release_mode == ReleaseMode::RENDER_ONLY) { | |
|
liberato (no reviews please)
2016/04/22 00:51:06
DCHECK(surface_texture_)
DaleCurtis
2016/04/22 01:33:58
Done.
| |
| 177 if (codec_buffer_index_ == kUpdateOnly) | |
| 178 return; | |
| 179 | |
| 180 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); | |
| 181 codec_buffer_index_ = kUpdateOnly; | |
| 182 | |
| 183 // This must be synchronous, so wait for OnFrameAvailable. | |
| 184 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame"); | |
| 185 shared_state_->WaitForFrameAvailable(); | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 DCHECK(release_mode == ReleaseMode::RENDER_AND_UPDATE); | |
| 190 | |
| 191 if (!surface_texture_) { | |
| 192 DCHECK_NE(codec_buffer_index_, kUpdateOnly); | |
| 193 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); | |
| 194 codec_buffer_index_ = kInvalidCodecBufferIndex; | |
| 195 return; | |
| 196 } | |
| 197 | |
| 198 // Surface texture is already attached, so just update it. | |
| 199 if (shared_state_->surface_texture_is_attached()) { | |
| 200 // Warning: This will cause reentrancy to this function. | |
| 201 UpdateSurfaceTexture(kDoRestoreBindings); | |
|
liberato (no reviews please)
2016/04/22 00:51:06
i think that this can be simplified to avoid the m
DaleCurtis
2016/04/22 01:33:58
I agree the recursion is nasty, will think on it s
liberato (no reviews please)
2016/04/22 02:16:43
the public api would be UpdateSurface(). i agree
| |
| 202 return; | |
| 203 } | |
| 204 | |
| 205 // Don't attach the surface texture permanently. Perhaps we should just | |
| 206 // attach the surface texture in avda and be done with it. | |
| 207 GLuint service_id = 0; | |
| 208 glGenTextures(1, &service_id); | |
| 209 GLint bound_service_id = 0; | |
| 210 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); | |
| 211 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); | |
| 212 AttachSurfaceTextureToContext(); | |
| 213 | |
| 214 // Warning: This will cause reentrancy to this function. | |
| 215 UpdateSurfaceTexture(kDontRestoreBindings); | |
| 216 | |
| 217 // Detach the surface texture, which deletes the generated texture. | |
| 218 surface_texture_->DetachFromGLContext(); | |
| 219 shared_state_->DidDetachSurfaceTexture(); | |
| 220 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); | |
| 221 } | |
| 222 | |
| 177 void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) { | 223 void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) { |
| 178 media_codec_ = codec; | 224 media_codec_ = codec; |
| 179 codec_buffer_index_ = -1; | 225 codec_buffer_index_ = kInvalidCodecBufferIndex; |
| 180 } | 226 } |
| 181 | 227 |
| 182 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) { | 228 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) { |
| 183 texture_ = texture; | 229 texture_ = texture; |
| 184 } | 230 } |
| 185 | 231 |
| 186 void AVDACodecImage::AttachSurfaceTextureToContext() { | 232 void AVDACodecImage::AttachSurfaceTextureToContext() { |
| 187 DCHECK(surface_texture_); | 233 DCHECK(surface_texture_); |
| 188 | 234 |
| 189 // We assume that the currently bound texture is the intended one. | 235 // We assume that the currently bound texture is the intended one. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 207 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; | 253 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; |
| 208 if (!shared_state_->context()->IsCurrent(NULL)) { | 254 if (!shared_state_->context()->IsCurrent(NULL)) { |
| 209 scoped_make_current.reset(new ui::ScopedMakeCurrent( | 255 scoped_make_current.reset(new ui::ScopedMakeCurrent( |
| 210 shared_state_->context(), shared_state_->surface())); | 256 shared_state_->context(), shared_state_->surface())); |
| 211 } | 257 } |
| 212 | 258 |
| 213 return scoped_make_current; | 259 return scoped_make_current; |
| 214 } | 260 } |
| 215 | 261 |
| 216 void AVDACodecImage::GetTextureMatrix(float matrix[16]) { | 262 void AVDACodecImage::GetTextureMatrix(float matrix[16]) { |
| 217 if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) { | 263 // Our current matrix may be stale. Update it if possible. |
| 218 // Our current matrix may be stale. Update it if possible. | 264 ReleaseOutputBuffer(ReleaseMode::RENDER_AND_UPDATE); |
|
liberato (no reviews please)
2016/04/22 00:51:06
this eats the check for |surface_texture_|. shoul
DaleCurtis
2016/04/22 01:33:58
Done.
| |
| 219 if (!shared_state_->surface_texture_is_attached()) { | |
| 220 // Don't attach the surface texture permanently. Perhaps we should | |
| 221 // just attach the surface texture in avda and be done with it. | |
| 222 GLuint service_id = 0; | |
| 223 glGenTextures(1, &service_id); | |
| 224 GLint bound_service_id = 0; | |
| 225 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); | |
| 226 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); | |
| 227 AttachSurfaceTextureToContext(); | |
| 228 UpdateSurfaceTexture(kDontRestoreBindings); | |
| 229 // Detach the surface texture, which deletes the generated texture. | |
| 230 surface_texture_->DetachFromGLContext(); | |
| 231 shared_state_->DidDetachSurfaceTexture(); | |
| 232 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); | |
| 233 } else { | |
| 234 // Surface texture is already attached, so just update it. | |
| 235 UpdateSurfaceTexture(kDoRestoreBindings); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_)); | 265 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_)); |
| 240 } | 266 } |
| 241 | 267 |
| 242 bool AVDACodecImage::IsCodecBufferOutstanding() const { | 268 bool AVDACodecImage::IsCodecBufferOutstanding() const { |
| 243 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_; | 269 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_; |
| 244 } | 270 } |
| 245 | 271 |
| 246 } // namespace content | 272 } // namespace content |
| OLD | NEW |