RTMP推送延时测试

为什么需要ChangeChunkSize这个函数,RTMP需要通过这个包指定一个ChunkSize??

pack.m_body[3] = nChunkSize & 0xff; //大字节序
pack.m_body[2] = nChunkSize >> 8;
pack.m_body[1] = nChunkSize >> 16;
pack.m_body[0] = nChunkSize >> 24;

m_pRtmp->m_outChunkSize = nChunkSize;

 

SendPacket(unsigned int nPacketType, unsigned int nHeaderType,char *data, unsigned int size, unsigned int nTimestamp)函数调用了

int nRet = RTMP_SendPacket(m_pRtmp, &packet, TRUE);

 

connect函数中调用:

RTMP_SetupStream(m_pRtmp, nprotocol, &av_host, nport, &av_sockhost, &av_playpath, &av_tcUrl, 0, 0, 
        &av_app, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5);

RTMP_EnableWrite(m_pRtmp);
if (!RTMP_Connect(m_pRtmp, NULL))
if (!RTMP_ConnectStream(m_pRtmp, 0))

 

int CVideoDecoder::DecodeSps(unsigned char* pData, int nSize)处理spspps,有一个数据成员szSpsPpsNal用于保存处理结果:
unsigned char* szSpsPpsNal;

 

int CVideoDecoder::DecodeFrame(unsigned char* pData, int nSize, size_t nTimeStamp, video_type eType)

int nRet = avcodec_decode_video2(m_pCodecCtx, m_pFrame, &got_picture, &m_packet);

if (got_picture)
{ ProcessPicture(m_nImgWidth, m_nImgHeight, m_pFrame, nTimeStamp);
  ……
}

 

int CVideoDecoder::Decode(unsigned char* pData, int nSize, size_t nTimeStamp)解码函数:

if (zCodeId == 7)
    {
        char zFrameType = *pData++ >> 4;
        // 1:Iframe  7:AVC  关键帧
        if (zFrameType == 1)
        {
            // IFrame, also key frame
            unsigned char zAVCFrameType = *pData++;
            //sps、pps数据
            if (zAVCFrameType == 0)
            {
                return DecodeSps(pData, nSize - 2);
            }
            else if (zAVCFrameType == 1)//关键帧视频数据
            {
                return DecodeFrame(pData, nSize - 2, nTimeStamp, TYPE_IDR);
            }
            else if (zAVCFrameType == 2)
            {
                LOG("[%d] 2 = AVC end of sequence\n", GetTickCount());
            }
        }
        else if (zFrameType == 2)// 2:Pframe  7:AVC  
        {
//            LOG("[%d] get P frame..\n", GetTickCount());
            // P frame 
            pData++; // should always be 1;
            return DecodeFrame(pData, nSize - 2, nTimeStamp, TYPE_P);
        }
        else
        {
            LOG("[%d] Unsupported frame type: %d\n", GetTickCount(), zFrameType);
            return -1;
        }
    }
    else
    {
        LOG("[%d] Unsupported video type: %d\n", GetTickCount(), zCodeId);
        return -1;
    }

 

int CVideoService::ConnectRTMP(const string& strRtmpUrl)

m_Rtmp = srs_rtmp_create(strRtmpUrl.c_str());
if ((ret = srs_rtmp_handshake(m_Rtmp)) != 0)
if ((ret = srs_rtmp_connect_app(m_Rtmp)) != 0)
if ((ret = srs_rtmp_play_stream(m_Rtmp)) != 0)

 

DWORD GetTickCount(void);    GetTickCount返回(retrieve)从操作系统启动所经过(elapsed)的毫秒数。

 

enum的这个用法:

enum 
{
    CHANGE_NONE,
    CHANGE_INCREASE,
    CHANGE_DECREASE
}m_eCurrentChangeState;

 

int CVideoService::VideoProcessThreadImpl(void)

