Skip to content
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

Buffer configuration for live streams #2438

Closed
petitTrung opened this issue Feb 10, 2017 · 3 comments
Closed

Buffer configuration for live streams #2438

petitTrung opened this issue Feb 10, 2017 · 3 comments
Labels

Comments

@petitTrung
Copy link

petitTrung commented Feb 10, 2017

Hello,

I've encountered an buffering issue with ExoPlayer 2 :

  • On my radio application, i would like to have a bigger buffer so that when the network is loss, i could continue listening for example 30s. Actually there some constants in the DefaultLoadControl class :
    /**
     * The default minimum duration of media that the player will attempt to ensure is buffered at all
     * times, in milliseconds.
     */
    public static final int DEFAULT_MIN_BUFFER_MS = 15000;

    /**
     * The default maximum duration of media that the player will attempt to buffer, in milliseconds.
     */
    public static final int DEFAULT_MAX_BUFFER_MS = 30000;

    /**
     * The default duration of media that must be buffered for playback to start or resume following a
     * user action such as a seek, in milliseconds.
     */
    public static final int DEFAULT_BUFFER_FOR_PLAYBACK_MS = 2500;

    /**
     * The default duration of media that must be buffered for playback to resume after a rebuffer,
     * in milliseconds. A rebuffer is defined to be caused by buffer depletion rather than a user
     * action.
     */
    public static final int DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = 5000;

Actually, i have 5s of buffers, I did increase these parameters by 3x, 4x, 5x, .... together or separately but i found no way to achieve the initial goal 30s. Could you explain in detail how we can control Buffering time, please ?

Thanks in advance

@WeiChungChang
Copy link
Contributor

WeiChungChang commented Feb 11, 2017

Dear @petitTrung:

I think the problem is similar to #2083; please refer to the logics below.

  private int getBufferTimeState(long bufferedDurationUs) {
    return bufferedDurationUs > maxBufferUs ? ABOVE_HIGH_WATERMARK
        : (bufferedDurationUs < minBufferUs ? BELOW_LOW_WATERMARK : BETWEEN_WATERMARKS);
  }
  @Override
  public boolean shouldContinueLoading(long bufferedDurationUs) {
    int bufferTimeState = getBufferTimeState(bufferedDurationUs);
    boolean targetBufferSizeReached = allocator.getTotalBytesAllocated() >= targetBufferSize;
    isBuffering = bufferTimeState == BELOW_LOW_WATERMARK
        || (bufferTimeState == BETWEEN_WATERMARKS && isBuffering && !targetBufferSizeReached);
    return isBuffering;
  }
  /**
   * A default size in bytes for an audio buffer.
   */
  public static final int DEFAULT_AUDIO_BUFFER_SIZE = 54 * DEFAULT_BUFFER_SEGMENT_SIZE;

There are four parameters within DefaultLoadControl; two of them control the load timing; the other twos control when the playback starts by having sufficient buffering. Please refer to the figure below.
The maxBufferUs & minBufferUs are about the load timing but bufferForPlaybackAfterRebufferUs & bufferForPlaybackUs are about when the playback starts by having sufficient buffering.

1

Refer to shouldContinueLoading(), a typical loading pattern includes 3 stages.
At the first stage we continuing loading until maxBufferUs is reached as below.
2

Since then isBuffering = false and bufferTimeState == BETWEEN_WATERMARKS; so shouldContinueLoading() returns false as below.
3

Finally, when bufferTimeState == BELOW_LOW_WATERMARK again we recover the download, as the figure below.
4

Per the flow described, you could see within the period of [t1, t3] actually we DO NOT load anymore. Therefore you may meet the condition, for example to have merely ~ 15 seconds buffering.

Beside, there is a limit upon buffering size.
From your description, your application is about radio. Hence it is limited by DEFAULT_AUDIO_BUFFER_SIZE = 54 * DEFAULT_BUFFER_SEGMENT_SIZE; (assume there is NO video).
So if the radio's bit-rate exceeds (54 * 64 / 30) = 115.2 KBps, you still will not be able to have 30 seconds maximum buffering.
In short, typically the buffering data will be from 15 to 30 second if your connection speed is good enough.

You have two choices to enlarge it.

  1. Enlarge both maxBufferUs & minBufferUs (instead of maxBufferUs only).
  2. Remove the limit by applying "drip-feeding" method.
    isBuffering = bufferTimeState == BELOW_LOW_WATERMARK
    || (bufferTimeState == BETWEEN_WATERMARKS /&& isBuffering/ && !targetBufferSizeReached);
    It is, once you are below maxBufferUs, do fetch immediately.

Finally, if it is a LIVE streaming. you are still limited by current available data at source.
For example, the source may own at most 20 seconds data so you could not buffer more than it.

@ojw28
Copy link
Contributor

ojw28 commented Feb 12, 2017

For radio or any other live stream, depending on the exact type of the stream, it might not be possible to build up a large buffer in a sensible way. For example if the stream/server only allows you to request the past 5s of the stream, then the only way a player could build up a 30s buffer would be for it to sit around buffering for 25s after opening the connection, prior to starting playback. That wouldn't be a good user experience. Note also that the larger the buffer, the further behind "live" the user will be.

I suspect in your case the stream/server is effectively controlling the buffer size to something around 5s, by only making that duration of past media available. In which case changes you make in the player probably wont have any effect.

@ojw28 ojw28 added the question label Feb 12, 2017
@ojw28 ojw28 changed the title [Buffer configuration] Buffer configuration for live streams Feb 12, 2017
@petitTrung
Copy link
Author

Thank both of you @WeiChungChang & @ojw28 for your help !

@ojw28 ojw28 closed this as completed Feb 15, 2017
@google google locked and limited conversation to collaborators Jun 28, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants