Package sofia (v1.15.9) [up] [repository]

remuxer.go

Index

Variables

var ErrStopped = errors.New("process stopped")

ErrStopped is returned by Process when the Stop channel was closed. Every segment processed before the return is durable in the output file; Progress reports where a resume should re-request from.

Functions

func Decrypt(data []byte, sample *SencSample, block cipher.Block)

--- Logic ---

func ExtractPsshData(data []byte) ([]byte, error)

ExtractPsshData takes a byte slice that may be raw protobuf, a single PSSH box, or nested PSSH boxes, and returns the innermost data payload.

Types

type Box

--- Box ---

type Box struct {
	Moov *MoovBox
	Moof *MoofBox
	Mdat *MdatBox
	Raw  []byte
}

Functions

func DecodeBoxes(data []byte) ([]Box, error)

type BoxHeader

--- BoxHeader ---

type BoxHeader struct {
	Size uint32
	Type [4]byte
}

Functions

func DecodeBoxHeader(data []byte) (*BoxHeader, error)

Methods

func (h *BoxHeader) Put(buffer []byte)

type Co64Box

--- CO64 ---

type Co64Box struct {
	Offsets []uint64
}

Functions

func DecodeCo64Box(data []byte) (*Co64Box, error)

Methods

func (b Co64Box) Encode() []byte

type CttsBox

--- CTTS ---

type CttsBox struct {
	Entries []CttsEntry
}

Functions

func DecodeCttsBox(data []byte) (*CttsBox, error)

Methods

func (b CttsBox) Encode() []byte

type CttsEntry

type CttsEntry struct {
	SampleCount  uint32
	SampleOffset int32
}

type EncBox

--- ENC (Encrypted Sample Entry) ---

type EncBox struct {
	Header      *BoxHeader
	EntryHeader []byte
	Sinf        *SinfBox
	RawChildren [][]byte
}

Functions

func DecodeEncBox(data []byte) (*EncBox, error)

Methods

func (b *EncBox) Encode() []byte

type FrmaBox

--- FRMA ---

type FrmaBox struct {
	Header     *BoxHeader
	DataFormat [4]byte
}

Functions

func DecodeFrmaBox(data []byte) (*FrmaBox, error)

Methods

func (b *FrmaBox) Encode() []byte

type MdatBox

--- MDAT ---

type MdatBox struct {
	Header  *BoxHeader
	Payload []byte
}

Functions

func DecodeMdatBox(data []byte) (*MdatBox, error)

type MdhdBox

--- MDHD ---

type MdhdBox struct {
	Header           *BoxHeader
	Version          byte
	Flags            [3]byte
	CreationTime     uint64
	ModificationTime uint64
	Timescale        uint32
	Duration         uint64
	Language         [2]byte
	Quality          [2]byte
}

Functions

func DecodeMdhdBox(data []byte) (*MdhdBox, error)

Methods

func (b *MdhdBox) Encode() []byte
func (b *MdhdBox) SetDuration(duration uint64)

type MdiaBox

--- MDIA ---

type MdiaBox struct {
	Header      *BoxHeader
	Mdhd        *MdhdBox
	Minf        *MinfBox
	RawChildren [][]byte
}

Functions

func DecodeMdiaBox(data []byte) (*MdiaBox, error)

Methods

func (b *MdiaBox) Encode() []byte

type MinfBox

--- MINF ---

type MinfBox struct {
	Header      *BoxHeader
	Stbl        *StblBox
	RawChildren [][]byte
}

Functions

func DecodeMinfBox(data []byte) (*MinfBox, error)

Methods

func (b *MinfBox) Encode() []byte

type MoofBox

--- MOOF ---

type MoofBox struct {
	Header      *BoxHeader
	Traf        *TrafBox
	RawChildren [][]byte
}

Functions

func DecodeMoofBox(data []byte) (*MoofBox, error)

type MoovBox

--- MOOV ---

type MoovBox struct {
	Header      *BoxHeader
	Mvhd        *MvhdBox
	Trak        []*TrakBox
	Pssh        []*PsshBox
	RawChildren [][]byte
}

Functions

func DecodeMoovBox(data []byte) (*MoovBox, error)
func FindMoov(boxes []Box) (*MoovBox, bool)

FindMoov returns the first moov of a decoded box list.

Methods

func (b *MoovBox) Encode() []byte
func (b *MoovBox) FindDefaultKID() []byte

FindDefaultKID walks the first track's sample entries and returns the first non-zero default KID declared by a 'tenc' box, following trak > mdia > minf > stbl > stsd > enc > sinf > schi > tenc. An all-zero KID means no key is declared by that box, so it is skipped. Returns nil if no KID is found.

func (b *MoovBox) FindPssh(systemID []byte) (*PsshBox, bool)
func (b *MoovBox) RemoveMvex()

type MvhdBox

--- MVHD ---

