Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1047)

Side by Side Diff: content/common/gpu/media/avda_codec_image.cc

Issue 1892013002: ReleaseOutputBuffer to surface back and front buffers where possible. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/avda_codec_image.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 return false; 77 return false;
78 78
79 // If the surface texture isn't attached yet, then attach it. Note that this 79 // If the surface texture isn't attached yet, then attach it. Note that this
80 // will be to the texture in |shared_state_|, because of the checks above. 80 // will be to the texture in |shared_state_|, because of the checks above.
81 if (!shared_state_->surface_texture_is_attached()) 81 if (!shared_state_->surface_texture_is_attached())
82 AttachSurfaceTextureToContext(); 82 AttachSurfaceTextureToContext();
83 83
84 // Make sure that we have the right image in the front buffer. Note that the 84 // Make sure that we have the right image in the front buffer. Note that the
85 // bound_service_id is guaranteed to be equal to the surface texture's client 85 // bound_service_id is guaranteed to be equal to the surface texture's client
86 // texture id, so we can skip preserving it if the right context is current. 86 // texture id, so we can skip preserving it if the right context is current.
87 UpdateSurfaceTexture(kDontRestoreBindings); 87 UpdateSurfaceInternal(UpdateMode::RENDER_TO_FRONT_BUFFER,
88 kDontRestoreBindings);
88 89
89 // By setting image state to UNBOUND instead of COPIED we ensure that 90 // By setting image state to UNBOUND instead of COPIED we ensure that
90 // CopyTexImage() is called each time the surface texture is used for drawing. 91 // CopyTexImage() is called each time the surface texture is used for drawing.
91 // It would be nice if we could do this via asking for the currently bound 92 // It would be nice if we could do this via asking for the currently bound
92 // Texture, but the active unit never seems to change. 93 // Texture, but the active unit never seems to change.
93 texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this, 94 texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
94 gpu::gles2::Texture::UNBOUND); 95 gpu::gles2::Texture::UNBOUND);
95 96
96 return true; 97 return true;
97 } 98 }
98 99
99 bool AVDACodecImage::CopyTexSubImage(unsigned target, 100 bool AVDACodecImage::CopyTexSubImage(unsigned target,
100 const gfx::Point& offset, 101 const gfx::Point& offset,
101 const gfx::Rect& rect) { 102 const gfx::Rect& rect) {
102 return false; 103 return false;
103 } 104 }
104 105
105 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, 106 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
106 int z_order, 107 int z_order,
107 gfx::OverlayTransform transform, 108 gfx::OverlayTransform transform,
108 const gfx::Rect& bounds_rect, 109 const gfx::Rect& bounds_rect,
109 const gfx::RectF& crop_rect) { 110 const gfx::RectF& crop_rect) {
110 // This should only be called when we're rendering to a SurfaceView. 111 // This should only be called when we're rendering to a SurfaceView.
111 if (surface_texture_) { 112 if (surface_texture_) {
112 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " 113 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is "
113 "SurfaceTexture backed."; 114 "SurfaceTexture backed.";
114 return false; 115 return false;
115 } 116 }
116 117
117 if (codec_buffer_index_ != kInvalidCodecBufferIndex) { 118 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER);
118 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
119 codec_buffer_index_ = kInvalidCodecBufferIndex;
120 }
121 return true; 119 return true;
122 } 120 }
123 121
124 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, 122 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
125 uint64_t process_tracing_id, 123 uint64_t process_tracing_id,
126 const std::string& dump_name) {} 124 const std::string& dump_name) {}
127 125
128 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { 126 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) {
129 DCHECK(surface_texture_); 127 DCHECK(surface_texture_);
130 128 DCHECK_EQ(codec_buffer_index_, kUpdateOnly);
131 // Render via the media codec if needed.
132 if (!IsCodecBufferOutstanding())
133 return;
134
135 // The decoder buffer is still pending.
136 // This must be synchronous, so wait for OnFrameAvailable.
137 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
138 {
139 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame");
140 shared_state_->WaitForFrameAvailable();
141 }
142
143 // Don't bother to check if we're rendered again.
144 codec_buffer_index_ = kInvalidCodecBufferIndex; 129 codec_buffer_index_ = kInvalidCodecBufferIndex;
145 130
146 // Swap the rendered image to the front. 131 // Swap the rendered image to the front.
147 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = 132 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current =
148 MakeCurrentIfNeeded(); 133 MakeCurrentIfNeeded();
149 134
150 // If we changed contexts, then we always want to restore it, since the caller 135 // If we changed contexts, then we always want to restore it, since the caller
151 // doesn't know that we're switching contexts. 136 // doesn't know that we're switching contexts.
152 if (scoped_make_current) 137 if (scoped_make_current)
153 mode = kDoRestoreBindings; 138 mode = kDoRestoreBindings;
154 139
155 // Save the current binding if requested. 140 // Save the current binding if requested.
156 GLint bound_service_id = 0; 141 GLint bound_service_id = 0;
157 if (mode == kDoRestoreBindings) 142 if (mode == kDoRestoreBindings)
158 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); 143 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
159 144
160 surface_texture_->UpdateTexImage(); 145 surface_texture_->UpdateTexImage();
161 if (mode == kDoRestoreBindings) 146 if (mode == kDoRestoreBindings)
162 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); 147 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
163 148
164 // Helpfully, this is already column major. 149 // Helpfully, this is already column major.
165 surface_texture_->GetTransformMatrix(gl_matrix_); 150 surface_texture_->GetTransformMatrix(gl_matrix_);
166 } 151 }
167 152
168 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) { 153 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) {
169 codec_buffer_index_ = buffer_index; 154 codec_buffer_index_ = buffer_index;
170 } 155 }
171 156
172 int AVDACodecImage::GetMediaCodecBufferIndex() const {
173 return codec_buffer_index_;
174 }
175
176 void AVDACodecImage::SetSize(const gfx::Size& size) { 157 void AVDACodecImage::SetSize(const gfx::Size& size) {
177 size_ = size; 158 size_ = size;
178 } 159 }
179 160
161 void AVDACodecImage::UpdateSurface(UpdateMode update_mode) {
162 UpdateSurfaceInternal(update_mode, kDoRestoreBindings);
163 }
164
180 void AVDACodecImage::CodecChanged(media::MediaCodecBridge* codec) { 165 void AVDACodecImage::CodecChanged(media::MediaCodecBridge* codec) {
181 media_codec_ = codec; 166 media_codec_ = codec;
182 codec_buffer_index_ = kInvalidCodecBufferIndex; 167 codec_buffer_index_ = kInvalidCodecBufferIndex;
183 } 168 }
184 169
185 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) { 170 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) {
186 texture_ = texture; 171 texture_ = texture;
187 } 172 }
188 173
174 void AVDACodecImage::UpdateSurfaceInternal(
175 UpdateMode update_mode,
176 RestoreBindingsMode attached_bindings_mode) {
177 if (!IsCodecBufferOutstanding())
178 return;
179
180 ReleaseOutputBuffer(update_mode);
181
182 // SurfaceViews are updated implicitly, so no further steps are necessary.
183 if (!surface_texture_) {
184 DCHECK(update_mode != UpdateMode::RENDER_TO_BACK_BUFFER);
185 return;
186 }
187
188 // If front buffer rendering hasn't been requested, exit early.
189 if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER)
190 return;
191
192 // Surface texture is already attached, so just update it.
193 if (shared_state_->surface_texture_is_attached()) {
194 UpdateSurfaceTexture(attached_bindings_mode);
195 return;
196 }
197
198 // Don't attach the surface texture permanently. Perhaps we should just
199 // attach the surface texture in avda and be done with it.
200 GLuint service_id = 0;
201 glGenTextures(1, &service_id);
202 GLint bound_service_id = 0;
203 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
204 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
205 AttachSurfaceTextureToContext();
206 UpdateSurfaceTexture(kDontRestoreBindings);
207
208 // Detach the surface texture, which deletes the generated texture.
209 surface_texture_->DetachFromGLContext();
210 shared_state_->DidDetachSurfaceTexture();
211 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
212 }
213
214 void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) {
215 DCHECK(IsCodecBufferOutstanding());
216
217 // In case of discard, simply discard and clear our codec buffer index.
218 if (update_mode == UpdateMode::DISCARD_CODEC_BUFFER) {
219 if (codec_buffer_index_ != kUpdateOnly)
220 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false);
221 codec_buffer_index_ = kInvalidCodecBufferIndex;
222 return;
223 }
224
225 DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER ||
226 update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER);
227
228 // If we've already released to the back buffer, there's nothing left to do.
229 if (codec_buffer_index_ == kUpdateOnly)
230 return;
231
232 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
233 codec_buffer_index_ = kUpdateOnly;
234
235 // If we're using a SurfaceView we're done!
236 if (!surface_texture_) {
237 codec_buffer_index_ = kInvalidCodecBufferIndex;
238 return;
239 }
240
241 // This must be synchronous, so wait for OnFrameAvailable.
242 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame");
243 shared_state_->WaitForFrameAvailable();
244 }
245
189 void AVDACodecImage::AttachSurfaceTextureToContext() { 246 void AVDACodecImage::AttachSurfaceTextureToContext() {
190 DCHECK(surface_texture_); 247 DCHECK(surface_texture_);
191 248
192 // We assume that the currently bound texture is the intended one. 249 // We assume that the currently bound texture is the intended one.
193 250
194 // Attach the surface texture to the first context we're bound on, so that 251 // Attach the surface texture to the first context we're bound on, so that
195 // no context switch is needed later. 252 // no context switch is needed later.
196 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 253 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
197 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 254 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
198 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 255 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
(...skipping 11 matching lines...) Expand all
210 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; 267 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current;
211 if (!shared_state_->context()->IsCurrent(NULL)) { 268 if (!shared_state_->context()->IsCurrent(NULL)) {
212 scoped_make_current.reset(new ui::ScopedMakeCurrent( 269 scoped_make_current.reset(new ui::ScopedMakeCurrent(
213 shared_state_->context(), shared_state_->surface())); 270 shared_state_->context(), shared_state_->surface()));
214 } 271 }
215 272
216 return scoped_make_current; 273 return scoped_make_current;
217 } 274 }
218 275
219 void AVDACodecImage::GetTextureMatrix(float matrix[16]) { 276 void AVDACodecImage::GetTextureMatrix(float matrix[16]) {
220 if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) { 277 // Our current matrix may be stale. Update it if possible.
221 // Our current matrix may be stale. Update it if possible. 278 if (surface_texture_)
222 if (!shared_state_->surface_texture_is_attached()) { 279 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER);
223 // Don't attach the surface texture permanently. Perhaps we should
224 // just attach the surface texture in avda and be done with it.
225 GLuint service_id = 0;
226 glGenTextures(1, &service_id);
227 GLint bound_service_id = 0;
228 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
229 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
230 AttachSurfaceTextureToContext();
231 UpdateSurfaceTexture(kDontRestoreBindings);
232 // Detach the surface texture, which deletes the generated texture.
233 surface_texture_->DetachFromGLContext();
234 shared_state_->DidDetachSurfaceTexture();
235 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
236 } else {
237 // Surface texture is already attached, so just update it.
238 UpdateSurfaceTexture(kDoRestoreBindings);
239 }
240 }
241
242 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_)); 280 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_));
243 } 281 }
244 282
245 bool AVDACodecImage::IsCodecBufferOutstanding() const { 283 bool AVDACodecImage::IsCodecBufferOutstanding() const {
246 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_; 284 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_;
247 } 285 }
248 286
249 } // namespace content 287 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/avda_codec_image.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698