| 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 "media/gpu/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> |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 125 |
| 126 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 126 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 127 DCHECK_EQ(encoder_state_, kUninitialized); | 127 DCHECK_EQ(encoder_state_, kUninitialized); |
| 128 | 128 |
| 129 struct v4l2_capability caps; | 129 struct v4l2_capability caps; |
| 130 memset(&caps, 0, sizeof(caps)); | 130 memset(&caps, 0, sizeof(caps)); |
| 131 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; | 131 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
| 132 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 132 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 133 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 133 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 134 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " | 134 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " |
| 135 "caps check failed: 0x" | 135 << "caps check failed: 0x" << std::hex << caps.capabilities; |
| 136 << std::hex << caps.capabilities; | |
| 137 return false; | 136 return false; |
| 138 } | 137 } |
| 139 | 138 |
| 140 if (!SetFormats(input_format, output_profile)) { | 139 if (!SetFormats(input_format, output_profile)) { |
| 141 DLOG(ERROR) << "Failed setting up formats"; | 140 DLOG(ERROR) << "Failed setting up formats"; |
| 142 return false; | 141 return false; |
| 143 } | 142 } |
| 144 | 143 |
| 145 if (input_format != device_input_format_) { | 144 if (input_format != device_input_format_) { |
| 146 DVLOG(1) << "Input format not supported by the HW, will convert to " | 145 DVLOG(1) << "Input format not supported by the HW, will convert to " |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 // * device_poll_thread_ is running normally | 506 // * device_poll_thread_ is running normally |
| 508 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down, | 507 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down, |
| 509 // in which case we're in kError state, and we should have early-outed | 508 // in which case we're in kError state, and we should have early-outed |
| 510 // already. | 509 // already. |
| 511 DCHECK(device_poll_thread_.message_loop()); | 510 DCHECK(device_poll_thread_.message_loop()); |
| 512 // Queue the DevicePollTask() now. | 511 // Queue the DevicePollTask() now. |
| 513 device_poll_thread_.message_loop()->PostTask( | 512 device_poll_thread_.message_loop()->PostTask( |
| 514 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, | 513 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::DevicePollTask, |
| 515 base::Unretained(this), poll_device)); | 514 base::Unretained(this), poll_device)); |
| 516 | 515 |
| 517 DVLOG(2) << __func__ << ": buffer counts: ENC[" << encoder_input_queue_.size() | 516 DVLOG(2) << __func__ << ": buffer counts: ENC[" |
| 518 << "] => DEVICE[" << free_input_buffers_.size() << "+" | 517 << encoder_input_queue_.size() << "] => DEVICE[" |
| 519 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() | 518 << free_input_buffers_.size() << "+" |
| 520 << "->" << free_output_buffers_.size() << "+" | 519 << input_buffer_queued_count_ << "/" |
| 521 << output_buffer_queued_count_ << "/" << output_buffer_map_.size() | 520 << input_buffer_map_.size() << "->" |
| 522 << "] => OUT[" << encoder_output_queue_.size() << "]"; | 521 << free_output_buffers_.size() << "+" |
| 522 << output_buffer_queued_count_ << "/" |
| 523 << output_buffer_map_.size() << "] => OUT[" |
| 524 << encoder_output_queue_.size() << "]"; |
| 523 } | 525 } |
| 524 | 526 |
| 525 void V4L2VideoEncodeAccelerator::Enqueue() { | 527 void V4L2VideoEncodeAccelerator::Enqueue() { |
| 526 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current()); | 528 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current()); |
| 527 | 529 |
| 528 DVLOG(3) << "Enqueue() " | 530 DVLOG(3) << "Enqueue() " |
| 529 << "free_input_buffers: " << free_input_buffers_.size() | 531 << "free_input_buffers: " << free_input_buffers_.size() |
| 530 << "input_queue: " << encoder_input_queue_.size(); | 532 << "input_queue: " << encoder_input_queue_.size(); |
| 531 | 533 |
| 532 // Enqueue all the inputs we can. | 534 // Enqueue all the inputs we can. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 memcpy(target_data + stream_header_size_, output_data, output_size); | 653 memcpy(target_data + stream_header_size_, output_data, output_size); |
| 652 output_size += stream_header_size_; | 654 output_size += stream_header_size_; |
| 653 } else { | 655 } else { |
| 654 memcpy(target_data, output_data, output_size); | 656 memcpy(target_data, output_data, output_size); |
| 655 } | 657 } |
| 656 } else { | 658 } else { |
| 657 memcpy(target_data, output_data, output_size); | 659 memcpy(target_data, output_data, output_size); |
| 658 } | 660 } |
| 659 | 661 |
| 660 DVLOG(3) << "Dequeue(): returning " | 662 DVLOG(3) << "Dequeue(): returning " |
| 661 "bitstream_buffer_id=" | 663 << "bitstream_buffer_id=" << output_record.buffer_ref->id |
| 662 << output_record.buffer_ref->id << ", size=" << output_size | 664 << ", size=" << output_size |
| 663 << ", key_frame=" << key_frame; | 665 << ", key_frame=" << key_frame; |
| 664 child_task_runner_->PostTask( | 666 child_task_runner_->PostTask( |
| 665 FROM_HERE, | 667 FROM_HERE, |
| 666 base::Bind(&Client::BitstreamBufferReady, client_, | 668 base::Bind(&Client::BitstreamBufferReady, client_, |
| 667 output_record.buffer_ref->id, output_size, key_frame)); | 669 output_record.buffer_ref->id, output_size, key_frame)); |
| 668 output_record.at_device = false; | 670 output_record.at_device = false; |
| 669 output_record.buffer_ref.reset(); | 671 output_record.buffer_ref.reset(); |
| 670 free_output_buffers_.push_back(dqbuf.index); | 672 free_output_buffers_.push_back(dqbuf.index); |
| 671 output_buffer_queued_count_--; | 673 output_buffer_queued_count_--; |
| 672 } | 674 } |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 struct v4l2_plane planes[1]; | 1192 struct v4l2_plane planes[1]; |
| 1191 struct v4l2_buffer buffer; | 1193 struct v4l2_buffer buffer; |
| 1192 memset(&buffer, 0, sizeof(buffer)); | 1194 memset(&buffer, 0, sizeof(buffer)); |
| 1193 memset(planes, 0, sizeof(planes)); | 1195 memset(planes, 0, sizeof(planes)); |
| 1194 buffer.index = i; | 1196 buffer.index = i; |
| 1195 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1197 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1196 buffer.memory = V4L2_MEMORY_MMAP; | 1198 buffer.memory = V4L2_MEMORY_MMAP; |
| 1197 buffer.m.planes = planes; | 1199 buffer.m.planes = planes; |
| 1198 buffer.length = arraysize(planes); | 1200 buffer.length = arraysize(planes); |
| 1199 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); | 1201 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer); |
| 1200 void* address = | 1202 void* address = device_->Mmap(NULL, |
| 1201 device_->Mmap(NULL, buffer.m.planes[0].length, PROT_READ | PROT_WRITE, | 1203 buffer.m.planes[0].length, |
| 1202 MAP_SHARED, buffer.m.planes[0].m.mem_offset); | 1204 PROT_READ | PROT_WRITE, |
| 1205 MAP_SHARED, |
| 1206 buffer.m.planes[0].m.mem_offset); |
| 1203 if (address == MAP_FAILED) { | 1207 if (address == MAP_FAILED) { |
| 1204 PLOG(ERROR) << "CreateOutputBuffers(): mmap() failed"; | 1208 PLOG(ERROR) << "CreateOutputBuffers(): mmap() failed"; |
| 1205 return false; | 1209 return false; |
| 1206 } | 1210 } |
| 1207 output_buffer_map_[i].address = address; | 1211 output_buffer_map_[i].address = address; |
| 1208 output_buffer_map_[i].length = buffer.m.planes[0].length; | 1212 output_buffer_map_[i].length = buffer.m.planes[0].length; |
| 1209 free_output_buffers_.push_back(i); | 1213 free_output_buffers_.push_back(i); |
| 1210 } | 1214 } |
| 1211 | 1215 |
| 1212 return true; | 1216 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 reqbufs.count = 0; | 1248 reqbufs.count = 0; |
| 1245 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1249 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1246 reqbufs.memory = V4L2_MEMORY_MMAP; | 1250 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1247 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 1251 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 1248 | 1252 |
| 1249 output_buffer_map_.clear(); | 1253 output_buffer_map_.clear(); |
| 1250 free_output_buffers_.clear(); | 1254 free_output_buffers_.clear(); |
| 1251 } | 1255 } |
| 1252 | 1256 |
| 1253 } // namespace media | 1257 } // namespace media |
| OLD | NEW |