EncodeDecodeMux — устройства Samsung — протестировано на S6 Edge и S5

Ссылка: https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java

Я использую приведенный выше код для кодирования/декодирования/мультиплексирования, чтобы сделать видео с более низким разрешением и битрейтом. Он отлично работает на всех разрешениях, включая видео 4k на nexus5, LG g3, one plus.

Но устройства Samsung ведут себя неадекватно.

  • Если я беру видео 4k (3840x2160) в качестве входных данных и хочу снизить его разрешение до 1920x1080, я получаю исключение.

  • Если я беру видео 4k (3840x2160) в качестве входных данных и хочу снизить его разрешение до 1280x720, я все равно получаю исключение.

  • Он отлично работает, если я установил целевое разрешение 640x360.

Я думаю, что это может быть связано с проблемами кодека на устройствах Samsung.

Ниже приведен фрагмент кода

 MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        surfaceReference.set(encoder.createInputSurface());
        encoder.start();

  MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat));
        decoder.configure(inputFormat, surface, null, 0);
decoder.start();

Следующий оператор вызывает исключение

decoder.configure(inputFormat, surface, null, 0);

Ниже приведена трассировка стека

I/ACodec: [OMX.Exynos.AVC.Encoder] Now Executing
03-15 14:35:23.801 25357-26008/com.test I/ACodec:  [] Now uninitialized
03-15 14:35:23.801 25357-26036/com.test I/OMXClient: Using client-side OMX mux.
03-15 14:35:23.811 25357-26036/com.test I/ACodec: can't find wfdsink-exynos-enable
03-15 14:35:23.811 25357-26036/com.test E/ACodec:  configureCodec multi window instance fail  appPid : 25357
03-15 14:35:23.811 25357-26036/com.test E/ACodec: [OMX.Exynos.avc.dec] configureCodec returning error -1021
03-15 14:35:23.811 25357-26036/com.test E/ACodec: signalError(omxError 0x80001001, internalError -1021)
03-15 14:35:23.811 25357-26035/com.test E/MediaCodec: Codec reported err 0xfffffc03, actionCode 0, while in state 3
03-15 14:35:23.811 25357-26008/com.test E/MediaCodec: configure failed with err 0xfffffc03, resetting...
03-15 14:35:23.811 25357-26036/com.test I/ACodec:  [OMX.Exynos.avc.dec] Now uninitialized
03-15 14:35:23.811 25357-26008/com.test I/ACodec:  [] Now uninitialized
03-15 14:35:23.811 25357-26036/com.test I/OMXClient: Using client-side OMX mux.

person Faizan Tariq    schedule 15.03.2016    source источник
comment
Самсунг - это всегда борьба. Удачи!   -  person Muhammad Babar    schedule 15.03.2016
comment
Может быть аппаратное ограничение, например. недостаточная пропускная способность в части кодека для обработки декодирования в 4K и кодирования в 720p. Сообщение об ошибке обычно бесполезно.   -  person fadden    schedule 15.03.2016
comment
Вы нашли решение этой проблемы?   -  person Mateus Zitelli    schedule 16.09.2016


Ответы (1)


По сути, кажется, что у некоторых устройств Samsung могут быть проблемы с декодером Exynos. Я получал почти те же сообщения об ошибках, что и вы. Решение было сложным, но, похоже, решило проблему.

Я заменил эти 2 строки кода:

decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, surface, null, 0);

С помощью этого метода:

private MediaCodec configDecoder(MediaFormat format, Surface surface) {

    if (format == null || surface == null) {
        return null;
    }

    MediaCodec codec;
    String mime = format.getString(MediaFormat.KEY_MIME);
    MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
    MediaCodecInfo[] infos = list.getCodecInfos();

    for (MediaCodecInfo info : infos) {

        CodecCapabilities capabilities;
        boolean formatSupported;

        // does codec support this mime type
        try {
            capabilities = info.getCapabilitiesForType(mime);
        } catch (IllegalArgumentException ignored) {
            continue;
        }

        // does codec support his video format
        try {
            formatSupported = capabilities.isFormatSupported(format);
        } catch (IllegalArgumentException ignored) {
            continue;
        }

        // can we configure it successfully
        if (formatSupported) {
            // try decoder
            try {
                codec = MediaCodec.createByCodecName(info.getName());
            } catch (IOException e) {
                continue;
            }
            try {
                codec.configure(format, surface, null, 0);
            } catch (IllegalArgumentException ignored) {
                // configure() failed
                codec.release();
                continue;
            } catch (IllegalStateException ignored) {
                // configure() failed
                codec.release();
                continue;
            }
            // configure() successful
            return codec;
        }
    } // end of for loop

    // no decoder found
    return null;
}

Обычно для получения кодека достаточно позвонить

MediaCodec.createDecoderByType(mimeType)

or

MediaCodecList.findDecoderForFormat(format)

Но это дает вам только один вариант. Используя метод, описанный выше, у вас есть более точный контроль над тем, какой кодек вы используете. Например, вы можете легко отфильтровать все кодеки Exynos, добавив

if (!info.getName().contains("Exynos"))

или что-то подобное.

В любом случае, надеюсь, это поможет кому-то еще в будущем. Это расстроило меня на несколько дней.

И последнее замечание: мои старые устройства отлично работали со старым кодом, а новый код использует некоторые методы Lollipop и выше, поэтому мое окончательное решение выглядело так:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    decoder = configDecoder(format, surface);
} else {
    decoder = MediaCodec.createDecoderByType(mime);
    decoder.configure(format, surface, null, 0);
}

Наблюдая за выполнением кода, он по-прежнему использует Exynos большую часть времени, но когда по какой-то причине происходит сбой configure(), приятно видеть, как он незаметно переходит к следующему кодеку.

person eatcrayons    schedule 05.03.2017