map的一个注意点

今天在调试程序,发现跑一会儿就会有问题(图像花屏),但是把保存下来的纯视频用暴风播就很正常。

后来在程序中加断点,发现每当花屏的时候,发现对应帧的长度不对,而且帧标志会有一次重复。经过流程的分析,确定是帧信息分析的代码问题。


由于音视频数据往往有着巨大的数据需要分析,所以在帧分析的位置添加打印,而不是单纯的断点。经过一个下午的跟踪,终于问题解决,原因就是map的一个特点之前没有碰到过,所以在这样大量项存在的情况下问题爆发了。


原始的代码逻辑如下:

map<UINT16, FrameInfo> m_mapFrame;   // 这是一个类中的全局变量

void GotAVData( char *buf, int len )
{
   put_data_to_map( buf, len, m_mapFrame );  //通过对buf的分析,拆分成一帧一帧后放入到m_mapFrame中
   FrameInfo fi;
   map<UINT16, FrameInfo>::iterator iter;
   iter = m_mapFrame.begin();
   while ( iter != m_mapFrame.end() )
   {
      fi = iter->second;
      put_frame_to_decoder(fi);
      iter = m_mapFrame.erase(iter);
   }
}

FrameInfo结构中有一个帧ID字段:UINT16 fid,其值的范围为:0~65535,m_mapFrame的key也就是这个fid。当值达到65535后,再返回到0开始。

以上代码是每次收到服务器发送过来的视频数据时就会调用。在put_data_to_map()中,每获取到一帧数据后,加入map的动作如下:

FrameInfo fi;
... // 分析数据并对fi附值
m_mapFrame[fi.fid] = fi;

显然,在put_data_to_map()中,最后来的数据,应该是最后才加入到了m_mapFrame中,在GotAVData()中用m_mapFrame.begin()获取它最早加入的项,但是结果不对。

比如一次性先后加入了如下的帧ID到m_mapFrame中:

65533,65534,65535,0,1,2,3,4,5,6,7

则在GotAVData()中的iter = m_mapFrame.begin();一行,得到的结果iter却是fid为0的帧,即不是第一个加入的65533!

这个情况导致我的判断不正常,从而导致拿到的帧数据是不正常的,最终导致解码出来的图像花掉。


后做如下修改解决问题,总体思路是记录当前取到的一个帧ID,然后固定地取对应帧ID的项,主要是对GotAVData()中的m_mapFrame操作进行了修改,大到如下:

void GotAVData( char *buf, int len )
{
   put_data_to_map( buf, len, m_mapFrame );  //通过对buf的分析,拆分成一帧一帧后放入到m_mapFrame中
   FrameInfo fi;
   map<UINT16, FrameInfo>::iterator iter;
   while ( GetAFrame(m_mapFrame, iter) )
   {
      fi = iter->second;
      put_frame_to_decoder(fi);
   }
}

其中的GetAFrame()大致如下:

bool GetAFrame( map<UINT16, FrameInfo> mapFrame, map<UINT16, FrameInfo>::iterator &iter )
{
   static UINT6 frmId = 0;
   iter = mapFrame.Find(frmId);
   frmId++;
   if ( iter == mapFrame.end() )
      return false;
   return true;
}


以上代码只是逻辑上的,仅用于展示问题,实际的工程代码还加入了异常处理的内容。

本文仅用于记录之前没有注意到的一个map使用上的问题,大致包含了问题的出现情况和解决办法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值