得到RTP包中的timestamp
NTP------网络时间协议
PTP------精确时间协议
PTS,DTS的关系:
http://www.cnblogs.com/qingquan/archive/2011/07/27/2118967.html
都知道RTSP协议中,真正的数据传输是RTP协议来传输的,每个RTP包都有一个timestamp,(相对时间戳 relative timestamp)这个时间戳是需要经过换算的,我需要把它换算成相应的时间打印到播放器显示的每一帧上。
不过据http://stackoverflow.com/questions/20094998/retrieving-timestamp-in-rtp-rtsp
介绍,AftergettingFrame回调函数中处理的帧时间的,这个时间是PTS(presentationTime timestamp)
以下是代码片断:
1 void DummySink::afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes, 2 struct timeval presentationTime, unsigned durationInMicroseconds) { 3 DummySink* sink = (DummySink*)clientData; 4 sink->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds); 5 } 6 7 // If you don't want to see debugging output for each received frame, then comment out the following line: 8 #define DEBUG_PRINT_EACH_RECEIVED_FRAME 1 9 10 void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, 11 struct timeval presentationTime, unsigned /*durationInMicroseconds*/) { 12 // We've just received a frame of data. (Optionally) print out information about it: 13 #ifdef DEBUG_PRINT_EACH_RECEIVED_FRAME 14 if (fStreamId != NULL) envir() << "Stream \"" << fStreamId << "\"; "; 15 envir() << fSubsession.mediumName() << "/" << fSubsession.codecName() << ":\tReceived " << frameSize << " bytes"; 16 if (numTruncatedBytes > 0) envir() << " (with " << numTruncatedBytes << " bytes truncated)"; 17 char uSecsStr[6 + 1]; // used to output the 'microseconds' part of the presentation time 18 sprintf_s(uSecsStr, "%06u", (unsigned)presentationTime.tv_usec); 19 envir() << ".\tPresentation time: " << (int)presentationTime.tv_sec << "." << uSecsStr; 20 if (fSubsession.rtpSource() != NULL && !fSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) { 21 envir() << "!"; // mark the debugging output to indicate that this presentation time is not RTCP-synchronized 22 } 23 //#ifdef DEBUG_PRINT_NPT 24 envir() << "\tNPT: " << fSubsession.getNormalPlayTime(presentationTime); 25 //#endif 26 envir() << "\n"; 27 #endif 28 29 // Then continue, to request the next frame of data: 30 continuePlaying(); 31 } 32 33 Boolean DummySink::continuePlaying() { 34 if (fSource == NULL) return False; // sanity check (should not happen) 35 36 // Request the next frame of data from our input source. "afterGettingFrame()" will get called later, when it arrives: 37 fSource->getNextFrame(fReceiveBuffer, DUMMY_SINK_RECEIVE_BUFFER_SIZE, 38 afterGettingFrame, this, 39 onSourceClosure, this); 40 return True; 41 }
以下是openRTSP Demo的timestamp片断:
1 if (notifyTheUser) { 2 struct timeval timeNow; 3 gettimeofday(&timeNow, NULL); 4 char timestampStr[100]; 5 sprintf_s(timestampStr, "%ld%03ld", timeNow.tv_sec, (long)(timeNow.tv_usec/1000)); 6 *env << (syncStreams ? "Synchronized d" : "D") 7 << "ata packets have begun arriving [" << timestampStr << "]\007\n"; 8 return; 9 }
当然LIVE555自身就在服务端把PTS转换成RTP timestamp了然后进行传输,然后到客户端又自动将RTP timestamp转换成PTS。如果要把PTS转换成世界协调时间(UTS),就需要用gettimeofday()这个函数来转换。
references:
http://comments.gmane.org/gmane.comp.multimedia.live555.devel/12552
http://bbs.csdn.net/topics/390676557?page=1
http://live-devel.live.narkive.com/LfuvIyZj/rtp-timestamp-to-utc-time