/*
作者: pengweizhi 博客地址: http://blog.csdn.net/zhoubotong2012
*/
#include "stdafx.h"
#include "RtmpStreamSession.h"
#include <sstream>
#define ONE_AUDIO_FRAME_SIZE 192000
string to_string(int n)
{
std::ostringstream stm;
string str;
stm << n;
str = stm.str();
//std::cout << str << std::endl;
return str;
}
//////////////////////////////////////////////////////////////
RtmpStreamSession::RtmpStreamSession()
{
m_stop_status = false;
m_videoStreamIndex = -1;
m_audioStreamIndex = -1;
m_hReadThread = nullptr;
m_bInited = FALSE;
m_bsfcH264 = nullptr;
m_bsfcAAC = nullptr;
coded_width = coded_height = 0;
m_frame_rate = 25;
m_pfd = nullptr;
m_inputAVFormatCxt = nullptr;
m_nVideoFramesNum = 0;
m_dwStartConnectTime = 0;
m_dwLastRecvFrameTime = 0;
m_nMaxConnectTimeOut = 8;
m_nMaxRecvTimeOut = 10;
m_bAudioDecoderInited = FALSE;
m_bVideoDecoderInited = FALSE;
m_pframe = NULL;
m_pVideoCBFunc = NULL;
m_pAudioCBFunc = NULL;
m_pAudioCodecCtx = NULL;
m_pAudioCodec = NULL;
m_pSamples = NULL;
m_pAudioFrame = NULL;
}
RtmpStreamSession::~RtmpStreamSession()
{
ReleaseCodecs();
}
void RtmpStreamSession::StopStream()
{
m_stop_status = true;
if (m_hReadThread != NULL)
{
WaitForSingleObject(m_hReadThread, INFINITE);
CloseHandle(m_hReadThread);
m_hReadThread = NULL;
}
closeInputStream();
}
void RtmpStreamSession::InitData()
{
coded_width = coded_height = 0;
m_nVideoFramesNum = 0;
m_bInited = FALSE;
m_stop_status = false;
m_bAudioDecoderInited = FALSE;
m_bVideoDecoderInited = FALSE;
}
//开始接收RTSP/RTMP流
//url -- URL路径
//record_file_path -- 录制的文件路径
//
BOOL RtmpStreamSession::StartStream(string url, string record_file_path)
{
m_InputUrl = url;
m_videoStreamIndex = -1;
m_audioStreamIndex = -1;
m_bInited = FALSE;
if(!record_file_path.empty())
{
m_DestSinkInfo.nType = 0x11;
strcpy(m_DestSinkInfo.szOutputFile, record_file_path.c_str());
}
else
{
m_DestSinkInfo.nType = 0x10;
memset(m_DestSinkInfo.szOutputFile, 0, sizeof(m_DestSinkInfo.szOutputFile));
}
InitData();
do
{
//if(!openInputStream())
//{
// break;
//}
//if(!openOutputStream())
//{
// break;
//}
DWORD threadID = 0;
m_hReadThread = CreateThread(NULL, 0, ReadingThrd, this, 0, &threadID);
return TRUE;
}while(0);
closeInputStream();
closeOutputStream();
ReleaseCodecs();
return FALSE;
}
DWORD WINAPI RtmpStreamSession::ReadingThrd(void * pParam)
{
RtmpStreamSession * pTask = (RtmpStreamSession *) pParam;
pTask->run();
OutputDebugString("ReadingThrd exited\n");
return 0;
}
void RtmpStreamSession::run()
{
do
{
m_stop_status = false;
if(!openInputStream())
{
break;
}
if(!openOutputStream())
{
break;
}
readAndMux();
}while(0);
closeInputStream();
closeOutputStream();
m_stop_status = true;
}
static int interruptCallBack(void *ctx)
{
RtmpStreamSession * pSession = (RtmpStreamSession*) ctx;
//once your preferred time is out you can return 1 and exit from the loop
if(pSession->CheckTimeOut(GetTickCount()))
{
return 1;
}
//continue
return 0;
}
BOOL RtmpStreamSession::CheckTimeOut(DWORD dwCurrentTime)
{
if(dwCurrentTime < m_dwLastRecvFrameTime) //CPU时间回滚
{
return FALSE;
}
if(m_stop_status)
return TRUE;
if(m_dwLastRecvFrameTime > 0)
{
if((dwCurrentTime - m_dwLastRecvFrameTime)/1000 > m_nMaxRecvTimeOut) //接收过程中超时
{
return TRUE;
}
}
else
{
if((dwCurrentTime - m_dwStartConnectTime)/1000 > m_nMaxConnectTimeOut) //连接超时
{
return TRUE;
}
}
return FALSE;
}
BOOL RtmpStreamSession::openInputStream()
{
if (m_inputAVFormatCxt)
{
TRACE("a