stereo3d: detect layout signalled in the video stream (frame packing SEI, st3d) - #18490
danielcamposramos wants to merge 2 commits into
Conversation
|
Follow-up on scope, before it comes up in review. The description says no container-tagged file changes behaviour. That holds when the container tag and the in-band signal agree, which is the normal case, but not when they disagree: This is deliberate — it mirrors the frame rotation handling a few lines below in |
? The rude part here is you letting clod flood the maintainers with redundant text. |
Please read the contribution guidelines. You need to show you're capable of responding to reviews with human-written responses, which the AI-slop written commit messages implies you're not. |
AI-slop - define this term, please? What about human slop, like being rude to a genuine contribuition proposal? You are assuming that because I leveraged AI to write the PR is slop? HandBreak actually verifyed my claims before that... This message might contain english errors because it's not my main language and mainteners prefer wrong english than AI assisted writting. |
|
How often the frame-packing SEI is actually attached to a frame? It needs no patched mpv and no sample downloads. The block # Build a 10 s SBS clip with the frame-packing SEI and a keyframe every 48 frames.
ffmpeg -v error -f lavfi -i "testsrc2=size=960x1080:rate=24:duration=10" \
-f lavfi -i "smptebars=size=960x1080:rate=24:duration=10" \
-filter_complex "[0:v][1:v]hstack=inputs=2[v]" -map "[v]" \
-c:v libx264 -crf 20 -pix_fmt yuv420p -g 48 \
-x264-params frame-packing=3 sei_multi.mp4
# Same thing without the SEI, as a negative control.
ffmpeg -v error -f lavfi -i "testsrc2=size=960x1080:rate=24:duration=10" \
-f lavfi -i "smptebars=size=960x1080:rate=24:duration=10" \
-filter_complex "[0:v][1:v]hstack=inputs=2[v]" -map "[v]" \
-c:v libx264 -crf 20 -pix_fmt yuv420p -g 48 no_sei.mp4
# How many frames actually carry AV_FRAME_DATA_STEREO3D?
for f in sei_multi.mp4 no_sei.mp4; do
ffprobe -v error -select_streams v:0 -show_frames "$f" > /tmp/f.$$
printf "%-16s frames=%-5s keyframes=%-4s stereo3d_side_data=%s\n" "$f" \
"$(grep -c '^media_type=video' /tmp/f.$$)" \
"$(grep -c '^key_frame=1' /tmp/f.$$)" \
"$(grep -c '^side_data_type=Stereo 3D' /tmp/f.$$)"
rm -f /tmp/f.$$
done
# And which frames they are.
ffprobe -v error -select_streams v:0 -show_frames sei_multi.mp4 | awk '
/^media_type=video/{n++} /^key_frame=1/{k[n]=1} /^side_data_type=Stereo 3D/{s[n]=1}
END{for(i=1;i<=n;i++) if(k[i]||s[i]) printf "frame %3d keyframe=%d stereo3d=%d\n", i, (k[i]?1:0), (s[i]?1:0)}'OutputSame counts and the same frame indices across three major FFmpeg versions, so the result is a property of the file rather than of one build. Why it is built this way? |
|
Another data point on the approach, in case it is useful to the review: Kodi already does this, and has for years.
Verified by running Kodi 21.2 on a file whose only 3D signal is the SEI (neutral filename, no container tag): Sample to check against: And on why it matters outside players: on 2011–2012 Sony BRAVIA sets this SEI is the only signal that makes the display engage 3D by itself. Measured through two independent DLNA servers, byte-exact: the SEI-carrying file engages 3D, the identical file with the SEI removed plays flat. |
4b52cf6 to
baaf79f
Compare
mp_image_from_av_frame() imports nine kinds of frame side data from libavcodec, but not AV_FRAME_DATA_STEREO3D. As a result the only stereo 3D layout mpv ever saw was the Matroska StereoMode element, read by demux_mkv.c; a layout signalled in the video stream itself was ignored. libavcodec decodes the H.264/HEVC frame_packing_arrangement SEI (payload type 45) and the MP4 st3d box into AVStereo3D side data, so the information is already attached to the frame by the time mpv receives it. Map it onto mp_image_params.stereo3d, whose numeric values match the Matroska StereoMode element, including the right-eye-first variants via AV_STEREO3D_FLAG_INVERT. A container level tag, if present, is applied earlier via opaque_ref and keeps priority, so files that worked before behave exactly as before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix_image_params() overwrote the layout on every frame with the container tag from the demuxer, discarding a layout signalled in the stream. Worse, the in-band signal is not always carried by every frame: DVB requires the frame_packing_arrangement SEI on every frame of a broadcast service, but in x264 output and in every file tested it is repeated per IDR only, so only keyframes arrive with AV_FRAME_DATA_STEREO3D attached. The first frame was therefore detected correctly and the next frame reset the format back to mono for the rest of playback. Remember the layout signalled in the stream and reapply it to the frames that do not repeat it, and only fall back to the container tag when the stream signals nothing. This mirrors the existing handling of frame rotation a few lines below, where the value from the frame also takes priority over the container, and matches the precedence DVB gives the in-band signal over other signalling (ETSI TS 101 547-2 V1.2.1, clause 6.5). The remembered value is cleared in mp_decoder_wrapper_reset_params() so it does not leak across segments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
baaf79f to
1c5c04f
Compare
|
Look, I am not that good with words and english can be complicated to convey, I therefore disclosured the leverage of AI on the PR. The new rule also landed one day after I filed the PR and merge request. |
|
@kasper93 urging for a neutral technical review here. |
Fixes #18489.
What this patches:
StereoModeelement. A layout signalled in the video stream, the H.264/HEVCframe_packing_arrangementSEI (payload type 45), or the MP4st3dbox, is ignored, and such files play asstereo-in=mono.libavcodec already decodes that SEI into
AVStereo3Dframe side data and hands it to mpv. mpv never asks for it.Reproduction steps:
Three files isolating each signal, built in three commands using ffmpeg:
Before this patch
sei_only.mp4reportsstereo-in=mono; after it reportsstereo-in=sbs2l.Why the first frame was not enough:
The in-band signal is attached only to the frames that carry it. Measured files.
Results
Verified on Debian 14, x86_64, libavcodec 63.1.101, libplacebo 7.360.1, built from this tree. Real files are ordinary 3D videos, not synthesized for the test.
No container-tagged file changes behaviour, and files with no signal stay
mono.The inverted case is the one that showed why metadata beats guessing: that file's SEI declares
side by side (inverted), the right eye first type, while its filename saysSBS.Before this change mpv showed it flat; a player guessing from the filename would swap the viewer's eyes. Only the declared layout gets it right.
Scope:
This makes mpv detect the layout. It does not change what mpv does with it, no automatic conversion is added, and
--vf=format:stereo-in=...still overrides as before.Files that already worked are unaffected.
Relation to existing issues:
AVStereo3Dbeing wiredthrough this path.
sbsl/ablchoices; its reporter's file is aMatroska whose tag mpv reads correctly. That is the layout vocabulary; this is the
detection source.
Why this is becoming more common:
HandBrake merged support for writing this SEI (PR #8100), and FFmpeg has an open request for a lossless injector for it (#24531), so files carrying the in-band signal are expected to keep appearing.
Testing:
Tested, per
DOCS/contribute.md. Built from this tree and run against the three control files and a 26-file library of real 3D videos. Happy to adjust the mapping's placement — it could live next to mp_stereo3d_names[]incsputils.c` instead of inline — or to split the fallback differently if you would rather the container tag always win.Disclosure:
An AI partner helped produce the outcomes. The words here are mine, edited in the browser.
Every result above was executed and measured on my machine, not inferred;
The patch was compiled, the before/after values come from running both binaries against the same files, and the side-data-per-keyframe counts were measured with
ffmpeg -vf showinfo.