diff --git a/src/context.c b/src/context.c index b7a34cf..b583917 100644 --- a/src/context.c +++ b/src/context.c @@ -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) { diff --git a/src/vp9.c b/src/vp9.c index b4444b2..436f684 100644 --- a/src/vp9.c +++ b/src/vp9.c @@ -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); } } }