OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_jpeg_decode_accelerator.h" | 5 #include "media/gpu/v4l2_jpeg_decode_accelerator.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 void V4L2JpegDecodeAccelerator::PostNotifyError(int32_t bitstream_buffer_id, | 180 void V4L2JpegDecodeAccelerator::PostNotifyError(int32_t bitstream_buffer_id, |
181 Error error) { | 181 Error error) { |
182 child_task_runner_->PostTask( | 182 child_task_runner_->PostTask( |
183 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::NotifyError, weak_ptr_, | 183 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::NotifyError, weak_ptr_, |
184 bitstream_buffer_id, error)); | 184 bitstream_buffer_id, error)); |
185 } | 185 } |
186 | 186 |
187 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) { | 187 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) { |
188 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 188 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
189 | 189 |
190 if (!device_->Open(V4L2Device::Type::kJpegDecoder, V4L2_PIX_FMT_JPEG)) { | |
191 LOG(ERROR) << "Failed to open device"; | |
192 return false; | |
193 } | |
194 | |
190 // Capabilities check. | 195 // Capabilities check. |
191 struct v4l2_capability caps; | 196 struct v4l2_capability caps; |
192 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; | 197 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; |
193 memset(&caps, 0, sizeof(caps)); | 198 memset(&caps, 0, sizeof(caps)); |
194 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { | 199 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { |
195 PLOG(ERROR) << __func__ << ": ioctl() failed: VIDIOC_QUERYCAP"; | 200 PLOG(ERROR) << __func__ << ": ioctl() failed: VIDIOC_QUERYCAP"; |
196 return false; | 201 return false; |
197 } | 202 } |
198 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 203 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
199 LOG(ERROR) << __func__ << ": VIDIOC_QUERYCAP, caps check failed: 0x" | 204 LOG(ERROR) << __func__ << ": VIDIOC_QUERYCAP, caps check failed: 0x" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 } | 251 } |
247 | 252 |
248 std::unique_ptr<JobRecord> job_record( | 253 std::unique_ptr<JobRecord> job_record( |
249 new JobRecord(bitstream_buffer, video_frame)); | 254 new JobRecord(bitstream_buffer, video_frame)); |
250 | 255 |
251 decoder_task_runner_->PostTask( | 256 decoder_task_runner_->PostTask( |
252 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::DecodeTask, | 257 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::DecodeTask, |
253 base::Unretained(this), base::Passed(&job_record))); | 258 base::Unretained(this), base::Passed(&job_record))); |
254 } | 259 } |
255 | 260 |
261 // static | |
256 bool V4L2JpegDecodeAccelerator::IsSupported() { | 262 bool V4L2JpegDecodeAccelerator::IsSupported() { |
257 v4l2_fmtdesc fmtdesc; | 263 scoped_refptr<V4L2Device> device = V4L2Device::Create(); |
258 memset(&fmtdesc, 0, sizeof(fmtdesc)); | 264 if (!device) |
259 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 265 return false; |
260 | 266 |
261 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { | 267 return device->IsJpegDecodingSupported(); |
262 if (fmtdesc.pixelformat == V4L2_PIX_FMT_JPEG) | |
263 return true; | |
264 } | |
265 return false; | |
266 } | 268 } |
267 | 269 |
268 void V4L2JpegDecodeAccelerator::DecodeTask( | 270 void V4L2JpegDecodeAccelerator::DecodeTask( |
269 std::unique_ptr<JobRecord> job_record) { | 271 std::unique_ptr<JobRecord> job_record) { |
270 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 272 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
271 if (!job_record->shm.Map()) { | 273 if (!job_record->shm.Map()) { |
272 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer"; | 274 PLOG(ERROR) << __func__ << ": could not map bitstream_buffer"; |
273 PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT); | 275 PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT); |
274 return; | 276 return; |
275 } | 277 } |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 } | 442 } |
441 output_buffer_map_[i].address = address; | 443 output_buffer_map_[i].address = address; |
442 output_buffer_map_[i].length = buffer.length; | 444 output_buffer_map_[i].length = buffer.length; |
443 } | 445 } |
444 | 446 |
445 return true; | 447 return true; |
446 } | 448 } |
447 | 449 |
448 void V4L2JpegDecodeAccelerator::DestroyInputBuffers() { | 450 void V4L2JpegDecodeAccelerator::DestroyInputBuffers() { |
449 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 451 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
450 DCHECK(!input_streamon_); | 452 DCHECK(!input_streamon_); |
kcwu
2016/10/07 11:19:05
I found this check is contradiction to line 459.
Pawel Osciak
2016/10/11 06:13:46
My guess is that the intention here could have bee
| |
451 | 453 |
454 free_input_buffers_.clear(); | |
455 | |
456 if (input_buffer_map_.empty()) | |
457 return; | |
458 | |
452 if (input_streamon_) { | 459 if (input_streamon_) { |
453 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 460 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
454 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); | 461 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); |
455 input_streamon_ = false; | 462 input_streamon_ = false; |
456 } | 463 } |
457 | 464 |
458 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 465 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
459 BufferRecord& input_record = input_buffer_map_[i]; | 466 BufferRecord& input_record = input_buffer_map_[i]; |
460 device_->Munmap(input_record.address, input_record.length); | 467 device_->Munmap(input_record.address, input_record.length); |
461 } | 468 } |
462 | 469 |
463 struct v4l2_requestbuffers reqbufs; | 470 struct v4l2_requestbuffers reqbufs; |
464 memset(&reqbufs, 0, sizeof(reqbufs)); | 471 memset(&reqbufs, 0, sizeof(reqbufs)); |
465 reqbufs.count = 0; | 472 reqbufs.count = 0; |
466 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 473 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
467 reqbufs.memory = V4L2_MEMORY_MMAP; | 474 reqbufs.memory = V4L2_MEMORY_MMAP; |
468 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 475 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
469 | 476 |
470 input_buffer_map_.clear(); | 477 input_buffer_map_.clear(); |
471 free_input_buffers_.clear(); | |
472 } | 478 } |
473 | 479 |
474 void V4L2JpegDecodeAccelerator::DestroyOutputBuffers() { | 480 void V4L2JpegDecodeAccelerator::DestroyOutputBuffers() { |
475 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 481 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
476 DCHECK(!output_streamon_); | 482 DCHECK(!output_streamon_); |
kcwu
2016/10/07 11:19:05
I found this check is contradiction to line 489.
Pawel Osciak
2016/10/11 06:13:46
Please see above.
| |
477 | 483 |
484 free_output_buffers_.clear(); | |
485 | |
486 if (output_buffer_map_.empty()) | |
487 return; | |
488 | |
478 if (output_streamon_) { | 489 if (output_streamon_) { |
479 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 490 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
480 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); | 491 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type); |
481 output_streamon_ = false; | 492 output_streamon_ = false; |
482 } | 493 } |
483 | 494 |
484 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 495 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
485 BufferRecord& output_record = output_buffer_map_[i]; | 496 BufferRecord& output_record = output_buffer_map_[i]; |
486 device_->Munmap(output_record.address, output_record.length); | 497 device_->Munmap(output_record.address, output_record.length); |
487 } | 498 } |
488 | 499 |
489 struct v4l2_requestbuffers reqbufs; | 500 struct v4l2_requestbuffers reqbufs; |
490 memset(&reqbufs, 0, sizeof(reqbufs)); | 501 memset(&reqbufs, 0, sizeof(reqbufs)); |
491 reqbufs.count = 0; | 502 reqbufs.count = 0; |
492 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 503 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
493 reqbufs.memory = V4L2_MEMORY_MMAP; | 504 reqbufs.memory = V4L2_MEMORY_MMAP; |
494 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 505 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
495 | 506 |
496 output_buffer_map_.clear(); | 507 output_buffer_map_.clear(); |
497 free_output_buffers_.clear(); | |
498 } | 508 } |
499 | 509 |
500 void V4L2JpegDecodeAccelerator::DevicePollTask() { | 510 void V4L2JpegDecodeAccelerator::DevicePollTask() { |
501 DCHECK(device_poll_task_runner_->BelongsToCurrentThread()); | 511 DCHECK(device_poll_task_runner_->BelongsToCurrentThread()); |
502 | 512 |
503 bool event_pending; | 513 bool event_pending; |
504 if (!device_->Poll(true, &event_pending)) { | 514 if (!device_->Poll(true, &event_pending)) { |
505 PLOG(ERROR) << __func__ << ": Poll device error."; | 515 PLOG(ERROR) << __func__ << ": Poll device error."; |
506 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); | 516 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); |
507 return; | 517 return; |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
890 device_poll_thread_.Stop(); | 900 device_poll_thread_.Stop(); |
891 | 901 |
892 // Clear the interrupt now, to be sure. | 902 // Clear the interrupt now, to be sure. |
893 if (!device_->ClearDevicePollInterrupt()) | 903 if (!device_->ClearDevicePollInterrupt()) |
894 return false; | 904 return false; |
895 | 905 |
896 return true; | 906 return true; |
897 } | 907 } |
898 | 908 |
899 } // namespace media | 909 } // namespace media |
OLD | NEW |