mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-08-03 08:41:41 +08:00
+1
-1
@@ -40,7 +40,7 @@ assert arch in [
|
||||
"Darwin", # macOS arm64 (x86 not supported)
|
||||
]
|
||||
|
||||
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
||||
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
||||
pkgs = [importlib.import_module(name) for name in pkg_names]
|
||||
acados = pkgs[pkg_names.index('acados')]
|
||||
acados_include_dirs = [
|
||||
|
||||
@@ -21,7 +21,7 @@ logger_lib = env.Library('logger', src)
|
||||
libs.insert(0, logger_lib)
|
||||
|
||||
env.Program('loggerd', ['loggerd.cc'], LIBS=libs, FRAMEWORKS=frameworks)
|
||||
env.Program('encoderd', ['encoderd.cc'], LIBS=libs + ["jpeg"], FRAMEWORKS=frameworks)
|
||||
env.Program('encoderd', ['encoderd.cc'], LIBS=libs, FRAMEWORKS=frameworks)
|
||||
env.Program('bootlog.cc', LIBS=libs, FRAMEWORKS=frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
|
||||
@@ -3,16 +3,50 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
JpegEncoder::JpegEncoder(const std::string &pusblish_name, int width, int height)
|
||||
: publish_name(pusblish_name), thumbnail_width(width), thumbnail_height(height) {
|
||||
yuv_buffer.resize((thumbnail_width * ((thumbnail_height + 15) & ~15) * 3) / 2);
|
||||
pm = std::make_unique<PubMaster>(std::vector{pusblish_name.c_str()});
|
||||
#include "common/swaglog.h"
|
||||
|
||||
// Lower qscale = higher quality / bigger files for MJPEG.
|
||||
constexpr int MJPEG_QSCALE = 7;
|
||||
|
||||
JpegEncoder::JpegEncoder(const std::string &publish_name, int width, int height)
|
||||
: publish_name(publish_name), thumbnail_width(width), thumbnail_height(height) {
|
||||
yuv_buffer.resize((thumbnail_width * thumbnail_height * 3) / 2);
|
||||
pm = std::make_unique<PubMaster>(std::vector{publish_name.c_str()});
|
||||
|
||||
const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
|
||||
assert(codec);
|
||||
|
||||
codec_ctx = avcodec_alloc_context3(codec);
|
||||
assert(codec_ctx);
|
||||
codec_ctx->width = thumbnail_width;
|
||||
codec_ctx->height = thumbnail_height;
|
||||
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
codec_ctx->time_base = (AVRational){1, 1};
|
||||
codec_ctx->color_range = AVCOL_RANGE_JPEG;
|
||||
codec_ctx->flags |= AV_CODEC_FLAG_QSCALE;
|
||||
codec_ctx->global_quality = FF_QP2LAMBDA * MJPEG_QSCALE;
|
||||
|
||||
int err = avcodec_open2(codec_ctx, codec, NULL);
|
||||
assert(err >= 0);
|
||||
|
||||
frame = av_frame_alloc();
|
||||
assert(frame);
|
||||
frame->format = codec_ctx->pix_fmt;
|
||||
frame->width = thumbnail_width;
|
||||
frame->height = thumbnail_height;
|
||||
frame->linesize[0] = thumbnail_width;
|
||||
frame->linesize[1] = thumbnail_width / 2;
|
||||
frame->linesize[2] = thumbnail_width / 2;
|
||||
frame->color_range = AVCOL_RANGE_JPEG;
|
||||
|
||||
pkt = av_packet_alloc();
|
||||
assert(pkt);
|
||||
}
|
||||
|
||||
JpegEncoder::~JpegEncoder() {
|
||||
if (out_buffer) {
|
||||
free(out_buffer);
|
||||
}
|
||||
av_packet_free(&pkt);
|
||||
av_frame_free(&frame);
|
||||
avcodec_free_context(&codec_ctx);
|
||||
}
|
||||
|
||||
void JpegEncoder::pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra) {
|
||||
@@ -22,7 +56,7 @@ void JpegEncoder::pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra)
|
||||
auto thumbnaild = msg.initEvent().initThumbnail();
|
||||
thumbnaild.setFrameId(extra.frame_id);
|
||||
thumbnaild.setTimestampEof(extra.timestamp_eof);
|
||||
thumbnaild.setThumbnail({out_buffer, out_size});
|
||||
thumbnaild.setThumbnail({out_buffer.data(), out_buffer.size()});
|
||||
|
||||
pm->send(publish_name.c_str(), msg);
|
||||
}
|
||||
@@ -31,12 +65,11 @@ void JpegEncoder::generateThumbnail(const uint8_t *y_addr, const uint8_t *uv_add
|
||||
int downscale = width / thumbnail_width;
|
||||
assert(downscale * thumbnail_height == height);
|
||||
|
||||
// make the buffer big enough. jpeg_write_raw_data requires 16-pixels aligned height to be used.
|
||||
uint8_t *y_plane = yuv_buffer.data();
|
||||
uint8_t *u_plane = y_plane + thumbnail_width * thumbnail_height;
|
||||
uint8_t *v_plane = u_plane + (thumbnail_width * thumbnail_height) / 4;
|
||||
{
|
||||
// subsampled conversion from nv12 to yuv
|
||||
// subsampled conversion from nv12 to yuv420p
|
||||
for (int hy = 0; hy < thumbnail_height / 2; hy++) {
|
||||
for (int hx = 0; hx < thumbnail_width / 2; hx++) {
|
||||
int ix = hx * downscale + (downscale - 1) / 2;
|
||||
@@ -55,51 +88,28 @@ void JpegEncoder::generateThumbnail(const uint8_t *y_addr, const uint8_t *uv_add
|
||||
}
|
||||
|
||||
void JpegEncoder::compressToJpeg(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane) {
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_compress(&cinfo);
|
||||
frame->data[0] = y_plane;
|
||||
frame->data[1] = u_plane;
|
||||
frame->data[2] = v_plane;
|
||||
// Required for MJPEG qscale to take effect (global_quality alone is not enough).
|
||||
frame->quality = FF_QP2LAMBDA * MJPEG_QSCALE;
|
||||
frame->pts = 0;
|
||||
|
||||
if (out_buffer) {
|
||||
free(out_buffer);
|
||||
out_buffer = nullptr;
|
||||
out_size = 0;
|
||||
}
|
||||
jpeg_mem_dest(&cinfo, &out_buffer, &out_size);
|
||||
|
||||
cinfo.image_width = thumbnail_width;
|
||||
cinfo.image_height = thumbnail_height;
|
||||
cinfo.input_components = 3;
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
jpeg_set_colorspace(&cinfo, JCS_YCbCr);
|
||||
// configure sampling factors for yuv420.
|
||||
cinfo.comp_info[0].h_samp_factor = 2; // Y
|
||||
cinfo.comp_info[0].v_samp_factor = 2;
|
||||
cinfo.comp_info[1].h_samp_factor = 1; // U
|
||||
cinfo.comp_info[1].v_samp_factor = 1;
|
||||
cinfo.comp_info[2].h_samp_factor = 1; // V
|
||||
cinfo.comp_info[2].v_samp_factor = 1;
|
||||
cinfo.raw_data_in = TRUE;
|
||||
|
||||
jpeg_set_quality(&cinfo, 50, TRUE);
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
JSAMPROW y[16], u[8], v[8];
|
||||
JSAMPARRAY planes[3]{y, u, v};
|
||||
|
||||
for (int line = 0; line < cinfo.image_height; line += 16) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
y[i] = y_plane + (line + i) * cinfo.image_width;
|
||||
if (i % 2 == 0) {
|
||||
int offset = (cinfo.image_width / 2) * ((i + line) / 2);
|
||||
u[i / 2] = u_plane + offset;
|
||||
v[i / 2] = v_plane + offset;
|
||||
}
|
||||
}
|
||||
jpeg_write_raw_data(&cinfo, planes, 16);
|
||||
int err = avcodec_send_frame(codec_ctx, frame);
|
||||
if (err < 0) {
|
||||
LOGE("thumbnail avcodec_send_frame error %d", err);
|
||||
out_buffer.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
av_packet_unref(pkt);
|
||||
err = avcodec_receive_packet(codec_ctx, pkt);
|
||||
if (err < 0) {
|
||||
LOGE("thumbnail avcodec_receive_packet error %d", err);
|
||||
out_buffer.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
out_buffer.assign(pkt->data, pkt->data + pkt->size);
|
||||
av_packet_unref(pkt);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <jpeglib.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "openpilot/cereal/messaging/messaging.h"
|
||||
#include "msgq/visionipc/visionbuf.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
class JpegEncoder {
|
||||
public:
|
||||
JpegEncoder(const std::string &pusblish_name, int width, int height);
|
||||
JpegEncoder(const std::string &publish_name, int width, int height);
|
||||
~JpegEncoder();
|
||||
void pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra);
|
||||
|
||||
@@ -24,9 +26,10 @@ private:
|
||||
int thumbnail_height;
|
||||
std::string publish_name;
|
||||
std::vector<uint8_t> yuv_buffer;
|
||||
std::vector<uint8_t> out_buffer;
|
||||
std::unique_ptr<PubMaster> pm;
|
||||
|
||||
// JPEG output buffer
|
||||
unsigned char* out_buffer = nullptr;
|
||||
unsigned long out_size = 0;
|
||||
AVCodecContext *codec_ctx = nullptr;
|
||||
AVFrame *frame = nullptr;
|
||||
AVPacket *pkt = nullptr;
|
||||
};
|
||||
|
||||
@@ -33,7 +33,6 @@ dependencies = [
|
||||
"acados @ git+https://github.com/commaai/dependencies.git@release-acados#subdirectory=acados",
|
||||
"eigen @ git+https://github.com/commaai/dependencies.git@release-eigen#subdirectory=eigen",
|
||||
"ffmpeg @ git+https://github.com/commaai/dependencies.git@release-ffmpeg#subdirectory=ffmpeg",
|
||||
"libjpeg @ git+https://github.com/commaai/dependencies.git@release-libjpeg#subdirectory=libjpeg",
|
||||
"libyuv @ git+https://github.com/commaai/dependencies.git@release-libyuv#subdirectory=libyuv",
|
||||
"zstd @ git+https://github.com/commaai/dependencies.git@release-zstd#subdirectory=zstd",
|
||||
"ncurses @ git+https://github.com/commaai/dependencies.git@release-ncurses#subdirectory=ncurses",
|
||||
|
||||
@@ -655,10 +655,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/e8/7923893f08504f28e0b5fb8b21795fc388d0363cfa2f412e2541c9464cb1/lefthook-2.1.9-py3-none-win_arm64.whl", hash = "sha256:6d8e3923c42a04e9375f88314ebc8c86f68879d3d0c9d856b6adbed109890e90", size = 4959833, upload-time = "2026-05-29T08:39:32.882Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libjpeg"
|
||||
version = "3.1.0"
|
||||
source = { git = "https://github.com/commaai/dependencies.git?subdirectory=libjpeg&rev=release-libjpeg#3f9a0796d1985576b0cb172456e08bb918f3afeb" }
|
||||
|
||||
[[package]]
|
||||
name = "libusb"
|
||||
@@ -909,7 +905,6 @@ dependencies = [
|
||||
{ name = "jeepney" },
|
||||
{ name = "json-rpc" },
|
||||
{ name = "json11" },
|
||||
{ name = "libjpeg" },
|
||||
{ name = "libusb" },
|
||||
{ name = "libyuv" },
|
||||
{ name = "ncurses" },
|
||||
@@ -997,7 +992,6 @@ requires-dist = [
|
||||
{ name = "jinja2", marker = "extra == 'docs'" },
|
||||
{ name = "json-rpc" },
|
||||
{ name = "json11", git = "https://github.com/commaai/dependencies.git?subdirectory=json11&rev=release-json11" },
|
||||
{ name = "libjpeg", git = "https://github.com/commaai/dependencies.git?subdirectory=libjpeg&rev=release-libjpeg" },
|
||||
{ name = "libusb", git = "https://github.com/commaai/dependencies.git?subdirectory=libusb&rev=release-libusb" },
|
||||
{ name = "libyuv", git = "https://github.com/commaai/dependencies.git?subdirectory=libyuv&rev=release-libyuv" },
|
||||
{ name = "matplotlib", marker = "extra == 'dev'" },
|
||||
|
||||
Reference in New Issue
Block a user