peaBerberian / wasp-hls

WebAssembly-based (Rust) & in-worker HLS Media Player for the web
https://peaberberian.github.io/wasp-hls/
MIT License
124 stars 4 forks source link

[WIP] Port MPEG-TS + Packed Audio AAC transmuxer from TypeScript to Rust (and thus from JS to WebAssembly) #5

Open peaBerberian opened 1 year ago

peaBerberian commented 1 year ago

NOTE: This PR is a work-in-progress still at the very beginning. Most of the code has been almost directly converted manually from TypeScript to Rust so some code may not look idiomatic yet (nor performant at all for that matter).

Transmuxing and the need for it

The HLS specification defines several allowed formats for media and initialization segments.

Among them, the WaspHlsPlayer supports the three most frequent ones: fmp4, mpeg2-ts and packed audio AAC.

The first one (fmp4) is very well supported amongst browser so may be pushed directly to the browser's SourceBuffer for later decoding. However, support is very poor for the other two, leading us to need to transform that data before communicating it to the browser.

That's where the "transmuxer" comes into play. In the WaspHlsPlayer it takes either an mpeg2-ts or AAC formatted segment, and basically repackage it into an fmp4 segment for the browser.

This is called transmuxing, an operation generally more performance-sensitive than others in an HLS web player and which also may handle huge chunks of memory - both areas where WebAssembly might be a better tool than JavaScript.

Previous state

For now, WaspHlsPlayer's transmuxer is written in TypeScript.

This is because it's a fork of mux.js's own transmuxer for reasons explained in the corresponding Pull Request.

On some segments (for example the content with 10 seconds segments found in the demo page), this transmuxer may take several hundreds of milliseconds to parse a single segment on the laptop I tested it on (Its performance is indistinguishable from the original transmuxer's one on that part). This doesn't block the UI as transmuxing is performed in a WebWorker and thus concurrently, yet it may still be annoying, for example when playing low-latency contents (though when playing low-latency contents we do parse much shorter chunks of data) or when doing an operation - like a seek - where the faster the response, the better (here we might both block the seek operation due to a segment already being parsed, and postpone the next segment pushing)

Moreover, transmuxing is an operation handling huge chunks of data where I would prefer to have a better control on memory management.

This PR

Consequently, this PR tries to port our TypeScript transmuxer (from the src/ts-transmux directory) to Rust (in the src/rs-core/transmux directory).

This is a very long ongoing effort, and there's no guarantee that it will actually perform better than the previous one, but still seems like a logical next-step in theory.

As this project is mainly for fun anyway, I decided to go on with it.

sonarcloud[bot] commented 1 year ago

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication