要解决部分三星手机不支持使用ffmpeg 1080p50 50fps的问题,可以使用以下代码示例来降低视频的分辨率和帧率:
// 导入相关类
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.os.Build;
// 检查设备是否支持指定的编解码器
private boolean isCodecSupported(String codecName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
MediaCodecInfo[] codecs = codecList.getCodecInfos();
for (MediaCodecInfo codec : codecs) {
if (codec.getName().equalsIgnoreCase(codecName)) {
return true;
}
}
}
return false;
}
// 降低视频分辨率和帧率
private void transcodeVideo(String inputFilePath, String outputFilePath) {
// 设置输出视频参数
MediaFormat outputFormat = MediaFormat.createVideoFormat("video/avc", 720, 480); // 设置输出视频分辨率为720x480
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1000000); // 设置输出视频的比特率为1Mbps
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30); // 设置输出视频的帧率为30fps
// 创建MediaCodec进行视频转码
MediaCodec encoder = MediaCodec.createEncoderByType("video/avc");
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
// 创建MediaCodec进行视频解码
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(inputFilePath);
int videoTrackIndex = selectTrack(extractor, false);
extractor.selectTrack(videoTrackIndex);
MediaFormat inputFormat = extractor.getTrackFormat(videoTrackIndex);
int width = inputFormat.getInteger(MediaFormat.KEY_WIDTH);
int height = inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
MediaCodec decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
decoder.configure(inputFormat, null, null, 0);
decoder.start();
// 创建输入输出缓冲区
ByteBuffer[] encoderInputBuffers = encoder.getInputBuffers();
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
ByteBuffer[] decoderOutputBuffers = decoder.getOutputBuffers();
// 处理输入数据
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
boolean isInputEnd = false;
boolean isOutputEnd = false;
while (!isOutputEnd) {
if (!isInputEnd) {
int inputIndex = decoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer inputBuffer = decoderInputBuffers[inputIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isInputEnd = true;
} else {
long presentationTimeUs = extractor.getSampleTime();
decoder.queueInputBuffer(inputIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
}
// 处理输出数据
int outputIndex = decoder.dequeueOutputBuffer(bufferInfo, 10000);
switch (outputIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
decoderOutputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
// 根据输出格式重新配置编码器
MediaFormat newFormat = decoder.getOutputFormat();
encoder.configure(newFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer outputBuffer = decoderOutputBuffers[outputIndex];
int encodeInputIndex = encoder.dequeueInputBuffer(10000);
if (encodeInputIndex >= 0) {
ByteBuffer encodeInputBuffer = encoderInputBuffers[encodeInputIndex];
encodeInputBuffer.clear();
encodeInputBuffer.put(outputBuffer);
encoder.queueInputBuffer(encodeInputIndex, 0, outputBuffer.position(), bufferInfo.presentationTimeUs, bufferInfo.flags);
}
decoder.releaseOutputBuffer(outputIndex, false);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
isOutputEnd = true;
}