| 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 <errno.h> | 5 #include <errno.h> |
| 6 #include <linux/videodev2.h> | 6 #include <linux/videodev2.h> |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <sys/mman.h> | 8 #include <sys/mman.h> |
| 9 | 9 |
| 10 #include "base/big_endian.h" | 10 #include "base/big_endian.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
| 13 #include "content/common/gpu/media/v4l2_jpeg_decode_accelerator.h" | |
| 14 #include "media/filters/jpeg_parser.h" | 13 #include "media/filters/jpeg_parser.h" |
| 14 #include "media/gpu/v4l2_jpeg_decode_accelerator.h" |
| 15 #include "third_party/libyuv/include/libyuv.h" | 15 #include "third_party/libyuv/include/libyuv.h" |
| 16 | 16 |
| 17 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_name) \ | 17 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_name) \ |
| 18 do { \ | 18 do { \ |
| 19 if (device_->Ioctl(type, arg) != 0) { \ | 19 if (device_->Ioctl(type, arg) != 0) { \ |
| 20 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_name; \ | 20 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_name; \ |
| 21 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); \ | 21 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); \ |
| 22 return value; \ | 22 return value; \ |
| 23 } \ | 23 } \ |
| 24 } while (0) | 24 } while (0) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 52 do { \ | 52 do { \ |
| 53 uint16_t _out; \ | 53 uint16_t _out; \ |
| 54 if (!reader.ReadU16(&_out)) { \ | 54 if (!reader.ReadU16(&_out)) { \ |
| 55 DVLOG(1) \ | 55 DVLOG(1) \ |
| 56 << "Error in stream: unexpected EOS while trying to read " #out; \ | 56 << "Error in stream: unexpected EOS while trying to read " #out; \ |
| 57 return false; \ | 57 return false; \ |
| 58 } \ | 58 } \ |
| 59 *(out) = _out; \ | 59 *(out) = _out; \ |
| 60 } while (0) | 60 } while (0) |
| 61 | 61 |
| 62 namespace content { | 62 namespace media { |
| 63 | 63 |
| 64 // This is default huffman segment for 8-bit precision luminance and | 64 // This is default huffman segment for 8-bit precision luminance and |
| 65 // chrominance. The default huffman segment is constructed with the tables from | 65 // chrominance. The default huffman segment is constructed with the tables from |
| 66 // JPEG standard section K.3. Actually there are no default tables. They are | 66 // JPEG standard section K.3. Actually there are no default tables. They are |
| 67 // typical tables. These tables are useful for many applications. Lots of | 67 // typical tables. These tables are useful for many applications. Lots of |
| 68 // softwares use them as standard tables such as ffmpeg. | 68 // softwares use them as standard tables such as ffmpeg. |
| 69 const uint8_t kDefaultDhtSeg[] = { | 69 const uint8_t kDefaultDhtSeg[] = { |
| 70 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, | 70 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, |
| 71 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, | 71 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 72 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, | 72 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, |
| 73 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, | 73 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, |
| 74 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, | 74 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, |
| 75 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, | 75 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, |
| 76 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, | 76 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, |
| 77 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, | 77 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, |
| 78 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, | 78 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, |
| 79 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, | 79 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, |
| 80 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, | 80 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, |
| 81 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, | 81 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, |
| 82 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, | 82 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, |
| 83 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, | 83 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, |
| 84 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, | 84 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, |
| 85 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, | 85 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, |
| 86 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, | 86 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, |
| 87 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, | 87 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, |
| 88 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, | 88 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, |
| 89 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, | 89 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, |
| 90 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, | 90 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, |
| 91 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, | 91 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, |
| 92 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, | 92 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, |
| 93 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, | 93 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, |
| 94 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, | 94 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, |
| 95 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, | 95 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, |
| 96 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, | 96 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, |
| 97 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, | 97 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, |
| 98 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, | 98 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, |
| 99 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, | 99 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, |
| 100 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, | 100 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, |
| 101 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, | 101 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, |
| 102 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, | 102 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, |
| 103 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, | 103 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, |
| 104 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA | 104 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA}; |
| 105 }; | |
| 106 | 105 |
| 107 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() | 106 V4L2JpegDecodeAccelerator::BufferRecord::BufferRecord() |
| 108 : address(nullptr), length(0), at_device(false) { | 107 : address(nullptr), length(0), at_device(false) {} |
| 109 } | |
| 110 | 108 |
| 111 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() { | 109 V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {} |
| 112 } | |
| 113 | 110 |
| 114 V4L2JpegDecodeAccelerator::JobRecord::JobRecord( | 111 V4L2JpegDecodeAccelerator::JobRecord::JobRecord( |
| 115 const media::BitstreamBuffer& bitstream_buffer, | 112 const media::BitstreamBuffer& bitstream_buffer, |
| 116 scoped_refptr<media::VideoFrame> video_frame) | 113 scoped_refptr<media::VideoFrame> video_frame) |
| 117 : bitstream_buffer_id(bitstream_buffer.id()), | 114 : bitstream_buffer_id(bitstream_buffer.id()), |
| 118 shm(bitstream_buffer, true), | 115 shm(bitstream_buffer, true), |
| 119 out_frame(video_frame) {} | 116 out_frame(video_frame) {} |
| 120 | 117 |
| 121 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() { | 118 V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {} |
| 122 } | |
| 123 | 119 |
| 124 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator( | 120 V4L2JpegDecodeAccelerator::V4L2JpegDecodeAccelerator( |
| 125 const scoped_refptr<V4L2Device>& device, | 121 const scoped_refptr<V4L2Device>& device, |
| 126 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | 122 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
| 127 : output_buffer_pixelformat_(0), | 123 : output_buffer_pixelformat_(0), |
| 128 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 124 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 129 io_task_runner_(io_task_runner), | 125 io_task_runner_(io_task_runner), |
| 130 client_(nullptr), | 126 client_(nullptr), |
| 131 device_(device), | 127 device_(device), |
| 132 decoder_thread_("V4L2JpegDecodeThread"), | 128 decoder_thread_("V4L2JpegDecodeThread"), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 } | 166 } |
| 171 | 167 |
| 172 void V4L2JpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id, | 168 void V4L2JpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id, |
| 173 Error error) { | 169 Error error) { |
| 174 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 170 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 175 LOG(ERROR) << "Notifying of error " << error << " for buffer id " | 171 LOG(ERROR) << "Notifying of error " << error << " for buffer id " |
| 176 << bitstream_buffer_id; | 172 << bitstream_buffer_id; |
| 177 client_->NotifyError(bitstream_buffer_id, error); | 173 client_->NotifyError(bitstream_buffer_id, error); |
| 178 } | 174 } |
| 179 | 175 |
| 180 void V4L2JpegDecodeAccelerator::PostNotifyError( | 176 void V4L2JpegDecodeAccelerator::PostNotifyError(int32_t bitstream_buffer_id, |
| 181 int32_t bitstream_buffer_id, | 177 Error error) { |
| 182 Error error) { | |
| 183 child_task_runner_->PostTask( | 178 child_task_runner_->PostTask( |
| 184 FROM_HERE, | 179 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::NotifyError, weak_ptr_, |
| 185 base::Bind(&V4L2JpegDecodeAccelerator::NotifyError, weak_ptr_, | 180 bitstream_buffer_id, error)); |
| 186 bitstream_buffer_id, error)); | |
| 187 } | 181 } |
| 188 | 182 |
| 189 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) { | 183 bool V4L2JpegDecodeAccelerator::Initialize(Client* client) { |
| 190 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 184 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 191 | 185 |
| 192 // Capabilities check. | 186 // Capabilities check. |
| 193 struct v4l2_capability caps; | 187 struct v4l2_capability caps; |
| 194 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; | 188 const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; |
| 195 memset(&caps, 0, sizeof(caps)); | 189 memset(&caps, 0, sizeof(caps)); |
| 196 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { | 190 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 } | 511 } |
| 518 | 512 |
| 519 bool V4L2JpegDecodeAccelerator::DequeueSourceChangeEvent() { | 513 bool V4L2JpegDecodeAccelerator::DequeueSourceChangeEvent() { |
| 520 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 514 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 521 | 515 |
| 522 struct v4l2_event ev; | 516 struct v4l2_event ev; |
| 523 memset(&ev, 0, sizeof(ev)); | 517 memset(&ev, 0, sizeof(ev)); |
| 524 | 518 |
| 525 if (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { | 519 if (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { |
| 526 if (ev.type == V4L2_EVENT_SOURCE_CHANGE) { | 520 if (ev.type == V4L2_EVENT_SOURCE_CHANGE) { |
| 527 DVLOG(3) << __func__ << ": got source change event: " | 521 DVLOG(3) << __func__ |
| 528 << ev.u.src_change.changes; | 522 << ": got source change event: " << ev.u.src_change.changes; |
| 529 if (ev.u.src_change.changes & | 523 if (ev.u.src_change.changes & |
| 530 (V4L2_EVENT_SRC_CH_RESOLUTION | V4L2_EVENT_SRC_CH_PIXELFORMAT)) { | 524 (V4L2_EVENT_SRC_CH_RESOLUTION | V4L2_EVENT_SRC_CH_PIXELFORMAT)) { |
| 531 return true; | 525 return true; |
| 532 } | 526 } |
| 533 LOG(ERROR) << __func__ << ": unexpected source change event."; | 527 LOG(ERROR) << __func__ << ": unexpected source change event."; |
| 534 } else { | 528 } else { |
| 535 LOG(ERROR) << __func__ << ": got an event (" << ev.type | 529 LOG(ERROR) << __func__ << ": got an event (" << ev.type |
| 536 << ") we haven't subscribed to."; | 530 << ") we haven't subscribed to."; |
| 537 } | 531 } |
| 538 } else { | 532 } else { |
| 539 LOG(ERROR) << __func__ << ": dequeue event failed."; | 533 LOG(ERROR) << __func__ << ": dequeue event failed."; |
| 540 } | 534 } |
| 541 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); | 535 PostNotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); |
| 542 return false; | 536 return false; |
| 543 } | 537 } |
| 544 | 538 |
| 545 void V4L2JpegDecodeAccelerator::ServiceDeviceTask(bool event_pending) { | 539 void V4L2JpegDecodeAccelerator::ServiceDeviceTask(bool event_pending) { |
| 546 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 540 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 547 // If DestroyTask() shuts |device_poll_thread_| down, we should early-out. | 541 // If DestroyTask() shuts |device_poll_thread_| down, we should early-out. |
| 548 if (!device_poll_thread_.IsRunning()) | 542 if (!device_poll_thread_.IsRunning()) |
| 549 return; | 543 return; |
| 550 | 544 |
| 551 if (!running_jobs_.empty()) | 545 if (!running_jobs_.empty()) |
| 552 Dequeue(); | 546 Dequeue(); |
| 553 | 547 |
| 554 if (ShouldRecreateInputBuffers() && !RecreateInputBuffers()) | 548 if (ShouldRecreateInputBuffers() && !RecreateInputBuffers()) |
| 555 return; | 549 return; |
| 556 | 550 |
| 557 if (event_pending) { | 551 if (event_pending) { |
| 558 if (!DequeueSourceChangeEvent()) return; | 552 if (!DequeueSourceChangeEvent()) |
| 559 if (!RecreateOutputBuffers()) return; | 553 return; |
| 554 if (!RecreateOutputBuffers()) |
| 555 return; |
| 560 } | 556 } |
| 561 | 557 |
| 562 EnqueueInput(); | 558 EnqueueInput(); |
| 563 EnqueueOutput(); | 559 EnqueueOutput(); |
| 564 | 560 |
| 565 if (!running_jobs_.empty()) { | 561 if (!running_jobs_.empty()) { |
| 566 device_poll_task_runner_->PostTask( | 562 device_poll_task_runner_->PostTask( |
| 567 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::DevicePollTask, | 563 FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::DevicePollTask, |
| 568 base::Unretained(this))); | 564 base::Unretained(this))); |
| 569 } | 565 } |
| 570 | 566 |
| 571 DVLOG(2) << __func__ << ": buffer counts: INPUT[" | 567 DVLOG(2) << __func__ << ": buffer counts: INPUT[" << input_jobs_.size() |
| 572 << input_jobs_.size() << "] => DEVICE[" | 568 << "] => DEVICE[" << free_input_buffers_.size() << "/" |
| 573 << free_input_buffers_.size() << "/" | 569 << input_buffer_map_.size() << "->" << free_output_buffers_.size() |
| 574 << input_buffer_map_.size() << "->" | 570 << "/" << output_buffer_map_.size() << "]"; |
| 575 << free_output_buffers_.size() << "/" | |
| 576 << output_buffer_map_.size() << "]"; | |
| 577 } | 571 } |
| 578 | 572 |
| 579 void V4L2JpegDecodeAccelerator::EnqueueInput() { | 573 void V4L2JpegDecodeAccelerator::EnqueueInput() { |
| 580 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 574 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 581 while (!input_jobs_.empty() && !free_input_buffers_.empty()) { | 575 while (!input_jobs_.empty() && !free_input_buffers_.empty()) { |
| 582 // If input buffers are required to re-create, do not enqueue input record | 576 // If input buffers are required to re-create, do not enqueue input record |
| 583 // until all pending frames are handled by device. | 577 // until all pending frames are handled by device. |
| 584 if (ShouldRecreateInputBuffers()) | 578 if (ShouldRecreateInputBuffers()) |
| 585 break; | 579 break; |
| 586 if (!EnqueueInputRecord()) | 580 if (!EnqueueInputRecord()) |
| 587 return; | 581 return; |
| 588 } | 582 } |
| 589 // Check here because we cannot STREAMON before QBUF in earlier kernel. | 583 // Check here because we cannot STREAMON before QBUF in earlier kernel. |
| 590 // (kernel version < 3.14) | 584 // (kernel version < 3.14) |
| 591 if (!input_streamon_ && InputBufferQueuedCount()) { | 585 if (!input_streamon_ && InputBufferQueuedCount()) { |
| 592 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | 586 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
| 593 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); | 587 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); |
| 594 input_streamon_ = true; | 588 input_streamon_ = true; |
| 595 } | 589 } |
| 596 } | 590 } |
| 597 | 591 |
| 598 void V4L2JpegDecodeAccelerator::EnqueueOutput() { | 592 void V4L2JpegDecodeAccelerator::EnqueueOutput() { |
| 599 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 593 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 600 // Output record can be enqueued because the output coded sizes of the frames | 594 // Output record can be enqueued because the output coded sizes of the frames |
| 601 // currently in the pipeline are all the same. | 595 // currently in the pipeline are all the same. |
| 602 while (running_jobs_.size() > OutputBufferQueuedCount() && | 596 while (running_jobs_.size() > OutputBufferQueuedCount() && |
| 603 !free_output_buffers_.empty()) { | 597 !free_output_buffers_.empty()) { |
| 604 if (!EnqueueOutputRecord()) | 598 if (!EnqueueOutputRecord()) |
| 605 return; | 599 return; |
| 606 } | 600 } |
| 607 // Check here because we cannot STREAMON before QBUF in earlier kernel. | 601 // Check here because we cannot STREAMON before QBUF in earlier kernel. |
| 608 // (kernel version < 3.14) | 602 // (kernel version < 3.14) |
| 609 if (!output_streamon_ && OutputBufferQueuedCount()) { | 603 if (!output_streamon_ && OutputBufferQueuedCount()) { |
| 610 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 604 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 611 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); | 605 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); |
| 612 output_streamon_ = true; | 606 output_streamon_ = true; |
| 613 } | 607 } |
| 614 } | 608 } |
| 615 | 609 |
| 616 static bool CopyOutputImage(const uint32_t src_pixelformat, | 610 static bool CopyOutputImage(const uint32_t src_pixelformat, |
| 617 const void* src_addr, | 611 const void* src_addr, |
| 618 const gfx::Size& src_coded_size, | 612 const gfx::Size& src_coded_size, |
| 619 const scoped_refptr<media::VideoFrame>& dst_frame) { | 613 const scoped_refptr<media::VideoFrame>& dst_frame) { |
| 620 media::VideoPixelFormat format = | 614 media::VideoPixelFormat format = |
| 621 V4L2Device::V4L2PixFmtToVideoPixelFormat(src_pixelformat); | 615 V4L2Device::V4L2PixFmtToVideoPixelFormat(src_pixelformat); |
| 622 size_t src_size = media::VideoFrame::AllocationSize(format, src_coded_size); | 616 size_t src_size = media::VideoFrame::AllocationSize(format, src_coded_size); |
| 623 uint8_t* dst_y = dst_frame->data(media::VideoFrame::kYPlane); | 617 uint8_t* dst_y = dst_frame->data(media::VideoFrame::kYPlane); |
| 624 uint8_t* dst_u = dst_frame->data(media::VideoFrame::kUPlane); | 618 uint8_t* dst_u = dst_frame->data(media::VideoFrame::kUPlane); |
| 625 uint8_t* dst_v = dst_frame->data(media::VideoFrame::kVPlane); | 619 uint8_t* dst_v = dst_frame->data(media::VideoFrame::kVPlane); |
| 626 size_t dst_y_stride = dst_frame->stride(media::VideoFrame::kYPlane); | 620 size_t dst_y_stride = dst_frame->stride(media::VideoFrame::kYPlane); |
| 627 size_t dst_u_stride = dst_frame->stride(media::VideoFrame::kUPlane); | 621 size_t dst_u_stride = dst_frame->stride(media::VideoFrame::kUPlane); |
| 628 size_t dst_v_stride = dst_frame->stride(media::VideoFrame::kVPlane); | 622 size_t dst_v_stride = dst_frame->stride(media::VideoFrame::kVPlane); |
| 629 | 623 |
| 630 // If the source format is I420, ConvertToI420 will simply copy the frame. | 624 // If the source format is I420, ConvertToI420 will simply copy the frame. |
| 631 if (libyuv::ConvertToI420(static_cast<uint8_t*>(const_cast<void*>(src_addr)), | 625 if (libyuv::ConvertToI420( |
| 632 src_size, | 626 static_cast<uint8_t*>(const_cast<void*>(src_addr)), src_size, dst_y, |
| 633 dst_y, dst_y_stride, | 627 dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, 0, 0, |
| 634 dst_u, dst_u_stride, | 628 src_coded_size.width(), src_coded_size.height(), |
| 635 dst_v, dst_v_stride, | 629 dst_frame->coded_size().width(), dst_frame->coded_size().height(), |
| 636 0, 0, | 630 libyuv::kRotate0, src_pixelformat)) { |
| 637 src_coded_size.width(), | |
| 638 src_coded_size.height(), | |
| 639 dst_frame->coded_size().width(), | |
| 640 dst_frame->coded_size().height(), | |
| 641 libyuv::kRotate0, | |
| 642 src_pixelformat)) { | |
| 643 LOG(ERROR) << "ConvertToI420 failed. Source format: " << src_pixelformat; | 631 LOG(ERROR) << "ConvertToI420 failed. Source format: " << src_pixelformat; |
| 644 return false; | 632 return false; |
| 645 } | 633 } |
| 646 return true; | 634 return true; |
| 647 } | 635 } |
| 648 | 636 |
| 649 void V4L2JpegDecodeAccelerator::Dequeue() { | 637 void V4L2JpegDecodeAccelerator::Dequeue() { |
| 650 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 638 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 651 | 639 |
| 652 // Dequeue completed input (VIDEO_OUTPUT) buffers, | 640 // Dequeue completed input (VIDEO_OUTPUT) buffers, |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 | 877 |
| 890 device_poll_thread_.Stop(); | 878 device_poll_thread_.Stop(); |
| 891 | 879 |
| 892 // Clear the interrupt now, to be sure. | 880 // Clear the interrupt now, to be sure. |
| 893 if (!device_->ClearDevicePollInterrupt()) | 881 if (!device_->ClearDevicePollInterrupt()) |
| 894 return false; | 882 return false; |
| 895 | 883 |
| 896 return true; | 884 return true; |
| 897 } | 885 } |
| 898 | 886 |
| 899 } // namespace content | 887 } // namespace media |
| OLD | NEW |