perf(camera): draw timestamps on NV12 luma plane

This commit is contained in:
linbo 2026-08-13 09:23:37 +08:00
parent 400327269a
commit 86452582f5
3 changed files with 30 additions and 24 deletions

View File

@ -47,7 +47,8 @@ public:
static bool encode(std::shared_ptr<FfmpegEncoderInfo>& encoder, static bool encode(std::shared_ptr<FfmpegEncoderInfo>& encoder,
const AVFrame* frame, const AVFrame* frame,
std::vector<uint8_t>& encoded_frame, std::vector<uint8_t>& encoded_frame,
bool& is_key); bool& is_key,
const CameraStreamEncodeOptions& options = {});
}; };
} // namespace cmvr::device } // namespace cmvr::device

View File

@ -337,7 +337,8 @@ bool CameraStreamEncoder::encode(std::shared_ptr<FfmpegEncoderInfo>& encoder,
bool CameraStreamEncoder::encode(std::shared_ptr<FfmpegEncoderInfo>& encoder, bool CameraStreamEncoder::encode(std::shared_ptr<FfmpegEncoderInfo>& encoder,
const AVFrame* frame, const AVFrame* frame,
std::vector<uint8_t>& encoded_frame, std::vector<uint8_t>& encoded_frame,
bool& is_key) bool& is_key,
const CameraStreamEncodeOptions& options)
{ {
encoded_frame.clear(); encoded_frame.clear();
is_key = false; is_key = false;
@ -426,6 +427,28 @@ bool CameraStreamEncoder::encode(std::shared_ptr<FfmpegEncoderInfo>& encoder,
return false; return false;
} }
if (options.draw_timestamp) {
const auto output_format = static_cast<AVPixelFormat>(encoder->frame->format);
if (output_format != AV_PIX_FMT_NV12 && output_format != AV_PIX_FMT_YUV420P) {
const char* format_name = av_get_pix_fmt_name(output_format);
CMVR_LOG(ERROR) << "[CameraStreamEncoder] cannot draw timestamp on pixel format "
<< (format_name ? format_name : "unknown");
return false;
}
if (!encoder->frame->data[0]
|| encoder->frame->linesize[0] < encoder->frame->width) {
CMVR_LOG(ERROR) << "[CameraStreamEncoder] invalid luma plane for timestamp";
return false;
}
cv::Mat luma_plane(
encoder->frame->height,
encoder->frame->width,
CV_8UC1,
encoder->frame->data[0],
static_cast<size_t>(encoder->frame->linesize[0]));
drawTimeStamp(luma_plane);
}
return encodePreparedFrame(*encoder, encoded_frame, is_key); return encodePreparedFrame(*encoder, encoded_frame, is_key);
} }

View File

@ -1055,33 +1055,15 @@ void UVCCamera::streaming_worker_() {
// 以下为编码部分,用于流模式 // 以下为编码部分,用于流模式
StreamFrameData frame_data; StreamFrameData frame_data;
// 保存图像数据 // 保存图像数据
cv::Mat bgr_to_encode;
const auto copy_end_time = std::chrono::steady_clock::now(); const auto copy_end_time = std::chrono::steady_clock::now();
// rgb图像编码 // rgb图像编码
if (enable_stream_timestamp_) {
success = convert_capture_frame_to_bgr_(frame, bgr_to_encode);
if (success && encode_width_ > 0 && encode_height_ > 0 &&
(bgr_to_encode.cols != encode_width_ || bgr_to_encode.rows != encode_height_)) {
cv::resize(bgr_to_encode,
bgr_to_encode,
cv::Size(encode_width_, encode_height_),
0.0,
0.0,
cv::INTER_LINEAR);
}
}
const auto resize_end_time = std::chrono::steady_clock::now(); const auto resize_end_time = std::chrono::steady_clock::now();
if (enable_stream_timestamp_) { CameraStreamEncodeOptions encode_options;
CameraStreamEncodeOptions encode_options; encode_options.draw_timestamp = enable_stream_timestamp_;
encode_options.draw_timestamp = true; success = CameraStreamEncoder::encode(
success = success && CameraStreamEncoder::encode( rgbEncoder_, frame, frame_data.rgbFrame, frame_data.bKey, encode_options);
rgbEncoder_, bgr_to_encode, frame_data.rgbFrame, frame_data.bKey, encode_options);
} else {
success = CameraStreamEncoder::encode(
rgbEncoder_, frame, frame_data.rgbFrame, frame_data.bKey);
}
const auto encode_end_time = std::chrono::steady_clock::now(); const auto encode_end_time = std::chrono::steady_clock::now();
if (success) { if (success) {