我正在使用 MediaMetadataRetriever 将视频帧捕获为位图。
MediaMetadataRetriever mmr;
double fps;
double duration;
long counter = 0;
long incrementer;
String fpsString;
int width;
int height;
int bitrate;
int rotation;
public FrameCollector(String path, String fpsString) {
try {
mmr = new MediaMetadataRetriever();
mmr.setDataSource(path);
width = Integer.valueOf(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
height = Integer.valueOf(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
bitrate = Integer.valueOf(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
String metaRotation = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
rotation = metaRotation == null ? 0 : Integer.parseInt(metaRotation);
Log.i("Rotation ", "rotation:" + rotation);
this.fpsString = fpsString;
fps = Double.valueOf(fpsString);
incrementer = (long) (1000000 / fps);
String stringDuration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
duration = Double.parseDouble(stringDuration) * 1000;
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Bitmap getFirstBitmapFrame() {
try {
Bitmap b = mmr.getFrameAtTime(counter, OPTION_CLOSEST);
return b;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
问题是当 mp4 视频具有 METADATA_KEY_VIDEO_ROTATION == 90 时,帧的宽度和高度已被转置,因此我使用 mediaCodec 从位图制作的视频具有错误的宽度和高度。
public void startEncoding(ArrayList<Bitmap> bitmaps, int rotation, int width, int height, int fps, int bitrate, File outputFile) {
if (rotation > 0) {
mWidth = height;
mHeight = width;
} else {
mWidth = width;
mHeight = height;
}
BIT_RATE = bitrate;
FRAME_RATE = fps;
mOutputFile = outputFile;
String outputFileString;
try {
outputFileString = outputFile.getCanonicalPath();
} catch (IOException e) {
Log.e(TAG, "Unable to get path for " + outputFile);
return;
}
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
if (codecInfo == null) {
Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
return;
}
Log.d(TAG, "found codec: " + codecInfo.getName());
int colorFormat;
try {
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
} catch (Exception e) {
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
}
try {
mediaCodec = MediaCodec.createByCodecName(codecInfo.getName());
} catch (IOException e) {
Log.e(TAG, "Unable to create MediaCodec " + e.getMessage());
return;
}
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
try {
mediaMuxer = new MediaMuxer(outputFileString, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
} catch (IOException e) {
Log.e(TAG, "MediaMuxer creation failed. " + e.getMessage());
return;
}
Log.d(TAG, "Initialization complete. Starting encoder...");
encode(bitmaps);
}
如您所见,我设法通过交换宽度和高度来使其工作,mediaCodec
但输出视频分辨率发生了变化,这是不可接受的。
这是我的问题:
- 有没有办法让 MediaMetadataRetriever 不考虑 METADATA_KEY_VIDEO_ROTATION 值?
- 有没有办法从 mp4 文件中删除此元数据?
- 是否可以
mediaCodec
检测旋转并生成正确的视频输出?
我不能使用FFmpeg
库,我已经尝试使用mp4parser
andjcodec
来更改旋转元数据(或删除它),但它们都没有奏效。
MP4解析器:
Movie inMovie = MovieCreator.build(parameters.getSourceVideoPath());
inMovie.setMatrix(Matrix.ROTATE_0);
BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(inMovie);
WritableByteChannel fc = new RandomAccessFile(
String.format(parameters.getDestinationVideoDirectory() + parameters.get_fileName()), "rw").getChannel();
out.writeContainer(fc);
fc.close();
当我使用 mp4parser 更改元数据时,没有任何反应,并且 MediaMetadataRetriever 的旋转值仍然相同。