| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/fake_video_decode_accelerator.h" | 5 #include "media/gpu/fake_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 15 #include "media/base/bitstream_buffer.h" | 15 #include "media/base/bitstream_buffer.h" |
| 16 #include "media/base/limits.h" | 16 #include "media/base/limits.h" |
| 17 #include "ui/gl/gl_context.h" | 17 #include "ui/gl/gl_context.h" |
| 18 #include "ui/gl/gl_implementation.h" | 18 #include "ui/gl/gl_implementation.h" |
| 19 #include "ui/gl/gl_surface.h" | 19 #include "ui/gl/gl_surface.h" |
| 20 #include "ui/gl/gl_surface_egl.h" | 20 #include "ui/gl/gl_surface_egl.h" |
| 21 #include "ui/gl/gl_surface_glx.h" | 21 #include "ui/gl/gl_surface_glx.h" |
| 22 | 22 |
| 23 namespace content { | 23 namespace media { |
| 24 | 24 |
| 25 static const uint32_t kDefaultTextureTarget = GL_TEXTURE_2D; | 25 static const uint32_t kDefaultTextureTarget = GL_TEXTURE_2D; |
| 26 // Must be at least 2 since the rendering helper will switch between textures | 26 // Must be at least 2 since the rendering helper will switch between textures |
| 27 // and if there is only one, it will wait for the next one that will never come. | 27 // and if there is only one, it will wait for the next one that will never come. |
| 28 // Must also be an even number as otherwise there won't be the same amount of | 28 // Must also be an even number as otherwise there won't be the same amount of |
| 29 // white and black frames. | 29 // white and black frames. |
| 30 static const unsigned int kNumBuffers = media::limits::kMaxVideoFrames + | 30 static const unsigned int kNumBuffers = |
| 31 (media::limits::kMaxVideoFrames & 1u); | 31 media::limits::kMaxVideoFrames + (media::limits::kMaxVideoFrames & 1u); |
| 32 | 32 |
| 33 FakeVideoDecodeAccelerator::FakeVideoDecodeAccelerator( | 33 FakeVideoDecodeAccelerator::FakeVideoDecodeAccelerator( |
| 34 const gfx::Size& size, | 34 const gfx::Size& size, |
| 35 const MakeGLContextCurrentCallback& make_context_current_cb) | 35 const MakeGLContextCurrentCallback& make_context_current_cb) |
| 36 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 36 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 37 client_(NULL), | 37 client_(NULL), |
| 38 make_context_current_cb_(make_context_current_cb), | 38 make_context_current_cb_(make_context_current_cb), |
| 39 frame_buffer_size_(size), | 39 frame_buffer_size_(size), |
| 40 flushing_(false), | 40 flushing_(false), |
| 41 weak_this_factory_(this) {} | 41 weak_this_factory_(this) {} |
| 42 | 42 |
| 43 FakeVideoDecodeAccelerator::~FakeVideoDecodeAccelerator() { | 43 FakeVideoDecodeAccelerator::~FakeVideoDecodeAccelerator() {} |
| 44 } | |
| 45 | 44 |
| 46 bool FakeVideoDecodeAccelerator::Initialize(const Config& config, | 45 bool FakeVideoDecodeAccelerator::Initialize(const Config& config, |
| 47 Client* client) { | 46 Client* client) { |
| 48 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 47 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 49 if (config.profile == media::VIDEO_CODEC_PROFILE_UNKNOWN) { | 48 if (config.profile == media::VIDEO_CODEC_PROFILE_UNKNOWN) { |
| 50 LOG(ERROR) << "unknown codec profile"; | 49 LOG(ERROR) << "unknown codec profile"; |
| 51 return false; | 50 return false; |
| 52 } | 51 } |
| 53 if (config.is_encrypted) { | 52 if (config.is_encrypted) { |
| 54 NOTREACHED() << "encrypted streams are not supported"; | 53 NOTREACHED() << "encrypted streams are not supported"; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 79 queued_bitstream_ids_.push(bitstream_buffer_id); | 78 queued_bitstream_ids_.push(bitstream_buffer_id); |
| 80 child_task_runner_->PostTask( | 79 child_task_runner_->PostTask( |
| 81 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady, | 80 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady, |
| 82 weak_this_factory_.GetWeakPtr())); | 81 weak_this_factory_.GetWeakPtr())); |
| 83 } | 82 } |
| 84 | 83 |
| 85 // Similar to UseOutputBitstreamBuffer for the encode accelerator. | 84 // Similar to UseOutputBitstreamBuffer for the encode accelerator. |
| 86 void FakeVideoDecodeAccelerator::AssignPictureBuffers( | 85 void FakeVideoDecodeAccelerator::AssignPictureBuffers( |
| 87 const std::vector<media::PictureBuffer>& buffers) { | 86 const std::vector<media::PictureBuffer>& buffers) { |
| 88 DCHECK(buffers.size() == kNumBuffers); | 87 DCHECK(buffers.size() == kNumBuffers); |
| 89 DCHECK(!(buffers.size()%2)); | 88 DCHECK(!(buffers.size() % 2)); |
| 90 | 89 |
| 91 // Save buffers and mark all buffers as ready for use. | 90 // Save buffers and mark all buffers as ready for use. |
| 92 std::unique_ptr<uint8_t[]> white_data( | 91 std::unique_ptr<uint8_t[]> white_data( |
| 93 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() * | 92 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() * |
| 94 4]); | 93 4]); |
| 95 memset(white_data.get(), | 94 memset(white_data.get(), UINT8_MAX, |
| 96 UINT8_MAX, | |
| 97 frame_buffer_size_.width() * frame_buffer_size_.height() * 4); | 95 frame_buffer_size_.width() * frame_buffer_size_.height() * 4); |
| 98 std::unique_ptr<uint8_t[]> black_data( | 96 std::unique_ptr<uint8_t[]> black_data( |
| 99 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() * | 97 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() * |
| 100 4]); | 98 4]); |
| 101 memset(black_data.get(), | 99 memset(black_data.get(), 0, |
| 102 0, | |
| 103 frame_buffer_size_.width() * frame_buffer_size_.height() * 4); | 100 frame_buffer_size_.width() * frame_buffer_size_.height() * 4); |
| 104 if (!make_context_current_cb_.Run()) { | 101 if (!make_context_current_cb_.Run()) { |
| 105 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 102 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
| 106 return; | 103 return; |
| 107 } | 104 } |
| 108 for (size_t index = 0; index < buffers.size(); ++index) { | 105 for (size_t index = 0; index < buffers.size(); ++index) { |
| 109 DCHECK_LE(1u, buffers[index].texture_ids().size()); | 106 DCHECK_LE(1u, buffers[index].texture_ids().size()); |
| 110 glBindTexture(GL_TEXTURE_2D, buffers[index].texture_ids()[0]); | 107 glBindTexture(GL_TEXTURE_2D, buffers[index].texture_ids()[0]); |
| 111 // Every other frame white and the rest black. | 108 // Every other frame white and the rest black. |
| 112 uint8_t* data = index % 2 ? white_data.get() : black_data.get(); | 109 uint8_t* data = index % 2 ? white_data.get() : black_data.get(); |
| 113 glTexImage2D(GL_TEXTURE_2D, | 110 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame_buffer_size_.width(), |
| 114 0, | 111 frame_buffer_size_.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 115 GL_RGBA, | |
| 116 frame_buffer_size_.width(), | |
| 117 frame_buffer_size_.height(), | |
| 118 0, | |
| 119 GL_RGBA, | |
| 120 GL_UNSIGNED_BYTE, | |
| 121 data); | 112 data); |
| 122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 126 glBindTexture(GL_TEXTURE_2D, 0); | 117 glBindTexture(GL_TEXTURE_2D, 0); |
| 127 free_output_buffers_.push(buffers[index].id()); | 118 free_output_buffers_.push(buffers[index].id()); |
| 128 } | 119 } |
| 129 child_task_runner_->PostTask( | 120 child_task_runner_->PostTask( |
| 130 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady, | 121 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 if (flushing_ && queued_bitstream_ids_.empty()) { | 162 if (flushing_ && queued_bitstream_ids_.empty()) { |
| 172 flushing_ = false; | 163 flushing_ = false; |
| 173 client_->NotifyFlushDone(); | 164 client_->NotifyFlushDone(); |
| 174 } | 165 } |
| 175 while (!free_output_buffers_.empty() && !queued_bitstream_ids_.empty()) { | 166 while (!free_output_buffers_.empty() && !queued_bitstream_ids_.empty()) { |
| 176 int bitstream_id = queued_bitstream_ids_.front(); | 167 int bitstream_id = queued_bitstream_ids_.front(); |
| 177 queued_bitstream_ids_.pop(); | 168 queued_bitstream_ids_.pop(); |
| 178 int buffer_id = free_output_buffers_.front(); | 169 int buffer_id = free_output_buffers_.front(); |
| 179 free_output_buffers_.pop(); | 170 free_output_buffers_.pop(); |
| 180 | 171 |
| 181 const media::Picture picture = | 172 const media::Picture picture = media::Picture( |
| 182 media::Picture(buffer_id, | 173 buffer_id, bitstream_id, gfx::Rect(frame_buffer_size_), false); |
| 183 bitstream_id, | |
| 184 gfx::Rect(frame_buffer_size_), | |
| 185 false); | |
| 186 client_->PictureReady(picture); | 174 client_->PictureReady(picture); |
| 187 // Bitstream no longer needed. | 175 // Bitstream no longer needed. |
| 188 client_->NotifyEndOfBitstreamBuffer(bitstream_id); | 176 client_->NotifyEndOfBitstreamBuffer(bitstream_id); |
| 189 if (flushing_ && queued_bitstream_ids_.empty()) { | 177 if (flushing_ && queued_bitstream_ids_.empty()) { |
| 190 flushing_ = false; | 178 flushing_ = false; |
| 191 client_->NotifyFlushDone(); | 179 client_->NotifyFlushDone(); |
| 192 } | 180 } |
| 193 } | 181 } |
| 194 } | 182 } |
| 195 | 183 |
| 196 } // namespace content | 184 } // namespace media |
| OLD | NEW |