Videodec2 now outputs 10-bit HEVC Main 10 frames, so the HEVC picture info
takes bitDepthLumaMinus8 and bitDepthChromaMinus8 from the decoded frame
instead of leaving them 0. The Main 10 stream moves to HevcFixture.hpp so the
Vdecsw test can decode it.
Vdecsw read every decoded picture's info through Videodec2's AVC picture
info, which throws for HEVC, so an HEVC decoder failed on its first
picture. Videodec2 now hands Vdecsw a codec-independent picture header,
records whether an HEVC access unit starts with an IDR slice, and Vdecsw
keeps the AVC or the 0xb8-byte HEVC picture info for each picture.
The HEVC test stream moves to HevcFixture.hpp so the Vdecsw test can
decode it.
sceVideodec2Flush drained libavcodec with an empty packet whenever the decoder
was not already flushing, and the next sceVideodec2Decode then restarted the
decoder with avcodec_flush_buffers, dropping its reference pictures. A caller
that flushes after every access unit, as Sony's PSP emulator does for its
H.264 movies, lost every P picture after the first: libavcodec withholds
pictures after a restart until it reaches a keyframe, so Daxter (PPSA09695)
got 8 pictures from 459 access units and showed a black screen ("Failed to
obtain a video frame") instead of its intro movie.
Flush now drains only when a decoded access unit has not produced its picture
yet. With nothing pending there is nothing to return, and the decoder keeps its
references for the units that follow.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceVideodec2GetPictureInfo writes the decoder's own picture layout. For a
VP9 decoder it now writes the 88-byte VP9 layout that
sceVideodec2GetVp9PictureInfo returns, instead of throwing. Mortal Shell 2
(PPSA34008) calls the generic query with that structure for its intro
movie. HEVC pictures still throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Move the AVCC collision to the second unit, add an AVCC unit opening
00 00 01 23 among Annex-B units, and an Annex-B stream with 3-byte start
codes whose SPS and PPS unit, padded with trailing zero bytes, also reads
as one length prefix.
A picture deeper than 8 bits threw ("output deeper than 8 bits is not
implemented"), which stops Mortalfin (PPSA99141) as soon as it plays an HEVC
Main10 video (#6640).
A 10-bit picture is now written as 16-bit little-endian words with the sample
in the low 10 bits: Y rows, then interleaved UV rows at framePitchInBytes
times the height. framePitch is in samples and framePitchInBytes in bytes
(twice the width, aligned to 256). QueryDecoderMemoryInfo sizes a frame of an
HEVC or VP9 profile 2 configuration with two bytes per sample.
The layout and sizes follow EVO-PLAYER-PS5, which decodes and presents 1080p
HEVC Main10 on hardware through this path: its 10-bit check
(pitch_bytes >= pitch * 2), its UV offset, its low-bit sampling factor, and
the 1920x1088 Main10 frame buffer its hardware log reports (6128 KB after
rounding to 16 KiB).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceVideodec2Decode threw when it followed sceVideodec2Flush without
sceVideodec2Reset. It now resets FFmpeg's drained decoder and decodes the
unit, keeping the pictures the flush has not returned yet.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Decode and Flush let FFmpeg crop every picture to its display size, so a
1080p H.264 stream came out as 1920x1080 with the chroma after 1080 luma
rows. The console reports and writes the coded picture: EVO-PLAYER-PS5's
hardware run of a 1080p H.264 IDR returned 1920x1088 with pitch 2048 and
the chroma after the 1088 luma rows, and ProsperoLight rejects a 1080p
H.264 or HEVC picture whose height is not 1088. FFmpeg's cropping is now
off, so the frame size, the chroma offset and the sizes in the AVC
picture info are those of the coded picture. The pitch is unchanged, and
the frame size QueryDecoderMemoryInfo reports, which aligns the maximum
height to 32 rows, still holds a picture coded within the maximum and the
macroblock-padded H.264 picture of a maximum given as the display size.
libSceVdecsw derived its crop offsets from the difference between that
size and the macroblock grid, which is now zero. It takes the crop FFmpeg
exports for the picture from libSceVideodec2 instead.
The H.264 fixture is coded at 64x48 with frame_crop_bottom_offset 4: its
pictures are checked at 64x48 and the crop through Vdecsw. The HEVC and
VP9 fixtures are coded at 64x40 and keep their hashes. The new hashes come
from FFmpeg 8.1 decoding with apply_cropping 0, hashed as the tests do;
the same method reproduces every previous H.264, HEVC and VP9 hash.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
guest_videodec2 splits the first access unit of the H.264 fixture into
its parameter sets and its slices and decodes the parameter sets as a
unit of their own: the call must succeed without a picture, and every
picture after it must still match the reference hashes. With the
previous Export.cpp the first call throws "packet submission failed".
sceVideodec2GetPictureInfo searched the live decoders in handle order and
returned the first one that had ever written the queried frame buffer. When
two decoders wrote the same address, the lower handle answered with stale
timestamps, a stale AVC decoder answered for an HEVC or VP9 picture, a stale
HEVC or VP9 decoder made an AVC query throw, and resetting or deleting the
decoder that wrote the buffer last exposed the older decoder's picture again.
Record the decoder that last published a picture into each frame buffer and
answer from that decoder only. Reset and Delete drop only the decoder's own
records, so another decoder's picture is never removed or brought back.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
libSceVdecsw is the software H.264 decoder interface PPSA05684 uses for
its movies. Decoder creation, compute queues, memory queries, decode
input and output, AVC picture info, reset and finalize are implemented
with the layouts of shadPS4's vdecsw.h, checked against the title's
movie decoder, and decode through libSceVideodec2. The H.264 stream the
Videodec2 test uses moves to a shared fixture, and a guest test decodes
it through Vdecsw.
Uncharted: Legacy of Thieves Collection (PPSA05684) plays its movies through libSceVdecsw and stopped at sceVdecswQueryComputeMemoryInfo.
EVO-PLAYER (PPSA99039) creates resident AVC, HEVC and VP9 decoders at
start-up, and stopped at "Videodec2: unsupported codec" on the HEVC one.
Codec types 974921 (HEVC) and 2382845 (VP9) now open FFmpeg's HEVC and
VP9 decoders. HEVC input goes through the same Annex B conversion as
H.264 and VP9 frames are passed through; output stays 8-bit NV12, and a
frame deeper than 8 bits throws. Picture info throws for HEVC and VP9,
whose layouts differ from the AVC one.
Assisted by Claude Code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DwFnKjMxmwGDWiuYYf1v4D
Adds libSceVideodec2. Access units (Annex B, or length-prefixed rewritten to
Annex B) are decoded by FFmpeg's H.264 decoder into the title's NV12 frame
buffers (256-byte pitch, chroma after the visible luma rows). Decode hands
out at most one picture per call, Flush drains the reordered ones, Reset
clears the decoder; timestamps and attached data travel with the picture.
FFmpeg is found through pkg-config and is optional: without it the decoders
return black pictures. guest_videodec2_tests checks the pictures of an
embedded stream against reference hashes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>