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

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: Fix several more bot-identified build issues Created 4 years, 8 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 "base/metrics/histogram_macros.h"
10 #include "content/common/gpu/media/avda_shared_state.h"
11 #include "gpu/command_buffer/service/context_group.h"
12 #include "gpu/command_buffer/service/context_state.h"
13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
14 #include "gpu/command_buffer/service/texture_manager.h"
15 #include "ui/gl/android/surface_texture.h"
16 #include "ui/gl/gl_context.h"
17 #include "ui/gl/scoped_make_current.h"
18
19 namespace content {
20
21 AVDACodecImage::AVDACodecImage(
22 const scoped_refptr<AVDASharedState>& shared_state,
23 media::VideoCodecBridge* codec,
24 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder,
25 const scoped_refptr<gfx::SurfaceTexture>& surface_texture)
26 : shared_state_(shared_state),
27 codec_buffer_index_(kInvalidCodecBufferIndex),
28 media_codec_(codec),
29 decoder_(decoder),
30 surface_texture_(surface_texture),
31 detach_surface_texture_on_destruction_(false),
32 texture_(0) {
33 // Default to a sane guess of "flip Y", just in case we can't get
34 // the matrix on the first call.
35 memset(gl_matrix_, 0, sizeof(gl_matrix_));
36 gl_matrix_[0] = gl_matrix_[10] = gl_matrix_[15] = 1.0f;
37 gl_matrix_[5] = -1.0f;
38 }
39
40 AVDACodecImage::~AVDACodecImage() {}
41
42 void AVDACodecImage::Destroy(bool have_context) {}
43
44 gfx::Size AVDACodecImage::GetSize() {
45 return size_;
46 }
47
48 unsigned AVDACodecImage::GetInternalFormat() {
49 return GL_RGBA;
50 }
51
52 bool AVDACodecImage::BindTexImage(unsigned target) {
53 return false;
54 }
55
56 void AVDACodecImage::ReleaseTexImage(unsigned target) {}
57
58 bool AVDACodecImage::CopyTexImage(unsigned target) {
59 if (!surface_texture_)
60 return false;
61
62 if (target != GL_TEXTURE_EXTERNAL_OES)
63 return false;
64
65 GLint bound_service_id = 0;
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.
69 if (bound_service_id != shared_state_->surface_texture_service_id())
70 return false;
71
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())
75 AttachSurfaceTextureToContext();
76
77 // Make sure that we have the right image in the front buffer. Note that the
78 // bound_service_id is guaranteed to be equal to the surface texture's client
79 // texture id, so we can skip preserving it if the right context is current.
80 UpdateSurfaceTexture(kDontRestoreBindings);
81
82 // By setting image state to UNBOUND instead of COPIED we ensure that
83 // CopyTexImage() is called each time the surface texture is used for drawing.
84 // It would be nice if we could do this via asking for the currently bound
85 // Texture, but the active unit never seems to change.
86 texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
87 gpu::gles2::Texture::UNBOUND);
88
89 return true;
90 }
91
92 bool AVDACodecImage::CopyTexSubImage(unsigned target,
93 const gfx::Point& offset,
94 const gfx::Rect& rect) {
95 return false;
96 }
97
98 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
99 int z_order,
100 gfx::OverlayTransform transform,
101 const gfx::Rect& bounds_rect,
102 const gfx::RectF& crop_rect) {
103 // This should only be called when we're rendering to a SurfaceView.
104 if (surface_texture_) {
105 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is "
106 "SurfaceTexture backed.";
107 return false;
108 }
109
110 if (codec_buffer_index_ != kInvalidCodecBufferIndex) {
111 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
112 codec_buffer_index_ = kInvalidCodecBufferIndex;
113 }
114 return true;
115 }
116
117 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
118 uint64_t process_tracing_id,
119 const std::string& dump_name) {}
120
121 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) {
122 DCHECK(surface_texture_);
123
124 // Render via the media codec if needed.
125 if (!IsCodecBufferOutstanding())
126 return;
127
128 // The decoder buffer is still pending.
129 // This must be synchronous, so wait for OnFrameAvailable.
130 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
131 {
132 SCOPED_UMA_HISTOGRAM_TIMER("Media.AvdaCodecImage.WaitTimeForFrame");
133 shared_state_->WaitForFrameAvailable();
134 }
135
136 // Don't bother to check if we're rendered again.
137 codec_buffer_index_ = kInvalidCodecBufferIndex;
138
139 // Swap the rendered image to the front.
140 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current =
141 MakeCurrentIfNeeded();
142
143 // If we changed contexts, then we always want to restore it, since the caller
144 // doesn't know that we're switching contexts.
145 if (scoped_make_current)
146 mode = kDoRestoreBindings;
147
148 // Save the current binding if requested.
149 GLint bound_service_id = 0;
150 if (mode == kDoRestoreBindings)
151 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
152
153 surface_texture_->UpdateTexImage();
154 if (mode == kDoRestoreBindings)
155 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
156
157 // Helpfully, this is already column major.
158 surface_texture_->GetTransformMatrix(gl_matrix_);
159 }
160
161 void AVDACodecImage::SetMediaCodecBufferIndex(int buffer_index) {
162 codec_buffer_index_ = buffer_index;
163 }
164
165 int AVDACodecImage::GetMediaCodecBufferIndex() const {
166 return codec_buffer_index_;
167 }
168
169 void AVDACodecImage::SetSize(const gfx::Size& size) {
170 size_ = size;
171 }
172
173 void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) {
174 media_codec_ = codec;
175 }
176
177 void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) {
178 texture_ = texture;
179 }
180
181 void AVDACodecImage::AttachSurfaceTextureToContext() {
182 DCHECK(surface_texture_);
183
184 // We assume that the currently bound texture is the intended one.
185
186 // Attach the surface texture to the first context we're bound on, so that
187 // no context switch is needed later.
188 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
189 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
190 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
192
193 // The surface texture is already detached, so just attach it.
194 // We could do this earlier, but SurfaceTexture has context affinity, and we
195 // don't want to require a context switch.
196 surface_texture_->AttachToGLContext();
197 shared_state_->DidAttachSurfaceTexture();
198 }
199
200 std::unique_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() {
201 DCHECK(shared_state_->context());
202 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current;
203 if (!shared_state_->context()->IsCurrent(NULL)) {
204 scoped_make_current.reset(new ui::ScopedMakeCurrent(
205 shared_state_->context(), shared_state_->surface()));
206 }
207
208 return scoped_make_current;
209 }
210
211 void AVDACodecImage::GetTextureMatrix(float matrix[16]) {
212 if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) {
213 // Our current matrix may be stale. Update it if possible.
214 if (!shared_state_->surface_texture_is_attached()) {
215 // Don't attach the surface texture permanently. Perhaps we should
216 // just attach the surface texture in avda and be done with it.
217 GLuint service_id = 0;
218 glGenTextures(1, &service_id);
219 GLint bound_service_id = 0;
220 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
221 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
222 AttachSurfaceTextureToContext();
223 UpdateSurfaceTexture(kDontRestoreBindings);
224 // Detach the surface texture, which deletes the generated texture.
225 surface_texture_->DetachFromGLContext();
226 shared_state_->DidDetachSurfaceTexture();
227 glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
228 } else {
229 // Surface texture is already attached, so just update it.
230 UpdateSurfaceTexture(kDoRestoreBindings);
231 }
232 }
233
234 memcpy(matrix, gl_matrix_, sizeof(gl_matrix_));
235 }
236
237 bool AVDACodecImage::IsCodecBufferOutstanding() const {
238 return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_;
239 }
240
241 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698