#include "RtspStreamClient.h"
RtspStreamClient::RtspStreamClient()
{
mUri = "";
mStopFlag = true;
mFormatContext = NULL;
mAudioCodecContext = NULL;
mSwrContext = NULL;
mWantAudioFrame = NULL;
wantAudioFrameData = NULL;
mAudioIndex =-1;
mWantAudioChannelCount = 1;
mWantAudioSamplelRate = 16000;
mWantAudioDataFormat = AV_SAMPLE_FMT_S16P;
mWantVideoWidth = DST_VIDEO_WIDTH;
mWantVideoHeight = DST_VIDEO_HEIGHT;
mVideoCodecContext = NULL;
mSwsContext = NULL;
mWantVideoFrame=NULL;
wantVideoFrameData=NULL;
mVideoIndex = -1;
mOldPixelFormat = AV_PIX_FMT_NONE;
mYUVBuffer = NULL;
mYUVBufferSize = NULL;
mAudioCallBack = NULL;
mVideoCallBack = NULL;
mAudioInstance = 0;
}
RtspStreamClient::~RtspStreamClient()
{
}
bool RtspStreamClient::Start(std::string strRtspUrl, int nMediaType)
{
bool bRet = false;
if (mStopFlag)
{
mStopFlag = false;
mUri = strRtspUrl;
mMediaType =(MediaType)nMediaType;
//需要创建处理线程
try
{
mThread = new std::thread(&RtspStreamClient::Run, this);
}
catch (const exception& e)
{
printf("Create thread failed:%s\r\n" ,e.what());
mThread = NULL;
mStopFlag = true;
mUri = "";
return false;
}
bRet = true;
}
return bRet;
}
void RtspStreamClient::Stop()
{
if (mThread)
{
mStopFlag = true;
AVInterruptCallBackFun(this);
mThread->join();
delete mThread;
mThread = NULL;
}
mUri = "";
}
string RtspStreamClient::GetRtspUrl()
{
return mUri;
}
void RtspStreamClient::SetWantVideoResolution(int nWidth, int nHeight)
{
if ((nWidth > 0 && nWidth < MAX_VIDEO_FRAME_WIDTH) && (nHeight > 0 && nHeight < MAX_VIDEO_FRAME_HEIGHT))
{
mWantVideoWidth = nWidth;
mWantVideoHeight = nHeight;
}
}
void RtspStreamClient::SetVideoOutputFormat(const VideoOutputFormat& videoOutputFormat)
{
mVideoOutputFormat = videoOutputFormat;
}
void RtspStreamClient::SetWantAudioOutput(int nChannel, int nSampleRate, int nAudioFormat)
{
mWantAudioChannelCount= nChannel;
mWantAudioSamplelRate= nSampleRate;
mWantAudioDataFormat= nAudioFormat;
}
void RtspStreamClient::SetAudioCallBack(PAUDIOCALLBACK dwAudioCallBack, void* dwInstance)
{
mAudioCallBack =dwAudioCallBack;
mAudioInstance = dwInstance;
}
void RtspStreamClient::SetVideoCallBack(PVIDEOCALLBACK dwCallBackFunction, void* dwInstance)
{
mVideoCallBack= dwCallBackFunction;
mVideoInstance = dwInstance;
}
VideoOutputFormat RtspStreamClient::GetVideoOutputFormat()
{
return mVideoOutputFormat;
}
bool RtspStreamClient::InitFormatCtx()
{
bool bRet = true;
if (mUri == "")
{
printf("mUri is null\r\n");
return false;
}
//设置rtsp超时时间
AVDictionary *avdic = NULL;
av_dict_set(&avdic, "stimeout", "3000000", 0);//3秒 microseconds
//创建格式上下文
mFormatContext = avformat_alloc_context();
if (mFormatContext == NULL)
{
printf ("avformat_alloc_context failure\r\n");
return false;
}
//打开输入流
int err_code = 0;
int nCount = 0;
if ((err_code = avformat_open_input(&mFormatContext, mUri.c_str(), NULL, &avdic)) < 0)
{
char buf[1024];
memset(buf, 0, 1024);
av_strerror(err_code, buf, 1024);
printf("err_code:%s\r\n",err_code);
printf("buf:%s\r\n",buf);
printf("avformat_open_input failure\r\n");
avformat_free_context(mFormatContext);
mFormatContext = NULL;
return false;
}
//阻塞中断函数
mFormatContext->interrupt_callback.callback = AVInterruptCallBackFun;
mFormatContext->interrupt_callback.opaque = this;
return bRet;
}
bool RtspStreamClient::InitAudioDecode()
{
bool bRet = true;
if (!mFormatContext)
{
printf("mFormatContext is null\r\n");
return false;
}
//遍历并找到音频流
mAudioIndex = -1;
for (int i = 0; i < mFormatContext->nb_streams; ++i)
{
if (mFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
mAudioIndex = i;
break;
}
}
if (mAudioIndex == -1)
{
printf("Don't find audio data\r\n");
avformat_close_input(&mFormatContext);
return false;
}
mAudioCodecContext = avcodec_alloc_context3(NULL);
if (!mAudioCodecContext)
{
printf("Don't avcodec_alloc_context3 mAudioCodecContext\r\n");
avformat_close_input(&mFormatContext);
return false;
}
int ret = avcodec_parameters_to_context(mAudioCodecContext, mFormatContext->streams[mAudioIndex]->codecpar);
if (ret < 0)
{
printf("Don't avcodec_parameters_to_context mAudioCodecContext\r\n");
avformat_close_input(&mFormatContext);
return false;
}
//读取编解码器上下文,并找到解码器
AVCodec *codec = avcodec_find_decoder(mAudioCodecContext->codec_id);
if (codec == NULL)
{
printf("Don't find audio decoder\r\n");
avformat_close_input(&mFormatContext);
return false;
}
//打开解码器
if (avcodec_open2(mAudioCodecContext, codec, NULL) < 0)
{
printf("open audio decoder failure\r\n");
avformat_close_input(&mFormatContext);
return false;
}
//开启转换器
mSwrContext = swr_alloc();
swr_alloc_set_opts(mSwrContext, av_get_default_channel_layout(mWantAudioChannelCount), (AVSampleFormat)AV_SAMPLE_FMT_S16P, mWantAudioSamplelRate,
av_get_default_channel_layout(mAudioCodecContext->channels), mAudioCodecContext->sample_fmt, mAudioCodecContext->sample_rate
, 0, NULL);
swr_init(mSwrContext);
mWantAudioFrame = av_frame_alloc();
if (mWantAudioFrame)
{
wantAudioFrameData = (unsigned char*)av_malloc(av_samples_get_buffer_size(NULL, mWantAudioChannelCount, mWantAudioSamplelRate, (AVSampleFormat)AV_SAMPLE_FMT_S16P, 0));
av_samples_fill_arrays(mWantAudioFrame->data, mWantAudioFrame->linesize, wantAudioFrameData, mWantAudioChannelCount, mWantAudioSamplelRate, (AVSampleFormat)AV_SAMPLE_FMT_S16P, 0);
mWantAudioFrame->channels = mWantAudioChannelCount;
mWantAudioFrame->sample_rate = mWantAudioSamplelRate;
mWantAudioFrame->format = AV_SAMPLE_FMT_S16P;
}
return bRet;
}
bool RtspStreamClient::InitVideoDecode()
{
bool bRet = true;
if (!mFormatContext)
{
printf("mFormatContext is null \r\n");
return false;
}
//获取视频流
mVideoIndex = -1;
mFrameRate = 0;
for (int i = 0; i < mFormatContext->nb_streams; ++i) {
if (mFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (mFormatContext->streams[i]->avg_frame_rate.den > 0)
{
mFrameRate = mFormatContext->streams[i]->avg_frame_rate.num / mFormatContext->streams[i]->avg_frame_rate.den;//每秒多少帧
printf("video stream frame_rate=%d\r\n", mFrameRate);
}
mVideoIndex = i;
break;
}
}
if (mVideoIndex == -1)
{
printf("video stream find failure\r\n");
avformat_free_context(mFormatContext);
return false;
}
mVideoCodecContext = avcodec_alloc_context3(NULL);
if (!mVideoCodecContext)
{
printf("Don't avcodec_alloc_context3 mVideoCodecContext\r\n");
avformat_close_input(&mFormatContext);
return false;
}
int ret = avcodec_parameters_to_context(mVideoCodecContext, mFormatContext->streams[mVideoIndex]->codecpar);
if (ret < 0)
{
printf("Don't avcodec_parameters_to_context mVideoCodecContext\r\n");
avformat_close_input(&mFormatContext);
return false;
}
//是否使用硬解码
AVCodec* codec = avcodec_find_decoder(mVideoCodecContext->codec_id);
if (codec == NULL)
{
printf("avcodec_find_decoder not find\r\n");
avformat_close_input(&mFormatContext);
return false;
}
if (avcodec_open2(mVideoCodecContext, codec, NULL) < 0)
{
printf("avcodec_open2 failure\r\n");
avformat_close_input(&mFormatContext);
return false;
}
if (mWantAudioFrame == NULL)
{
mWantAudioFrame = av_frame_alloc();
}
mOldPixelFormat = AV_PIX_FMT_NONE;
return bRet;
}
void RtspStreamClient::ExChangeSwsCtx(const AVFrame* frame)
{
if (frame->format != mOldPixelFormat || (frame->width != mWantVideoFr