Add a low latency decoder option and actually apply the MediaCodec keys - #113
Add a low latency decoder option and actually apply the MediaCodec keys#113iflyhere wants to merge 1 commit into
Conversation
writeAndroidPerformanceParams() was never called: both call sites in AndroidMediaFormatHelper.h were commented out, and the same keys sat commented out a second time in VideoDecoder::configureStartDecoder(). So every decoder was configured without "low-latency" and without "priority", i.e. MediaCodec kept its default reorder/output queue, which on a live stream with no B-frames only adds latency. The keys are now written, but behind a switch so a device whose decoder does not like them can be put back on the stock pipeline: - Settings -> Video -> Low latency, persisted as "low_latency_decoder", default on - plumbed through VideoPlayer.setLowLatency() / nativeSetLowLatency() to VideoDecoder, applied when the decoder is configured - writeAndroidPerformanceParams() also gained the vendor low-latency keys that were commented out in VideoDecoder.cpp (Qualcomm, HiSilicon, rtc-ext) and is now static like the two functions next to it Unknown AMediaFormat keys are ignored by MediaCodec, so writing all variants is safe across vendors and Android versions.
PR Summary by QodoApply MediaCodec low-latency keys behind a user setting
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record |
Note
Compile tested only (arm64-v8a + armeabi-v7a). Not yet flown. A glass-to-glass
comparison with the switch on/off on real hardware would be very welcome,
especially on non-Qualcomm SoCs.
The problem
writeAndroidPerformanceParams()inapp/videonative/src/main/cpp/helper/AndroidMediaFormatHelper.hsets the two decoder keys that matter for a live stream:
It is never called. Both call sites are commented out:
h264_configureAMediaFormat()—// writeAndroidPerformanceParams(format);h265_configureAMediaFormat()—// writeAndroidPerformanceParams(format);and the same keys sit commented out a second time in
VideoDecoder::configureStartDecoder(), including the vendor variants:So every decoder is configured with the stock MediaCodec pipeline. Without
KEY_LOW_LATENCYthe codec may hold output frames back for reordering, whichfor a majestic stream (no B-frames, low slice count) buys nothing and only
costs frames of latency. Without
priority = 0the codec runs as best effortinstead of realtime, so it competes with everything else on the device.
The change
The keys are written now, but behind a switch. "Change how the decoder
behaves" is exactly the kind of thing that should be escapable on a device
whose vendor codec does not like it, so:
Settings → Video → Low latency, persisted as
low_latency_decoder,default on.
Plumbing:
VideoPlayer.setLowLatency(boolean)→nativeSetLowLatency()→VideoDecoder::setLowLatency()VideoDecoder::configureStartDecoder()callswriteAndroidPerformanceParams()only when the flag is setVideoActivitypushes the persisted value down as soon as the player exists,so the setting survives a restart
Because the decoder is created lazily once SPS/PPS arrive, toggling the switch
takes effect the next time the decoder is configured (next video start /
channel change), not on a decoder that is already running. The menu says so.
writeAndroidPerformanceParams()also picked up the vendor keys that werecommented out in
VideoDecoder.cpp(Qualcomm, HiSilicon, rtc-ext) and is nowstatic, like the two functions next to it. UnknownAMediaFormatkeys areignored by MediaCodec, so writing all variants is safe across vendors and
Android versions.
Not in this PR
VideoDecoder::feedDecoder()blocks the receive thread for up toBUFFER_TIMEOUT_US(17 ms) per NALU and retries for up to a second, andBufferedPacketQueuehas no time bound on how long it holds a reorder buffer.Both also cost latency but need their own discussion.
Part of a small series of independent fixes found while profiling the receive path.
Each one is standalone and mergeable on its own, in any order — no dependencies
between them, and no shared files except
VideoActivity.java/VideoPlayer.*,which touch different methods:
All five compile clean for arm64-v8a + armeabi-v7a.