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