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

Side by Side Diff: media/gpu/avda_picture_buffer_manager.cc

Issue 2461073002: Use MediaCodec.setOutputSurface() for fullscreen transitions on M. (Closed)
Patch Set: Simplify APIs. Created 4 years, 1 month 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
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 "media/gpu/avda_picture_buffer_manager.h" 5 #include "media/gpu/avda_picture_buffer_manager.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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 // SurfaceTexture and attach it lazily in the compositor's context. But that 70 // SurfaceTexture and attach it lazily in the compositor's context. But that
71 // was flaky because SurfaceTexture#detachFromGLContext() is buggy on a lot of 71 // was flaky because SurfaceTexture#detachFromGLContext() is buggy on a lot of
72 // devices. Now we attach it to the current context, which means we might have 72 // devices. Now we attach it to the current context, which means we might have
73 // to context switch later to call updateTexImage(). Fortunately, if virtual 73 // to context switch later to call updateTexImage(). Fortunately, if virtual
74 // contexts are in use, we won't have to context switch. 74 // contexts are in use, we won't have to context switch.
75 return gl::SurfaceTexture::Create(texture_id); 75 return gl::SurfaceTexture::Create(texture_id);
76 } 76 }
77 77
78 } // namespace 78 } // namespace
79 79
80 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, 80 AVDAPictureBufferManager::AVDAPictureBufferManager(
81 // we take care that the object that wants them still exists. WeakPtrs cannot 81 AVDAStateProvider* state_provider)
82 // be used because OnFrameAvailable callbacks can occur on any thread. We also 82 : state_provider_(state_provider), media_codec_(nullptr) {}
83 // can't guarantee when the SurfaceTexture will quit sending callbacks to
84 // coordinate with the destruction of the AVDA and PictureBufferManager, so we
85 // have a separate object that the callback can own.
86 class AVDAPictureBufferManager::OnFrameAvailableHandler
87 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> {
88 public:
89 // We do not retain ownership of |listener|. It must remain valid until after
90 // ClearListener() is called. This will register with |surface_texture| to
91 // receive OnFrameAvailable callbacks.
92 OnFrameAvailableHandler(AVDASharedState* listener,
93 gl::SurfaceTexture* surface_texture)
94 : listener_(listener) {
95 surface_texture->SetFrameAvailableCallbackOnAnyThread(
96 base::Bind(&OnFrameAvailableHandler::OnFrameAvailable,
97 scoped_refptr<OnFrameAvailableHandler>(this)));
98 }
99
100 // Forget about |listener_|, which is required before one deletes it.
101 // No further callbacks will happen once this completes.
102 void ClearListener() {
103 base::AutoLock lock(lock_);
104 listener_ = nullptr;
105 }
106
107 // Notify the listener if there is one.
108 void OnFrameAvailable() {
109 base::AutoLock auto_lock(lock_);
110 if (listener_)
111 listener_->SignalFrameAvailable();
112 }
113
114 private:
115 friend class base::RefCountedThreadSafe<OnFrameAvailableHandler>;
116
117 ~OnFrameAvailableHandler() { DCHECK(!listener_); }
118
119 // Protects changes to listener_.
120 base::Lock lock_;
121
122 // The AVDASharedState that wants the OnFrameAvailable callback.
123 AVDASharedState* listener_;
124
125 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler);
126 };
127
128 AVDAPictureBufferManager::AVDAPictureBufferManager()
129 : state_provider_(nullptr), media_codec_(nullptr) {}
130 83
131 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} 84 AVDAPictureBufferManager::~AVDAPictureBufferManager() {}
132 85
133 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize( 86 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize(int surface_id) {
134 AVDAStateProvider* state_provider,
135 int surface_view_id) {
136 state_provider_ = state_provider;
137 shared_state_ = new AVDASharedState(); 87 shared_state_ = new AVDASharedState();
138 88
139 // Acquire the SurfaceView surface if given a valid id. 89 // Acquire the SurfaceView surface if given a valid id.
140 if (surface_view_id != VideoDecodeAccelerator::Config::kNoSurfaceID) { 90 if (surface_id != SurfaceManager::kNoSurfaceID) {
141 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( 91 if (surface_texture_) {
142 surface_view_id); 92 surface_texture_->ReleaseSurfaceTexture();
93 surface_texture_ = nullptr;
94 }
95 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_id);
143 } 96 }
144 97
145 // Otherwise create a SurfaceTexture. 98 // Always create a SurfaceTexture, we'll use it for entering and exiting from
146 GLuint service_id = 0; 99 // fullscreen mode.
100 GLuint service_id;
147 surface_texture_ = CreateAttachedSurfaceTexture( 101 surface_texture_ = CreateAttachedSurfaceTexture(
148 state_provider_->GetGlDecoder(), &service_id); 102 state_provider_->GetGlDecoder(), &service_id);
149 if (surface_texture_) {
150 on_frame_available_handler_ = new OnFrameAvailableHandler(
151 shared_state_.get(), surface_texture_.get());
152 }
153 shared_state_->SetSurfaceTexture(surface_texture_, service_id); 103 shared_state_->SetSurfaceTexture(surface_texture_, service_id);
154 return gl::ScopedJavaSurface(surface_texture_.get()); 104 return gl::ScopedJavaSurface(surface_texture_.get());
155 } 105 }
156 106
157 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { 107 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) {
158 // Do nothing if Initialize() has not been called. 108 // Do nothing if Initialize() has not been called.
159 if (!shared_state_) 109 if (!shared_state_)
160 return; 110 return;
161 111
162 // If we have an OnFrameAvailable handler, tell it that we no longer want
163 // callbacks.
164 if (on_frame_available_handler_)
165 on_frame_available_handler_->ClearListener();
166
167 ReleaseCodecBuffers(buffers); 112 ReleaseCodecBuffers(buffers);
168 CodecChanged(nullptr); 113 CodecChanged(nullptr);
169 114
170 // Release the surface texture and any back buffers. This will preserve the 115 // Release the surface texture and any back buffers. This will preserve the
171 // front buffer, if any. 116 // front buffer, if any.
172 if (surface_texture_) 117 if (surface_texture_)
173 surface_texture_->ReleaseSurfaceTexture(); 118 surface_texture_->ReleaseSurfaceTexture();
174 } 119 }
175 120
176 uint32_t AVDAPictureBufferManager::GetTextureTarget() const { 121 uint32_t AVDAPictureBufferManager::GetTextureTarget() const {
177 // If we're using a surface texture, then we need an external texture target 122 // Always use OES textures even though this will cause flickering in dev tools
178 // to sample from it. If not, then we'll use 2D transparent textures to draw 123 // when inspecting a fullscreen video. See http://crbug.com/592798
179 // a transparent hole through which to see the SurfaceView. This is normally 124 return GL_TEXTURE_EXTERNAL_OES;
180 // needed only for the devtools inspector, since the overlay mechanism handles
181 // it otherwise.
182 return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
183 } 125 }
184 126
185 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { 127 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const {
186 // For SurfaceView, request a 1x1 2D texture to reduce memory during 128 // Allocate a picture buffer that is the actual frame size. Note that it will
187 // initialization. For SurfaceTexture, allocate a picture buffer that is the 129 // be an external texture anyway, so it doesn't allocate an image of that
188 // actual frame size. Note that it will be an external texture anyway, so it 130 // size. It's important to get the coded size right, so that VideoLayerImpl
189 // doesn't allocate an image of that size. However, it's still important to 131 // doesn't try to scale the texture when building the quad for it.
190 // get the coded size right, so that VideoLayerImpl doesn't try to scale the 132 return state_provider_->GetSize();
191 // texture when building the quad for it.
192 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1);
193 } 133 }
194 134
195 gpu::gles2::TextureRef* AVDAPictureBufferManager::GetTextureForPicture( 135 gpu::gles2::TextureRef* AVDAPictureBufferManager::GetTextureForPicture(
196 const PictureBuffer& picture_buffer) { 136 const PictureBuffer& picture_buffer) {
197 auto gles_decoder = state_provider_->GetGlDecoder(); 137 auto gles_decoder = state_provider_->GetGlDecoder();
198 RETURN_NULL_IF_NULL(gles_decoder); 138 RETURN_NULL_IF_NULL(gles_decoder);
199 RETURN_NULL_IF_NULL(gles_decoder->GetContextGroup()); 139 RETURN_NULL_IF_NULL(gles_decoder->GetContextGroup());
200 140
201 gpu::gles2::TextureManager* texture_manager = 141 gpu::gles2::TextureManager* texture_manager =
202 gles_decoder->GetContextGroup()->texture_manager(); 142 gles_decoder->GetContextGroup()->texture_manager();
203 RETURN_NULL_IF_NULL(texture_manager); 143 RETURN_NULL_IF_NULL(texture_manager);
204 144
205 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); 145 DCHECK_LE(1u, picture_buffer.client_texture_ids().size());
206 gpu::gles2::TextureRef* texture_ref = 146 gpu::gles2::TextureRef* texture_ref =
207 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); 147 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]);
208 RETURN_NULL_IF_NULL(texture_ref); 148 RETURN_NULL_IF_NULL(texture_ref);
209 149
210 return texture_ref; 150 return texture_ref;
211 } 151 }
212 152
213 void AVDAPictureBufferManager::SetImageForPicture( 153 void AVDAPictureBufferManager::SetImageForPicture(
214 const PictureBuffer& picture_buffer, 154 const PictureBuffer& picture_buffer,
215 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { 155 gpu::gles2::GLStreamTextureImage* image) {
216 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer); 156 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer);
217 RETURN_IF_NULL(texture_ref); 157 RETURN_IF_NULL(texture_ref);
218 158
219 gpu::gles2::TextureManager* texture_manager = 159 gpu::gles2::TextureManager* texture_manager =
220 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); 160 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager();
221 RETURN_IF_NULL(texture_manager); 161 RETURN_IF_NULL(texture_manager);
222 162
223 // Default to zero which will clear the stream texture service id if one was 163 // Default to zero which will clear the stream texture service id if one was
224 // previously set. 164 // previously set.
225 GLuint stream_texture_service_id = 0; 165 GLuint stream_texture_service_id = 0;
226 if (image) { 166 if (image) {
227 if (shared_state_->surface_texture_service_id() != 0) { 167 if (shared_state_->surface_texture_service_id() != 0) {
228 // Override the Texture's service id, so that it will use the one that is 168 // Override the Texture's service id, so that it will use the one that is
229 // attached to the SurfaceTexture. 169 // attached to the SurfaceTexture.
230 stream_texture_service_id = shared_state_->surface_texture_service_id(); 170 stream_texture_service_id = shared_state_->surface_texture_service_id();
231 } 171 }
232 172
233 // Also set the parameters for the level if we're not clearing the image. 173 // Also set the parameters for the level if we're not clearing the image.
234 const gfx::Size size = state_provider_->GetSize(); 174 const gfx::Size size = state_provider_->GetSize();
235 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, 175 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA,
236 size.width(), size.height(), 1, 0, GL_RGBA, 176 size.width(), size.height(), 1, 0, GL_RGBA,
237 GL_UNSIGNED_BYTE, gfx::Rect()); 177 GL_UNSIGNED_BYTE, gfx::Rect());
238 178
239 static_cast<AVDACodecImage*>(image.get()) 179 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture());
240 ->set_texture(texture_ref->texture());
241 } 180 }
242 181
243 // If we're clearing the image, or setting a SurfaceTexture backed image, we 182 // If we're clearing the image, or setting a SurfaceTexture backed image, we
244 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the 183 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the
245 // implementation will call CopyTexImage, which is where AVDACodecImage 184 // implementation will call CopyTexImage, which is where AVDACodecImage
246 // updates the SurfaceTexture to the right frame. 185 // updates the SurfaceTexture to the right frame.
247 auto image_state = gpu::gles2::Texture::UNBOUND; 186 auto image_state = gpu::gles2::Texture::UNBOUND;
248 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane 187 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane
249 // requires it. If something tries to sample from this texture it won't work, 188 // requires it. If something tries to sample from this texture it won't work,
250 // but there's no way to sample from a SurfaceView anyway, so it doesn't 189 // but there's no way to sample from a SurfaceView anyway, so it doesn't
251 // matter. 190 // matter.
252 if (image && !surface_texture_) 191 if (image && !shared_state_->surface_texture_service_id())
253 image_state = gpu::gles2::Texture::BOUND; 192 image_state = gpu::gles2::Texture::BOUND;
254 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), 193 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(),
255 0, image.get(), image_state, 194 0, image, image_state,
256 stream_texture_service_id); 195 stream_texture_service_id);
257 } 196 }
258 197
198 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture(
199 int picture_buffer_id) const {
200 auto it = codec_images_.find(picture_buffer_id);
201 return it == codec_images_.end() ? nullptr : it->second;
202 }
203
259 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( 204 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer(
260 int32_t codec_buf_index, 205 int32_t codec_buf_index,
261 const PictureBuffer& picture_buffer) { 206 const PictureBuffer& picture_buffer) {
262 // Make sure that the decoder is available. 207 // Make sure that the decoder is available.
263 RETURN_IF_NULL(state_provider_->GetGlDecoder()); 208 RETURN_IF_NULL(state_provider_->GetGlDecoder());
264 209
265 // Notify the AVDACodecImage for picture_buffer that it should use the 210 // Notify the AVDACodecImage for picture_buffer that it should use the
266 // decoded buffer codec_buf_index to render this frame. 211 // decoded buffer codec_buf_index to render this frame.
267 AVDACodecImage* avda_image = 212 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id());
268 shared_state_->GetImageForPicture(picture_buffer.id());
269 RETURN_IF_NULL(avda_image); 213 RETURN_IF_NULL(avda_image);
270 214
271 // Note that this is not a race, since we do not re-use a PictureBuffer 215 // Note that this is not a race, since we do not re-use a PictureBuffer
272 // until after the CC is done drawing it. 216 // until after the CC is done drawing it.
273 pictures_out_for_display_.push_back(picture_buffer.id()); 217 pictures_out_for_display_.push_back(picture_buffer.id());
274 avda_image->set_media_codec_buffer_index(codec_buf_index); 218 avda_image->SetBufferMetadata(codec_buf_index,
275 avda_image->set_size(state_provider_->GetSize()); 219 !!shared_state_->surface_texture_service_id(),
220 state_provider_->GetSize());
221
222 // If the shared state has changed for this image, retarget its texture.
223 if (avda_image->SetSharedState(shared_state_)) {
224 gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer);
225 RETURN_IF_NULL(texture_ref);
226 texture_ref->texture()->SetStreamTextureServiceId(
227 shared_state_->surface_texture_service_id());
228
229 // TODO(dalecurtis): What about ImageState? For ST we set UNBOUND while we
230 // always set BOUND for SV.
liberato (no reviews please) 2016/11/03 20:51:04 we should do that here too, i think. actually, i
DaleCurtis 2016/11/03 20:59:35 Originally tried this, but there are some restrict
DaleCurtis 2016/11/03 23:25:05 Ah, this was because the last ref to the GLImage w
231 }
276 232
277 MaybeRenderEarly(); 233 MaybeRenderEarly();
278 } 234 }
279 235
280 void AVDAPictureBufferManager::AssignOnePictureBuffer( 236 void AVDAPictureBufferManager::AssignOnePictureBuffer(
281 const PictureBuffer& picture_buffer, 237 const PictureBuffer& picture_buffer,
282 bool have_context) { 238 bool have_context) {
283 // Attach a GLImage to each texture that will use the surface texture. 239 // Attach a GLImage to each texture that will use the surface texture.
284 // We use a refptr here in case SetImageForPicture fails. 240 // We use a refptr here in case SetImageForPicture fails.
285 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = 241 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = new AVDACodecImage(
286 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, 242 shared_state_, media_codec_, state_provider_->GetGlDecoder());
287 state_provider_->GetGlDecoder()); 243 SetImageForPicture(picture_buffer, gl_image.get());
288 SetImageForPicture(picture_buffer, gl_image); 244 codec_images_[picture_buffer.id()] =
245 static_cast<AVDACodecImage*>(gl_image.get());
289 246
290 if (!surface_texture_ && have_context) { 247 // if (!shared_state_->surface_texture_service_id() && have_context) {
291 // To make devtools work, we're using a 2D texture. Make it transparent, 248 // // To make devtools work, we're using a 2D texture. Make it transparent,
292 // so that it draws a hole for the SV to show through. This is only 249 // // so that it draws a hole for the SV to show through. This is only
293 // because devtools draws and reads back, which skips overlay processing. 250 // // because devtools draws and reads back, which skips overlay processing.
294 // It's unclear why devtools renders twice -- once normally, and once 251 // // It's unclear why devtools renders twice -- once normally, and once
295 // including a readback layer. The result is that the device screen 252 // // including a readback layer. The result is that the device screen
296 // flashes as we alternately draw the overlay hole and this texture, 253 // // flashes as we alternately draw the overlay hole and this texture,
297 // unless we make the texture transparent. 254 // // unless we make the texture transparent.
298 static const uint8_t rgba[] = {0, 0, 0, 0}; 255 // static const uint8_t rgba[] = {0, 0, 0, 0};
299 const gfx::Size size(1, 1); 256 // const gfx::Size size(1, 1);
300 DCHECK_LE(1u, picture_buffer.service_texture_ids().size()); 257 // DCHECK_LE(1u, picture_buffer.service_texture_ids().size());
301 glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]); 258 // glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]);
302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, 259 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
303 GL_RGBA, GL_UNSIGNED_BYTE, rgba); 260 // GL_RGBA, GL_UNSIGNED_BYTE, rgba);
304 } 261 // }
305 } 262 }
306 263
307 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( 264 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture(
308 const PictureBuffer& picture_buffer) { 265 const PictureBuffer& picture_buffer) {
309 AVDACodecImage* avda_image = 266 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id());
310 shared_state_->GetImageForPicture(picture_buffer.id());
311 RETURN_IF_NULL(avda_image); 267 RETURN_IF_NULL(avda_image);
312 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); 268 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER);
313 } 269 }
314 270
315 void AVDAPictureBufferManager::ReuseOnePictureBuffer( 271 void AVDAPictureBufferManager::ReuseOnePictureBuffer(
316 const PictureBuffer& picture_buffer) { 272 const PictureBuffer& picture_buffer) {
317 pictures_out_for_display_.erase( 273 pictures_out_for_display_.erase(
318 std::remove(pictures_out_for_display_.begin(), 274 std::remove(pictures_out_for_display_.begin(),
319 pictures_out_for_display_.end(), picture_buffer.id()), 275 pictures_out_for_display_.end(), picture_buffer.id()),
320 pictures_out_for_display_.end()); 276 pictures_out_for_display_.end());
(...skipping 16 matching lines...) Expand all
337 if (pictures_out_for_display_.empty()) 293 if (pictures_out_for_display_.empty())
338 return; 294 return;
339 295
340 // See if we can consume the front buffer / render to the SurfaceView. Iterate 296 // See if we can consume the front buffer / render to the SurfaceView. Iterate
341 // in reverse to find the most recent front buffer. If none is found, the 297 // in reverse to find the most recent front buffer. If none is found, the
342 // |front_index| will point to the beginning of the array. 298 // |front_index| will point to the beginning of the array.
343 size_t front_index = pictures_out_for_display_.size() - 1; 299 size_t front_index = pictures_out_for_display_.size() - 1;
344 AVDACodecImage* first_renderable_image = nullptr; 300 AVDACodecImage* first_renderable_image = nullptr;
345 for (int i = front_index; i >= 0; --i) { 301 for (int i = front_index; i >= 0; --i) {
346 const int id = pictures_out_for_display_[i]; 302 const int id = pictures_out_for_display_[i];
347 AVDACodecImage* avda_image = shared_state_->GetImageForPicture(id); 303 AVDACodecImage* avda_image = GetImageForPicture(id);
348 if (!avda_image) 304 if (!avda_image)
349 continue; 305 continue;
350 306
351 // Update the front buffer index as we move along to shorten the number of 307 // Update the front buffer index as we move along to shorten the number of
352 // candidate images we look at for back buffer rendering. 308 // candidate images we look at for back buffer rendering.
353 front_index = i; 309 front_index = i;
354 first_renderable_image = avda_image; 310 first_renderable_image = avda_image;
355 311
356 // If we find a front buffer, stop and indicate that front buffer rendering 312 // If we find a front buffer, stop and indicate that front buffer rendering
357 // is not possible since another image is already in the front buffer. 313 // is not possible since another image is already in the front buffer.
358 if (avda_image->was_rendered_to_front_buffer()) { 314 if (avda_image->was_rendered_to_front_buffer()) {
359 first_renderable_image = nullptr; 315 first_renderable_image = nullptr;
360 break; 316 break;
361 } 317 }
362 } 318 }
363 319
364 if (first_renderable_image) { 320 if (first_renderable_image) {
365 first_renderable_image->UpdateSurface( 321 first_renderable_image->UpdateSurface(
366 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); 322 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER);
367 } 323 }
368 324
369 // Back buffer rendering is only available for surface textures. We'll always 325 // Back buffer rendering is only available for surface textures. We'll always
370 // have at least one front buffer, so the next buffer must be the backbuffer. 326 // have at least one front buffer, so the next buffer must be the backbuffer.
371 size_t backbuffer_index = front_index + 1; 327 size_t backbuffer_index = front_index + 1;
372 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) 328 if (!shared_state_->surface_texture_service_id() ||
329 backbuffer_index >= pictures_out_for_display_.size()) {
373 return; 330 return;
331 }
374 332
375 // See if the back buffer is free. If so, then render the frame adjacent to 333 // See if the back buffer is free. If so, then render the frame adjacent to
376 // the front buffer. The listing is in render order, so we can just use the 334 // the front buffer. The listing is in render order, so we can just use the
377 // first unrendered frame if there is back buffer space. 335 // first unrendered frame if there is back buffer space.
378 first_renderable_image = shared_state_->GetImageForPicture( 336 first_renderable_image =
379 pictures_out_for_display_[backbuffer_index]); 337 GetImageForPicture(pictures_out_for_display_[backbuffer_index]);
380 if (!first_renderable_image || 338 if (!first_renderable_image ||
381 first_renderable_image->was_rendered_to_back_buffer()) { 339 first_renderable_image->was_rendered_to_back_buffer()) {
382 return; 340 return;
383 } 341 }
384 342
385 // Due to the loop in the beginning this should never be true. 343 // Due to the loop in the beginning this should never be true.
386 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); 344 DCHECK(!first_renderable_image->was_rendered_to_front_buffer());
387 first_renderable_image->UpdateSurface( 345 first_renderable_image->UpdateSurface(
388 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); 346 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER);
389 } 347 }
390 348
391 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { 349 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) {
392 media_codec_ = codec; 350 media_codec_ = codec;
393 shared_state_->CodecChanged(codec); 351 for (auto& image_kv : codec_images_)
352 image_kv.second->CodecChanged(codec);
353 shared_state_->clear_release_time();
394 } 354 }
395 355
396 bool AVDAPictureBufferManager::ArePicturesOverlayable() { 356 bool AVDAPictureBufferManager::ArePicturesOverlayable() {
397 // SurfaceView frames are always overlayable because that's the only way to 357 // SurfaceView frames are always overlayable because that's the only way to
398 // display them. 358 // display them.
399 return !surface_texture_; 359 return !shared_state_->surface_texture_service_id();
360 }
361
362 bool AVDAPictureBufferManager::ArePicturesOutstanding() const {
363 for (int id : pictures_out_for_display_) {
364 AVDACodecImage* avda_image = GetImageForPicture(id);
365 if (avda_image && avda_image->has_unrendered_frame())
366 return true;
367 }
368 return false;
400 } 369 }
401 370
402 } // namespace media 371 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698