You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
VP8 diary: P-frame foundation series + cross-thread fix + cost note (#1594)
Updates the living diary entry at diary/2026-04-26-Claude-Opus-4.7/
result.md with everything that landed since the last update:
* New "P-frame foundation series (Apr 27-28)" subsection under
Followup work, listing #1586 through #1592 with one-line summaries
of what each PR added, plus the two notable bugs surfaced and how
they were caught (decoder cnt[CNT_INTRA] mismatch caught by per-MB
pixel-dump diagnostics; cross-thread regression caught by Aaron
running the example app and reported as a stack trace).
* Rewrites Capabilities of the encoder as it stands -- moves
keyframe-only out of Implemented into the new key+inter capability
line, lists the new ZEROMV LAST_FRAME inter mode and the
cross-thread-safe FrameEncoderBuffers, and updates the Not yet
implemented list with NEWMV / NEAREST / NEAR / SPLITMV / GOLDEN /
ALTREF as the next-step gaps. Also fixes a pre-existing duplicate
"## Capabilities of the encoder as it stands" header.
* Updates the Roadmap to push real motion estimation to position 1
(the biggest remaining compression lever now that the inter
pipeline works) and demotes the now-implemented P-frame
foundation item from the list.
* Adds a new "## Cost" section near the top recording that the
successful encoder write cost approximately EUR 150 in Anthropic
credits, spanning the seven-PR keyframe series + SRTP investigation
and fix + five-PR P-frame foundation + cross-thread fix. Useful
forward reference for what this scope of port-and-debug work
costs in 2026 dollars.
* Updates the Headline to reflect that the stream is now
keyframe + inter rather than keyframe-only.
@@ -7,19 +7,28 @@ This is a **living record** — kept up to date as further progress lands.
7
7
## Headline
8
8
9
9
The fifth AI attempt at this task is the first to clear the wall the previous
10
-
four ran into. `VP8Codec.EncodeVideo` produces a fully-decodable VP8 keyframe
11
-
stream that Chrome renders correctly and continuously —**the
10
+
four ran into. `VP8Codec.EncodeVideo` produces a fully-decodable VP8 stream
11
+
(keyframe + inter) that Chrome renders correctly and continuously --**the
12
12
WebRTCGetStartedVP8Net example streams audio + video to Chrome at the
13
-
default Q=32 / 30 fps for 7+ minutes with no audio loss and no video
14
-
artefacts** (running on the `srtp-per-ssrc-rollover-counter` branch — see
15
-
"Followup work" below for why that branch matters).
13
+
default Q=32 / 30 fps with no audio loss and no video artefacts** (running
14
+
on master after the SRTP fix and the P-frame foundation series merged --
15
+
see "Followup work" below).
16
16
17
17
Encoder primitives are individually bit-exact-verified against libvpx C
18
18
reference output. The end-to-end stream against Chrome is the structural
19
19
signal that the foundation port worked.
20
20
21
21
Compared to the prior four entries in this diary, the difference is not the
22
-
model alone — it's the working method. See "What worked" below.
22
+
model alone -- it's the working method. See "What worked" below.
23
+
24
+
## Cost
25
+
26
+
Aaron's commission of the work cost approximately **EUR 150 in
27
+
Anthropic credits** for the successful encoder write -- spanning the
28
+
seven-PR keyframe foundation series, the SRTP rollover-counter
29
+
investigation and fix, the five-PR P-frame foundation series, and the
30
+
follow-up cross-thread fix. Recorded here for future reference on what
31
+
this scope of port-and-debug work costs in 2026 dollars.
23
32
24
33
## Reframing of the original task
25
34
@@ -138,35 +147,87 @@ keyframe-only stream wraps the video sequence number every 30-50
138
147
seconds; libvpx's mostly-P-frame stream wraps roughly an order of
139
148
magnitude less often, so the bug is statistically much rarer to hit.
140
149
141
-
## Capabilities of the encoder as it stands
150
+
### P-frame foundation series (Apr 27-28)
151
+
152
+
With the SRTP fix landed and audio + video stable for arbitrarily long
153
+
sessions, the next thing on the roadmap was inter (P) frames. Same
154
+
foundation-series shape as the original encoder port: a sequence of
155
+
small, independently-testable PRs each porting one libvpx primitive,
156
+
with the orchestration ticked over to "real" inter encoding only in the
157
+
final PR. Five PRs, plus a follow-up cross-thread bug fix.
158
+
159
+
| PR | Title | What it did |
160
+
| --- | --- | --- |
161
+
|[#1586](https://github.com/sipsorcery-org/sipsorcery/pull/1586)| P-frame foundation: reference frame storage + key/inter cadence (PR 1 of 5) |`FrameEncoderBuffers.LastFrameY/U/V`, `VP8Codec.KeyframeIntervalFrames`, `_framesSinceLastKeyframe` counter. Inter branch in `EncodeVideo` is wired but still falls through to `EncodeKeyframe` -- decision logic in place, behaviour unchanged. |
162
+
|[#1587](https://github.com/sipsorcery-org/sipsorcery/pull/1587)| P-frame foundation: inter (P-frame) header writer (PR 2 of 5) |`bitstream.StartInterFrameHeader` + `FinishInterFrameFirstPartition`. Frame tag with `key_frame_flag = 1`, no start code, no dimensions. Compressed first-partition prefix through `refresh_last_frame`. Bit-exact round-trip tests against the existing decoder's frame-tag parser. |
163
+
|[#1588](https://github.com/sipsorcery-org/sipsorcery/pull/1588)| P-frame foundation: ZEROMV inter MB encoder (PR 3 of 5) |`mb_encoder.EncodeMacroblockZeroMvLast`. Same DCT/Walsh/quantize/tokenize pipeline as DC_PRED but the prediction is the same-position 16x16 + 8x8 + 8x8 samples from the previous frame's reconstruction. |
164
+
|[#1589](https://github.com/sipsorcery-org/sipsorcery/pull/1589)| P-frame foundation: per-MB inter mode + ref bits writer (PR 4 of 5) |`bitstream.WriteInterMbRefAndMode`, `WriteInterMode`, `vp8_treed_write`, `WriteInterMbZeroMvLast`. The inter-mode tree path bits, walking `vp8_mv_ref_tree` for any of ZEROMV / NEAREST / NEAR / NEW / SPLITMV. Round-trip tested for every (ref_frame, mode) combination against the decoder's `vp8_treed_read`. |
165
+
|[#1591](https://github.com/sipsorcery-org/sipsorcery/pull/1591)| P-frame foundation: `EncodeInterFrame` orchestration + `EncodeVideo` wire-up (PR 5 of 5) |`frame_encoder.EncodeInterFrame`. `VP8Codec.EncodeVideo` inter branch now actually emits a P-frame instead of falling through. Round-trip tests at Q=4/16/32 vs source PSNR. |
166
+
|[#1592](https://github.com/sipsorcery-org/sipsorcery/pull/1592)| VP8: fix cross-thread inter-frame encoding (regression from #1591) | Lifts `FrameEncoderBuffers` from `[ThreadStatic]` on `frame_encoder` to a per-instance field on `VP8Codec`, so the LAST_FRAME reference survives the .NET thread pool moving the work between worker threads on each Timer tick. |
167
+
168
+
The single bug surfaced during the series was caught by per-MB pixel
169
+
dumping under a moving-content round-trip test. The decoder picks a
170
+
row of `vp8_mode_contexts` based on `cnt[CNT_INTRA]`, which it
171
+
computes by walking the above/left/aboveleft neighbours' inter state.
172
+
For an all-ZEROMV LAST_FRAME stream that's deterministic by MB
0 commit comments