Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Record video with MediaCodec and MediaMuxer, but the bitrate and framerate are incorrect

I wrote a demo to record a video using MediaCodec and MediaMuxer.

I record a video with my demo and use ffprobe to check the video, the result is as follows:

  Duration: 00:00:06.86, start: 0.000000, bitrate: 723 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 320x240, 619 kb/s, SAR 1:1 DAR 4:3, 30.02 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : VideoHandle
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : SoundHandle

It contains video and audio information, I found the audio properties are the same as I set in the source code, but the video properties are not all right. My video settings source code is as follows:

        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 384000);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, 19);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
    if (VERBOSE) Log.d(TAG, "format: " + format);
    mVideoEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
    mVideoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mInputSurface = mVideoEncoder.createInputSurface();
    mVideoEncoder.start();

The width and height of the video are right but bitrate and framerate are higher than I set in source code. It results in that the video file size is much larger than I expected. Then, I modified my source code to remove audio recording thread and just record the video only. But it didn't make any differences, the bitrate and framerate are also higher. Who can tell me the reason and give me some advices?

And there is another problem. I record a broken video occasionally which can be played by system player, but the begining of the video is just black and normal image displayed after 1 or 2 seconds. I don't know how to upload file in stackoverflow, I can send the broken video file to anyone who need it. Is there someone came with this problem?

ADD: I found another strange thing: My video encoding config:

private int mWidth = 480;
private int mHeight = 848;
private int mVideoBitrate = 1200 * 1000;

    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, 480, 848);

    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 1200000);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);

but the actual video info is:

  Duration: 00:00:06.01, start: 0.000000, bitrate: 6491 kb/s
Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 15 kb/s (default)
Metadata:
  creation_time   : 2015-09-30 15:44:18
  handler_name    : SoundHandle
Stream #0:1(eng): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 480x848, 6484 kb/s, SAR 1:1 DAR 30:53, 16 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
  creation_time   : 2015-09-30 15:44:18
  handler_name    : VideoHandle
like image 869
dragonfly Avatar asked Jun 05 '15 14:06

dragonfly


1 Answers

It looks like your expected frame rate (19fps) doesn't match the actual frame rate (30fps). The encoder is attempting to meet the bit rate requirements for frames submitted at 19fps, but they're coming in faster, so it misses and the actual bit rate is higher. I'm assuming the 30fps value is determined from the actual presentation time stamps in the video file, which are set by the presentation time stamps passed into MediaMuxer. If you want 19fps video, you need to generate time stamps that are (1000/19) milliseconds apart.

If your input video is 30fps, you will need to drop frames during the encoding process to get to 19fps. MediaCodec does not drop frames for you -- it encodes everything you pass in.

I don't know why you'd be getting a broken section at the start of the video.

like image 100
fadden Avatar answered Oct 23 '22 12:10

fadden