playbackbuffer

package
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: GPL-3.0 Imports: 8 Imported by: 0

README

Retained output and publication barrier

This package is a delivery-controller primitive for encoder-worker loss. It does not recover a controller or source, start or retire encoders, maintain sessions in SQL, publish HTTP playlists, or infer client buffering.

New requires explicit global and per-session byte, segment and init counts, plus a session count. OpenSession starts at floor -1. Retain charges five times the declared length before reading (retained backing bytes plus conservative parser workspace); after EOF validation it releases the workspace charge. Limits cover payload backing bytes and counts, not Go runtime/allocator overhead. No partial input is committed. Readers must honor cancellation themselves when a Read can block: the package creates no goroutines and cannot cancel arbitrary io.Reader implementations. Checks occur between reads and before commit.

Retained entries are staged. Publish atomically advances an exact state CAS and makes a contiguous batch available to Acquire. Snapshots copy metadata and facts; leases expose copy-out ReadAt, never a writable slice. Published bytes cannot be deleted, and session close fails while a reader or reservation is active. Capacity exhaustion refuses new work; it never silently evicts old bytes. Use fresh session IDs after close. This intentionally bounded first implementation has no rolling publication-retirement policy.

FreezeGeneration(id, expected, next State) freezes ordinary publication and returns a store-specific single-use token binding session, old/new generation, old/new seek epochs and exact old/new sequence floors. PublishTransition checks that same state, then checks every staged segment's stored facts under the publication lock. Old committed keys remain readable throughout. AbortTransition unfreezes without publishing; staged bytes can then be explicitly deleted. Closing a session also invalidates its token. This package has no authority to stop a worker.

Evidence boundary

The initial parser supports single-program MPEGTS with one-packet PAT/PMT, H.264 Annex B, and ADTS AAC. It validates table CRCs, transport continuity, PES lengths, timestamp markers, and supported elementary framing. Each track reports raw 33-bit PES PTS/DTS in 90,000 Hz ticks. LastPTS is the maximum observed PES timestamp, not the final AAC frame inside that PES or its end time. Clock wrap, discontinuity, unsupported tracks, malformed structure and incomplete PES deny verified facts. Zero-length video PES is unsupported because packet-aligned truncation is otherwise ambiguous; recovery CPU output must use -omit_video_pes_length 0, and oversized video PES is likewise unsupported. fMP4 and init bytes can be retained and ordinarily published but never authorize a recovery transition.

Facts.Verified certifies these structural observations only. H.264 independence means that SPS/PPS precede the first VCL and that first VCL is IDR. It does not validate every codec syntax element or prove that a decoder accepts the payload. Config hashes compare the actual observed SPS/PPS or ADTS configuration bytes. ADTS validation does not decode audio samples. Arbitrary codec corruption can be undetectable at this structural layer; these are not decoded-media certificates.

A transition requires equal track identities/configurations, independent incoming tracks, and strictly advancing observed timestamps. It does not establish sample-end duration, gap-free continuity, AV synchronization, a shared title clock, client receipt, client retention, decoded output, or seamless playback. Higher-level recovery acceptance must validate those separately. HTTP completion belongs to delivery accounting and cannot turn these facts into client-buffer claims. No filenames, sequence numbers or playlist durations supply media facts.

The offline fixture is 0.3 seconds of generated black video and a generated sine wave, not external media. It was produced with:

ffmpeg -f lavfi -i color=c=black:s=64x64:r=10 \
  -f lavfi -i sine=frequency=440:sample_rate=48000 -t 0.3 \
  -c:v libx264 -preset ultrafast -threads 1 -bf 0 -g 3 \
  -x264-params repeat-headers=1:scenecut=0 -c:a aac -b:a 32k \
  -omit_video_pes_length 0 -f mpegts testdata/cpu.ts

Tests need neither ffmpeg nor network access.

Documentation

Overview

Package playbackbuffer retains completed encoder output for a surviving delivery controller. It owns neither encoder lifecycle nor client playback state.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Budget

type Budget struct {
	Bytes           int64
	Segments, Inits int
}

type Facts

type Facts struct {
	Verified bool
	Reason   string
	Tracks   []TrackFacts
}

Facts describe container observations, not a decoder verdict or sample-end durations. Verified is deliberately false for unsupported formats, transport discontinuities, clock wrap, missing tracks, and structural parse failures. An initial per-PID discontinuity marker is a legal muxer reset, not an intra-segment discontinuity. MPEGTS timestamps are unsigned 33-bit ticks at exactly 90000 Hz. Wrap is rejected, never silently normalized against an unrelated generation.

type Format

type Format uint8
const (
	MPEGTS Format = iota
	FMP4
)

