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, ×tamp, &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(一个宏),难道它里面有一个关联容器对各个定时器进行关联??