1

我正在使用 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但输出视频分辨率发生了变化,这是不可接受的。

这是我的问题:

  1. 有没有办法让 MediaMetadataRetriever 不考虑 METADATA_KEY_VIDEO_ROTATION 值?
  2. 有没有办法从 mp4 文件中删除此元数据?
  3. 是否可以mediaCodec检测旋转并生成正确的视频输出?

我不能使用FFmpeg库,我已经尝试使用mp4parserandjcodec来更改旋转元数据(或删除它),但它们都没有奏效。

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 的旋转值仍然相同。

4

0 回答 0