feat(rtsp-source): packet ring publishing (v0.2 Step 4)
build / cmake build (CUDA 12.4, Ubuntu 22.04) (pull_request) Successful in 1m39s
build / ffmpeg filter patch (out-of-tree) (pull_request) Successful in 1m44s

- cuframes::Publisher (C++ wrapper): добавлены enable_packets(),
  set_codec_extradata(), publish_packet() методы.
- cuframes-rtsp-source: новый CLI flag --enable-packet-ring. При его
  установке после opening stream — pub.enable_packets(codec_id) +
  set_codec_extradata из vstream->codecpar->extradata.
- В main loop: после av_read_frame, до avcodec_send_packet, packet
  публикуется в packet ring с конверсией pts/dts из stream_tb в ns,
  AV_PKT_FLAG_KEY/CORRUPT/DISCONTINUITY → CUFRAMES_PKT_FLAG_*.

Тест:
  cuframes-rtsp-source --rtsp rtsp://... --key cam1 --enable-packet-ring
  # frames consumer'ы продолжают работать через cuframes:// (как v0.1)
  # record consumer'ы могут brать packets через cuframes_packets:// (Step 5)

Связано: #2, PR #4.
This commit is contained in:
2026-05-19 16:45:29 +01:00
parent 4cb0321a6f
commit 8cd96721ff
2 changed files with 65 additions and 0 deletions
+48
View File
@@ -60,6 +60,7 @@ struct Args {
bool verbose = false;
bool realtime = false; // emulate -re у ffmpeg CLI: sleep по pts
bool loop = false; // loop input на eof (для file://)
bool enable_packet_ring = false; // v0.2 — публиковать encoded packets
};
static void print_usage() {
@@ -75,6 +76,8 @@ static void print_usage() {
" --ring N cuframes ring size (default 4, range 2..16)\n"
" --realtime pace input по PTS (как ffmpeg -re; полезно для файла)\n"
" --loop loop input на EOF (только для file://)\n"
" --enable-packet-ring v0.2: дополнительно публиковать encoded packets\n"
" (для consumer'ов с -c:v copy, Frigate record path)\n"
" --verbose debug logs\n"
" -h, --help this help\n";
}
@@ -92,6 +95,7 @@ static int parse_args(int argc, char **argv, Args &a) {
else if (s == "--ring") a.ring_size = std::stoi(next());
else if (s == "--realtime") a.realtime = true;
else if (s == "--loop") a.loop = true;
else if (s == "--enable-packet-ring") a.enable_packet_ring = true;
else if (s == "--verbose") a.verbose = true;
else if (s == "-h" || s == "--help") { print_usage(); std::exit(0); }
else { std::cerr << "Unknown arg: " << s << "\n"; print_usage(); std::exit(1); }
@@ -235,6 +239,27 @@ int main(int argc, char **argv) {
<< "' ready, ring=" << a.ring_size
<< " pool_size=" << frame_size << " bytes/frame\n";
/* v0.2 — encoded packet ring (опционально). */
if (a.enable_packet_ring) {
cuframes_packet_ring_options_t pkt_opts{};
pkt_opts.codec_id = (uint32_t)vstream->codecpar->codec_id;
/* остальные поля = 0 → library использует defaults (64 slots, 8MiB, 2MiB max) */
pub.enable_packets(&pkt_opts);
if (vstream->codecpar->extradata_size > 0 && vstream->codecpar->extradata) {
pub.set_codec_extradata(vstream->codecpar->extradata,
(size_t)vstream->codecpar->extradata_size);
std::cerr << "[cuframes-src] packet ring active, codec_id="
<< vstream->codecpar->codec_id
<< " extradata=" << vstream->codecpar->extradata_size
<< " bytes\n";
} else {
std::cerr << "[cuframes-src] packet ring active, codec_id="
<< vstream->codecpar->codec_id
<< " (no extradata in stream — will rely on in-band SPS/PPS)\n";
}
}
/* Stream для D2D copies */
cudaStream_t stream;
cudaStreamCreate(&stream);
@@ -279,6 +304,29 @@ int main(int argc, char **argv) {
continue;
}
/* v0.2 — публикуем encoded packet в packet ring ДО decoder. Это позволяет
* record-consumer'ам брать packet без второго RTSP-подключения к камере. */
if (a.enable_packet_ring) {
int64_t pkt_pts_ns = (pkt->pts != AV_NOPTS_VALUE)
? av_rescale_q(pkt->pts, stream_tb, AVRational{1, 1000000000})
: cuframes::now_ns();
int64_t pkt_dts_ns = (pkt->dts != AV_NOPTS_VALUE)
? av_rescale_q(pkt->dts, stream_tb, AVRational{1, 1000000000})
: pkt_pts_ns;
uint32_t pkt_flags = 0;
if (pkt->flags & AV_PKT_FLAG_KEY) pkt_flags |= CUFRAMES_PKT_FLAG_KEY;
if (pkt->flags & AV_PKT_FLAG_CORRUPT) pkt_flags |= CUFRAMES_PKT_FLAG_CORRUPT;
#ifdef AV_PKT_FLAG_DISCONTINUITY
if (pkt->flags & AV_PKT_FLAG_DISCONTINUITY) pkt_flags |= CUFRAMES_PKT_FLAG_DISCONTINUITY;
#endif
int prr = pub.publish_packet(pkt->data, (size_t)pkt->size,
pkt_pts_ns, pkt_dts_ns, pkt_flags);
if (prr != CUFRAMES_OK && a.verbose) {
std::cerr << "[cuframes-src] publish_packet rc=" << prr
<< " size=" << pkt->size << "\n";
}
}
r = avcodec_send_packet(ctx, pkt);
av_packet_unref(pkt);
if (r < 0) continue;