| 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 <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
| 11 #include <sys/ioctl.h> | 11 #include <sys/ioctl.h> |
| 12 #include <sys/mman.h> | 12 #include <sys/mman.h> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/debug/trace_event.h" | 16 #include "base/debug/trace_event.h" |
| 17 #include "base/memory/shared_memory.h" | 17 #include "base/memory/shared_memory.h" |
| 18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 19 #include "base/message_loop/message_loop_proxy.h" | 19 #include "base/message_loop/message_loop_proxy.h" |
| 20 #include "base/numerics/safe_conversions.h" | 20 #include "base/numerics/safe_conversions.h" |
| 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
| 22 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
| 23 #include "media/filters/h264_parser.h" | 23 #include "media/filters/h264_parser.h" |
| 24 #include "ui/gl/scoped_binders.h" | 24 #include "ui/gl/scoped_binders.h" |
| 25 | 25 |
| 26 #define NOTIFY_ERROR(x) \ | 26 #define NOTIFY_ERROR(x) \ |
| 27 do { \ | 27 do { \ |
| 28 SetDecoderState(kError); \ | 28 SetDecoderState(kError); \ |
| 29 DLOG(ERROR) << "calling NotifyError(): " << x; \ | 29 LOG(ERROR) << "calling NotifyError(): " << x; \ |
| 30 NotifyError(x); \ | 30 NotifyError(x); \ |
| 31 } while (0) | 31 } while (0) |
| 32 | 32 |
| 33 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ | 33 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ |
| 34 do { \ | 34 do { \ |
| 35 if (device_->Ioctl(type, arg) != 0) { \ | 35 if (device_->Ioctl(type, arg) != 0) { \ |
| 36 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ | 36 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ |
| 37 NOTIFY_ERROR(PLATFORM_FAILURE); \ | 37 NOTIFY_ERROR(PLATFORM_FAILURE); \ |
| 38 return value; \ | 38 return value; \ |
| 39 } \ | 39 } \ |
| 40 } while (0) | 40 } while (0) |
| 41 | 41 |
| 42 #define IOCTL_OR_ERROR_RETURN(type, arg) \ | 42 #define IOCTL_OR_ERROR_RETURN(type, arg) \ |
| 43 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0)) | 43 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0)) |
| 44 | 44 |
| 45 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ | 45 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ |
| 46 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false) | 46 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false) |
| 47 | 47 |
| 48 #define IOCTL_OR_LOG_ERROR(type, arg) \ | 48 #define IOCTL_OR_LOG_ERROR(type, arg) \ |
| 49 do { \ | 49 do { \ |
| 50 if (device_->Ioctl(type, arg) != 0) \ | 50 if (device_->Ioctl(type, arg) != 0) \ |
| 51 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ | 51 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ |
| 52 } while (0) | 52 } while (0) |
| 53 | 53 |
| 54 namespace content { | 54 namespace content { |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| 57 | 57 |
| 58 // TODO(posciak): remove once we update linux-headers. | 58 // TODO(posciak): remove once we update linux-headers. |
| 59 #ifndef V4L2_EVENT_RESOLUTION_CHANGE | 59 #ifndef V4L2_EVENT_RESOLUTION_CHANGE |
| 60 #define V4L2_EVENT_RESOLUTION_CHANGE 5 | 60 #define V4L2_EVENT_RESOLUTION_CHANGE 5 |
| 61 #endif | 61 #endif |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 case media::VP8PROFILE_ANY: | 227 case media::VP8PROFILE_ANY: |
| 228 DVLOG(2) << "Initialize(): profile VP8PROFILE_ANY"; | 228 DVLOG(2) << "Initialize(): profile VP8PROFILE_ANY"; |
| 229 break; | 229 break; |
| 230 default: | 230 default: |
| 231 DLOG(ERROR) << "Initialize(): unsupported profile=" << profile; | 231 DLOG(ERROR) << "Initialize(): unsupported profile=" << profile; |
| 232 return false; | 232 return false; |
| 233 }; | 233 }; |
| 234 video_profile_ = profile; | 234 video_profile_ = profile; |
| 235 | 235 |
| 236 if (egl_display_ == EGL_NO_DISPLAY) { | 236 if (egl_display_ == EGL_NO_DISPLAY) { |
| 237 DLOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 237 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
| 238 NOTIFY_ERROR(PLATFORM_FAILURE); | 238 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| 241 | 241 |
| 242 // We need the context to be initialized to query extensions. | 242 // We need the context to be initialized to query extensions. |
| 243 if (!make_context_current_.Run()) { | 243 if (!make_context_current_.Run()) { |
| 244 DLOG(ERROR) << "Initialize(): could not make context current"; | 244 LOG(ERROR) << "Initialize(): could not make context current"; |
| 245 NOTIFY_ERROR(PLATFORM_FAILURE); | 245 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 246 return false; | 246 return false; |
| 247 } | 247 } |
| 248 | 248 |
| 249 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { | 249 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
| 250 DLOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; | 250 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; |
| 251 NOTIFY_ERROR(PLATFORM_FAILURE); | 251 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 252 return false; | 252 return false; |
| 253 } | 253 } |
| 254 | 254 |
| 255 // Capabilities check. | 255 // Capabilities check. |
| 256 struct v4l2_capability caps; | 256 struct v4l2_capability caps; |
| 257 const __u32 kCapsRequired = | 257 const __u32 kCapsRequired = |
| 258 V4L2_CAP_VIDEO_CAPTURE_MPLANE | | 258 V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
| 259 V4L2_CAP_VIDEO_OUTPUT_MPLANE | | 259 V4L2_CAP_VIDEO_OUTPUT_MPLANE | |
| 260 V4L2_CAP_STREAMING; | 260 V4L2_CAP_STREAMING; |
| 261 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 261 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 262 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 262 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 263 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" | 263 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
| 264 ", caps check failed: 0x" << std::hex << caps.capabilities; | 264 ", caps check failed: 0x" << std::hex << caps.capabilities; |
| 265 NOTIFY_ERROR(PLATFORM_FAILURE); | 265 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 266 return false; | 266 return false; |
| 267 } | 267 } |
| 268 | 268 |
| 269 if (!CreateInputBuffers()) | 269 if (!CreateInputBuffers()) |
| 270 return false; | 270 return false; |
| 271 | 271 |
| 272 // Output format has to be setup before streaming starts. | 272 // Output format has to be setup before streaming starts. |
| 273 struct v4l2_format format; | 273 struct v4l2_format format; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 288 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; | 288 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; |
| 289 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); | 289 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); |
| 290 | 290 |
| 291 // Initialize format-specific bits. | 291 // Initialize format-specific bits. |
| 292 if (video_profile_ >= media::H264PROFILE_MIN && | 292 if (video_profile_ >= media::H264PROFILE_MIN && |
| 293 video_profile_ <= media::H264PROFILE_MAX) { | 293 video_profile_ <= media::H264PROFILE_MAX) { |
| 294 decoder_h264_parser_.reset(new media::H264Parser()); | 294 decoder_h264_parser_.reset(new media::H264Parser()); |
| 295 } | 295 } |
| 296 | 296 |
| 297 if (!decoder_thread_.Start()) { | 297 if (!decoder_thread_.Start()) { |
| 298 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; | 298 LOG(ERROR) << "Initialize(): decoder thread failed to start"; |
| 299 NOTIFY_ERROR(PLATFORM_FAILURE); | 299 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 300 return false; | 300 return false; |
| 301 } | 301 } |
| 302 | 302 |
| 303 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. | 303 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. |
| 304 decoder_thread_.message_loop()->PostTask( | 304 decoder_thread_.message_loop()->PostTask( |
| 305 FROM_HERE, | 305 FROM_HERE, |
| 306 base::Bind( | 306 base::Bind( |
| 307 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 307 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), |
| 308 base::Unretained(this))); | 308 base::Unretained(this))); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 322 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 322 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), |
| 323 bitstream_buffer)); | 323 bitstream_buffer)); |
| 324 } | 324 } |
| 325 | 325 |
| 326 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( | 326 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
| 327 const std::vector<media::PictureBuffer>& buffers) { | 327 const std::vector<media::PictureBuffer>& buffers) { |
| 328 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 328 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
| 329 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 329 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 330 | 330 |
| 331 if (buffers.size() != output_buffer_map_.size()) { | 331 if (buffers.size() != output_buffer_map_.size()) { |
| 332 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 332 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
| 333 " buffers. (Got " << buffers.size() | 333 " buffers. (Got " << buffers.size() |
| 334 << ", requested " << output_buffer_map_.size() << ")"; | 334 << ", requested " << output_buffer_map_.size() << ")"; |
| 335 NOTIFY_ERROR(INVALID_ARGUMENT); | 335 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 336 return; | 336 return; |
| 337 } | 337 } |
| 338 | 338 |
| 339 if (!make_context_current_.Run()) { | 339 if (!make_context_current_.Run()) { |
| 340 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 340 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
| 341 NOTIFY_ERROR(PLATFORM_FAILURE); | 341 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 342 return; | 342 return; |
| 343 } | 343 } |
| 344 | 344 |
| 345 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 345 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
| 346 | 346 |
| 347 // It's safe to manipulate all the buffer state here, because the decoder | 347 // It's safe to manipulate all the buffer state here, because the decoder |
| 348 // thread is waiting on pictures_assigned_. | 348 // thread is waiting on pictures_assigned_. |
| 349 DCHECK(free_output_buffers_.empty()); | 349 DCHECK(free_output_buffers_.empty()); |
| 350 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 350 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 351 DCHECK(buffers[i].size() == frame_buffer_size_); | 351 DCHECK(buffers[i].size() == frame_buffer_size_); |
| 352 | 352 |
| 353 OutputRecord& output_record = output_buffer_map_[i]; | 353 OutputRecord& output_record = output_buffer_map_[i]; |
| 354 DCHECK(!output_record.at_device); | 354 DCHECK(!output_record.at_device); |
| 355 DCHECK(!output_record.at_client); | 355 DCHECK(!output_record.at_client); |
| 356 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 356 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 357 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 357 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 358 DCHECK_EQ(output_record.picture_id, -1); | 358 DCHECK_EQ(output_record.picture_id, -1); |
| 359 DCHECK_EQ(output_record.cleared, false); | 359 DCHECK_EQ(output_record.cleared, false); |
| 360 | 360 |
| 361 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, | 361 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
| 362 egl_context_, | 362 egl_context_, |
| 363 buffers[i].texture_id(), | 363 buffers[i].texture_id(), |
| 364 frame_buffer_size_, | 364 frame_buffer_size_, |
| 365 i, | 365 i, |
| 366 output_planes_count_); | 366 output_planes_count_); |
| 367 if (egl_image == EGL_NO_IMAGE_KHR) { | 367 if (egl_image == EGL_NO_IMAGE_KHR) { |
| 368 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 368 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
| 369 // Ownership of EGLImages allocated in previous iterations of this loop | 369 // Ownership of EGLImages allocated in previous iterations of this loop |
| 370 // has been transferred to output_buffer_map_. After we error-out here | 370 // has been transferred to output_buffer_map_. After we error-out here |
| 371 // the destructor will handle their cleanup. | 371 // the destructor will handle their cleanup. |
| 372 NOTIFY_ERROR(PLATFORM_FAILURE); | 372 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 373 return; | 373 return; |
| 374 } | 374 } |
| 375 | 375 |
| 376 output_record.egl_image = egl_image; | 376 output_record.egl_image = egl_image; |
| 377 output_record.picture_id = buffers[i].id(); | 377 output_record.picture_id = buffers[i].id(); |
| 378 free_output_buffers_.push(i); | 378 free_output_buffers_.push(i); |
| 379 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i | 379 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i |
| 380 << "]: picture_id=" << output_record.picture_id; | 380 << "]: picture_id=" << output_record.picture_id; |
| 381 } | 381 } |
| 382 | 382 |
| 383 pictures_assigned_.Signal(); | 383 pictures_assigned_.Signal(); |
| 384 } | 384 } |
| 385 | 385 |
| 386 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 386 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
| 387 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 387 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
| 388 // Must be run on child thread, as we'll insert a sync in the EGL context. | 388 // Must be run on child thread, as we'll insert a sync in the EGL context. |
| 389 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 389 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 390 | 390 |
| 391 if (!make_context_current_.Run()) { | 391 if (!make_context_current_.Run()) { |
| 392 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 392 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
| 393 NOTIFY_ERROR(PLATFORM_FAILURE); | 393 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 394 return; | 394 return; |
| 395 } | 395 } |
| 396 | 396 |
| 397 EGLSyncKHR egl_sync = | 397 EGLSyncKHR egl_sync = |
| 398 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 398 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
| 399 if (egl_sync == EGL_NO_SYNC_KHR) { | 399 if (egl_sync == EGL_NO_SYNC_KHR) { |
| 400 DLOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; | 400 LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; |
| 401 NOTIFY_ERROR(PLATFORM_FAILURE); | 401 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 402 return; | 402 return; |
| 403 } | 403 } |
| 404 | 404 |
| 405 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( | 405 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( |
| 406 egl_display_, egl_sync)); | 406 egl_display_, egl_sync)); |
| 407 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 407 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 408 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, | 408 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, |
| 409 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); | 409 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); |
| 410 } | 410 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 457 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 458 DCHECK_NE(decoder_state_, kUninitialized); | 458 DCHECK_NE(decoder_state_, kUninitialized); |
| 459 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 459 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
| 460 bitstream_buffer.id()); | 460 bitstream_buffer.id()); |
| 461 | 461 |
| 462 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 462 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 463 io_client_, io_message_loop_proxy_, | 463 io_client_, io_message_loop_proxy_, |
| 464 new base::SharedMemory(bitstream_buffer.handle(), true), | 464 new base::SharedMemory(bitstream_buffer.handle(), true), |
| 465 bitstream_buffer.size(), bitstream_buffer.id())); | 465 bitstream_buffer.size(), bitstream_buffer.id())); |
| 466 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | 466 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { |
| 467 DLOG(ERROR) << "Decode(): could not map bitstream_buffer"; | 467 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; |
| 468 NOTIFY_ERROR(UNREADABLE_INPUT); | 468 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 469 return; | 469 return; |
| 470 } | 470 } |
| 471 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); | 471 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); |
| 472 | 472 |
| 473 if (decoder_state_ == kResetting || decoder_flushing_) { | 473 if (decoder_state_ == kResetting || decoder_flushing_) { |
| 474 // In the case that we're resetting or flushing, we need to delay decoding | 474 // In the case that we're resetting or flushing, we need to delay decoding |
| 475 // the BitstreamBuffers that come after the Reset() or Flush() call. When | 475 // the BitstreamBuffers that come after the Reset() or Flush() call. When |
| 476 // we're here, we know that this DecodeTask() was scheduled by a Decode() | 476 // we're here, we know that this DecodeTask() was scheduled by a Decode() |
| 477 // call that came after (in the client thread) the Reset() or Flush() call; | 477 // call that came after (in the client thread) the Reset() or Flush() call; |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 // Drain the pipe of completed decode buffers. | 957 // Drain the pipe of completed decode buffers. |
| 958 const int old_inputs_queued = input_buffer_queued_count_; | 958 const int old_inputs_queued = input_buffer_queued_count_; |
| 959 while (!input_ready_queue_.empty()) { | 959 while (!input_ready_queue_.empty()) { |
| 960 if (!EnqueueInputRecord()) | 960 if (!EnqueueInputRecord()) |
| 961 return; | 961 return; |
| 962 } | 962 } |
| 963 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) { | 963 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) { |
| 964 // We just started up a previously empty queue. | 964 // We just started up a previously empty queue. |
| 965 // Queue state changed; signal interrupt. | 965 // Queue state changed; signal interrupt. |
| 966 if (!device_->SetDevicePollInterrupt()) { | 966 if (!device_->SetDevicePollInterrupt()) { |
| 967 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; | 967 PLOG(ERROR) << "SetDevicePollInterrupt(): failed"; |
| 968 NOTIFY_ERROR(PLATFORM_FAILURE); | 968 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 969 return; | 969 return; |
| 970 } | 970 } |
| 971 // Start VIDIOC_STREAMON if we haven't yet. | 971 // Start VIDIOC_STREAMON if we haven't yet. |
| 972 if (!input_streamon_) { | 972 if (!input_streamon_) { |
| 973 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 973 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 974 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); | 974 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); |
| 975 input_streamon_ = true; | 975 input_streamon_ = true; |
| 976 } | 976 } |
| 977 } | 977 } |
| 978 | 978 |
| 979 // Enqueue all the outputs we can. | 979 // Enqueue all the outputs we can. |
| 980 const int old_outputs_queued = output_buffer_queued_count_; | 980 const int old_outputs_queued = output_buffer_queued_count_; |
| 981 while (!free_output_buffers_.empty()) { | 981 while (!free_output_buffers_.empty()) { |
| 982 if (!EnqueueOutputRecord()) | 982 if (!EnqueueOutputRecord()) |
| 983 return; | 983 return; |
| 984 } | 984 } |
| 985 if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) { | 985 if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) { |
| 986 // We just started up a previously empty queue. | 986 // We just started up a previously empty queue. |
| 987 // Queue state changed; signal interrupt. | 987 // Queue state changed; signal interrupt. |
| 988 if (!device_->SetDevicePollInterrupt()) { | 988 if (!device_->SetDevicePollInterrupt()) { |
| 989 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; | 989 PLOG(ERROR) << "SetDevicePollInterrupt(): failed"; |
| 990 NOTIFY_ERROR(PLATFORM_FAILURE); | 990 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 991 return; | 991 return; |
| 992 } | 992 } |
| 993 // Start VIDIOC_STREAMON if we haven't yet. | 993 // Start VIDIOC_STREAMON if we haven't yet. |
| 994 if (!output_streamon_) { | 994 if (!output_streamon_) { |
| 995 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 995 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 996 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); | 996 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); |
| 997 output_streamon_ = true; | 997 output_streamon_ = true; |
| 998 } | 998 } |
| 999 } | 999 } |
| 1000 } | 1000 } |
| 1001 | 1001 |
| 1002 void V4L2VideoDecodeAccelerator::DequeueEvents() { | 1002 void V4L2VideoDecodeAccelerator::DequeueEvents() { |
| 1003 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1003 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1004 DCHECK_NE(decoder_state_, kUninitialized); | 1004 DCHECK_NE(decoder_state_, kUninitialized); |
| 1005 DVLOG(3) << "DequeueEvents()"; | 1005 DVLOG(3) << "DequeueEvents()"; |
| 1006 | 1006 |
| 1007 struct v4l2_event ev; | 1007 struct v4l2_event ev; |
| 1008 memset(&ev, 0, sizeof(ev)); | 1008 memset(&ev, 0, sizeof(ev)); |
| 1009 | 1009 |
| 1010 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { | 1010 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { |
| 1011 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { | 1011 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { |
| 1012 DVLOG(3) << "DequeueEvents(): got resolution change event."; | 1012 DVLOG(3) << "DequeueEvents(): got resolution change event."; |
| 1013 DCHECK(!resolution_change_pending_); | 1013 DCHECK(!resolution_change_pending_); |
| 1014 resolution_change_pending_ = IsResolutionChangeNecessary(); | 1014 resolution_change_pending_ = IsResolutionChangeNecessary(); |
| 1015 } else { | 1015 } else { |
| 1016 DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type | 1016 LOG(ERROR) << "DequeueEvents(): got an event (" << ev.type |
| 1017 << ") we haven't subscribed to."; | 1017 << ") we haven't subscribed to."; |
| 1018 } | 1018 } |
| 1019 } | 1019 } |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 void V4L2VideoDecodeAccelerator::Dequeue() { | 1022 void V4L2VideoDecodeAccelerator::Dequeue() { |
| 1023 DVLOG(3) << "Dequeue()"; | 1023 DVLOG(3) << "Dequeue()"; |
| 1024 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1024 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1025 DCHECK_NE(decoder_state_, kUninitialized); | 1025 DCHECK_NE(decoder_state_, kUninitialized); |
| 1026 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); | 1026 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); |
| 1027 | 1027 |
| 1028 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free | 1028 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free |
| 1029 // list. | 1029 // list. |
| 1030 while (input_buffer_queued_count_ > 0) { | 1030 while (input_buffer_queued_count_ > 0) { |
| 1031 DCHECK(input_streamon_); | 1031 DCHECK(input_streamon_); |
| 1032 struct v4l2_buffer dqbuf; | 1032 struct v4l2_buffer dqbuf; |
| 1033 struct v4l2_plane planes[1]; | 1033 struct v4l2_plane planes[1]; |
| 1034 memset(&dqbuf, 0, sizeof(dqbuf)); | 1034 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 1035 memset(planes, 0, sizeof(planes)); | 1035 memset(planes, 0, sizeof(planes)); |
| 1036 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1036 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1037 dqbuf.memory = V4L2_MEMORY_MMAP; | 1037 dqbuf.memory = V4L2_MEMORY_MMAP; |
| 1038 dqbuf.m.planes = planes; | 1038 dqbuf.m.planes = planes; |
| 1039 dqbuf.length = 1; | 1039 dqbuf.length = 1; |
| 1040 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { | 1040 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1041 if (errno == EAGAIN) { | 1041 if (errno == EAGAIN) { |
| 1042 // EAGAIN if we're just out of buffers to dequeue. | 1042 // EAGAIN if we're just out of buffers to dequeue. |
| 1043 break; | 1043 break; |
| 1044 } | 1044 } |
| 1045 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; | 1045 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; |
| 1046 NOTIFY_ERROR(PLATFORM_FAILURE); | 1046 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1047 return; | 1047 return; |
| 1048 } | 1048 } |
| 1049 InputRecord& input_record = input_buffer_map_[dqbuf.index]; | 1049 InputRecord& input_record = input_buffer_map_[dqbuf.index]; |
| 1050 DCHECK(input_record.at_device); | 1050 DCHECK(input_record.at_device); |
| 1051 free_input_buffers_.push_back(dqbuf.index); | 1051 free_input_buffers_.push_back(dqbuf.index); |
| 1052 input_record.at_device = false; | 1052 input_record.at_device = false; |
| 1053 input_record.bytes_used = 0; | 1053 input_record.bytes_used = 0; |
| 1054 input_record.input_id = -1; | 1054 input_record.input_id = -1; |
| 1055 input_buffer_queued_count_--; | 1055 input_buffer_queued_count_--; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1066 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); | 1066 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); |
| 1067 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1067 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1068 dqbuf.memory = V4L2_MEMORY_MMAP; | 1068 dqbuf.memory = V4L2_MEMORY_MMAP; |
| 1069 dqbuf.m.planes = planes.get(); | 1069 dqbuf.m.planes = planes.get(); |
| 1070 dqbuf.length = output_planes_count_; | 1070 dqbuf.length = output_planes_count_; |
| 1071 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { | 1071 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1072 if (errno == EAGAIN) { | 1072 if (errno == EAGAIN) { |
| 1073 // EAGAIN if we're just out of buffers to dequeue. | 1073 // EAGAIN if we're just out of buffers to dequeue. |
| 1074 break; | 1074 break; |
| 1075 } | 1075 } |
| 1076 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; | 1076 PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; |
| 1077 NOTIFY_ERROR(PLATFORM_FAILURE); | 1077 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1078 return; | 1078 return; |
| 1079 } | 1079 } |
| 1080 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; | 1080 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; |
| 1081 DCHECK(output_record.at_device); | 1081 DCHECK(output_record.at_device); |
| 1082 DCHECK(!output_record.at_client); | 1082 DCHECK(!output_record.at_client); |
| 1083 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | 1083 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 1084 DCHECK_NE(output_record.picture_id, -1); | 1084 DCHECK_NE(output_record.picture_id, -1); |
| 1085 output_record.at_device = false; | 1085 output_record.at_device = false; |
| 1086 if (dqbuf.m.planes[0].bytesused + dqbuf.m.planes[1].bytesused == 0) { | 1086 if (dqbuf.m.planes[0].bytesused + dqbuf.m.planes[1].bytesused == 0) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 "V4L2VDA::EnqueueOutputRecord: eglClientWaitSyncKHR"); | 1151 "V4L2VDA::EnqueueOutputRecord: eglClientWaitSyncKHR"); |
| 1152 // If we have to wait for completion, wait. Note that | 1152 // If we have to wait for completion, wait. Note that |
| 1153 // free_output_buffers_ is a FIFO queue, so we always wait on the | 1153 // free_output_buffers_ is a FIFO queue, so we always wait on the |
| 1154 // buffer that has been in the queue the longest. | 1154 // buffer that has been in the queue the longest. |
| 1155 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, | 1155 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, |
| 1156 EGL_FOREVER_KHR) == EGL_FALSE) { | 1156 EGL_FOREVER_KHR) == EGL_FALSE) { |
| 1157 // This will cause tearing, but is safe otherwise. | 1157 // This will cause tearing, but is safe otherwise. |
| 1158 DVLOG(1) << __func__ << " eglClientWaitSyncKHR failed!"; | 1158 DVLOG(1) << __func__ << " eglClientWaitSyncKHR failed!"; |
| 1159 } | 1159 } |
| 1160 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { | 1160 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { |
| 1161 DLOG(FATAL) << __func__ << " eglDestroySyncKHR failed!"; | 1161 LOG(ERROR) << __func__ << " eglDestroySyncKHR failed!"; |
| 1162 NOTIFY_ERROR(PLATFORM_FAILURE); | 1162 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1163 return false; | 1163 return false; |
| 1164 } | 1164 } |
| 1165 output_record.egl_sync = EGL_NO_SYNC_KHR; | 1165 output_record.egl_sync = EGL_NO_SYNC_KHR; |
| 1166 } | 1166 } |
| 1167 struct v4l2_buffer qbuf; | 1167 struct v4l2_buffer qbuf; |
| 1168 scoped_ptr<struct v4l2_plane[]> qbuf_planes( | 1168 scoped_ptr<struct v4l2_plane[]> qbuf_planes( |
| 1169 new v4l2_plane[output_planes_count_]); | 1169 new v4l2_plane[output_planes_count_]); |
| 1170 memset(&qbuf, 0, sizeof(qbuf)); | 1170 memset(&qbuf, 0, sizeof(qbuf)); |
| 1171 memset( | 1171 memset( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 // posted to us by the client. In that case just ignore this (we've already | 1211 // posted to us by the client. In that case just ignore this (we've already |
| 1212 // dismissed it and accounted for that) and let the sync object get | 1212 // dismissed it and accounted for that) and let the sync object get |
| 1213 // destroyed. | 1213 // destroyed. |
| 1214 DVLOG(4) << "ReusePictureBufferTask(): got picture id= " | 1214 DVLOG(4) << "ReusePictureBufferTask(): got picture id= " |
| 1215 << picture_buffer_id << " not in use (anymore?)."; | 1215 << picture_buffer_id << " not in use (anymore?)."; |
| 1216 return; | 1216 return; |
| 1217 } | 1217 } |
| 1218 | 1218 |
| 1219 OutputRecord& output_record = output_buffer_map_[index]; | 1219 OutputRecord& output_record = output_buffer_map_[index]; |
| 1220 if (output_record.at_device || !output_record.at_client) { | 1220 if (output_record.at_device || !output_record.at_client) { |
| 1221 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable"; | 1221 LOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable"; |
| 1222 NOTIFY_ERROR(INVALID_ARGUMENT); | 1222 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 1223 return; | 1223 return; |
| 1224 } | 1224 } |
| 1225 | 1225 |
| 1226 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1226 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1227 DCHECK(!output_record.at_device); | 1227 DCHECK(!output_record.at_device); |
| 1228 output_record.at_client = false; | 1228 output_record.at_client = false; |
| 1229 output_record.egl_sync = egl_sync_ref->egl_sync; | 1229 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1230 free_output_buffers_.push(index); | 1230 free_output_buffers_.push(index); |
| 1231 decoder_frames_at_client_--; | 1231 decoder_frames_at_client_--; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 decoder_state_ = kError; | 1417 decoder_state_ = kError; |
| 1418 } | 1418 } |
| 1419 | 1419 |
| 1420 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { | 1420 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { |
| 1421 DVLOG(3) << "StartDevicePoll()"; | 1421 DVLOG(3) << "StartDevicePoll()"; |
| 1422 DCHECK(!device_poll_thread_.IsRunning()); | 1422 DCHECK(!device_poll_thread_.IsRunning()); |
| 1423 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1423 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1424 | 1424 |
| 1425 // Start up the device poll thread and schedule its first DevicePollTask(). | 1425 // Start up the device poll thread and schedule its first DevicePollTask(). |
| 1426 if (!device_poll_thread_.Start()) { | 1426 if (!device_poll_thread_.Start()) { |
| 1427 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 1427 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
| 1428 NOTIFY_ERROR(PLATFORM_FAILURE); | 1428 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1429 return false; | 1429 return false; |
| 1430 } | 1430 } |
| 1431 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1431 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1432 &V4L2VideoDecodeAccelerator::DevicePollTask, | 1432 &V4L2VideoDecodeAccelerator::DevicePollTask, |
| 1433 base::Unretained(this), | 1433 base::Unretained(this), |
| 1434 0)); | 1434 0)); |
| 1435 | 1435 |
| 1436 return true; | 1436 return true; |
| 1437 } | 1437 } |
| 1438 | 1438 |
| 1439 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { | 1439 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { |
| 1440 DVLOG(3) << "StopDevicePoll()"; | 1440 DVLOG(3) << "StopDevicePoll()"; |
| 1441 if (decoder_thread_.IsRunning()) | 1441 if (decoder_thread_.IsRunning()) |
| 1442 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1442 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1443 | 1443 |
| 1444 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 1444 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
| 1445 if (!device_->SetDevicePollInterrupt()) { | 1445 if (!device_->SetDevicePollInterrupt()) { |
| 1446 DPLOG(ERROR) << "SetDevicePollInterrupt(): failed"; | 1446 PLOG(ERROR) << "SetDevicePollInterrupt(): failed"; |
| 1447 NOTIFY_ERROR(PLATFORM_FAILURE); | 1447 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1448 return false; | 1448 return false; |
| 1449 } | 1449 } |
| 1450 device_poll_thread_.Stop(); | 1450 device_poll_thread_.Stop(); |
| 1451 // Clear the interrupt now, to be sure. | 1451 // Clear the interrupt now, to be sure. |
| 1452 if (!device_->ClearDevicePollInterrupt()) { | 1452 if (!device_->ClearDevicePollInterrupt()) { |
| 1453 NOTIFY_ERROR(PLATFORM_FAILURE); | 1453 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1454 return false; | 1454 return false; |
| 1455 } | 1455 } |
| 1456 | 1456 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 | 1537 |
| 1538 if (decoder_state_ == kError) { | 1538 if (decoder_state_ == kError) { |
| 1539 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; | 1539 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; |
| 1540 return; | 1540 return; |
| 1541 } | 1541 } |
| 1542 | 1542 |
| 1543 struct v4l2_format format; | 1543 struct v4l2_format format; |
| 1544 bool again; | 1544 bool again; |
| 1545 bool ret = GetFormatInfo(&format, &again); | 1545 bool ret = GetFormatInfo(&format, &again); |
| 1546 if (!ret || again) { | 1546 if (!ret || again) { |
| 1547 DVLOG(3) << "Couldn't get format information after resolution change"; | 1547 LOG(ERROR) << "Couldn't get format information after resolution change"; |
| 1548 NOTIFY_ERROR(PLATFORM_FAILURE); | 1548 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1549 return; | 1549 return; |
| 1550 } | 1550 } |
| 1551 | 1551 |
| 1552 if (!CreateBuffersForFormat(format)) { | 1552 if (!CreateBuffersForFormat(format)) { |
| 1553 DVLOG(3) << "Couldn't reallocate buffers after resolution change"; | 1553 LOG(ERROR) << "Couldn't reallocate buffers after resolution change"; |
| 1554 NOTIFY_ERROR(PLATFORM_FAILURE); | 1554 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1555 return; | 1555 return; |
| 1556 } | 1556 } |
| 1557 | 1557 |
| 1558 decoder_state_ = kDecoding; | 1558 decoder_state_ = kDecoding; |
| 1559 | 1559 |
| 1560 if (resolution_change_reset_pending_) { | 1560 if (resolution_change_reset_pending_) { |
| 1561 resolution_change_reset_pending_ = false; | 1561 resolution_change_reset_pending_ = false; |
| 1562 ResetTask(); | 1562 ResetTask(); |
| 1563 return; | 1563 return; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 | 1625 |
| 1626 *again = false; | 1626 *again = false; |
| 1627 memset(format, 0, sizeof(*format)); | 1627 memset(format, 0, sizeof(*format)); |
| 1628 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1628 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1629 if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { | 1629 if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { |
| 1630 if (errno == EINVAL) { | 1630 if (errno == EINVAL) { |
| 1631 // EINVAL means we haven't seen sufficient stream to decode the format. | 1631 // EINVAL means we haven't seen sufficient stream to decode the format. |
| 1632 *again = true; | 1632 *again = true; |
| 1633 return true; | 1633 return true; |
| 1634 } else { | 1634 } else { |
| 1635 DPLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT"; | 1635 PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT"; |
| 1636 NOTIFY_ERROR(PLATFORM_FAILURE); | 1636 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1637 return false; | 1637 return false; |
| 1638 } | 1638 } |
| 1639 } | 1639 } |
| 1640 | 1640 |
| 1641 return true; | 1641 return true; |
| 1642 } | 1642 } |
| 1643 | 1643 |
| 1644 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( | 1644 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( |
| 1645 const struct v4l2_format& format) { | 1645 const struct v4l2_format& format) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1701 buffer.memory = V4L2_MEMORY_MMAP; | 1701 buffer.memory = V4L2_MEMORY_MMAP; |
| 1702 buffer.m.planes = planes; | 1702 buffer.m.planes = planes; |
| 1703 buffer.length = 1; | 1703 buffer.length = 1; |
| 1704 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); | 1704 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); |
| 1705 void* address = device_->Mmap(NULL, | 1705 void* address = device_->Mmap(NULL, |
| 1706 buffer.m.planes[0].length, | 1706 buffer.m.planes[0].length, |
| 1707 PROT_READ | PROT_WRITE, | 1707 PROT_READ | PROT_WRITE, |
| 1708 MAP_SHARED, | 1708 MAP_SHARED, |
| 1709 buffer.m.planes[0].m.mem_offset); | 1709 buffer.m.planes[0].m.mem_offset); |
| 1710 if (address == MAP_FAILED) { | 1710 if (address == MAP_FAILED) { |
| 1711 DPLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; | 1711 PLOG(ERROR) << "CreateInputBuffers(): mmap() failed"; |
| 1712 return false; | 1712 return false; |
| 1713 } | 1713 } |
| 1714 input_buffer_map_[i].address = address; | 1714 input_buffer_map_[i].address = address; |
| 1715 input_buffer_map_[i].length = buffer.m.planes[0].length; | 1715 input_buffer_map_[i].length = buffer.m.planes[0].length; |
| 1716 } | 1716 } |
| 1717 | 1717 |
| 1718 return true; | 1718 return true; |
| 1719 } | 1719 } |
| 1720 | 1720 |
| 1721 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { | 1721 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1828 base::Bind( | 1828 base::Bind( |
| 1829 &Client::DismissPictureBuffer, client_, output_record.picture_id)); | 1829 &Client::DismissPictureBuffer, client_, output_record.picture_id)); |
| 1830 } | 1830 } |
| 1831 | 1831 |
| 1832 struct v4l2_requestbuffers reqbufs; | 1832 struct v4l2_requestbuffers reqbufs; |
| 1833 memset(&reqbufs, 0, sizeof(reqbufs)); | 1833 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1834 reqbufs.count = 0; | 1834 reqbufs.count = 0; |
| 1835 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1835 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1836 reqbufs.memory = V4L2_MEMORY_MMAP; | 1836 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1837 if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) { | 1837 if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) { |
| 1838 DPLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; | 1838 PLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; |
| 1839 success = false; | 1839 success = false; |
| 1840 } | 1840 } |
| 1841 | 1841 |
| 1842 output_buffer_map_.clear(); | 1842 output_buffer_map_.clear(); |
| 1843 while (!free_output_buffers_.empty()) | 1843 while (!free_output_buffers_.empty()) |
| 1844 free_output_buffers_.pop(); | 1844 free_output_buffers_.pop(); |
| 1845 | 1845 |
| 1846 return success; | 1846 return success; |
| 1847 } | 1847 } |
| 1848 | 1848 |
| 1849 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { | 1849 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
| 1850 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1850 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1851 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | 1851 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; |
| 1852 | 1852 |
| 1853 if (!DestroyOutputBuffers()) { | 1853 if (!DestroyOutputBuffers()) { |
| 1854 DLOG(FATAL) << __func__ << " Failed destroying output buffers."; | 1854 LOG(ERROR) << __func__ << " Failed destroying output buffers."; |
| 1855 NOTIFY_ERROR(PLATFORM_FAILURE); | 1855 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1856 return; | 1856 return; |
| 1857 } | 1857 } |
| 1858 | 1858 |
| 1859 // Finish resolution change on decoder thread. | 1859 // Finish resolution change on decoder thread. |
| 1860 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1860 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1861 &V4L2VideoDecodeAccelerator::FinishResolutionChange, | 1861 &V4L2VideoDecodeAccelerator::FinishResolutionChange, |
| 1862 base::Unretained(this))); | 1862 base::Unretained(this))); |
| 1863 } | 1863 } |
| 1864 | 1864 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1934 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width), | 1934 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width), |
| 1935 base::checked_cast<int>(format.fmt.pix_mp.height)); | 1935 base::checked_cast<int>(format.fmt.pix_mp.height)); |
| 1936 if (frame_buffer_size_ != new_size) { | 1936 if (frame_buffer_size_ != new_size) { |
| 1937 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; | 1937 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; |
| 1938 return true; | 1938 return true; |
| 1939 } | 1939 } |
| 1940 return false; | 1940 return false; |
| 1941 } | 1941 } |
| 1942 | 1942 |
| 1943 } // namespace content | 1943 } // namespace content |
| OLD | NEW |