2016-02-08 3 views
2

Я пытаюсь декодировать поток h.264 с использованием интерфейса MediaCodec от Android. Все работает отлично на моих тестовых устройствах, но на одном клиентском устройстве, к которому у меня нет доступа (Samsung Tab S), есть странные проблемы.Ошибка декодирования MediaCodec h264 на одном устройстве

Когда я декодирую поток, я не отправляю NAL SPS/PPS или исходный кадр. Я просто начинаю толкать данные из потока в реальном времени, нарезанные блоками, заканчивающимися 0x09 NAL, и декодер будет очень легко синхронизироваться без проблем довольно быстро.

Проблема, по крайней мере, с этим устройством заключается в том, что, когда я получаю BufferInfo из декодера, он заявляет, что он декодировал 1413120 байт данных, но размер буфера составляет всего лишь 1382400! Поэтому, конечно, если я даже попытаюсь достать столько данных из буфера, он рухнет.

Видеоролик 1280x720 и декодируется в NV12, поэтому размер буфера в порядке. Описанный размер декодированного выхода не является. Если я заставляю размер 1382400 и конвертировать NV12 в RGB, я получаю почти правильное изображение. Первые 32 строки имеют сильный зеленый цвет, а синий канал сдвинут довольно много. Это означает, что УФ-блок частично декодирован на этом устройстве.

Неужели кто-нибудь сталкивался с подобным вопросом раньше? Я записал необработанный поток h264 с этого конкретного устройства, и он отлично воспроизводится без зеленых блоков или цветовых сдвигов.

Должен ли я настроить SPS/PPS и начальную рамку перед началом потоковой передачи? Поток, похоже, содержит все необходимое, поскольку декодер понимает правильность разрешения, настраивает буферы и декодирует на каждом другом устройстве, которое я тестировал, кроме этого. Поэтому мне просто интересно, есть ли у Samsung что-то особенное.

Другое приложение, декодирующее тот же поток, показывает его без проблем, но насколько я знаю, они используют ffmpeg внутренне, а не MediaCodec. Я предпочел бы использовать встроенные системные кодеки, если это возможно.

Вот пример результата. У вас нет изображения только потока, обратите внимание, что кадр вращается. Компонент Y в зеленой зоне очень хорош, а на белом блоке справа вы можете четко видеть синий сдвиг.

enter image description here

Изменить: Даже если я запустить декодер с блоками SPS/PPS в CSD-0 цвет проблемы сохраняются. Так что это не из-за этого.

Также удалось протестировать точный поток с помощью другого устройства. Нет зеленой полосы, без изменения цвета. Таким образом, это проблема с кодеком в этом конкретном устройстве/модели.

+0

Попробуйте установить SPS/PPS, как мы не можем ожидать, что такое же поведение на всех устройствах. Установите его и проверьте, это может помочь. –

+0

Хм, поэтому для уточнения 'MediaCodec.BufferInfo.size' является 1413120, но емкость' ByteBuffer' составляет всего лишь 1382400? Что содержит выходной файл MediaFormat? – mstorsjo

+0

@mstorsjo Да, 'ByteBuffer' правильно задан на уровне 1382400, но' MediaCodec.BufferInfo.size' говорит 1413120, что составляет 16 строк данных больше, чем должно быть. Выход 'MediaFormat' имеет ширину 1280 и высоту 720, как и следовало ожидать, не проверял никаких других полей. –

ответ

2

У меня были аналогичные проблемы в прошлом (в частности, на устройствах Samsung), и, если я правильно помню, это было связано с отсутствием данных SPS/PPS. Вы должны получать данные SPS/PPS, если хотите получить согласованные результаты.

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

Я не знаю, как вы инстанцировании декодер, но часто люди используют тип пантомимы, как так:

decoder = MediaCodec.createDecoderByType("video/avc"); 

Устройство будет затем выбрать предпочтительный декодер (возможно оборудование).

Вы можете альтернативно экземпляр конкретного декодера следующим образом:

decoder = MediaCodec.createByCodecName("OMX.google.h264.decoder"); 

// OR 

decoder = MediaCodec.createByCodecName("OMX.qcom.video.decoder.avc"); 

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

Вы можете просмотреть список всех доступных кодеков, используя следующий код:

static MediaCodecInfo[] getCodecs() { 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS); 
     return mediaCodecList.getCodecInfos(); 
    } else { 
     int numCodecs = MediaCodecList.getCodecCount(); 
     MediaCodecInfo[] mediaCodecInfo = new MediaCodecInfo[numCodecs]; 

     for (int i = 0; i < numCodecs; i++) { 
      MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); 
      mediaCodecInfo[i] = codecInfo; 
     } 

     return mediaCodecInfo; 
    }  
} 
Смежные вопросы