Transcoder Design
@jailuthra is already working on this.
Since Oct 30, 2020.
- Dominant language
- Go
- Stars
- 283
- Forks
- 72
- Avg merge
- 27m
- Merged PRs (30d)
- 1
Description
Two primary options when it comes to transcoder design.
**Single threaded, straight through:** each profile is encoded serially. Closely matches the current behavior of the transcoder. Note that FFmpeg currently doesn't go much over 100% CPU when transcoding; in many cases this actually leads the transcode job running slower than real-time. Broadcast latency suffers as a result.
This is the quickest to implement, but does not offer any parallelization potential. It also should not be any worse than what we have now.
**Split the processing into stages.**
1. Demuxing
2. Decoding
2. Rescaling (video) or Resampling (audio)
3. Encoding
4. Muxing
The benefits of splitting are twofold.
1. We can calculate the optimal code-path that a given profile should take. For example, if the input and output have the same codecs and resolution, we can simply transmux. If only the codec differs, we can skip rescaling. Different output formats that share the same encoding profile (eg, mpegts and mp4) can re-use the same encoded packets [1].
2. Allows for increased concurrency: each component can run independently, including having a thread for each rescaler, encoder and/or muxer.
There are three ways we can implement this splitting:
1. Entirely in C. Simplest approach architecturally, although it would likely require additional scaffolding to handle the bookkeping and interaction between each component (eg, a thread-safe queue).
2. Bind each stage individually to Cgo, with the bookkeeping done in go-land. We achieve concurrency via goroutines. This approach seems the neatest in principle, but there is concern about hitting GOMAXPROCS and creating contention with the scheduler. In general, 'long running' Cgo routines are supposed to be detached to avoid counting against GOMAXPROCS [2][3], but the granularity and frequency of our Cgo calls might work against us [4]. Note that each transcoding profile could have up to 5 Cgo entry points (rescaler, resampler, video-encoder, audio-encoder, muxer), so our current 3-profile output could have 17 Cgo entry points (demuxer, decoder, 3x5-profile). While we should still achieve some semblance of work interleaving, this approach might actually make things worse if it disrupts the scheduler too much.
3. Rust to manage the bookkeeping and concurrency. Since Rust can expose a C-compatible FFI, this can be bound with Cgo as well as a single entry point. Drawback is this adds a rather large component to the build system that might not be justified.
[1] Technically we'd have to run a bitstream filter to convert between MP4's Annex B format and a transport stream, but that's a much lighter operation than a re-encode.
[2] Working off the assumption that we shouldn't be overriding the user's GOMAXPROCS for them eg, by wrapping the `livepeer` go-binary in a shell script.
[3] https://github.com/golang/go/issues/8636#issuecomment-66098275
[4] Not to mention that transitioning the Go-Cgo boundary is slower, although not sure how much that would affect us in practice.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.