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