從最新版的
FFMPEG
源碼來看,是有相關的videotoolbox
函數在里邊,但是不能確定是否只支持Mac而不支持iOS
.
實踐
編譯FFMPEG
源碼測試
FFMPEG
官網添加videotoolbox
path
直接編譯FFMPEG
源碼,播放h264文件。根據來源于雷霄驊
Demo改編的TSFFMPEG
,使用
AVHWAccel *pp = ff_find_hwaccel(pCodecCtx->codec->id, pCodecCtx->pix_fmt);
返回nil
,也就是找不到支持硬解碼
的解碼庫,不知道是默認編譯庫屏蔽了還是代碼問題。
在官網
Mac/iOS是支持videotoolbox,這是肯定的源碼里都有。
iOS支持編碼不支持解碼?從這里別人失敗記錄可以看出,iOS是支持硬解碼的。但需要直接證據
修改FFMPEG 3.2
的configure
,默認是關閉videotoolbox
重新編譯
使用以下代碼可以測出,只真的支持了。
AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt)
{
AVHWAccel *hwaccel=NULL;
while((hwaccel= av_hwaccel_next(hwaccel))){
NSLog(@"name:%s type:%d id:%u pix:%d",hwaccel->name,hwaccel->type,hwaccel->id,hwaccel->pix_fmt);
if ( hwaccel->id == codec_id
&& hwaccel->pix_fmt == pix_fmt)
return hwaccel;
}
return NULL;
}
日志結果:
2017-01-23 15:14:38.047166 TSKXMoiveDemo[11779:1686079] name:h264_videotoolbox type:0 id:28 pix:334
2017-01-23 15:14:38.047433 TSKXMoiveDemo[11779:1686079] name:mpeg1_videotoolbox type:0 id:1 pix:334
2017-01-23 15:14:38.047558 TSKXMoiveDemo[11779:1686079] name:mpeg2_videotoolbox type:0 id:2 pix:334
2017-01-23 15:14:38.047681 TSKXMoiveDemo[11779:1686079] name:mpeg4_videotoolbox type:0 id:13 pix:334
(lldb)
其中的334是AV_PIX_FMT_VIDEOTOOLBOX
,由此看出是支持iOS
硬解碼的。下來的問題是:怎么用?
關鍵在于AV_PIX_FMT_VIDEOTOOLBOX
這個格式怎么來的,需要研究,最終找到h264_slice.c
里邊,關鍵是這個函數
static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
{
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
CONFIG_H264_D3D11VA_HWACCEL + \
CONFIG_H264_VAAPI_HWACCEL + \
(CONFIG_H264_VDA_HWACCEL * 2) + \
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
CONFIG_H264_VDPAU_HWACCEL)
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
const enum AVPixelFormat *choices = pix_fmts;
int i;
switch (h->ps.sps->bit_depth_luma) {
case 9:
if (CHROMA444(h)) {
if (h->avctx->colorspace == AVCOL_SPC_RGB) {
*fmt++ = AV_PIX_FMT_GBRP9;
} else
*fmt++ = AV_PIX_FMT_YUV444P9;
} else if (CHROMA422(h))
*fmt++ = AV_PIX_FMT_YUV422P9;
else
*fmt++ = AV_PIX_FMT_YUV420P9;
break;
case 10:
if (CHROMA444(h)) {
if (h->avctx->colorspace == AVCOL_SPC_RGB) {
*fmt++ = AV_PIX_FMT_GBRP10;
} else
*fmt++ = AV_PIX_FMT_YUV444P10;
} else if (CHROMA422(h))
*fmt++ = AV_PIX_FMT_YUV422P10;
else
*fmt++ = AV_PIX_FMT_YUV420P10;
break;
case 12:
if (CHROMA444(h)) {
if (h->avctx->colorspace == AVCOL_SPC_RGB) {
*fmt++ = AV_PIX_FMT_GBRP12;
} else
*fmt++ = AV_PIX_FMT_YUV444P12;
} else if (CHROMA422(h))
*fmt++ = AV_PIX_FMT_YUV422P12;
else
*fmt++ = AV_PIX_FMT_YUV420P12;
break;
case 14:
if (CHROMA444(h)) {
if (h->avctx->colorspace == AVCOL_SPC_RGB) {
*fmt++ = AV_PIX_FMT_GBRP14;
} else
*fmt++ = AV_PIX_FMT_YUV444P14;
} else if (CHROMA422(h))
*fmt++ = AV_PIX_FMT_YUV422P14;
else
*fmt++ = AV_PIX_FMT_YUV420P14;
break;
case 8:
#if CONFIG_H264_VDPAU_HWACCEL
*fmt++ = AV_PIX_FMT_VDPAU;
#endif
if (CHROMA444(h)) {
if (h->avctx->colorspace == AVCOL_SPC_RGB)
*fmt++ = AV_PIX_FMT_GBRP;
else if (h->avctx->color_range == AVCOL_RANGE_JPEG)
*fmt++ = AV_PIX_FMT_YUVJ444P;
else
*fmt++ = AV_PIX_FMT_YUV444P;
} else if (CHROMA422(h)) {
if (h->avctx->color_range == AVCOL_RANGE_JPEG)
*fmt++ = AV_PIX_FMT_YUVJ422P;
else
*fmt++ = AV_PIX_FMT_YUV422P;
} else {
#if CONFIG_H264_DXVA2_HWACCEL
*fmt++ = AV_PIX_FMT_DXVA2_VLD;
#endif
#if CONFIG_H264_D3D11VA_HWACCEL
*fmt++ = AV_PIX_FMT_D3D11VA_VLD;
#endif
#if CONFIG_H264_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
#if CONFIG_H264_VDA_HWACCEL
*fmt++ = AV_PIX_FMT_VDA_VLD;
*fmt++ = AV_PIX_FMT_VDA;
#endif
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
if (h->avctx->codec->pix_fmts)
choices = h->avctx->codec->pix_fmts;
else if (h->avctx->color_range == AVCOL_RANGE_JPEG)
*fmt++ = AV_PIX_FMT_YUVJ420P;
else
*fmt++ = AV_PIX_FMT_YUV420P;
}
break;
default:
av_log(h->avctx, AV_LOG_ERROR,
"Unsupported bit depth %d\n", h->ps.sps->bit_depth_luma);
return AVERROR_INVALIDDATA;
}
*fmt = AV_PIX_FMT_NONE;
for (i=0; choices[i] != AV_PIX_FMT_NONE; i++)
if (choices[i] == h->avctx->pix_fmt && !force_callback)
return choices[i];
return ff_thread_get_format(h->avctx, choices);
}
TSFFMPEG
Demo里的,
(lldb) po pCodecCtx->pix_fmt
AV_PIX_FMT_YUV420P
打個日志,看這個AV_PIX_FMT_YUV420P
從哪個case
獲取的
經過幾天查詢資料,放棄研究使用
ffmpeg
iOS硬解碼,代碼可以參考。具體的iOS硬解碼
準備參考ijkplayer
以及vlc
的。
研究ijkplayer
按照這里下載,安裝上
ijkplayer
ijkplayer
是基于FFMPEG
的,從源碼跟文檔上來看,是支持iOS硬解碼的,具體只要設置
[options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];
當這個參數為0跟為1時候,函數調用不用,為1時候,調用ijkplayer
自己的VDA,不知道怎么樣才能調用FFMPEG
的VDA。
測試默認打不開RTSP鏈接
研究kxmovie
代碼于14年末已經不維護了,之后
FFMPEG
才支持硬解碼
的,不過這個工程師使用FFMPEG
最簡單的,可以用來學習,研究。
- 官網的工程編譯方法已經不行了,需要自己生成.a.
研究VLC
學習VLC
的iOS客戶端源碼,VLC
官網關于硬解碼介紹里,并沒有明確說明是否支持iOS
硬解碼(VDA),只說了支持Mac
。
根據這里,VLC
的iOS
leader回答,7.2之后,默認開啟狀態。
VideoToolbox is enabled by default on the master branch and requires both modules you mentioned. It is not enabled on the 2.7-iOS branch and won't be.
You can check whether HW acceleration is enabled or not through VLCKit's debug log, which you can enable on the respective VLCLibrary instance.
剩下就是研究VLC
的硬解碼
是否使用的是FFMPEG
的硬解碼
.
VideoKit
VideoKit
封裝的FFMPEG
拿來賣的,但可以以用來借鑒
運行看到如下日志,說明播放despicable.mp4
可以用來測試,是否使用的硬編碼。
Using hardware acceleration (VIDEOTOOLBOX)
并且cpu利用率內存使用很低20%以內,用kxmoive
同一個視頻,cpu內存均很高。