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/video/gpu_memory_buffer_video_frame_pool.h" | 5 #include "media/video/gpu_memory_buffer_video_frame_pool.h" |
6 | 6 |
7 #include <GLES2/gl2.h> | 7 #include <GLES2/gl2.h> |
8 #include <GLES2/gl2ext.h> | 8 #include <GLES2/gl2ext.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <list> | 11 #include <list> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "base/barrier_closure.h" | 14 #include "base/barrier_closure.h" |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/containers/stack_container.h" | 16 #include "base/containers/stack_container.h" |
17 #include "base/location.h" | 17 #include "base/location.h" |
18 #include "base/memory/linked_ptr.h" | 18 #include "base/memory/linked_ptr.h" |
19 #include "base/trace_event/trace_event.h" | 19 #include "base/trace_event/trace_event.h" |
20 #include "gpu/command_buffer/client/gles2_interface.h" | 20 #include "gpu/command_buffer/client/gles2_interface.h" |
21 #include "media/renderers/gpu_video_accelerator_factories.h" | 21 #include "media/renderers/gpu_video_accelerator_factories.h" |
22 #include "third_party/libyuv/include/libyuv.h" | |
22 | 23 |
23 namespace media { | 24 namespace media { |
24 | 25 |
25 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames. | 26 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames. |
26 class GpuMemoryBufferVideoFramePool::PoolImpl | 27 class GpuMemoryBufferVideoFramePool::PoolImpl |
27 : public base::RefCountedThreadSafe< | 28 : public base::RefCountedThreadSafe< |
28 GpuMemoryBufferVideoFramePool::PoolImpl> { | 29 GpuMemoryBufferVideoFramePool::PoolImpl> { |
29 public: | 30 public: |
30 // |media_task_runner| is the media task runner associated with the | 31 // |media_task_runner| is the media task runner associated with the |
31 // GL context provided by |gpu_factories| | 32 // GL context provided by |gpu_factories| |
32 // |worker_task_runner| is a task runner used to asynchronously copy | 33 // |worker_task_runner| is a task runner used to asynchronously copy |
33 // video frame's planes. | 34 // video frame's planes. |
34 // |gpu_factories| is an interface to GPU related operation and can be | 35 // |gpu_factories| is an interface to GPU related operation and can be |
35 // null if a GL context is not available. | 36 // null if a GL context is not available. |
36 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 37 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
37 const scoped_refptr<base::TaskRunner>& worker_task_runner, | 38 const scoped_refptr<base::TaskRunner>& worker_task_runner, |
38 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) | 39 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) |
39 : media_task_runner_(media_task_runner), | 40 : media_task_runner_(media_task_runner), |
40 worker_task_runner_(worker_task_runner), | 41 worker_task_runner_(worker_task_runner), |
41 gpu_factories_(gpu_factories), | 42 gpu_factories_(gpu_factories), |
42 texture_target_(gpu_factories ? gpu_factories->ImageTextureTarget() | 43 texture_target_(gpu_factories ? gpu_factories->ImageTextureTarget() |
43 : GL_TEXTURE_2D) { | 44 : GL_TEXTURE_2D), |
45 format_((gpu_factories ? gpu_factories->VideoFramePixelFormat() | |
46 : PIXEL_FORMAT_I420)) { | |
Andre
2015/08/21 18:18:36
nit: don't need double parenthesis.
Daniele Castagna
2015/08/21 18:49:02
Done.
| |
44 DCHECK(media_task_runner_); | 47 DCHECK(media_task_runner_); |
45 DCHECK(worker_task_runner_); | 48 DCHECK(worker_task_runner_); |
46 } | 49 } |
47 | 50 |
48 // Takes a software VideoFrame and calls |frame_ready_cb| with a VideoFrame | 51 // Takes a software VideoFrame and calls |frame_ready_cb| with a VideoFrame |
49 // backed by native textures if possible. | 52 // backed by native textures if possible. |
50 // The data contained in video_frame is copied into the returned frame | 53 // The data contained in video_frame is copied into the returned frame |
51 // asynchronously posting tasks to |worker_task_runner_|, while | 54 // asynchronously posting tasks to |worker_task_runner_|, while |
52 // |frame_ready_cb| will be called on |media_task_runner_| once all the data | 55 // |frame_ready_cb| will be called on |media_task_runner_| once all the data |
53 // has been copied. | 56 // has been copied. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 // Task runner used to asynchronously copy planes. | 137 // Task runner used to asynchronously copy planes. |
135 scoped_refptr<base::TaskRunner> worker_task_runner_; | 138 scoped_refptr<base::TaskRunner> worker_task_runner_; |
136 | 139 |
137 // Interface to GPU related operations. | 140 // Interface to GPU related operations. |
138 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; | 141 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; |
139 | 142 |
140 // Pool of resources. | 143 // Pool of resources. |
141 std::list<FrameResources*> resources_pool_; | 144 std::list<FrameResources*> resources_pool_; |
142 | 145 |
143 const unsigned texture_target_; | 146 const unsigned texture_target_; |
147 const VideoPixelFormat format_; | |
Andre
2015/08/21 18:18:36
Maybe call this output_format_ or hardware_format_
Daniele Castagna
2015/08/21 18:49:02
Good point. Removed.
| |
148 | |
144 DISALLOW_COPY_AND_ASSIGN(PoolImpl); | 149 DISALLOW_COPY_AND_ASSIGN(PoolImpl); |
145 }; | 150 }; |
146 | 151 |
147 namespace { | 152 namespace { |
148 | 153 |
149 // VideoFrame copies to GpuMemoryBuffers will be split in |kBytesPerCopyTarget| | 154 // VideoFrame copies to GpuMemoryBuffers will be split in copies where the |
150 // bytes copies and run in parallel. | 155 // output |
Andre
2015/08/21 18:18:36
don't wrap before output.
Daniele Castagna
2015/08/21 18:49:02
Done.
| |
156 // size is |kBytesPerCopyTarget| bytes and run in parallel. | |
151 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB | 157 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB |
152 | 158 |
153 void CopyRowsToBuffer(int first_row, | 159 // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat |
154 int rows, | 160 // and plane. |
155 int bytes_per_row, | 161 gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) { |
156 const uint8* source, | 162 switch (format) { |
157 int source_stride, | 163 case PIXEL_FORMAT_I420: |
158 uint8* output, | 164 DCHECK_LE(plane, 2u); |
159 int dest_stride, | 165 return gfx::BufferFormat::R_8; |
160 const base::Closure& done) { | 166 case PIXEL_FORMAT_UYVY: |
161 TRACE_EVENT2("media", "CopyRowsToBuffer", "bytes_per_row", bytes_per_row, | 167 DCHECK_EQ(0u, plane); |
168 return gfx::BufferFormat::UYVY_422; | |
169 default: | |
170 NOTREACHED(); | |
171 return gfx::BufferFormat::BGRA_8888; | |
172 } | |
173 } | |
174 | |
175 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) { | |
176 switch (format) { | |
177 case PIXEL_FORMAT_I420: | |
178 DCHECK_LE(plane, 2u); | |
179 return GL_R8_EXT; | |
180 case PIXEL_FORMAT_UYVY: | |
181 DCHECK_EQ(0u, plane); | |
182 return GL_RGB; | |
183 default: | |
184 NOTREACHED(); | |
185 return 0; | |
186 } | |
187 } | |
188 | |
189 void CopyRowsToI420Buffer(int first_row, | |
190 int rows, | |
191 int bytes_per_row, | |
192 const uint8* source, | |
193 int source_stride, | |
194 uint8* output, | |
195 int dest_stride, | |
196 const base::Closure& done) { | |
197 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, | |
162 "rows", rows); | 198 "rows", rows); |
163 DCHECK_NE(dest_stride, 0); | 199 DCHECK_NE(dest_stride, 0); |
164 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); | 200 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); |
165 DCHECK_LE(bytes_per_row, source_stride); | 201 DCHECK_LE(bytes_per_row, source_stride); |
166 for (int row = first_row; row < first_row + rows; ++row) { | 202 for (int row = first_row; row < first_row + rows; ++row) { |
167 memcpy(output + dest_stride * row, source + source_stride * row, | 203 memcpy(output + dest_stride * row, source + source_stride * row, |
168 bytes_per_row); | 204 bytes_per_row); |
169 } | 205 } |
170 done.Run(); | 206 done.Run(); |
171 } | 207 } |
172 | 208 |
209 void CopyRowsToUYVYBuffer(int first_row, | |
210 int rows, | |
211 int width, | |
212 const scoped_refptr<VideoFrame>& source_frame, | |
213 uint8* output, | |
214 int dest_stride, | |
215 const base::Closure& done) { | |
216 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, | |
217 "rows", rows); | |
218 DCHECK_NE(dest_stride, 0); | |
219 DCHECK_LE(width, std::abs(dest_stride / 2)); | |
220 DCHECK_EQ(0, first_row % 2); | |
221 libyuv::I420ToUYVY( | |
222 source_frame->data(VideoFrame::kYPlane) + | |
223 first_row * source_frame->stride(VideoFrame::kYPlane), | |
224 source_frame->stride(VideoFrame::kYPlane), | |
225 source_frame->data(VideoFrame::kUPlane) + | |
226 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), | |
227 source_frame->stride(VideoFrame::kUPlane), | |
228 source_frame->data(VideoFrame::kVPlane) + | |
229 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), | |
230 source_frame->stride(VideoFrame::kVPlane), | |
231 output + first_row * dest_stride, dest_stride, width, rows); | |
232 done.Run(); | |
233 } | |
234 | |
173 } // unnamed namespace | 235 } // unnamed namespace |
174 | 236 |
175 // Creates a VideoFrame backed by native textures starting from a software | 237 // Creates a VideoFrame backed by native textures starting from a software |
176 // VideoFrame. | 238 // VideoFrame. |
177 // The data contained in |video_frame| is copied into the VideoFrame passed to | 239 // The data contained in |video_frame| is copied into the VideoFrame passed to |
178 // |frame_ready_cb|. | 240 // |frame_ready_cb|. |
179 // This has to be called on the thread where |media_task_runner_| is current. | 241 // This has to be called on the thread where |media_task_runner_| is current. |
180 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( | 242 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( |
181 const scoped_refptr<VideoFrame>& video_frame, | 243 const scoped_refptr<VideoFrame>& video_frame, |
182 const FrameReadyCB& frame_ready_cb) { | 244 const FrameReadyCB& frame_ready_cb) { |
183 DCHECK(media_task_runner_->BelongsToCurrentThread()); | 245 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
184 if (!gpu_factories_ || !gpu_factories_->IsTextureRGSupported()) { | 246 if (!gpu_factories_ || (format_ == PIXEL_FORMAT_I420 && |
247 !gpu_factories_->IsTextureRGSupported())) { | |
185 frame_ready_cb.Run(video_frame); | 248 frame_ready_cb.Run(video_frame); |
186 return; | 249 return; |
187 } | 250 } |
188 switch (video_frame->format()) { | 251 switch (video_frame->format()) { |
189 // Supported cases. | 252 // Supported cases. |
190 case PIXEL_FORMAT_YV12: | 253 case PIXEL_FORMAT_YV12: |
191 case PIXEL_FORMAT_I420: | 254 case PIXEL_FORMAT_I420: |
192 break; | 255 break; |
193 // Unsupported cases. | 256 // Unsupported cases. |
194 case PIXEL_FORMAT_YV12A: | 257 case PIXEL_FORMAT_YV12A: |
195 case PIXEL_FORMAT_YV16: | 258 case PIXEL_FORMAT_YV16: |
196 case PIXEL_FORMAT_YV24: | 259 case PIXEL_FORMAT_YV24: |
197 case PIXEL_FORMAT_NV12: | 260 case PIXEL_FORMAT_NV12: |
198 case PIXEL_FORMAT_ARGB: | 261 case PIXEL_FORMAT_ARGB: |
199 case PIXEL_FORMAT_XRGB: | 262 case PIXEL_FORMAT_XRGB: |
200 case PIXEL_FORMAT_UYVY: | 263 case PIXEL_FORMAT_UYVY: |
201 case PIXEL_FORMAT_UNKNOWN: | 264 case PIXEL_FORMAT_UNKNOWN: |
202 frame_ready_cb.Run(video_frame); | 265 frame_ready_cb.Run(video_frame); |
203 return; | 266 return; |
204 } | 267 } |
205 | 268 |
206 VideoPixelFormat format = video_frame->format(); | |
207 DCHECK(video_frame->visible_rect().origin().IsOrigin()); | 269 DCHECK(video_frame->visible_rect().origin().IsOrigin()); |
208 const gfx::Size size = video_frame->visible_rect().size(); | 270 const gfx::Size size = video_frame->visible_rect().size(); |
209 | 271 |
210 // Acquire resources. Incompatible ones will be dropped from the pool. | 272 // Acquire resources. Incompatible ones will be dropped from the pool. |
211 FrameResources* frame_resources = GetOrCreateFrameResources(size, format); | 273 FrameResources* frame_resources = GetOrCreateFrameResources(size, format_); |
212 if (!frame_resources) { | 274 if (!frame_resources) { |
213 frame_ready_cb.Run(video_frame); | 275 frame_ready_cb.Run(video_frame); |
214 return; | 276 return; |
215 } | 277 } |
216 | 278 |
217 worker_task_runner_->PostTask( | 279 worker_task_runner_->PostTask( |
218 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, | 280 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, |
219 video_frame, frame_resources, frame_ready_cb)); | 281 video_frame, frame_resources, frame_ready_cb)); |
220 } | 282 } |
221 | 283 |
222 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( | 284 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( |
223 const scoped_refptr<VideoFrame>& video_frame, | 285 const scoped_refptr<VideoFrame>& video_frame, |
224 FrameResources* frame_resources, | 286 FrameResources* frame_resources, |
225 const FrameReadyCB& frame_ready_cb) { | 287 const FrameReadyCB& frame_ready_cb) { |
226 const VideoPixelFormat format = video_frame->format(); | 288 const size_t planes = VideoFrame::NumPlanes(frame_resources->format); |
227 const size_t planes = VideoFrame::NumPlanes(format); | |
228 for (size_t i = 0; i < planes; ++i) { | 289 for (size_t i = 0; i < planes; ++i) { |
229 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap(); | 290 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap(); |
230 } | 291 } |
231 | 292 |
232 media_task_runner_->PostTask( | 293 media_task_runner_->PostTask( |
233 FROM_HERE, | 294 FROM_HERE, |
234 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this, | 295 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this, |
235 video_frame, frame_resources, frame_ready_cb)); | 296 video_frame, frame_resources, frame_ready_cb)); |
236 } | 297 } |
237 | 298 |
238 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks | 299 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks |
239 // that will be synchronized by a barrier. | 300 // that will be synchronized by a barrier. |
240 // After the barrier is passed OnCopiesDone will be called. | 301 // After the barrier is passed OnCopiesDone will be called. |
241 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( | 302 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( |
242 const scoped_refptr<VideoFrame>& video_frame, | 303 const scoped_refptr<VideoFrame>& video_frame, |
243 FrameResources* frame_resources, | 304 FrameResources* frame_resources, |
244 const FrameReadyCB& frame_ready_cb) { | 305 const FrameReadyCB& frame_ready_cb) { |
245 const VideoPixelFormat format = video_frame->format(); | 306 // Compute the number of tasks to post and create the barrier. |
246 const size_t planes = VideoFrame::NumPlanes(format); | 307 const VideoPixelFormat dest_format = frame_resources->format; |
308 const size_t dest_planes = VideoFrame::NumPlanes(dest_format); | |
247 gfx::Size size = video_frame->visible_rect().size(); | 309 gfx::Size size = video_frame->visible_rect().size(); |
248 size_t copies = 0; | 310 size_t copies = 0; |
249 for (size_t i = 0; i < planes; ++i) { | 311 for (size_t i = 0; i < dest_planes; ++i) { |
250 int rows = VideoFrame::Rows(i, format, size.height()); | 312 int rows = VideoFrame::Rows(i, dest_format, size.height()); |
251 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width()); | 313 int bytes_per_row = VideoFrame::RowBytes(i, dest_format, size.width()); |
314 // Copy a even number of lines, and at least one. | |
252 int rows_per_copy = | 315 int rows_per_copy = |
253 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1); | 316 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1); |
254 copies += rows / rows_per_copy; | 317 copies += rows / rows_per_copy; |
255 if (rows % rows_per_copy) | 318 if (rows % rows_per_copy) |
256 ++copies; | 319 ++copies; |
257 } | 320 } |
258 | |
259 base::Closure copies_done = | 321 base::Closure copies_done = |
260 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, | 322 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, |
261 frame_ready_cb); | 323 frame_ready_cb); |
262 base::Closure barrier = base::BarrierClosure(copies, copies_done); | 324 base::Closure barrier = base::BarrierClosure(copies, copies_done); |
325 // Post all the async tasks. | |
326 for (size_t i = 0; i < dest_planes; ++i) { | |
327 int rows = VideoFrame::Rows(i, dest_format, size.height()); | |
328 int bytes_per_row = VideoFrame::RowBytes(i, dest_format, size.width()); | |
329 int rows_per_copy = | |
330 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1); | |
263 | 331 |
264 for (size_t i = 0; i < planes; ++i) { | 332 void* data = nullptr; |
Andre
2015/08/21 18:18:36
CHECK_EQ(1, gfx::NumberOfPlanesForBufferFormat(des
Daniele Castagna
2015/08/21 18:49:02
Done.
| |
265 int rows = VideoFrame::Rows(i, format, size.height()); | 333 CHECK(frame_resources->plane_resources[i].gpu_memory_buffer->Map(&data)); |
266 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width()); | 334 uint8* mapped_buffer = static_cast<uint8*>(data); |
267 int rows_per_copy = | |
268 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1); | |
269 | 335 |
270 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | |
271 void* data = nullptr; | |
272 CHECK(plane_resource.gpu_memory_buffer->Map(&data)); | |
273 uint8* mapped_buffer = static_cast<uint8*>(data); | |
274 int dest_stride = 0; | 336 int dest_stride = 0; |
275 plane_resource.gpu_memory_buffer->GetStride(&dest_stride); | 337 frame_resources->plane_resources[i].gpu_memory_buffer->GetStride( |
338 &dest_stride); | |
276 | 339 |
277 for (int row = 0; row < rows; row += rows_per_copy) { | 340 for (int row = 0; row < rows; row += rows_per_copy) { |
278 worker_task_runner_->PostTask( | 341 switch (dest_format) { |
279 FROM_HERE, | 342 case PIXEL_FORMAT_I420: |
280 base::Bind(&CopyRowsToBuffer, row, | 343 worker_task_runner_->PostTask( |
281 std::min(rows_per_copy, rows - row), bytes_per_row, | 344 FROM_HERE, |
282 video_frame->data(i), video_frame->stride(i), | 345 base::Bind(&CopyRowsToI420Buffer, row, |
283 mapped_buffer, dest_stride, barrier)); | 346 std::min(rows_per_copy, rows - row), bytes_per_row, |
347 video_frame->data(i), video_frame->stride(i), | |
348 mapped_buffer, dest_stride, barrier)); | |
349 break; | |
350 case PIXEL_FORMAT_UYVY: | |
351 worker_task_runner_->PostTask( | |
352 FROM_HERE, | |
353 base::Bind(&CopyRowsToUYVYBuffer, row, | |
354 std::min(rows_per_copy, rows - row), size.width(), | |
355 video_frame, mapped_buffer, dest_stride, barrier)); | |
356 break; | |
357 default: | |
358 NOTREACHED(); | |
359 } | |
284 } | 360 } |
285 } | 361 } |
286 } | 362 } |
287 | 363 |
288 void GpuMemoryBufferVideoFramePool::PoolImpl:: | 364 void GpuMemoryBufferVideoFramePool::PoolImpl:: |
289 BindAndCreateMailboxesHardwareFrameResources( | 365 BindAndCreateMailboxesHardwareFrameResources( |
290 const scoped_refptr<VideoFrame>& video_frame, | 366 const scoped_refptr<VideoFrame>& video_frame, |
291 FrameResources* frame_resources, | 367 FrameResources* frame_resources, |
292 const FrameReadyCB& frame_ready_cb) { | 368 const FrameReadyCB& frame_ready_cb) { |
293 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); | 369 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); |
294 if (!gles2) { | 370 if (!gles2) { |
295 frame_ready_cb.Run(video_frame); | 371 frame_ready_cb.Run(video_frame); |
296 return; | 372 return; |
297 } | 373 } |
298 | 374 |
299 const VideoPixelFormat format = video_frame->format(); | 375 const size_t planes = VideoFrame::NumPlanes(frame_resources->format); |
300 const size_t planes = VideoFrame::NumPlanes(format); | |
301 const gfx::Size size = video_frame->visible_rect().size(); | 376 const gfx::Size size = video_frame->visible_rect().size(); |
302 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; | 377 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; |
303 // Set up the planes creating the mailboxes needed to refer to the textures. | 378 // Set up the planes creating the mailboxes needed to refer to the textures. |
304 for (size_t i = 0; i < planes; ++i) { | 379 for (size_t i = 0; i < planes; ++i) { |
305 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | 380 PlaneResource& plane_resource = frame_resources->plane_resources[i]; |
306 // Bind the texture and create or rebind the image. | 381 // Bind the texture and create or rebind the image. |
307 gles2->BindTexture(texture_target_, plane_resource.texture_id); | 382 gles2->BindTexture(texture_target_, plane_resource.texture_id); |
308 | 383 |
309 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { | 384 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { |
310 const size_t width = VideoFrame::Columns(i, format, size.width()); | 385 const size_t width = |
311 const size_t height = VideoFrame::Rows(i, format, size.height()); | 386 VideoFrame::Columns(i, frame_resources->format, size.width()); |
387 const size_t height = | |
388 VideoFrame::Rows(i, frame_resources->format, size.height()); | |
312 plane_resource.image_id = gles2->CreateImageCHROMIUM( | 389 plane_resource.image_id = gles2->CreateImageCHROMIUM( |
313 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, | 390 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, |
314 GL_R8_EXT); | 391 ImageInternalFormat(frame_resources->format, i)); |
315 } else { | 392 } else { |
316 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, | 393 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, |
317 plane_resource.image_id); | 394 plane_resource.image_id); |
318 } | 395 } |
319 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); | 396 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); |
320 mailbox_holders[i] = | 397 mailbox_holders[i] = |
321 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); | 398 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); |
322 } | 399 } |
323 | 400 |
324 // Insert a sync_point, this is needed to make sure that the textures the | 401 // Insert a sync_point, this is needed to make sure that the textures the |
325 // mailboxes refer to will be used only after all the previous commands posted | 402 // mailboxes refer to will be used only after all the previous commands posted |
326 // in the command buffer have been processed. | 403 // in the command buffer have been processed. |
327 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); | 404 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); |
328 for (size_t i = 0; i < planes; ++i) { | 405 for (size_t i = 0; i < planes; ++i) { |
329 mailbox_holders[i].sync_point = sync_point; | 406 mailbox_holders[i].sync_point = sync_point; |
330 } | 407 } |
331 | 408 |
409 scoped_refptr<VideoFrame> frame; | |
332 // Create the VideoFrame backed by native textures. | 410 // Create the VideoFrame backed by native textures. |
333 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures( | 411 switch (frame_resources->format) { |
334 mailbox_holders[VideoFrame::kYPlane], | 412 case PIXEL_FORMAT_I420: |
335 mailbox_holders[VideoFrame::kUPlane], | 413 frame = VideoFrame::WrapYUV420NativeTextures( |
336 mailbox_holders[VideoFrame::kVPlane], | 414 mailbox_holders[VideoFrame::kYPlane], |
337 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), | 415 mailbox_holders[VideoFrame::kUPlane], |
338 size, video_frame->visible_rect(), video_frame->natural_size(), | 416 mailbox_holders[VideoFrame::kVPlane], |
339 video_frame->timestamp()); | 417 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), |
418 size, video_frame->visible_rect(), video_frame->natural_size(), | |
419 video_frame->timestamp()); | |
340 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) | 420 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) |
Andre
2015/08/21 18:18:36
indent +4
Daniele Castagna
2015/08/21 18:49:02
Done.
| |
341 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); | 421 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
422 break; | |
423 case PIXEL_FORMAT_UYVY: | |
424 frame = VideoFrame::WrapNativeTexture( | |
425 PIXEL_FORMAT_UYVY, mailbox_holders[VideoFrame::kYPlane], | |
426 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), | |
427 size, video_frame->visible_rect(), video_frame->natural_size(), | |
428 video_frame->timestamp()); | |
429 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); | |
430 break; | |
431 default: | |
432 NOTREACHED(); | |
433 } | |
342 frame_ready_cb.Run(frame); | 434 frame_ready_cb.Run(frame); |
343 } | 435 } |
344 | 436 |
345 // Destroy all the resources posting one task per FrameResources | 437 // Destroy all the resources posting one task per FrameResources |
346 // to the |media_task_runner_|. | 438 // to the |media_task_runner_|. |
347 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { | 439 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { |
348 // Delete all the resources on the media thread. | 440 // Delete all the resources on the media thread. |
349 while (!resources_pool_.empty()) { | 441 while (!resources_pool_.empty()) { |
350 FrameResources* frame_resources = resources_pool_.front(); | 442 FrameResources* frame_resources = resources_pool_.front(); |
351 resources_pool_.pop_front(); | 443 resources_pool_.pop_front(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 return nullptr; | 476 return nullptr; |
385 gles2->ActiveTexture(GL_TEXTURE0); | 477 gles2->ActiveTexture(GL_TEXTURE0); |
386 size_t planes = VideoFrame::NumPlanes(format); | 478 size_t planes = VideoFrame::NumPlanes(format); |
387 FrameResources* frame_resources = new FrameResources(format, size); | 479 FrameResources* frame_resources = new FrameResources(format, size); |
388 resources_pool_.push_back(frame_resources); | 480 resources_pool_.push_back(frame_resources); |
389 for (size_t i = 0; i < planes; ++i) { | 481 for (size_t i = 0; i < planes; ++i) { |
390 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | 482 PlaneResource& plane_resource = frame_resources->plane_resources[i]; |
391 const size_t width = VideoFrame::Columns(i, format, size.width()); | 483 const size_t width = VideoFrame::Columns(i, format, size.width()); |
392 const size_t height = VideoFrame::Rows(i, format, size.height()); | 484 const size_t height = VideoFrame::Rows(i, format, size.height()); |
393 const gfx::Size plane_size(width, height); | 485 const gfx::Size plane_size(width, height); |
486 | |
394 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( | 487 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( |
395 plane_size, gfx::BufferFormat::R_8, gfx::BufferUsage::MAP); | 488 plane_size, GpuMemoryBufferFormat(format, i), gfx::BufferUsage::MAP); |
396 | 489 |
397 gles2->GenTextures(1, &plane_resource.texture_id); | 490 gles2->GenTextures(1, &plane_resource.texture_id); |
398 gles2->BindTexture(texture_target_, plane_resource.texture_id); | 491 gles2->BindTexture(texture_target_, plane_resource.texture_id); |
399 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 492 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
400 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 493 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
401 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 494 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
402 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 495 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
403 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); | 496 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); |
404 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name); | 497 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name); |
405 } | 498 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
460 } | 553 } |
461 | 554 |
462 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( | 555 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( |
463 const scoped_refptr<VideoFrame>& video_frame, | 556 const scoped_refptr<VideoFrame>& video_frame, |
464 const FrameReadyCB& frame_ready_cb) { | 557 const FrameReadyCB& frame_ready_cb) { |
465 DCHECK(video_frame); | 558 DCHECK(video_frame); |
466 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); | 559 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); |
467 } | 560 } |
468 | 561 |
469 } // namespace media | 562 } // namespace media |
OLD | NEW |