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_codec_image.h" | 5 #include "media/gpu/avda_codec_image.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 | 10 |
11 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 11 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
12 #include "gpu/command_buffer/service/texture_manager.h" | 12 #include "gpu/command_buffer/service/texture_manager.h" |
13 #include "media/base/android/sdk_media_codec_bridge.h" | 13 #include "media/base/android/sdk_media_codec_bridge.h" |
14 #include "media/gpu/avda_shared_state.h" | 14 #include "media/gpu/avda_shared_state.h" |
15 #include "ui/gl/android/surface_texture.h" | 15 #include "ui/gl/android/surface_texture.h" |
16 #include "ui/gl/gl_context.h" | 16 #include "ui/gl/gl_context.h" |
17 #include "ui/gl/scoped_make_current.h" | 17 #include "ui/gl/scoped_make_current.h" |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 | 20 |
21 AVDACodecImage::AVDACodecImage( | 21 AVDACodecImage::AVDACodecImage( |
22 int picture_buffer_id, | 22 int picture_buffer_id, |
23 const scoped_refptr<AVDASharedState>& shared_state, | 23 const scoped_refptr<AVDASharedState>& shared_state, |
24 VideoCodecBridge* codec, | 24 VideoCodecBridge* codec, |
25 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) | 25 const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) |
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 has_surface_texture_(!!shared_state_->surface_texture_service_id()), | |
31 texture_(0), | 30 texture_(0), |
32 picture_buffer_id_(picture_buffer_id) { | 31 picture_buffer_id_(picture_buffer_id) { |
33 shared_state_->SetImageForPicture(picture_buffer_id_, this); | 32 shared_state_->SetImageForPicture(picture_buffer_id_, this); |
34 } | 33 } |
35 | 34 |
36 AVDACodecImage::~AVDACodecImage() { | 35 AVDACodecImage::~AVDACodecImage() { |
37 shared_state_->SetImageForPicture(picture_buffer_id_, nullptr); | 36 shared_state_->SetImageForPicture(picture_buffer_id_, nullptr); |
38 } | 37 } |
39 | 38 |
40 void AVDACodecImage::Destroy(bool have_context) {} | 39 void AVDACodecImage::Destroy(bool have_context) {} |
41 | 40 |
42 gfx::Size AVDACodecImage::GetSize() { | 41 gfx::Size AVDACodecImage::GetSize() { |
43 return size_; | 42 return size_; |
44 } | 43 } |
45 | 44 |
46 unsigned AVDACodecImage::GetInternalFormat() { | 45 unsigned AVDACodecImage::GetInternalFormat() { |
47 return GL_RGBA; | 46 return GL_RGBA; |
48 } | 47 } |
49 | 48 |
50 bool AVDACodecImage::BindTexImage(unsigned target) { | 49 bool AVDACodecImage::BindTexImage(unsigned target) { |
51 return false; | 50 return false; |
52 } | 51 } |
53 | 52 |
54 void AVDACodecImage::ReleaseTexImage(unsigned target) {} | 53 void AVDACodecImage::ReleaseTexImage(unsigned target) {} |
55 | 54 |
56 bool AVDACodecImage::CopyTexImage(unsigned target) { | 55 bool AVDACodecImage::CopyTexImage(unsigned target) { |
57 if (!has_surface_texture_) | 56 if (!shared_state_->surface_texture_service_id()) |
58 return false; | 57 return false; |
59 | 58 |
60 if (target != GL_TEXTURE_EXTERNAL_OES) | 59 if (target != GL_TEXTURE_EXTERNAL_OES) |
61 return false; | 60 return false; |
62 | 61 |
63 GLint bound_service_id = 0; | 62 GLint bound_service_id = 0; |
64 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); | 63 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); |
65 // We insist that the currently bound texture is the right one. | 64 // We insist that the currently bound texture is the right one. |
66 if (bound_service_id != | 65 if (bound_service_id != |
67 static_cast<GLint>(shared_state_->surface_texture_service_id())) { | 66 static_cast<GLint>(shared_state_->surface_texture_service_id())) { |
(...skipping 21 matching lines...) Expand all Loading... |
89 const gfx::Rect& rect) { | 88 const gfx::Rect& rect) { |
90 return false; | 89 return false; |
91 } | 90 } |
92 | 91 |
93 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, | 92 bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
94 int z_order, | 93 int z_order, |
95 gfx::OverlayTransform transform, | 94 gfx::OverlayTransform transform, |
96 const gfx::Rect& bounds_rect, | 95 const gfx::Rect& bounds_rect, |
97 const gfx::RectF& crop_rect) { | 96 const gfx::RectF& crop_rect) { |
98 // This should only be called when we're rendering to a SurfaceView. | 97 // This should only be called when we're rendering to a SurfaceView. |
99 if (has_surface_texture_) { | 98 if (shared_state_->surface_texture_service_id()) { |
100 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " | 99 DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " |
101 "SurfaceTexture backed."; | 100 "SurfaceTexture backed."; |
102 return false; | 101 return false; |
103 } | 102 } |
104 | 103 |
105 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); | 104 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); |
106 return true; | 105 return true; |
107 } | 106 } |
108 | 107 |
109 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, | 108 void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
110 uint64_t process_tracing_id, | 109 uint64_t process_tracing_id, |
111 const std::string& dump_name) {} | 110 const std::string& dump_name) {} |
112 | 111 |
113 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { | 112 void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { |
114 DCHECK(has_surface_texture_); | 113 DCHECK(shared_state_->surface_texture_service_id()); |
115 DCHECK_EQ(codec_buffer_index_, kUpdateOnly); | 114 DCHECK_EQ(codec_buffer_index_, kUpdateOnly); |
116 codec_buffer_index_ = kRendered; | 115 codec_buffer_index_ = kRendered; |
117 | 116 |
118 // Swap the rendered image to the front. | 117 // Swap the rendered image to the front. |
119 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = | 118 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = |
120 MakeCurrentIfNeeded(); | 119 MakeCurrentIfNeeded(); |
121 | 120 |
122 // If we changed contexts, then we always want to restore it, since the caller | 121 // If we changed contexts, then we always want to restore it, since the caller |
123 // doesn't know that we're switching contexts. | 122 // doesn't know that we're switching contexts. |
124 if (scoped_make_current) | 123 if (scoped_make_current) |
(...skipping 20 matching lines...) Expand all Loading... |
145 | 144 |
146 void AVDACodecImage::UpdateSurfaceInternal( | 145 void AVDACodecImage::UpdateSurfaceInternal( |
147 UpdateMode update_mode, | 146 UpdateMode update_mode, |
148 RestoreBindingsMode attached_bindings_mode) { | 147 RestoreBindingsMode attached_bindings_mode) { |
149 if (!IsCodecBufferOutstanding()) | 148 if (!IsCodecBufferOutstanding()) |
150 return; | 149 return; |
151 | 150 |
152 ReleaseOutputBuffer(update_mode); | 151 ReleaseOutputBuffer(update_mode); |
153 | 152 |
154 // SurfaceViews are updated implicitly, so no further steps are necessary. | 153 // SurfaceViews are updated implicitly, so no further steps are necessary. |
155 if (!has_surface_texture_) { | 154 if (!shared_state_->surface_texture_service_id()) { |
156 DCHECK(update_mode != UpdateMode::RENDER_TO_BACK_BUFFER); | 155 DCHECK(update_mode != UpdateMode::RENDER_TO_BACK_BUFFER); |
157 return; | 156 return; |
158 } | 157 } |
159 | 158 |
160 // If front buffer rendering hasn't been requested, exit early. | 159 // If front buffer rendering hasn't been requested, exit early. |
161 if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER) | 160 if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER) |
162 return; | 161 return; |
163 | 162 |
164 UpdateSurfaceTexture(attached_bindings_mode); | 163 UpdateSurfaceTexture(attached_bindings_mode); |
165 } | 164 } |
166 | 165 |
167 void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) { | 166 void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) { |
168 DCHECK(IsCodecBufferOutstanding()); | 167 DCHECK(IsCodecBufferOutstanding()); |
169 | 168 |
170 // In case of discard, simply discard and clear our codec buffer index. | 169 // In case of discard, simply discard and clear our codec buffer index. |
171 if (update_mode == UpdateMode::DISCARD_CODEC_BUFFER) { | 170 if (update_mode == UpdateMode::DISCARD_CODEC_BUFFER) { |
172 if (codec_buffer_index_ != kUpdateOnly) | 171 if (codec_buffer_index_ != kUpdateOnly) |
173 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false); | 172 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, false); |
174 | 173 |
175 // Note: No need to wait for the frame to be available in the kUpdateOnly | 174 // Note: No need to wait for the frame to be available in the kUpdateOnly |
176 // case since it will be or has been waited on by another release call. | 175 // case since it will be or has been waited on by another release call. |
177 codec_buffer_index_ = kInvalidCodecBufferIndex; | 176 codec_buffer_index_ = kInvalidCodecBufferIndex; |
178 return; | 177 return; |
179 } | 178 } |
180 | 179 |
181 DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER || | 180 DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER || |
182 update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); | 181 update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); |
183 | 182 |
184 if (!has_surface_texture_) { | 183 if (!shared_state_->surface_texture_service_id()) { |
185 DCHECK(update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); | 184 DCHECK(update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); |
186 DCHECK_GE(codec_buffer_index_, 0); | 185 DCHECK_GE(codec_buffer_index_, 0); |
187 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); | 186 media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); |
188 codec_buffer_index_ = kRendered; | 187 codec_buffer_index_ = kRendered; |
189 return; | 188 return; |
190 } | 189 } |
191 | 190 |
192 // If we've already released to the back buffer, there's nothing left to do, | 191 // If we've already released to the back buffer, there's nothing left to do, |
193 // but wait for the previously released buffer if necessary. | 192 // but wait for the previously released buffer if necessary. |
194 if (codec_buffer_index_ != kUpdateOnly) { | 193 if (codec_buffer_index_ != kUpdateOnly) { |
195 DCHECK(has_surface_texture_); | 194 DCHECK(shared_state_->surface_texture_service_id()); |
196 DCHECK_GE(codec_buffer_index_, 0); | 195 DCHECK_GE(codec_buffer_index_, 0); |
197 shared_state_->RenderCodecBufferToSurfaceTexture(media_codec_, | 196 shared_state_->RenderCodecBufferToSurfaceTexture(media_codec_, |
198 codec_buffer_index_); | 197 codec_buffer_index_); |
199 codec_buffer_index_ = kUpdateOnly; | 198 codec_buffer_index_ = kUpdateOnly; |
200 } | 199 } |
201 | 200 |
202 // Only wait for the SurfaceTexture update if we're rendering to the front. | 201 // Only wait for the SurfaceTexture update if we're rendering to the front. |
203 if (update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER) | 202 if (update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER) |
204 shared_state_->WaitForFrameAvailable(); | 203 shared_state_->WaitForFrameAvailable(); |
205 } | 204 } |
206 | 205 |
207 std::unique_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() { | 206 std::unique_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() { |
208 DCHECK(shared_state_->context()); | 207 DCHECK(shared_state_->context()); |
209 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; | 208 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; |
210 // Remember: virtual contexts return true if and only if their shared context | 209 // Remember: virtual contexts return true if and only if their shared context |
211 // is current, regardless of which virtual context it is. | 210 // is current, regardless of which virtual context it is. |
212 if (!shared_state_->context()->IsCurrent(NULL)) { | 211 if (!shared_state_->context()->IsCurrent(NULL)) { |
213 scoped_make_current.reset(new ui::ScopedMakeCurrent( | 212 scoped_make_current.reset(new ui::ScopedMakeCurrent( |
214 shared_state_->context(), shared_state_->surface())); | 213 shared_state_->context(), shared_state_->surface())); |
215 } | 214 } |
216 | 215 |
217 return scoped_make_current; | 216 return scoped_make_current; |
218 } | 217 } |
219 | 218 |
220 void AVDACodecImage::GetTextureMatrix(float matrix[16]) { | 219 void AVDACodecImage::GetTextureMatrix(float matrix[16]) { |
221 // Our current matrix may be stale. Update it if possible. | 220 // Our current matrix may be stale. Update it if possible. |
222 if (has_surface_texture_) | 221 if (shared_state_->surface_texture_service_id()) |
223 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); | 222 UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); |
224 shared_state_->GetTransformMatrix(matrix); | 223 shared_state_->GetTransformMatrix(matrix); |
225 YInvertMatrix(matrix); | 224 YInvertMatrix(matrix); |
226 } | 225 } |
227 | 226 |
228 bool AVDACodecImage::IsCodecBufferOutstanding() const { | 227 bool AVDACodecImage::IsCodecBufferOutstanding() const { |
229 static_assert(kUpdateOnly < 0 && kUpdateOnly > kRendered && | 228 static_assert(kUpdateOnly < 0 && kUpdateOnly > kRendered && |
230 kRendered > kInvalidCodecBufferIndex, | 229 kRendered > kInvalidCodecBufferIndex, |
231 "Codec buffer index enum values are not ordered correctly."); | 230 "Codec buffer index enum values are not ordered correctly."); |
232 return codec_buffer_index_ > kRendered && media_codec_; | 231 return codec_buffer_index_ > kRendered && media_codec_; |
233 } | 232 } |
234 | 233 |
235 } // namespace media | 234 } // namespace media |
OLD | NEW |