if ((nret = srs_rtmp_read_packet(m_Rtmp, &type, &timestamp, &data, &size)) == 0)//其中的data为char*,并未分配空间,因此可能在这个函数内有内存分配操作

 

除了ProcessPicture外,还会调用很多的CEventNotifier::GetEventNotifier().NotifyEvent及NotifyEventSync :

if (got_picture){
     bNeedShowMessage = true;
     ProcessPicture(nImgWidth, nImgHeight, m_pFrame, nTimeStamp);
     //printf("%d: IFrame decode OK, return; %d, nal len: %d\n", nTimeStamp, nRet, nNalLen); 
}
CEventNotifier::GetEventNotifier().NotifyEvent(pService->m_strDeviceCode, EVENT_VIDEO_REPLAYING, 0);
CEventNotifier::GetEventNotifier().NotifyEvent(m_strDeviceCode, EVENT_VIDEO_BAND_WIDTH_LOW);
CEventNotifier::GetEventNotifier().NotifyEventSync(m_strDeviceCode, EVENT_VIDEO_UPDATE_INFO_W_H, (WPARAM)nImgWidth, (LPARAM)nImgHeight);

 

类CVideoService有一个 成员变量volatile bool m_bPlaying;但是它好像只在函数int CVideoService::CancelVideoProcess()里被改变。

 

如果没有定义#ifdef USE_SRS_LIBRTMP  ,才会在int CVideoService::VideoProcessThreadImpl(void)函数内

用到CVideoService类的成员变量CVideoDecoder m_pVideoDecoder来进行视频处理解码。其中CVideoDecoder类中包含:

 

class CVideoDecoder
{
        ……
private:
    AVCodecContext  *m_pCodecCtx;
    AVFrame         *m_pFrame;
    AVPacket m_packet;
    unsigned char* szSpsPpsNal;
    size_t nSpsPpsLen;
    bool m_bFirstFrame;
    int m_nImgWidth;
    int m_nImgHeight;
    string m_strDeviceCode;
};

 

 

昨天在想GetDownloadSpeedOnTimer这个函数是怎么定时检测调整速度的,原来是在VideoProcessThreadImpl函数内有:

CGlobalTimerManager::GetTimerManager().SetTimer(TIMER_DOWNLOAD_SPEED_DETECTED, 5 * 1000, CVideoService::GetDownloadSpeedOnTimer, this);

 

#else
int CVideoService::VideoProcessThreadImpl(void)函数内有计算延时的:

LOG("delay time : %d\n", GetTickCount() - rPacket.m_nTimeStamp - CControlInfoManage::GetControlInfoManager().GetDiffTime(m_strDeviceCode));

但是在另一个VideoProcessThreadImpl函数内却没有,此外

while (RTMP_IsConnected(m_Rtmp) && RTMP_ReadPacket(m_Rtmp, &rPacket))

前一个用的是srs_rtmp_read_packet

 

int CVideoService::ProcessInvokeMessage(RTMPPacket *rPacket)这个函数似乎也是在没有定义#ifdef USE_SRS_LIBRTMP 的时候才定义的。具体作用是什么??

#ifndef USE_SRS_LIBRTMP
    int ProcessInvokeMessage(RTMPPacket *packet);
#endif

 

RTMP_CONNECT_RESULT CRTMPStream::Connect(const char* szBaseUrl, const char* szSessionId, const char* szPadCode, const char* szstreamName, const char* strPublishCode)

RTMP_SetupStream(m_pRtmp, nprotocol, &av_host, nport, &av_sockhost, &av_playpath, &av_tcUrl, 0, 0, 
        &av_app, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5);

 

CGlobalTimerManager::GetTimerManager()的setTimer和killTimer函数用到参数TIMER_DOWNLOAD_SPEED_DETECTED(一个宏),难道它里面有一个关联容器对各个定时器进行关联??

 

posted @ 2017-03-31 18:22  IT由零开始  阅读(1673)  评论(0编辑  收藏  举报