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 "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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |