diff --git a/system/loggerd/encoder/encoder.cc b/system/loggerd/encoder/encoder.cc index 7ac2948861..b45ad874a6 100644 --- a/system/loggerd/encoder/encoder.cc +++ b/system/loggerd/encoder/encoder.cc @@ -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::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; } diff --git a/system/loggerd/encoder/encoder.h b/system/loggerd/encoder/encoder.h index 9ea6b884cf..d88274be84 100644 --- a/system/loggerd/encoder/encoder.h +++ b/system/loggerd/encoder/encoder.h @@ -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 pm; - const char *service_name; }; diff --git a/system/loggerd/encoder/ffmpeg_encoder.cc b/system/loggerd/encoder/ffmpeg_encoder.cc index af05b5df97..198216114a 100644 --- a/system/loggerd/encoder/ffmpeg_encoder.cc +++ b/system/loggerd/encoder/ffmpeg_encoder.cc @@ -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, diff --git a/system/loggerd/encoder/ffmpeg_encoder.h b/system/loggerd/encoder/ffmpeg_encoder.h index 6b4b6e104c..d3ba18e52c 100644 --- a/system/loggerd/encoder/ffmpeg_encoder.h +++ b/system/loggerd/encoder/ffmpeg_encoder.h @@ -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); diff --git a/system/loggerd/encoder/v4l_encoder.cc b/system/loggerd/encoder/v4l_encoder.cc index 20ae4b7370..53fb93d834 100644 --- a/system/loggerd/encoder/v4l_encoder.cc +++ b/system/loggerd/encoder/v4l_encoder.cc @@ -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}, diff --git a/system/loggerd/encoder/v4l_encoder.h b/system/loggerd/encoder/v4l_encoder.h index b0af4039fe..bd27838b89 100644 --- a/system/loggerd/encoder/v4l_encoder.h +++ b/system/loggerd/encoder/v4l_encoder.h @@ -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); diff --git a/system/loggerd/encoderd.cc b/system/loggerd/encoderd.cc index b4f0b913e5..877fbac452 100644 --- a/system/loggerd/encoderd.cc +++ b/system/loggerd/encoderd.cc @@ -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"); diff --git a/system/loggerd/loggerd.cc b/system/loggerd/loggerd.cc index af526ccb41..d1d9596e02 100644 --- a/system/loggerd/loggerd.cc +++ b/system/loggerd/loggerd.cc @@ -1,3 +1,6 @@ +#include + +#include "system/loggerd/encoder/encoder.h" #include "system/loggerd/loggerd.h" #include "system/loggerd/video_writer.h" diff --git a/system/loggerd/loggerd.h b/system/loggerd/loggerd.h index 579b079dbb..0226e631d5 100644 --- a/system/loggerd/loggerd.h +++ b/system/loggerd/loggerd.h @@ -1,42 +1,25 @@ #pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #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}; -