rtp音视频同步问题解决方法_第1页
rtp音视频同步问题解决方法_第2页
rtp音视频同步问题解决方法_第3页
rtp音视频同步问题解决方法_第4页
rtp音视频同步问题解决方法_第5页
免费预览已结束,剩余16页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、rtp 音视频同步问题解决方法rtp 同步方法的思考由于音视频流是以两条独立的数据流在网络上传输的, 如果网络质量相当差,那么在接收端收到的音视频数据流就有可能不是同步的了,为了克服这种不同步的现象, 需要添加同步机制。 的同步机制是使用开源库 jrtplib3.7.1 来实现的,严格遵守 rtp 协议标准。解决的方案如下:当有数据需要发送时,往数据中加入时间戳,在接收端,读取时间戳,进行比较,如果相同或相差很近,就提交播放,如果其中一个时间戳更大,就等待。如果网络质量很差,那么存在两种不同步的情况:1. 对于单条数据流来说,如果网络质量很差,可能出现数据流的接收不流畅, 如果没有做流畅处理,

2、 那么就可能出现2. 对于多条数据流来说,如果网络质量很差,可能出现本应该同时播放的数据帧没有在同一时间到达, 需要做同步处理。解决第 1 个问题的方法是向每个发送的数据包加上时间戳,在rtp 库中, 时间戳表示在打包数据段中第一个采样所对应的时间, 时间戳的启始值是随机的,后续的时间戳是在前一个时间戳上的增量,在SendPacke冲的时间戳参数表示的是时间戳增量,所以数据流的同步需要计算出时间戳增量。对于音频数据,由于音频数据的采样率是8000Hz所以每采样一次需要时间是1/8000S,由于是每20ms封包一次,所以时间戳的增量是 (20*10*-3)*8000=160 。对于视频数据,由于

3、视频数据的采样率是90000Hz所以每采样一次需要 时 间 是 1/90000s, 如 果 帧 率 是 25 帧 /s, 所 以 时 间 戳 增 量 是 90000/25=3600。在发送端,每发送一个数据包,都打上该数据包对于的时间戳值,只需要向SendPacket的最后个参数传递时间戳增量,rtp库会自动算出时间戳,并加到发送的 rtp 数据包首部里边。在接收端,当收到一个数据包时,获取该rtp 数据包的时间戳值,计算出与前一个数据包的时间戳值的差值,乘以该媒体流的时间戳单位,就得出了当前数据包与前一个数据包之间的间隔的打包时间 T。所以只要保证在与前一个数据包被提交过后T 时间后再提交当

4、前接收到的数据包,那么在rtp 层就解决了上边提出的第一个问题。解决第 2 个问题的方法是使用 rtcp 发送者报告数据包中的时间信息,发送者报告被发送的间隔时间是不固定的, 它的大小与参与到会话中的同步源数量成正比。 每个发送者报告中都有个ntp 时间和 rtp 时间,该 ntp 时间表示在发送时间戳为该rtp 时间的 rtp 包时的系统绝对时间,就是在发送这个rtp 包时的系统时间,所以这两个时间值有对应关系,由于对于一个同步源,时间戳单位是固定的,所以可以由后续的某个数据包的 rtp 时间戳 timestamp1 计算出这个数据包所对应的绝对时间, 这个绝对时间就是在发送这个数据包时,发

5、送端的系统时间这个思路就是:已知:ntp0, rtp0, rtpl ,时间戳单位u,且ntp0与rtp0是表示同一时间值,只是测量标尺不同。计算: ntp1 ,该 ntp1 与 rtp1 表示同一时间值计算的公式:ntp1 = ntp0 + (rtp1- rtp0)*u使用这种方法就可以计算出每个收到的 rtp 数据包在发送端的系统时间, 这个系统时间在发送端是单调递增的, 所以可以通过这个值来同步多条数据流。发送端(需要修改) :if(mediatype = 0)if(first_flag)/usleep(125*266*30);presampletime = RTPTime:Current

6、Time();status = rtpsession->SendPacket(void *)buf, len, payloadtype, false, 0);first_flag = false;elsetmpcurtime = curtime = RTPTime:CurrentTime();curtime-=presampletime;interval = (uint32_t)(curtime.GetDouble() * 8000.0);status = rtpsession->SendPacket(void *)buf, len, payloadtype, fa

7、lse, 160/*interval*/);presampletime = tmpcurtime;elseGwRTPRecv:g_start_send = 1;if(GwRTPRecv:g_skip_frame=1)char buf123="#1234#"status = rtpsession->SendPacket(void*)buf123, strlen(buf123), payloadtype,true,0);GwRTPRecv:g_skip_frame = 2;if(GwMpeg4Codec:g_key_frame)if(buf10 !

8、= 'I')return false;else if(GwMpeg4Codec:g_key_frame=2)GwMpeg4Codec:g_key_frame = 0;first_flag = true;if(first_flag)presampletime = RTPTime:CurrentTime();status = rtpsession->SendPacket(void *)buf, len, payloadtype, false, 0);first_flag = false;elsetmpcurtime = curtime = RTPTim

9、e:CurrentTime();curtime-=presampletime;interval = (uint32_t)(curtime.GetDouble() * 90000.0);status = rtpsession->SendPacket(void *)buf, len, payloadtype, false, interval);presampletime = tmpcurtime;接收端(需要修改) :bool recved = false;RTPPacket *pack;uint8_t *data ;RTPTime curtime(0,0);uint32_t tim

