Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GroupKey ¶
GroupKey returns the key that groups the discs of one title, and this disc's number. It prefers the volume label and falls back to the image's file name when the label is empty or has no disc suffix. A label without a disc suffix is its own key with disc number 0.
func ListISOFiles ¶
func ListISOFiles(ctx context.Context, rs io.ReadSeeker) ([]isoFileEntry, error)
ListISOFiles walks the ISO 9660/UDF filesystem and returns all non-directory entries. It tries UDF first (correct 64-bit sizes, authoritative for Blu-ray) and falls back to ISO 9660 for plain discs without UDF. ctx is threaded through the UDF walk so silent-drop sites can emit slog.WarnContext logs for diagnosis without polluting the io.ReadSeeker signature.
func ReadVolumeLabel ¶
func ReadVolumeLabel(rs io.ReadSeeker) string
ReadVolumeLabel returns the ISO 9660 Volume Identifier from the Primary Volume Descriptor at sector 16. Hybrid Blu-ray discs always carry a 9660 PVD even when the active filesystem is UDF, so this works for both plain ISOs and BD images.
Returns an empty string if the descriptor is missing or invalid — callers fall back to the ISO filename for disc-group keying.
Types ¶
type Analysis ¶
type Analysis struct {
// Label is the volume identifier, which groups the discs of one title.
Label string
// Files is every non-empty file.
Files []File
// MainFeature is the ordered clips of the Blu-ray main feature playlist,
// nil for a disc without one. Playing them back to back is the movie.
MainFeature []Clip
// DurationTicks is the main feature's authored length at 45 kHz.
DurationTicks int64
}
Analysis is what an ISO image holds.
func Analyze ¶
func Analyze(ctx context.Context, r io.ReaderAt, size int64, progress func(done, total int)) (*Analysis, error)
Analyze reads the filesystem of the ISO image r (size bytes), looks for a Blu-ray main feature and returns what it found. progress, when set, reports the playlists examined. It only reads structure: a few small ranges of the image, never its media.
type Clip ¶
Clip is a main-feature file with the playlist timing the Blu-ray gives it, in 45 kHz ticks. InTicks is where the clip's own timeline starts.
type Extent ¶
type Extent struct {
Offset, Length int64
}
Extent is one contiguous run of ISO image bytes.
type File ¶
File is one non-directory file of the image. Its bytes are the Extents in order (Blu-ray feature clips routinely use hundreds of them).
type MPLSPlayItem ¶
type MPLSPlayItem struct {
// ClipName is the 5-character clip_information_file_name (e.g. "00001").
// The corresponding stream lives at BDMV/STREAM/<ClipName>.M2TS.
ClipName string
// InTime and OutTime are 45 kHz presentation timestamps. Duration in
// ticks is OutTime - InTime; convert to seconds by dividing by 45000.
InTime uint32
OutTime uint32
}
MPLSPlayItem describes one entry in a PlayList.
type MPLSPlayList ¶
type MPLSPlayList struct {
Version string // e.g. "0100", "0200", "0300"
PlayItems []MPLSPlayItem
}
MPLSPlayList is the parsed view of a single .mpls file.
func ParseMPLS ¶
func ParseMPLS(data []byte) (*MPLSPlayList, error)
ParseMPLS decodes a .mpls file. All multi-byte integers are big-endian per the BDA spec. Sub-paths, the STN table, and per-angle alternates are skipped — we use each PlayItem's leading length field to advance past everything we don't need.
func (*MPLSPlayList) DurationTicks ¶
func (p *MPLSPlayList) DurationTicks() int64
DurationTicks returns the sum of (OutTime-InTime) across PlayItems in 45 kHz ticks. This is the standard proxy for "longest playlist = main feature" used by every Blu-ray player.
type MainFeaturePlaylist ¶
type MainFeaturePlaylist struct {
PlaylistName string // e.g. "00800.MPLS" — for logging only
SourceKind string // "m2ts" or "ssif" — selected source family
DurationTicks int64 // sum of (OUT-IN) at 45 kHz — informational, not used for selection
Streams []isoFileEntry // ordered M2TS entries (duplicates preserved if the playlist legitimately repeats a clip)
UniqueClipBytes uint64 // sum of file sizes of UNIQUE clips referenced; the primary scoring metric
UniqueClipCount int // number of distinct clips referenced; scoring tiebreaker
// ClipInTimes and ClipDurations are parallel to Streams: the MPLS
// PlayItem IN_time and (OUT−IN) for each stream, in 45 kHz ticks. They
// drive the continuous-timeline remux of the concatenated clips.
ClipInTimes []int64
ClipDurations []int64
}
MainFeaturePlaylist is the result of analysing a Blu-ray's BDMV. Streams is the ordered list of M2TS file entries that, concatenated, form the main feature; the slice is empty if no parseable playlist was found.
func ResolveMainFeature ¶
func ResolveMainFeature(ctx context.Context, rs io.ReadSeeker, files []isoFileEntry, progress func(done, total int)) *MainFeaturePlaylist
ResolveMainFeature inspects the entries returned by ListISOFiles for a Blu-ray (BDMV) structure and returns the playlist that represents the main movie. Returns nil if the disc is not BDMV, has no .mpls, or no playlist resolves to a non-empty M2TS sequence.
Selection heuristic: pick the playlist with the longest total presentation duration. Ties break on PlayItem count (more clips wins), then lexicographically smallest filename for determinism.
Failures parsing individual playlists are non-fatal — we skip them and keep evaluating the rest, mirroring how every Blu-ray player tolerates malformed entries in BDMV/PLAYLIST/.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package isotest builds ISO 9660 images and Blu-ray playlists for tests.
|
Package isotest builds ISO 9660 images and Blu-ray playlists for tests. |
|
cmd/genbluray
command
Command genbluray writes the small Blu-ray disc image used by the encrypted disc fixtures (see internal/archive/testdata/gen-iso7z.sh) and the main feature's bytes next to it.
|
Command genbluray writes the small Blu-ray disc image used by the encrypted disc fixtures (see internal/archive/testdata/gen-iso7z.sh) and the main feature's bytes next to it. |