type MvhdBox struct {
	Header           *BoxHeader
	Version          byte
	Flags            [3]byte
	CreationTime     uint64
	ModificationTime uint64
	Timescale        uint32
	Duration         uint64
	RemainingData    []byte
}

Functions

func DecodeMvhdBox(data []byte) (*MvhdBox, error)

Methods

func (b *MvhdBox) Encode() []byte
func (b *MvhdBox) SetDuration(duration uint64)

type PsshBox

--- PSSH ---

type PsshBox struct {
	Header   *BoxHeader
	Version  byte
	Flags    [3]byte
	SystemID [16]byte
	KIDs     [][16]byte
	Data     []byte
}

Functions

func DecodePsshBox(data []byte) (*PsshBox, error)

type RemuxSample

type RemuxSample struct {
	Size                  uint32
	Duration              uint32
	IsSync                bool
	CompositionTimeOffset int32
}

type RemuxState

RemuxState is the remuxer bookkeeping recovered from a stopped file. It is exactly the state the remuxer held when it was stopped, derived from the sample tables in the moov that Finish wrote to the file.

type RemuxState struct {
	Samples         []*RemuxSample
	ChunkOffsets    []uint64
	SamplesPerChunk []uint32
}

Functions

func StateFromMoov(moovData []byte) (*RemuxState, error)

StateFromMoov rebuilds remuxer state from the moov that Finish wrote to a stopped file. It is a pure decode: the input is only the moov bytes, which the caller reads from the file without touching the media data, so memory use is bounded by the moov size, never the file size.

type Remuxer

type Remuxer struct {
	Writer   io.WriteSeeker
	Moov     *MoovBox
	OnSample func(data []byte, sample *SencSample)
	// OnMoov, when set, is called by Process when it consumes a moov from
	// the stream, before any segment is processed. Returning an error
	// aborts Process. This is where a caller fetches its DRM key: the KID
	// lives in the moov, and the key must be in hand before any sample is
	// decrypted. While the callback runs the reader is simply not being
	// read; the open HTTP connection sits backpressured.
	OnMoov func(moov *MoovBox) error
	// Stop, when closed, asks Process to return ErrStopped at the next
	// segment boundary. A nil Stop means Process never stops early. The
	// caller owns the channel and closes it; sofia only receives.
	Stop <-chan struct{}
	// contains filtered or unexported fields
}

Methods

func (r *Remuxer) AddSegment(segmentData []byte) error

AddSegment processes one complete, standalone segment: every moof+mdat pair inside it becomes a fragment. Trailing bytes that do not form a complete box are ignored.

func (r *Remuxer) AdoptState(initSegment []byte, state *RemuxState, segmentsDone int) error

AdoptState resumes a remuxer from state recovered out of a stopped file (StateFromMoov). The mdat header written by Initialize sits at offset 0 of the original file, where the payloads still begin, so the chunk offsets in the state remain valid as-is. The caller truncates the old moov away and positions the writer at the payload boundary; AdoptState itself performs no I/O.

func (r *Remuxer) Finish() error
func (r *Remuxer) Initialize(initSegment []byte) error
func (r *Remuxer) Process(reader io.Reader) error

Process streams a continuous MP4 from reader: ftyp, sidx, styp and free boxes are skipped without interpretation, the first moov initializes the remuxer (calling OnMoov before any segment is processed; a moov arriving when the remuxer is already initialized — from an init segment or a resume — is skipped), and each moof+mdat pair becomes a segment processed exactly as AddSegment would process it. One segment at a time is held in memory — the moof and mdat bytes — and released before the next segment is read. The reader is consumed directly with no intermediate buffering: it should be the raw HTTP response body. It returns nil at EOF, ErrStopped when Stop was closed, or the first error. Stop is checked between segments, so a segment whose moof was already read still completes.

func (r *Remuxer) Progress() (inputOffset int64, segmentsDone int)

Progress reports the resume point after Process returns: the number of bytes consumed just past the last complete segment, and the number of segments processed. The offset is relative to the first byte this session's Process call read, so a resumed session adds the offset it started from.

type SchiBox

--- SCHI (Scheme Information) ---

type SchiBox struct {
	Header      *BoxHeader
	Tenc        *TencBox
	RawChildren [][]byte
}

Functions

func DecodeSchiBox(data []byte) (*SchiBox, error)

Methods

func (b *SchiBox) Encode() []byte

type SencBox

--- SENC ---

type SencBox struct {
	Header  *BoxHeader
	Flags   uint32
	Samples []SencSample
}

Functions

func DecodeSencBox(data []byte) (*SencBox, error)

type SencSample

type SencSample struct {
	IV         []byte
	Subsamples []Subsample
}

type SinfBox

--- SINF ---

type SinfBox struct {
	Header      *BoxHeader
	Frma        *FrmaBox
	Schi        *SchiBox
	RawChildren [][]byte
}

Functions

