| 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 "content/common/gpu/media/v4l2_video_encode_accelerator.h" | 5 #include "media/gpu/v4l2_video_encode_accelerator.h" |
| 6 | 6 |
| 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 <utility> | 15 #include <utility> |
| 16 | 16 |
| 17 #include "base/callback.h" | 17 #include "base/callback.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/numerics/safe_conversions.h" | 20 #include "base/numerics/safe_conversions.h" |
| 21 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" |
| 22 #include "base/trace_event/trace_event.h" | 22 #include "base/trace_event/trace_event.h" |
| 23 #include "content/common/gpu/media/shared_memory_region.h" | |
| 24 #include "media/base/bind_to_current_loop.h" | 23 #include "media/base/bind_to_current_loop.h" |
| 25 #include "media/base/bitstream_buffer.h" | 24 #include "media/base/bitstream_buffer.h" |
| 25 #include "media/gpu/shared_memory_region.h" |
| 26 | 26 |
| 27 #define NOTIFY_ERROR(x) \ | 27 #define NOTIFY_ERROR(x) \ |
| 28 do { \ | 28 do { \ |
| 29 LOG(ERROR) << "Setting error state:" << x; \ | 29 LOG(ERROR) << "Setting error state:" << x; \ |
| 30 SetErrorState(x); \ | 30 SetErrorState(x); \ |
| 31 } while (0) | 31 } while (0) |
| 32 | 32 |
| 33 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ | 33 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ |
| 34 do { \ | 34 do { \ |
| 35 if (device_->Ioctl(type, arg) != 0) { \ | 35 if (device_->Ioctl(type, arg) != 0) { \ |
| 36 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \ | 36 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \ |
| 37 NOTIFY_ERROR(kPlatformFailureError); \ | 37 NOTIFY_ERROR(kPlatformFailureError); \ |
| 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), #type) | 43 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type) |
| 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, #type) | 46 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type) |
| 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 PLOG(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 media { |
| 55 | 55 |
| 56 struct V4L2VideoEncodeAccelerator::BitstreamBufferRef { | 56 struct V4L2VideoEncodeAccelerator::BitstreamBufferRef { |
| 57 BitstreamBufferRef(int32_t id, std::unique_ptr<SharedMemoryRegion> shm) | 57 BitstreamBufferRef(int32_t id, std::unique_ptr<SharedMemoryRegion> shm) |
| 58 : id(id), shm(std::move(shm)) {} | 58 : id(id), shm(std::move(shm)) {} |
| 59 const int32_t id; | 59 const int32_t id; |
| 60 const std::unique_ptr<SharedMemoryRegion> shm; | 60 const std::unique_ptr<SharedMemoryRegion> shm; |
| 61 }; | 61 }; |
| 62 | 62 |
| 63 V4L2VideoEncodeAccelerator::InputRecord::InputRecord() : at_device(false) { | 63 V4L2VideoEncodeAccelerator::InputRecord::InputRecord() : at_device(false) {} |
| 64 } | |
| 65 | 64 |
| 66 V4L2VideoEncodeAccelerator::InputRecord::~InputRecord() { | 65 V4L2VideoEncodeAccelerator::InputRecord::~InputRecord() {} |
| 67 } | |
| 68 | 66 |
| 69 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord() | 67 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord() |
| 70 : at_device(false), address(NULL), length(0) { | 68 : at_device(false), address(NULL), length(0) {} |
| 71 } | |
| 72 | 69 |
| 73 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() { | 70 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() {} |
| 74 } | |
| 75 | 71 |
| 76 V4L2VideoEncodeAccelerator::ImageProcessorInputRecord:: | 72 V4L2VideoEncodeAccelerator::ImageProcessorInputRecord:: |
| 77 ImageProcessorInputRecord() | 73 ImageProcessorInputRecord() |
| 78 : force_keyframe(false) {} | 74 : force_keyframe(false) {} |
| 79 | 75 |
| 80 V4L2VideoEncodeAccelerator::ImageProcessorInputRecord:: | 76 V4L2VideoEncodeAccelerator::ImageProcessorInputRecord:: |
| 81 ~ImageProcessorInputRecord() {} | 77 ~ImageProcessorInputRecord() {} |
| 82 | 78 |
| 83 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator( | 79 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator( |
| 84 const scoped_refptr<V4L2Device>& device) | 80 const scoped_refptr<V4L2Device>& device) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 | 125 |
| 130 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 126 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 131 DCHECK_EQ(encoder_state_, kUninitialized); | 127 DCHECK_EQ(encoder_state_, kUninitialized); |
| 132 | 128 |
| 133 struct v4l2_capability caps; | 129 struct v4l2_capability caps; |
| 134 memset(&caps, 0, sizeof(caps)); | 130 memset(&caps, 0, sizeof(caps)); |
| 135 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | 131 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
| 136 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 132 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 137 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 133 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 138 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " | 134 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " |
| 139 "caps check failed: 0x" << std::hex << caps.capabilities; | 135 "caps check failed: 0x" |
| 136 << std::hex << caps.capabilities; |
| 140 return false; | 137 return false; |
| 141 } | 138 } |
| 142 | 139 |
| 143 if (!SetFormats(input_format, output_profile)) { | 140 if (!SetFormats(input_format, output_profile)) { |
| 144 DLOG(ERROR) << "Failed setting up formats"; | 141 DLOG(ERROR) << "Failed setting up formats"; |
| 145 return false; | 142 return false; |
| 146 } | 143 } |
| 147 | 144 |
| 148 if (input_format != device_input_format_) { | 145 if (input_format != device_input_format_) { |
| 149 DVLOG(1) << "Input format not supported by the HW, will convert to " | 146 DVLOG(1) << "Input format not supported by the HW, will convert to " |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 base::Unretained(this), force_keyframe, | 239 base::Unretained(this), force_keyframe, |
| 243 frame->timestamp())); | 240 frame->timestamp())); |
| 244 } else { | 241 } else { |
| 245 ImageProcessorInputRecord record; | 242 ImageProcessorInputRecord record; |
| 246 record.frame = frame; | 243 record.frame = frame; |
| 247 record.force_keyframe = force_keyframe; | 244 record.force_keyframe = force_keyframe; |
| 248 image_processor_input_queue_.push(record); | 245 image_processor_input_queue_.push(record); |
| 249 } | 246 } |
| 250 } else { | 247 } else { |
| 251 encoder_thread_.message_loop()->PostTask( | 248 encoder_thread_.message_loop()->PostTask( |
| 252 FROM_HERE, | 249 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, |
| 253 base::Bind(&V4L2VideoEncodeAccelerator::EncodeTask, | 250 base::Unretained(this), frame, force_keyframe)); |
| 254 base::Unretained(this), | |
| 255 frame, | |
| 256 force_keyframe)); | |
| 257 } | 251 } |
| 258 } | 252 } |
| 259 | 253 |
| 260 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer( | 254 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer( |
| 261 const media::BitstreamBuffer& buffer) { | 255 const media::BitstreamBuffer& buffer) { |
| 262 DVLOG(3) << "UseOutputBitstreamBuffer(): id=" << buffer.id(); | 256 DVLOG(3) << "UseOutputBitstreamBuffer(): id=" << buffer.id(); |
| 263 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 257 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 264 | 258 |
| 265 if (buffer.size() < output_buffer_byte_size_) { | 259 if (buffer.size() < output_buffer_byte_size_) { |
| 266 NOTIFY_ERROR(kInvalidArgumentError); | 260 NOTIFY_ERROR(kInvalidArgumentError); |
| 267 return; | 261 return; |
| 268 } | 262 } |
| 269 | 263 |
| 270 std::unique_ptr<SharedMemoryRegion> shm( | 264 std::unique_ptr<SharedMemoryRegion> shm( |
| 271 new SharedMemoryRegion(buffer, false)); | 265 new SharedMemoryRegion(buffer, false)); |
| 272 if (!shm->Map()) { | 266 if (!shm->Map()) { |
| 273 NOTIFY_ERROR(kPlatformFailureError); | 267 NOTIFY_ERROR(kPlatformFailureError); |
| 274 return; | 268 return; |
| 275 } | 269 } |
| 276 | 270 |
| 277 std::unique_ptr<BitstreamBufferRef> buffer_ref( | 271 std::unique_ptr<BitstreamBufferRef> buffer_ref( |
| 278 new BitstreamBufferRef(buffer.id(), std::move(shm))); | 272 new BitstreamBufferRef(buffer.id(), std::move(shm))); |
| 279 encoder_thread_.message_loop()->PostTask( | 273 encoder_thread_.message_loop()->PostTask( |
| 280 FROM_HERE, | 274 FROM_HERE, |
| 281 base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 275 base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
| 282 base::Unretained(this), | 276 base::Unretained(this), base::Passed(&buffer_ref))); |
| 283 base::Passed(&buffer_ref))); | |
| 284 } | 277 } |
| 285 | 278 |
| 286 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange( | 279 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange( |
| 287 uint32_t bitrate, | 280 uint32_t bitrate, |
| 288 uint32_t framerate) { | 281 uint32_t framerate) { |
| 289 DVLOG(3) << "RequestEncodingParametersChange(): bitrate=" << bitrate | 282 DVLOG(3) << "RequestEncodingParametersChange(): bitrate=" << bitrate |
| 290 << ", framerate=" << framerate; | 283 << ", framerate=" << framerate; |
| 291 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 284 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 292 | 285 |
| 293 encoder_thread_.message_loop()->PostTask( | 286 encoder_thread_.message_loop()->PostTask( |
| 294 FROM_HERE, | 287 FROM_HERE, |
| 295 base::Bind( | 288 base::Bind( |
| 296 &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask, | 289 &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask, |
| 297 base::Unretained(this), | 290 base::Unretained(this), bitrate, framerate)); |
| 298 bitrate, | |
| 299 framerate)); | |
| 300 } | 291 } |
| 301 | 292 |
| 302 void V4L2VideoEncodeAccelerator::Destroy() { | 293 void V4L2VideoEncodeAccelerator::Destroy() { |
| 303 DVLOG(3) << "Destroy()"; | 294 DVLOG(3) << "Destroy()"; |
| 304 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 295 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 305 | 296 |
| 306 // We're destroying; cancel all callbacks. | 297 // We're destroying; cancel all callbacks. |
| 307 client_ptr_factory_.reset(); | 298 client_ptr_factory_.reset(); |
| 308 weak_this_ptr_factory_.InvalidateWeakPtrs(); | 299 weak_this_ptr_factory_.InvalidateWeakPtrs(); |
| 309 | 300 |
| 310 if (image_processor_.get()) | 301 if (image_processor_.get()) |
| 311 image_processor_.release()->Destroy(); | 302 image_processor_.release()->Destroy(); |
| 312 | 303 |
| 313 // If the encoder thread is running, destroy using posted task. | 304 // If the encoder thread is running, destroy using posted task. |
| 314 if (encoder_thread_.IsRunning()) { | 305 if (encoder_thread_.IsRunning()) { |
| 315 encoder_thread_.message_loop()->PostTask( | 306 encoder_thread_.message_loop()->PostTask( |
| 316 FROM_HERE, | 307 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::DestroyTask, |
| 317 base::Bind(&V4L2VideoEncodeAccelerator::DestroyTask, | 308 base::Unretained(this))); |
| 318 base::Unretained(this))); | |
| 319 // DestroyTask() will put the encoder into kError state and cause all tasks | 309 // DestroyTask() will put the encoder into kError state and cause all tasks |
| 320 // to no-op. | 310 // to no-op. |
| 321 encoder_thread_.Stop(); | 311 encoder_thread_.Stop(); |
| 322 } else { | 312 } else { |
| 323 // Otherwise, call the destroy task directly. | 313 // Otherwise, call the destroy task directly. |
| 324 DestroyTask(); | 314 DestroyTask(); |
| 325 } | 315 } |
| 326 | 316 |
| 327 // Set to kError state just in case. | 317 // Set to kError state just in case. |
| 328 encoder_state_ = kError; | 318 encoder_state_ = kError; |
| 329 | 319 |
| 330 delete this; | 320 delete this; |
| 331 } | 321 } |
| 332 | 322 |
| 333 media::VideoEncodeAccelerator::SupportedProfiles | 323 media::VideoEncodeAccelerator::SupportedProfiles |
| 334 V4L2VideoEncodeAccelerator::GetSupportedProfiles() { | 324 V4L2VideoEncodeAccelerator::GetSupportedProfiles() { |
| 335 SupportedProfiles profiles; | 325 SupportedProfiles profiles; |
| 336 SupportedProfile profile; | 326 SupportedProfile profile; |
| 337 profile.max_framerate_numerator = 30; | 327 profile.max_framerate_numerator = 30; |
| 338 profile.max_framerate_denominator = 1; | 328 profile.max_framerate_denominator = 1; |
| 339 | 329 |
| 340 gfx::Size min_resolution; | 330 gfx::Size min_resolution; |
| 341 v4l2_fmtdesc fmtdesc; | 331 v4l2_fmtdesc fmtdesc; |
| 342 memset(&fmtdesc, 0, sizeof(fmtdesc)); | 332 memset(&fmtdesc, 0, sizeof(fmtdesc)); |
| 343 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 333 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 344 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { | 334 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { |
| 345 device_->GetSupportedResolution(fmtdesc.pixelformat, | 335 device_->GetSupportedResolution(fmtdesc.pixelformat, &min_resolution, |
| 346 &min_resolution, &profile.max_resolution); | 336 &profile.max_resolution); |
| 347 switch (fmtdesc.pixelformat) { | 337 switch (fmtdesc.pixelformat) { |
| 348 case V4L2_PIX_FMT_H264: | 338 case V4L2_PIX_FMT_H264: |
| 349 profile.profile = media::H264PROFILE_MAIN; | 339 profile.profile = media::H264PROFILE_MAIN; |
| 350 profiles.push_back(profile); | 340 profiles.push_back(profile); |
| 351 break; | 341 break; |
| 352 case V4L2_PIX_FMT_VP8: | 342 case V4L2_PIX_FMT_VP8: |
| 353 profile.profile = media::VP8PROFILE_ANY; | 343 profile.profile = media::VP8PROFILE_ANY; |
| 354 profiles.push_back(profile); | 344 profiles.push_back(profile); |
| 355 break; | 345 break; |
| 356 case V4L2_PIX_FMT_VP9: | 346 case V4L2_PIX_FMT_VP9: |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 | 504 |
| 515 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), | 505 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), |
| 516 // so either: | 506 // so either: |
| 517 // * device_poll_thread_ is running normally | 507 // * device_poll_thread_ is running normally |
| 518 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down, | 508 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down, |
| 519 // in which case we're in kError state, and we should have early-outed | 509 // in which case we're in kError state, and we should have early-outed |
| 520 // already. | 510 // already. |
| 521 DCHECK(device_poll_thread_.message_loop()); | 511 DCHECK(device_poll_thread_.message_loop()); |
| 522 // Queue the DevicePollTask() now. | 512 // Queue the DevicePollTask() now. |
| 523 device_poll_thread_.message_loop()->PostTask( | 513 device_poll_thread_.message_loop()->PostTask( |
| 524 FROM_HERE, | 514 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, |
| 525 base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, | 515 base::Unretained(this), poll_device)); |
| 526 base::Unretained(this), | |
| 527 poll_device)); | |
| 528 | 516 |
| 529 DVLOG(2) << __func__ << ": buffer counts: ENC[" | 517 DVLOG(2) << __func__ << ": buffer counts: ENC[" << encoder_input_queue_.size() |
| 530 << encoder_input_queue_.size() << "] => DEVICE[" | 518 << "] => DEVICE[" << free_input_buffers_.size() << "+" |
| 531 << free_input_buffers_.size() << "+" | 519 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() |
| 532 << input_buffer_queued_count_ << "/" | 520 << "->" << free_output_buffers_.size() << "+" |
| 533 << input_buffer_map_.size() << "->" | 521 << output_buffer_queued_count_ << "/" << output_buffer_map_.size() |
| 534 << free_output_buffers_.size() << "+" | 522 << "] => OUT[" << encoder_output_queue_.size() << "]"; |
| 535 << output_buffer_queued_count_ << "/" | |
| 536 << output_buffer_map_.size() << "] => OUT[" | |
| 537 << encoder_output_queue_.size() << "]"; | |
| 538 } | 523 } |
| 539 | 524 |
| 540 void V4L2VideoEncodeAccelerator::Enqueue() { | 525 void V4L2VideoEncodeAccelerator::Enqueue() { |
| 541 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current()); | 526 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current()); |
| 542 | 527 |
| 543 DVLOG(3) << "Enqueue() " | 528 DVLOG(3) << "Enqueue() " |
| 544 << "free_input_buffers: " << free_input_buffers_.size() | 529 << "free_input_buffers: " << free_input_buffers_.size() |
| 545 << "input_queue: " << encoder_input_queue_.size(); | 530 << "input_queue: " << encoder_input_queue_.size(); |
| 546 | 531 |
| 547 // Enqueue all the inputs we can. | 532 // Enqueue all the inputs we can. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 memcpy(target_data + stream_header_size_, output_data, output_size); | 651 memcpy(target_data + stream_header_size_, output_data, output_size); |
| 667 output_size += stream_header_size_; | 652 output_size += stream_header_size_; |
| 668 } else { | 653 } else { |
| 669 memcpy(target_data, output_data, output_size); | 654 memcpy(target_data, output_data, output_size); |
| 670 } | 655 } |
| 671 } else { | 656 } else { |
| 672 memcpy(target_data, output_data, output_size); | 657 memcpy(target_data, output_data, output_size); |
| 673 } | 658 } |
| 674 | 659 |
| 675 DVLOG(3) << "Dequeue(): returning " | 660 DVLOG(3) << "Dequeue(): returning " |
| 676 "bitstream_buffer_id=" << output_record.buffer_ref->id | 661 "bitstream_buffer_id=" |
| 677 << ", size=" << output_size << ", key_frame=" << key_frame; | 662 << output_record.buffer_ref->id << ", size=" << output_size |
| 663 << ", key_frame=" << key_frame; |
| 678 child_task_runner_->PostTask( | 664 child_task_runner_->PostTask( |
| 679 FROM_HERE, | 665 FROM_HERE, |
| 680 base::Bind(&Client::BitstreamBufferReady, client_, | 666 base::Bind(&Client::BitstreamBufferReady, client_, |
| 681 output_record.buffer_ref->id, output_size, key_frame)); | 667 output_record.buffer_ref->id, output_size, key_frame)); |
| 682 output_record.at_device = false; | 668 output_record.at_device = false; |
| 683 output_record.buffer_ref.reset(); | 669 output_record.buffer_ref.reset(); |
| 684 free_output_buffers_.push_back(dqbuf.index); | 670 free_output_buffers_.push_back(dqbuf.index); |
| 685 output_buffer_queued_count_--; | 671 output_buffer_queued_count_--; |
| 686 } | 672 } |
| 687 } | 673 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 699 struct v4l2_buffer qbuf; | 685 struct v4l2_buffer qbuf; |
| 700 struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES]; | 686 struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES]; |
| 701 memset(&qbuf, 0, sizeof(qbuf)); | 687 memset(&qbuf, 0, sizeof(qbuf)); |
| 702 memset(qbuf_planes, 0, sizeof(qbuf_planes)); | 688 memset(qbuf_planes, 0, sizeof(qbuf_planes)); |
| 703 qbuf.index = index; | 689 qbuf.index = index; |
| 704 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 690 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 705 qbuf.m.planes = qbuf_planes; | 691 qbuf.m.planes = qbuf_planes; |
| 706 | 692 |
| 707 DCHECK_EQ(device_input_format_, frame->format()); | 693 DCHECK_EQ(device_input_format_, frame->format()); |
| 708 for (size_t i = 0; i < input_planes_count_; ++i) { | 694 for (size_t i = 0; i < input_planes_count_; ++i) { |
| 709 qbuf.m.planes[i].bytesused = | 695 qbuf.m.planes[i].bytesused = base::checked_cast<__u32>( |
| 710 base::checked_cast<__u32>(media::VideoFrame::PlaneSize( | 696 media::VideoFrame::PlaneSize(frame->format(), i, input_allocated_size_) |
| 711 frame->format(), i, input_allocated_size_).GetArea()); | 697 .GetArea()); |
| 712 | 698 |
| 713 switch (input_memory_type_) { | 699 switch (input_memory_type_) { |
| 714 case V4L2_MEMORY_USERPTR: | 700 case V4L2_MEMORY_USERPTR: |
| 715 qbuf.m.planes[i].length = qbuf.m.planes[i].bytesused; | 701 qbuf.m.planes[i].length = qbuf.m.planes[i].bytesused; |
| 716 qbuf.m.planes[i].m.userptr = | 702 qbuf.m.planes[i].m.userptr = |
| 717 reinterpret_cast<unsigned long>(frame->data(i)); | 703 reinterpret_cast<unsigned long>(frame->data(i)); |
| 718 DCHECK(qbuf.m.planes[i].m.userptr); | 704 DCHECK(qbuf.m.planes[i].m.userptr); |
| 719 break; | 705 break; |
| 720 | 706 |
| 721 case V4L2_MEMORY_DMABUF: | 707 case V4L2_MEMORY_DMABUF: |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 | 763 |
| 778 // Start up the device poll thread and schedule its first DevicePollTask(). | 764 // Start up the device poll thread and schedule its first DevicePollTask(). |
| 779 if (!device_poll_thread_.Start()) { | 765 if (!device_poll_thread_.Start()) { |
| 780 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 766 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
| 781 NOTIFY_ERROR(kPlatformFailureError); | 767 NOTIFY_ERROR(kPlatformFailureError); |
| 782 return false; | 768 return false; |
| 783 } | 769 } |
| 784 // Enqueue a poll task with no devices to poll on -- it will wait only on the | 770 // Enqueue a poll task with no devices to poll on -- it will wait only on the |
| 785 // interrupt fd. | 771 // interrupt fd. |
| 786 device_poll_thread_.message_loop()->PostTask( | 772 device_poll_thread_.message_loop()->PostTask( |
| 787 FROM_HERE, | 773 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, |
| 788 base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, | 774 base::Unretained(this), false)); |
| 789 base::Unretained(this), | |
| 790 false)); | |
| 791 | 775 |
| 792 return true; | 776 return true; |
| 793 } | 777 } |
| 794 | 778 |
| 795 bool V4L2VideoEncodeAccelerator::StopDevicePoll() { | 779 bool V4L2VideoEncodeAccelerator::StopDevicePoll() { |
| 796 DVLOG(3) << "StopDevicePoll()"; | 780 DVLOG(3) << "StopDevicePoll()"; |
| 797 | 781 |
| 798 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 782 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
| 799 if (!device_->SetDevicePollInterrupt()) | 783 if (!device_->SetDevicePollInterrupt()) |
| 800 return false; | 784 return false; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 | 832 |
| 849 bool event_pending; | 833 bool event_pending; |
| 850 if (!device_->Poll(poll_device, &event_pending)) { | 834 if (!device_->Poll(poll_device, &event_pending)) { |
| 851 NOTIFY_ERROR(kPlatformFailureError); | 835 NOTIFY_ERROR(kPlatformFailureError); |
| 852 return; | 836 return; |
| 853 } | 837 } |
| 854 | 838 |
| 855 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 839 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
| 856 // touch encoder state from this thread. | 840 // touch encoder state from this thread. |
| 857 encoder_thread_.message_loop()->PostTask( | 841 encoder_thread_.message_loop()->PostTask( |
| 858 FROM_HERE, | 842 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::ServiceDeviceTask, |
| 859 base::Bind(&V4L2VideoEncodeAccelerator::ServiceDeviceTask, | 843 base::Unretained(this))); |
| 860 base::Unretained(this))); | |
| 861 } | 844 } |
| 862 | 845 |
| 863 void V4L2VideoEncodeAccelerator::NotifyError(Error error) { | 846 void V4L2VideoEncodeAccelerator::NotifyError(Error error) { |
| 864 DVLOG(1) << "NotifyError(): error=" << error; | 847 DVLOG(1) << "NotifyError(): error=" << error; |
| 865 | 848 |
| 866 if (!child_task_runner_->BelongsToCurrentThread()) { | 849 if (!child_task_runner_->BelongsToCurrentThread()) { |
| 867 child_task_runner_->PostTask( | 850 child_task_runner_->PostTask( |
| 868 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::NotifyError, | 851 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::NotifyError, |
| 869 weak_this_, error)); | 852 weak_this_, error)); |
| 870 return; | 853 return; |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 struct v4l2_plane planes[1]; | 1190 struct v4l2_plane planes[1]; |
| 1208 struct v4l2_buffer buffer; | 1191 struct v4l2_buffer buffer; |
| 1209 memset(&buffer, 0, sizeof(buffer)); | 1192 memset(&buffer, 0, sizeof(buffer)); |
| 1210 memset(planes, 0, sizeof(planes)); | 1193 memset(planes, 0, sizeof(planes)); |
| 1211 buffer.index = i; | 1194 buffer.index = i; |
| 1212 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1195 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1213 buffer.memory = V4L2_MEMORY_MMAP; | 1196 buffer.memory = V4L2_MEMORY_MMAP; |
| 1214 buffer.m.planes = planes; | 1197 buffer.m.planes = planes; |
| 1215 buffer.length = arraysize(planes); | 1198 buffer.length = arraysize(planes); |
| 1216 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); | 1199 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); |
| 1217 void* address = device_->Mmap(NULL, | 1200 void* address = |
| 1218 buffer.m.planes[0].length, | 1201 device_->Mmap(NULL, buffer.m.planes[0].length, PROT_READ | PROT_WRITE, |
| 1219 PROT_READ | PROT_WRITE, | 1202 MAP_SHARED, buffer.m.planes[0].m.mem_offset); |
| 1220 MAP_SHARED, | |
| 1221 buffer.m.planes[0].m.mem_offset); | |
| 1222 if (address == MAP_FAILED) { | 1203 if (address == MAP_FAILED) { |
| 1223 PLOG(ERROR) << "CreateOutputBuffers(): mmap() failed"; | 1204 PLOG(ERROR) << "CreateOutputBuffers(): mmap() failed"; |
| 1224 return false; | 1205 return false; |
| 1225 } | 1206 } |
| 1226 output_buffer_map_[i].address = address; | 1207 output_buffer_map_[i].address = address; |
| 1227 output_buffer_map_[i].length = buffer.m.planes[0].length; | 1208 output_buffer_map_[i].length = buffer.m.planes[0].length; |
| 1228 free_output_buffers_.push_back(i); | 1209 free_output_buffers_.push_back(i); |
| 1229 } | 1210 } |
| 1230 | 1211 |
| 1231 return true; | 1212 return true; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1262 memset(&reqbufs, 0, sizeof(reqbufs)); | 1243 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1263 reqbufs.count = 0; | 1244 reqbufs.count = 0; |
| 1264 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1245 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1265 reqbufs.memory = V4L2_MEMORY_MMAP; | 1246 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1266 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 1247 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 1267 | 1248 |
| 1268 output_buffer_map_.clear(); | 1249 output_buffer_map_.clear(); |
| 1269 free_output_buffers_.clear(); | 1250 free_output_buffers_.clear(); |
| 1270 } | 1251 } |
| 1271 | 1252 |
| 1272 } // namespace content | 1253 } // namespace media |
| OLD | NEW |