Chromium Code Reviews| 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 |