mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 10:53:50 +02:00
199 lines
9.2 KiB
Plaintext
199 lines
9.2 KiB
Plaintext
================================================================================
|
|
MEDIABUNNY HLS BRANCH - BUG FIXES AND BEHAVIOR CHANGES TO EXISTING CODE
|
|
For use in release notes. Only covers changes to pre-existing code.
|
|
New HLS/CMAF features are not listed here.
|
|
================================================================================
|
|
|
|
|
|
============================================================
|
|
BUG FIXES
|
|
============================================================
|
|
|
|
1. SourceRef race conditions (commit aa810fc)
|
|
- Source cache entry was added BEFORE the reference was fully created,
|
|
allowing premature garbage collection of cached sources
|
|
- Cache eviction variable pointed to wrong ref (local instead of entry)
|
|
- `count > MAX_SOURCE_CACHE_SIZE` off-by-one -> `count >= MAX_SOURCE_CACHE_SIZE`
|
|
- Input.source and Input.target getters could return unused/stale instances
|
|
when using async callbacks; now properly tracked via _getRootSourceRef()
|
|
|
|
2. Track closing race conditions in all muxers (commit 94678dd)
|
|
- ISOBMFF, Matroska, MPEG-TS, and OGG muxers used `trackData.track.source._closed`
|
|
to check if tracks were closed. This was racy because the closed state could
|
|
change between check and use. Added explicit `closed: boolean` field to all
|
|
muxer track data structures, set synchronously in onTrackClose().
|
|
|
|
3. Target.slice() validation bug (commit 7b70756)
|
|
- Validation used `!Number.isInteger(offset) && offset < 0` (AND), meaning
|
|
negative non-integer offsets slipped through. Fixed to use OR (`||`).
|
|
|
|
4. MPEG-TS demuxer: off-by-one errors in reorder buffer logic
|
|
- Rewind loop changed from `reorderSize` to `reorderSize + 1` iterations,
|
|
fixing packet duration calculation near seek points
|
|
- End-of-stream rewind loop changed from `reorderSize - 1` to `reorderSize`
|
|
- Flush condition changed from `>= reorderSize` to `> reorderSize`, keeping
|
|
one extra packet in the buffer before flushing for correct presentation
|
|
order computation
|
|
|
|
5. MPEG-TS demuxer: first chunk assertion crash (line 1031-1035)
|
|
- Old code asserted that a key frame is always found in the first chunk,
|
|
crashing on files where that assumption doesn't hold (e.g., HLS segments
|
|
starting mid-GOP). Changed to gracefully return null.
|
|
|
|
6. MPEG-TS demuxer: video parameters only searched in first packet
|
|
- Some muxers place SPS/PPS in later packets. The demuxer now loops through
|
|
multiple packets to find AVC/HEVC decoder configuration records instead of
|
|
only checking the first one.
|
|
|
|
7. ISOBMFF: duration calculation didn't account for sample duration
|
|
- `lastPresentedSample()` found the sample with the highest timestamp but
|
|
didn't add its duration. Replaced with `presentationSpan()` that correctly
|
|
computes `maxEndTimestamp - minTimestamp`.
|
|
|
|
8. ISOBMFF demuxer: assertion crash on unavailable data
|
|
- Demuxer asserted that read slices are non-null. Changed to gracefully
|
|
return null when data is outside available range (important for streaming/
|
|
progressive scenarios).
|
|
|
|
9. ISOBMFF demuxer: multiple trun boxes per fragment rejected
|
|
- Old code logged a warning and skipped the second trun box. Now correctly
|
|
accumulates samples across multiple trun boxes per track per fragment,
|
|
maintaining cumulative offset and timestamp state.
|
|
|
|
10. Conversion API: track count validation before fan-out consideration
|
|
(commit 2f576aa)
|
|
- Tracks were validated against the max count before considering that some
|
|
track options had `discard: true`. Now validates inside the fan-out loop.
|
|
|
|
11. MP3 muxer: frame positions recorded at wrong offset
|
|
- Frame byte positions were recorded AFTER writing packet data. Now recorded
|
|
BEFORE writing, which is correct for Xing TOC frame offset calculations.
|
|
|
|
12. FLAC demuxer: missing STREAMINFO validation
|
|
- Added explicit error when STREAMINFO metadata block is missing,
|
|
producing a clear "Corrupted FLAC file" message instead of undefined
|
|
behavior downstream.
|
|
|
|
|
|
============================================================
|
|
BEHAVIOR CHANGES
|
|
============================================================
|
|
|
|
1. Default keyFrameInterval changed from 5 seconds to 2 seconds
|
|
(commit c6e505a)
|
|
Aligns with default HLS segment duration. Affects all video encoding
|
|
that doesn't explicitly set keyFrameInterval.
|
|
|
|
2. Conversion API copies input pairability graph by default (commit 6410ea9)
|
|
When track group is not explicitly specified, conversion now auto-creates
|
|
OutputTrackGroups that mirror the input track pairing relationships. This
|
|
means converted outputs preserve which tracks are meant to play together.
|
|
|
|
3. Matroska demuxer: removed implicit track sorting by default disposition
|
|
Tracks are no longer sorted so that default=true tracks come first.
|
|
Now all tracks have `primary: false` by default. Callers should use the
|
|
getPrimaryVideoTrack()/getPrimaryAudioTrack() methods for selection.
|
|
|
|
4. Removed superfluous end-position seeks in muxer finalize methods
|
|
(commit 7b70756)
|
|
MP3, FLAC, and Matroska muxers no longer seek to the end of file after
|
|
writing final metadata. The seek was unnecessary since the writer is
|
|
done at that point.
|
|
|
|
5. clampCropRectangle now returns a new object instead of mutating input
|
|
(src/sample.ts:1123)
|
|
|
|
6. Date.now() -> performance.now() in FinalizationRegistry callback
|
|
(src/sample.ts:48)
|
|
Uses monotonic time for timing measurements.
|
|
|
|
7. Codec string parsing: mp4a.40.34 now correctly identified as MP3
|
|
(src/codec.ts:677-686)
|
|
Previously would have matched the aac prefix check. MP3 check now
|
|
runs first and includes this codec string.
|
|
|
|
8. UrlSource: servers without Content-Length now supported
|
|
Previously, if the server returned 200 without a Content-Length header,
|
|
UrlSource threw an error. Now it gracefully handles this by downloading
|
|
the entire resource with an unbounded worker (targetPos = Infinity,
|
|
strictTarget = false), determining file size once the stream ends.
|
|
|
|
9. UrlSource: file size probing request removed
|
|
The old UrlSource always made a dedicated initial `Range: bytes=0-`
|
|
request solely to probe file size and range request support. File size
|
|
is now determined lazily from the response headers of the first actual
|
|
read, removing the extra round-trip.
|
|
|
|
10. UrlSource: non-range-request server warnings deduplicated per origin
|
|
The "server did not respond with 206 Partial Content" warning is now
|
|
emitted at most once per origin instead of on every request.
|
|
|
|
11. ReadableStreamSource: reader now canceled on dispose
|
|
ReadableStreamSource._dispose() now calls `this._reader?.cancel()`,
|
|
properly releasing the underlying stream resource.
|
|
|
|
12. ReadOrchestrator: worker queue system
|
|
When the maximum worker count is reached, reads are now queued and
|
|
dispatched when a worker becomes free, instead of evicting running
|
|
workers which could abort in-flight fetches.
|
|
|
|
|
|
============================================================
|
|
DEPRECATIONS
|
|
============================================================
|
|
|
|
1. InputTrack sync property getters (commit 051578c)
|
|
All sync getters on InputTrack/InputVideoTrack/InputAudioTrack are now
|
|
deprecated in favor of async methods:
|
|
.codec -> await .getCodec()
|
|
.languageCode -> await .getLanguageCode()
|
|
.name -> await .getName()
|
|
.timeResolution -> await .getTimeResolution()
|
|
.disposition -> await .getDisposition()
|
|
.displayWidth -> await .getDisplayWidth()
|
|
.displayHeight -> await .getDisplayHeight()
|
|
.rotation -> await .getRotation()
|
|
(etc.)
|
|
The sync getters still work for non-HLS inputs but throw when the
|
|
backing requires async resolution (e.g., HLS tracks before hydration).
|
|
|
|
2. Source.onread callback -> source.on('read', handler)
|
|
The onread setter still works but is marked @deprecated.
|
|
|
|
3. Target.onwrite callback -> target.on('write', handler)
|
|
Same as above.
|
|
|
|
|
|
============================================================
|
|
REMOVALS
|
|
============================================================
|
|
|
|
1. Target.onfinalized callback (commit 6410ea9)
|
|
Removed entirely. Use the 'finalized' event: target.on('finalized', ...).
|
|
|
|
2. InputTrackDescriptor concept (commit 051578c)
|
|
The entire InputTrackDescriptor API was removed. Its functionality
|
|
(pairable tracks, primary track selection) is now directly on InputTrack.
|
|
|
|
3. InputTrack[] option for ConversionOptions.tracks (commit 606ee87)
|
|
ConversionOptions.tracks now only accepts 'all' | 'primary', no longer
|
|
accepts an array of InputTrack instances.
|
|
|
|
4. Unnecessary sync getter wrappers (commit 8241820)
|
|
Removed deprecated sync getters for: hasOnlyKeyPackets, bitrate,
|
|
averageBitrate, isRelativeToUnixEpoch on InputTrack.
|
|
|
|
|
|
============================================================
|
|
API ADDITIONS (for context, not release-note-worthy on their own)
|
|
============================================================
|
|
|
|
- PacketRetrievalOptions.skipLiveWait (fixes #342)
|
|
- DiscardedTrack.trackOptions field
|
|
- TargetRequest.mimeType
|
|
- TrackDisposition.primary
|
|
- Source/Target/Output extend EventEmitter
|
|
- CanvasSink methods now async generators (getCanvas, canvases, canvasesAtTimestamps)
|
|
- EncodedPacketSink.getFirstPacket/getPacket/getNextPacket now async
|
|
- Muxer writers deferred to start() instead of constructor
|