Skip to content

ffmpeg: read SVAC 3.0 from a GB/T 28181 program stream - #15

Merged
widgetii merged 1 commit into
masterfrom
svac3-ps
Oct 29, 2026
Merged

widgetii merged 1 commit into
masterfrom
svac3-ps

Conversation

@widgetii

Copy link
Copy Markdown
Member

Why

GB/T 28181 platforms carry video as an MPEG-2 program stream over RTP, and OpenIPC cameras can now send SVAC 3.0 that way. FFmpeg's MPEG-PS demuxer did not know SVAC's stream type, so it could not read such a capture.

What

  • 0003-avformat-mpeg-read-SVAC-video-from-a-GB-T-28181-program-stream.patch: maps stream_type 0x80 in the program stream map to AV_CODEC_ID_SVAC3. It applies only on a video stream id (0xE0–0xEF), because 0x80 is user-private in ISO/IEC 13818-1. The demuxer already sets full parsing, so the SVAC3 parser applies unchanged.
  • ffmpeg/ps_write.py: an independent program-stream writer:
    • one pack per access unit;
    • a system header and map on units with an SPS or random-access patch;
    • PES packets split at the 16-bit length, with the PTS on the first.
  • ffmpeg/ps_check.sh: writes every corpus stream with it, reads it back with -f mpeg, and checks against the golden framemd5. It runs as a new CI step; the CI FFmpeg build adds the mpegps demuxer.
  • ffmpeg/README.md: documents the patch order and the program-stream notes.

Verified

  • All 3 patches apply in order to a clean n9.0.2.
  • All 8 corpus streams are bit-exact through ps_write.py → -f mpeg, SMART_P and multi-patch streams included.
  • A program stream captured from a camera's RTSP PS/90000 session (its RTP payloads concatenated) decodes with -f mpeg: 240 frames at 1920x1080, the same count libsvac3d gives on the extracted elementary stream.

FFmpeg has no RTP depacketizer for PS/90000 itself; that is outside this repo's patches.

0003 maps program stream map stream_type 0x80 to AV_CODEC_ID_SVAC3 in
libavformat/mpeg.c, on a video stream id only (the value is user-private
in ISO/IEC 13818-1), so ffmpeg -f mpeg reads SVAC the way GB/T 28181
carries it.

ps_write.py writes a program stream independently of any camera
(pack per access unit, system header and map on random-access units,
PES split at the 16-bit length), and CI holds every corpus stream read
back through it to the golden framemd5.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Read SVAC 3.0 from GB/T 28181 MPEG program streams

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Recognize SVAC 3.0 in GB/T 28181 program streams without treating every private stream as SVAC.
• Generate program streams from the corpus and verify decoded frames against golden hashes in CI.
• Document patch order, program-stream playback, and the unsupported PS/90000 RTP transport.
Diagram

graph TD
  A["SVAC corpus"] --> B["PS writer"] --> C["Program stream"] --> D["MPEG-PS demuxer"] --> E["SVAC parser decoder"] --> F["Frame hash check"]
  G["Golden hashes"] --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Validate SVAC payload before assigning the codec
  • ➕ Reduces misclassification of other private 0x80 video streams.
  • ➖ Adds probing complexity and may fail when reading from the middle of a stream.
2. Add a GB/T-specific program-stream demuxer
  • ➕ Keeps the private stream-type interpretation separate from generic MPEG-PS handling.
  • ➖ Duplicates established program-stream parsing for a narrow codec-mapping change.

Recommendation: Use the existing MPEG-PS demuxer and video-stream-ID guard as proposed; it is the smallest change that enables the documented captures. Revisit payload validation if interoperability with other private 0x80 video streams becomes necessary.

Files changed (5) +188 / -3

Enhancement (1) +46 / -0
0003-avformat-mpeg-read-SVAC-video-from-a-GB-T-28181-program-stream.patchMap GB/T 28181 program-stream video to SVAC3 +46/-0

Map GB/T 28181 program-stream video to SVAC3

• Adds the 0x80 stream-type definition and maps it to AV_CODEC_ID_SVAC3 in FFmpeg's MPEG-PS demuxer only for video stream IDs 0xE0–0xEF.

ffmpeg/0003-avformat-mpeg-read-SVAC-video-from-a-GB-T-28181-program-stream.patch

Tests (2) +120 / -0
ps_check.shCheck program-stream decoding against golden frame hashes +23/-0

Check program-stream decoding against golden frame hashes

• Wraps each matching corpus stream as a program stream, decodes it with FFmpeg's MPEG demuxer, and compares its framemd5 output with the existing golden result.

ffmpeg/ps_check.sh

ps_write.pyGenerate MPEG-2 program-stream fixtures from SVAC access units +97/-0

Generate MPEG-2 program-stream fixtures from SVAC access units

• Writes packs, headers, stream maps, timestamps, and length-bounded PES packets from the existing SVAC access-unit grouping. This provides an independent input generator for the demuxer regression check.

ffmpeg/ps_write.py

Documentation (1) +19 / -2
README.mdDocument program-stream support and verification +19/-2

Document program-stream support and verification

• Lists the third FFmpeg patch, describes the new corpus check, and explains playback of saved GB/T 28181 program streams. It notes that FFmpeg does not depacketize PS/90000 RTP.

ffmpeg/README.md

Other (1) +3 / -1
ci.ymlBuild MPEG-PS support and run the program-stream regression check +3/-1

Build MPEG-PS support and run the program-stream regression check

• Enables the mpegps demuxer in the minimal FFmpeg build and adds a CI step that runs the new corpus round-trip check.

.github/workflows/ci.yml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@widgetii
widgetii merged commit 0f43e41 into master Oct 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant