Mux Blu-ray 3D (MVC) as a single MVC video track
Fold the MVC dependent (right-eye) view into the base H.264 track as a per-frame BlockAdditional under an mvcC BlockAdditionMapping, so a 3D title produces one MVC video track instead of two independent H.264 tracks. - h264: MVC-passthrough parser mode keeps the dependent view's subset SPS/PPS in-band, so each emitted frame is a self-contained dependent access unit for a BlockAdditional - resolve: route the dependent stream through the passthrough parser - mkvstream: detect the dependent view, pair it to the base frame by PTS (bounded FIFO), attach it as a BlockAdditional (BlockAddID=2), and skip building its own track; build the mvcC MVCDecoderConfigurationRecord from the captured subset SPS/PPS and set it on the base track at activation - mkv: emit the mvcC BlockAdditionMapping and BlockGroup/BlockAdditions, with a ReferenceBlock on non-keyframe base frames - ebml: add BlockAdditions/BlockMore/BlockAdditional/BlockAddID/ BlockAddIDValue/ReferenceBlock elements and a signed-int writer Verified against a Blu-ray 3D ISO: ffprobe shows a single MVC track, the mvcC mapping is present, ~144k BlockAdditionals carry the dependent view (8.7 GB), and the base view decodes cleanly with no regression. MVCDecoderConfigurationRecord follows ISO/IEC 14496-15 7.6.2; StereoMode is intentionally omitted (no enum value describes MVC-in-BlockAdditional; the mvcC mapping is the primary 3D signal per RFC 9559).
This commit is contained in:
+11
-1
@@ -575,7 +575,17 @@ fn build_demux_state(title: &DiscTitle, format: ContentFormat) -> DemuxState {
|
||||
pids.push(pid);
|
||||
pid_to_track.push((pid, idx));
|
||||
let is_dvd_ps = matches!(format, ContentFormat::MpegPs);
|
||||
parsers.push((pid, super::codec::parser_for_codec(codec, None, is_dvd_ps)));
|
||||
// The Blu-ray 3D MVC dependent (right-eye) view uses a param-set-
|
||||
// passthrough H.264 parser so each frame is a self-contained dependent
|
||||
// access unit for a BlockAdditional; every other stream uses the
|
||||
// ordinary parser for its codec.
|
||||
let parser = match s {
|
||||
crate::disc::Stream::Video(v) if v.is_mvc_dependent() => {
|
||||
super::codec::parser_for_mvc_dependent(codec, is_dvd_ps)
|
||||
}
|
||||
_ => super::codec::parser_for_codec(codec, None, is_dvd_ps),
|
||||
};
|
||||
parsers.push((pid, parser));
|
||||
}
|
||||
let (ts, ps) = match format {
|
||||
ContentFormat::MpegPs => (None, Some(super::ps::PsDemuxer::new())),
|
||||
|
||||
Reference in New Issue
Block a user