12

I'm using MediaCodec to encode H.264 video from camera, the problem is, when I move my phone, the output video's quality is very pool, full of mosaic/visual blocks in the video.

Belows are some details:

My encoder bitrate is 500 kbps, and bitrate-mode is BITRATE_MODE_VBR.

I try to change bitrate to 800 kbps, the output video quality improves a lot, and if I change bitrate-mode into BITRATE_MODE_CQ, the output video quality is perfect, but the bitrate will increase up to 1400 kbps.

I want to keep the average bitrate at a low level, e.g. 500 kbps, but allowing the bitrate burst into some bigger bitrate when the phone is moving, e.g. 800 kbps. In iOS VideoToolBox, there is an API kVTCompressionPropertyKey_DataRateLimits to set the average bitrate and the max bitrate, but in Android, how could I achieve that average-max bitrate control?

I noticed that there is a hide "max-bitrate" parameter when configure the MediaCodec, but it has no effect (because Android framework ignore this parameter, see http://androidxref.com/7.1.1_r6/xref/frameworks/av/media/libstagefright/ACodec.cpp#configureCodec), I also noticed that there is a hide “quality” parameter, but it also has no effect.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Piasy
  • 989
  • 13
  • 35
  • How to save processed audio from your library? I can only play it but i want to save that audio also in storage. Please help me out ASAP – Anand Savjani Mar 23 '18 at 17:02
  • How to save processed audio from your library? I can only play it but i want to save that audio also in storage. Please help me out ASAP – Anand Savjani Mar 23 '18 at 17:03

1 Answers1

0

From the android source code, it looks like KEY_MAX_BIT_RATE will set the max bit rate. See below the snapshot from media/java/android/media/MediaCodecInfo.java

private static boolean supportsBitrate(
                Range<Integer> bitrateRange, MediaFormat format) {
            Map<String, Object> map = format.getMap();

            // consider max bitrate over average bitrate for support
            Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
            Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
            if (bitrate == null) {
                bitrate = maxBitrate;
            } else if (maxBitrate != null) {
                bitrate = Math.max(bitrate, maxBitrate);
            }

            if (bitrate != null && bitrate > 0) {
                return bitrateRange.contains(bitrate);
            }

            return true;
        }

I would suggest you to put a higher value depending on video resolution. For example, 1080p video won't look good at 500kbps VBR or CBR.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
manishg
  • 9,520
  • 1
  • 16
  • 19
  • I've tried the `KEY_MAX_BIT_RATE` parameter, actually the key is "max-bitrate", but it has no effect in VBR, and it seems that parameter is discarded by native code, see http://androidxref.com/7.1.1_r6/xref/frameworks/av/media/libstagefright/ACodec.cpp#configureCodec . When I encode 720p video, I set the bitrate as 800 kbps, when I move around the camera, the output video quality is very bad, full of blocks, I want let MediaCodec to increase the bitrate temporarily when the input data increases, and decrease the bitrate to average level when input data decreases, auto. How can I do it? – Piasy Mar 05 '17 at 14:51
  • The video chipset is the source of latency. You are asking it to do too many deltas. – Dominic Cerisano Jul 29 '17 at 20:24