type FreezeToken

type FreezeToken struct {
	// contains filtered or unexported fields
}

FreezeToken is opaque, store-specific and single-use. It grants no start or retirement authority. Its target generation is fixed at freeze time.

type Key

type Key struct {
	Session               string
	Generation, SeekEpoch uint64
	Sequence              int64
	Kind                  Kind
}

Key identifies bytes permanently within a session lifetime. Generations must increase; callers must use a fresh session identity when reopening a session.

type Kind

type Kind uint8
const (
	Segment Kind = iota
	Init
)

type Lease

type Lease struct {
	// contains filtered or unexported fields
}

Lease exposes copy-out reads only. Close waits for concurrent ReadAt calls and releases the pin. No method returns the store's mutable backing slice.

func (*Lease) Close

func (l *Lease) Close() error

func (*Lease) Identity

func (l *Lease) Identity() (RetainedIdentity, error)

Identity rechecks the pin, entry and current generation under the store lock. Old generation leases remain readable through ReadAt but cannot mint fresh recovery receipts after a transition. No parsed metadata is trusted here.

func (*Lease) ReadAt

func (l *Lease) ReadAt(p []byte, off int64) (int, error)

type Limits

type Limits struct {
	Global, PerSession Budget
	Sessions           int
}

type Metadata

type Metadata struct {
	Key       Key
	Format    Format
	Size      int64
	Published bool
	Facts     Facts
}

type RetainedIdentity

type RetainedIdentity struct {
	Key    Key
	Format Format
	Size   int64
	State  State
}

RetainedIdentity describes an actual published entry and the live session state at inspection time. It is evidence, never a publication permission.

type Snapshot

type Snapshot struct {
	// FirstPublishedSequence through State.PublishedFloor is the retained,
	// contiguous public sequence range; -1 denotes an empty range.
	FirstPublishedSequence int64
	State                  State
	Frozen                 bool
	Usage                  Budget
	Entries                []Metadata
}

type State

type State struct {
	Generation, SeekEpoch uint64
	PublishedFloor        int64
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

func New

func New(l Limits) (*Store, error)

func (*Store) AbortTransition

func (s *Store) AbortTransition(t *FreezeToken) error

func (*Store) Acquire

func (s *Store) Acquire(k Key) (*Lease, error)

func (*Store) AdvanceGeneration

func (s *Store) AdvanceGeneration(id string, expected State, generation uint64) error

AdvanceGeneration is a controller-authorized fixed-grid ownership change. The contiguous published prefix remains immutable and readable. Old staged bytes cannot publish after this CAS; the next generation begins at floor+1. This method does not certify media/audio continuity; the encoder resume contract and independent playback acceptance must establish those facts.

func (*Store) CloseSession

func (s *Store) CloseSession(id string) error

func (*Store) Delete

func (s *Store) Delete(k Key) error

Delete only releases staged bytes. Published output is promised until the controller explicitly closes the session; there is no automatic eviction.

func (*Store) FreezeGeneration

func (s *Store) FreezeGeneration(id string, expected State, next State) (*FreezeToken, error)

func (*Store) OpenSession

func (s *Store) OpenSession(id string, initial State) error

func (*Store) Publish

func (s *Store) Publish(id string, expected State, keys []Key) error

Publish atomically exposes a contiguous batch from the current generation. Ordinary publication can expose unverified media; a recovery transition cannot.

func (*Store) PublishTransition

func (s *Store) PublishTransition(t *FreezeToken, keys []Key) error

PublishTransition verifies advancing observed PES timestamps and independent starts on every track. It does NOT prove a gap-free sample-duration boundary, decodability, delivery, or seamless playback. Old publications remain readable.

func (*Store) Retain

func (s *Store) Retain(ctx context.Context, k Key, f Format, n int64, r io.Reader) error

Retain reserves five times the declared size (bytes plus bounded parsing workspace) before reading, reduced to exact retained bytes on success. It and requires EOF immediately after it. Reader must honor ctx itself if its Read can block; no hidden reader goroutine is created. All failed reads release their reservation. Successful bytes are staged and cannot be acquired until Publish or PublishTransition.

func (*Store) Snapshot

func (s *Store) Snapshot(id string) (Snapshot, error)

type TrackFacts

type TrackFacts struct {
	PID                                  uint16
	StreamType                           byte
	FirstPTS, LastPTS, FirstDTS, LastDTS int64
	Independent                          bool
	Config                               [32]byte
}

TrackFacts timestamps are the first and maximum observed PES PTS and first/last PES DTS, not every access-unit timestamp. In particular an AAC PES can contain several ADTS frames after LastPTS. No sample-end time is inferred.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL