最近有个天猫魔盒(Tmall,MagicBox_M17,MagicBox_M17)有报错,报错信息如下:
generic_decoder.cc, (line 98): Too many frames backed up in the decoder, dropping frame with timestamp 4219980314
https://chromium.googlesource.com/external/webrtc/+/lkgr/modules/video_coding/generic_decoder.cc#115
{
MutexLock lock(&lock_);
int initial_timestamp_map_size = _timestampMap.Size();
frameInfo = _timestampMap.Pop(decodedImage.timestamp());
timestamp_map_size = _timestampMap.Size();
// _timestampMap.Pop() erases all frame upto the specified timestamp and
// return the frame info for this timestamp if it exists. Thus, the
// difference in the _timestampMap size before and after Pop() will show
// internally dropped frames.
dropped_frames =initial_timestamp_map_size - timestamp_map_size - (frameInfo ? 1 : 0);
}
https://chromium.googlesource.com/external/webrtc/+/lkgr/modules/video_coding/timestamp_map.cc#38
absl::optional<VCMFrameInformation> VCMTimestampMap::Pop(uint32_t timestamp) {while (!IsEmpty()) {if (ring_buffer_[next_pop_idx_].timestamp == timestamp) {// Found start time for this timestamp.const VCMFrameInformation& data = ring_buffer_[next_pop_idx_].data;ring_buffer_[next_pop_idx_].timestamp = 0;next_pop_idx_ = (next_pop_idx_ + 1) % capacity_;return data;} else if (IsNewerTimestamp(ring_buffer_[next_pop_idx_].timestamp,timestamp)) {// The timestamp we are looking for is not in the list.return absl::nullopt;}// Not in this position, check next (and forget this position).next_pop_idx_ = (next_pop_idx_ + 1) % capacity_;}// Could not find matching timestamp in list.return absl::nullopt;
}
看了一下前后逻辑,进出 _timestampMap
都在 generic_decoder.cc
中处理。
timestamp_map
中是一个环状数据,容量为10。
所以触发上面的报错有几个可能点:
- 解码时间太久了,新数据超过10帧。即30帧视频,超过300ms,60帧视频超过150ms。
- 期间有脏数据,导致
timestamp_map
数据在上一轮查找中被置清空。 - 解码过程中有报错,导致
timestamp_map
被清空了。
模拟这几个条件,自测只有可能第一点能正常触发日志报错。
所以这个问题的解决就变成:
- 降低视频大小、分辨率、修改编码类型实现、降低帧率,可以减少问题的产生。
- 去掉上面那一处的判断,即接受存在150ms-300ms的延迟。