跪拜 Guibai
← Back to the summary

Debugging a Smart Litter Box: How a 1.2s Live Stream Load Time Was Achieved

Android Smart Litter Box Video Loading Slow and Stuttering Problem Analysis

1. Reference Documents:

https://help.aliyun.com/zh/document_detail/148284.html?spm=a2c4g.11186623.help-menu-123207.d_5_0_8.6f42a749hxJxQ1&scm=20140722.H_148284._.OR_help-T_cn~zh-V_1

2. SDK Itself Stuttering Reasons:

2.1 Why the First Frame Time is Large

If the device responds normally to the forced I-frame command (taking office WiFi as an example), and the device's response to the forced I-frame takes less than 300ms, the first frame delay should generally be within 1.5 seconds.

First frame time = Time to request the playback address (300ms) + Time to connect to the playback address (150ms) + Time waiting for the device I-frame (300ms) + Player internal buffer delay (200ms) + Decoding and rendering time (10ms)

The main reasons for a large first frame delay are the following two situations.

2.2 Why Live Playback Stutters

The main reasons for playback stuttering and frame skipping are as follows.

Note

It is recommended that you use the bitstream self-check function provided by the device-side SDK for timestamp checking.

Live Playback Disconnection

The main reasons for the picture freezing for a period of time during playback and then reporting an error are as follows.

If the player fails to pull the stream for a continuous period or detects a network disconnection, it will throw an error to the upper layer, which is a normal phenomenon.

Note

For player-side stream pulling errors (1100), it is recommended that the App actively implement 1-2 retry attempts during implementation. If it still fails, present the retry option to the user.

Device-side settings need to be checked on the device

3. App Stuttering and Slow Loading Cause Analysis:

3.1 Not Setting a Fixed Number of Player Buffer Frames

/**
 * Set the fixed number of player buffer frames
 * @param frameCount Fixed number of player buffer frames, value range: 0 frames~50 frames. A larger value increases player delay but improves smoothness. Default is 5 frames.
 */
void setBufferedFrameCount(int frameCount);

3.2 Not Setting the Player's Anti-jitter Maximum Buffer Duration

 /**
   * Set the player's anti-jitter maximum buffer duration, default 1000ms, range 200-3000ms
   * @param jitterBufferSizeInMs
   */
  void setMaxJitterBufferSizeInMs(int jitterBufferSizeInMs);

3.3 Not Setting the Picture When Playback Stops

If this mode is not set, the next time you enter after playback stops, the screen will always be black by default. When the network is poor or loading fails, the last frame is displayed by default.

/**
 * Set the picture drawing strategy when playback stops
 * @param playerStoppedDrawingMode
 * ALWAYS_KEEP_LAST_FRAME          Always keep the last frame picture when playback stops
 * KEEP_LAST_FRAME_WITHOUT_ERROR   Keep the last frame picture only when no error occurs when playback stops (this is the default mode) 
 * ALWAYS_BLACK                    Always display black when playback stops
 */
void setPlayerStoppedDrawingMode(PlayerStoppedDrawingMode playerStoppedDrawingMode)

3.4 Incorrect Playback Failure Retry Mechanism:

image.png

3.5 Initialization and Close Interface Resource Recycling Strategy:

3.6 Modifying the Timing for Setting the Player Data Source:

4. Modifying the Loading Animation:

            @Override
            public void onPlayerStateChange(LVPlayerState state) {
                switch (state) {
                    case STATE_BUFFERING:
                        binding.loading.setVisibility(View.VISIBLE);
                        break;
                    case STATE_READY:
                    case STATE_IDLE:
                    case STATE_ENDED:
                        binding.loading.setVisibility(View.GONE);
                        break;
                }
            }

5. Optimized Time Statistics and Effects:

Currently tested 20 times, the average video loading time is 1.2s

1bffdb69edb495ca0422ab164f314215.png

There is always a picture when live streaming is paused, no black screen:

image.png

6. Summary

