chromium/media/base/android/java/src/test/org/chromium/media/MediaFormatBuilderTest.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.media;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaFormat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;

import org.chromium.base.test.BaseRobolectricTestRunner;

import java.nio.ByteBuffer;

/** Tests for MediaFormatBuilder. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class MediaFormatBuilderTest {
    private static final String VIDEO_DECODER_MIME = MediaFormat.MIMETYPE_VIDEO_AVC;
    private static final int VIDEO_WIDTH = 640;
    private static final int VIDEO_HEIGHT = 480;
    private static final byte[] AVC_SPS_EXAMPLE = {
        0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x0a, (byte) 0xf8, 0x41, (byte) 0xa2
    };
    private static final byte[] AVC_PPS_EXAMPLE = {
        0x00, 0x00, 0x00, 0x01, 0x68, (byte) 0xce, 0x38, (byte) 0x80
    };

    private static final String VIDEO_ENCODER_MIME = MediaFormat.MIMETYPE_VIDEO_AVC;
    private static final int BITRATE_MODE_CBR = 2;
    private static final int VIDEO_ENCODER_BIT_RATE = 16000000;
    private static final int VIDEO_ENCODER_FRAME_RATE = 30;
    private static final int VIDEO_ENCODER_I_FRAME_INTERVAL = 2;
    private static final int VIDEO_ENCODER_COLOR_FORMAT = CodecCapabilities.COLOR_Format24bitBGR888;

    private static final String AUDIO_DECODER_MIME = MediaFormat.MIMETYPE_AUDIO_OPUS;
    private static final int AUDIO_DECODER_SAMPLE_RATE = 48000;
    private static final int AUDIO_DECODER_CHANNEL_COUNT = 2;
    private static final byte[] OPUS_IDENTIFICATION_HEADER = "OpusHead".getBytes();
    private static final byte[] OPUS_PRE_SKIP_NSEC = ByteBuffer.allocate(8).putLong(11971).array();
    private static final byte[] OPUS_SEEK_PRE_ROLL_NSEC =
            ByteBuffer.allocate(8).putLong(80000000).array();

    private static class MockHdrMetadata extends HdrMetadata {
        public boolean was_called;

        @Override
        public void addMetadataToFormat(MediaFormat format) {
            was_called = true;
        }
    }

    @Test
    public void testCreateVideoDecoderWithNoCodecSpecificData() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, null, false);
        assertFalse(format.containsKey("csd-0"));
        assertFalse(format.containsKey("csd-1"));
        assertFalse(format.containsKey("csd-2"));
    }

    @Test
    public void testCreateVideoDecoderWithSingleCodecSpecificDataBuffer() {
        byte[] csd0 = AVC_SPS_EXAMPLE;
        byte[][] csds = {csd0};
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, null, false);
        assertEquals(format.getByteBuffer("csd-0"), ByteBuffer.wrap(csd0));
        assertFalse(format.containsKey("csd-1"));
        assertFalse(format.containsKey("csd-2"));
    }

    @Test
    public void testCreateVideoDecoderWithMultipleCodecSpecificDataBuffers() {
        byte[] csd0 = AVC_SPS_EXAMPLE;
        byte[] csd1 = AVC_PPS_EXAMPLE;
        byte[][] csds = {csd0, csd1};
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, null, false);
        assertEquals(format.getByteBuffer("csd-0"), ByteBuffer.wrap(csd0));
        assertEquals(format.getByteBuffer("csd-1"), ByteBuffer.wrap(csd1));
        assertFalse(format.containsKey("csd-2"));
    }

    @Test
    public void testCreateVideoDecoderWithHdrMetadata() {
        byte[][] csds = {};
        MockHdrMetadata hdrMetadata = new MockHdrMetadata();
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, hdrMetadata, false);
        assertTrue(hdrMetadata.was_called);
    }

    @Test
    public void testCreateVideoDecoderWithAdaptivePlaybackDisabled() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, null, false);
        assertFalse(format.containsKey(MediaFormat.KEY_MAX_WIDTH));
        assertFalse(format.containsKey(MediaFormat.KEY_MAX_HEIGHT));
    }

    @Test
    public void testCreateVideoDecoderWithAdaptivePlaybackEnabled() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createVideoDecoderFormat(
                        VIDEO_DECODER_MIME, VIDEO_WIDTH, VIDEO_HEIGHT, csds, null, true);
        assertTrue(format.containsKey(MediaFormat.KEY_MAX_WIDTH));
        assertTrue(format.containsKey(MediaFormat.KEY_MAX_HEIGHT));
    }

    @Test
    public void testCreateVideoEncoderSetsRelevantKeys() {
        MediaFormat format =
                MediaFormatBuilder.createVideoEncoderFormat(
                        VIDEO_ENCODER_MIME,
                        VIDEO_WIDTH,
                        VIDEO_HEIGHT,
                        BITRATE_MODE_CBR,
                        VIDEO_ENCODER_BIT_RATE,
                        VIDEO_ENCODER_FRAME_RATE,
                        VIDEO_ENCODER_I_FRAME_INTERVAL,
                        VIDEO_ENCODER_COLOR_FORMAT,
                        false);
        assertEquals(format.getInteger(MediaFormat.KEY_BIT_RATE), VIDEO_ENCODER_BIT_RATE);
        assertEquals(format.getInteger(MediaFormat.KEY_BITRATE_MODE), BITRATE_MODE_CBR);
        assertEquals(format.getInteger(MediaFormat.KEY_FRAME_RATE), VIDEO_ENCODER_FRAME_RATE);
        assertEquals(
                format.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL),
                VIDEO_ENCODER_I_FRAME_INTERVAL);
        assertEquals(format.getInteger(MediaFormat.KEY_COLOR_FORMAT), VIDEO_ENCODER_COLOR_FORMAT);
    }

    @Test
    public void testCreateVideoEncoderWithAdaptivePlaybackDisabled() {
        MediaFormat format =
                MediaFormatBuilder.createVideoEncoderFormat(
                        VIDEO_ENCODER_MIME,
                        VIDEO_WIDTH,
                        VIDEO_HEIGHT,
                        BITRATE_MODE_CBR,
                        VIDEO_ENCODER_BIT_RATE,
                        VIDEO_ENCODER_FRAME_RATE,
                        VIDEO_ENCODER_I_FRAME_INTERVAL,
                        VIDEO_ENCODER_COLOR_FORMAT,
                        false);
        assertFalse(format.containsKey(MediaFormat.KEY_MAX_WIDTH));
        assertFalse(format.containsKey(MediaFormat.KEY_MAX_HEIGHT));
    }

    @Test
    public void testCreateVideoEncoderWithAdaptivePlaybackEnabled() {
        MediaFormat format =
                MediaFormatBuilder.createVideoEncoderFormat(
                        VIDEO_ENCODER_MIME,
                        VIDEO_WIDTH,
                        VIDEO_HEIGHT,
                        BITRATE_MODE_CBR,
                        VIDEO_ENCODER_BIT_RATE,
                        VIDEO_ENCODER_FRAME_RATE,
                        VIDEO_ENCODER_I_FRAME_INTERVAL,
                        VIDEO_ENCODER_COLOR_FORMAT,
                        true);
        assertTrue(format.containsKey(MediaFormat.KEY_MAX_WIDTH));
        assertTrue(format.containsKey(MediaFormat.KEY_MAX_HEIGHT));
    }

    @Test
    public void testCreateAudioFormatWithoutAdtsHeader() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createAudioFormat(
                        AUDIO_DECODER_MIME,
                        AUDIO_DECODER_SAMPLE_RATE,
                        AUDIO_DECODER_CHANNEL_COUNT,
                        csds,
                        false);
        assertFalse(format.containsKey(MediaFormat.KEY_IS_ADTS));
    }

    @Test
    public void testCreateAudioFormatWithAdtsHeader() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createAudioFormat(
                        AUDIO_DECODER_MIME,
                        AUDIO_DECODER_SAMPLE_RATE,
                        AUDIO_DECODER_CHANNEL_COUNT,
                        csds,
                        true);
        assertEquals(format.getInteger(MediaFormat.KEY_IS_ADTS), 1);
    }

    @Test
    public void testCreateAudioFormatWithoutCsds() {
        byte[][] csds = {};
        MediaFormat format =
                MediaFormatBuilder.createAudioFormat(
                        AUDIO_DECODER_MIME,
                        AUDIO_DECODER_SAMPLE_RATE,
                        AUDIO_DECODER_CHANNEL_COUNT,
                        csds,
                        false);
        assertFalse(format.containsKey("csd-0"));
        assertFalse(format.containsKey("csd-1"));
        assertFalse(format.containsKey("csd-2"));
    }

    @Test
    public void testCreateAudioFormatWithCsds() {
        byte[] csd0 = OPUS_IDENTIFICATION_HEADER;
        byte[] csd1 = OPUS_PRE_SKIP_NSEC;
        byte[] csd2 = OPUS_SEEK_PRE_ROLL_NSEC;
        byte[][] csds = {csd0, csd1, csd2};
        MediaFormat format =
                MediaFormatBuilder.createAudioFormat(
                        AUDIO_DECODER_MIME,
                        AUDIO_DECODER_SAMPLE_RATE,
                        AUDIO_DECODER_CHANNEL_COUNT,
                        csds,
                        false);
        assertEquals(format.getByteBuffer("csd-0"), ByteBuffer.wrap(csd0));
        assertEquals(format.getByteBuffer("csd-1"), ByteBuffer.wrap(csd1));
        assertEquals(format.getByteBuffer("csd-2"), ByteBuffer.wrap(csd2));
    }
}