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:
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.
- When the device does not respond normally to the forced I-frame command, it adds a delay equal to the length of one GOP. In this case, you need to make the device respond normally to the forced I-frame command.
- The device side takes a long time to connect to the push stream address. In this case, please contact us via the Ticket system in the upper right corner of the console.
2.2 Why Live Playback Stutters
The main reasons for playback stuttering and frame skipping are as follows.
Device SDK buffer is set too small
The Link Visual device-side SDK provides an interface for setting the bitrate. The SDK internally calculates and sets the buffer size based on the passed bitrate. If the bitrate is set too small, it will cause the device-side SDK buffer to frequently trigger packet loss, thus affecting the picture quality. In this case, it is recommended that you reset the SDK buffer to a suitable size.
Note
Link Visual currently does not support the transmission of bitstreams with a frame size exceeding 512KB.
Poor device network
If the upstream bandwidth of the device's network is insufficient to support the set bitrate transmission, it will cause frequent packet loss in the device-side SDK buffer, thus affecting the picture quality. It is recommended that you adjust the device's location or check the device's network status.
Poor player-side network
The downstream network bandwidth of the player side must be at least greater than the current bitrate. The player provides an interface to get the bitrate, which can be used to display the current actual bitrate information. Please check if the player-side network bandwidth meets the requirements, and it is recommended that you display the current bitrate (suggested bitrate display format: 24fps 80KB/s) to facilitate future problem location.
Bitstream issues
Link Visual does not support B-frames. For H264, it is recommended to use Baseline/Main Profile.
The maximum bitrate and resolution comparison table is as follows.
Encoding Format Resolution Maximum Bitrate H264 1080P <2Mbps 720P <1Mbps D1 <0.5Mbps H265 1080P <1.5Mbps 720P <0.75Mbps D1 <0.5Mbps High decoding time consumption
When complex encoding or oversized frames cause high decoding time consumption, it leads the player to actively drop frames, resulting in a stuttering picture. In this case, it is recommended that you reduce the device's encoding complexity and bitstream size.
Abnormal device timestamps
The PTS/DTS difference between two consecutive frames should be consistent with the actual timestamp difference when the encoder generates the frames.
- If the difference between two Link Visual timestamps is larger than the actual difference, it will cause the player-side decoder to delay decoding, potentially triggering a player buffer overflow and frame dropping, causing slow playback and picture stuttering.
- If the difference between two Link Visual timestamps is smaller than the actual difference, it will cause the player-side decoder to decode prematurely, causing fast playback.
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.
Device push stream anomaly
The device's push stream suddenly interrupts due to network disconnection or program bugs. If it is not caused by the network, it is necessary to analyze the device-side logs to eliminate bugs.
Poor player-side network
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:
- On Android, playback failure re-initializes after a 5-second delay. If the network is poor, it will keep initializing.
- Repeated re-initialization consumes resources. The player needs to be closed and recycled promptly.
- The SDK documentation recommends adding 2 reconnection attempts, not continuous initialization.
3.5 Initialization and Close Interface Resource Recycling Strategy:
- Set the fixed number of player buffer frames during initialization.
- Set the player's anti-jitter maximum buffer duration.
- Recycle previous resources before creating the player.
- Recycle resources when closing the interface.
- Add an initialization flag variable to prevent duplicate initialization.
3.6 Modifying the Timing for Setting the Player Data Source:
- Set the data source after the previous preparation work is completed.
- Do not set the data source at the very beginning.
4. Modifying the Loading Animation:
- Only display the loading animation when buffering.
- Hide the animation in other states.
- Do not keep loading continuously due to player state issues.
@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
There is always a picture when live streaming is paused, no black screen:
6. Summary
6.1. Device Hardware & Push Stream End Root Causes
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
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.
Insufficient Device Upstream Network Bandwidth The upstream bandwidth cannot support the current encoding bitrate, causing continuous packet loss.
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.
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.
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)
- The fixed number of player buffer frames
setBufferedFrameCountwas not manually limited. An unreasonable number of buffer frames cannot balance smoothness and delay; the default is 5 frames, range 0-50 frames. - The anti-jitter buffer duration
setMaxJitterBufferSizeInMsuses the default 1000ms without adjustment based on the network environment (adjustable range 200-3000ms), making it prone to stuttering under network fluctuations. - 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_FRAMEto retain the last frame picture and avoid the black screen problem.
6.3. Player Lifecycle, Resource, and Initialization Issues
- 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;
- A missing initialization flag variable caused the player to be initialized multiple times repeatedly;
- 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
- The old solution cyclically initialized the player with a fixed 5-second delay after playback failure;
- Unlimited retries repeatedly created and destroyed the player, causing severe CPU resource consumption;
- 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
- Standardized player initialization sequence, buffer parameters, jitter buffer, and stop-playback frame retention configuration;
- Managed the player instance lifecycle, prevented duplicate initialization, and ensured resource recycling;
- Limited the number of playback failure retries, eliminating infinite initialization;
- Bound the player state to control the Loading animation;
- On the device side, standardized I-frame pushing, bitstream upper limits, H264 encoding configuration, and PTS timestamps;
- 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.
- 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.