forked from marfrit/libva-v4l2-request-fourier
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
|
||||
* 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
|
||||
* called in the current code path; the planned probe-then-set
|
||||
* commit will replace this hardcoded assignment with a runtime
|
||||
* 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);
|
||||
if (rc < 0) {
|
||||
|
||||
@@ -230,21 +230,25 @@ static unsigned uh_read_bits(struct uh_reader *r, int n)
|
||||
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 sign = uh_read_bits(r, 1);
|
||||
int v = (int)uh_read_bits(r, n);
|
||||
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)
|
||||
{
|
||||
if (uh_read_bits(r, 1)) {
|
||||
int v = uh_read_bits(r, 4);
|
||||
|
||||
return uh_read_bits(r, 1) ? -v : v;
|
||||
}
|
||||
/* read_delta_q(): if delta_coded bit set, read s(4) = 4 mag + 1 sign */
|
||||
if (uh_read_bits(r, 1))
|
||||
return uh_read_sbits(r, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -373,12 +377,12 @@ static void vp9_parse_uncompressed_header_lf_quant(
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (uh_read_bits(&r, 1))
|
||||
persistent_ref_deltas[i] =
|
||||
(int8_t)uh_read_signed_6(&r);
|
||||
(int8_t)uh_read_sbits(&r, 6);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (uh_read_bits(&r, 1))
|
||||
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