Skip to content

Commit edfca47

Browse files
yinwenjieraymondzheng
authored andcommitted
VideoToolbox Hardware Decoding for HEVC enabled
Forbid H.265 vtb-hw-decoding when lower than iOS 11 and unsupported devices
1 parent 44dd409 commit edfca47

File tree

3 files changed

+122
-61
lines changed

3 files changed

+122
-61
lines changed

ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijkplayer/ios/pipeline/IJKVideoToolBoxAsync.m

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ static void dict_set_i32(CFMutableDictionaryRef dict, CFStringRef key,
894894
CFRelease(number);
895895
}
896896

897-
static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(Uint32 format_id, int width, int height, const uint8_t *extradata, int extradata_size, uint32_t atom)
897+
static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(CMVideoCodecType format_id, int width, int height, const uint8_t *extradata, int extradata_size, uint32_t atom)
898898
{
899899
CMFormatDescriptionRef fmt_desc = NULL;
900900
OSStatus status;
@@ -906,8 +906,19 @@ static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(Uint32 format
906906
/* CVPixelAspectRatio dict */
907907
dict_set_i32(par, CFSTR ("HorizontalSpacing"), 0);
908908
dict_set_i32(par, CFSTR ("VerticalSpacing"), 0);
909+
909910
/* SampleDescriptionExtensionAtoms dict */
910-
dict_set_data(atoms, CFSTR ("avcC"), (uint8_t *)extradata, extradata_size);
911+
switch (format_id) {
912+
case kCMVideoCodecType_H264:
913+
dict_set_data(atoms, CFSTR ("avcC"), (uint8_t *)extradata, extradata_size);
914+
break;
915+
case kCMVideoCodecType_HEVC:
916+
dict_set_data(atoms, CFSTR ("hvcC"), (uint8_t *)extradata, extradata_size);
917+
break;
918+
default:
919+
break;
920+
}
921+
911922

912923
/* Extensions dict */
913924
dict_set_string(extensions, CFSTR ("CVImageBufferChromaLocationBottomField"), "left");
@@ -1032,6 +1043,9 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
10321043
int codec = codecpar->codec_id;
10331044
uint8_t* extradata = codecpar->extradata;
10341045

1046+
bool isHevcSupported = false;
1047+
CMVideoCodecType format_id = 0;
1048+
10351049
#if 0
10361050
switch (profile) {
10371051
case FF_PROFILE_H264_HIGH_10:
@@ -1053,19 +1067,39 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
10531067
goto fail;
10541068
}
10551069

1070+
if (extrasize < 7 || extradata == NULL) {
1071+
ALOGI("%s - avcC or hvcC atom data too small or missing", __FUNCTION__);
1072+
goto fail;
1073+
}
1074+
10561075
switch (codec) {
1057-
case AV_CODEC_ID_H264:
1058-
if (extrasize < 7 || extradata == NULL) {
1059-
ALOGI("%s - avcC atom too data small or missing", __FUNCTION__);
1076+
case AV_CODEC_ID_HEVC:
1077+
format_id = kCMVideoCodecType_HEVC;
1078+
if (@available(iOS 11.0, *)) {
1079+
isHevcSupported = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC);
1080+
} else {
1081+
// Fallback on earlier versions
1082+
isHevcSupported = false;
1083+
}
1084+
if (!isHevcSupported) {
10601085
goto fail;
10611086
}
1062-
1063-
if (extradata[0] == 1) {
1064-
if (!validate_avcC_spc(extradata, extrasize, &fmt_desc->max_ref_frames, &sps_level, &sps_profile)) {
1065-
//goto failed;
1066-
}
1067-
if (level == 0 && sps_level > 0)
1068-
level = sps_level;
1087+
break;
1088+
1089+
case AV_CODEC_ID_H264:
1090+
format_id = kCMVideoCodecType_H264;
1091+
break;
1092+
1093+
default:
1094+
goto fail;
1095+
}
1096+
1097+
if (extradata[0] == 1) {
1098+
// if (!validate_avcC_spc(extradata, extrasize, &fmt_desc->max_ref_frames, &sps_level, &sps_profile)) {
1099+
//goto failed;
1100+
// }
1101+
if (level == 0 && sps_level > 0)
1102+
level = sps_level;
10691103

10701104
if (profile == 0 && sps_profile > 0)
10711105
profile = sps_profile;
@@ -1079,10 +1113,10 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
10791113
fmt_desc->convert_3byteTo4byteNALSize = true;
10801114
}
10811115

1082-
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(kCMVideoCodecType_H264, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
1083-
if (fmt_desc->fmt_desc == NULL) {
1084-
goto fail;
1085-
}
1116+
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(format_id, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
1117+
if (fmt_desc->fmt_desc == NULL) {
1118+
goto fail;
1119+
}
10861120

10871121
ALOGI("%s - using avcC atom of size(%d), ref_frames(%d)", __FUNCTION__, extrasize, fmt_desc->max_ref_frames);
10881122
} else {
@@ -1104,20 +1138,16 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
11041138
goto fail;
11051139
}
11061140

1107-
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(kCMVideoCodecType_H264, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
1108-
if (fmt_desc->fmt_desc == NULL) {
1109-
goto fail;
1110-
}
1111-
1112-
av_free(extradata);
1113-
} else {
1114-
ALOGI("%s - invalid avcC atom data", __FUNCTION__);
1115-
goto fail;
1116-
}
1141+
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(format_id, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
1142+
if (fmt_desc->fmt_desc == NULL) {
1143+
goto fail;
11171144
}
1118-
break;
1119-
default:
1145+
1146+
av_free(extradata);
1147+
} else {
1148+
ALOGI("%s - invalid avcC atom data", __FUNCTION__);
11201149
goto fail;
1150+
}
11211151
}
11221152

11231153
fmt_desc->max_ref_frames = FFMAX(fmt_desc->max_ref_frames, 2);

ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijkplayer/ios/pipeline/IJKVideoToolBoxSync.m

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ static void dict_set_i32(CFMutableDictionaryRef dict, CFStringRef key,
761761
CFRelease(number);
762762
}
763763

764-
static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(Uint32 format_id, int width, int height, const uint8_t *extradata, int extradata_size, uint32_t atom)
764+
static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(CMVideoCodecType format_id, int width, int height, const uint8_t *extradata, int extradata_size, uint32_t atom)
765765
{
766766
CMFormatDescriptionRef fmt_desc = NULL;
767767
OSStatus status;
@@ -773,8 +773,19 @@ static CMFormatDescriptionRef CreateFormatDescriptionFromCodecData(Uint32 format
773773
/* CVPixelAspectRatio dict */
774774
dict_set_i32(par, CFSTR ("HorizontalSpacing"), 0);
775775
dict_set_i32(par, CFSTR ("VerticalSpacing"), 0);
776+
776777
/* SampleDescriptionExtensionAtoms dict */
777-
dict_set_data(atoms, CFSTR ("avcC"), (uint8_t *)extradata, extradata_size);
778+
switch (format_id) {
779+
case kCMVideoCodecType_H264:
780+
dict_set_data(atoms, CFSTR ("avcC"), (uint8_t *)extradata, extradata_size);
781+
break;
782+
case kCMVideoCodecType_HEVC:
783+
dict_set_data(atoms, CFSTR ("hvcC"), (uint8_t *)extradata, extradata_size);
784+
break;
785+
default:
786+
break;
787+
}
788+
778789

779790
/* Extensions dict */
780791
dict_set_string(extensions, CFSTR ("CVImageBufferChromaLocationBottomField"), "left");
@@ -896,6 +907,9 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
896907
int codec = codecpar->codec_id;
897908
uint8_t* extradata = codecpar->extradata;
898909

910+
bool isHevcSupported = false;
911+
CMVideoCodecType format_id = 0;
912+
899913
#if 0
900914
switch (profile) {
901915
case FF_PROFILE_H264_HIGH_10:
@@ -917,19 +931,39 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
917931
goto fail;
918932
}
919933

934+
if (extrasize < 7 || extradata == NULL) {
935+
ALOGI("%s - avcC or hvcC atom data too small or missing", __FUNCTION__);
936+
goto fail;
937+
}
938+
920939
switch (codec) {
921-
case AV_CODEC_ID_H264:
922-
if (extrasize < 7 || extradata == NULL) {
923-
ALOGI("%s - avcC atom too data small or missing", __FUNCTION__);
940+
case AV_CODEC_ID_HEVC:
941+
format_id = kCMVideoCodecType_HEVC;
942+
if (@available(iOS 11.0, *)) {
943+
isHevcSupported = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC);
944+
} else {
945+
// Fallback on earlier versions
946+
isHevcSupported = false;
947+
}
948+
if (!isHevcSupported) {
924949
goto fail;
925950
}
926-
927-
if (extradata[0] == 1) {
928-
if (!validate_avcC_spc(extradata, extrasize, &fmt_desc->max_ref_frames, &sps_level, &sps_profile)) {
929-
//goto failed;
930-
}
931-
if (level == 0 && sps_level > 0)
932-
level = sps_level;
951+
break;
952+
953+
case AV_CODEC_ID_H264:
954+
format_id = kCMVideoCodecType_H264;
955+
break;
956+
957+
default:
958+
goto fail;
959+
}
960+
961+
if (extradata[0] == 1) {
962+
// if (!validate_avcC_spc(extradata, extrasize, &fmt_desc->max_ref_frames, &sps_level, &sps_profile)) {
963+
//goto failed;
964+
// }
965+
if (level == 0 && sps_level > 0)
966+
level = sps_level;
933967

934968
if (profile == 0 && sps_profile > 0)
935969
profile = sps_profile;
@@ -943,10 +977,10 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
943977
fmt_desc->convert_3byteTo4byteNALSize = true;
944978
}
945979

946-
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(kCMVideoCodecType_H264, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
947-
if (fmt_desc->fmt_desc == NULL) {
948-
goto fail;
949-
}
980+
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(format_id, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
981+
if (fmt_desc->fmt_desc == NULL) {
982+
goto fail;
983+
}
950984

951985
ALOGI("%s - using avcC atom of size(%d), ref_frames(%d)", __FUNCTION__, extrasize, fmt_desc->max_ref_frames);
952986
} else {
@@ -968,20 +1002,16 @@ static int vtbformat_init(VTBFormatDesc *fmt_desc, AVCodecParameters *codecpar)
9681002
goto fail;
9691003
}
9701004

971-
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(kCMVideoCodecType_H264, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
972-
if (fmt_desc->fmt_desc == NULL) {
973-
goto fail;
974-
}
975-
976-
av_free(extradata);
977-
} else {
978-
ALOGI("%s - invalid avcC atom data", __FUNCTION__);
979-
goto fail;
980-
}
1005+
fmt_desc->fmt_desc = CreateFormatDescriptionFromCodecData(format_id, width, height, extradata, extrasize, IJK_VTB_FCC_AVCC);
1006+
if (fmt_desc->fmt_desc == NULL) {
1007+
goto fail;
9811008
}
982-
break;
983-
default:
1009+
1010+
av_free(extradata);
1011+
} else {
1012+
ALOGI("%s - invalid avcC atom data", __FUNCTION__);
9841013
goto fail;
1014+
}
9851015
}
9861016

9871017
fmt_desc->max_ref_frames = FFMAX(fmt_desc->max_ref_frames, 2);

ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vdec.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,14 @@ static int func_run_sync(IJKFF_Pipenode *node)
112112
opaque->avctx = opaque->decoder->avctx;
113113
switch (opaque->avctx->codec_id) {
114114
case AV_CODEC_ID_H264:
115-
if (ffp->vtb_async)
116-
opaque->context = Ijk_VideoToolbox_Async_Create(ffp, opaque->avctx);
117-
else
118-
opaque->context = Ijk_VideoToolbox_Sync_Create(ffp, opaque->avctx);
115+
case AV_CODEC_ID_HEVC:
116+
if (ffp->vtb_async)
117+
opaque->context = Ijk_VideoToolbox_Async_Create(ffp, opaque->avctx);
118+
else
119+
opaque->context = Ijk_VideoToolbox_Sync_Create(ffp, opaque->avctx);
119120
break;
120121
default:
121-
ALOGI("Videotoolbox-pipeline:open_video_decoder: not H264\n");
122+
ALOGI("Videotoolbox-pipeline:open_video_decoder: not H264 or H265\n");
122123
goto fail;
123124
}
124125
if (opaque->context == NULL) {

0 commit comments

Comments
 (0)