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