23#include "NvBufSurface.h"
25#include "opencv2/core/core.hpp"
26#include "opencv2/highgui/highgui.hpp"
27#include "opencv2/imgproc/imgproc.hpp"
48 AINFO <<
"Camera config: \n" << config_.DebugString();
66 nvbuffer_pool_->ConstructAll(
69 nvbuffer_pool_->GetObject()->allocateMemory();
71 }
catch (
const std::bad_alloc& e) {
77 downsampled_image_pool_.reset(
new CCObjectPool<std::pair<std::vector<char>, std::vector<unsigned char>>>(
79 downsampled_image_pool_->ConstructAll();
81 (downsampled_image_pool_->GetObject()->first).reserve(buffer_size_);
82 (downsampled_image_pool_->GetObject()->second).reserve(buffer_size_);
84 }
catch (
const std::bad_alloc& e) {
89 jpegenc_ = NvJPEGEncoder::createJPEGEncoder(
"jpegenc");
90 jpegenc_->setCropRect(0, 0, 0, 0);
97 ADEBUG <<
"procing compressed";
98 if (
cyber_unlikely(image->height() != height_ || image->width() != width_)) {
99 AERROR <<
"Setting resolution is " << width_ <<
"x" << height_ <<
", but received " << image->width() <<
"x"
104 auto compressed_image = writer_->AcquireMessage();
105 compressed_image->mutable_header()->CopyFrom(image->header());
106 compressed_image->set_frame_id(image->frame_id());
107 compressed_image->set_measurement_time(image->measurement_time());
108 compressed_image->set_height(height_);
109 compressed_image->set_width(width_);
112 compressed_image->set_format(image->encoding() +
"; jpeg compressed");
113 auto nvbuffer = nvbuffer_pool_->GetObject();
114 auto downsampled_image = downsampled_image_pool_->GetObject();
116 YUV422ToYUV420(
const_cast<char*
>(image->data().data()), (downsampled_image->first).data()) != 0)) {
117 AERROR <<
"Failed to downsample image";
120 if (
cyber_unlikely(ReadBuffer((downsampled_image->first).data(), &(*nvbuffer)) != 0)) {
121 AERROR <<
"Failed to convert image to nvbuffer";
124 auto out_buffer = (downsampled_image->second).data();
125 auto buffer_size =
static_cast<uint64_t
>(buffer_size_);
127 auto ret = jpegenc_->encodeFromBuffer(*nvbuffer, JCS_YCbCr, &out_buffer, buffer_size, 95);
129 AERROR <<
"nvjpeg failed to compress image";
131 compressed_image->set_data((downsampled_image->second).data(), buffer_size);
133 compressed_image->set_format(image->encoding() +
"; jpeg compressed bgr8");
135 std::vector<int> params;
137 params[0] = cv::IMWRITE_JPEG_QUALITY;
142 image->height(), image->width(), CV_8UC3,
const_cast<char*
>(image->data().data()), image->step());
144 cv::cvtColor(mat_image, tmp_mat, cv::COLOR_RGB2BGR);
145 std::vector<uint8_t> compress_buffer;
146 if (!cv::imencode(
".jpg", tmp_mat, compress_buffer, params)) {
147 AERROR <<
"cv::imencode (jpeg) failed on input image";
150 compressed_image->set_data(compress_buffer.data(), compress_buffer.size());
151 }
catch (std::exception& e) {
152 AERROR <<
"cv::imencode (jpeg) exception :" << e.what();
156 writer_->Write(compressed_image);
161int CompressComponent::YUV422ToYUV420(
char* src,
char* dst) {
162 static uint line_length = width_ * 2;
163 static uint y_num = width_ * height_;
164 static uint cb_start = y_num;
165 static uint cr_start = cb_start + cb_start / 4;
195 auto usrc =
reinterpret_cast<unsigned char*
>(src);
196 auto udst =
reinterpret_cast<unsigned char*
>(dst);
198 int frameSize = width_ * height_;
199 int chromaSize = frameSize / 4;
201 unsigned char* yPlane = udst;
202 unsigned char* uPlane = udst + frameSize;
203 unsigned char* vPlane = uPlane + chromaSize;
209 for (
int j = 0; j < height_; j += 2) {
210 for (
int i = 0; i < width_; i += 16) {
212 uint8x16x2_t row0 = vld2q_u8(usrc + j * width_ * 2 + i * 2);
213 uint8x16x2_t row1 = vld2q_u8(usrc + (j + 1) * width_ * 2 + i * 2);
216 uint8x16_t y0 = row0.val[0];
217 uint8x16_t y1 = row1.val[0];
220 vst1q_u8(yPlane + yIndex, y0);
221 vst1q_u8(yPlane + yIndex + width_, y1);
225 uint8x16_t u0 = row0.val[1];
226 uint8x16_t v0 = row1.val[1];
228 uint16x8_t u16_low = vaddl_u8(vget_low_u8(u0), vget_low_u8(v0));
229 uint16x8_t u16_high = vaddl_u8(vget_high_u8(u0), vget_high_u8(v0));
230 uint8x8_t u8_avg_low = vshrn_n_u16(u16_low, 1);
231 uint8x8_t u8_avg_high = vshrn_n_u16(u16_high, 1);
233 uint16x8_t v16_low = vaddl_u8(vget_low_u8(row0.val[1]), vget_low_u8(row1.val[1]));
234 uint16x8_t v16_high = vaddl_u8(vget_high_u8(row0.val[1]), vget_high_u8(row1.val[1]));
235 uint8x8_t v8_avg_low = vshrn_n_u16(v16_low, 1);
236 uint8x8_t v8_avg_high = vshrn_n_u16(v16_high, 1);
238 uint8x16_t u_avg = vcombine_u8(u8_avg_low, u8_avg_high);
239 uint8x16_t v_avg = vcombine_u8(v8_avg_low, v8_avg_high);
242 vst1_u8(uPlane + uIndex, u8_avg_low);
243 vst1_u8(vPlane + vIndex, v8_avg_low);
253int CompressComponent::ReadBuffer(
char* file_buffer, NvBuffer* buffer) {
256 char* data =
nullptr;
258 for (i = 0; i < buffer->n_planes; i++) {
259 NvBuffer::NvBufferPlane& plane = buffer->planes[i];
260 int bytes_to_read = plane.fmt.bytesperpixel * plane.fmt.width;
262 data =
reinterpret_cast<char*
>(plane.data);
264 for (j = 0; j < plane.fmt.height; j++) {
265 memcpy(data, file_buffer, bytes_to_read);
266 data += plane.fmt.stride;
267 file_buffer += bytes_to_read;
269 plane.bytesused = plane.fmt.stride * plane.fmt.height;
bool GetProtoConfig(T *config) const
const std::string & ConfigFilePath() const
std::shared_ptr< Node > node_
bool Proc(const std::shared_ptr< apollo::drivers::Image > &image) override
#define cyber_unlikely(x)
optional uint32 image_pool_size
optional string output_channel
optional CompressConfig compress_conf