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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 AVDAPictureBufferManager::AVDAPictureBufferManager( | 77 AVDAPictureBufferManager::AVDAPictureBufferManager( |
78 AVDAStateProvider* state_provider) | 78 AVDAStateProvider* state_provider) |
79 : state_provider_(state_provider), media_codec_(nullptr) {} | 79 : state_provider_(state_provider), media_codec_(nullptr) {} |
80 | 80 |
81 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} | 81 AVDAPictureBufferManager::~AVDAPictureBufferManager() {} |
82 | 82 |
83 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize(int surface_id) { | 83 gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize(int surface_id) { |
84 shared_state_ = new AVDASharedState(); | 84 shared_state_ = new AVDASharedState(); |
85 | 85 |
86 // Acquire the SurfaceView surface if given a valid id. | 86 // Acquire the SurfaceView surface if given a valid id. |
87 if (surface_id != SurfaceManager::kNoSurfaceID) | 87 if (surface_id != SurfaceManager::kNoSurfaceID) { |
88 if (surface_texture_) { | |
89 surface_texture_->ReleaseSurfaceTexture(); | |
90 surface_texture_ = nullptr; | |
91 } | |
88 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_id); | 92 return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_id); |
93 } | |
89 | 94 |
90 // Otherwise create a SurfaceTexture. | 95 // Otherwise create a SurfaceTexture. |
91 GLuint service_id; | 96 GLuint service_id; |
92 surface_texture_ = CreateAttachedSurfaceTexture( | 97 surface_texture_ = CreateAttachedSurfaceTexture( |
93 state_provider_->GetGlDecoder(), &service_id); | 98 state_provider_->GetGlDecoder(), &service_id); |
94 shared_state_->SetSurfaceTexture(surface_texture_, service_id); | 99 shared_state_->SetSurfaceTexture(surface_texture_, service_id); |
95 return gl::ScopedJavaSurface(surface_texture_.get()); | 100 return gl::ScopedJavaSurface(surface_texture_.get()); |
96 } | 101 } |
97 | 102 |
98 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { | 103 void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { |
99 // Do nothing if Initialize() has not been called. | 104 // Do nothing if Initialize() has not been called. |
100 if (!shared_state_) | 105 if (!shared_state_) |
101 return; | 106 return; |
102 | 107 |
103 ReleaseCodecBuffers(buffers); | 108 ReleaseCodecBuffers(buffers); |
104 CodecChanged(nullptr); | 109 CodecChanged(nullptr); |
105 | 110 |
106 // Release the surface texture and any back buffers. This will preserve the | 111 // Release the surface texture and any back buffers. This will preserve the |
107 // front buffer, if any. | 112 // front buffer, if any. |
108 if (surface_texture_) | 113 if (surface_texture_) |
109 surface_texture_->ReleaseSurfaceTexture(); | 114 surface_texture_->ReleaseSurfaceTexture(); |
110 } | 115 } |
111 | 116 |
112 uint32_t AVDAPictureBufferManager::GetTextureTarget() const { | |
113 // If we're using a surface texture, then we need an external texture target | |
114 // to sample from it. If not, then we'll use 2D transparent textures to draw | |
115 // a transparent hole through which to see the SurfaceView. This is normally | |
116 // needed only for the devtools inspector, since the overlay mechanism handles | |
117 // it otherwise. | |
118 return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; | |
119 } | |
120 | |
121 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { | 117 gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { |
watk
2016/11/09 01:20:48
Just realized the only caller of this is AVDA and
DaleCurtis
2016/11/09 21:58:17
Good catch, removed, fixed up code to use DCHECK i
| |
122 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 118 // Allocate a picture buffer that is the actual frame size. Note that it will |
123 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 119 // be an external texture anyway, so it doesn't allocate an image of that |
124 // actual frame size. Note that it will be an external texture anyway, so it | 120 // size. It's important to get the coded size right, so that VideoLayerImpl |
125 // doesn't allocate an image of that size. However, it's still important to | 121 // doesn't try to scale the texture when building the quad for it. |
126 // get the coded size right, so that VideoLayerImpl doesn't try to scale the | 122 return state_provider_->GetSize(); |
127 // texture when building the quad for it. | |
128 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | |
129 } | 123 } |
130 | 124 |
131 void AVDAPictureBufferManager::SetImageForPicture( | 125 void AVDAPictureBufferManager::SetImageForPicture( |
132 const PictureBuffer& picture_buffer, | 126 const PictureBuffer& picture_buffer, |
133 gpu::gles2::GLStreamTextureImage* image) { | 127 gpu::gles2::GLStreamTextureImage* image) { |
134 auto gles_decoder = state_provider_->GetGlDecoder(); | 128 auto gles_decoder = state_provider_->GetGlDecoder(); |
135 RETURN_IF_NULL(gles_decoder); | 129 RETURN_IF_NULL(gles_decoder); |
136 RETURN_IF_NULL(gles_decoder->GetContextGroup()); | 130 auto* context_group = gles_decoder->GetContextGroup(); |
137 | 131 RETURN_IF_NULL(context_group); |
138 gpu::gles2::TextureManager* texture_manager = | 132 auto* texture_manager = context_group->texture_manager(); |
139 gles_decoder->GetContextGroup()->texture_manager(); | |
140 RETURN_IF_NULL(texture_manager); | 133 RETURN_IF_NULL(texture_manager); |
141 | 134 |
142 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); | 135 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); |
143 gpu::gles2::TextureRef* texture_ref = | 136 gpu::gles2::TextureRef* texture_ref = |
144 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); | 137 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); |
145 RETURN_IF_NULL(texture_ref); | 138 RETURN_IF_NULL(texture_ref); |
146 | 139 |
147 // Default to zero which will clear the stream texture service id if one was | 140 // Default to zero which will clear the stream texture service id if one was |
148 // previously set. | 141 // previously set. |
149 GLuint stream_texture_service_id = 0; | 142 GLuint stream_texture_service_id = 0; |
150 if (image) { | 143 if (image) { |
151 // Override the Texture's service id, so that it will use the one that is | 144 // Override the Texture's service id, so that it will use the one that is |
152 // attached to the SurfaceTexture. | 145 // attached to the SurfaceTexture. |
153 stream_texture_service_id = shared_state_->surface_texture_service_id(); | 146 stream_texture_service_id = shared_state_->surface_texture_service_id(); |
154 | 147 |
155 // Also set the parameters for the level if we're not clearing the image. | 148 // Also set the parameters for the level if we're not clearing the image. |
156 const gfx::Size size = state_provider_->GetSize(); | 149 const gfx::Size size = state_provider_->GetSize(); |
157 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, | 150 texture_manager->SetLevelInfo(texture_ref, kTextureTarget, 0, GL_RGBA, |
158 size.width(), size.height(), 1, 0, GL_RGBA, | 151 size.width(), size.height(), 1, 0, GL_RGBA, |
159 GL_UNSIGNED_BYTE, gfx::Rect()); | 152 GL_UNSIGNED_BYTE, gfx::Rect()); |
160 | 153 |
161 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture()); | 154 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture()); |
162 } | 155 } |
163 | 156 |
164 // If we're clearing the image, or setting a SurfaceTexture backed image, we | 157 // If we're clearing the image, or setting a SurfaceTexture backed image, we |
165 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the | 158 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the |
166 // implementation will call CopyTexImage, which is where AVDACodecImage | 159 // implementation will call CopyTexImage, which is where AVDACodecImage |
167 // updates the SurfaceTexture to the right frame. | 160 // updates the SurfaceTexture to the right frame. |
168 auto image_state = gpu::gles2::Texture::UNBOUND; | 161 auto image_state = gpu::gles2::Texture::UNBOUND; |
169 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane | 162 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane |
170 // requires it. If something tries to sample from this texture it won't work, | 163 // requires it. If something tries to sample from this texture it won't work, |
171 // but there's no way to sample from a SurfaceView anyway, so it doesn't | 164 // but there's no way to sample from a SurfaceView anyway, so it doesn't |
172 // matter. | 165 // matter. |
173 if (image && !surface_texture_) | 166 if (image && !surface_texture_) |
174 image_state = gpu::gles2::Texture::BOUND; | 167 image_state = gpu::gles2::Texture::BOUND; |
175 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), | 168 texture_manager->SetLevelStreamTextureImage(texture_ref, kTextureTarget, 0, |
176 0, image, image_state, | 169 image, image_state, |
177 stream_texture_service_id); | 170 stream_texture_service_id); |
178 texture_manager->SetLevelCleared(texture_ref, GetTextureTarget(), 0, true); | 171 texture_manager->SetLevelCleared(texture_ref, kTextureTarget, 0, true); |
179 } | 172 } |
180 | 173 |
181 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture( | 174 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture( |
182 int picture_buffer_id) const { | 175 int picture_buffer_id) const { |
183 auto it = codec_images_.find(picture_buffer_id); | 176 auto it = codec_images_.find(picture_buffer_id); |
184 return it == codec_images_.end() ? nullptr : it->second.get(); | 177 DCHECK(it != codec_images_.end()); |
178 return it->second.get(); | |
185 } | 179 } |
186 | 180 |
187 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( | 181 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( |
188 int32_t codec_buf_index, | 182 int32_t codec_buf_index, |
189 const PictureBuffer& picture_buffer) { | 183 const PictureBuffer& picture_buffer) { |
190 // Make sure that the decoder is available. | |
191 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | |
192 | |
193 // Notify the AVDACodecImage for picture_buffer that it should use the | 184 // Notify the AVDACodecImage for picture_buffer that it should use the |
194 // decoded buffer codec_buf_index to render this frame. | 185 // decoded buffer codec_buf_index to render this frame. |
195 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); | 186 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); |
196 RETURN_IF_NULL(avda_image); | |
197 | 187 |
198 // Note that this is not a race, since we do not re-use a PictureBuffer | 188 // Note that this is not a race, since we do not re-use a PictureBuffer |
199 // until after the CC is done drawing it. | 189 // until after the CC is done drawing it. |
200 pictures_out_for_display_.push_back(picture_buffer.id()); | 190 pictures_out_for_display_.push_back(picture_buffer.id()); |
201 avda_image->set_media_codec_buffer_index(codec_buf_index); | 191 avda_image->SetBufferMetadata(codec_buf_index, !!surface_texture_, |
202 avda_image->set_size(state_provider_->GetSize()); | 192 state_provider_->GetSize()); |
193 | |
194 // If the shared state has changed for this image, retarget its texture. | |
195 if (avda_image->SetSharedState(shared_state_)) | |
196 SetImageForPicture(picture_buffer, avda_image); | |
203 | 197 |
204 MaybeRenderEarly(); | 198 MaybeRenderEarly(); |
205 } | 199 } |
206 | 200 |
207 void AVDAPictureBufferManager::AssignOnePictureBuffer( | 201 void AVDAPictureBufferManager::AssignOnePictureBuffer( |
208 const PictureBuffer& picture_buffer, | 202 const PictureBuffer& picture_buffer, |
209 bool have_context) { | 203 bool have_context) { |
210 // Attach a GLImage to each texture that will use the surface texture. | 204 // Attach a GLImage to each texture that will use the surface texture. |
211 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 205 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
212 codec_images_[picture_buffer.id()] = new AVDACodecImage( | 206 codec_images_[picture_buffer.id()] = new AVDACodecImage( |
213 shared_state_, media_codec_, state_provider_->GetGlDecoder()); | 207 shared_state_, media_codec_, state_provider_->GetGlDecoder()); |
214 SetImageForPicture(picture_buffer, gl_image.get()); | 208 SetImageForPicture(picture_buffer, gl_image.get()); |
215 | |
216 if (!surface_texture_ && have_context) { | |
217 // To make devtools work, we're using a 2D texture. Make it transparent, | |
218 // so that it draws a hole for the SV to show through. This is only | |
219 // because devtools draws and reads back, which skips overlay processing. | |
220 // It's unclear why devtools renders twice -- once normally, and once | |
221 // including a readback layer. The result is that the device screen | |
222 // flashes as we alternately draw the overlay hole and this texture, | |
223 // unless we make the texture transparent. | |
224 static const uint8_t rgba[] = {0, 0, 0, 0}; | |
225 const gfx::Size size(1, 1); | |
226 DCHECK_LE(1u, picture_buffer.service_texture_ids().size()); | |
227 glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]); | |
228 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | |
229 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | |
230 } | |
231 } | 209 } |
232 | 210 |
233 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( | 211 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( |
234 const PictureBuffer& picture_buffer) { | 212 const PictureBuffer& picture_buffer) { |
235 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); | 213 GetImageForPicture(picture_buffer.id()) |
236 RETURN_IF_NULL(avda_image); | 214 ->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
237 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); | |
238 } | 215 } |
239 | 216 |
240 void AVDAPictureBufferManager::ReuseOnePictureBuffer( | 217 void AVDAPictureBufferManager::ReuseOnePictureBuffer( |
241 const PictureBuffer& picture_buffer) { | 218 const PictureBuffer& picture_buffer) { |
242 pictures_out_for_display_.erase( | 219 pictures_out_for_display_.erase( |
243 std::remove(pictures_out_for_display_.begin(), | 220 std::remove(pictures_out_for_display_.begin(), |
244 pictures_out_for_display_.end(), picture_buffer.id()), | 221 pictures_out_for_display_.end(), picture_buffer.id()), |
245 pictures_out_for_display_.end()); | 222 pictures_out_for_display_.end()); |
246 | 223 |
247 // At this point, the CC must be done with the picture. We can't really | 224 // At this point, the CC must be done with the picture. We can't really |
(...skipping 15 matching lines...) Expand all Loading... | |
263 return; | 240 return; |
264 | 241 |
265 // See if we can consume the front buffer / render to the SurfaceView. Iterate | 242 // See if we can consume the front buffer / render to the SurfaceView. Iterate |
266 // in reverse to find the most recent front buffer. If none is found, the | 243 // in reverse to find the most recent front buffer. If none is found, the |
267 // |front_index| will point to the beginning of the array. | 244 // |front_index| will point to the beginning of the array. |
268 size_t front_index = pictures_out_for_display_.size() - 1; | 245 size_t front_index = pictures_out_for_display_.size() - 1; |
269 AVDACodecImage* first_renderable_image = nullptr; | 246 AVDACodecImage* first_renderable_image = nullptr; |
270 for (int i = front_index; i >= 0; --i) { | 247 for (int i = front_index; i >= 0; --i) { |
271 const int id = pictures_out_for_display_[i]; | 248 const int id = pictures_out_for_display_[i]; |
272 AVDACodecImage* avda_image = GetImageForPicture(id); | 249 AVDACodecImage* avda_image = GetImageForPicture(id); |
273 if (!avda_image) | |
274 continue; | |
275 | 250 |
276 // Update the front buffer index as we move along to shorten the number of | 251 // Update the front buffer index as we move along to shorten the number of |
277 // candidate images we look at for back buffer rendering. | 252 // candidate images we look at for back buffer rendering. |
278 front_index = i; | 253 front_index = i; |
279 first_renderable_image = avda_image; | 254 first_renderable_image = avda_image; |
280 | 255 |
281 // If we find a front buffer, stop and indicate that front buffer rendering | 256 // If we find a front buffer, stop and indicate that front buffer rendering |
282 // is not possible since another image is already in the front buffer. | 257 // is not possible since another image is already in the front buffer. |
283 if (avda_image->was_rendered_to_front_buffer()) { | 258 if (avda_image->was_rendered_to_front_buffer()) { |
284 first_renderable_image = nullptr; | 259 first_renderable_image = nullptr; |
(...skipping 10 matching lines...) Expand all Loading... | |
295 // have at least one front buffer, so the next buffer must be the backbuffer. | 270 // have at least one front buffer, so the next buffer must be the backbuffer. |
296 size_t backbuffer_index = front_index + 1; | 271 size_t backbuffer_index = front_index + 1; |
297 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) | 272 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) |
298 return; | 273 return; |
299 | 274 |
300 // See if the back buffer is free. If so, then render the frame adjacent to | 275 // See if the back buffer is free. If so, then render the frame adjacent to |
301 // the front buffer. The listing is in render order, so we can just use the | 276 // the front buffer. The listing is in render order, so we can just use the |
302 // first unrendered frame if there is back buffer space. | 277 // first unrendered frame if there is back buffer space. |
303 first_renderable_image = | 278 first_renderable_image = |
304 GetImageForPicture(pictures_out_for_display_[backbuffer_index]); | 279 GetImageForPicture(pictures_out_for_display_[backbuffer_index]); |
305 if (!first_renderable_image || | 280 if (first_renderable_image->was_rendered_to_back_buffer()) |
306 first_renderable_image->was_rendered_to_back_buffer()) { | |
307 return; | 281 return; |
308 } | |
309 | 282 |
310 // Due to the loop in the beginning this should never be true. | 283 // Due to the loop in the beginning this should never be true. |
311 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); | 284 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); |
312 first_renderable_image->UpdateSurface( | 285 first_renderable_image->UpdateSurface( |
313 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); | 286 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); |
314 } | 287 } |
315 | 288 |
316 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { | 289 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { |
317 media_codec_ = codec; | 290 media_codec_ = codec; |
318 for (auto& image_kv : codec_images_) | 291 for (auto& image_kv : codec_images_) |
319 image_kv.second->CodecChanged(codec); | 292 image_kv.second->CodecChanged(codec); |
320 shared_state_->clear_release_time(); | 293 shared_state_->clear_release_time(); |
321 } | 294 } |
322 | 295 |
323 bool AVDAPictureBufferManager::ArePicturesOverlayable() { | 296 bool AVDAPictureBufferManager::ArePicturesOverlayable() { |
324 // SurfaceView frames are always overlayable because that's the only way to | 297 // SurfaceView frames are always overlayable because that's the only way to |
325 // display them. | 298 // display them. |
326 return !surface_texture_; | 299 return !surface_texture_; |
327 } | 300 } |
328 | 301 |
302 bool AVDAPictureBufferManager::HasUnrenderedPictures() const { | |
303 for (int id : pictures_out_for_display_) { | |
304 if (GetImageForPicture(id)->is_unrendered()) | |
305 return true; | |
306 } | |
307 return false; | |
308 } | |
309 | |
329 } // namespace media | 310 } // namespace media |
OLD | NEW |