在多媒体应用中,针对Client端的带宽情况,Server端对Video Data要进行不同的处理,当Client带宽比较差时,需要在Server端对不同的视频帧进行是丢弃处理,如在低带宽条件下,对于非关键帧,为了更好的用户体验性和播放的平滑性,可对其进行丢弃,而关键帧,则一般不给予丢弃。下面结合代码,详细分析下Red5是如何根据Client端的带宽进行丢包处理的。
Red5的Video Data丢包处理的代码集中在其PlayEngine 的 PushMessage方法,代码如下:
if (body instanceof VideoData) {
IVideoStreamCodec videoCodec = null;
if (msgIn instanceof IBroadcastScope) {
IBroadcastStream stream = (IBroadcastStream) ((IBroadcastScope) msgIn)
.getAttribute(IBroadcastScope.STREAM_ATTRIBUTE);
if (stream != null && stream.getCodecInfo() != null) {
videoCodec = stream.getCodecInfo().getVideoCodec();
}
}
//dont try to drop frames if video codec is null - related to SN-77
if (videoCodec != null && videoCodec.canDropFrames()) {
if (playlistSubscriberStream.state == State.PAUSED) {
// The subscriber paused the video
log.debug("Dropping packet because we are paused");
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
// Only check for frame dropping if the codec supports it
long pendingVideos = pendingVideoMessages();
if (!videoFrameDropper.canSendPacket(rtmpMessage, pendingVideos)) {
// Drop frame as it depends on other frames that were dropped before.
log.debug("Dropping packet because frame dropper says we cant send it");
return;
}
if (!receiveVideo) {
// The client disabled video or the app doesn't have enough bandwidth
// allowed for this stream.
log.debug("Dropping packet because we cant receive video or token acquire failed");
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
// increment the number of times we had pending video frames sequentially
if (pendingVideos > 1) {
numSequentialPendingVideoFrames++;
} else {
// reset number of sequential pending frames if 1 or 0 are pending.
numSequentialPendingVideoFrames = 0;
}
if (pendingVideos > maxPendingVideoFramesThreshold
|| numSequentialPendingVideoFrames > maxSequentialPendingVideoFrames) {
log.debug("Pending: {} Threshold: {} Sequential: {}", new Object[] { pendingVideos,
maxPendingVideoFramesThreshold, numSequentialPendingVideoFrames });
// We drop because the client has insufficient bandwidth.
long now = System.currentTimeMillis();
if (bufferCheckInterval > 0 && now >= nextCheckBufferUnderrun) {
// Notify client about frame dropping (keyframe)
sendInsufficientBandwidthStatus(currentItem);
nextCheckBufferUnderrun = now + bufferCheckInterval;
}
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
videoFrameDropper.sendPacket(rtmpMessage);
}
}
首先Red5根据Stream的Codec来决定是不是需要启用丢包处理。Red5共定义了三种Codec,分别为ScreenVideo,SorensonVideo和AVCVideo,其中ScreenVideo是用于屏幕截取,Red5的缺省实现是,不可以采取丢包处理,而SorensonVideo和AVCVideo分别用于手机和视频播放,Red5的缺省实现是可以采取丢包处理。如果我们需要在采用ScreenVideo的时候也启用丢包处理,则需要修改ScreenVideo的代码,如下所示:
/** {@inheritDoc} */
public boolean canDropFrames() {
return false;
}
在Red5的代码中,之所有在此处直接返回false,不支持丢包,主要是因为ScreenVideo这种Codec的Video data的Decode依赖于前后帧,如果丢弃了一帧,很可能接下来的好几帧数据都不能正确Decode。当然如果网络非常差的情况下,还是通过修改ScreenVideo的canDropFrames(),使其返回true,则可在低带宽条件下启动丢包处理,只不过这样在播放端就会出现连续的花屏现象。
在判断Codec是否支持Drop frames后,Red5主要根据Mina通道里的pendingVideos的数量来决定是否丢弃Video data。由上面的代码可以得知,pendingVideos 是通过方法pendingVideoMessages()获取的。pendingVideoMessages的返回的是RTMPConnection里面的pendingVideos的值(当往Mina的通道里写入一个),在Red5的代码中,如果pendingVideos超过最大允许的等待帧数,则启动丢包处理:
// increment the number of times we had pending video frames sequentially
if (pendingVideos > 1) {
numSequentialPendingVideoFrames++;
} else {
// reset number of sequential pending frames if 1 or 0 are pending.
numSequentialPendingVideoFrames = 0;
}
if (pendingVideos > maxPendingVideoFramesThreshold
|| numSequentialPendingVideoFrames > maxSequentialPendingVideoFrames) {
log.debug("Pending: {} Threshold: {} Sequential: {}", new Object[] { pendingVideos,
maxPendingVideoFramesThreshold, numSequentialPendingVideoFrames });
// We drop because the client has insufficient bandwidth.
long now = System.currentTimeMillis();
if (bufferCheckInterval > 0 && now >= nextCheckBufferUnderrun) {
// Notify client about frame dropping (keyframe)
sendInsufficientBandwidthStatus(currentItem);
nextCheckBufferUnderrun = now + bufferCheckInterval;
}
videoFrameDropper.dropPacket(rtmpMessage);
return;
}
这里之所以用pendingVideos和numSequentialPendingVideoFrames同时作为是否启用丢包的判断条件,主要是为了保证统计的实时性和准确性。
上面分析了Red5如何判断是否应该丢包,及采取什么样的丢包策略,因此在实际应用的时候可以根据具体的需求,对上述流程进行调节和改动,以适用于不同的应用场景。
分享到:
相关推荐
丢包处理技术的研究对于提高VoIP通信的稳定性和音质至关重要。 一、前言 VoIP丢包处理技术是现代通信技术领域的重要研究方向,其目的是减少丢包对语音通话质量的影响。随着互联网的广泛应用,VoIP技术在企业通信、...
同时,需要处理网络抖动、丢包等问题,确保视频通话的流畅性。 视频直播则更侧重于将单个源流分发给多个接收者。Red5服务器在此扮演关键角色,它接收来自Android客户端的视频流,并将其分发给多个订阅者。订阅者...
1. **拥塞避免算法**:虽然UDP本身没有内置的拥塞控制,但开发者可以自定义算法,例如使用随机早期检测(RED)或者尾丢弃(Tail-Drop)策略来减少拥塞导致的丢包。 2. **设置合适的发送速率**:根据网络状况动态调整...
- 总体而言,RED算法通过提前干预和动态调整丢包概率,能够在保持较高吞吐量的同时有效减少拥塞和丢包现象。 #### 五、结论 通过对队尾丢弃(Droptail)算法和随机早期检测(RED)算法在NS2仿真平台上的对比研究...
3. **概率丢包(Probabilistic Packet Dropping)**:当平均队列长度在Wmin和Wmax之间时,RED会以一定的概率丢弃新到达的数据包。这个概率随着平均队列长度接近Wmax而增加,使得在网络状态恶化前就能采取行动。 4. ...
本文主要探讨了一种丢包区分方法,称为WECN(Explicit Congestion Notification,显式拥塞通告),及其在Linux操作系统中的实现。传统TCP拥塞控制策略依赖于丢包作为网络拥塞的标志,但在无线/有线混合环境中,这种...
3. **网络优化**:在弱网络环境下,需要考虑丢包重传、延迟控制、码率自适应等策略,以保证直播的流畅性。 4. **性能优化**:利用硬件加速来减轻CPU负担,提高直播质量和稳定性。 5. **多码流适应**:根据用户设备...
此外,RED算法的丢包率降低了13%,这意味着网络的可靠性得到改善。 RED算法的这些优势使其成为路由器队列管理的一种理想选择,尤其是在高带宽和高流量的网络环境中。然而,实施RED算法也存在一定的挑战,如需要更...
这种策略在高负载情况下会导致突发性的丢包,进而触发TCP的拥塞窗口减小机制,从而降低网络拥塞。然而,Droptail的缺点是它对拥塞的响应较慢,可能会导致不必要的延迟和丢包。 相比之下,RED队列管理策略更为智能。...
实验结果表明,MRED算法在Web集群许可控制中的应用可以显著提高系统对突发流量的应对能力,减少数据包的延迟和丢包率,从而提升用户体验和系统的服务水平。 总之,MRED算法通过对传统RED算法的改进,结合Web集群的...
当网络的负载超过其处理能力时,数据包就会被丢弃,导致丢包率上升。 在上述基础上,DRED算法通过动态调节RED算法的参数,改进了网络的适应性和链路利用率。文章指出,DRED算法在模拟实验中表现出良好的性能,有效...
不同于尾丢弃算法,RED在队列长度达到一定阈值但未达到最大门限时就开始随机丢包,这样可以更早地向发送源发出拥塞警告,避免拥塞的加剧。此外,RED通过随机选择丢弃的数据包,减少了全局同步的风险,因为不同源端...
这是因为PID算法在处理快速变化的数据流量时可能会出现过调或欠调的现象,而RED-r算法通过其独特的丢包概率计算方式,能够在数据流量发生变化时提供更加平滑的响应。 #### NS2仿真结果 为了验证RED-r算法的有效性...
RED关注平均队列长度而非瞬间队列长度,避免在队列空闲时丢包,而在队列接近满载时加大丢包概率。 RED算法包含两部分: 1) 平均队列长度估计:采用指数加权滑动平均方法(2.1),通过权值w和当前队列长度q计算。...
- **网络接口指标**:如吞吐量、丢包率等。 - **块设备指标**:包括磁盘I/O速率和队列长度。 ### 2. 监控工具 #### 2.1 工具功能概述 本部分提供了多种监控工具的介绍和使用方法。 #### 2.2 uptime 显示系统运行...