-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support renderer mode that only renders the first frame (for trick play) #8592
Comments
It is indeed the case that Side note: some information in #6794 (comment) may be interesting, if only to confirm your current solution is reasonable. |
I think it's more likely that the delay is just a result of decoding up to the exact frame corresponding to the requested seek position. You might be able to speed things up by calling To what extent this works may depend on the streaming standard and container format being used. In particular, my suggestion is unlikely to make any difference if you're using HLS (due to #2882 still being open). It should make things better for DASH and most modern progressive container formats (e.g., MP4, MKV). Ideally the player would have a trick-play mode that would internally do all of the steps required to get the player into a suitable state. Probably including switching the video renderer into a mode where it immediately renders any key-frame it receives. This is tracked by #7171. |
Note that you can easily disambiguate between the potential issues @andrewlewis and I are suggesting by adding debugging to If you're not seeing any calls to this method until multiple frames have been queued, then that indicates the issue described by @andrewlewis where the codec needs multiple frames before it provides any output. Conversely, if you're seeing calls to this method with |
@andrewlewis @ojw28 thanks a lot for fast answer! Anyway, thanks for your help. I will investigate further options for customizing the video renderer. |
Regarding the additional debugging you did: I don't think it's as simple as counting the number of frames queued before you see the first frame being dequeued. This is because the
Note that this is a frame that's being discarded rather than rendered, probably because its timestamp is earlier than the seek position. If you don't care about accuracy during trick-play, which seems likely, then finding a way to render this frame as the first frame would speed things up. You can experiment with this just by flipping |
I have checked this by limiting the amount of data downloaded by overriding DefaultLoadControl.shouldContinueLoading. If I stop downloading after sending three frames to the decoder, I see no calls of MediaCodecVideoRenderer.processOutputBuffer at all with infinite wait.
I have checked it. It really decreases delay between seeks from ~500ms to ~300ms. So, I will override MediaCodecVideoRenderer.processOutputBuffer and set isDecodeOnlyBuffer to false for trick case. Thanks! |
@davydovvladimir It's on the input side that decode only is set, So I"m taking the tack of fixing this in the HLS input side (implement frame accurate seek, at least for I-Frame tracks). As for the decoder, I've observed exactly what you describe on AmLogic and BRCM platform, so it may be a MediaCodec thing not a platform thing. There is no reason we cannot get < 100ms first frame with reasonable iFrame fetch times. PS, I'm the author of the i-Frame only support ;-) |
The HLS implementation of `getAdjustedSeekPositionUs()` now completely supports `SeekParameters.CLOSEST_SYNC` and it's brotheran, assuming the HLS stream indicates segments all start with an IDR (that is EXT-X-INDEPENDENT-SEGMENTS is specified). This fixes issue google#2882 and improves (but does not completely solve google#8592
The HLS implementation of `getAdjustedSeekPositionUs()` now completely supports `SeekParameters.CLOSEST_SYNC` and it's brotheran, assuming the HLS stream indicates segments all start with an IDR (that is EXT-X-INDEPENDENT-SEGMENTS is specified). This fixes issue google#2882 and improves (but does not completely solve google#8592
An update... I have been able to get single frames rendered pretty quickly in pause mode. Here's example logging:
Most of the 320ms is the load time on the rather large iFrame segments. The logs above are with code that has:
With the second change it is possible to inject other NALU's after the I-Frame segments IDR to experiment with for various codecs. @andrewlewis any other ideas besides sending end of stream NALU? |
Hi @stevemayhew
what a change do you mean? |
I’m still working out if that is necessary, but if so ultimately we’ll need
a mode where the track is in trickplay then add that flag based on the
Format (role).
Some origin servers (including sadly Apple’s mediafilesegmentor) add
garbage NALUs after the IDR (type 5). These trailing P/B slice NALU can
freeze you on a frame that looks, well not as good as the reference frame
(IDR)
…On Wed, Nov 3, 2021 at 12:46 AM davydovvladimir ***@***.***> wrote:
Hi @stevemayhew <https://github.com/stevemayhew>
thank you for the update
1. lastly a change that sets MediaCodec.BUFFER_FLAG_KEY_FRAME on the
MediaCodec.queueInputBuffer() flags argument.
what a change do you mean?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#8592 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADBF6AE2UY5J7R5TSJFWM3UKDSEXANCNFSM4XWIEB6Q>
.
|
I'm not sure that it is same issue. But I see some strange behavior in my implementation of trick mode by using seek on pause. Let me remind details of my implementation:
|
@davydovvladimir What are you using to generate the i-Frame only tracks? If you can make a small VOD example, zip and send it I can have a look. You can use ffmpeg to show the NALU structure in the i-Frame. Use:
|
@davydovvladimir I've been testing this extensively on AmLogic based SOC's (this includes Google's own Chrome Cast / Goggle TV and TiVoStream) and it works perfectly (frames queued to the decoder I have reproduced the delay with boxes that have Broadcom SOCs in them (Arris, others). With these boxes it takes 2-3 frames queued before one is emitted. |
The HLS implementation of `getAdjustedSeekPositionUs()` now completely supports `SeekParameters.CLOSEST_SYNC` and it's brotheran, assuming the HLS stream indicates segments all start with an IDR (that is EXT-X-INDEPENDENT-SEGMENTS is specified). This fixes issue google#2882 and improves (but does not completely solve google#8592
Just to clarify what this issue is actually tracking: My understanding is that this issue is about a special mode that can be configured on the video renderer that only renders the first keyframe, following by an end-of-stream signal to ensure the codec doesn't get stuck. This mode is useful during trick-play/scrubbing-with-keyframes-only because it avoids queuing additional frames on the decoder we don't actually need. The main downside is that we can't just continue playback after this point as we have to decode the same frame again even if we want to continue from the current position. @stevemayhew I'm aware this is quite an old issue by now, but does that match your understanding? And did the initial attempts you were referring to above show that this helps the get the first frame faster? In theory, if the codec just outputs the first keyframe as soon as it's ready, this change wouldn't even make a difference I guess (besides the unnecessary decoding work). |
@tonihei I think so, sorry I've been busy with Widevine / MultiDRM issues so I've been neglecting the work to finish off "trick-play". The AmLogic codecs do this well (that includes Chromecast with Google TV) but the BRCM SoC's do not, most force using tunneling mode to even work at higher frame rates. I don't think we are going to get fixes to these codecs and tracking it as an ExoPlayer issue makes even less sense, so I'd close this as not supported for BRCM. What is remaining on my plate is to make this all work is (in priority order):
If you can assign an RFE to me in Media3 repo I can start carving out time to work on it, also give us a good place to debate the design ;-) |
Continue on the existing PRs (in media3) sounds like a good idea to get them merged. The 3rd bullet (prefer seeks in sample queue vs reloading) also sounds useful as a PR. The more general trick-play support (point 2) is less straight-forward as it needs more design discussions how the overall integration looks like. So it might be better to wait until we have a full design in place (which we may be able to share externally to accept PRs). And I re-word this issue here to track the specific feature request for the single-frame mode. |
Thanks, I’d love to see your design…
We already have a working implementation, it required overriding the track
selector and renderer. So it would be much better to open and RFE bug and
share details there rather than working independently in conflicting
directions
…On Thu, Feb 8, 2024 at 2:05 AM tonihei ***@***.***> wrote:
Continue on the existing PRs (in media3) sounds like a good idea to get
them merged. The 3rd bullet (prefer seeks in sample queue vs reloading)
also sounds useful as a PR.
The more general trick-play support (point 2) is less straight-forward as
it needs more design discussions how the overall integration looks like. So
it might be better to wait until we have a full design in place (which we
may be able to share externally to accept PRs).
And I re-word this issue here to track the specific feature request for
the single-frame mode.
—
Reply to this email directly, view it on GitHub
<#8592 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADBF6CE543KC3PQVX6FVGDYSSPPDAVCNFSM4XWIEB62U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOJTGM3TIMJXG43Q>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Oh, yes, please feel free to share what you have! That's actually quite useful and a good start for a conversation. I was just saying it's much harder to merge pull requests for a larger feature without knowing the bigger picture first (compared to these other changes that all have a clear benefit in isolation). But just to note, we are not very likely to look into this in detail until later this year. |
Hello dear developers!
First, let me explain what I'm doing.
I'm trying to implement reverse trick mode by using I-Frames provided by #EXT-X-I-FRAME-STREAM-INF track.
The current algorithm is as follows:
This algorithm is working for me but has some disadvantages.
The main problem is the time between seek() operation and onRenderedFirstFrame event.
It takes about 500ms and looks pretty big.
I have debuged the code and found that first frame is rendered only after 4-5 I-Frames pushed to the decoder.
I found it by additional trace before
ExoPlayer/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
Line 1349 in 4b1e0fa
I've tried to control buffering by overriding DefaultLoadControl.shouldContinueLoading() and I see if I load only 2 or 3 I-Frame chunks after seek(), then the onRenderedFirstFrame event does not come at all.
In theory, sending one i-frame to the decoder is enough to receive onRenderedFirstFrame.
But maybe MediaCodec or Renderer has some internal buffering and requires mulptiple frames to display the first.
Could you tell me why this is happening and how to avoid it?
Thanks.
The text was updated successfully, but these errors were encountered: