ffmpeg
sdk 開發介紹
1.簡介:
ffmpeg是一套可以用來記錄、轉換數字音頻、視訊,并能将其轉化為流的開源計算機程式。
使用ffmpeg能夠完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,stream和player等.
2.下載下傳和編譯:
下載下傳位址: http://ffmpeg.org/download.html
編譯:
1)windows平台static library/shared library, 編譯工具:mingw-gcc或者在linux平台下交叉編譯(推薦)
2)linux平台static library/shared library, 編譯工具:gcc
子產品:
libavcodec - 編碼解碼器
libavdevice - 輸入輸出裝置的支援
libavfilter - 視音頻濾鏡支援
libavformat - 視音頻等格式的解析
libavutil - 工具庫
libpostproc - 後期效果處理
libswscale - 圖像顔色、尺寸轉換
3.sdk介紹和開發(基于ffmpeg 0.8 sdk)
ffmpeg每部分功能都采用plugin的方式,使用統一的接口調用,這樣就能夠非常友善的使用和擴充。
plugin分為幾種:muxer,demuxer,protocol,hwaccel,encoder,decoder,parser,bitstream,filter,...
是以在使用sdk的時候第一步就是注冊plugin
avcodec_register_all() : 注冊 hwaccel,encoder,decoder,parser,bitstream
av_register_all() : 注冊 muxer,demuxer,protocol
avfilter_register_all() : 注冊 濾鏡filter
下面根據不同的應用場景,給出主要的代碼示例(僅是代碼片斷,不一定能編譯通過):
1)如何擷取媒體檔案的資訊(parser):
// 參考v3代碼: interface ifiledecoder, media/impl/filedecoderimpl.cpp
{
av_register_all();
avformatcontext * pformatctx = null;
int err = 0;
const char *filename = "c:\\test.mp4";
err = av_open_input_file(&pformatctx, filename, null, 0, null);
if(err != 0)
{
// break ;
}
err = av_find_stream_info(pformatctx);
if(err < 0)
for(uint32_t i = 0; i < pformatctx->nb_streams; i ++)
// stream 結構資料
avstream *pstream = pformatctx->streams[i];
// 幀率資訊
avrational framerate = pstream->r_frame_rate;
// 時間機關比率
avrational timebase = pstream->time_base;
// stream duration
int64_t duration = pstream->duration;
// 擷取codec資料結構
avcodeccontext *pcodecctx = pstream->codec;
avmediatype codectype = pcodecctx->codec_type;
codecid codecid = pcodecctx->codec_id;
if(codectype == avmedia_type_video)
{
// 擷取video基本資訊
int width = pcodecctx->width;
int height = pcodecctx->height;
pixelformat pixelformat = pcodecctx->pix_fmt;
}
else if(codectype == avmedia_type_audio)
// 擷取audio基本資訊
int channels = pcodecctx->channels;
int sample_rate = pcodecctx->sample_rate;
avsampleformat samplefmt = pcodecctx->sample_fmt;
// 釋放
if(pformatctx != null)
av_close_input_file(pformatctx);
pformatctx = null;
}
}
2)讀取sample資料(read raw sample不解碼)
// 參考parser代碼
// av_register_all();
// avformatcontext * pformatctx = null;
// err = av_open_input_file(&pformatctx, filename, null, 0, null);
avpacket packet;
av_init_packet(&packet);
int ret = av_read_frame(pformatctx, &packet);
if(ret >= 0)
int streamindex = packet.stream_index;
avstream *pstream = pformatctx->streams[streamindex];
// 計算timestamp
// 轉換時間到1/1000000秒
avrational time_base;
time_base.num = 1;
time_base.den = 1000000;
// 25.0 1/25, 29.97 1001/30000
// 擷取 dts/pts
const int64_t dts = av_rescale_q(packet.dts, pstream->time_base, time_base);
const int64_t pts = av_rescale_q(packet.pts, pstream->time_base, time_base);
uint8_t *data = packet.data;
int size = packet.size;
bool iskey = ((packet.flags & av_pkt_flag_key) == av_pkt_flag_key);
av_free_packet(&packet);
3)解碼sample(video es=>yuv/rgb, audio es=>pcm)
// 參考v3代碼: interface ivideodecoder/iaudiodecoder, media/impl/videodecoderimpl.cpp/audiodecoderimpl.cpp
// 參考parser,read raw sample代碼