Phase 2 RTSP: --out - / pipe:1 для прямого pipe в ffmpeg
Подтверждено live-тестом end-to-end в продакшен-условиях: grid_record --out - → ffmpeg -i pipe:0 -c copy -f rtsp -rtsp_transport tcp → mediamtx rtsp://...:554/cfc-grid → VLC на MacBook VLC принимает поток штатно, картинка не тормозит — лучше чем у предыдущего цельного ffmpeg-pipeline (vf-cuda-grid). 1920x1080 H.264 High@4.0 4Mbps, 4 источника active. Изменения тривиальные: stdout не закрывается через fclose, чтобы пайп оставался открытым для дочернего ffmpeg-процесса.
This commit is contained in:
+20
-8
@@ -182,14 +182,25 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Output file. */
|
||||
/* Output: "-" / "/dev/stdout" / "pipe:1" = stdout (для pipe в ffmpeg).
|
||||
* stdout не закрывается через fclose чтобы не убивать дочерний процесс
|
||||
* raньше времени. */
|
||||
write_ctx_t wctx = { 0 };
|
||||
wctx.fp = fopen(out_path, "wb");
|
||||
if (!wctx.fp) {
|
||||
fprintf(stderr, "fopen(%s): %s\n", out_path, strerror(errno));
|
||||
cfc_encoder_destroy(enc);
|
||||
cfc_composer_destroy(comp);
|
||||
return 1;
|
||||
int is_stdout = (!strcmp(out_path, "-") || !strcmp(out_path, "pipe:1") ||
|
||||
!strcmp(out_path, "/dev/stdout"));
|
||||
if (is_stdout) {
|
||||
wctx.fp = stdout;
|
||||
/* line-buffer'инг disabled — пишем full-buffered для производительности.
|
||||
* Caller'у нужно flush при exit. */
|
||||
setvbuf(stdout, NULL, _IOFBF, 1024 * 1024);
|
||||
} else {
|
||||
wctx.fp = fopen(out_path, "wb");
|
||||
if (!wctx.fp) {
|
||||
fprintf(stderr, "fopen(%s): %s\n", out_path, strerror(errno));
|
||||
cfc_encoder_destroy(enc);
|
||||
cfc_composer_destroy(comp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "[grid_record] начало записи в %s (Ctrl+C для остановки)\n",
|
||||
out_path);
|
||||
@@ -261,7 +272,8 @@ int main(int argc, char **argv)
|
||||
(unsigned long long)wctx.idr_count,
|
||||
wctx.bytes_written / 1048576.0);
|
||||
|
||||
fclose(wctx.fp);
|
||||
fflush(wctx.fp);
|
||||
if (!is_stdout) fclose(wctx.fp);
|
||||
cfc_encoder_destroy(enc);
|
||||
cfc_composer_destroy(comp);
|
||||
cuCtxPopCurrent(NULL);
|
||||
|
||||
@@ -180,13 +180,20 @@ int main(int argc, char **argv)
|
||||
goto cleanup_src;
|
||||
}
|
||||
|
||||
/* 5) Открыть выходной файл. */
|
||||
/* 5) Открыть выходной файл (или stdout если "-"/"pipe:1"). */
|
||||
write_ctx_t wctx = { 0 };
|
||||
wctx.fp = fopen(out_path, "wb");
|
||||
if (!wctx.fp) {
|
||||
fprintf(stderr, "[simple_record] fopen(%s) failed: %s\n",
|
||||
out_path, strerror(errno));
|
||||
goto cleanup_enc;
|
||||
int is_stdout = (!strcmp(out_path, "-") || !strcmp(out_path, "pipe:1") ||
|
||||
!strcmp(out_path, "/dev/stdout"));
|
||||
if (is_stdout) {
|
||||
wctx.fp = stdout;
|
||||
setvbuf(stdout, NULL, _IOFBF, 1024 * 1024);
|
||||
} else {
|
||||
wctx.fp = fopen(out_path, "wb");
|
||||
if (!wctx.fp) {
|
||||
fprintf(stderr, "[simple_record] fopen(%s) failed: %s\n",
|
||||
out_path, strerror(errno));
|
||||
goto cleanup_enc;
|
||||
}
|
||||
}
|
||||
|
||||
/* 6) Главный цикл — забираем кадры по seq, кодируем. */
|
||||
@@ -258,7 +265,8 @@ int main(int argc, char **argv)
|
||||
(unsigned long long)wctx.idr_count,
|
||||
wctx.bytes_written / 1048576.0);
|
||||
|
||||
fclose(wctx.fp);
|
||||
fflush(wctx.fp);
|
||||
if (!is_stdout) fclose(wctx.fp);
|
||||
|
||||
cleanup_enc:
|
||||
cfc_encoder_destroy(enc);
|
||||
|
||||
Reference in New Issue
Block a user