10、estamp;RTPTime delay_time(0, 0);uint32_t rtcp_timestamp;RTPNTPTime rtcp_ntptime(0,0);double interval_time;double interval_time_abs;RTPSourceData* psourcedata;char need_sync_flag = false;if(mediatype = 0)rtpsession->BeginDataAccess();if (rtpsession->GotoFirstSourceWithData()dowhile (pac

11、k = rtpsession->GetNextPacket() != NULL)if(pack->GetPayloadType() != payloadtype)rtpsession->DeletePacket(pack);continue;recvlen = pack->GetPayloadLength();if(recvlen > pack_size| recvlen <= 0 )rtpsession->DeletePacket(pack);continue;timestamp = pack-

12、>GetTimestamp();data = pack->GetPayloadData();*len = recvlen;memcpy(buf, data, recvlen);recved = true;psourcedata rtpsession->GetCurrentSourceInfo();if(psourcedata->SR_HasInfo()rtcp_timestamp = psourcedata->SR_GetRTPTimestamp();rtcp_ntptime = psourcedata->SR

13、_GetNTPTimestamp();recvd_rtcp = true;if(recvd_rtcp)RTPTime rtcpntptime(rtcp_ntptime);uint32_t timestamp_bound = timestamp >rtcp_timestamp?(timestamp-rtcp_timestamp):(rtcp_timestamp-timesta mp);if(timestamp_bound > 0xffff0000)interval_time_abs = (0xffffffff - timestamp_bound)/8000.0;int

14、erval_time=timestamp<rtcp_timestamp?(interval_time_abs):(-interval_time_abs);elseinterval_time_abs = timestamp_bound/8000.0;interval_time=timestamp<rtcp_timestamp?(-interval_time_abs):(interval_time_abs);RTPTime rtptime_interval(interval_time_abs);if(interval_time > 0)rtcpntptim

15、e+=rtptime_interval;elsertcpntptime-=rtptime_interval;audio_time_sem.lockSem();audio_curtime = rtcpntptime;audio_time_sem.unlockSem();rtpsession->DeletePacket(pack);goto aurecv_end; while (rtpsession->GotoNextSourceWithData();aurecv_end:rtpsession->EndDataAccess();elsertpsession

16、->BeginDataAccess();if (rtpsession->GotoFirstSourceWithData()dowhile (pack = rtpsession->GetNextPacket() != NULL)if(pack->GetPayloadType() != payloadtype)rtpsession->DeletePacket(pack);continue;recvlen = pack->GetPayloadLength();if(recvlen > pack_size

17、| recvlen <= 0 )rtpsession->DeletePacket(pack);continue;timestamp = pack->GetTimestamp();data = pack->GetPayloadData();*len = recvlen;memcpy(buf, data, recvlen);recved = true;if(pack->HasMarker() && strncmp(char*)data,"#1234#", 6)

18、= 0)rtpsession->DeletePacket(pack);goto verecv_end;if(buffer0='#' && buffer3='*'&& buffer2 = 'I')first_flag = true;psourcedata = rtpsession->GetCurrentSourceInfo();if(psourcedata->SR_HasInfo()rtcp_ti

19、mestamp = psourcedata->SR_GetRTPTimestamp();rtcp_ntptime = psourcedata->SR_GetNTPTimestamp();recvd_rtcp = true;if(recvd_rtcp)RTPTime rtcpntptime(rtcp_ntptime);uint32_t timestamp_bound = timestamp >rtcp_timestamp?(timestamp-rtcp_timestamp):(rtcp_timestamp-timesta mp);if(timestamp

20、_bound > 0xffff0000)interval_time_abs = (0xffffffff - timestamp_bound)/90000.0;<interval_time=timestamprtcp_timestamp?(interval_time_abs):(-interval_time_abs);elseinterval_time_abs = timestamp_bound/90000.0;interval_time = timestamp < rtcp_timestamp?(-interval_time_abs):(interva

21、l_time_abs);RTPTime rtptime_interval(interval_time_abs);if(interval_time > 0)rtcpntptime+=rtptime_interval;elsertcpntptime-=rtptime_interval;audio_time_sem.lockSem();RTPTime audio_curtime1 = audio_curtime;audio_time_sem.unlockSem();if(audio_curtime1.GetSeconds()!=0|audio_curtime1.GetMicroSeco

22、nds() != 0)if(rtcpntptime < audio_curtime1)RTPTime tmp = audio_curtime1;if(tmp-=rtcpntptime) > RTPTime(0, 500000)first_flag = true; /*make vedio stream receive faster*/*len = 0;recved = false; /*discard packet becase it is too late*/goto verecv_end;elseif(first_sync_flag)presynctime =

23、RTPTime:CurrentTime();first_sync_flag = false;need_sync_flag = true;elsecurtime = RTPTime:CurrentTime();RTPTime tmp = curtime;tmp -= presynctime;if(tmp >= RTPTime(5,0)need_sync_flag = true;presynctime = curtime;if(need_sync_flag)rtcpntptime-=RTPTime(0, 1000);while ( audio_recving && rtcpntptime >audio_curtime1 ) /*vedio advance*/audio_time_sem.lockSem();audio_curtime1 = audio_curt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论