直播问题分析总结 -- 跳帧
2017-05-15 本文已影响98人
FlyingPenguin
跳帧策略
跳帧策略是指在播放累积延迟逐渐增大时采取的 " 丢弃非实时数据 " 的策略。
跳帧目的
为了保证实时性。
跳帧的原因分析
跳帧的原因汇总非实时数据来不及处理
由于流媒体服务器本身的处理能力的问题,累计的非实时数据超过一定阈值(比如50帧),此时流媒体服务器可能会采取直接丢弃非实时帧序列的策略,然后直接处理实时帧,此时在客户端看来就会出现跳帧的现象。
除了直播,如果录制的文件存在跳帧的现象(一般只会在大批量录制的时候出现),非常可能是服务器的硬盘读写功能跟不上,来不及写数据就被丢弃了,此时应更换性能更好的硬盘。
CPU占用过高
CPU占用过高,处理能力有限,导致收到的数据被丢弃,继而处理最新的数据,从而出现跳帧现象。
播放器缓冲过小
播放器的缓存时间过小,比如为0或着0.1,也会导致跳帧出现。
增加缓存时间可有效避免跳帧,但会影响实时性。
某次跳帧现象的分析和解决
现象描述
Windows 7下MFC开发的终端软件(下文中简称终端),在内嵌浏览器(Microsoft Web Browser控件)中打开网页。
网页中通过Flash Player播放rtmp流,存在严重的跳帧的现象。
基本上是,正常23秒,然后跳23秒,很是诡异。
处理步骤:
- Step 1: 用IE直接网页直播
关闭终端,直接在IE中打开网页查看直播,发现不存在跳帧现象,所以基本断定应该是终端本身处理的问题。 - Step 2: 排除网络原因。
分别通过以下ping的方式,
ping 192.168.2.222 -t -l 4096
简单分析了,视频源到流媒体服务器,还有流媒体服务器到终端的网络情况,发现时间基本上都在1~2ms左右,说明网络情况良好。
- Step 3: 分析流本身的问题。
获取到rtmp流的实际地址,通过工具将rtmp流直接录制能flv文件,将文件播放后发现,视频连续,也不存在跳帧的现象。说明流数据本身是好的。 - Step 4: 分析终端的逻辑。
查看终端的任务浏览器时,发现了一个令人怀疑的现象,CPU的使用率本身并不高,一般在20%~50%左右,但CPU的频率过高,一直在100%以上。
CPU的频率过高
这时候,怀疑可能是终端程序中,对CPU的处理导致的。
忽然想起前一阵,在程序中加入了CPU的处理流程,每隔5秒中,获取当前程序占用CPU和系统占用的CPU,返回给服务器。
代码如下:
#include <stdio.h>
#include <Windows.h>
typedef long long int64_t;
typedef unsigned long long uint64_t;
/// 时间转换
static uint64_t file_time_2_utc(const FILETIME* ftime)
{
LARGE_INTEGER li;
li.LowPart = ftime->dwLowDateTime;
li.HighPart = ftime->dwHighDateTime;
return li.QuadPart;
}
/// 获得CPU的核数
static int get_processor_number()
{
SYSTEM_INFO info;
GetSystemInfo(&info);
return (int)info.dwNumberOfProcessors;
}
/// 获取指定进程占用的CPU
int get_cpu_usage(int pid)
{
/// cpu数量
static int processor_count_ = -1;
// 上一次的时间
static uint64_t last_time_ = 0;
static uint64_t last_system_time_ = 0;
FILETIME now;
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
uint64_t system_time;
uint64_t time;
uint64_t system_time_delta;
uint64_t time_delta;
int cpu = -1;
if(processor_count_ == -1)
{
processor_count_ = get_processor_number();
}
GetSystemTimeAsFileTime(&now);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
{
return 0;
}
system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time))
/ processor_count_;
time = file_time_2_utc(&now);
if ((last_system_time_ == 0) || (last_time_ == 0))
{
last_system_time_ = system_time;
last_time_ = time;
return 0;
}
system_time_delta = system_time - last_system_time_;
time_delta = time - last_time_;
if (time_delta == 0)
{
return 0;
}
cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);
last_system_time_ = system_time;
last_time_ = time;
return cpu;
}
/// 获取系统占用的CPU
int get_sys_cpu_usage()
{
/// cpu数量
static int processor_count_ = -1;
/// 上一次的时间
static int64_t last_time_ = 0;
static int64_t last_system_time_ = 0;
FILETIME now;
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
int64_t system_time;
int64_t time;
int64_t system_time_delta;
int64_t time_delta;
int cpu = -1;
if(processor_count_ == -1)
{
processor_count_ = get_processor_number();
}
GetSystemTimeAsFileTime(&now);
if (!GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
&kernel_time, &user_time))
{
// We don't assert here because in some cases (such as in the Task Manager)
// we may call this function on a process that has just exited but we have
// not yet received the notification.
return -1;
}
system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time))
/ processor_count_;
time = file_time_2_utc(&now);
if ((last_system_time_ == 0) || (last_time_ == 0))
{
// First call, just set the last values.
last_system_time_ = system_time;
last_time_ = time;
return -1;
}
system_time_delta = system_time - last_system_time_;
time_delta = time - last_time_;
if (time_delta == 0)
{
return -1;
}
// We add time_delta / 2 so the result is rounded.
cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta);
last_system_time_ = system_time;
last_time_ = time;
return cpu;
}
分析发现,禁用CPU操作相关的函数后,跳帧的现象消失。
References:
https://alwaysmavs.gitbooks.io/plplayerkit/content/4%20%E7%9B%B4%E6%92%AD%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/4.1%20%E8%B7%B3%E5%B8%A7%E7%AD%96%E7%95%A5.html
http://www.jianshu.com/p/ecf51ee32589