FFMPEG(一)使用初探

本系列文章的重要参考来源是雷神的博客。
使用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功能。

你可能感兴趣的:(FFMPEG(一)使用初探)