1、解码流程:
根据FFmpeg中视频解码器的名称找到对应手机硬解码器,如果存在则可以硬解码,
走硬解码流程;不存在就只能走软解码流程。
2、硬解码:
使用MediaCodec直接解码AVpacket,此时需要对AVPacket进行格式过滤,然后
MediaCodec解码后的数据用OpenGL ES渲染出来。
3、软解码:
直接用OpenGL ES 渲染YUV数据。
判断是否支持硬解码,及支持的类型
public class JfVideoSupUtil {
private static Map<String,String> codecMap = new HashMap<>();
static {
codecMap.put("h264","video/avc");
}
public static String findVideoCodecName(String ffcodecname){
if (codecMap.containsKey(ffcodecname)){
return codecMap.get(ffcodecname);
}
return "";
}
//@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public static boolean isSupCodec(String ffcodecname){
boolean supVideo = false;
int count = MediaCodecList.getCodecCount();
for (int i = 0;i < count;i++){
String[] types = MediaCodecList.getCodecInfoAt(i).getSupportedTypes();
for (int j = 0;j < types.length;j++){
if (types[j].equals(findVideoCodecName(ffcodecname))) {
supVideo = true;
break;
}
}
if (supVideo){
break;
}
}
return supVideo;
}
}
MediaCodecList.getCodecCount()支持的最低的SDK版本是16,buile.gradle中改 minSdkVersion 16
供C++层调用,传入codecname;
/**
*
* @param ffcodecname
* @return
*/
public boolean onCallIsSupCodec(String ffcodecname){
JfLog.d("ffcodecname == " + ffcodecname);
return JfVideoSupUtil.isSupCodec(ffcodecname);
}
检测是否可以硬解码
宏定义硬解码、软解码
#define CODEC_YUV 0
#define CODEC_MEDIACODEC 1
const char *codecName = ((const AVCodec*) video->pVCodecCtx->codec)->name;
if (supMediaCodec = callJava->onCallIsSupCodec(codecName)){
LOGD("当前设备支持硬解码当前视频");
}
if (supMediaCodec){
video->codectype = CODEC_MEDIACODEC;
}