一:解碼器初始化步驟
AVCodec *codec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
AVCodecContext *vc = avcodec_alloc_context3(codec)
avcodec_parameters_to_context(vc,ic->streams[videoStream]->codecpar)
vc->thread_count=1;
re=avcodec_open2(vc, 0, 0);
avcodec_find_decoder擷取解碼器方法,avcodec_alloc_context3擷取視訊解碼器上下文,thread_count設定解碼器線程數,
avcodec_open2打開解碼器。
同樣音頻解碼器初始化方式一樣:
AVCodec *acodec = avcodec_find_decoder(ic->streams[audioStream]->codecpar->codec_id);
AVCodecContext *ac = avcodec_alloc_context3(acodec);
avcodec_parameters_to_context(ac,ic->streams[audioStream]->codecpar);
ac->thread_count=1;
re=avcodec_open2(ac, 0, 0);
注意avcodec_find_decoder中所傳參數。
二:解碼
解碼部分主要涉及兩個重要步驟,上傳和擷取。上傳是将原始資料上傳解碼器進行解碼,擷取是接受解碼好的幀資料。
主要方法:avcodec_send_packet(cc,pkt); avcodec_receive_frame(cc,frame); 第一個參數都是AVCodecContext 解碼上下文。
AVPacket和AVFrame聲明
AVPacket *pkt=av_packet_alloc();
AVFrame *frame=av_frame_alloc();
具體代碼:
AVPacket *pkt=av_packet_alloc();
AVFrame *frame=av_frame_alloc();
long long start=getNowMs();
int frameCount=0;
for(;;)
{
if(getNowMs()-start>=3000)
{
LOGW("now decode fps is %d",frameCount/3);
start=getNowMs();
frameCount=0;
}
int re = av_read_frame(ic,pkt);
if(re != 0)
{
LOGW("讀取到結尾處!");
int pos = 20 * r2d(ic->streams[videoStream]->time_base);
av_seek_frame(ic,videoStream,pos,AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME );
continue;
}
AVCodecContext *cc = vc;
if(pkt->stream_index == audioStream)
cc=ac;
//發送到線程中解碼
re = avcodec_send_packet(cc,pkt);
//清理
int p = pkt->pts;
av_packet_unref(pkt);
if(re != 0)
{
LOGW("avcodec_send_packet failed!");
continue;
}
for(;;)
{
re = avcodec_receive_frame(cc,frame);
if(re !=0)
{
//LOGW("avcodec_receive_frame failed!");
break;
}
LOGW("avcodec_receive_frame %lld",frame->pts);
if (cc == vc) {
frameCount++;
}
}
}
}else{
LOGW("avformat_open_input %s error", av_err2str(re));
}
這塊要判斷是音頻流還是視訊流,上下文參數不一樣。
frameCount是用于記錄幀數。上面使用的線程數是1,三秒鐘列印一次幀數:
日志中看到的fps為100左右 ,這個是在開啟neon下線程數為1的速度。如果測試不支援neon可以替換之前編譯的未開啟neon庫。
此時的Cpu占用情況:
把解碼器的thread_count 修改為8再測試:
此時fps為300左右,解碼速度明顯提升了很多。
再看下Cpu情況:
Cpu的使用率上升到70-80。
三:硬解碼測試
将codec初始化為硬解碼,調用java的mediacodec(反射),需要手動配置虛拟機環境
注意引用的so庫要是支援硬解碼的,相關的編譯參數配置正确,不然會報錯。
看到Cpu的使用率下降到8
再看下fps:
關于軟硬解碼的差別網上有很多詳細的文章,軟解碼使用Cpu進行是以對于處理器來說占用率很大,硬解碼使用非cpu解碼如Gpu等。軟解碼Cpu負載率重性能比硬解碼低,低碼率下品質不如硬解碼。
項目連接配接:編譯好的So庫