| 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 |