6.1. Device Hardware & Push Stream End Root Causes

  1. High First Frame Delay

    • The device does not respond promptly to the forced I-frame command, adding one GOP waiting time;

    • The device takes too long to connect to the push stream address.

    Calculation formula: First frame time = Time to get playback address + Time to connect address + Waiting for I-frame + Player buffer + Decoding and rendering time

  2. Unreasonable Buffer Configuration The SDK buffer is derived from the set bitrate. If the bitrate parameter is too small, the buffer capacity is insufficient, causing frequent packet loss and screen tearing/stuttering due to upstream bitstream overflow; also, the bitstream per frame cannot exceed 512KB.

  3. Insufficient Device Upstream Network Bandwidth The upstream bandwidth cannot support the current encoding bitrate, causing continuous packet loss.

  4. Encoding Parameters Do Not Meet SDK Constraints

    • H264 cannot carry B-frames; use Baseline / Main Profile;
    • Different resolutions and encoding formats have maximum bitrate limits. Exceeding the limit easily causes decoding stuttering;
    • H265 and high-resolution bitstreams have a high load, causing high decoding pressure and leading the player to actively drop frames.
  5. Abnormal Video Timestamps PTS/DTS

    • Frame interval timestamp is too large → Decoder backlog, buffer overflow, picture stuttering and slow playback
    • Frame interval timestamp is too small → Picture plays at double speed. You can call the SDK bitstream self-check function to verify timestamps.
  6. Device-side Push Stream Interruption Device network jitter disconnection or hardware/program exceptions directly terminate the video push stream, and the App's playback picture freezes and then throws an error.

6.2. Player Side (App-SDK Parameter Configuration Defects)

  1. The fixed number of player buffer frames setBufferedFrameCount was not manually limited. An unreasonable number of buffer frames cannot balance smoothness and delay; the default is 5 frames, range 0-50 frames.
  2. The anti-jitter buffer duration setMaxJitterBufferSizeInMs uses the default 1000ms without adjustment based on the network environment (adjustable range 200-3000ms), making it prone to stuttering under network fluctuations.
  3. The stop playback picture strategy was not configured, resulting in a black screen by default after an error; it is necessary to set ALWAYS_KEEP_LAST_FRAME to retain the last frame picture and avoid the black screen problem.

6.3. Player Lifecycle, Resource, and Initialization Issues

  1. Player resources were not properly reused and recycled. Creating a new instance without releasing the previous playback instance caused resource conflicts and high memory usage;
  2. A missing initialization flag variable caused the player to be initialized multiple times repeatedly;
  3. The timing for setting the playback data source was wrong: setting the DataSource too early disrupted the player preparation process and slowed down the first frame loading speed; the correct sequence is: configure buffer parameters → initialize the player → set the playback address last.

6.4. Abnormal Reconnection Retry Logic Defects

  1. The old solution cyclically initialized the player with a fixed 5-second delay after playback failure;
  2. Unlimited retries repeatedly created and destroyed the player, causing severe CPU resource consumption;
  3. Optimized solution: Limit to only 1-2 reconnection attempts, and if retries fail, hand over to the user for manual triggering.

6.5. UI Loading State Logic Error

The loading animation was always displayed persistently without being bound to the player state; optimization: only display the loading animation during the STATE_BUFFERING buffering phase, and hide the Loading in ready, idle, and playback ended states.

6.6. Final Optimization Results

  1. Standardized player initialization sequence, buffer parameters, jitter buffer, and stop-playback frame retention configuration;
  2. Managed the player instance lifecycle, prevented duplicate initialization, and ensured resource recycling;
  3. Limited the number of playback failure retries, eliminating infinite initialization;
  4. Bound the player state to control the Loading animation;
  5. On the device side, standardized I-frame pushing, bitstream upper limits, H264 encoding configuration, and PTS timestamps;
  6. Actual testing showed the average first frame loading time dropped to 1.2s over 20 tests. Pausing playback retains the last frame, no longer showing a black screen.
  7. If the network is very poor or there is no network, abnormal situations are unavoidable. Either add caching, but for scenarios with high real-time requirements like live push streaming, caching loses its meaning.