国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

live555學習筆記12-h(huán)264 rtp包的時間戳

2019-11-08 18:26:08
字體:
供稿:網(wǎng)友

十二 h264 rtp包的時間戳

這次我們一起來分析一下live555中是怎樣為rtp包打時間戳的.就以h264為例吧.

[cpp] view plain copyvoid H264VideoRTPSink::doSpecialFrameHandling(unsigned /*fragmentationOffset*/,          unsigned char* /*frameStart*/,          unsigned /*numBytesInFrame*/,          struct timeval frameaccess unit' (i.e. video frame).      if (fOurFragmenter != NULL) {          H264VideoStreamFramer* framerSource = (H264VideoStreamFramer*) (fOurFragmenter->inputSource());          // This relies on our fragmenter's source being a "H264VideoStreamFramer".          if (fOurFragmenter->lastFragmentCompletedNALUnit()                  && framerSource != NULL && framerSource->pictureEndMarker()) {              setMarkerBit();              framerSource->pictureEndMarker() = False;          }      }        setTimestamp(framePresentationTime);  }  函數(shù)中先檢測是否是一個幀的最后一個包,如果是,打上'M'標記.然后就設(shè)置時間戳.這個間戳是哪來的呢?需看函數(shù)doSpecialFrameHandling()是被誰調(diào)用的,經(jīng)查找,是被MultiFramedRTPSink::afterGettingFrame1()調(diào)用的.MultiFramedRTPSink::afterGettingFrame1()的參數(shù)presentationTime傳給了doSpecialFrameHandling().MultiFramedRTPSink::afterGettingFrame1()是在調(diào)用source的getNextFrame()時傳給了source.傳給哪個source呢?傳給了H264FUAFragmenter,還記得暗渡陳倉那件事嗎?所以H264FUAFragmenter在獲取一個nal unit后調(diào)用了MultiFramedRTPSink::afterGettingFrame1().也就是H264FUAFragmenter::afterGettingFrame1()調(diào)用了MultiFramedRTPSink::afterGettingFrame1().H264FUAFragmenter::afterGettingFrame1()是被它自己的source的afterGettingFrame1()調(diào)用的.H264FUAFragmenter的source是誰呢?是H264VideoStreamFramer,是在暗渡陳倉時傳給H264FUAFragmenter的構(gòu)造函數(shù)的.H264VideoStreamFramer的afterGettingFrame1()是沒有的,代替之的是MPEGVideoStreamFramer::continueReadProcessin().它被MPEGVideoStreamParser暗中傳給了StreamParser的構(gòu)造函數(shù).所以StreamParser在分析完一幀(或nal unit)之后,調(diào)用的就是MPEGVideoStreamFramer::continueReadProcessin().以下即是證明:(補充:以下函數(shù)并不是在parser分析完一幀(或nal unit)之后調(diào)用,而是parser利用ByteStreamFileSuorce獲取到原始數(shù)據(jù)后調(diào)用,然后MPEGVideoStreamFramer再調(diào)用Parser的parser()函數(shù)分析原始數(shù)據(jù))

