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 |