mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 21:14:01 +08:00
loggerd/encoder: refactor constructors to take EncoderInfo as parameter (#28921)
* refactor constructors to take EncoderInfo as parameter
* remove last arg codec
* use macro to init function pointers
old-commit-hash: 713d2ec586
This commit is contained in:
@@ -5,8 +5,7 @@ VideoEncoder::~VideoEncoder() {}
|
||||
|
||||
void VideoEncoder::publisher_init() {
|
||||
// publish
|
||||
service_name = this->publish_name;
|
||||
pm.reset(new PubMaster({service_name}));
|
||||
pm.reset(new PubMaster({encoder_info.publish_name}));
|
||||
}
|
||||
|
||||
void VideoEncoder::publisher_publish(VideoEncoder *e, int segment_num, uint32_t idx, VisionIpcBufExtra &extra,
|
||||
@@ -14,9 +13,7 @@ void VideoEncoder::publisher_publish(VideoEncoder *e, int segment_num, uint32_t
|
||||
// broadcast packet
|
||||
MessageBuilder msg;
|
||||
auto event = msg.initEvent(true);
|
||||
auto edat = (e->type == DriverCam) ? event.initDriverEncodeData() :
|
||||
((e->type == WideRoadCam) ? event.initWideRoadEncodeData() :
|
||||
(e->in_width == e->out_width ? event.initRoadEncodeData() : event.initQRoadEncodeData()));
|
||||
auto edat = (event.*(e->encoder_info.init_encode_data_func))();
|
||||
auto edata = edat.initIdx();
|
||||
struct timespec ts;
|
||||
timespec_get(&ts, TIME_UTC);
|
||||
@@ -24,7 +21,7 @@ void VideoEncoder::publisher_publish(VideoEncoder *e, int segment_num, uint32_t
|
||||
edata.setFrameId(extra.frame_id);
|
||||
edata.setTimestampSof(extra.timestamp_sof);
|
||||
edata.setTimestampEof(extra.timestamp_eof);
|
||||
edata.setType(e->codec);
|
||||
edata.setType(e->encoder_info.encode_type);
|
||||
edata.setEncodeId(e->cnt++);
|
||||
edata.setSegmentNum(segment_num);
|
||||
edata.setSegmentId(idx);
|
||||
@@ -35,6 +32,6 @@ void VideoEncoder::publisher_publish(VideoEncoder *e, int segment_num, uint32_t
|
||||
|
||||
auto words = new kj::Array<capnp::word>(capnp::messageToFlatArray(msg));
|
||||
auto bytes = words->asBytes();
|
||||
e->pm->send(e->service_name, bytes.begin(), bytes.size());
|
||||
e->pm->send(e->encoder_info.publish_name, bytes.begin(), bytes.size());
|
||||
delete words;
|
||||
}
|
||||
|
||||
@@ -8,17 +8,14 @@
|
||||
#include "cereal/visionipc/visionipc.h"
|
||||
#include "common/queue.h"
|
||||
#include "system/camerad/cameras/camera_common.h"
|
||||
#include "system/loggerd/loggerd.h"
|
||||
|
||||
#define V4L2_BUF_FLAG_KEYFRAME 8
|
||||
|
||||
class VideoEncoder {
|
||||
public:
|
||||
VideoEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height,
|
||||
const char* publish_name)
|
||||
: filename(filename), type(type), in_width(in_width), in_height(in_height), fps(fps),
|
||||
bitrate(bitrate), codec(codec), out_width(out_width), out_height(out_height),
|
||||
publish_name(publish_name) { }
|
||||
VideoEncoder(const EncoderInfo &encoder_info, int in_width, int in_height)
|
||||
: encoder_info(encoder_info), in_width(in_width), in_height(in_height) {}
|
||||
virtual ~VideoEncoder();
|
||||
virtual int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) = 0;
|
||||
virtual void encoder_open(const char* path) = 0;
|
||||
@@ -29,13 +26,8 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
const char* filename;
|
||||
const char* publish_name;
|
||||
int in_width, in_height;
|
||||
int out_width, out_height, fps;
|
||||
int bitrate;
|
||||
cereal::EncodeIndex::Type codec;
|
||||
CameraType type;
|
||||
const EncoderInfo encoder_info;
|
||||
|
||||
private:
|
||||
// total frames encoded
|
||||
@@ -43,5 +35,4 @@ private:
|
||||
|
||||
// publishing
|
||||
std::unique_ptr<PubMaster> pm;
|
||||
const char *service_name;
|
||||
};
|
||||
|
||||
@@ -28,16 +28,16 @@ void FfmpegEncoder::encoder_init() {
|
||||
frame = av_frame_alloc();
|
||||
assert(frame);
|
||||
frame->format = AV_PIX_FMT_YUV420P;
|
||||
frame->width = out_width;
|
||||
frame->height = out_height;
|
||||
frame->linesize[0] = out_width;
|
||||
frame->linesize[1] = out_width/2;
|
||||
frame->linesize[2] = out_width/2;
|
||||
frame->width = encoder_info.frame_width;
|
||||
frame->height = encoder_info.frame_height;
|
||||
frame->linesize[0] = encoder_info.frame_width;
|
||||
frame->linesize[1] = encoder_info.frame_width/2;
|
||||
frame->linesize[2] = encoder_info.frame_width/2;
|
||||
|
||||
convert_buf.resize(in_width * in_height * 3 / 2);
|
||||
|
||||
if (in_width != out_width || in_height != out_height) {
|
||||
downscale_buf.resize(out_width * out_height * 3 / 2);
|
||||
if (in_width != encoder_info.frame_width || in_height != encoder_info.frame_height) {
|
||||
downscale_buf.resize(encoder_info.frame_width * encoder_info.frame_height * 3 / 2);
|
||||
}
|
||||
|
||||
publisher_init();
|
||||
@@ -56,7 +56,7 @@ void FfmpegEncoder::encoder_open(const char* path) {
|
||||
this->codec_ctx->width = frame->width;
|
||||
this->codec_ctx->height = frame->height;
|
||||
this->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
this->codec_ctx->time_base = (AVRational){ 1, fps };
|
||||
this->codec_ctx->time_base = (AVRational){ 1, encoder_info.fps };
|
||||
int err = avcodec_open2(this->codec_ctx, codec, NULL);
|
||||
assert(err >= 0);
|
||||
|
||||
@@ -136,7 +136,7 @@ int FfmpegEncoder::encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) {
|
||||
}
|
||||
|
||||
if (env_debug_encoder) {
|
||||
printf("%20s got %8d bytes flags %8x idx %4d id %8d\n", this->filename, pkt.size, pkt.flags, counter, extra->frame_id);
|
||||
printf("%20s got %8d bytes flags %8x idx %4d id %8d\n", encoder_info.filename, pkt.size, pkt.flags, counter, extra->frame_id);
|
||||
}
|
||||
|
||||
publisher_publish(this, segment_num, counter, *extra,
|
||||
|
||||
@@ -15,12 +15,9 @@ extern "C" {
|
||||
#include "system/loggerd/loggerd.h"
|
||||
|
||||
class FfmpegEncoder : public VideoEncoder {
|
||||
public:
|
||||
FfmpegEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height,
|
||||
const char* publish_name) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS, out_width, out_height, publish_name) { encoder_init(); }
|
||||
public:
|
||||
FfmpegEncoder(const EncoderInfo &encoder_info, int in_width, int in_height)
|
||||
: VideoEncoder(encoder_info, in_width, in_height) { encoder_init(); }
|
||||
~FfmpegEncoder();
|
||||
void encoder_init();
|
||||
int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra);
|
||||
|
||||
@@ -68,7 +68,7 @@ static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count)
|
||||
}
|
||||
|
||||
void V4LEncoder::dequeue_handler(V4LEncoder *e) {
|
||||
std::string dequeue_thread_name = "dq-"+std::string(e->filename);
|
||||
std::string dequeue_thread_name = "dq-"+std::string(e->encoder_info.filename);
|
||||
util::set_thread_name(dequeue_thread_name.c_str());
|
||||
|
||||
e->segment_num++;
|
||||
@@ -88,7 +88,7 @@ void V4LEncoder::dequeue_handler(V4LEncoder *e) {
|
||||
if (!rc) { LOGE("encoder dequeue poll timeout"); continue; }
|
||||
|
||||
if (env_debug_encoder >= 2) {
|
||||
printf("%20s poll %x at %.2f ms\n", e->filename, pfd.revents, millis_since_boot());
|
||||
printf("%20s poll %x at %.2f ms\n", e->encoder_info.filename, pfd.revents, millis_since_boot());
|
||||
}
|
||||
|
||||
int frame_id = -1;
|
||||
@@ -116,7 +116,7 @@ void V4LEncoder::dequeue_handler(V4LEncoder *e) {
|
||||
|
||||
if (env_debug_encoder) {
|
||||
printf("%20s got(%d) %6d bytes flags %8x idx %3d/%4d id %8d ts %ld lat %.2f ms (%lu frames free)\n",
|
||||
e->filename, index, bytesused, flags, e->segment_num, idx, frame_id, ts, millis_since_boot()-(ts/1000.), e->free_buf_in.size());
|
||||
e->encoder_info.filename, index, bytesused, flags, e->segment_num, idx, frame_id, ts, millis_since_boot()-(ts/1000.), e->free_buf_in.size());
|
||||
}
|
||||
|
||||
// requeue the buffer
|
||||
@@ -146,9 +146,9 @@ void V4LEncoder::encoder_init() {
|
||||
.fmt = {
|
||||
.pix_mp = {
|
||||
// downscales are free with v4l
|
||||
.width = (unsigned int)out_width,
|
||||
.height = (unsigned int)out_height,
|
||||
.pixelformat = (codec == cereal::EncodeIndex::Type::FULL_H_E_V_C) ? V4L2_PIX_FMT_HEVC : V4L2_PIX_FMT_H264,
|
||||
.width = (unsigned int)encoder_info.frame_width,
|
||||
.height = (unsigned int)encoder_info.frame_height,
|
||||
.pixelformat = (encoder_info.encode_type == cereal::EncodeIndex::Type::FULL_H_E_V_C) ? V4L2_PIX_FMT_HEVC : V4L2_PIX_FMT_H264,
|
||||
.field = V4L2_FIELD_ANY,
|
||||
.colorspace = V4L2_COLORSPACE_DEFAULT,
|
||||
}
|
||||
@@ -192,7 +192,7 @@ void V4LEncoder::encoder_init() {
|
||||
{
|
||||
struct v4l2_control ctrls[] = {
|
||||
{ .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE, .value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE},
|
||||
{ .id = V4L2_CID_MPEG_VIDEO_BITRATE, .value = bitrate},
|
||||
{ .id = V4L2_CID_MPEG_VIDEO_BITRATE, .value = encoder_info.bitrate},
|
||||
{ .id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL, .value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR},
|
||||
{ .id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY, .value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE},
|
||||
{ .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD, .value = 1},
|
||||
@@ -202,7 +202,7 @@ void V4LEncoder::encoder_init() {
|
||||
}
|
||||
}
|
||||
|
||||
if (codec == cereal::EncodeIndex::Type::FULL_H_E_V_C) {
|
||||
if (encoder_info.encode_type == cereal::EncodeIndex::Type::FULL_H_E_V_C) {
|
||||
struct v4l2_control ctrls[] = {
|
||||
{ .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE, .value = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN},
|
||||
{ .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL, .value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5},
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
class V4LEncoder : public VideoEncoder {
|
||||
public:
|
||||
V4LEncoder(const char* filename, CameraType type, int in_width, int in_height, int fps,
|
||||
int bitrate, cereal::EncodeIndex::Type codec, int out_width, int out_height, const char* publish_name) :
|
||||
VideoEncoder(filename, type, in_width, in_height, fps, bitrate, codec, out_width, out_height, publish_name) { encoder_init(); }
|
||||
V4LEncoder(const EncoderInfo &encoder_info, int in_width, int in_height)
|
||||
: VideoEncoder(encoder_info, in_width, in_height) { encoder_init(); }
|
||||
~V4LEncoder();
|
||||
void encoder_init();
|
||||
int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra);
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#include "system/loggerd/loggerd.h"
|
||||
|
||||
#ifdef QCOM2
|
||||
#include "system/loggerd/encoder/v4l_encoder.h"
|
||||
#define Encoder V4LEncoder
|
||||
#else
|
||||
#include "system/loggerd/encoder/ffmpeg_encoder.h"
|
||||
#define Encoder FfmpegEncoder
|
||||
#endif
|
||||
|
||||
ExitHandler do_exit;
|
||||
|
||||
struct EncoderdState {
|
||||
@@ -54,11 +62,7 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
|
||||
|
||||
if (buf_info.width > 0 && buf_info.height > 0) {
|
||||
for (const auto &encoder_info: cam_info.encoder_infos){
|
||||
encoders.push_back(new Encoder(encoder_info.filename, cam_info.type, buf_info.width, buf_info.height,
|
||||
encoder_info.fps, encoder_info.bitrate,
|
||||
encoder_info.encode_type,
|
||||
encoder_info.frame_width, encoder_info.frame_height,
|
||||
encoder_info.publish_name));
|
||||
encoders.push_back(new Encoder(encoder_info, buf_info.width, buf_info.height));
|
||||
}
|
||||
} else {
|
||||
LOGE("not initting empty encoder");
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "system/loggerd/encoder/encoder.h"
|
||||
#include "system/loggerd/loggerd.h"
|
||||
#include "system/loggerd/video_writer.h"
|
||||
|
||||
|
||||
@@ -1,42 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "cereal/messaging/messaging.h"
|
||||
#include "cereal/services.h"
|
||||
#include "cereal/visionipc/visionipc.h"
|
||||
#include "cereal/visionipc/visionipc_client.h"
|
||||
#include "system/camerad/cameras/camera_common.h"
|
||||
#include "system/hardware/hw.h"
|
||||
#include "common/params.h"
|
||||
#include "common/swaglog.h"
|
||||
#include "common/timing.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
#include "system/loggerd/encoder/encoder.h"
|
||||
#include "system/loggerd/logger.h"
|
||||
#ifdef QCOM2
|
||||
#include "system/loggerd/encoder/v4l_encoder.h"
|
||||
#define Encoder V4LEncoder
|
||||
#else
|
||||
#include "system/loggerd/encoder/ffmpeg_encoder.h"
|
||||
#define Encoder FfmpegEncoder
|
||||
#endif
|
||||
|
||||
constexpr int MAIN_FPS = 20;
|
||||
const int MAIN_BITRATE = 10000000;
|
||||
|
||||
#define NO_CAMERA_PATIENCE 500 // fall back to time-based rotation if all cameras are dead
|
||||
#define NO_CAMERA_PATIENCE 500 // fall back to time-based rotation if all cameras are dead
|
||||
|
||||
#define INIT_ENCODE_FUNCTIONS(encode_type) \
|
||||
.get_encode_data_func = &cereal::Event::Reader::get##encode_type##Data, \
|
||||
.set_encode_idx_func = &cereal::Event::Builder::set##encode_type##Idx, \
|
||||
.init_encode_data_func = &cereal::Event::Builder::init##encode_type##Data
|
||||
|
||||
const bool LOGGERD_TEST = getenv("LOGGERD_TEST");
|
||||
const int SEGMENT_LENGTH = LOGGERD_TEST ? atoi(getenv("LOGGERD_SEGMENT_LENGTH")) : 60;
|
||||
@@ -50,9 +33,11 @@ public:
|
||||
int frame_height = 1208;
|
||||
int fps = MAIN_FPS;
|
||||
int bitrate = MAIN_BITRATE;
|
||||
cereal::EncodeIndex::Type encode_type = cereal::EncodeIndex::Type::FULL_H_E_V_C;
|
||||
cereal::EncodeIndex::Type encode_type = Hardware::PC() ? cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS
|
||||
: cereal::EncodeIndex::Type::FULL_H_E_V_C;
|
||||
::cereal::EncodeData::Reader (cereal::Event::Reader::*get_encode_data_func)() const;
|
||||
void (cereal::Event::Builder::*set_encode_idx_func)(::cereal::EncodeIndex::Reader);
|
||||
cereal::EncodeData::Builder (cereal::Event::Builder::*init_encode_data_func)();
|
||||
};
|
||||
|
||||
class LogCameraInfo {
|
||||
@@ -67,21 +52,18 @@ public:
|
||||
const EncoderInfo main_road_encoder_info = {
|
||||
.publish_name = "roadEncodeData",
|
||||
.filename = "fcamera.hevc",
|
||||
.get_encode_data_func = &cereal::Event::Reader::getRoadEncodeData,
|
||||
.set_encode_idx_func = &cereal::Event::Builder::setRoadEncodeIdx,
|
||||
INIT_ENCODE_FUNCTIONS(RoadEncode),
|
||||
};
|
||||
const EncoderInfo main_wide_road_encoder_info = {
|
||||
.publish_name = "wideRoadEncodeData",
|
||||
.filename = "ecamera.hevc",
|
||||
.get_encode_data_func = &cereal::Event::Reader::getWideRoadEncodeData,
|
||||
.set_encode_idx_func = &cereal::Event::Builder::setWideRoadEncodeIdx,
|
||||
INIT_ENCODE_FUNCTIONS(WideRoadEncode),
|
||||
};
|
||||
const EncoderInfo main_driver_encoder_info = {
|
||||
.publish_name = "driverEncodeData",
|
||||
.filename = "dcamera.hevc",
|
||||
.record = Params().getBool("RecordFront"),
|
||||
.get_encode_data_func = &cereal::Event::Reader::getDriverEncodeData,
|
||||
.set_encode_idx_func = &cereal::Event::Builder::setDriverEncodeIdx,
|
||||
INIT_ENCODE_FUNCTIONS(DriverEncode),
|
||||
};
|
||||
|
||||
const EncoderInfo qcam_encoder_info = {
|
||||
@@ -91,8 +73,7 @@ const EncoderInfo qcam_encoder_info = {
|
||||
.encode_type = cereal::EncodeIndex::Type::QCAMERA_H264,
|
||||
.frame_width = 526,
|
||||
.frame_height = 330,
|
||||
.get_encode_data_func = &cereal::Event::Reader::getQRoadEncodeData,
|
||||
.set_encode_idx_func = &cereal::Event::Builder::setQRoadEncodeIdx,
|
||||
INIT_ENCODE_FUNCTIONS(QRoadEncode),
|
||||
};
|
||||
|
||||
|
||||
@@ -109,7 +90,7 @@ const LogCameraInfo wide_road_camera_info{
|
||||
.stream_type = VISION_STREAM_WIDE_ROAD,
|
||||
.encoder_infos = {main_wide_road_encoder_info}
|
||||
};
|
||||
|
||||
|
||||
const LogCameraInfo driver_camera_info{
|
||||
.thread_name = "driver_cam_encoder",
|
||||
.type = DriverCam,
|
||||
@@ -118,4 +99,3 @@ const LogCameraInfo driver_camera_info{
|
||||
};
|
||||
|
||||
const LogCameraInfo cameras_logged[] = {road_camera_info, wide_road_camera_info, driver_camera_info};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user