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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/eventfd.h> | 11 #include <sys/eventfd.h> |
12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
20 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
21 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
23 #include "content/common/gpu/media/shared_memory_region.h" | |
24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | |
25 #include "media/base/media_switches.h" | 23 #include "media/base/media_switches.h" |
26 #include "media/filters/h264_parser.h" | 24 #include "media/filters/h264_parser.h" |
| 25 #include "media/gpu/shared_memory_region.h" |
| 26 #include "media/gpu/v4l2_video_decode_accelerator.h" |
27 #include "ui/gfx/geometry/rect.h" | 27 #include "ui/gfx/geometry/rect.h" |
28 #include "ui/gl/gl_context.h" | 28 #include "ui/gl/gl_context.h" |
29 #include "ui/gl/scoped_binders.h" | 29 #include "ui/gl/scoped_binders.h" |
30 | 30 |
31 #define NOTIFY_ERROR(x) \ | 31 #define NOTIFY_ERROR(x) \ |
32 do { \ | 32 do { \ |
33 LOG(ERROR) << "Setting error state:" << x; \ | 33 LOG(ERROR) << "Setting error state:" << x; \ |
34 SetErrorState(x); \ | 34 SetErrorState(x); \ |
35 } while (0) | 35 } while (0) |
36 | 36 |
37 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ | 37 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ |
38 do { \ | 38 do { \ |
39 if (device_->Ioctl(type, arg) != 0) { \ | 39 if (device_->Ioctl(type, arg) != 0) { \ |
40 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \ | 40 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \ |
41 NOTIFY_ERROR(PLATFORM_FAILURE); \ | 41 NOTIFY_ERROR(PLATFORM_FAILURE); \ |
42 return value; \ | 42 return value; \ |
43 } \ | 43 } \ |
44 } while (0) | 44 } while (0) |
45 | 45 |
46 #define IOCTL_OR_ERROR_RETURN(type, arg) \ | 46 #define IOCTL_OR_ERROR_RETURN(type, arg) \ |
47 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type) | 47 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type) |
48 | 48 |
49 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ | 49 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ |
50 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type) | 50 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type) |
51 | 51 |
52 #define IOCTL_OR_LOG_ERROR(type, arg) \ | 52 #define IOCTL_OR_LOG_ERROR(type, arg) \ |
53 do { \ | 53 do { \ |
54 if (device_->Ioctl(type, arg) != 0) \ | 54 if (device_->Ioctl(type, arg) != 0) \ |
55 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ | 55 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ |
56 } while (0) | 56 } while (0) |
57 | 57 |
58 namespace content { | 58 namespace media { |
59 | 59 |
60 // static | 60 // static |
61 const uint32_t V4L2VideoDecodeAccelerator::supported_input_fourccs_[] = { | 61 const uint32_t V4L2VideoDecodeAccelerator::supported_input_fourccs_[] = { |
62 V4L2_PIX_FMT_H264, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, | 62 V4L2_PIX_FMT_H264, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, |
63 }; | 63 }; |
64 | 64 |
65 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { | 65 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { |
66 BitstreamBufferRef( | 66 BitstreamBufferRef( |
67 base::WeakPtr<Client>& client, | 67 base::WeakPtr<Client>& client, |
68 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, | 68 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 input_id(input_id) {} | 102 input_id(input_id) {} |
103 | 103 |
104 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 104 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
105 if (input_id >= 0) { | 105 if (input_id >= 0) { |
106 client_task_runner->PostTask( | 106 client_task_runner->PostTask( |
107 FROM_HERE, | 107 FROM_HERE, |
108 base::Bind(&Client::NotifyEndOfBitstreamBuffer, client, input_id)); | 108 base::Bind(&Client::NotifyEndOfBitstreamBuffer, client, input_id)); |
109 } | 109 } |
110 } | 110 } |
111 | 111 |
112 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( | 112 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef(EGLDisplay egl_display, |
113 EGLDisplay egl_display, EGLSyncKHR egl_sync) | 113 EGLSyncKHR egl_sync) |
114 : egl_display(egl_display), | 114 : egl_display(egl_display), egl_sync(egl_sync) {} |
115 egl_sync(egl_sync) { | |
116 } | |
117 | 115 |
118 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { | 116 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { |
119 // We don't check for eglDestroySyncKHR failures, because if we get here | 117 // We don't check for eglDestroySyncKHR failures, because if we get here |
120 // with a valid sync object, something went wrong and we are getting | 118 // with a valid sync object, something went wrong and we are getting |
121 // destroyed anyway. | 119 // destroyed anyway. |
122 if (egl_sync != EGL_NO_SYNC_KHR) | 120 if (egl_sync != EGL_NO_SYNC_KHR) |
123 eglDestroySyncKHR(egl_display, egl_sync); | 121 eglDestroySyncKHR(egl_display, egl_sync); |
124 } | 122 } |
125 | 123 |
126 V4L2VideoDecodeAccelerator::InputRecord::InputRecord() | 124 V4L2VideoDecodeAccelerator::InputRecord::InputRecord() |
127 : at_device(false), | 125 : at_device(false), address(NULL), length(0), bytes_used(0), input_id(-1) {} |
128 address(NULL), | |
129 length(0), | |
130 bytes_used(0), | |
131 input_id(-1) { | |
132 } | |
133 | 126 |
134 V4L2VideoDecodeAccelerator::InputRecord::~InputRecord() { | 127 V4L2VideoDecodeAccelerator::InputRecord::~InputRecord() {} |
135 } | |
136 | 128 |
137 V4L2VideoDecodeAccelerator::OutputRecord::OutputRecord() | 129 V4L2VideoDecodeAccelerator::OutputRecord::OutputRecord() |
138 : at_device(false), | 130 : at_device(false), |
139 at_client(false), | 131 at_client(false), |
140 egl_image(EGL_NO_IMAGE_KHR), | 132 egl_image(EGL_NO_IMAGE_KHR), |
141 egl_sync(EGL_NO_SYNC_KHR), | 133 egl_sync(EGL_NO_SYNC_KHR), |
142 picture_id(-1), | 134 picture_id(-1), |
143 cleared(false) { | 135 cleared(false) {} |
144 } | |
145 | 136 |
146 V4L2VideoDecodeAccelerator::OutputRecord::~OutputRecord() {} | 137 V4L2VideoDecodeAccelerator::OutputRecord::~OutputRecord() {} |
147 | 138 |
148 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( | 139 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( |
149 bool cleared, | 140 bool cleared, |
150 const media::Picture& picture) | 141 const media::Picture& picture) |
151 : cleared(cleared), picture(picture) {} | 142 : cleared(cleared), picture(picture) {} |
152 | 143 |
153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 144 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
154 | 145 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 return false; | 244 return false; |
254 } | 245 } |
255 #endif | 246 #endif |
256 | 247 |
257 // Capabilities check. | 248 // Capabilities check. |
258 struct v4l2_capability caps; | 249 struct v4l2_capability caps; |
259 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | 250 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
260 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 251 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
261 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 252 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
262 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" | 253 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
263 ", caps check failed: 0x" << std::hex << caps.capabilities; | 254 ", caps check failed: 0x" |
| 255 << std::hex << caps.capabilities; |
264 return false; | 256 return false; |
265 } | 257 } |
266 | 258 |
267 if (!SetupFormats()) | 259 if (!SetupFormats()) |
268 return false; | 260 return false; |
269 | 261 |
270 // Subscribe to the resolution change event. | 262 // Subscribe to the resolution change event. |
271 struct v4l2_event_subscription sub; | 263 struct v4l2_event_subscription sub; |
272 memset(&sub, 0, sizeof(sub)); | 264 memset(&sub, 0, sizeof(sub)); |
273 sub.type = V4L2_EVENT_SOURCE_CHANGE; | 265 sub.type = V4L2_EVENT_SOURCE_CHANGE; |
274 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); | 266 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); |
275 | 267 |
276 if (video_profile_ >= media::H264PROFILE_MIN && | 268 if (video_profile_ >= media::H264PROFILE_MIN && |
277 video_profile_ <= media::H264PROFILE_MAX) { | 269 video_profile_ <= media::H264PROFILE_MAX) { |
278 decoder_h264_parser_.reset(new media::H264Parser()); | 270 decoder_h264_parser_.reset(new media::H264Parser()); |
279 } | 271 } |
280 | 272 |
281 if (!CreateInputBuffers()) | 273 if (!CreateInputBuffers()) |
282 return false; | 274 return false; |
283 | 275 |
284 if (!decoder_thread_.Start()) { | 276 if (!decoder_thread_.Start()) { |
285 LOG(ERROR) << "Initialize(): decoder thread failed to start"; | 277 LOG(ERROR) << "Initialize(): decoder thread failed to start"; |
286 return false; | 278 return false; |
287 } | 279 } |
288 | 280 |
289 decoder_state_ = kInitialized; | 281 decoder_state_ = kInitialized; |
290 | 282 |
291 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. | 283 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. |
292 decoder_thread_.message_loop()->PostTask( | 284 decoder_thread_.message_loop()->PostTask( |
293 FROM_HERE, | 285 FROM_HERE, base::Bind(base::IgnoreResult( |
294 base::Bind( | 286 &V4L2VideoDecodeAccelerator::StartDevicePoll), |
295 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 287 base::Unretained(this))); |
296 base::Unretained(this))); | |
297 | 288 |
298 return true; | 289 return true; |
299 } | 290 } |
300 | 291 |
301 void V4L2VideoDecodeAccelerator::Decode( | 292 void V4L2VideoDecodeAccelerator::Decode( |
302 const media::BitstreamBuffer& bitstream_buffer) { | 293 const media::BitstreamBuffer& bitstream_buffer) { |
303 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 294 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
304 << ", size=" << bitstream_buffer.size(); | 295 << ", size=" << bitstream_buffer.size(); |
305 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 296 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
306 | 297 |
307 if (bitstream_buffer.id() < 0) { | 298 if (bitstream_buffer.id() < 0) { |
308 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 299 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
309 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 300 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
310 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 301 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
311 NOTIFY_ERROR(INVALID_ARGUMENT); | 302 NOTIFY_ERROR(INVALID_ARGUMENT); |
312 return; | 303 return; |
313 } | 304 } |
314 | 305 |
315 // DecodeTask() will take care of running a DecodeBufferTask(). | 306 // DecodeTask() will take care of running a DecodeBufferTask(). |
316 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 307 decoder_thread_.message_loop()->PostTask( |
317 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 308 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeTask, |
318 bitstream_buffer)); | 309 base::Unretained(this), bitstream_buffer)); |
319 } | 310 } |
320 | 311 |
321 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( | 312 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
322 const std::vector<media::PictureBuffer>& buffers) { | 313 const std::vector<media::PictureBuffer>& buffers) { |
323 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 314 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
324 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 315 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
325 | 316 |
326 const uint32_t req_buffer_count = | 317 const uint32_t req_buffer_count = |
327 output_dpb_size_ + kDpbOutputBufferExtraCount; | 318 output_dpb_size_ + kDpbOutputBufferExtraCount; |
328 | 319 |
329 if (buffers.size() < req_buffer_count) { | 320 if (buffers.size() < req_buffer_count) { |
330 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 321 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
331 " buffers. (Got " << buffers.size() | 322 " buffers. (Got " |
332 << ", requested " << req_buffer_count << ")"; | 323 << buffers.size() << ", requested " << req_buffer_count << ")"; |
333 NOTIFY_ERROR(INVALID_ARGUMENT); | 324 NOTIFY_ERROR(INVALID_ARGUMENT); |
334 return; | 325 return; |
335 } | 326 } |
336 | 327 |
337 gfx::GLContext* gl_context = get_gl_context_cb_.Run(); | 328 gfx::GLContext* gl_context = get_gl_context_cb_.Run(); |
338 if (!gl_context || !make_context_current_cb_.Run()) { | 329 if (!gl_context || !make_context_current_cb_.Run()) { |
339 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 330 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
340 NOTIFY_ERROR(PLATFORM_FAILURE); | 331 NOTIFY_ERROR(PLATFORM_FAILURE); |
341 return; | 332 return; |
342 } | 333 } |
343 | 334 |
344 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 335 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
345 | 336 |
346 // It's safe to manipulate all the buffer state here, because the decoder | 337 // It's safe to manipulate all the buffer state here, because the decoder |
347 // thread is waiting on pictures_assigned_. | 338 // thread is waiting on pictures_assigned_. |
348 | 339 |
349 // Allocate the output buffers. | 340 // Allocate the output buffers. |
350 struct v4l2_requestbuffers reqbufs; | 341 struct v4l2_requestbuffers reqbufs; |
351 memset(&reqbufs, 0, sizeof(reqbufs)); | 342 memset(&reqbufs, 0, sizeof(reqbufs)); |
352 reqbufs.count = buffers.size(); | 343 reqbufs.count = buffers.size(); |
353 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 344 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
354 reqbufs.memory = V4L2_MEMORY_MMAP; | 345 reqbufs.memory = V4L2_MEMORY_MMAP; |
355 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); | 346 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); |
356 | 347 |
357 if (reqbufs.count != buffers.size()) { | 348 if (reqbufs.count != buffers.size()) { |
358 DLOG(ERROR) << "Could not allocate enough output buffers"; | 349 DLOG(ERROR) << "Could not allocate enough output buffers"; |
359 NOTIFY_ERROR(PLATFORM_FAILURE); | 350 NOTIFY_ERROR(PLATFORM_FAILURE); |
360 return; | 351 return; |
361 } | 352 } |
362 | 353 |
363 output_buffer_map_.resize(buffers.size()); | 354 output_buffer_map_.resize(buffers.size()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 405 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
415 if (egl_sync == EGL_NO_SYNC_KHR) { | 406 if (egl_sync == EGL_NO_SYNC_KHR) { |
416 LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; | 407 LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; |
417 NOTIFY_ERROR(PLATFORM_FAILURE); | 408 NOTIFY_ERROR(PLATFORM_FAILURE); |
418 return; | 409 return; |
419 } | 410 } |
420 #endif | 411 #endif |
421 | 412 |
422 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref( | 413 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref( |
423 new EGLSyncKHRRef(egl_display_, egl_sync)); | 414 new EGLSyncKHRRef(egl_display_, egl_sync)); |
424 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 415 decoder_thread_.message_loop()->PostTask( |
425 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, | 416 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ReusePictureBufferTask, |
426 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); | 417 base::Unretained(this), picture_buffer_id, |
| 418 base::Passed(&egl_sync_ref))); |
427 } | 419 } |
428 | 420 |
429 void V4L2VideoDecodeAccelerator::Flush() { | 421 void V4L2VideoDecodeAccelerator::Flush() { |
430 DVLOG(3) << "Flush()"; | 422 DVLOG(3) << "Flush()"; |
431 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 423 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
432 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 424 decoder_thread_.message_loop()->PostTask( |
433 &V4L2VideoDecodeAccelerator::FlushTask, base::Unretained(this))); | 425 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::FlushTask, |
| 426 base::Unretained(this))); |
434 } | 427 } |
435 | 428 |
436 void V4L2VideoDecodeAccelerator::Reset() { | 429 void V4L2VideoDecodeAccelerator::Reset() { |
437 DVLOG(3) << "Reset()"; | 430 DVLOG(3) << "Reset()"; |
438 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 431 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
439 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 432 decoder_thread_.message_loop()->PostTask( |
440 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this))); | 433 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetTask, |
| 434 base::Unretained(this))); |
441 } | 435 } |
442 | 436 |
443 void V4L2VideoDecodeAccelerator::Destroy() { | 437 void V4L2VideoDecodeAccelerator::Destroy() { |
444 DVLOG(3) << "Destroy()"; | 438 DVLOG(3) << "Destroy()"; |
445 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 439 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
446 | 440 |
447 // We're destroying; cancel all callbacks. | 441 // We're destroying; cancel all callbacks. |
448 client_ptr_factory_.reset(); | 442 client_ptr_factory_.reset(); |
449 weak_this_factory_.InvalidateWeakPtrs(); | 443 weak_this_factory_.InvalidateWeakPtrs(); |
450 | 444 |
451 // If the decoder thread is running, destroy using posted task. | 445 // If the decoder thread is running, destroy using posted task. |
452 if (decoder_thread_.IsRunning()) { | 446 if (decoder_thread_.IsRunning()) { |
453 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 447 decoder_thread_.message_loop()->PostTask( |
454 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this))); | 448 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DestroyTask, |
| 449 base::Unretained(this))); |
455 pictures_assigned_.Signal(); | 450 pictures_assigned_.Signal(); |
456 // DestroyTask() will cause the decoder_thread_ to flush all tasks. | 451 // DestroyTask() will cause the decoder_thread_ to flush all tasks. |
457 decoder_thread_.Stop(); | 452 decoder_thread_.Stop(); |
458 } else { | 453 } else { |
459 // Otherwise, call the destroy task directly. | 454 // Otherwise, call the destroy task directly. |
460 DestroyTask(); | 455 DestroyTask(); |
461 } | 456 } |
462 | 457 |
463 delete this; | 458 delete this; |
464 } | 459 } |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 | 722 |
728 void V4L2VideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 723 void V4L2VideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
729 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 724 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
730 | 725 |
731 // If we're behind on tasks, schedule another one. | 726 // If we're behind on tasks, schedule another one. |
732 int buffers_to_decode = decoder_input_queue_.size(); | 727 int buffers_to_decode = decoder_input_queue_.size(); |
733 if (decoder_current_bitstream_buffer_ != NULL) | 728 if (decoder_current_bitstream_buffer_ != NULL) |
734 buffers_to_decode++; | 729 buffers_to_decode++; |
735 if (decoder_decode_buffer_tasks_scheduled_ < buffers_to_decode) { | 730 if (decoder_decode_buffer_tasks_scheduled_ < buffers_to_decode) { |
736 decoder_decode_buffer_tasks_scheduled_++; | 731 decoder_decode_buffer_tasks_scheduled_++; |
737 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 732 decoder_thread_.message_loop()->PostTask( |
738 &V4L2VideoDecodeAccelerator::DecodeBufferTask, | 733 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeBufferTask, |
739 base::Unretained(this))); | 734 base::Unretained(this))); |
740 } | 735 } |
741 } | 736 } |
742 | 737 |
743 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial( | 738 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial(const void* data, |
744 const void* data, size_t size, size_t* endpos) { | 739 size_t size, |
| 740 size_t* endpos) { |
745 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; | 741 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; |
746 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 742 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
747 DCHECK_NE(decoder_state_, kUninitialized); | 743 DCHECK_NE(decoder_state_, kUninitialized); |
748 DCHECK_NE(decoder_state_, kDecoding); | 744 DCHECK_NE(decoder_state_, kDecoding); |
749 // Initial decode. We haven't been able to get output stream format info yet. | 745 // Initial decode. We haven't been able to get output stream format info yet. |
750 // Get it, and start decoding. | 746 // Get it, and start decoding. |
751 | 747 |
752 // Copy in and send to HW. | 748 // Copy in and send to HW. |
753 if (!AppendToInputFrame(data, size)) | 749 if (!AppendToInputFrame(data, size)) |
754 return false; | 750 return false; |
(...skipping 28 matching lines...) Expand all Loading... |
783 // Success! Setup our parameters. | 779 // Success! Setup our parameters. |
784 if (!CreateBuffersForFormat(format, visible_size)) | 780 if (!CreateBuffersForFormat(format, visible_size)) |
785 return false; | 781 return false; |
786 } | 782 } |
787 | 783 |
788 decoder_state_ = kDecoding; | 784 decoder_state_ = kDecoding; |
789 ScheduleDecodeBufferTaskIfNeeded(); | 785 ScheduleDecodeBufferTaskIfNeeded(); |
790 return true; | 786 return true; |
791 } | 787 } |
792 | 788 |
793 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue( | 789 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue(const void* data, |
794 const void* data, size_t size) { | 790 size_t size) { |
795 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; | 791 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; |
796 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 792 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
797 DCHECK_EQ(decoder_state_, kDecoding); | 793 DCHECK_EQ(decoder_state_, kDecoding); |
798 | 794 |
799 // Both of these calls will set kError state if they fail. | 795 // Both of these calls will set kError state if they fail. |
800 // Only flush the frame if it's complete. | 796 // Only flush the frame if it's complete. |
801 return (AppendToInputFrame(data, size) && | 797 return (AppendToInputFrame(data, size) && |
802 (decoder_partial_frame_pending_ || FlushInputFrame())); | 798 (decoder_partial_frame_pending_ || FlushInputFrame())); |
803 } | 799 } |
804 | 800 |
805 bool V4L2VideoDecodeAccelerator::AppendToInputFrame( | 801 bool V4L2VideoDecodeAccelerator::AppendToInputFrame(const void* data, |
806 const void* data, size_t size) { | 802 size_t size) { |
807 DVLOG(3) << "AppendToInputFrame()"; | 803 DVLOG(3) << "AppendToInputFrame()"; |
808 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 804 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
809 DCHECK_NE(decoder_state_, kUninitialized); | 805 DCHECK_NE(decoder_state_, kUninitialized); |
810 DCHECK_NE(decoder_state_, kResetting); | 806 DCHECK_NE(decoder_state_, kResetting); |
811 DCHECK_NE(decoder_state_, kError); | 807 DCHECK_NE(decoder_state_, kError); |
812 // This routine can handle data == NULL and size == 0, which occurs when | 808 // This routine can handle data == NULL and size == 0, which occurs when |
813 // we queue an empty buffer for the purposes of flushing the pipe. | 809 // we queue an empty buffer for the purposes of flushing the pipe. |
814 | 810 |
815 // Flush if we're too big | 811 // Flush if we're too big |
816 if (decoder_current_input_buffer_ != -1) { | 812 if (decoder_current_input_buffer_ != -1) { |
(...skipping 29 matching lines...) Expand all Loading... |
846 | 842 |
847 DCHECK(data != NULL || size == 0); | 843 DCHECK(data != NULL || size == 0); |
848 if (size == 0) { | 844 if (size == 0) { |
849 // If we asked for an empty buffer, return now. We return only after | 845 // If we asked for an empty buffer, return now. We return only after |
850 // getting the next input buffer, since we might actually want an empty | 846 // getting the next input buffer, since we might actually want an empty |
851 // input buffer for flushing purposes. | 847 // input buffer for flushing purposes. |
852 return true; | 848 return true; |
853 } | 849 } |
854 | 850 |
855 // Copy in to the buffer. | 851 // Copy in to the buffer. |
856 InputRecord& input_record = | 852 InputRecord& input_record = input_buffer_map_[decoder_current_input_buffer_]; |
857 input_buffer_map_[decoder_current_input_buffer_]; | |
858 if (size > input_record.length - input_record.bytes_used) { | 853 if (size > input_record.length - input_record.bytes_used) { |
859 LOG(ERROR) << "AppendToInputFrame(): over-size frame, erroring"; | 854 LOG(ERROR) << "AppendToInputFrame(): over-size frame, erroring"; |
860 NOTIFY_ERROR(UNREADABLE_INPUT); | 855 NOTIFY_ERROR(UNREADABLE_INPUT); |
861 return false; | 856 return false; |
862 } | 857 } |
863 memcpy(reinterpret_cast<uint8_t*>(input_record.address) + | 858 memcpy(reinterpret_cast<uint8_t*>(input_record.address) + |
864 input_record.bytes_used, | 859 input_record.bytes_used, |
865 data, size); | 860 data, size); |
866 input_record.bytes_used += size; | 861 input_record.bytes_used += size; |
867 | 862 |
868 return true; | 863 return true; |
869 } | 864 } |
870 | 865 |
871 bool V4L2VideoDecodeAccelerator::FlushInputFrame() { | 866 bool V4L2VideoDecodeAccelerator::FlushInputFrame() { |
872 DVLOG(3) << "FlushInputFrame()"; | 867 DVLOG(3) << "FlushInputFrame()"; |
873 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 868 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
874 DCHECK_NE(decoder_state_, kUninitialized); | 869 DCHECK_NE(decoder_state_, kUninitialized); |
875 DCHECK_NE(decoder_state_, kResetting); | 870 DCHECK_NE(decoder_state_, kResetting); |
876 DCHECK_NE(decoder_state_, kError); | 871 DCHECK_NE(decoder_state_, kError); |
877 | 872 |
878 if (decoder_current_input_buffer_ == -1) | 873 if (decoder_current_input_buffer_ == -1) |
879 return true; | 874 return true; |
880 | 875 |
881 InputRecord& input_record = | 876 InputRecord& input_record = input_buffer_map_[decoder_current_input_buffer_]; |
882 input_buffer_map_[decoder_current_input_buffer_]; | |
883 DCHECK_NE(input_record.input_id, -1); | 877 DCHECK_NE(input_record.input_id, -1); |
884 DCHECK(input_record.input_id != kFlushBufferId || | 878 DCHECK(input_record.input_id != kFlushBufferId || |
885 input_record.bytes_used == 0); | 879 input_record.bytes_used == 0); |
886 // * if input_id >= 0, this input buffer was prompted by a bitstream buffer we | 880 // * if input_id >= 0, this input buffer was prompted by a bitstream buffer we |
887 // got from the client. We can skip it if it is empty. | 881 // got from the client. We can skip it if it is empty. |
888 // * if input_id < 0 (should be kFlushBufferId in this case), this input | 882 // * if input_id < 0 (should be kFlushBufferId in this case), this input |
889 // buffer was prompted by a flush buffer, and should be queued even when | 883 // buffer was prompted by a flush buffer, and should be queued even when |
890 // empty. | 884 // empty. |
891 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { | 885 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { |
892 input_record.input_id = -1; | 886 input_record.input_id = -1; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 | 937 |
944 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), | 938 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), |
945 // so either: | 939 // so either: |
946 // * device_poll_thread_ is running normally | 940 // * device_poll_thread_ is running normally |
947 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() | 941 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() |
948 // shut it down, in which case we're either in kResetting or kError states | 942 // shut it down, in which case we're either in kResetting or kError states |
949 // respectively, and we should have early-outed already. | 943 // respectively, and we should have early-outed already. |
950 DCHECK(device_poll_thread_.message_loop()); | 944 DCHECK(device_poll_thread_.message_loop()); |
951 // Queue the DevicePollTask() now. | 945 // Queue the DevicePollTask() now. |
952 device_poll_thread_.message_loop()->PostTask( | 946 device_poll_thread_.message_loop()->PostTask( |
953 FROM_HERE, | 947 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask, |
954 base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask, | 948 base::Unretained(this), poll_device)); |
955 base::Unretained(this), | |
956 poll_device)); | |
957 | 949 |
958 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" | 950 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" |
959 << decoder_input_queue_.size() << "->" | 951 << decoder_input_queue_.size() << "->" << input_ready_queue_.size() |
960 << input_ready_queue_.size() << "] => DEVICE[" | 952 << "] => DEVICE[" << free_input_buffers_.size() << "+" |
961 << free_input_buffers_.size() << "+" | 953 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() |
962 << input_buffer_queued_count_ << "/" | 954 << "->" << free_output_buffers_.size() << "+" |
963 << input_buffer_map_.size() << "->" | 955 << output_buffer_queued_count_ << "/" << output_buffer_map_.size() |
964 << free_output_buffers_.size() << "+" | 956 << "] => VDA[" << decoder_frames_at_client_ << "]"; |
965 << output_buffer_queued_count_ << "/" | |
966 << output_buffer_map_.size() << "] => VDA[" | |
967 << decoder_frames_at_client_ << "]"; | |
968 | 957 |
969 ScheduleDecodeBufferTaskIfNeeded(); | 958 ScheduleDecodeBufferTaskIfNeeded(); |
970 if (resolution_change_pending) | 959 if (resolution_change_pending) |
971 StartResolutionChange(); | 960 StartResolutionChange(); |
972 } | 961 } |
973 | 962 |
974 void V4L2VideoDecodeAccelerator::Enqueue() { | 963 void V4L2VideoDecodeAccelerator::Enqueue() { |
975 DVLOG(3) << "Enqueue()"; | 964 DVLOG(3) << "Enqueue()"; |
976 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 965 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
977 DCHECK_NE(decoder_state_, kUninitialized); | 966 DCHECK_NE(decoder_state_, kUninitialized); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); | 1041 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); |
1053 | 1042 |
1054 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free | 1043 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free |
1055 // list. | 1044 // list. |
1056 while (input_buffer_queued_count_ > 0) { | 1045 while (input_buffer_queued_count_ > 0) { |
1057 DCHECK(input_streamon_); | 1046 DCHECK(input_streamon_); |
1058 struct v4l2_buffer dqbuf; | 1047 struct v4l2_buffer dqbuf; |
1059 struct v4l2_plane planes[1]; | 1048 struct v4l2_plane planes[1]; |
1060 memset(&dqbuf, 0, sizeof(dqbuf)); | 1049 memset(&dqbuf, 0, sizeof(dqbuf)); |
1061 memset(planes, 0, sizeof(planes)); | 1050 memset(planes, 0, sizeof(planes)); |
1062 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1051 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1063 dqbuf.memory = V4L2_MEMORY_MMAP; | 1052 dqbuf.memory = V4L2_MEMORY_MMAP; |
1064 dqbuf.m.planes = planes; | 1053 dqbuf.m.planes = planes; |
1065 dqbuf.length = 1; | 1054 dqbuf.length = 1; |
1066 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { | 1055 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
1067 if (errno == EAGAIN) { | 1056 if (errno == EAGAIN) { |
1068 // EAGAIN if we're just out of buffers to dequeue. | 1057 // EAGAIN if we're just out of buffers to dequeue. |
1069 break; | 1058 break; |
1070 } | 1059 } |
1071 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; | 1060 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; |
1072 NOTIFY_ERROR(PLATFORM_FAILURE); | 1061 NOTIFY_ERROR(PLATFORM_FAILURE); |
(...skipping 10 matching lines...) Expand all Loading... |
1083 | 1072 |
1084 // Dequeue completed output (VIDEO_CAPTURE) buffers, and queue to the | 1073 // Dequeue completed output (VIDEO_CAPTURE) buffers, and queue to the |
1085 // completed queue. | 1074 // completed queue. |
1086 while (output_buffer_queued_count_ > 0) { | 1075 while (output_buffer_queued_count_ > 0) { |
1087 DCHECK(output_streamon_); | 1076 DCHECK(output_streamon_); |
1088 struct v4l2_buffer dqbuf; | 1077 struct v4l2_buffer dqbuf; |
1089 std::unique_ptr<struct v4l2_plane[]> planes( | 1078 std::unique_ptr<struct v4l2_plane[]> planes( |
1090 new v4l2_plane[output_planes_count_]); | 1079 new v4l2_plane[output_planes_count_]); |
1091 memset(&dqbuf, 0, sizeof(dqbuf)); | 1080 memset(&dqbuf, 0, sizeof(dqbuf)); |
1092 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); | 1081 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); |
1093 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1082 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1094 dqbuf.memory = V4L2_MEMORY_MMAP; | 1083 dqbuf.memory = V4L2_MEMORY_MMAP; |
1095 dqbuf.m.planes = planes.get(); | 1084 dqbuf.m.planes = planes.get(); |
1096 dqbuf.length = output_planes_count_; | 1085 dqbuf.length = output_planes_count_; |
1097 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { | 1086 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
1098 if (errno == EAGAIN) { | 1087 if (errno == EAGAIN) { |
1099 // EAGAIN if we're just out of buffers to dequeue. | 1088 // EAGAIN if we're just out of buffers to dequeue. |
1100 break; | 1089 break; |
1101 } | 1090 } |
1102 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; | 1091 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; |
1103 NOTIFY_ERROR(PLATFORM_FAILURE); | 1092 NOTIFY_ERROR(PLATFORM_FAILURE); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 DCHECK(!input_ready_queue_.empty()); | 1126 DCHECK(!input_ready_queue_.empty()); |
1138 | 1127 |
1139 // Enqueue an input (VIDEO_OUTPUT) buffer. | 1128 // Enqueue an input (VIDEO_OUTPUT) buffer. |
1140 const int buffer = input_ready_queue_.front(); | 1129 const int buffer = input_ready_queue_.front(); |
1141 InputRecord& input_record = input_buffer_map_[buffer]; | 1130 InputRecord& input_record = input_buffer_map_[buffer]; |
1142 DCHECK(!input_record.at_device); | 1131 DCHECK(!input_record.at_device); |
1143 struct v4l2_buffer qbuf; | 1132 struct v4l2_buffer qbuf; |
1144 struct v4l2_plane qbuf_plane; | 1133 struct v4l2_plane qbuf_plane; |
1145 memset(&qbuf, 0, sizeof(qbuf)); | 1134 memset(&qbuf, 0, sizeof(qbuf)); |
1146 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); | 1135 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); |
1147 qbuf.index = buffer; | 1136 qbuf.index = buffer; |
1148 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1137 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1149 qbuf.timestamp.tv_sec = input_record.input_id; | 1138 qbuf.timestamp.tv_sec = input_record.input_id; |
1150 qbuf.memory = V4L2_MEMORY_MMAP; | 1139 qbuf.memory = V4L2_MEMORY_MMAP; |
1151 qbuf.m.planes = &qbuf_plane; | 1140 qbuf.m.planes = &qbuf_plane; |
1152 qbuf.m.planes[0].bytesused = input_record.bytes_used; | 1141 qbuf.m.planes[0].bytesused = input_record.bytes_used; |
1153 qbuf.length = 1; | 1142 qbuf.length = 1; |
1154 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); | 1143 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); |
1155 input_ready_queue_.pop(); | 1144 input_ready_queue_.pop(); |
1156 input_record.at_device = true; | 1145 input_record.at_device = true; |
1157 input_buffer_queued_count_++; | 1146 input_buffer_queued_count_++; |
1158 DVLOG(3) << "EnqueueInputRecord(): enqueued input_id=" | 1147 DVLOG(3) << "EnqueueInputRecord(): enqueued input_id=" |
1159 << input_record.input_id << " size=" << input_record.bytes_used; | 1148 << input_record.input_id << " size=" << input_record.bytes_used; |
1160 return true; | 1149 return true; |
1161 } | 1150 } |
1162 | 1151 |
1163 bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() { | 1152 bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() { |
1164 DVLOG(3) << "EnqueueOutputRecord()"; | 1153 DVLOG(3) << "EnqueueOutputRecord()"; |
1165 DCHECK(!free_output_buffers_.empty()); | 1154 DCHECK(!free_output_buffers_.empty()); |
1166 | 1155 |
1167 // Enqueue an output (VIDEO_CAPTURE) buffer. | 1156 // Enqueue an output (VIDEO_CAPTURE) buffer. |
1168 const int buffer = free_output_buffers_.front(); | 1157 const int buffer = free_output_buffers_.front(); |
1169 OutputRecord& output_record = output_buffer_map_[buffer]; | 1158 OutputRecord& output_record = output_buffer_map_[buffer]; |
(...skipping 16 matching lines...) Expand all Loading... |
1186 LOG(ERROR) << __func__ << " eglDestroySyncKHR failed!"; | 1175 LOG(ERROR) << __func__ << " eglDestroySyncKHR failed!"; |
1187 NOTIFY_ERROR(PLATFORM_FAILURE); | 1176 NOTIFY_ERROR(PLATFORM_FAILURE); |
1188 return false; | 1177 return false; |
1189 } | 1178 } |
1190 output_record.egl_sync = EGL_NO_SYNC_KHR; | 1179 output_record.egl_sync = EGL_NO_SYNC_KHR; |
1191 } | 1180 } |
1192 struct v4l2_buffer qbuf; | 1181 struct v4l2_buffer qbuf; |
1193 std::unique_ptr<struct v4l2_plane[]> qbuf_planes( | 1182 std::unique_ptr<struct v4l2_plane[]> qbuf_planes( |
1194 new v4l2_plane[output_planes_count_]); | 1183 new v4l2_plane[output_planes_count_]); |
1195 memset(&qbuf, 0, sizeof(qbuf)); | 1184 memset(&qbuf, 0, sizeof(qbuf)); |
1196 memset( | 1185 memset(qbuf_planes.get(), 0, |
1197 qbuf_planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); | 1186 sizeof(struct v4l2_plane) * output_planes_count_); |
1198 qbuf.index = buffer; | 1187 qbuf.index = buffer; |
1199 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1188 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1200 qbuf.memory = V4L2_MEMORY_MMAP; | 1189 qbuf.memory = V4L2_MEMORY_MMAP; |
1201 qbuf.m.planes = qbuf_planes.get(); | 1190 qbuf.m.planes = qbuf_planes.get(); |
1202 qbuf.length = output_planes_count_; | 1191 qbuf.length = output_planes_count_; |
1203 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); | 1192 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); |
1204 free_output_buffers_.pop(); | 1193 free_output_buffers_.pop(); |
1205 output_record.at_device = true; | 1194 output_record.at_device = true; |
1206 output_buffer_queued_count_++; | 1195 output_buffer_queued_count_++; |
1207 return true; | 1196 return true; |
1208 } | 1197 } |
1209 | 1198 |
1210 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( | 1199 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 decoder_current_input_buffer_ = -1; | 1368 decoder_current_input_buffer_ = -1; |
1380 | 1369 |
1381 // If we were flushing, we'll never return any more BitstreamBuffers or | 1370 // If we were flushing, we'll never return any more BitstreamBuffers or |
1382 // PictureBuffers; they have all been dropped and returned by now. | 1371 // PictureBuffers; they have all been dropped and returned by now. |
1383 NotifyFlushDoneIfNeeded(); | 1372 NotifyFlushDoneIfNeeded(); |
1384 | 1373 |
1385 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening | 1374 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening |
1386 // jobs will early-out in the kResetting state. | 1375 // jobs will early-out in the kResetting state. |
1387 decoder_state_ = kResetting; | 1376 decoder_state_ = kResetting; |
1388 SendPictureReady(); // Send all pending PictureReady. | 1377 SendPictureReady(); // Send all pending PictureReady. |
1389 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1378 decoder_thread_.message_loop()->PostTask( |
1390 &V4L2VideoDecodeAccelerator::ResetDoneTask, base::Unretained(this))); | 1379 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetDoneTask, |
| 1380 base::Unretained(this))); |
1391 } | 1381 } |
1392 | 1382 |
1393 void V4L2VideoDecodeAccelerator::ResetDoneTask() { | 1383 void V4L2VideoDecodeAccelerator::ResetDoneTask() { |
1394 DVLOG(3) << "ResetDoneTask()"; | 1384 DVLOG(3) << "ResetDoneTask()"; |
1395 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1385 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1396 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetDoneTask"); | 1386 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetDoneTask"); |
1397 | 1387 |
1398 if (decoder_state_ == kError) { | 1388 if (decoder_state_ == kError) { |
1399 DVLOG(2) << "ResetDoneTask(): early out: kError state"; | 1389 DVLOG(2) << "ResetDoneTask(): early out: kError state"; |
1400 return; | 1390 return; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1454 DVLOG(3) << "StartDevicePoll()"; | 1444 DVLOG(3) << "StartDevicePoll()"; |
1455 DCHECK(!device_poll_thread_.IsRunning()); | 1445 DCHECK(!device_poll_thread_.IsRunning()); |
1456 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1446 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1457 | 1447 |
1458 // Start up the device poll thread and schedule its first DevicePollTask(). | 1448 // Start up the device poll thread and schedule its first DevicePollTask(). |
1459 if (!device_poll_thread_.Start()) { | 1449 if (!device_poll_thread_.Start()) { |
1460 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 1450 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
1461 NOTIFY_ERROR(PLATFORM_FAILURE); | 1451 NOTIFY_ERROR(PLATFORM_FAILURE); |
1462 return false; | 1452 return false; |
1463 } | 1453 } |
1464 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1454 device_poll_thread_.message_loop()->PostTask( |
1465 &V4L2VideoDecodeAccelerator::DevicePollTask, | 1455 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask, |
1466 base::Unretained(this), | 1456 base::Unretained(this), 0)); |
1467 0)); | |
1468 | 1457 |
1469 return true; | 1458 return true; |
1470 } | 1459 } |
1471 | 1460 |
1472 bool V4L2VideoDecodeAccelerator::StopDevicePoll() { | 1461 bool V4L2VideoDecodeAccelerator::StopDevicePoll() { |
1473 DVLOG(3) << "StopDevicePoll()"; | 1462 DVLOG(3) << "StopDevicePoll()"; |
1474 | 1463 |
1475 if (!device_poll_thread_.IsRunning()) | 1464 if (!device_poll_thread_.IsRunning()) |
1476 return true; | 1465 return true; |
1477 | 1466 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1617 | 1606 |
1618 bool event_pending = false; | 1607 bool event_pending = false; |
1619 | 1608 |
1620 if (!device_->Poll(poll_device, &event_pending)) { | 1609 if (!device_->Poll(poll_device, &event_pending)) { |
1621 NOTIFY_ERROR(PLATFORM_FAILURE); | 1610 NOTIFY_ERROR(PLATFORM_FAILURE); |
1622 return; | 1611 return; |
1623 } | 1612 } |
1624 | 1613 |
1625 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 1614 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
1626 // touch decoder state from this thread. | 1615 // touch decoder state from this thread. |
1627 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1616 decoder_thread_.message_loop()->PostTask( |
1628 &V4L2VideoDecodeAccelerator::ServiceDeviceTask, | 1617 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ServiceDeviceTask, |
1629 base::Unretained(this), event_pending)); | 1618 base::Unretained(this), event_pending)); |
1630 } | 1619 } |
1631 | 1620 |
1632 void V4L2VideoDecodeAccelerator::NotifyError(Error error) { | 1621 void V4L2VideoDecodeAccelerator::NotifyError(Error error) { |
1633 DVLOG(2) << "NotifyError()"; | 1622 DVLOG(2) << "NotifyError()"; |
1634 | 1623 |
1635 if (!child_task_runner_->BelongsToCurrentThread()) { | 1624 if (!child_task_runner_->BelongsToCurrentThread()) { |
1636 child_task_runner_->PostTask( | 1625 child_task_runner_->PostTask( |
1637 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::NotifyError, | 1626 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::NotifyError, |
1638 weak_this_, error)); | 1627 weak_this_, error)); |
1639 return; | 1628 return; |
1640 } | 1629 } |
1641 | 1630 |
1642 if (client_) { | 1631 if (client_) { |
1643 client_->NotifyError(error); | 1632 client_->NotifyError(error); |
1644 client_ptr_factory_.reset(); | 1633 client_ptr_factory_.reset(); |
1645 } | 1634 } |
1646 } | 1635 } |
1647 | 1636 |
1648 void V4L2VideoDecodeAccelerator::SetErrorState(Error error) { | 1637 void V4L2VideoDecodeAccelerator::SetErrorState(Error error) { |
1649 // We can touch decoder_state_ only if this is the decoder thread or the | 1638 // We can touch decoder_state_ only if this is the decoder thread or the |
1650 // decoder thread isn't running. | 1639 // decoder thread isn't running. |
1651 if (decoder_thread_.message_loop() != NULL && | 1640 if (decoder_thread_.message_loop() != NULL && |
1652 decoder_thread_.message_loop() != base::MessageLoop::current()) { | 1641 decoder_thread_.message_loop() != base::MessageLoop::current()) { |
1653 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1642 decoder_thread_.message_loop()->PostTask( |
1654 &V4L2VideoDecodeAccelerator::SetErrorState, | 1643 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::SetErrorState, |
1655 base::Unretained(this), error)); | 1644 base::Unretained(this), error)); |
1656 return; | 1645 return; |
1657 } | 1646 } |
1658 | 1647 |
1659 // Post NotifyError only if we are already initialized, as the API does | 1648 // Post NotifyError only if we are already initialized, as the API does |
1660 // not allow doing so before that. | 1649 // not allow doing so before that. |
1661 if (decoder_state_ != kError && decoder_state_ != kUninitialized) | 1650 if (decoder_state_ != kError && decoder_state_ != kUninitialized) |
1662 NotifyError(error); | 1651 NotifyError(error); |
1663 | 1652 |
1664 decoder_state_ = kError; | 1653 decoder_state_ = kError; |
1665 } | 1654 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1698 } | 1687 } |
1699 | 1688 |
1700 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( | 1689 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( |
1701 const struct v4l2_format& format, | 1690 const struct v4l2_format& format, |
1702 const gfx::Size& visible_size) { | 1691 const gfx::Size& visible_size) { |
1703 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1692 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1704 output_planes_count_ = format.fmt.pix_mp.num_planes; | 1693 output_planes_count_ = format.fmt.pix_mp.num_planes; |
1705 coded_size_.SetSize(format.fmt.pix_mp.width, format.fmt.pix_mp.height); | 1694 coded_size_.SetSize(format.fmt.pix_mp.width, format.fmt.pix_mp.height); |
1706 visible_size_ = visible_size; | 1695 visible_size_ = visible_size; |
1707 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " | 1696 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " |
1708 << coded_size_.ToString() << ", visible size: " | 1697 << coded_size_.ToString() |
1709 << visible_size_.ToString(); | 1698 << ", visible size: " << visible_size_.ToString(); |
1710 | 1699 |
1711 return CreateOutputBuffers(); | 1700 return CreateOutputBuffers(); |
1712 } | 1701 } |
1713 | 1702 |
1714 gfx::Size V4L2VideoDecodeAccelerator::GetVisibleSize( | 1703 gfx::Size V4L2VideoDecodeAccelerator::GetVisibleSize( |
1715 const gfx::Size& coded_size) { | 1704 const gfx::Size& coded_size) { |
1716 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1705 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1717 | 1706 |
1718 struct v4l2_crop crop_arg; | 1707 struct v4l2_crop crop_arg; |
1719 memset(&crop_arg, 0, sizeof(crop_arg)); | 1708 memset(&crop_arg, 0, sizeof(crop_arg)); |
(...skipping 29 matching lines...) Expand all Loading... |
1749 | 1738 |
1750 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { | 1739 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { |
1751 DVLOG(3) << "CreateInputBuffers()"; | 1740 DVLOG(3) << "CreateInputBuffers()"; |
1752 // We always run this as we prepare to initialize. | 1741 // We always run this as we prepare to initialize. |
1753 DCHECK_EQ(decoder_state_, kUninitialized); | 1742 DCHECK_EQ(decoder_state_, kUninitialized); |
1754 DCHECK(!input_streamon_); | 1743 DCHECK(!input_streamon_); |
1755 DCHECK(input_buffer_map_.empty()); | 1744 DCHECK(input_buffer_map_.empty()); |
1756 | 1745 |
1757 struct v4l2_requestbuffers reqbufs; | 1746 struct v4l2_requestbuffers reqbufs; |
1758 memset(&reqbufs, 0, sizeof(reqbufs)); | 1747 memset(&reqbufs, 0, sizeof(reqbufs)); |
1759 reqbufs.count = kInputBufferCount; | 1748 reqbufs.count = kInputBufferCount; |
1760 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1749 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1761 reqbufs.memory = V4L2_MEMORY_MMAP; | 1750 reqbufs.memory = V4L2_MEMORY_MMAP; |
1762 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1751 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
1763 input_buffer_map_.resize(reqbufs.count); | 1752 input_buffer_map_.resize(reqbufs.count); |
1764 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 1753 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
1765 free_input_buffers_.push_back(i); | 1754 free_input_buffers_.push_back(i); |
1766 | 1755 |
1767 // Query for the MEMORY_MMAP pointer. | 1756 // Query for the MEMORY_MMAP pointer. |
1768 struct v4l2_plane planes[1]; | 1757 struct v4l2_plane planes[1]; |
1769 struct v4l2_buffer buffer; | 1758 struct v4l2_buffer buffer; |
1770 memset(&buffer, 0, sizeof(buffer)); | 1759 memset(&buffer, 0, sizeof(buffer)); |
1771 memset(planes, 0, sizeof(planes)); | 1760 memset(planes, 0, sizeof(planes)); |
1772 buffer.index = i; | 1761 buffer.index = i; |
1773 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1762 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1774 buffer.memory = V4L2_MEMORY_MMAP; | 1763 buffer.memory = V4L2_MEMORY_MMAP; |
1775 buffer.m.planes = planes; | 1764 buffer.m.planes = planes; |
1776 buffer.length = 1; | 1765 buffer.length = 1; |
1777 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); | 1766 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); |
1778 void* address = device_->Mmap(NULL, | 1767 void* address = |
1779 buffer.m.planes[0].length, | 1768 device_->Mmap(NULL, buffer.m.planes[0].length, PROT_READ | PROT_WRITE, |
1780 PROT_READ | PROT_WRITE, | 1769 MAP_SHARED, buffer.m.planes[0].m.mem_offset); |
1781 MAP_SHARED, | |
1782 buffer.m.planes[0].m.mem_offset); | |
1783 if (address == MAP_FAILED) { | 1770 if (address == MAP_FAILED) { |
1784 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; | 1771 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; |
1785 return false; | 1772 return false; |
1786 } | 1773 } |
1787 input_buffer_map_[i].address = address; | 1774 input_buffer_map_[i].address = address; |
1788 input_buffer_map_[i].length = buffer.m.planes[0].length; | 1775 input_buffer_map_[i].length = buffer.m.planes[0].length; |
1789 } | 1776 } |
1790 | 1777 |
1791 return true; | 1778 return true; |
1792 } | 1779 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1986 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 1973 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1987 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | 1974 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; |
1988 | 1975 |
1989 if (!DestroyOutputBuffers()) { | 1976 if (!DestroyOutputBuffers()) { |
1990 LOG(ERROR) << __func__ << " Failed destroying output buffers."; | 1977 LOG(ERROR) << __func__ << " Failed destroying output buffers."; |
1991 NOTIFY_ERROR(PLATFORM_FAILURE); | 1978 NOTIFY_ERROR(PLATFORM_FAILURE); |
1992 return; | 1979 return; |
1993 } | 1980 } |
1994 | 1981 |
1995 // Finish resolution change on decoder thread. | 1982 // Finish resolution change on decoder thread. |
1996 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1983 decoder_thread_.message_loop()->PostTask( |
1997 &V4L2VideoDecodeAccelerator::FinishResolutionChange, | 1984 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::FinishResolutionChange, |
1998 base::Unretained(this))); | 1985 base::Unretained(this))); |
1999 } | 1986 } |
2000 | 1987 |
2001 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 1988 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
2002 DVLOG(3) << "SendPictureReady()"; | 1989 DVLOG(3) << "SendPictureReady()"; |
2003 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1990 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2004 bool resetting_or_flushing = | 1991 bool resetting_or_flushing = |
2005 (decoder_state_ == kResetting || decoder_flushing_); | 1992 (decoder_state_ == kResetting || decoder_flushing_); |
2006 while (pending_picture_ready_.size() > 0) { | 1993 while (pending_picture_ready_.size() > 0) { |
2007 bool cleared = pending_picture_ready_.front().cleared; | 1994 bool cleared = pending_picture_ready_.front().cleared; |
2008 const media::Picture& picture = pending_picture_ready_.front().picture; | 1995 const media::Picture& picture = pending_picture_ready_.front().picture; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 } | 2029 } |
2043 | 2030 |
2044 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2031 void V4L2VideoDecodeAccelerator::PictureCleared() { |
2045 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2032 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
2046 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2033 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2047 DCHECK_GT(picture_clearing_count_, 0); | 2034 DCHECK_GT(picture_clearing_count_, 0); |
2048 picture_clearing_count_--; | 2035 picture_clearing_count_--; |
2049 SendPictureReady(); | 2036 SendPictureReady(); |
2050 } | 2037 } |
2051 | 2038 |
2052 } // namespace content | 2039 } // namespace media |
OLD | NEW |