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

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

Issue 1559203003: Add GLStreamTextureImage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/GL_EXPORT/GPU_EXPORT for windows Created 4 years, 10 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
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 "content/common/gpu/media/avda_codec_image.h" 5 #include "content/common/gpu/media/avda_codec_image.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "content/common/gpu/media/avda_shared_state.h" 10 #include "content/common/gpu/media/avda_shared_state.h"
(...skipping 11 matching lines...) Expand all
22 const scoped_refptr<AVDASharedState>& shared_state, 22 const scoped_refptr<AVDASharedState>& shared_state,
23 media::VideoCodecBridge* codec, 23 media::VideoCodecBridge* codec,
24 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder, 24 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder,
25 const scoped_refptr<gfx::SurfaceTexture>& surface_texture) 25 const scoped_refptr<gfx::SurfaceTexture>& surface_texture)
26 : shared_state_(shared_state), 26 : shared_state_(shared_state),
27 codec_buffer_index_(kInvalidCodecBufferIndex), 27 codec_buffer_index_(kInvalidCodecBufferIndex),
28 media_codec_(codec), 28 media_codec_(codec),
29 decoder_(decoder), 29 decoder_(decoder),
30 surface_texture_(surface_texture), 30 surface_texture_(surface_texture),
31 detach_surface_texture_on_destruction_(false), 31 detach_surface_texture_on_destruction_(false),
32 texture_(0), 32 texture_(0) {
33 need_shader_info_(true), 33 // Default to a sane guess of "flip Y", just in case we can't get
34 texmatrix_uniform_location_(-1) { 34 // the matrix on the first call.
35 memset(gl_matrix_, 0, sizeof(gl_matrix_)); 35 memset(gl_matrix_, 0, sizeof(gl_matrix_));
36 gl_matrix_[0] = gl_matrix_[5] = gl_matrix_[10] = gl_matrix_[15] = 1.0f; 36 gl_matrix_[0] = gl_matrix_[10] = gl_matrix_[15] = 1.0f;
37 gl_matrix_[5] = -1.0f;
37 } 38 }
38 39
39 AVDACodecImage::~AVDACodecImage() {} 40 AVDACodecImage::~AVDACodecImage() {}
40 41
41 void AVDACodecImage::Destroy(bool have_context) {} 42 void AVDACodecImage::Destroy(bool have_context) {}
42 43
43 gfx::Size AVDACodecImage::GetSize() { 44 gfx::Size AVDACodecImage::GetSize() {
44 return size_; 45 return size_;
45 } 46 }
46 47
47 unsigned AVDACodecImage::GetInternalFormat() { 48 unsigned AVDACodecImage::GetInternalFormat() {
48 return GL_RGBA; 49 return GL_RGBA;
49 } 50 }
50 51
51 bool AVDACodecImage::BindTexImage(unsigned target) { 52 bool AVDACodecImage::BindTexImage(unsigned target) {
52 return false; 53 return false;
53 } 54 }
54 55
55 void AVDACodecImage::ReleaseTexImage(unsigned target) {} 56 void AVDACodecImage::ReleaseTexImage(unsigned target) {}
56 57
57 bool AVDACodecImage::CopyTexImage(unsigned target) { 58 bool AVDACodecImage::CopyTexImage(unsigned target) {
58 if (!surface_texture_) 59 if (!surface_texture_)
59 return false; 60 return false;
60 61
61 if (target != GL_TEXTURE_EXTERNAL_OES) 62 if (target != GL_TEXTURE_EXTERNAL_OES)
62 return false; 63 return false;
63 64
64 // Verify that the currently bound texture is the right one. If we're not
65 // copying to a Texture that shares our service_id, then we can't do much.
66 // This will force a copy.
67 // TODO(liberato): Fall back to a copy that uses the texture matrix.
68 GLint bound_service_id = 0; 65 GLint bound_service_id = 0;
69 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); 66 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
67 // We insist that the currently bound texture is the right one. We could
68 // make a new glimage from a 2D image.
70 if (bound_service_id != shared_state_->surface_texture_service_id()) 69 if (bound_service_id != shared_state_->surface_texture_service_id())
71 return false; 70 return false;
72 71
73 // Attach the surface texture to our GL context if needed. 72 // If the surface texture isn't attached yet, then attach it. Note that this
73 // will be to the texture in |shared_state_|, because of the checks above.
74 if (!shared_state_->surface_texture_is_attached()) 74 if (!shared_state_->surface_texture_is_attached())
75 AttachSurfaceTextureToContext(); 75 AttachSurfaceTextureToContext();
76 76
77 // Make sure that we have the right image in the front buffer. 77 // Make sure that we have the right image in the front buffer. Note that the
78 UpdateSurfaceTexture(); 78 // bound_service_id is guaranteed to be equal to the surface texture's client
79 79 // texture id, so we can skip preserving it if the right context is current.
80 InstallTextureMatrix(); 80 UpdateSurfaceTexture(kDontRestoreBindings);
81
82 // TODO(liberato): Handle the texture matrix properly.
83 // Either we can update the shader with it or we can move all of the logic
84 // to updateTexImage() to the right place in the cc to send it to the shader.
85 // For now, we just skip it. crbug.com/530681
86 81
87 // By setting image state to UNBOUND instead of COPIED we ensure that 82 // By setting image state to UNBOUND instead of COPIED we ensure that
88 // CopyTexImage() is called each time the surface texture is used for drawing. 83 // CopyTexImage() is called each time the surface texture is used for drawing.
89 // It would be nice if we could do this via asking for the currently bound 84 // It would be nice if we could do this via asking for the currently bound
90 // Texture, but the active unit never seems to change. 85 // Texture, but the active unit never seems to change.
91 texture_->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this, 86 texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
92 gpu::gles2::Texture::UNBOUND); 87 gpu::gles2::Texture::UNBOUND);
93 88
94 return true; 89 return true;
95 } 90 }
96 91
97 bool AVDACodecImage::CopyTexSubImage(unsigned target, 92 bool AVDACodecImage::CopyTexSubImage(unsigned target,
98 const gfx::Point& offset, 93 const gfx::Point& offset,
99 const gfx::Rect& rect) { 94 const gfx::Rect& rect) {
100 return false; 95 return false;
101 } 96 }
102 97
(...skipping 13 matching lines...) Expand all
116 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); 111 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
117 codec_buffer_index_ = kInvalidCodecBufferIndex; 112 codec_buffer_index_ = kInvalidCodecBufferIndex;
118 } 113 }
119 return true; 114 return true;
120 } 115 }
121 116
122 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, 117 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
123 uint64_t process_tracing_id, 118 uint64_t process_tracing_id,
124 const std::string& dump_name) {} 119 const std::string& dump_name) {}
125 120
126 void AVDACodecImage::UpdateSurfaceTexture() { 121 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) {
127 DCHECK(surface_texture_); 122 DCHECK(surface_texture_);
128 123
129 // Render via the media codec if needed. 124 // Render via the media codec if needed.
130 if (codec_buffer_index_ == kInvalidCodecBufferIndex || !media_codec_) 125 if (!IsCodecBufferOutstanding())
131 return; 126 return;
132 127
133 // The decoder buffer is still pending. 128 // The decoder buffer is still pending.
134 // This must be synchronous, so wait for OnFrameAvailable. 129 // This must be synchronous, so wait for OnFrameAvailable.
135 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); 130 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
136 { 131 {
137 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame"); 132 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame");
138 shared_state_->WaitForFrameAvailable(); 133 shared_state_->WaitForFrameAvailable();
139 } 134 }
140 135
141 // Don't bother to check if we're rendered again. 136 // Don't bother to check if we're rendered again.
142 codec_buffer_index_ = kInvalidCodecBufferIndex; 137 codec_buffer_index_ = kInvalidCodecBufferIndex;
143 138
144 // Swap the rendered image to the front. 139 // Swap the rendered image to the front.
145 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current; 140 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current = MakeCurrentIfNeeded();
146 if (!shared_state_->context()->IsCurrent(NULL)) { 141
147 scoped_make_current.reset(new ui::ScopedMakeCurrent( 142 // If we changed contexts, then we always want to restore it, since the caller
148 shared_state_->context(), shared_state_->surface())); 143 // doesn't know that we're switching contexts.
149 } 144 if (scoped_make_current)
145 mode = kDoRestoreBindings;
146
147 // Save the current binding if requested.
148 GLint bound_service_id = 0;
149 if (mode == kDoRestoreBindings)
150 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
151
150 surface_texture_->UpdateTexImage(); 152 surface_texture_->UpdateTexImage();
153 if (mode == kDoRestoreBindings)
154 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
151 155
152 // Helpfully, this is already column major. 156 // Helpfully, this is already column major.
153 surface_texture_->GetTransformMatrix(gl_matrix_); 157 surface_texture_->GetTransformMatrix(gl_matrix_);
154 } 158 }
155 159
156 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) { 160 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) {
157 codec_buffer_index_ = buffer_index; 161 codec_buffer_index_ = buffer_index;
158 } 162 }
159 163
160 int AVDACodecImage::GetMediaCodecBufferIndex() const { 164 int AVDACodecImage::GetMediaCodecBufferIndex() const {
161 return codec_buffer_index_; 165 return codec_buffer_index_;
162 } 166 }
163 167
164 void AVDACodecImage::SetSize(const gfx::Size& size) { 168 void AVDACodecImage::SetSize(const gfx::Size& size) {
165 size_ = size; 169 size_ = size;
166 } 170 }
167 171
168 void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) { 172 void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) {
169 media_codec_ = codec; 173 media_codec_ = codec;
170 } 174 }
171 175
172 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) { 176 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) {
173 texture_ = texture; 177 texture_ = texture;
174 } 178 }
175 179
176 void AVDACodecImage::AttachSurfaceTextureToContext() { 180 void AVDACodecImage::AttachSurfaceTextureToContext() {
177 DCHECK(surface_texture_); 181 DCHECK(surface_texture_);
178 182
183 // We assume that the currently bound texture is the intended one.
184
179 // Attach the surface texture to the first context we're bound on, so that 185 // Attach the surface texture to the first context we're bound on, so that
180 // no context switch is needed later. 186 // no context switch is needed later.
181 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 187 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
182 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 188 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
183 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 189 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
184 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 190 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
185 191
186 // The surface texture is already detached, so just attach it. 192 // The surface texture is already detached, so just attach it.
187 // We could do this earlier, but SurfaceTexture has context affinity, and we 193 // We could do this earlier, but SurfaceTexture has context affinity, and we
188 // don't want to require a context switch. 194 // don't want to require a context switch.
189 surface_texture_->AttachToGLContext(); 195 surface_texture_->AttachToGLContext();
190 shared_state_->did_attach_surface_texture(); 196 shared_state_->DidAttachSurfaceTexture();
191 } 197 }
192 198
193 void AVDACodecImage::InstallTextureMatrix() { 199 scoped_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() {
194 DCHECK(surface_texture_); 200 DCHECK(shared_state_->context());
195 201 scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
196 // glUseProgram() has been run already -- just modify the uniform. 202 if (!shared_state_->context()->IsCurrent(NULL)) {
197 // Updating this via VideoFrameProvider::Client::DidUpdateMatrix() would 203 scoped_make_current.reset(new ui::ScopedMakeCurrent(
198 // be a better solution, except that we'd definitely miss a frame at this 204 shared_state_->context(), shared_state_->surface()));
199 // point in drawing.
200 // Our current method assumes that we'll end up being a stream resource,
201 // and that the program has a texMatrix uniform that does what we want.
202 if (need_shader_info_) {
203 GLint program_id = -1;
204 glGetIntegerv(GL_CURRENT_PROGRAM, &program_id);
205
206 if (program_id >= 0) {
207 // This is memorized from cc/output/shader.cc .
208 const char* uniformName = "texMatrix";
209
210 // Within unittests this value may be -1.
211 texmatrix_uniform_location_ =
212 glGetUniformLocation(program_id, uniformName);
213 }
214
215 // Only try once.
216 need_shader_info_ = false;
217 } 205 }
218 206
219 if (texmatrix_uniform_location_ >= 0) { 207 return scoped_make_current;
220 glUniformMatrix4fv(texmatrix_uniform_location_, 1, false, gl_matrix_); 208 }
209
210 void AVDACodecImage::GetTextureMatrix(float matrix[16]) {
211 if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) {
212 // Our current matrix may be stale. Update it if possible.
213 if (!shared_state_->surface_texture_is_attached()) {
214 // Don't attach the surface texture permanently. Perhaps we should
215 // just attach the surface texture in avda and be done with it.
216 GLuint service_id = 0;
217 glGenTextures(1, &service_id);
218 GLint bound_service_id = 0;
219 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
220 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
221 AttachSurfaceTextureToContext();
222 UpdateSurfaceTexture(kDontRestoreBindings);
223 // Detach the surface texture, which deletes the generated texture.
224 surface_texture_->DetachFromGLContext();
225 shared_state_->DidDetachSurfaceTexture();
226 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
227 } else {
228 // Surface texture is already attached, so just update it.
229 UpdateSurfaceTexture(kDoRestoreBindings);
230 }
221 } 231 }
232
233 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_));
234 }
235
236 bool AVDACodecImage::IsCodecBufferOutstanding() const {
237 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_;
222 } 238 }
223 239
224 } // namespace content 240 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/avda_codec_image.h ('k') | content/common/gpu/media/avda_shared_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698