1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/gpu/v4l2/v4l2_jpeg_encode_accelerator.h"
6 
7 #include <errno.h>
8 #include <linux/videodev2.h>
9 #include <string.h>
10 #include <sys/mman.h>
11 
12 #include <memory>
13 
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/numerics/ranges.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "media/gpu/chromeos/fourcc.h"
19 #include "media/gpu/chromeos/platform_video_frame_utils.h"
20 #include "media/gpu/macros.h"
21 #include "media/gpu/v4l2/v4l2_device.h"
22 #include "third_party/libyuv/include/libyuv.h"
23 
24 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_name) \
25   do {                                                           \
26     if (device_->Ioctl(type, arg) != 0) {                        \
27       VPLOGF(1) << "ioctl() failed: " << type_name;              \
28       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);  \
29       return value;                                              \
30     }                                                            \
31   } while (0)
32 
33 #define IOCTL_OR_ERROR_RETURN(type, arg) \
34   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type)
35 
36 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
37   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type)
38 
39 #define IOCTL_OR_LOG_ERROR(type, arg)                           \
40   do {                                                          \
41     if (device_->Ioctl(type, arg) != 0) {                       \
42       VPLOGF(1) << "ioctl() failed: " << #type;                 \
43       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE); \
44     }                                                           \
45   } while (0)
46 
47 namespace media {
48 
I420BufferRecord()49 V4L2JpegEncodeAccelerator::I420BufferRecord::I420BufferRecord()
50     : at_device(false) {
51   memset(address, 0, sizeof(address));
52   memset(length, 0, sizeof(length));
53 }
54 
~I420BufferRecord()55 V4L2JpegEncodeAccelerator::I420BufferRecord::~I420BufferRecord() {}
56 
JpegBufferRecord()57 V4L2JpegEncodeAccelerator::JpegBufferRecord::JpegBufferRecord()
58     : at_device(false) {
59   memset(address, 0, sizeof(address));
60   memset(length, 0, sizeof(length));
61 }
62 
~JpegBufferRecord()63 V4L2JpegEncodeAccelerator::JpegBufferRecord::~JpegBufferRecord() {}
64 
JobRecord(scoped_refptr<VideoFrame> input_frame,scoped_refptr<VideoFrame> output_frame,int quality,int32_t task_id,BitstreamBuffer * exif_buffer)65 V4L2JpegEncodeAccelerator::JobRecord::JobRecord(
66     scoped_refptr<VideoFrame> input_frame,
67     scoped_refptr<VideoFrame> output_frame,
68     int quality,
69     int32_t task_id,
70     BitstreamBuffer* exif_buffer)
71     : input_frame(input_frame),
72       output_frame(output_frame),
73       quality(quality),
74       task_id(task_id),
75       output_shm(base::subtle::PlatformSharedMemoryRegion(), 0, true),  // dummy
76       exif_shm(nullptr) {
77   if (exif_buffer) {
78     exif_shm.reset(new UnalignedSharedMemory(exif_buffer->TakeRegion(),
79                                              exif_buffer->size(), false));
80     exif_offset = exif_buffer->offset();
81   }
82 }
83 
JobRecord(scoped_refptr<VideoFrame> input_frame,int quality,BitstreamBuffer * exif_buffer,BitstreamBuffer output_buffer)84 V4L2JpegEncodeAccelerator::JobRecord::JobRecord(
85     scoped_refptr<VideoFrame> input_frame,
86     int quality,
87     BitstreamBuffer* exif_buffer,
88     BitstreamBuffer output_buffer)
89     : input_frame(input_frame),
90       quality(quality),
91       task_id(output_buffer.id()),
92       output_shm(output_buffer.TakeRegion(), output_buffer.size(), false),
93       output_offset(output_buffer.offset()),
94       exif_shm(nullptr) {
95   if (exif_buffer) {
96     exif_shm.reset(new UnalignedSharedMemory(exif_buffer->TakeRegion(),
97                                              exif_buffer->size(), false));
98     exif_offset = exif_buffer->offset();
99   }
100 }
101 
~JobRecord()102 V4L2JpegEncodeAccelerator::JobRecord::~JobRecord() {}
103 
EncodedInstance(V4L2JpegEncodeAccelerator * parent)104 V4L2JpegEncodeAccelerator::EncodedInstance::EncodedInstance(
105     V4L2JpegEncodeAccelerator* parent)
106     : parent_(parent),
107       input_streamon_(false),
108       output_streamon_(false),
109       input_buffer_pixelformat_(0),
110       input_buffer_num_planes_(0),
111       output_buffer_pixelformat_(0) {}
112 
~EncodedInstance()113 V4L2JpegEncodeAccelerator::EncodedInstance::~EncodedInstance() {}
114 
DestroyTask()115 void V4L2JpegEncodeAccelerator::EncodedInstance::DestroyTask() {
116   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
117   while (!input_job_queue_.empty())
118     input_job_queue_.pop();
119   while (!running_job_queue_.empty())
120     running_job_queue_.pop();
121 
122   DestroyInputBuffers();
123   DestroyOutputBuffers();
124 }
125 
Initialize()126 bool V4L2JpegEncodeAccelerator::EncodedInstance::Initialize() {
127   device_ = V4L2Device::Create();
128 
129   if (!device_) {
130     VLOGF(1) << "Failed to Create V4L2Device";
131     return false;
132   }
133 
134   output_buffer_pixelformat_ = V4L2_PIX_FMT_JPEG_RAW;
135   if (!device_->Open(V4L2Device::Type::kJpegEncoder,
136                      output_buffer_pixelformat_)) {
137     VLOGF(1) << "Failed to open device";
138     return false;
139   }
140 
141   // Capabilities check.
142   struct v4l2_capability caps;
143   const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
144   memset(&caps, 0, sizeof(caps));
145   if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
146     VPLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP";
147     return false;
148   }
149   if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
150     VLOGF(1) << "VIDIOC_QUERYCAP, caps check failed: 0x" << std::hex
151              << caps.capabilities;
152     return false;
153   }
154 
155   return true;
156 }
157 
158 // static
FillQuantizationTable(int quality,const uint8_t * basic_table,uint8_t * dst_table)159 void V4L2JpegEncodeAccelerator::EncodedInstance::FillQuantizationTable(
160     int quality,
161     const uint8_t* basic_table,
162     uint8_t* dst_table) {
163   unsigned int temp;
164 
165   if (quality < 50)
166     quality = 5000 / quality;
167   else
168     quality = 200 - quality * 2;
169 
170   for (size_t i = 0; i < kDctSize; i++) {
171     temp = ((unsigned int)basic_table[kZigZag8x8[i]] * quality + 50) / 100;
172     /* limit the values to the valid range */
173     dst_table[i] = base::ClampToRange(temp, 1u, 255u);
174   }
175 }
176 
PrepareJpegMarkers(gfx::Size coded_size)177 void V4L2JpegEncodeAccelerator::EncodedInstance::PrepareJpegMarkers(
178     gfx::Size coded_size) {
179   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
180   // Quantization Tables.
181   // i = 0 for Luminance
182   // i = 1 for Chrominance
183   const int kNumDQT = 2;
184   for (size_t i = 0; i < kNumDQT; ++i) {
185     const uint8_t kQuantSegment[] = {
186         0xFF, JPEG_DQT, 0x00,
187         0x03 + kDctSize,         // Segment length:67 (2-byte).
188         static_cast<uint8_t>(i)  // Precision (4-bit high) = 0,
189                                  // Index (4-bit low) = i.
190     };
191     for (size_t j = 0; j < sizeof(kQuantSegment); ++j) {
192       jpeg_markers_.push_back(kQuantSegment[j]);
193     }
194 
195     for (size_t j = 0; j < kDctSize; ++j) {
196       jpeg_markers_.push_back(quantization_table_[i].value[j]);
197     }
198   }
199 
200   // Start of Frame - Baseline.
201   const int kNumOfComponents = 3;
202   const uint8_t kStartOfFrame[] = {
203       0xFF,
204       JPEG_SOF0,  // Baseline.
205       0x00,
206       0x11,  // Segment length:17 (2-byte).
207       8,     // Data precision.
208       static_cast<uint8_t>((coded_size.height() >> 8) & 0xFF),
209       static_cast<uint8_t>(coded_size.height() & 0xFF),
210       static_cast<uint8_t>((coded_size.width() >> 8) & 0xFF),
211       static_cast<uint8_t>(coded_size.width() & 0xFF),
212       kNumOfComponents,
213   };
214   for (size_t i = 0; i < sizeof(kStartOfFrame); ++i) {
215     jpeg_markers_.push_back(kStartOfFrame[i]);
216   }
217   // i = 0 for Y Plane
218   // i = 1 for U Plane
219   // i = 2 for V Plane
220   for (size_t i = 0; i < kNumOfComponents; ++i) {
221     // These are the values for U and V planes.
222     uint8_t h_sample_factor = 1;
223     uint8_t v_sample_factor = 1;
224     uint8_t quant_table_number = 1;
225     if (!i) {
226       // These are the values for Y plane.
227       h_sample_factor = 2;
228       v_sample_factor = 2;
229       quant_table_number = 0;
230     }
231 
232     jpeg_markers_.push_back(i + 1);
233     // Horizontal Sample Factor (4-bit high),
234     // Vertical Sample Factor (4-bit low).
235     jpeg_markers_.push_back((h_sample_factor << 4) | v_sample_factor);
236     jpeg_markers_.push_back(quant_table_number);
237   }
238 
239   // Huffman Tables.
240   static const uint8_t kDcSegment[] = {
241       0xFF, JPEG_DHT, 0x00,
242       0x1F,  // Segment length:31 (2-byte).
243   };
244   static const uint8_t kAcSegment[] = {
245       0xFF, JPEG_DHT, 0x00,
246       0xB5,  // Segment length:181 (2-byte).
247   };
248 
249   // i = 0 for Luminance
250   // i = 1 for Chrominance
251   const int kNumHuffmanTables = 2;
252   for (size_t i = 0; i < kNumHuffmanTables; ++i) {
253     // DC Table.
254     for (size_t j = 0; j < sizeof(kDcSegment); ++j) {
255       jpeg_markers_.push_back(kDcSegment[j]);
256     }
257 
258     // Type (4-bit high) = 0:DC, Index (4-bit low).
259     jpeg_markers_.push_back(static_cast<uint8_t>(i));
260 
261     const JpegHuffmanTable& dcTable = kDefaultDcTable[i];
262     for (size_t j = 0; j < kNumDcRunSizeBits; ++j)
263       jpeg_markers_.push_back(dcTable.code_length[j]);
264     for (size_t j = 0; j < kNumDcCodeWordsHuffVal; ++j)
265       jpeg_markers_.push_back(dcTable.code_value[j]);
266 
267     // AC Table.
268     for (size_t j = 0; j < sizeof(kAcSegment); ++j) {
269       jpeg_markers_.push_back(kAcSegment[j]);
270     }
271 
272     // Type (4-bit high) = 1:AC, Index (4-bit low).
273     jpeg_markers_.push_back(0x10 | static_cast<uint8_t>(i));
274 
275     const JpegHuffmanTable& acTable = kDefaultAcTable[i];
276     for (size_t j = 0; j < kNumAcRunSizeBits; ++j)
277       jpeg_markers_.push_back(acTable.code_length[j]);
278     for (size_t j = 0; j < kNumAcCodeWordsHuffVal; ++j)
279       jpeg_markers_.push_back(acTable.code_value[j]);
280   }
281 
282   // Start of Scan.
283   static const uint8_t kStartOfScan[] = {
284       0xFF, JPEG_SOS, 0x00,
285       0x0C,  // Segment Length:12 (2-byte).
286       0x03   // Number of components in scan.
287   };
288   for (size_t i = 0; i < sizeof(kStartOfScan); ++i) {
289     jpeg_markers_.push_back(kStartOfScan[i]);
290   }
291 
292   // i = 0 for Y Plane
293   // i = 1 for U Plane
294   // i = 2 for V Plane
295   for (uint8_t i = 0; i < kNumOfComponents; ++i) {
296     uint8_t dc_table_number = 1;
297     uint8_t ac_table_number = 1;
298     if (!i) {
299       dc_table_number = 0;
300       ac_table_number = 0;
301     }
302 
303     jpeg_markers_.push_back(i + 1);
304     // DC Table Selector (4-bit high), AC Table Selector (4-bit low).
305     jpeg_markers_.push_back((dc_table_number << 4) | ac_table_number);
306   }
307   jpeg_markers_.push_back(0x00);  // 0 for Baseline.
308   jpeg_markers_.push_back(0x3F);  // 63 for Baseline.
309   jpeg_markers_.push_back(0x00);  // 0 for Baseline.
310 }
311 
SetUpJpegParameters(int quality,gfx::Size coded_size)312 bool V4L2JpegEncodeAccelerator::EncodedInstance::SetUpJpegParameters(
313     int quality,
314     gfx::Size coded_size) {
315   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
316 
317   struct v4l2_ext_controls ctrls;
318   struct v4l2_ext_control ctrl;
319 
320   memset(&ctrls, 0, sizeof(ctrls));
321   memset(&ctrl, 0, sizeof(ctrl));
322 
323   ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
324   ctrls.controls = &ctrl;
325   ctrls.count = 1;
326 
327   switch (output_buffer_pixelformat_) {
328     case V4L2_PIX_FMT_JPEG_RAW:
329       FillQuantizationTable(quality, kDefaultQuantTable[0].value,
330                             quantization_table_[0].value);
331       FillQuantizationTable(quality, kDefaultQuantTable[1].value,
332                             quantization_table_[1].value);
333 
334       ctrl.id = V4L2_CID_JPEG_LUMA_QUANTIZATION;
335       ctrl.size = kDctSize;
336       ctrl.ptr = quantization_table_[0].value;
337       IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, &ctrls);
338 
339       ctrl.id = V4L2_CID_JPEG_CHROMA_QUANTIZATION;
340       ctrl.size = kDctSize;
341       ctrl.ptr = quantization_table_[1].value;
342       IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, &ctrls);
343 
344       // We need to prepare our own JPEG Markers.
345       PrepareJpegMarkers(coded_size);
346       break;
347 
348     default:
349       NOTREACHED();
350   }
351 
352   return true;
353 }
354 
InputBufferQueuedCount()355 size_t V4L2JpegEncodeAccelerator::EncodedInstance::InputBufferQueuedCount() {
356   return input_buffer_map_.size() - free_input_buffers_.size();
357 }
358 
OutputBufferQueuedCount()359 size_t V4L2JpegEncodeAccelerator::EncodedInstance::OutputBufferQueuedCount() {
360   return output_buffer_map_.size() - free_output_buffers_.size();
361 }
362 
CreateBuffers(gfx::Size coded_size,size_t output_buffer_size)363 bool V4L2JpegEncodeAccelerator::EncodedInstance::CreateBuffers(
364     gfx::Size coded_size,
365     size_t output_buffer_size) {
366   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
367 
368   // The order of set output/input formats matters.
369   // rk3399 reset input format when we set output format.
370   if (!SetOutputBufferFormat(coded_size, output_buffer_size)) {
371     return false;
372   }
373 
374   if (!SetInputBufferFormat(coded_size)) {
375     return false;
376   }
377 
378   if (!RequestInputBuffers()) {
379     return false;
380   }
381 
382   if (!RequestOutputBuffers()) {
383     return false;
384   }
385 
386   return true;
387 }
388 
SetInputBufferFormat(gfx::Size coded_size)389 bool V4L2JpegEncodeAccelerator::EncodedInstance::SetInputBufferFormat(
390     gfx::Size coded_size) {
391   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
392   DCHECK(!input_streamon_);
393   DCHECK(input_job_queue_.empty());
394 
395   constexpr uint32_t input_pix_fmt_candidates[] = {
396       V4L2_PIX_FMT_YUV420M,
397       V4L2_PIX_FMT_YUV420,
398   };
399 
400   struct v4l2_format format;
401   input_buffer_pixelformat_ = 0;
402   for (const auto input_pix_fmt : input_pix_fmt_candidates) {
403     DCHECK_EQ(Fourcc::FromV4L2PixFmt(input_pix_fmt)->ToVideoPixelFormat(),
404               PIXEL_FORMAT_I420);
405     memset(&format, 0, sizeof(format));
406     format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
407     format.fmt.pix_mp.num_planes = kMaxI420Plane;
408     format.fmt.pix_mp.pixelformat = input_pix_fmt;
409     format.fmt.pix_mp.field = V4L2_FIELD_ANY;
410     format.fmt.pix_mp.width = coded_size.width();
411     format.fmt.pix_mp.height = coded_size.height();
412 
413     if (device_->Ioctl(VIDIOC_S_FMT, &format) == 0 &&
414         format.fmt.pix_mp.pixelformat == input_pix_fmt) {
415       // Save V4L2 returned values.
416       input_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
417       input_buffer_num_planes_ = format.fmt.pix_mp.num_planes;
418       input_buffer_height_ = format.fmt.pix_mp.height;
419       break;
420     }
421   }
422 
423   if (input_buffer_pixelformat_ == 0) {
424     VLOGF(1) << "Neither YUV420 nor YUV420M is supported.";
425     return false;
426   }
427 
428   if (format.fmt.pix_mp.width != static_cast<uint32_t>(coded_size.width()) ||
429       format.fmt.pix_mp.height != static_cast<uint32_t>(coded_size.height())) {
430     VLOGF(1) << "Width " << coded_size.width() << "->"
431              << format.fmt.pix_mp.width << ",Height " << coded_size.height()
432              << "->" << format.fmt.pix_mp.height;
433     return false;
434   }
435   for (int i = 0; i < format.fmt.pix_mp.num_planes; i++) {
436     bytes_per_line_[i] = format.fmt.pix_mp.plane_fmt[i].bytesperline;
437     VLOGF(3) << "Bytes Per Line:" << bytes_per_line_[i];
438   }
439 
440   return true;
441 }
442 
SetOutputBufferFormat(gfx::Size coded_size,size_t buffer_size)443 bool V4L2JpegEncodeAccelerator::EncodedInstance::SetOutputBufferFormat(
444     gfx::Size coded_size,
445     size_t buffer_size) {
446   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
447   DCHECK(!output_streamon_);
448   DCHECK(running_job_queue_.empty());
449 
450   struct v4l2_format format;
451   memset(&format, 0, sizeof(format));
452   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
453   format.fmt.pix_mp.num_planes = kMaxJpegPlane;
454   format.fmt.pix_mp.pixelformat = output_buffer_pixelformat_;
455   format.fmt.pix_mp.field = V4L2_FIELD_ANY;
456   format.fmt.pix_mp.plane_fmt[0].sizeimage = buffer_size;
457   format.fmt.pix_mp.width = coded_size.width();
458   format.fmt.pix_mp.height = coded_size.height();
459   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
460   DCHECK_EQ(format.fmt.pix_mp.pixelformat, output_buffer_pixelformat_);
461 
462   return true;
463 }
464 
RequestInputBuffers()465 bool V4L2JpegEncodeAccelerator::EncodedInstance::RequestInputBuffers() {
466   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
467   struct v4l2_format format;
468   memset(&format, 0, sizeof(format));
469   format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
470   format.fmt.pix_mp.pixelformat = input_buffer_pixelformat_;
471   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_FMT, &format);
472 
473   struct v4l2_requestbuffers reqbufs;
474   memset(&reqbufs, 0, sizeof(reqbufs));
475   reqbufs.count = kBufferCount;
476   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
477   reqbufs.memory = V4L2_MEMORY_MMAP;
478   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
479 
480   DCHECK(input_buffer_map_.empty());
481   input_buffer_map_.resize(reqbufs.count);
482 
483   for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
484     free_input_buffers_.push_back(i);
485 
486     struct v4l2_buffer buffer;
487     struct v4l2_plane planes[kMaxI420Plane];
488     memset(&buffer, 0, sizeof(buffer));
489     memset(planes, 0, sizeof(planes));
490     buffer.index = i;
491     buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
492     buffer.memory = V4L2_MEMORY_MMAP;
493     buffer.m.planes = planes;
494     buffer.length = base::size(planes);
495     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
496 
497     if (input_buffer_num_planes_ != buffer.length) {
498       return false;
499     }
500     for (size_t j = 0; j < buffer.length; ++j) {
501       if (base::checked_cast<int64_t>(planes[j].length) <
502           VideoFrame::PlaneSize(
503               PIXEL_FORMAT_I420, j,
504               gfx::Size(format.fmt.pix_mp.width, format.fmt.pix_mp.height))
505               .GetArea()) {
506         return false;
507       }
508       void* address =
509           device_->Mmap(NULL, planes[j].length, PROT_READ | PROT_WRITE,
510                         MAP_SHARED, planes[j].m.mem_offset);
511       if (address == MAP_FAILED) {
512         VPLOGF(1) << "mmap() failed";
513         return false;
514       }
515       input_buffer_map_[i].address[j] = address;
516       input_buffer_map_[i].length[j] = planes[j].length;
517     }
518   }
519 
520   return true;
521 }
522 
RequestOutputBuffers()523 bool V4L2JpegEncodeAccelerator::EncodedInstance::RequestOutputBuffers() {
524   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
525   struct v4l2_requestbuffers reqbufs;
526   memset(&reqbufs, 0, sizeof(reqbufs));
527   reqbufs.count = kBufferCount;
528   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
529   reqbufs.memory = V4L2_MEMORY_MMAP;
530   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
531 
532   DCHECK(output_buffer_map_.empty());
533   output_buffer_map_.resize(reqbufs.count);
534 
535   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
536     free_output_buffers_.push_back(i);
537 
538     struct v4l2_buffer buffer;
539     struct v4l2_plane planes[kMaxJpegPlane];
540     memset(&buffer, 0, sizeof(buffer));
541     memset(planes, 0, sizeof(planes));
542     buffer.index = i;
543     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
544     buffer.m.planes = planes;
545     buffer.length = base::size(planes);
546     buffer.memory = V4L2_MEMORY_MMAP;
547     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
548     if (buffer.length != kMaxJpegPlane) {
549       return false;
550     }
551     void* address =
552         device_->Mmap(NULL, planes[0].length, PROT_READ | PROT_WRITE,
553                       MAP_SHARED, planes[0].m.mem_offset);
554     if (address == MAP_FAILED) {
555       VPLOGF(1) << "mmap() failed";
556       return false;
557     }
558     output_buffer_map_[i].address[0] = address;
559     output_buffer_map_[i].length[0] = planes[0].length;
560   }
561 
562   return true;
563 }
564 
DestroyInputBuffers()565 void V4L2JpegEncodeAccelerator::EncodedInstance::DestroyInputBuffers() {
566   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
567   free_input_buffers_.clear();
568 
569   if (input_buffer_map_.empty())
570     return;
571 
572   if (input_streamon_) {
573     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
574     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
575     input_streamon_ = false;
576   }
577 
578   for (const auto& input_record : input_buffer_map_) {
579     for (size_t i = 0; i < input_buffer_num_planes_; ++i) {
580       device_->Munmap(input_record.address[i], input_record.length[i]);
581     }
582   }
583 
584   struct v4l2_requestbuffers reqbufs;
585   memset(&reqbufs, 0, sizeof(reqbufs));
586   reqbufs.count = 0;
587   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
588   reqbufs.memory = V4L2_MEMORY_MMAP;
589   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
590 
591   input_buffer_map_.clear();
592   input_buffer_num_planes_ = 0;
593 }
594 
DestroyOutputBuffers()595 void V4L2JpegEncodeAccelerator::EncodedInstance::DestroyOutputBuffers() {
596   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
597   free_output_buffers_.clear();
598 
599   if (output_buffer_map_.empty())
600     return;
601 
602   if (output_streamon_) {
603     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
604     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
605     output_streamon_ = false;
606   }
607 
608   for (const auto& output_record : output_buffer_map_) {
609     device_->Munmap(output_record.address[0], output_record.length[0]);
610   }
611 
612   struct v4l2_requestbuffers reqbufs;
613   memset(&reqbufs, 0, sizeof(reqbufs));
614   reqbufs.count = 0;
615   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
616   reqbufs.memory = V4L2_MEMORY_MMAP;
617   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
618 
619   output_buffer_map_.clear();
620 }
621 
ServiceDevice()622 void V4L2JpegEncodeAccelerator::EncodedInstance::ServiceDevice() {
623   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
624 
625   if (!running_job_queue_.empty()) {
626     Dequeue();
627   }
628 
629   EnqueueInput();
630   EnqueueOutput();
631 
632   DVLOGF(3) << "buffer counts: INPUT[" << input_job_queue_.size()
633             << "] => DEVICE[" << free_input_buffers_.size() << "/"
634             << input_buffer_map_.size() << "->" << free_output_buffers_.size()
635             << "/" << output_buffer_map_.size() << "]";
636 }
637 
EnqueueInput()638 void V4L2JpegEncodeAccelerator::EncodedInstance::EnqueueInput() {
639   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
640   while (!input_job_queue_.empty() && !free_input_buffers_.empty()) {
641     if (!EnqueueInputRecord())
642       return;
643   }
644 
645   if (!input_streamon_ && InputBufferQueuedCount()) {
646     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
647     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
648     input_streamon_ = true;
649   }
650 }
651 
EnqueueOutput()652 void V4L2JpegEncodeAccelerator::EncodedInstance::EnqueueOutput() {
653   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
654   while (running_job_queue_.size() > OutputBufferQueuedCount() &&
655          !free_output_buffers_.empty()) {
656     if (!EnqueueOutputRecord())
657       return;
658   }
659 
660   if (!output_streamon_ && OutputBufferQueuedCount()) {
661     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
662     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
663     output_streamon_ = true;
664   }
665 }
666 
EnqueueInputRecord()667 bool V4L2JpegEncodeAccelerator::EncodedInstance::EnqueueInputRecord() {
668   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
669   DCHECK(!input_job_queue_.empty());
670   DCHECK(!free_input_buffers_.empty());
671 
672   // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
673   std::unique_ptr<JobRecord> job_record = std::move(input_job_queue_.front());
674   input_job_queue_.pop();
675   const int index = free_input_buffers_.back();
676   I420BufferRecord& input_record = input_buffer_map_[index];
677   DCHECK(!input_record.at_device);
678 
679   // Copy image from user memory to MMAP memory.
680   uint8_t* src_y = job_record->input_frame->data(VideoFrame::kYPlane);
681   uint8_t* src_u = job_record->input_frame->data(VideoFrame::kUPlane);
682   uint8_t* src_v = job_record->input_frame->data(VideoFrame::kVPlane);
683   size_t src_y_stride = job_record->input_frame->stride(VideoFrame::kYPlane);
684   size_t src_u_stride = job_record->input_frame->stride(VideoFrame::kUPlane);
685   size_t src_v_stride = job_record->input_frame->stride(VideoFrame::kVPlane);
686 
687   size_t input_coded_width = job_record->input_frame->coded_size().width();
688   size_t input_coded_height = job_record->input_frame->coded_size().height();
689 
690   size_t dst_y_stride = bytes_per_line_[0];
691   size_t dst_u_stride;
692   size_t dst_v_stride;
693 
694   uint8_t* dst_y = static_cast<uint8_t*>(input_record.address[0]);
695   uint8_t* dst_u;
696   uint8_t* dst_v;
697 
698   if (input_buffer_num_planes_ == 1) {
699     dst_u_stride = dst_y_stride / 2;
700     dst_v_stride = dst_y_stride / 2;
701     dst_u = dst_y + dst_y_stride * input_buffer_height_;
702     dst_v = dst_u + dst_u_stride * input_buffer_height_ / 2;
703   } else {
704     DCHECK(input_buffer_num_planes_ == 3);
705 
706     dst_u_stride = bytes_per_line_[1];
707     dst_v_stride = bytes_per_line_[2];
708 
709     dst_u = static_cast<uint8_t*>(input_record.address[1]);
710     dst_v = static_cast<uint8_t*>(input_record.address[2]);
711   }
712 
713   if (libyuv::I420Copy(src_y, src_y_stride, src_u, src_u_stride, src_v,
714                        src_v_stride, dst_y, dst_y_stride, dst_u, dst_u_stride,
715                        dst_v, dst_v_stride, input_coded_width,
716                        input_coded_height)) {
717     VLOGF(1) << "I420Copy failed";
718     return false;
719   }
720 
721   struct v4l2_buffer qbuf;
722   struct v4l2_plane planes[kMaxI420Plane];
723   memset(&qbuf, 0, sizeof(qbuf));
724   memset(planes, 0, sizeof(planes));
725   qbuf.index = index;
726   qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
727   qbuf.memory = V4L2_MEMORY_MMAP;
728   qbuf.length = base::size(planes);
729   for (size_t i = 0; i < input_buffer_num_planes_; i++) {
730     // sets this to 0 means the size of the plane.
731     planes[i].bytesused = 0;
732   }
733   qbuf.m.planes = planes;
734   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
735   input_record.at_device = true;
736   running_job_queue_.push(std::move(job_record));
737   free_input_buffers_.pop_back();
738 
739   DVLOGF(3) << "enqueued frame id=" << job_record->task_id << " to device.";
740   return true;
741 }
742 
EnqueueOutputRecord()743 bool V4L2JpegEncodeAccelerator::EncodedInstance::EnqueueOutputRecord() {
744   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
745   DCHECK(!free_output_buffers_.empty());
746 
747   // Enqueue an output (VIDEO_CAPTURE) buffer.
748   const int index = free_output_buffers_.back();
749   JpegBufferRecord& output_record = output_buffer_map_[index];
750   DCHECK(!output_record.at_device);
751   struct v4l2_buffer qbuf;
752   struct v4l2_plane planes[kMaxJpegPlane];
753   memset(&qbuf, 0, sizeof(qbuf));
754   memset(planes, 0, sizeof(planes));
755   qbuf.index = index;
756   qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
757   qbuf.memory = V4L2_MEMORY_MMAP;
758   qbuf.length = base::size(planes);
759   qbuf.m.planes = planes;
760   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
761   output_record.at_device = true;
762   free_output_buffers_.pop_back();
763   return true;
764 }
765 
FinalizeJpegImage(uint8_t * dst_ptr,const JpegBufferRecord & output_buffer,size_t buffer_size,std::unique_ptr<UnalignedSharedMemory> exif_shm)766 size_t V4L2JpegEncodeAccelerator::EncodedInstance::FinalizeJpegImage(
767     uint8_t* dst_ptr,
768     const JpegBufferRecord& output_buffer,
769     size_t buffer_size,
770     std::unique_ptr<UnalignedSharedMemory> exif_shm) {
771   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
772   size_t idx;
773 
774   // Fill SOI and EXIF markers.
775   dst_ptr[0] = 0xFF;
776   dst_ptr[1] = JPEG_SOI;
777   idx = 2;
778 
779   if (exif_shm) {
780     uint8_t* exif_buffer = static_cast<uint8_t*>(exif_shm->memory());
781     size_t exif_buffer_size = exif_shm->size();
782     // Application Segment for Exif data.
783     uint16_t exif_segment_size = static_cast<uint16_t>(exif_buffer_size + 2);
784     const uint8_t kAppSegment[] = {
785         0xFF, JPEG_APP1, static_cast<uint8_t>(exif_segment_size / 256),
786         static_cast<uint8_t>(exif_segment_size % 256)};
787     memcpy(dst_ptr + idx, kAppSegment, sizeof(kAppSegment));
788     idx += sizeof(kAppSegment);
789     memcpy(dst_ptr + idx, exif_buffer, exif_buffer_size);
790     idx += exif_buffer_size;
791   } else {
792     // Application Segment - JFIF standard 1.01.
793     static const uint8_t kAppSegment[] = {
794         0xFF, JPEG_APP0, 0x00,
795         0x10,  // Segment length:16 (2-byte).
796         0x4A,  // J
797         0x46,  // F
798         0x49,  // I
799         0x46,  // F
800         0x00,  // 0
801         0x01,  // Major version.
802         0x01,  // Minor version.
803         0x01,  // Density units 0:no units, 1:pixels per inch,
804                // 2: pixels per cm.
805         0x00,
806         0x48,  // X density (2-byte).
807         0x00,
808         0x48,  // Y density (2-byte).
809         0x00,  // Thumbnail width.
810         0x00   // Thumbnail height.
811     };
812     memcpy(dst_ptr + idx, kAppSegment, sizeof(kAppSegment));
813     idx += sizeof(kAppSegment);
814   }
815 
816   switch (output_buffer_pixelformat_) {
817     case V4L2_PIX_FMT_JPEG_RAW:
818       // Fill the other jpeg markers for RAW JPEG.
819       memcpy(dst_ptr + idx, jpeg_markers_.data(), jpeg_markers_.size());
820       idx += jpeg_markers_.size();
821       // Fill Compressed stream.
822       memcpy(dst_ptr + idx, output_buffer.address[0], buffer_size);
823       idx += buffer_size;
824       // Fill EOI. Before Fill EOI we checked if the V4L2 device filled EOI
825       // first.
826       if (dst_ptr[idx - 2] != 0xFF && dst_ptr[idx - 1] != JPEG_EOI) {
827         dst_ptr[idx] = 0xFF;
828         dst_ptr[idx + 1] = JPEG_EOI;
829         idx += 2;
830       }
831       break;
832 
833     default:
834       NOTREACHED() << "Unsupported output pixel format";
835   }
836 
837   return idx;
838 }
839 
Dequeue()840 void V4L2JpegEncodeAccelerator::EncodedInstance::Dequeue() {
841   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
842   // Dequeue completed input (VIDEO_OUTPUT) buffers,
843   // and recycle to the free list.
844   struct v4l2_buffer dqbuf;
845   struct v4l2_plane planes[kMaxI420Plane];
846   while (InputBufferQueuedCount() > 0) {
847     DCHECK(input_streamon_);
848     memset(&dqbuf, 0, sizeof(dqbuf));
849     memset(planes, 0, sizeof(planes));
850     dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
851     dqbuf.memory = V4L2_MEMORY_MMAP;
852     dqbuf.length = base::size(planes);
853     dqbuf.m.planes = planes;
854     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
855       if (errno == EAGAIN) {
856         // EAGAIN if we're just out of buffers to dequeue.
857         break;
858       }
859       VPLOGF(1) << "ioctl() failed: input buffer VIDIOC_DQBUF failed.";
860       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
861       return;
862     }
863     I420BufferRecord& input_record = input_buffer_map_[dqbuf.index];
864     DCHECK(input_record.at_device);
865     input_record.at_device = false;
866     free_input_buffers_.push_back(dqbuf.index);
867 
868     if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
869       VLOGF(1) << "Error in dequeued input buffer.";
870       NotifyError(kInvalidBitstreamBufferId, PARSE_IMAGE_FAILED);
871       running_job_queue_.pop();
872     }
873   }
874 
875   // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
876   // Return the finished buffer to the client via the job ready callback.
877   // If dequeued input buffer has an error, the error frame has removed from
878   // |running_job_queue_|. We only have to dequeue output buffer when we
879   // actually have pending frames in |running_job_queue_| and also enqueued
880   // output buffers.
881   while (!running_job_queue_.empty() && OutputBufferQueuedCount() > 0) {
882     DCHECK(output_streamon_);
883     memset(&dqbuf, 0, sizeof(dqbuf));
884     memset(planes, 0, sizeof(planes));
885     dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
886     dqbuf.memory = V4L2_MEMORY_MMAP;
887     dqbuf.length = base::size(planes);
888     dqbuf.m.planes = planes;
889     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
890       if (errno == EAGAIN) {
891         // EAGAIN if we're just out of buffers to dequeue.
892         break;
893       }
894       VPLOGF(1) << "ioctl() failed: output buffer VIDIOC_DQBUF failed.";
895       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
896       return;
897     }
898     JpegBufferRecord& output_record = output_buffer_map_[dqbuf.index];
899     DCHECK(output_record.at_device);
900     output_record.at_device = false;
901     free_output_buffers_.push_back(dqbuf.index);
902 
903     // Jobs are always processed in FIFO order.
904     std::unique_ptr<JobRecord> job_record =
905         std::move(running_job_queue_.front());
906     running_job_queue_.pop();
907 
908     if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
909       VLOGF(1) << "Error in dequeued output buffer.";
910       NotifyError(kInvalidBitstreamBufferId, PARSE_IMAGE_FAILED);
911       return;
912     }
913 
914     size_t jpeg_size = FinalizeJpegImage(
915         static_cast<uint8_t*>(job_record->output_shm.memory()), output_record,
916         planes[0].bytesused, std::move(job_record->exif_shm));
917     if (!jpeg_size) {
918       NotifyError(job_record->task_id, PLATFORM_FAILURE);
919       return;
920     }
921     DVLOGF(4) << "Encoding finished, returning bitstream buffer, id="
922               << job_record->task_id;
923 
924     parent_->VideoFrameReady(job_record->task_id, jpeg_size);
925   }
926 }
927 
NotifyError(int32_t task_id,Status status)928 void V4L2JpegEncodeAccelerator::EncodedInstance::NotifyError(int32_t task_id,
929                                                              Status status) {
930   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
931   parent_->NotifyError(task_id, status);
932 }
933 
EncodedInstanceDmaBuf(V4L2JpegEncodeAccelerator * parent)934 V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::EncodedInstanceDmaBuf(
935     V4L2JpegEncodeAccelerator* parent)
936     : parent_(parent),
937       input_streamon_(false),
938       output_streamon_(false),
939       input_buffer_pixelformat_(0),
940       input_buffer_num_planes_(0),
941       output_buffer_pixelformat_(0) {}
942 
~EncodedInstanceDmaBuf()943 V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::~EncodedInstanceDmaBuf() {}
944 
DestroyTask()945 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::DestroyTask() {
946   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
947   while (!input_job_queue_.empty())
948     input_job_queue_.pop();
949   while (!running_job_queue_.empty())
950     running_job_queue_.pop();
951 
952   DestroyInputBuffers();
953   DestroyOutputBuffers();
954 }
955 
Initialize()956 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::Initialize() {
957   device_ = V4L2Device::Create();
958   gpu_memory_buffer_support_ = std::make_unique<gpu::GpuMemoryBufferSupport>();
959 
960   if (!device_) {
961     VLOGF(1) << "Failed to Create V4L2Device";
962     return false;
963   }
964 
965   output_buffer_pixelformat_ = V4L2_PIX_FMT_JPEG_RAW;
966   if (!device_->Open(V4L2Device::Type::kJpegEncoder,
967                      output_buffer_pixelformat_)) {
968     VLOGF(1) << "Failed to open device";
969     return false;
970   }
971 
972   // Capabilities check.
973   struct v4l2_capability caps;
974   const __u32 kCapsRequired = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
975   memset(&caps, 0, sizeof(caps));
976   if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
977     VPLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP";
978     return false;
979   }
980   if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
981     VLOGF(1) << "VIDIOC_QUERYCAP, caps check failed: 0x" << std::hex
982              << caps.capabilities;
983     return false;
984   }
985 
986   return true;
987 }
988 
989 // static
FillQuantizationTable(int quality,const uint8_t * basic_table,uint8_t * dst_table)990 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::FillQuantizationTable(
991     int quality,
992     const uint8_t* basic_table,
993     uint8_t* dst_table) {
994   unsigned int temp;
995 
996   if (quality < 50)
997     quality = 5000 / quality;
998   else
999     quality = 200 - quality * 2;
1000 
1001   for (size_t i = 0; i < kDctSize; i++) {
1002     temp = ((unsigned int)basic_table[kZigZag8x8[i]] * quality + 50) / 100;
1003     /* limit the values to the valid range */
1004     dst_table[i] = base::ClampToRange(temp, 1u, 255u);
1005   }
1006 }
1007 
PrepareJpegMarkers(gfx::Size coded_size)1008 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::PrepareJpegMarkers(
1009     gfx::Size coded_size) {
1010   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1011   // Quantization Tables.
1012   // i = 0 for Luminance
1013   // i = 1 for Chrominance
1014   const int kNumDQT = 2;
1015   for (size_t i = 0; i < kNumDQT; ++i) {
1016     const uint8_t kQuantSegment[] = {
1017         0xFF, JPEG_DQT, 0x00,
1018         0x03 + kDctSize,         // Segment length:67 (2-byte).
1019         static_cast<uint8_t>(i)  // Precision (4-bit high) = 0,
1020                                  // Index (4-bit low) = i.
1021     };
1022     for (size_t j = 0; j < sizeof(kQuantSegment); ++j) {
1023       jpeg_markers_.push_back(kQuantSegment[j]);
1024     }
1025 
1026     for (size_t j = 0; j < kDctSize; ++j) {
1027       jpeg_markers_.push_back(quantization_table_[i].value[j]);
1028     }
1029   }
1030 
1031   // Start of Frame - Baseline.
1032   const int kNumOfComponents = 3;
1033   const uint8_t kStartOfFrame[] = {
1034       0xFF,
1035       JPEG_SOF0,  // Baseline.
1036       0x00,
1037       0x11,  // Segment length:17 (2-byte).
1038       8,     // Data precision.
1039       static_cast<uint8_t>((coded_size.height() >> 8) & 0xFF),
1040       static_cast<uint8_t>(coded_size.height() & 0xFF),
1041       static_cast<uint8_t>((coded_size.width() >> 8) & 0xFF),
1042       static_cast<uint8_t>(coded_size.width() & 0xFF),
1043       kNumOfComponents,
1044   };
1045   for (size_t i = 0; i < sizeof(kStartOfFrame); ++i) {
1046     jpeg_markers_.push_back(kStartOfFrame[i]);
1047   }
1048   // i = 0 for Y Plane
1049   // i = 1 for U Plane
1050   // i = 2 for V Plane
1051   for (size_t i = 0; i < kNumOfComponents; ++i) {
1052     // These are the values for U and V planes.
1053     uint8_t h_sample_factor = 1;
1054     uint8_t v_sample_factor = 1;
1055     uint8_t quant_table_number = 1;
1056     if (!i) {
1057       // These are the values for Y plane.
1058       h_sample_factor = 2;
1059       v_sample_factor = 2;
1060       quant_table_number = 0;
1061     }
1062 
1063     jpeg_markers_.push_back(i + 1);
1064     // Horizontal Sample Factor (4-bit high),
1065     // Vertical Sample Factor (4-bit low).
1066     jpeg_markers_.push_back((h_sample_factor << 4) | v_sample_factor);
1067     jpeg_markers_.push_back(quant_table_number);
1068   }
1069 
1070   // Huffman Tables.
1071   static const uint8_t kDcSegment[] = {
1072       0xFF, JPEG_DHT, 0x00,
1073       0x1F,  // Segment length:31 (2-byte).
1074   };
1075   static const uint8_t kAcSegment[] = {
1076       0xFF, JPEG_DHT, 0x00,
1077       0xB5,  // Segment length:181 (2-byte).
1078   };
1079 
1080   // i = 0 for Luminance
1081   // i = 1 for Chrominance
1082   const int kNumHuffmanTables = 2;
1083   for (size_t i = 0; i < kNumHuffmanTables; ++i) {
1084     // DC Table.
1085     for (size_t j = 0; j < sizeof(kDcSegment); ++j) {
1086       jpeg_markers_.push_back(kDcSegment[j]);
1087     }
1088 
1089     // Type (4-bit high) = 0:DC, Index (4-bit low).
1090     jpeg_markers_.push_back(static_cast<uint8_t>(i));
1091 
1092     const JpegHuffmanTable& dcTable = kDefaultDcTable[i];
1093     for (size_t j = 0; j < kNumDcRunSizeBits; ++j)
1094       jpeg_markers_.push_back(dcTable.code_length[j]);
1095     for (size_t j = 0; j < kNumDcCodeWordsHuffVal; ++j)
1096       jpeg_markers_.push_back(dcTable.code_value[j]);
1097 
1098     // AC Table.
1099     for (size_t j = 0; j < sizeof(kAcSegment); ++j) {
1100       jpeg_markers_.push_back(kAcSegment[j]);
1101     }
1102 
1103     // Type (4-bit high) = 1:AC, Index (4-bit low).
1104     jpeg_markers_.push_back(0x10 | static_cast<uint8_t>(i));
1105 
1106     const JpegHuffmanTable& acTable = kDefaultAcTable[i];
1107     for (size_t j = 0; j < kNumAcRunSizeBits; ++j)
1108       jpeg_markers_.push_back(acTable.code_length[j]);
1109     for (size_t j = 0; j < kNumAcCodeWordsHuffVal; ++j)
1110       jpeg_markers_.push_back(acTable.code_value[j]);
1111   }
1112 
1113   // Start of Scan.
1114   static const uint8_t kStartOfScan[] = {
1115       0xFF, JPEG_SOS, 0x00,
1116       0x0C,  // Segment Length:12 (2-byte).
1117       0x03   // Number of components in scan.
1118   };
1119   for (size_t i = 0; i < sizeof(kStartOfScan); ++i) {
1120     jpeg_markers_.push_back(kStartOfScan[i]);
1121   }
1122 
1123   // i = 0 for Y Plane
1124   // i = 1 for U Plane
1125   // i = 2 for V Plane
1126   for (uint8_t i = 0; i < kNumOfComponents; ++i) {
1127     uint8_t dc_table_number = 1;
1128     uint8_t ac_table_number = 1;
1129     if (!i) {
1130       dc_table_number = 0;
1131       ac_table_number = 0;
1132     }
1133 
1134     jpeg_markers_.push_back(i + 1);
1135     // DC Table Selector (4-bit high), AC Table Selector (4-bit low).
1136     jpeg_markers_.push_back((dc_table_number << 4) | ac_table_number);
1137   }
1138   jpeg_markers_.push_back(0x00);  // 0 for Baseline.
1139   jpeg_markers_.push_back(0x3F);  // 63 for Baseline.
1140   jpeg_markers_.push_back(0x00);  // 0 for Baseline.
1141 }
1142 
SetUpJpegParameters(int quality,gfx::Size coded_size)1143 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::SetUpJpegParameters(
1144     int quality,
1145     gfx::Size coded_size) {
1146   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1147 
1148   struct v4l2_ext_controls ctrls;
1149   struct v4l2_ext_control ctrl;
1150 
1151   memset(&ctrls, 0, sizeof(ctrls));
1152   memset(&ctrl, 0, sizeof(ctrl));
1153 
1154   ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
1155   ctrls.controls = &ctrl;
1156   ctrls.count = 1;
1157 
1158   switch (output_buffer_pixelformat_) {
1159     case V4L2_PIX_FMT_JPEG_RAW:
1160       FillQuantizationTable(quality, kDefaultQuantTable[0].value,
1161                             quantization_table_[0].value);
1162       FillQuantizationTable(quality, kDefaultQuantTable[1].value,
1163                             quantization_table_[1].value);
1164 
1165       ctrl.id = V4L2_CID_JPEG_LUMA_QUANTIZATION;
1166       ctrl.size = kDctSize;
1167       ctrl.ptr = quantization_table_[0].value;
1168       IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, &ctrls);
1169 
1170       ctrl.id = V4L2_CID_JPEG_CHROMA_QUANTIZATION;
1171       ctrl.size = kDctSize;
1172       ctrl.ptr = quantization_table_[1].value;
1173       IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, &ctrls);
1174 
1175       // We need to prepare our own JPEG Markers.
1176       PrepareJpegMarkers(coded_size);
1177       break;
1178 
1179     default:
1180       NOTREACHED();
1181   }
1182 
1183   return true;
1184 }
1185 
1186 size_t
InputBufferQueuedCount()1187 V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::InputBufferQueuedCount() {
1188   return kBufferCount - free_input_buffers_.size();
1189 }
1190 
1191 size_t
OutputBufferQueuedCount()1192 V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::OutputBufferQueuedCount() {
1193   return kBufferCount - free_output_buffers_.size();
1194 }
1195 
CreateBuffers(gfx::Size coded_size,const VideoFrameLayout & input_layout,size_t output_buffer_size)1196 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::CreateBuffers(
1197     gfx::Size coded_size,
1198     const VideoFrameLayout& input_layout,
1199     size_t output_buffer_size) {
1200   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1201 
1202   // The order of set output/input formats matters.
1203   // rk3399 reset input format when we set output format.
1204   if (!SetOutputBufferFormat(coded_size, output_buffer_size)) {
1205     return false;
1206   }
1207 
1208   if (!SetInputBufferFormat(coded_size, input_layout)) {
1209     return false;
1210   }
1211 
1212   if (!RequestInputBuffers()) {
1213     return false;
1214   }
1215 
1216   if (!RequestOutputBuffers()) {
1217     return false;
1218   }
1219 
1220   return true;
1221 }
1222 
SetInputBufferFormat(gfx::Size coded_size,const VideoFrameLayout & input_layout)1223 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::SetInputBufferFormat(
1224     gfx::Size coded_size,
1225     const VideoFrameLayout& input_layout) {
1226   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1227   DCHECK(!input_streamon_);
1228   DCHECK(input_job_queue_.empty());
1229 
1230   constexpr uint32_t input_pix_fmt_candidates[] = {V4L2_PIX_FMT_NV12M,
1231                                                    V4L2_PIX_FMT_NV12};
1232 
1233   struct v4l2_format format;
1234   input_buffer_pixelformat_ = 0;
1235   for (const auto input_pix_fmt : input_pix_fmt_candidates) {
1236     DCHECK_EQ(Fourcc::FromV4L2PixFmt(input_pix_fmt)->ToVideoPixelFormat(),
1237               PIXEL_FORMAT_NV12);
1238     memset(&format, 0, sizeof(format));
1239     format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1240     format.fmt.pix_mp.num_planes = kMaxNV12Plane;
1241     format.fmt.pix_mp.pixelformat = input_pix_fmt;
1242     format.fmt.pix_mp.field = V4L2_FIELD_ANY;
1243     format.fmt.pix_mp.width = coded_size.width();
1244     format.fmt.pix_mp.height = coded_size.height();
1245 
1246     auto num_planes = input_layout.num_planes();
1247     for (size_t i = 0; i < num_planes; i++) {
1248       format.fmt.pix_mp.plane_fmt[i].sizeimage = input_layout.planes()[i].size;
1249       format.fmt.pix_mp.plane_fmt[i].bytesperline =
1250           input_layout.planes()[i].stride;
1251     }
1252 
1253     if (device_->Ioctl(VIDIOC_S_FMT, &format) == 0 &&
1254         format.fmt.pix_mp.pixelformat == input_pix_fmt) {
1255       device_input_layout_ = V4L2Device::V4L2FormatToVideoFrameLayout(format);
1256 
1257       // Save V4L2 returned values.
1258       input_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
1259       input_buffer_num_planes_ = format.fmt.pix_mp.num_planes;
1260       input_buffer_height_ = format.fmt.pix_mp.height;
1261       break;
1262     }
1263   }
1264 
1265   if (input_buffer_pixelformat_ == 0) {
1266     VLOGF(1) << "Neither NV12 nor NV12M is supported.";
1267     return false;
1268   }
1269 
1270   if (format.fmt.pix_mp.width != static_cast<uint32_t>(coded_size.width()) ||
1271       format.fmt.pix_mp.height != static_cast<uint32_t>(coded_size.height())) {
1272     VLOGF(1) << "Width " << coded_size.width() << "->"
1273              << format.fmt.pix_mp.width << ",Height " << coded_size.height()
1274              << "->" << format.fmt.pix_mp.height;
1275     return false;
1276   }
1277   return true;
1278 }
1279 
SetOutputBufferFormat(gfx::Size coded_size,size_t buffer_size)1280 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::SetOutputBufferFormat(
1281     gfx::Size coded_size,
1282     size_t buffer_size) {
1283   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1284   DCHECK(!output_streamon_);
1285   DCHECK(running_job_queue_.empty());
1286 
1287   struct v4l2_format format;
1288   memset(&format, 0, sizeof(format));
1289   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1290   format.fmt.pix_mp.num_planes = kMaxJpegPlane;
1291   format.fmt.pix_mp.pixelformat = output_buffer_pixelformat_;
1292   format.fmt.pix_mp.field = V4L2_FIELD_ANY;
1293   format.fmt.pix_mp.plane_fmt[0].sizeimage = buffer_size;
1294   format.fmt.pix_mp.width = coded_size.width();
1295   format.fmt.pix_mp.height = coded_size.height();
1296   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
1297   DCHECK_EQ(format.fmt.pix_mp.pixelformat, output_buffer_pixelformat_);
1298 
1299   return true;
1300 }
1301 
RequestInputBuffers()1302 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::RequestInputBuffers() {
1303   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1304   struct v4l2_format format;
1305   memset(&format, 0, sizeof(format));
1306   format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1307   format.fmt.pix_mp.pixelformat = input_buffer_pixelformat_;
1308   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_FMT, &format);
1309 
1310   struct v4l2_requestbuffers reqbufs;
1311   memset(&reqbufs, 0, sizeof(reqbufs));
1312   reqbufs.count = kBufferCount;
1313   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1314   reqbufs.memory = V4L2_MEMORY_DMABUF;
1315   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1316 
1317   DCHECK(free_input_buffers_.empty());
1318   for (size_t i = 0; i < reqbufs.count; ++i) {
1319     free_input_buffers_.push_back(i);
1320   }
1321 
1322   return true;
1323 }
1324 
RequestOutputBuffers()1325 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::RequestOutputBuffers() {
1326   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1327   struct v4l2_requestbuffers reqbufs;
1328   memset(&reqbufs, 0, sizeof(reqbufs));
1329   reqbufs.count = kBufferCount;
1330   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1331   reqbufs.memory = V4L2_MEMORY_DMABUF;
1332   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1333 
1334   DCHECK(free_output_buffers_.empty());
1335   for (size_t i = 0; i < reqbufs.count; ++i) {
1336     free_output_buffers_.push_back(i);
1337   }
1338 
1339   return true;
1340 }
1341 
DestroyInputBuffers()1342 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::DestroyInputBuffers() {
1343   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1344   free_input_buffers_.clear();
1345 
1346   if (input_streamon_) {
1347     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1348     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
1349     input_streamon_ = false;
1350   }
1351 
1352   struct v4l2_requestbuffers reqbufs;
1353   memset(&reqbufs, 0, sizeof(reqbufs));
1354   reqbufs.count = 0;
1355   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1356   reqbufs.memory = V4L2_MEMORY_DMABUF;
1357   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1358 
1359   input_buffer_num_planes_ = 0;
1360 }
1361 
DestroyOutputBuffers()1362 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::DestroyOutputBuffers() {
1363   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1364   free_output_buffers_.clear();
1365 
1366   if (output_streamon_) {
1367     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1368     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
1369     output_streamon_ = false;
1370   }
1371 
1372   struct v4l2_requestbuffers reqbufs;
1373   memset(&reqbufs, 0, sizeof(reqbufs));
1374   reqbufs.count = 0;
1375   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1376   reqbufs.memory = V4L2_MEMORY_DMABUF;
1377   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1378 }
1379 
ServiceDevice()1380 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::ServiceDevice() {
1381   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1382 
1383   if (!running_job_queue_.empty()) {
1384     Dequeue();
1385   }
1386 
1387   EnqueueInput();
1388   EnqueueOutput();
1389 
1390   DVLOGF(3) << "buffer counts: INPUT[" << input_job_queue_.size()
1391             << "] => DEVICE[" << free_input_buffers_.size() << "/"
1392             << "->" << free_output_buffers_.size() << "]";
1393 }
1394 
EnqueueInput()1395 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::EnqueueInput() {
1396   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1397   while (!input_job_queue_.empty() && !free_input_buffers_.empty()) {
1398     if (!EnqueueInputRecord())
1399       return;
1400   }
1401 
1402   if (!input_streamon_ && InputBufferQueuedCount()) {
1403     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1404     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
1405     input_streamon_ = true;
1406   }
1407 }
1408 
EnqueueOutput()1409 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::EnqueueOutput() {
1410   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1411   while (running_job_queue_.size() > OutputBufferQueuedCount() &&
1412          !free_output_buffers_.empty()) {
1413     if (!EnqueueOutputRecord())
1414       return;
1415   }
1416 
1417   if (!output_streamon_ && OutputBufferQueuedCount()) {
1418     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1419     IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
1420     output_streamon_ = true;
1421   }
1422 }
1423 
EnqueueInputRecord()1424 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::EnqueueInputRecord() {
1425   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1426   DCHECK(!input_job_queue_.empty());
1427   DCHECK(!free_input_buffers_.empty());
1428 
1429   // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
1430   std::unique_ptr<JobRecord> job_record = std::move(input_job_queue_.front());
1431   input_job_queue_.pop();
1432   const int index = free_input_buffers_.back();
1433 
1434   struct v4l2_buffer qbuf;
1435   struct v4l2_plane planes[kMaxNV12Plane];
1436   memset(&qbuf, 0, sizeof(qbuf));
1437   memset(planes, 0, sizeof(planes));
1438   qbuf.index = index;
1439   qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1440   qbuf.memory = V4L2_MEMORY_DMABUF;
1441   qbuf.length = base::size(planes);
1442   qbuf.m.planes = planes;
1443 
1444   const auto& frame = job_record->input_frame;
1445   for (size_t i = 0; i < input_buffer_num_planes_; i++) {
1446     if (device_input_layout_->is_multi_planar()) {
1447       qbuf.m.planes[i].bytesused = base::checked_cast<__u32>(
1448           VideoFrame::PlaneSize(frame->format(), i,
1449                                 device_input_layout_->coded_size())
1450               .GetArea());
1451     } else {
1452       qbuf.m.planes[i].bytesused = VideoFrame::AllocationSize(
1453           frame->format(), device_input_layout_->coded_size());
1454     }
1455 
1456     const auto& fds = frame->DmabufFds();
1457     const auto& planes = frame->layout().planes();
1458     qbuf.m.planes[i].m.fd = (i < fds.size()) ? fds[i].get() : fds.back().get();
1459     qbuf.m.planes[i].data_offset = planes[i].offset;
1460     qbuf.m.planes[i].bytesused += qbuf.m.planes[i].data_offset;
1461     qbuf.m.planes[i].length = planes[i].size + qbuf.m.planes[i].data_offset;
1462   }
1463 
1464   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1465   running_job_queue_.push(std::move(job_record));
1466   free_input_buffers_.pop_back();
1467   return true;
1468 }
1469 
EnqueueOutputRecord()1470 bool V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::EnqueueOutputRecord() {
1471   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1472   DCHECK(!free_output_buffers_.empty());
1473 
1474   // Enqueue an output (VIDEO_CAPTURE) buffer.
1475   const int index = free_output_buffers_.back();
1476   struct v4l2_buffer qbuf;
1477   struct v4l2_plane planes[kMaxJpegPlane];
1478   memset(&qbuf, 0, sizeof(qbuf));
1479   memset(planes, 0, sizeof(planes));
1480   qbuf.index = index;
1481   qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1482   qbuf.memory = V4L2_MEMORY_DMABUF;
1483   qbuf.length = base::size(planes);
1484   qbuf.m.planes = planes;
1485 
1486   auto& job_record = running_job_queue_.back();
1487   for (size_t i = 0; i < qbuf.length; i++) {
1488     planes[i].m.fd = job_record->output_frame->DmabufFds()[i].get();
1489   }
1490   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1491   free_output_buffers_.pop_back();
1492   return true;
1493 }
1494 
FinalizeJpegImage(scoped_refptr<VideoFrame> output_frame,size_t buffer_size,std::unique_ptr<UnalignedSharedMemory> exif_shm)1495 size_t V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::FinalizeJpegImage(
1496     scoped_refptr<VideoFrame> output_frame,
1497     size_t buffer_size,
1498     std::unique_ptr<UnalignedSharedMemory> exif_shm) {
1499   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1500   size_t idx = 0;
1501 
1502   auto output_gmb_handle = CreateGpuMemoryBufferHandle(output_frame.get());
1503   DCHECK(!output_gmb_handle.is_null());
1504 
1505   // In this case, we use the R_8 buffer with height == 1 to represent a data
1506   // container. As a result, we use plane.stride as size of the data here since
1507   // plane.size might be larger due to height alignment.
1508   const gfx::Size output_gmb_buffer_size(
1509       base::checked_cast<int32_t>(output_frame->layout().planes()[0].stride),
1510       1);
1511 
1512   auto output_gmb_buffer =
1513       gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
1514           std::move(output_gmb_handle), output_gmb_buffer_size,
1515           gfx::BufferFormat::R_8, gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
1516           base::DoNothing());
1517 
1518   bool isMapped = output_gmb_buffer->Map();
1519   if (!isMapped) {
1520     VLOGF(1) << "Failed to map gmb buffer";
1521     return 0;
1522   }
1523   uint8_t* dst_ptr = static_cast<uint8_t*>(output_gmb_buffer->memory(0));
1524 
1525   // Fill SOI and EXIF markers.
1526   static const uint8_t kJpegStart[] = {0xFF, JPEG_SOI};
1527 
1528   if (exif_shm) {
1529     uint8_t* exif_buffer = static_cast<uint8_t*>(exif_shm->memory());
1530     size_t exif_buffer_size = exif_shm->size();
1531     // Application Segment for Exif data.
1532     uint16_t exif_segment_size = static_cast<uint16_t>(exif_buffer_size + 2);
1533     const uint8_t kAppSegment[] = {
1534         0xFF, JPEG_APP1, static_cast<uint8_t>(exif_segment_size / 256),
1535         static_cast<uint8_t>(exif_segment_size % 256)};
1536 
1537     // Move compressed data first.
1538     size_t compressed_data_offset = sizeof(kJpegStart) + sizeof(kAppSegment) +
1539                                     exif_buffer_size + jpeg_markers_.size();
1540     memmove(dst_ptr + compressed_data_offset, dst_ptr, buffer_size);
1541 
1542     memcpy(dst_ptr, kJpegStart, sizeof(kJpegStart));
1543     idx += sizeof(kJpegStart);
1544     memcpy(dst_ptr + idx, kAppSegment, sizeof(kAppSegment));
1545     idx += sizeof(kAppSegment);
1546     memcpy(dst_ptr + idx, exif_buffer, exif_buffer_size);
1547     idx += exif_buffer_size;
1548   } else {
1549     // Application Segment - JFIF standard 1.01.
1550     static const uint8_t kAppSegment[] = {
1551         0xFF, JPEG_APP0, 0x00,
1552         0x10,  // Segment length:16 (2-byte).
1553         0x4A,  // J
1554         0x46,  // F
1555         0x49,  // I
1556         0x46,  // F
1557         0x00,  // 0
1558         0x01,  // Major version.
1559         0x01,  // Minor version.
1560         0x01,  // Density units 0:no units, 1:pixels per inch,
1561                // 2: pixels per cm.
1562         0x00,
1563         0x48,  // X density (2-byte).
1564         0x00,
1565         0x48,  // Y density (2-byte).
1566         0x00,  // Thumbnail width.
1567         0x00   // Thumbnail height.
1568     };
1569 
1570     // Move compressed data first.
1571     size_t compressed_data_offset =
1572         sizeof(kJpegStart) + sizeof(kAppSegment) + jpeg_markers_.size();
1573     memmove(dst_ptr + compressed_data_offset, dst_ptr, buffer_size);
1574 
1575     memcpy(dst_ptr, kJpegStart, sizeof(kJpegStart));
1576     idx += sizeof(kJpegStart);
1577 
1578     memcpy(dst_ptr + idx, kAppSegment, sizeof(kAppSegment));
1579     idx += sizeof(kAppSegment);
1580   }
1581 
1582   switch (output_buffer_pixelformat_) {
1583     case V4L2_PIX_FMT_JPEG_RAW:
1584       // Fill the other jpeg markers for RAW JPEG.
1585       memcpy(dst_ptr + idx, jpeg_markers_.data(), jpeg_markers_.size());
1586       idx += jpeg_markers_.size();
1587       // We already moved the compressed data.
1588       idx += buffer_size;
1589       // Fill EOI. Before Fill EOI we checked if the V4L2 device filled EOI
1590       // first.
1591       if (dst_ptr[idx - 2] != 0xFF && dst_ptr[idx - 1] != JPEG_EOI) {
1592         dst_ptr[idx] = 0xFF;
1593         dst_ptr[idx + 1] = JPEG_EOI;
1594         idx += 2;
1595       }
1596       break;
1597 
1598     default:
1599       NOTREACHED() << "Unsupported output pixel format";
1600   }
1601 
1602   output_gmb_buffer->Unmap();
1603 
1604   return idx;
1605 }
1606 
Dequeue()1607 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::Dequeue() {
1608   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1609   // Dequeue completed input (VIDEO_OUTPUT) buffers,
1610   // and recycle to the free list.
1611   struct v4l2_buffer dqbuf;
1612   struct v4l2_plane planes[kMaxNV12Plane];
1613   while (InputBufferQueuedCount() > 0) {
1614     DCHECK(input_streamon_);
1615     memset(&dqbuf, 0, sizeof(dqbuf));
1616     memset(planes, 0, sizeof(planes));
1617     dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1618     dqbuf.memory = V4L2_MEMORY_DMABUF;
1619     dqbuf.length = base::size(planes);
1620     dqbuf.m.planes = planes;
1621     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
1622       if (errno == EAGAIN) {
1623         // EAGAIN if we're just out of buffers to dequeue.
1624         break;
1625       }
1626       VPLOGF(1) << "ioctl() failed: input buffer VIDIOC_DQBUF failed.";
1627       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
1628       return;
1629     }
1630     free_input_buffers_.push_back(dqbuf.index);
1631 
1632     if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
1633       VLOGF(1) << "Error in dequeued input buffer.";
1634       NotifyError(kInvalidBitstreamBufferId, PARSE_IMAGE_FAILED);
1635       running_job_queue_.pop();
1636     }
1637   }
1638 
1639   // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
1640   // Return the finished buffer to the client via the job ready callback.
1641   // If dequeued input buffer has an error, the error frame has removed from
1642   // |running_job_queue_|. We only have to dequeue output buffer when we
1643   // actually have pending frames in |running_job_queue_| and also enqueued
1644   // output buffers.
1645   while (!running_job_queue_.empty() && OutputBufferQueuedCount() > 0) {
1646     DCHECK(output_streamon_);
1647     memset(&dqbuf, 0, sizeof(dqbuf));
1648     memset(planes, 0, sizeof(planes));
1649     dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1650     dqbuf.memory = V4L2_MEMORY_DMABUF;
1651     dqbuf.length = base::size(planes);
1652     dqbuf.m.planes = planes;
1653     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
1654       if (errno == EAGAIN) {
1655         // EAGAIN if we're just out of buffers to dequeue.
1656         break;
1657       }
1658       VPLOGF(1) << "ioctl() failed: output buffer VIDIOC_DQBUF failed.";
1659       NotifyError(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
1660       return;
1661     }
1662     free_output_buffers_.push_back(dqbuf.index);
1663 
1664     // Jobs are always processed in FIFO order.
1665     std::unique_ptr<JobRecord> job_record =
1666         std::move(running_job_queue_.front());
1667     running_job_queue_.pop();
1668 
1669     if (dqbuf.flags & V4L2_BUF_FLAG_ERROR) {
1670       VLOGF(1) << "Error in dequeued output buffer.";
1671       NotifyError(kInvalidBitstreamBufferId, PARSE_IMAGE_FAILED);
1672       return;
1673     }
1674 
1675     size_t jpeg_size =
1676         FinalizeJpegImage(job_record->output_frame, planes[0].bytesused,
1677                           std::move(job_record->exif_shm));
1678 
1679     if (!jpeg_size) {
1680       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1681       return;
1682     }
1683     DVLOGF(4) << "Encoding finished, returning bitstream buffer, id="
1684               << job_record->task_id;
1685 
1686     parent_->VideoFrameReady(job_record->task_id, jpeg_size);
1687   }
1688 }
1689 
NotifyError(int32_t task_id,Status status)1690 void V4L2JpegEncodeAccelerator::EncodedInstanceDmaBuf::NotifyError(
1691     int32_t task_id,
1692     Status status) {
1693   DCHECK(parent_->encoder_task_runner_->BelongsToCurrentThread());
1694   parent_->NotifyError(task_id, status);
1695 }
1696 
V4L2JpegEncodeAccelerator(const scoped_refptr<base::SingleThreadTaskRunner> & io_task_runner)1697 V4L2JpegEncodeAccelerator::V4L2JpegEncodeAccelerator(
1698     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
1699     : child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
1700       io_task_runner_(io_task_runner),
1701       client_(nullptr),
1702       encoder_thread_("V4L2JpegEncodeThread"),
1703       weak_factory_(this) {
1704   weak_ptr_ = weak_factory_.GetWeakPtr();
1705 }
1706 
~V4L2JpegEncodeAccelerator()1707 V4L2JpegEncodeAccelerator::~V4L2JpegEncodeAccelerator() {
1708   DCHECK(child_task_runner_->BelongsToCurrentThread());
1709 
1710   if (encoder_thread_.IsRunning()) {
1711     encoder_task_runner_->PostTask(
1712         FROM_HERE, base::BindOnce(&V4L2JpegEncodeAccelerator::DestroyTask,
1713                                   base::Unretained(this)));
1714     encoder_thread_.Stop();
1715   }
1716   weak_factory_.InvalidateWeakPtrs();
1717 }
1718 
DestroyTask()1719 void V4L2JpegEncodeAccelerator::DestroyTask() {
1720   DCHECK(encoder_task_runner_->BelongsToCurrentThread());
1721 
1722   while (!encoded_instances_.empty()) {
1723     encoded_instances_.front()->DestroyTask();
1724     encoded_instances_.pop();
1725   }
1726 
1727   while (!encoded_instances_dma_buf_.empty()) {
1728     encoded_instances_dma_buf_.front()->DestroyTask();
1729     encoded_instances_dma_buf_.pop();
1730   }
1731 }
1732 
VideoFrameReady(int32_t task_id,size_t encoded_picture_size)1733 void V4L2JpegEncodeAccelerator::VideoFrameReady(int32_t task_id,
1734                                                 size_t encoded_picture_size) {
1735   if (!child_task_runner_->BelongsToCurrentThread()) {
1736     child_task_runner_->PostTask(
1737         FROM_HERE, base::BindOnce(&V4L2JpegEncodeAccelerator::VideoFrameReady,
1738                                   weak_ptr_, task_id, encoded_picture_size));
1739     return;
1740   }
1741   VLOGF(1) << "Encoding finished task id=" << task_id
1742            << " Compressed size:" << encoded_picture_size;
1743   client_->VideoFrameReady(task_id, encoded_picture_size);
1744 }
1745 
NotifyError(int32_t task_id,Status status)1746 void V4L2JpegEncodeAccelerator::NotifyError(int32_t task_id, Status status) {
1747   if (!child_task_runner_->BelongsToCurrentThread()) {
1748     child_task_runner_->PostTask(
1749         FROM_HERE, base::BindOnce(&V4L2JpegEncodeAccelerator::NotifyError,
1750                                   weak_ptr_, task_id, status));
1751 
1752     return;
1753   }
1754   VLOGF(1) << "Notifying of error " << status << " for task id " << task_id;
1755   client_->NotifyError(task_id, status);
1756 }
1757 
1758 chromeos_camera::JpegEncodeAccelerator::Status
Initialize(chromeos_camera::JpegEncodeAccelerator::Client * client)1759 V4L2JpegEncodeAccelerator::Initialize(
1760     chromeos_camera::JpegEncodeAccelerator::Client* client) {
1761   DCHECK(child_task_runner_->BelongsToCurrentThread());
1762 
1763   std::unique_ptr<EncodedInstanceDmaBuf> encoded_device(
1764       new EncodedInstanceDmaBuf(this));
1765 
1766   // We just check if we can initialize device here.
1767   if (!encoded_device->Initialize()) {
1768     VLOGF(1) << "Failed to initialize device";
1769     return HW_JPEG_ENCODE_NOT_SUPPORTED;
1770   }
1771 
1772   if (!encoder_thread_.Start()) {
1773     VLOGF(1) << "encoder thread failed to start";
1774     return THREAD_CREATION_FAILED;
1775   }
1776 
1777   client_ = client;
1778 
1779   encoder_task_runner_ = encoder_thread_.task_runner();
1780 
1781   VLOGF(2) << "V4L2JpegEncodeAccelerator initialized.";
1782   return ENCODE_OK;
1783 }
1784 
GetMaxCodedBufferSize(const gfx::Size & picture_size)1785 size_t V4L2JpegEncodeAccelerator::GetMaxCodedBufferSize(
1786     const gfx::Size& picture_size) {
1787   return picture_size.GetArea() * 3 / 2 + kJpegDefaultHeaderSize;
1788 }
1789 
Encode(scoped_refptr<media::VideoFrame> video_frame,int quality,BitstreamBuffer * exif_buffer,BitstreamBuffer output_buffer)1790 void V4L2JpegEncodeAccelerator::Encode(
1791     scoped_refptr<media::VideoFrame> video_frame,
1792     int quality,
1793     BitstreamBuffer* exif_buffer,
1794     BitstreamBuffer output_buffer) {
1795   DCHECK(io_task_runner_->BelongsToCurrentThread());
1796 
1797   DVLOGF(4) << "task_id=" << output_buffer.id()
1798             << ", size=" << output_buffer.size();
1799 
1800   if (quality <= 0 || quality > 100) {
1801     VLOGF(1) << "quality is not in range. " << quality;
1802     NotifyError(output_buffer.id(), INVALID_ARGUMENT);
1803     return;
1804   }
1805 
1806   if (video_frame->format() != VideoPixelFormat::PIXEL_FORMAT_I420) {
1807     VLOGF(1) << "Format is not I420";
1808     NotifyError(output_buffer.id(), INVALID_ARGUMENT);
1809     return;
1810   }
1811 
1812   if (exif_buffer) {
1813     VLOGF(4) << "EXIF size " << exif_buffer->size();
1814     if (exif_buffer->size() > kMaxMarkerSizeAllowed) {
1815       NotifyError(output_buffer.id(), INVALID_ARGUMENT);
1816       return;
1817     }
1818   }
1819 
1820   std::unique_ptr<JobRecord> job_record(new JobRecord(
1821       video_frame, quality, exif_buffer, std::move(output_buffer)));
1822 
1823   encoder_task_runner_->PostTask(
1824       FROM_HERE,
1825       base::BindOnce(&V4L2JpegEncodeAccelerator::EncodeTaskLegacy,
1826                      base::Unretained(this), base::Passed(&job_record)));
1827 }
1828 
EncodeWithDmaBuf(scoped_refptr<VideoFrame> input_frame,scoped_refptr<VideoFrame> output_frame,int quality,int32_t task_id,BitstreamBuffer * exif_buffer)1829 void V4L2JpegEncodeAccelerator::EncodeWithDmaBuf(
1830     scoped_refptr<VideoFrame> input_frame,
1831     scoped_refptr<VideoFrame> output_frame,
1832     int quality,
1833     int32_t task_id,
1834     BitstreamBuffer* exif_buffer) {
1835   DCHECK(io_task_runner_->BelongsToCurrentThread());
1836 
1837   if (quality <= 0 || quality > 100) {
1838     VLOGF(1) << "quality is not in range. " << quality;
1839     NotifyError(task_id, INVALID_ARGUMENT);
1840     return;
1841   }
1842 
1843   if (input_frame->format() != VideoPixelFormat::PIXEL_FORMAT_NV12) {
1844     VLOGF(1) << "Format is not NV12";
1845     NotifyError(task_id, INVALID_ARGUMENT);
1846     return;
1847   }
1848 
1849   if (exif_buffer) {
1850     VLOGF(4) << "EXIF size " << exif_buffer->size();
1851     if (exif_buffer->size() > kMaxMarkerSizeAllowed) {
1852       NotifyError(task_id, INVALID_ARGUMENT);
1853       return;
1854     }
1855   }
1856 
1857   std::unique_ptr<JobRecord> job_record(
1858       new JobRecord(input_frame, output_frame, quality, task_id, exif_buffer));
1859 
1860   encoder_task_runner_->PostTask(
1861       FROM_HERE,
1862       base::BindOnce(&V4L2JpegEncodeAccelerator::EncodeTask,
1863                      base::Unretained(this), base::Passed(&job_record)));
1864 }
1865 
EncodeTaskLegacy(std::unique_ptr<JobRecord> job_record)1866 void V4L2JpegEncodeAccelerator::EncodeTaskLegacy(
1867     std::unique_ptr<JobRecord> job_record) {
1868   DCHECK(encoder_task_runner_->BelongsToCurrentThread());
1869   if (!job_record->output_shm.MapAt(job_record->output_offset,
1870                                     job_record->output_shm.size())) {
1871     VPLOGF(1) << "could not map I420 bitstream_buffer";
1872     NotifyError(job_record->task_id, PLATFORM_FAILURE);
1873     return;
1874   }
1875   if (job_record->exif_shm &&
1876       !job_record->exif_shm->MapAt(job_record->exif_offset,
1877                                    job_record->exif_shm->size())) {
1878     VPLOGF(1) << "could not map exif bitstream_buffer";
1879     NotifyError(job_record->task_id, PLATFORM_FAILURE);
1880     return;
1881   }
1882 
1883   // Check if the parameters of input frame changes.
1884   // If it changes, we open a new device and put the job in it.
1885   // If it doesn't change, we use the same device as last used.
1886   gfx::Size coded_size = job_record->input_frame->coded_size();
1887   if (latest_input_buffer_coded_size_legacy_ != coded_size ||
1888       latest_quality_legacy_ != job_record->quality) {
1889     std::unique_ptr<EncodedInstance> encoded_device(new EncodedInstance(this));
1890     VLOGF(1) << "Open Device for quality " << job_record->quality
1891              << ", width: " << coded_size.width()
1892              << ", height: " << coded_size.height();
1893     if (!encoded_device->Initialize()) {
1894       VLOGF(1) << "Failed to initialize device";
1895       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1896       return;
1897     }
1898 
1899     if (!encoded_device->SetUpJpegParameters(job_record->quality, coded_size)) {
1900       VLOGF(1) << "SetUpJpegParameters failed";
1901       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1902       return;
1903     }
1904 
1905     if (!encoded_device->CreateBuffers(coded_size,
1906                                        job_record->output_shm.size())) {
1907       VLOGF(1) << "Create buffers failed.";
1908       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1909       return;
1910     }
1911 
1912     latest_input_buffer_coded_size_legacy_ = coded_size;
1913     latest_quality_legacy_ = job_record->quality;
1914 
1915     encoded_instances_.push(std::move(encoded_device));
1916   }
1917 
1918   // Always use latest opened device for new job.
1919   encoded_instances_.back()->input_job_queue_.push(std::move(job_record));
1920 
1921   ServiceDeviceTaskLegacy();
1922 }
1923 
EncodeTask(std::unique_ptr<JobRecord> job_record)1924 void V4L2JpegEncodeAccelerator::EncodeTask(
1925     std::unique_ptr<JobRecord> job_record) {
1926   DCHECK(encoder_task_runner_->BelongsToCurrentThread());
1927   if (job_record->exif_shm &&
1928       !job_record->exif_shm->MapAt(job_record->exif_offset,
1929                                    job_record->exif_shm->size())) {
1930     VPLOGF(1) << "could not map exif bitstream_buffer";
1931     NotifyError(job_record->task_id, PLATFORM_FAILURE);
1932     return;
1933   }
1934 
1935   // Check if the parameters of input frame changes.
1936   // If it changes, we open a new device and put the job in it.
1937   // If it doesn't change, we use the same device as last used.
1938   gfx::Size coded_size = job_record->input_frame->coded_size();
1939   if (latest_input_buffer_coded_size_ != coded_size ||
1940       latest_quality_ != job_record->quality) {
1941     std::unique_ptr<EncodedInstanceDmaBuf> encoded_device(
1942         new EncodedInstanceDmaBuf(this));
1943     VLOGF(1) << "Open Device for quality " << job_record->quality
1944              << ", width: " << coded_size.width()
1945              << ", height: " << coded_size.height();
1946     if (!encoded_device->Initialize()) {
1947       VLOGF(1) << "Failed to initialize device";
1948       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1949       return;
1950     }
1951 
1952     if (!encoded_device->SetUpJpegParameters(job_record->quality, coded_size)) {
1953       VLOGF(1) << "SetUpJpegParameters failed";
1954       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1955       return;
1956     }
1957 
1958     // The output buffer size is coded in the first plane's size.
1959     if (!encoded_device->CreateBuffers(
1960             coded_size, job_record->input_frame->layout(),
1961             job_record->output_frame->layout().planes()[0].size)) {
1962       VLOGF(1) << "Create buffers failed.";
1963       NotifyError(job_record->task_id, PLATFORM_FAILURE);
1964       return;
1965     }
1966 
1967     latest_input_buffer_coded_size_ = coded_size;
1968     latest_quality_ = job_record->quality;
1969 
1970     encoded_instances_dma_buf_.push(std::move(encoded_device));
1971   }
1972 
1973   // Always use latest opened device for new job.
1974   encoded_instances_dma_buf_.back()->input_job_queue_.push(
1975       std::move(job_record));
1976 
1977   ServiceDeviceTask();
1978 }
1979 
ServiceDeviceTaskLegacy()1980 void V4L2JpegEncodeAccelerator::ServiceDeviceTaskLegacy() {
1981   DCHECK(encoder_task_runner_->BelongsToCurrentThread());
1982 
1983   // Always service the first device to keep the input order.
1984   encoded_instances_.front()->ServiceDevice();
1985 
1986   // If we have more than 1 devices, we can remove the oldest one after all jobs
1987   // finished.
1988   if (encoded_instances_.size() > 1) {
1989     if (encoded_instances_.front()->running_job_queue_.empty() &&
1990         encoded_instances_.front()->input_job_queue_.empty()) {
1991       encoded_instances_.pop();
1992     }
1993   }
1994 
1995   if (!encoded_instances_.front()->running_job_queue_.empty() ||
1996       !encoded_instances_.front()->input_job_queue_.empty()) {
1997     encoder_task_runner_->PostTask(
1998         FROM_HERE,
1999         base::BindOnce(&V4L2JpegEncodeAccelerator::ServiceDeviceTaskLegacy,
2000                        base::Unretained(this)));
2001   }
2002 }
2003 
ServiceDeviceTask()2004 void V4L2JpegEncodeAccelerator::ServiceDeviceTask() {
2005   DCHECK(encoder_task_runner_->BelongsToCurrentThread());
2006 
2007   // Always service the first device to keep the input order.
2008   encoded_instances_dma_buf_.front()->ServiceDevice();
2009 
2010   // If we have more than 1 devices, we can remove the oldest one after all jobs
2011   // finished.
2012   if (encoded_instances_dma_buf_.size() > 1) {
2013     if (encoded_instances_dma_buf_.front()->running_job_queue_.empty() &&
2014         encoded_instances_dma_buf_.front()->input_job_queue_.empty()) {
2015       encoded_instances_dma_buf_.pop();
2016     }
2017   }
2018 
2019   if (!encoded_instances_dma_buf_.front()->running_job_queue_.empty() ||
2020       !encoded_instances_dma_buf_.front()->input_job_queue_.empty()) {
2021     encoder_task_runner_->PostTask(
2022         FROM_HERE, base::BindOnce(&V4L2JpegEncodeAccelerator::ServiceDeviceTask,
2023                                   base::Unretained(this)));
2024   }
2025 }
2026 
2027 }  // namespace media
2028