一、硬解不支持Hevc
開(kāi)啟硬解:
[options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];
主要原因:
硬解annex-b格式的視頻幀,需要把a(bǔ)nnex-b轉(zhuǎn)換為Avcc格式卿吐。看ijkplayer源碼,只有H264的轉(zhuǎn)換函數(shù):ff_isom_write_avcc
解決辦法:
對(duì)于H265,需要把a(bǔ)nnex-b轉(zhuǎn)換為Hvcc格式虫埂,發(fā)現(xiàn)有ff_isom_write_hvcc函數(shù),只是沒(méi)有公開(kāi)函數(shù)圃验。只需要加入hevc.h頭文件就可以使用:
IJKVideoToolBoxSync.m 大概1047行
if(codecpar->codec_id==AV_CODEC_ID_HEVC)
ff_isom_write_hvcc(pb, extradata, extrasize,1);
else
ff_isom_write_avcc(pb, extradata, extrasize);
后面的validate_avcC_spc校驗(yàn)函數(shù)掉伏,可以校驗(yàn)H264的,但無(wú)法校驗(yàn)H265澳窑,可以注釋掉斧散,也可以控制只校驗(yàn)H264。
二照捡、硬解不支持動(dòng)態(tài)分辨率
開(kāi)啟硬解支持動(dòng)態(tài)分辨率:
[options setPlayerOptionIntValue:1 forKey:@"videotoolbox-handle-resolution-change"];
IJKVideoToolBoxSync.m 大概690行 decode_video這個(gè)函數(shù)內(nèi)
主要原因:av_packet_get_side_data這個(gè)無(wú)法從AVPacket獲取到對(duì)應(yīng)的extradata值颅湘,猜測(cè)這個(gè)函數(shù)只支持avcc格式,不支持annex-b栗精。
解決辦法:自己實(shí)現(xiàn)獲取extradata功能
我項(xiàng)目的主幀的頭部是帶上sps闯参,pps等信息的。所以我只需從第一個(gè)字節(jié)獲取到主幀標(biāo)志的前一個(gè)字節(jié)悲立,就是對(duì)應(yīng)的extradata鹿寨。具體實(shí)現(xiàn)如下:
static uint8_t s_alBuf[300];
//by alex 讀取extradata videoType:0:H264 1:H265
static uint8_t *al_packet_get_side_data(AVPacket *avpkt,int *size,int videoType){
uint8_t *ptr = avpkt->data;
uint8_t keyFlag = 0x05; //h264主幀
if(videoType==1)
keyFlag = 0x13; //h265主幀
int extraSize = 0;
for(int i=0;i<avpkt->size;i++){
uint8_t s = ptr[i];
if(videoType==1)
s = (s & 0x7E)>>1;
else
s = s & 0x1F;
if(s!=keyFlag){
continue;
}
if(i<=3){
continue;
}
//00000001
if(ptr[i-1]==1&&ptr[i-2]==0&&ptr[i-3]==0&&ptr[i-4]==0){
extraSize = i-4;
break;
}
//000001
if(ptr[i-1]==1&&ptr[i-2]==0&&ptr[i-3]==0){
extraSize = i-3;
break;
}
}
if(extraSize>0){
*size = extraSize;
int bufSize = sizeof(s_alBuf);
bufSize = MIN(bufSize, extraSize);
memset(s_alBuf, 0, sizeof(s_alBuf));
memcpy(s_alBuf, ptr, bufSize);
return s_alBuf;
}
return NULL;
}
IJKVideoToolBoxSync.m 的函數(shù)decode_video修改如下:
大概在decode_video函數(shù)下面10行
if (context->ffp->vtb_handle_resolution_change &&
(context->codecpar->codec_id == AV_CODEC_ID_H264||context->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
//by alex
if(ff_avpacket_is_key(avpkt)){
size_data = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &size_data_size);
if(!size_data){
if(avctx->codec_id == AV_CODEC_ID_HEVC)
size_data = al_packet_get_side_data(avpkt, &size_data_size,1);
else
size_data = al_packet_get_side_data(avpkt, &size_data_size,0);
}
}