@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); }