@property AVFormatContext *pFormatCtx;
//video
@property struct AVCodecContext *pVideoCodecCtx;
@property struct AVFrame *videoAVFrame;
@property int video_sampleRate;
@property int video_stream_index;
//audio
@property enum AVCodecID audio_codecID;
@property int audio_sampleRate;
@property int audio_stream_index;
@property AVCodecContext *pAudioCodecCtx;
@property struct AVFrame *audioAVFrame;
@property SwrContext *swrContext;
av_register_all();
avcodec_register_all();
avformat_network_init();
_pFormatCtx = avformat_alloc_context();
errCode = avformat_open_input(&_pFormatCtx, "rtsp://192.168.1.100:554/live1.sdp", NULL, NULL);
if(errCode!=0)
{
printf("Couldn't open input stream \n");
return;
}
if(avformat_find_stream_info(_pFormatCtx, NULL)<0)
{
printf("Couldn't find stream information \n");
return;
}
for(int i = 0;i < _pFormatCtx->nb_streams;i++)
{
if(_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
AVCodec *audioCodec = NULL
_audio_sampleRate = _pFormatCtx->streams[i]->codec->sample_rate;
audioCodec = avcodec_find_decoder(_pAudioCodecCtx->codec_id);
_audio_stream_index = i;
if(!audioCodec)
{
printf("get audio Codec error\n");
}
if(avcodec_open2(_pAudioCodecCtx, audioCodec, NULL)<0)
{
printf("avcode_open for audio error\n");
}
//For Audio Convert
int64_t chIn = av_get_default_channel_layout(_pAudioCodecCtx->channels);//src channel数,例如channel为2
int64_t chOut = av_get_default_channel_layout(_audioPlayer->_channels);//dst channel数,例如channel为2
//从src的格式(网络数据),转为dst的格式(本地播放器,可以自己设定)
_swrContext = swr_alloc_set_opts(NULL,
chOut,//dst
_audioPlayer->_sampleFormat,//dst 例如AV_SAMPLE_FMT_S16
_audioPlayer->_sampleRate,//dst 例如8k
chIn, //src
_pAudioCodecCtx->sample_fmt,//src
_pAudioCodecCtx->sample_rate,//src
0,
NULL);
swr_init(_swrContext);
//End Aduio Convert
}
else if(_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
AVCodec *videcCodec = NULL;
_pVideoCodecCtx = _pFormatCtx->streams[i]->codec;
videcCodec = avcodec_find_decoder(_pVideoCodecCtx->codec_id);
_video_stream_index = i;
if(videcCodec==NULL)
{
printf("Video Codec not found \n");
return ;
}
if(avcodec_open2(_pVideoCodecCtx, _pVideoCodec, NULL)<0)
{
printf("Video Codec open Fail \n");
return;
}
}
}
_videoAVFrame = avcodec_alloc_frame();
_audioAVFrame = avcodec_alloc_frame();
if(!_audioAVFrame || !_videoAVFrame)
{
printf("alloc frame fail\n");
}
//Read Frame
while (1)
{
int ret = 0;
int got_frame = 0;
AVPacket packet;
if(av_read_frame(_pFormatCtx,&packet)<0)
{
printf("av_read_frame not find frame\n");
continue;
}
if(packet.stream_index == _video_stream_index)
{
ret = avcodec_decode_video2(_pVideoCodecCtx, _videoAVFrame, &got_frame, &packet);
if(ret<0)
{
printf("video decode fail\n");
}
if(got_frame)
{
//to do
//图像信息都在_videoAVFrame中,自己去渲染
}
}
else if(packet.stream_index == _audio_stream_index)
{
ret = avcodec_decode_audio4(_pAudioCodecCtx, _audioAVFrame, &got_frame, &packet);
if(ret<0)
{
printf("decode audio fail\n");
}
if(got_frame)
{
//音频信息都在_audioAVFrame中,自己渲染
//音频比视频多一步:音频转化,将所有的音频都转为固定的设定(例如都转为8k 2ch 16bits)
static unsigned char * p = NULL;
if(p==NULL)
{
p = (unsigned char*)malloc(1024*1024);//接收区足够大,暂不释放
}
int numSample = swr_convert(_swrContext, &p, _audioAVFrame->nb_samples, (const uint8_t**)_audioAVFrame->data, _audioAVFrame->nb_samples);
//实际有效的输出到耳机的bytes数目
int iAvaSize = numSample * _audioPlayer->_channels/* dst 的channel数*/ * _audioPlayer->mDataFormat.mBitsPerChannel/*dst bits数,例如AV_SAMPLE_FMT_S16就应该是16bits*/ / 8;
//to do
//memcpy(地址,p,iAvaSize);//iAvaSize为实际输出的有效bytes
}
}
av_free_packet(&packet);
}
avcodec_free_frame(&_audioAVFrame);
avcodec_free_frame(&_videoAVFrame);
if (_pFormatCtx)
{
avformat_close_input(&_pFormatCtx);
avformat_free_context(_pFormatCtx);
}
FFMPEG 实时流媒体 客户端 大致流程
最新推荐文章于 2024-07-21 00:38:10 发布