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 |