在嵌入式 Linux 開發中,常見需求是通過 Video for Linux 2 (V4L2) 接口採集攝像頭視頻流,經過 H.264 編碼後,按固定時間間隔(如每 10 秒)切割成獨立文件寫入 SD 卡。本文梳理完整實現流程,重點解決「定時切片」與「數據流緩衝」兩大核心難點。
採用「生產者-消費者」模型:
/mnt/sdcard/video_YYYYMMDD_HHMMSS.h264)。int fd = open("/dev/video0", O_RDWR);
struct v4l2_format fmt = {0};
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ioctl(fd, VIDIOC_S_FMT, &fmt);
// 申請緩衲區、映射內存、入隊、啟動串流...
AVCodecContext *ctx = avcodec_alloc_context3(codec);
ctx->width = 1920; ctx->height = 1080;
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
ctx->time_base = (AVRational){1, 30};
ctx->bit_rate = 4000000;
avcodec_open2(ctx, codec, NULL);
// 循環:avcodec_send_frame -> avcodec_receive_packet -> 推入隊列
使用 timerfd_create(CLOCK_MONOTONIC, 0) 創建高精度定時器,設置 10 秒週期。定時器回調中:
fclose(fp)fp = fopen(new_path, "wb")fwrite 到新 fpSD 卡屬於塊設備,頻繁 fwrite 會觸發大量擦寫。建議:
fwritenoatime,nodiratime 減少元數據寫入fsync 確保數據落盤,平衡性能與可靠性| 問題 | 原因 | 解決方案 |
|---|---|---|
| 文件時長不足 10 秒 | 關鍵幀間隔過大 | 編碼器設置 g=300 (30fps×10s) 強制關鍵幀 |
| 首幀花屏 | SPS/PPS 未寫入文件頭 | 切片時先寫入 extradata 再寫數據 |
| SD 卡寫入卡頓 | 文件系統同步阻塞 |
可參考 CSDN 開源項目:V4L2_H264_SD_Recorder,包含 Makefile、信號處理、優雅退出等工程化細節。
核心在於「隊列解耦採集與寫入」+「定時器驅動切片」。只要處理好關鍵幀對齊、緩衝區回收、SD 卡壽命管理,即可構建穩定可靠的嵌入式視頻錄製系統。