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

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

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Squash and rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/media/avda_codec_image.h"
6
7 #include <string.h>
8
9 #include <memory>
10
11 #include "base/metrics/histogram_macros.h"
12 #include "content/common/gpu/media/avda_shared_state.h"
13 #include "gpu/command_buffer/service/context_group.h"
14 #include "gpu/command_buffer/service/context_state.h"
15 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
16 #include "gpu/command_buffer/service/texture_manager.h"
17 #include "ui/gl/android/surface_texture.h"
18 #include "ui/gl/gl_context.h"
19 #include "ui/gl/scoped_make_current.h"
20
21 namespace content {
22
23 AVDACodecImage::AVDACodecImage(
24 int picture_buffer_id,
25 const scoped_refptr<AVDASharedState>& shared_state,
26 media::VideoCodecBridge* codec,
27 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder,
28 const scoped_refptr<gfx::SurfaceTexture>& surface_texture)
29 : shared_state_(shared_state),
30 codec_buffer_index_(kInvalidCodecBufferIndex),
31 media_codec_(codec),
32 decoder_(decoder),
33 surface_texture_(surface_texture),
34 detach_surface_texture_on_destruction_(false),
35 texture_(0),
36 picture_buffer_id_(picture_buffer_id) {
37 // Default to a sane guess of "flip Y", just in case we can't get
38 // the matrix on the first call.
39 memset(gl_matrix_, 0, sizeof(gl_matrix_));
40 gl_matrix_[0] = gl_matrix_[10] = gl_matrix_[15] = 1.0f;
41 gl_matrix_[5] = -1.0f;
42 shared_state_->SetImageForPicture(picture_buffer_id_, this);
43 }
44
45 AVDACodecImage::~AVDACodecImage() {
46 shared_state_->SetImageForPicture(picture_buffer_id_, nullptr);
47 }
48
49 void AVDACodecImage::Destroy(bool have_context) {}
50
51 gfx::Size AVDACodecImage::GetSize() {
52 return size_;
53 }
54
55 unsigned AVDACodecImage::GetInternalFormat() {
56 return GL_RGBA;
57 }
58
59 bool AVDACodecImage::BindTexImage(unsigned target) {
60 return false;
61 }
62
63 void AVDACodecImage::ReleaseTexImage(unsigned target) {}
64
65 bool AVDACodecImage::CopyTexImage(unsigned target) {
66 if (!surface_texture_)
67 return false;
68
69 if (target != GL_TEXTURE_EXTERNAL_OES)
70 return false;
71
72 GLint bound_service_id = 0;
73 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
74 // We insist that the currently bound texture is the right one. We could
75 // make a new glimage from a 2D image.
76 if (bound_service_id != shared_state_->surface_texture_service_id())
77 return false;
78
79 // If the surface texture isn't attached yet, then attach it. Note that this
80 // will be to the texture in |shared_state_|, because of the checks above.
81 if (!shared_state_->surface_texture_is_attached())
82 AttachSurfaceTextureToContext();
83
84 // Make sure that we have the right image in the front buffer. Note that the
85 // bound_service_id is guaranteed to be equal to the surface texture's client
86 // texture id, so we can skip preserving it if the right context is current.
87 UpdateSurfaceInternal(UpdateMode::RENDER_TO_FRONT_BUFFER,
88 kDontRestoreBindings);
89
90 // By setting image state to UNBOUND instead of COPIED we ensure that
91 // CopyTexImage() is called each time the surface texture is used for drawing.
92 // It would be nice if we could do this via asking for the currently bound
93 // Texture, but the active unit never seems to change.
94 texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
95 gpu::gles2::Texture::UNBOUND);
96
97 return true;
98 }
99
100 bool AVDACodecImage::CopyTexSubImage(unsigned target,
101 const gfx::Point& offset,
102 const gfx::Rect& rect) {
103 return false;
104 }
105
106 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
107 int z_order,
108 gfx::OverlayTransform transform,
109 const gfx::Rect& bounds_rect,
110 const gfx::RectF& crop_rect) {
111 // This should only be called when we're rendering to a SurfaceView.
112 if (surface_texture_) {
113 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is "
114 "SurfaceTexture backed.";
115 return false;
116 }
117
118 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER);
119 return true;
120 }
121
122 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
123 uint64_t process_tracing_id,
124 const std::string& dump_name) {}
125
126 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) {
127 DCHECK(surface_texture_);
128 DCHECK_EQ(codec_buffer_index_, kUpdateOnly);
129 codec_buffer_index_ = kInvalidCodecBufferIndex;
130
131 // Swap the rendered image to the front.
132 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current =
133 MakeCurrentIfNeeded();
134
135 // If we changed contexts, then we always want to restore it, since the caller
136 // doesn't know that we're switching contexts.
137 if (scoped_make_current)
138 mode = kDoRestoreBindings;
139
140 // Save the current binding if requested.
141 GLint bound_service_id = 0;
142 if (mode == kDoRestoreBindings)
143 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
144
145 surface_texture_->UpdateTexImage();
146 if (mode == kDoRestoreBindings)
147 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
148
149 // Helpfully, this is already column major.
150 surface_texture_->GetTransformMatrix(gl_matrix_);
151 }
152
153 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) {
154 codec_buffer_index_ = buffer_index;
155 }
156
157 void AVDACodecImage::SetSize(const gfx::Size& size) {
158 size_ = size;
159 }
160
161 void AVDACodecImage::UpdateSurface(UpdateMode update_mode) {
162 UpdateSurfaceInternal(update_mode, kDoRestoreBindings);
163 }
164
165 void AVDACodecImage::CodecChanged(media::MediaCodecBridge* codec) {
166 media_codec_ = codec;
167 codec_buffer_index_ = kInvalidCodecBufferIndex;
168 }
169
170 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) {
171 texture_ = texture;
172 }
173
174 void AVDACodecImage::UpdateSurfaceInternal(
175 UpdateMode update_mode,
176 RestoreBindingsMode attached_bindings_mode) {
177 if (!IsCodecBufferOutstanding())
178 return;
179
180 ReleaseOutputBuffer(update_mode);
181
182 // SurfaceViews are updated implicitly, so no further steps are necessary.
183 if (!surface_texture_) {
184 DCHECK(update_mode != UpdateMode::RENDER_TO_BACK_BUFFER);
185 return;
186 }
187
188 // If front buffer rendering hasn't been requested, exit early.
189 if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER)
190 return;
191
192 // Surface texture is already attached, so just update it.
193 if (shared_state_->surface_texture_is_attached()) {
194 UpdateSurfaceTexture(attached_bindings_mode);
195 return;
196 }
197
198 // Don't attach the surface texture permanently. Perhaps we should just
199 // attach the surface texture in avda and be done with it.
200 GLuint service_id = 0;
201 glGenTextures(1, &service_id);
202 GLint bound_service_id = 0;
203 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
204 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
205 AttachSurfaceTextureToContext();
206 UpdateSurfaceTexture(kDontRestoreBindings);
207
208 // Detach the surface texture, which deletes the generated texture.
209 surface_texture_->DetachFromGLContext();
210 shared_state_->DidDetachSurfaceTexture();
211 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
212 }
213
214 void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) {
215 DCHECK(IsCodecBufferOutstanding());
216
217 // In case of discard, simply discard and clear our codec buffer index.
218 if (update_mode == UpdateMode::DISCARD_CODEC_BUFFER) {
219 if (codec_buffer_index_ != kUpdateOnly)
220 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false);
221 codec_buffer_index_ = kInvalidCodecBufferIndex;
222 return;
223 }
224
225 DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER ||
226 update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER);
227
228 // If we've already released to the back buffer, there's nothing left to do.
229 if (codec_buffer_index_ == kUpdateOnly)
230 return;
231
232 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
233 codec_buffer_index_ = kUpdateOnly;
234
235 // If we're using a SurfaceView we're done!
236 if (!surface_texture_) {
237 codec_buffer_index_ = kInvalidCodecBufferIndex;
238 return;
239 }
240
241 // This must be synchronous, so wait for OnFrameAvailable.
242 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame");
243 shared_state_->WaitForFrameAvailable();
244 }
245
246 void AVDACodecImage::AttachSurfaceTextureToContext() {
247 DCHECK(surface_texture_);
248
249 // We assume that the currently bound texture is the intended one.
250
251 // Attach the surface texture to the first context we're bound on, so that
252 // no context switch is needed later.
253 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
254 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
255 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
256 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
257
258 // The surface texture is already detached, so just attach it.
259 // We could do this earlier, but SurfaceTexture has context affinity, and we
260 // don't want to require a context switch.
261 surface_texture_->AttachToGLContext();
262 shared_state_->DidAttachSurfaceTexture();
263 }
264
265 std::unique_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() {
266 DCHECK(shared_state_->context());
267 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current;
268 if (!shared_state_->context()->IsCurrent(NULL)) {
269 scoped_make_current.reset(new ui::ScopedMakeCurrent(
270 shared_state_->context(), shared_state_->surface()));
271 }
272
273 return scoped_make_current;
274 }
275
276 void AVDACodecImage::GetTextureMatrix(float matrix[16]) {
277 // Our current matrix may be stale. Update it if possible.
278 if (surface_texture_)
279 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER);
280 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_));
281 }
282
283 bool AVDACodecImage::IsCodecBufferOutstanding() const {
284 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_;
285 }
286
287 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698