FFMPEG(一)使用初探

来源:互联网 发布:大数据存储技术研究 编辑:程序博客网 时间:2024/06/01 08:36
本系列文章的重要参考来源是雷神的博客。
使用FFMPEG的主要流程如下:

av_register_all()->avformat_open_input()->av_find_stream_info()->avcodec_find_decoder()->avcodec_open()->av_read_frame()->loop{get packet->avcodec_decode_video2()}->end

FFMPEG打开媒体的的过程开始于avformat_open_input,这中间会涉及到输入输出结构体AVIOContext和URLProtocol结构体,每种输入协议都会定义一个URLProtocol变量,这里会定义url_open等函数。


如果说,在Windows平台上开发相关的程序,可以使用另一个开源库SDL,该开源库在Android中的路径为prebuilts/misc/windows/sdl2/,使用SDL的基本流程如下:

SDL_init()->SDL_SetVideoMode()创建出SDL_Surface->SDL_CreateYUVOverlay()创建出SDL_Overlay->loop{SDL_DisplayYUVOverlay()->decode->YUV->送给SDL_Overlay}->到显示器显示

其中SDL_Surface就是使用SDL的时候弹出的那个窗口。在SDL1.x版本中,只可以创建一个SDL_Surface。

SDL_Overlay用于显示YUV数据。一个SDL_Overlay对应一帧YUV数据。
SDL_Rect用于确定SDL_Overlay显示的位置。注意:一个SDL_Overlay可以指定多个不同的SDL_Rect,这样就可以在SDL_Surface不同位置显示相同的内容。

下面以一个音频播放的例子,说明代码实现流程。

static Uint8 *audio_chunk; static Uint32 audio_len; static Uint8 *audio_pos; void fill_audio(void *udata,Uint8 *stream,int len){ if(audio_len==0) /* Only play if we have data left */ return; len=(len>audio_len?audio_len:len); /* Mix as much data as possible */ SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME); audio_pos += len; audio_len -= len; } int main(int argc, char* argv[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; char url[]="WavinFlag.aac";av_register_all(); avformat_network_init(); pFormatCtx = avformat_alloc_context(); //Open avformat_open_input(&pFormatCtx,url,NULL,NULL);// Retrieve stream information av_find_stream_info(pFormatCtx)<0);// Find the first audio stream for(i=0; i < pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){ audioStream=i; break; } // Get a pointer to the codec context for the audio stream pCodecCtx=pFormatCtx->streams[audioStream]->codec; // Find the decoder for the audio stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); // Open codec avcodec_open2(pCodecCtx, pCodec,NULL)<0);AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket)); av_init_packet(packet); AVFrame *pFrame; pFrame=avcodec_alloc_frame(); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);SDL_AudioSpec wanted_spec; wanted_spec.freq = out_sample_rate; wanted_spec.format = AUDIO_S16SYS; wanted_spec.channels = out_channels; wanted_spec.silence = 0; wanted_spec.samples = out_nb_samples; wanted_spec.callback = fill_audio; //Swr struct SwrContext *au_convert_ctx; au_convert_ctx = swr_alloc(); au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,in_channel_layout,pCodecCtx->sample_fmt , pCodecCtx->sample_rate,0, NULL); swr_init(au_convert_ctx); //Play SDL_PauseAudio(0); wanted_spec.userdata = pCodecCtx; SDL_OpenAudio(&wanted_spec, NULL);while(av_read_frame(pFormatCtx, packet)>=0){ if(packet->stream_index==audioStream){ avcodec_decode_audio4( pCodecCtx, pFrame,&got_picture, packet);if ( got_picture > 0 ){ swr_convert(au_convert_ctx,&out_buffer, MAX_AUDIO_FRAME_SIZE,(const uint8_t **)pFrame->data , pFrame->nb_samples);} //Set audio buffer (PCM data) audio_chunk = (Uint8 *) out_buffer; //Audio buffer length audio_len =out_buffer_size; audio_pos = audio_chunk; while(audio_len>0)//Wait until finish SDL_Delay(1); } av_free_packet(packet); } swr_free(&au_convert_ctx); SDL_CloseAudio();//Close SDL SDL_Quit(); av_free(out_buffer); avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); return 0; } 

对上面代码的简单理解,主要是如下三点:

1)以AVFormatContext、AVCodecContext和AVCodec为核心变量的构建输入源解码环境,经decode函数将解码的码流放入AVFrame变量,不过在解码过程中还要用到一个AVPacket中间变量,应该是Track数据容器。
2)SwrContex用于处理源音频格式向目标音频格式的转换。
3)SDL相关通过SDL_AudioSpec变量描述播放参数和音频流传输回调函数,解码器与回调函数之间通过全局变量协调音频流播放完成的节奏,其中每次解码的buffer大小固定的,用av_samples_get_buffer_size根据输入输出音频参数计算。

附录:
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

MinGW,是Minimalist GNUfor Windows的缩写。它是一个可自由使用和自由发布的Windows特定头文件和使用GNU工具集导入库的集合,允许你在GNU/Linux和Windows平台生成本地的Windows程序而不需要第三方C运行时(C Runtime)库。MinGW 是一组包含文件和端口库,其功能是允许控制台模式的程序使用微软的标准C运行时(C Runtime)库(MSVCRT.DLL),该库在所有的 NT OS 上有效,在所有的 Windows 95发行版以上的 Windows OS 有效,使用基本运行时,你可以使用 GCC 写控制台模式的符合美国标准化组织(ANSI)程序,可以使用微软提供的 C 运行时(C Runtime)扩展,与基本运行时相结合,就可以有充分的权利既使用 CRT(C Runtime)又使用 WindowsAPI功能。
原创粉丝点击