[cpp] view plain copyvoid StreamParser::afterGettingBytes(void* clientData,          unsigned numBytesRead,          unsigned /*numTruncatedBytes*/,          struct timeval presentationTime,          unsigned /*durationInMicroseconds*/)  {      StreamParser* parser = (StreamParser*) clientData;      if (parser != NULL)          parser->afterGettingBytes1(numBytesRead, presentationTime);  }    void StreamParser::afterGettingBytes1(unsigned numBytesRead,          struct timeval presentationTime)  {      // Sanity check: Make sure we didn't get too many bytes for our bank:      if (fTotNumValidBytes + numBytesRead > BANK_SIZE) {          fInputSource->envir()                  << "StreamParser::afterGettingBytes() warning: read "                  << numBytesRead << " bytes; expected no more than "                  << BANK_SIZE - fTotNumValidBytes << "/n";      }        fLastSeenPresentationTime = presentationTime;        unsigned char* ptr = &curBank()[fTotNumValidBytes];      fTotNumValidBytes += numBytesRead;        // Continue our original calling source where it left off:      restoreSavedParserState();      // Sigh... this is a crock; things would have been a lot simpler      // here if we were using threads, with synchronous I/O...      fClientContinueFunc(fClientContinueClientData, ptr, numBytesRead,              presentationTime);  }  fClientContinueFunc就是MPEGVideoStreamFramer::continueReadProcessin(),而且我們看到時間戳被傳入fClientContinueFunc.然而,MPEGVideoStreamFramer::continueReadProcessin()中跟本就不理這個時間戳,因為這個時間戳是ByteStreamFileSource計算出來的,它跟本就不可能正確.

[cpp] view plain copyvoid MPEGVideoStreamFramer::continueReadProcessing(void* clientData,          unsigned char* /*ptr*/,          unsigned /*size*/,          struct timeval /*presentationTime*/)  {      MPEGVideoStreamFramer* framer = (MPEGVideoStreamFramer*) clientData;      framer->continueReadProcessing();  }  看來真正的時間戳是在MPEGVideoStreamFramer中計算的,但是H264VideoStreamFramer并沒有用到MPEGVideoStreamFramer中那些計算時間戳的函數(shù),而是另外計算,其實H264VideoStreamFramer也沒有自己去計算,而是利用H264VideoStreamParser計算的.是在哪個函數(shù)中呢?在parser()中!

[cpp] view plain copyunsigned H264VideoStreamParser::parse()  {      try {          // The stream must start with a 0x00000001:          if (!fHaveSeenFirstStartCode) {              // Sk

每當開始一個新幀時,計算新的時間戳.時間戳保存在fNextPresentationTime中,在usingSource()->setPresentationTime()中傳給fPresentationTime.哇,我們看到live555的類之間調(diào)用關(guān)系曲折復雜,的確有點不易維護啊!同時我寫的也不夠清析,自己看著都暈,如果把你搞暈了,這很正常哦!

fPresentationTime是64位的時間,經(jīng)convertToRTPTimestamp轉(zhuǎn)換為32的rtp時間戳,見函數(shù):

[cpp] view plain copyu_int32_t RTPSink::convertToRTPTimestamp(struct timeval tv)  {      // Begin by converting from "struct timeval" units to RTP timestamp units:      u_int32_t timestampIncrement = (fTimestampFrequency * tv.tv_sec);      timestampIncrement += (u_int32_t)(              (2.0 * fTimestampFrequency * tv.tv_usec + 1000000.0) / 2000000);      // note: rounding        // Then add this to our 'timestamp base':      if (fNextTimestampHasBeenPreset) {          // Make the returned timestamp the same as the current "fTimestampBase",          // so that timestamps begin with the value that was previously preset:          fTimestampBase -= timestampIncrement;          fNextTimestampHasBeenPreset = False;      }        u_int32_t const rtpTimestamp = fTimestampBase + timestampIncrement;            return rtpTimestamp;  }  其實時間戳的轉(zhuǎn)換主要就是把以秒為單位的時間,提升成按頻率為單位的時間.也就是提升后,時間間隔不是以秒為單位,而是以1/fTimestampFrequency為單位,也就是1/9000秒。然后再強轉(zhuǎn)為32。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 宝兴县| 南城县| 怀宁县| 来宾市| 汶上县| 石渠县| 武汉市| 宁明县| 尚义县| 交城县| 泸西县| 龙井市| 洛浦县| 南雄市| 清镇市| 修文县| 双牌县| 和硕县| 隆德县| 中卫市| 韶关市| 英吉沙县| 万源市| 江都市| 疏附县| 土默特左旗| 石渠县| 明光市| 花莲市| 吴江市| 长岛县| 利津县| 长沙县| 增城市| 盱眙县| 马龙县| 咸宁市| 墨竹工卡县| 天柱县| 平罗县| 铜陵市|