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

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

Issue 2461073002: Use MediaCodec.setOutputSurface() for fullscreen transitions on M. (Closed)
Patch Set: Address comments. 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
« no previous file with comments | « media/gpu/avda_picture_buffer_manager.h ('k') | media/gpu/avda_shared_state.cc » ('j') | 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 "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
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 {
122 // For SurfaceView, request a 1x1 2D texture to reduce memory during
123 // initialization. For SurfaceTexture, allocate a picture buffer that is the
124 // actual frame size. Note that it will be an external texture anyway, so it
125 // doesn't allocate an image of that size. However, it's still important to
126 // get the coded size right, so that VideoLayerImpl doesn't try to scale the
127 // texture when building the quad for it.
128 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1);
129 }
130
131 void AVDAPictureBufferManager::SetImageForPicture( 117 void AVDAPictureBufferManager::SetImageForPicture(
132 const PictureBuffer& picture_buffer, 118 const PictureBuffer& picture_buffer,
133 gpu::gles2::GLStreamTextureImage* image) { 119 gpu::gles2::GLStreamTextureImage* image) {
134 auto gles_decoder = state_provider_->GetGlDecoder(); 120 auto gles_decoder = state_provider_->GetGlDecoder();
135 RETURN_IF_NULL(gles_decoder); 121 RETURN_IF_NULL(gles_decoder);
136 RETURN_IF_NULL(gles_decoder->GetContextGroup()); 122 auto* context_group = gles_decoder->GetContextGroup();
137 123 RETURN_IF_NULL(context_group);
138 gpu::gles2::TextureManager* texture_manager = 124 auto* texture_manager = context_group->texture_manager();
139 gles_decoder->GetContextGroup()->texture_manager();
140 RETURN_IF_NULL(texture_manager); 125 RETURN_IF_NULL(texture_manager);
141 126
142 DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); 127 DCHECK_LE(1u, picture_buffer.client_texture_ids().size());
143 gpu::gles2::TextureRef* texture_ref = 128 gpu::gles2::TextureRef* texture_ref =
144 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]); 129 texture_manager->GetTexture(picture_buffer.client_texture_ids()[0]);
145 RETURN_IF_NULL(texture_ref); 130 RETURN_IF_NULL(texture_ref);
146 131
147 // Default to zero which will clear the stream texture service id if one was 132 // Default to zero which will clear the stream texture service id if one was
148 // previously set. 133 // previously set.
149 GLuint stream_texture_service_id = 0; 134 GLuint stream_texture_service_id = 0;
150 if (image) { 135 if (image) {
151 // Override the Texture's service id, so that it will use the one that is 136 // Override the Texture's service id, so that it will use the one that is
152 // attached to the SurfaceTexture. 137 // attached to the SurfaceTexture.
153 stream_texture_service_id = shared_state_->surface_texture_service_id(); 138 stream_texture_service_id = shared_state_->surface_texture_service_id();
154 139
155 // Also set the parameters for the level if we're not clearing the image. 140 // Also set the parameters for the level if we're not clearing the image.
156 const gfx::Size size = state_provider_->GetSize(); 141 const gfx::Size size = state_provider_->GetSize();
157 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, 142 texture_manager->SetLevelInfo(texture_ref, kTextureTarget, 0, GL_RGBA,
158 size.width(), size.height(), 1, 0, GL_RGBA, 143 size.width(), size.height(), 1, 0, GL_RGBA,
159 GL_UNSIGNED_BYTE, gfx::Rect()); 144 GL_UNSIGNED_BYTE, gfx::Rect());
160 145
161 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture()); 146 static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture());
162 } 147 }
163 148
164 // If we're clearing the image, or setting a SurfaceTexture backed image, we 149 // 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 150 // set the state to UNBOUND. For SurfaceTexture images, this ensures that the
166 // implementation will call CopyTexImage, which is where AVDACodecImage 151 // implementation will call CopyTexImage, which is where AVDACodecImage
167 // updates the SurfaceTexture to the right frame. 152 // updates the SurfaceTexture to the right frame.
168 auto image_state = gpu::gles2::Texture::UNBOUND; 153 auto image_state = gpu::gles2::Texture::UNBOUND;
169 // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane 154 // 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, 155 // 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 156 // but there's no way to sample from a SurfaceView anyway, so it doesn't
172 // matter. 157 // matter.
173 if (image && !surface_texture_) 158 if (image && !surface_texture_)
174 image_state = gpu::gles2::Texture::BOUND; 159 image_state = gpu::gles2::Texture::BOUND;
175 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), 160 texture_manager->SetLevelStreamTextureImage(texture_ref, kTextureTarget, 0,
176 0, image, image_state, 161 image, image_state,
177 stream_texture_service_id); 162 stream_texture_service_id);
178 texture_manager->SetLevelCleared(texture_ref, GetTextureTarget(), 0, true); 163 texture_manager->SetLevelCleared(texture_ref, kTextureTarget, 0, true);
179 } 164 }
180 165
181 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture( 166 AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture(
182 int picture_buffer_id) const { 167 int picture_buffer_id) const {
183 auto it = codec_images_.find(picture_buffer_id); 168 auto it = codec_images_.find(picture_buffer_id);
184 return it == codec_images_.end() ? nullptr : it->second.get(); 169 DCHECK(it != codec_images_.end());
170 return it->second.get();
185 } 171 }
186 172
187 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( 173 void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer(
188 int32_t codec_buf_index, 174 int32_t codec_buf_index,
189 const PictureBuffer& picture_buffer) { 175 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 176 // Notify the AVDACodecImage for picture_buffer that it should use the
194 // decoded buffer codec_buf_index to render this frame. 177 // decoded buffer codec_buf_index to render this frame.
195 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); 178 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id());
196 RETURN_IF_NULL(avda_image);
197 179
198 // Note that this is not a race, since we do not re-use a PictureBuffer 180 // Note that this is not a race, since we do not re-use a PictureBuffer
199 // until after the CC is done drawing it. 181 // until after the CC is done drawing it.
200 pictures_out_for_display_.push_back(picture_buffer.id()); 182 pictures_out_for_display_.push_back(picture_buffer.id());
201 avda_image->set_media_codec_buffer_index(codec_buf_index); 183 avda_image->SetBufferMetadata(codec_buf_index, !!surface_texture_,
202 avda_image->set_size(state_provider_->GetSize()); 184 state_provider_->GetSize());
185
186 // If the shared state has changed for this image, retarget its texture.
187 if (avda_image->SetSharedState(shared_state_))
188 SetImageForPicture(picture_buffer, avda_image);
203 189
204 MaybeRenderEarly(); 190 MaybeRenderEarly();
205 } 191 }
206 192
207 void AVDAPictureBufferManager::AssignOnePictureBuffer( 193 void AVDAPictureBufferManager::AssignOnePictureBuffer(
208 const PictureBuffer& picture_buffer, 194 const PictureBuffer& picture_buffer,
209 bool have_context) { 195 bool have_context) {
210 // Attach a GLImage to each texture that will use the surface texture. 196 // Attach a GLImage to each texture that will use the surface texture.
211 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = 197 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image =
212 codec_images_[picture_buffer.id()] = new AVDACodecImage( 198 codec_images_[picture_buffer.id()] = new AVDACodecImage(
213 shared_state_, media_codec_, state_provider_->GetGlDecoder()); 199 shared_state_, media_codec_, state_provider_->GetGlDecoder());
214 SetImageForPicture(picture_buffer, gl_image.get()); 200 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 } 201 }
232 202
233 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( 203 void AVDAPictureBufferManager::ReleaseCodecBufferForPicture(
234 const PictureBuffer& picture_buffer) { 204 const PictureBuffer& picture_buffer) {
235 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); 205 GetImageForPicture(picture_buffer.id())
236 RETURN_IF_NULL(avda_image); 206 ->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER);
237 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER);
238 } 207 }
239 208
240 void AVDAPictureBufferManager::ReuseOnePictureBuffer( 209 void AVDAPictureBufferManager::ReuseOnePictureBuffer(
241 const PictureBuffer& picture_buffer) { 210 const PictureBuffer& picture_buffer) {
242 pictures_out_for_display_.erase( 211 pictures_out_for_display_.erase(
243 std::remove(pictures_out_for_display_.begin(), 212 std::remove(pictures_out_for_display_.begin(),
244 pictures_out_for_display_.end(), picture_buffer.id()), 213 pictures_out_for_display_.end(), picture_buffer.id()),
245 pictures_out_for_display_.end()); 214 pictures_out_for_display_.end());
246 215
247 // At this point, the CC must be done with the picture. We can't really 216 // At this point, the CC must be done with the picture. We can't really
(...skipping 15 matching lines...) Expand all
263 return; 232 return;
264 233
265 // See if we can consume the front buffer / render to the SurfaceView. Iterate 234 // 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 235 // 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. 236 // |front_index| will point to the beginning of the array.
268 size_t front_index = pictures_out_for_display_.size() - 1; 237 size_t front_index = pictures_out_for_display_.size() - 1;
269 AVDACodecImage* first_renderable_image = nullptr; 238 AVDACodecImage* first_renderable_image = nullptr;
270 for (int i = front_index; i >= 0; --i) { 239 for (int i = front_index; i >= 0; --i) {
271 const int id = pictures_out_for_display_[i]; 240 const int id = pictures_out_for_display_[i];
272 AVDACodecImage* avda_image = GetImageForPicture(id); 241 AVDACodecImage* avda_image = GetImageForPicture(id);
273 if (!avda_image)
274 continue;
275 242
276 // Update the front buffer index as we move along to shorten the number of 243 // Update the front buffer index as we move along to shorten the number of
277 // candidate images we look at for back buffer rendering. 244 // candidate images we look at for back buffer rendering.
278 front_index = i; 245 front_index = i;
279 first_renderable_image = avda_image; 246 first_renderable_image = avda_image;
280 247
281 // If we find a front buffer, stop and indicate that front buffer rendering 248 // 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. 249 // is not possible since another image is already in the front buffer.
283 if (avda_image->was_rendered_to_front_buffer()) { 250 if (avda_image->was_rendered_to_front_buffer()) {
284 first_renderable_image = nullptr; 251 first_renderable_image = nullptr;
(...skipping 10 matching lines...) Expand all
295 // have at least one front buffer, so the next buffer must be the backbuffer. 262 // have at least one front buffer, so the next buffer must be the backbuffer.
296 size_t backbuffer_index = front_index + 1; 263 size_t backbuffer_index = front_index + 1;
297 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) 264 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size())
298 return; 265 return;
299 266
300 // See if the back buffer is free. If so, then render the frame adjacent to 267 // 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 268 // 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. 269 // first unrendered frame if there is back buffer space.
303 first_renderable_image = 270 first_renderable_image =
304 GetImageForPicture(pictures_out_for_display_[backbuffer_index]); 271 GetImageForPicture(pictures_out_for_display_[backbuffer_index]);
305 if (!first_renderable_image || 272 if (first_renderable_image->was_rendered_to_back_buffer())
306 first_renderable_image->was_rendered_to_back_buffer()) {
307 return; 273 return;
308 }
309 274
310 // Due to the loop in the beginning this should never be true. 275 // Due to the loop in the beginning this should never be true.
311 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); 276 DCHECK(!first_renderable_image->was_rendered_to_front_buffer());
312 first_renderable_image->UpdateSurface( 277 first_renderable_image->UpdateSurface(
313 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); 278 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER);
314 } 279 }
315 280
316 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) { 281 void AVDAPictureBufferManager::CodecChanged(VideoCodecBridge* codec) {
317 media_codec_ = codec; 282 media_codec_ = codec;
318 for (auto& image_kv : codec_images_) 283 for (auto& image_kv : codec_images_)
319 image_kv.second->CodecChanged(codec); 284 image_kv.second->CodecChanged(codec);
320 shared_state_->clear_release_time(); 285 shared_state_->clear_release_time();
321 } 286 }
322 287
323 bool AVDAPictureBufferManager::ArePicturesOverlayable() { 288 bool AVDAPictureBufferManager::ArePicturesOverlayable() {
324 // SurfaceView frames are always overlayable because that's the only way to 289 // SurfaceView frames are always overlayable because that's the only way to
325 // display them. 290 // display them.
326 return !surface_texture_; 291 return !surface_texture_;
327 } 292 }
328 293
294 bool AVDAPictureBufferManager::HasUnrenderedPictures() const {
295 for (int id : pictures_out_for_display_) {
296 if (GetImageForPicture(id)->is_unrendered())
297 return true;
298 }
299 return false;
300 }
301
329 } // namespace media 302 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/avda_picture_buffer_manager.h ('k') | media/gpu/avda_shared_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698