In Android ACodec.cpp setupAVCEncoderParameters
, it reads profile
and level
from msg
(msg->findInt32("profile", &profile)
/msg->findInt32("level", &level)
), the msg
appears to be coming from format
in MediaCodec.configure()
. So, I think we can set profile
/level
manually before MediaCodec.configure()
like below:
format.setInteger(MediaCodec.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
format.setInteger(MediaCodec.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel5);
Of course, I agree it's not a good idea, because we don't konw if our device support the profile/level we set. And also I find most example code didn't set these values at all.
For example:
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // API >= 18
format.setInteger(MediaFormat.KEY_BIT_RATE, calcBitRate());
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10)
mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Maybe they will be set automatically? Will MediaCodec query which profile/level current device support and choose one automatically? If device support more than one profile/level, which one will be selected? The lower level one(baseline, e.g.) or the higher level one(high, e.g.)?
In most cases (as far as I know), it will be baseline, since higher profiles (with B-frames enabled) requires you as a caller to be prepared to handle it correctly (a trivial/naive application might have assumptions that don't hold up with B-frames), and an encoder with B-frames has got higher latency.