最近用rtsp 傳視頻vlc 播放總是出現閃屏,一段時間就卡灰屏一下 ,因爲視頻幀不是直接從機器獲取,通過網絡傳輸過來,幀率不是很穩定,調試後發現幀率一直爲25幀,機器實際只有20幀左右。查找原因是因爲H264or5VideoStreamParser::parse() 中解析SPS 的時候沒有解析出num_units_in_tick和time_scale 所以只能設置默認值或者根據幀的類型計算 nal_unit_type =0x1 爲普通幀,nal_unit_type=0x7 爲SPS這樣可以實時計算出幀率。
所以在 H264or5VideoStreamParser::parse() 中添加 CALCULATE_FPS 區代碼計算幀率。
if (fHNumber == 264) {
nal_unit_type = fFirstByteOfNALUnit&0x1F;
#ifdef DEBUG
u_int8_t nal_ref_idc = (fFirstByteOfNALUnit&0x60)>>5;
fprintf(stderr, "Parsed %d-byte NAL-unit (nal_ref_idc: %d, nal_unit_type: %d (\"%s\"))\n",
curFrameSize()-fOutputStartCodeSize, nal_ref_idc, nal_unit_type, nal_unit_type_description_h264[nal_unit_type]);
#endif
} else { // 265
nal_unit_type = (fFirstByteOfNALUnit&0x7E)>>1;
#ifdef DEBUG
fprintf(stderr, "Parsed %d-byte NAL-unit (nal_unit_type: %d (\"%s\"))\n",
curFrameSize()-fOutputStartCodeSize, nal_unit_type, nal_unit_type_description_h265[nal_unit_type]);
#endif
}
// usingSource()->fFrameRate = fParsedFrameRate = 20.0;
#ifdef CALCULATE_FPS
if(nal_unit_type == 0x1 && m_frameSum < 256) m_frameSum++;
#endif
// printf("%sfParsedFrameRate =%f nalType = 0x%x m_frameSum =%d\n",__func__,fParsedFrameRate,nal_unit_type,m_frameSum);
// Now that we have found (& copied) a NAL unit, process it if it's of special interest to us:
if (isVPS(nal_unit_type)) { // Video parameter set
// First, save a copy of this NAL unit, in case the downstream object wants to see it:
usingSource()->saveCopyOfVPS(fStartOfFrame + fOutputStartCodeSize, curFrameSize() - fOutputStartCodeSize);
if (fParsedFrameRate == 0.0) {
// We haven't yet parsed a frame rate from the stream.
// So parse this NAL unit to check whether frame rate information is present:
unsigned num_units_in_tick, time_scale;
analyze_video_parameter_set_data(num_units_in_tick, time_scale);
if (time_scale > 0 && num_units_in_tick > 0) {
usingSource()->fFrameRate = fParsedFrameRate = time_scale/(DeltaTfiDivisor*num_units_in_tick);
// printf("Set frame rate to %f fps fParsedFrameRate =%f time_scale =%d Delta=f\n",usingSource()->fFrameRate,fParsedFrameRate ,time_scale,(DeltaTfiDivisor*num_units_in_tick));
#ifdef DEBUG
fprintf(stderr, "Set frame rate to %f fps\n", usingSource()->fFrameRate);
#endif
} else {
#ifdef DEBUG
fprintf(stderr, "\tThis \"Video Parameter Set\" NAL unit contained no frame rate information, so we use a default frame rate of %f fps\n", usingSource()->fFrameRate);
#endif
}
}
} else if (isSPS(nal_unit_type)) { // Sequence parameter set
// First, save a copy of this NAL unit, in case the downstream object wants to see it:
usingSource()->saveCopyOfSPS(fStartOfFrame + fOutputStartCodeSize, curFrameSize() - fOutputStartCodeSize);
// xu add for analyze_seq_parameter_set_data() can't get num_units_in_tick & time_scale
#ifdef CALCULATE_FPS
m_frameSum ++;
struct timeval tmpTs;
gettimeofday(&tmpTs, NULL);
double curTs= (((double)tmpTs.tv_sec*1000 +(double)tmpTs.tv_usec/1000)/1000);
double durTs = curTs - m_lastGopTs;
if(durTs > 0 && durTs <3.0)
{
usingSource()->fFrameRate = fParsedFrameRate = m_frameSum/durTs;
// printf("Set frame rate to %f fps,durTs =%f sum=%d lastTs =%f curTs=%fs\n" ,((double)m_frameSum/durTs),durTs,(int)m_frameSum ,m_lastGopTs,curTs);
}
m_lastGopTs = curTs;
m_frameSum = 0;
#endif
if (fParsedFrameRate == 0.0) {
// We haven't yet parsed a frame rate from the stream.
// So parse this NAL unit to check whether frame rate information is present:
unsigned num_units_in_tick, time_scale;
analyze_seq_parameter_set_data(num_units_in_tick, time_scale);
參考:https://blog.csdn.net/caoshangpa/article/details/53083410?utm_source=blogxgwz0