fresnel-fourier iter4 Phase 7 fix-forward: gate ANNEX-B start-code prepend on H.264/HEVC profiles
Root cause for VP9 criterion-4 failure traced via runtime instrumentation: context.c:194 unconditionally set context_object->h264_start_code = true for every CreateContext, regardless of codec profile. picture.c:70 then prepends 0x00 0x00 0x01 (ANNEX-B start code) to ALL slice data including VP9 frames. VP9 has no start codes — its uncompressed_header begins with the raw frame_marker byte (0x10 in the high 2 bits). The 3-byte prefix shifted the rkvdec driver's bitstream-read by 24 bits, producing a silent decode failure (frame_marker mismatch -> driver fails to locate a valid frame -> CAPTURE slot stays at cap_pool init pattern, the dim 0x4c green visible in Phase 7 hwdownload PNGs). iter4 fix: switch on config_object->profile in RequestCreateContext. Set h264_start_code = true only for VAProfileH264* and VAProfileHEVCMain. False for MPEG2/VP8/VP9. iter1 (MPEG-2) and iter3 (VP8) had this same bug latent — they passed because their criterion-4 verification used different paths (iter1 direct readback was small enough to mask, iter3 used transitive proof not pixel comparison). The Phase 7 byte-level pixel comparison is what exposed it. Empirical proof of the fix on fresnel: - pre-fix submission FRAME control bytes 0-23: lf.flags=0x01 (only DELTA_ENABLED), base_q_idx=0x41 — bit-misaligned because parser was reading the prefix bytes. - post-fix submission FRAME control bytes 0-23 byte-match Phase 3 kernel-direct anchor: lf.flags=0x03 (ENABLED|UPDATE), base_q_idx=0x2e (46). Transitive-proof leg 1 (backend-payload == kernel-direct-payload) satisfied for the keyframe. - s(6) bit-width fix in vp9.c (4 mag + 1 sign -> 6 mag + 1 sign per VP9 spec) was a real bug too, latent because Bug 1 (this commit's fix) prevented its code path from running. Both fixes ship together. Pixels still produce 0x4c constant pattern post-fix — that is Bug 2 (substrate-wide cap_pool readback regression on linux-fresnel-fourier 7.0-1) per phase7_iter4_verification.md. Bug 2 is out of iter4 scope per Option-A choice; transitive proof remains the criterion-4 verification path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-1
@@ -186,12 +186,35 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
|||||||
* boundaries, and emits a zeroed CAPTURE buffer (visually a
|
* boundaries, and emits a zeroed CAPTURE buffer (visually a
|
||||||
* flat dark-green frame).
|
* flat dark-green frame).
|
||||||
*
|
*
|
||||||
|
* iter4 fix: this start-code prepend is ANNEX-B-specific and
|
||||||
|
* applies to H.264 and HEVC ONLY. MPEG-2, VP8, and VP9 use raw
|
||||||
|
* frame bitstreams without start codes — prepending 0x00 0x00 0x01
|
||||||
|
* to a VP9 uncompressed header produces a frame_marker mismatch
|
||||||
|
* (kernel reads 0x00 instead of 0x10), the rkvdec driver silently
|
||||||
|
* fails to find a valid frame, and the CAPTURE slot stays at its
|
||||||
|
* cap_pool init pattern (a dim 0x4c green). Phase 7 verification
|
||||||
|
* caught this for VP9; iter1+iter3 transitive proof masked it for
|
||||||
|
* MPEG-2/VP8 because those iters compared payload bytes, not
|
||||||
|
* decoded pixels.
|
||||||
|
*
|
||||||
* h264_get_controls() exists for this purpose but is never
|
* h264_get_controls() exists for this purpose but is never
|
||||||
* called in the current code path; the planned probe-then-set
|
* called in the current code path; the planned probe-then-set
|
||||||
* commit will replace this hardcoded assignment with a runtime
|
* commit will replace this hardcoded assignment with a runtime
|
||||||
* read of the kernel's accepted START_CODE value.
|
* read of the kernel's accepted START_CODE value.
|
||||||
*/
|
*/
|
||||||
context_object->h264_start_code = true;
|
switch (config_object->profile) {
|
||||||
|
case VAProfileH264Main:
|
||||||
|
case VAProfileH264High:
|
||||||
|
case VAProfileH264ConstrainedBaseline:
|
||||||
|
case VAProfileH264MultiviewHigh:
|
||||||
|
case VAProfileH264StereoHigh:
|
||||||
|
case VAProfileHEVCMain:
|
||||||
|
context_object->h264_start_code = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
context_object->h264_start_code = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
rc = v4l2_set_stream(driver_data->video_fd, output_type, true);
|
rc = v4l2_set_stream(driver_data->video_fd, output_type, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
|||||||
@@ -230,21 +230,25 @@ static unsigned uh_read_bits(struct uh_reader *r, int n)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uh_read_signed_6(struct uh_reader *r)
|
/* Phase 7 fix: VP9 spec s(N) is N magnitude bits + 1 sign bit (total N+1).
|
||||||
|
* Previous uh_read_signed_6 read 4+1=5 bits instead of 6+1=7; bit drift of
|
||||||
|
* 2 bits per ref_delta accumulated across the lf_delta updates and shifted
|
||||||
|
* base_q_idx by 8 bits, producing 0x41 (frame 1 keyframe) instead of 0x2e.
|
||||||
|
* Phase 3 anchor cross-check confirmed the corrected 7-bit read places
|
||||||
|
* base_q_idx at bit 111 with value 0x2e=46. */
|
||||||
|
static int uh_read_sbits(struct uh_reader *r, int n)
|
||||||
{
|
{
|
||||||
int mag = uh_read_bits(r, 4);
|
int v = (int)uh_read_bits(r, n);
|
||||||
int sign = uh_read_bits(r, 1);
|
int sign = (int)uh_read_bits(r, 1);
|
||||||
|
|
||||||
return sign ? -mag : mag;
|
return sign ? -v : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uh_read_delta_q(struct uh_reader *r)
|
static int uh_read_delta_q(struct uh_reader *r)
|
||||||
{
|
{
|
||||||
if (uh_read_bits(r, 1)) {
|
/* read_delta_q(): if delta_coded bit set, read s(4) = 4 mag + 1 sign */
|
||||||
int v = uh_read_bits(r, 4);
|
if (uh_read_bits(r, 1))
|
||||||
|
return uh_read_sbits(r, 4);
|
||||||
return uh_read_bits(r, 1) ? -v : v;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,12 +377,12 @@ static void vp9_parse_uncompressed_header_lf_quant(
|
|||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
if (uh_read_bits(&r, 1))
|
if (uh_read_bits(&r, 1))
|
||||||
persistent_ref_deltas[i] =
|
persistent_ref_deltas[i] =
|
||||||
(int8_t)uh_read_signed_6(&r);
|
(int8_t)uh_read_sbits(&r, 6);
|
||||||
}
|
}
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (uh_read_bits(&r, 1))
|
if (uh_read_bits(&r, 1))
|
||||||
persistent_mode_deltas[i] =
|
persistent_mode_deltas[i] =
|
||||||
(int8_t)uh_read_signed_6(&r);
|
(int8_t)uh_read_sbits(&r, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user