func DecodeSinfBox(data []byte) (*SinfBox, error)

Methods

func (b *SinfBox) Encode() []byte

type StblBox

--- STBL ---

type StblBox struct {
	Header      *BoxHeader
	Stsd        *StsdBox
	Stts        *SttsBox
	Ctts        *CttsBox
	Stsz        *StszBox
	Stsc        *StscBox
	Stco        *StcoBox
	Co64        *Co64Box
	Stss        *StssBox
	RawChildren [][]byte
}

Functions

func DecodeStblBox(data []byte) (*StblBox, error)

Methods

func (b *StblBox) Encode() []byte

type StcoBox

--- STCO ---

type StcoBox struct {
	Offsets []uint32
}

Functions

func DecodeStcoBox(data []byte) (*StcoBox, error)

Methods

func (b StcoBox) Encode() []byte

type StscBox

--- STSC ---

type StscBox struct {
	Entries []StscEntry
}

Functions

func DecodeStscBox(data []byte) (*StscBox, error)

Methods

func (b StscBox) Encode() []byte

type StscEntry

type StscEntry struct {
	FirstChunk             uint32
	SamplesPerChunk        uint32
	SampleDescriptionIndex uint32
}

type StsdBox

--- STSD ---

type StsdBox struct {
	Header       *BoxHeader
	HeaderFields [8]byte // Ver(1)+Flags(3)+EntryCount(4)
	EncChildren  []*EncBox
	RawChildren  [][]byte
}

Functions

func DecodeStsdBox(data []byte) (*StsdBox, error)

Methods

func (b *StsdBox) Encode() []byte
func (b *StsdBox) RemoveSinf() error

type StssBox

--- STSS ---

type StssBox struct {
	Indices []uint32
}

Functions

func DecodeStssBox(data []byte) (*StssBox, error)

Methods

func (b StssBox) Encode() []byte

type StszBox

--- STSZ ---

type StszBox struct {
	SampleSize  uint32
	SampleCount uint32
	EntrySizes  []uint32
}

Functions

func DecodeStszBox(data []byte) (*StszBox, error)

Methods

func (b StszBox) Encode() []byte

type SttsBox

--- STTS ---

type SttsBox struct {
	Entries []SttsEntry
}

Functions

func DecodeSttsBox(data []byte) (*SttsBox, error)

Methods

func (b SttsBox) Encode() []byte

type SttsEntry

type SttsEntry struct {
	SampleCount    uint32
	SampleDuration uint32
}

type Subsample

type Subsample struct {
	BytesOfClearData     uint16
	BytesOfProtectedData uint32
}

type TencBox

--- TENC --- TencBox defines the Track Encryption Box ('tenc'), which contains default encryption parameters for a track. Specification: ISO/IEC 23001-7

type TencBox struct {
	Header                 *BoxHeader
	Version                byte
	Flags                  uint32
	DefaultIsProtected     byte
	DefaultPerSampleIVSize byte
	DefaultKID             [16]byte
	DefaultConstantIVSize  byte   // Present if DefaultIsProtected=1 and DefaultPerSampleIVSize=0
	DefaultConstantIV      []byte // Present if DefaultIsProtected=1 and DefaultPerSampleIVSize=0
}

Functions

func DecodeTencBox(data []byte) (*TencBox, error)

Methods

func (b *TencBox) Encode() []byte

type TfhdBox

--- TFHD ---

type TfhdBox struct {
	Header                 *BoxHeader
	Flags                  uint32
	TrackID                uint32
	BaseDataOffset         uint64
	SampleDescriptionIndex uint32
	DefaultSampleDuration  uint32
	DefaultSampleSize      uint32
	DefaultSampleFlags     uint32
}

Functions

func DecodeTfhdBox(data []byte) (*TfhdBox, error)

type TrafBox

--- TRAF ---

type TrafBox struct {
	Header      *BoxHeader
	Tfhd        *TfhdBox
	Trun        []*TrunBox
	Senc        *SencBox
	RawChildren [][]byte
}

Functions

func DecodeTrafBox(data []byte) (*TrafBox, error)

type TrakBox

--- TRAK ---

type TrakBox struct {
	Header      *BoxHeader
	Mdia        *MdiaBox
	RawChildren [][]byte
}

Functions

func DecodeTrakBox(data []byte) (*TrakBox, error)

Methods

func (b *TrakBox) Encode() []byte
func (b *TrakBox) RemoveEdts()

type TrunBox

--- TRUN ---

type TrunBox struct {
	Header           *BoxHeader
	Flags            uint32
	SampleCount      uint32
	DataOffset       int32
	FirstSampleFlags uint32
	Samples          []TrunSample
}

Functions

func DecodeTrunBox(data []byte) (*TrunBox, error)

type TrunSample

type TrunSample struct {
	Size                  uint32
	Duration              uint32
	Flags                 uint32
	CompositionTimeOffset int32
}