Декодирование Raw H264 в андроиде?

У меня есть проект, в котором мне было предложено отображать видеопоток в android, поток является сырым H.264, и я подключаюсь к серверу и получаю поток байтов с сервера.

В принципе, мне интересно, есть ли способ отправить необработанные байты в декодер в Android и отобразить его на поверхности?

Мне удалось декодировать H264, завернутый в контейнер mp4, используя новый MediaCodec и MediaExtractor API в android 4.1, к сожалению, я не нашел способ декодировать необработанный файл H264 или поток, используя эти API.

Я понимаю, что одним из способов является компиляция и использование FFmpeg, но я бы предпочел использовать встроенный метод, который может использовать ускорение HW. Я также понимаю, что потоковая передача RTSP поддерживается в android, но это не вариант. Версия для Android не является проблемой.

Ответ 1

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

Итак, вот мой обзор того, как я получил исходное кодированное видео H.264 для работы с использованием класса MediaCodec (http://developer.android.com/reference/android/media/MediaCodec.html).

Используя приведенную выше ссылку, приведен пример получения установки декодера и способа ее использования, вам нужно будет настроить его для декодирования H264 AVC.

Формат H.264 состоит в том, что он состоит из блоков NAL, каждый из которых начинается с префикса запуска из трех байтов со значениями 0x00, 0x00, 0x01, и каждый блок имеет другой тип в зависимости от значения 4-го байта сразу после этих 3 стартовых байтов. Один блок NAL НЕ один кадр в видео, каждый кадр состоит из нескольких блоков NAL.

В основном я написал метод, который находит каждый отдельный блок и передает его в декодер (один блок NAL является стартовым префиксом и любыми байтами там до следующего стартового префикса).

Теперь, если у вас есть установка декодера для декодирования H.264 AVC и у вас есть InputBuffer из декодера, тогда вы готовы к работе. Вам необходимо заполнить этот InputBuffer модулем NAL и передать его обратно в декодер и продолжить делать это для длины потока. Но для выполнения этой работы мне пришлось сначала передать декодер SPS (набор параметров последовательности) NAL Unit. Этот блок имеет байтовое значение 0x67 после стартового префикса (4-й байт), на некоторых устройствах декодер будет сбой, если он не получит это устройство в первую очередь. В основном, пока вы не найдете это устройство, игнорируйте все другие блоки NAL и продолжайте разбор потока до тех пор, пока не получите это устройство, тогда вы можете передать все остальные единицы в декодер.

Некоторые устройства не нуждались в SPS, и некоторые сделали, но лучше сначала перенести его.

Теперь, если у вас была поверхность, которую вы передали декодеру, когда вы ее настроили, тогда, когда он получит достаточное количество блоков NAL для кадра, он должен отображать его на поверхности.

Ответ 2

Вы можете загрузить необработанный H.264 с сервера, а затем предложить его через локальный HTTP-сервер, работающий по телефону, а затем позволить VLC для Android выполнять воспроизведение с этого HTTP-сервера. Вы должны использовать схему VLC http/h264://, чтобы заставить демультиплекс к необработанному H.264 (если вы не заставляете демультиплексор VLC быть не в состоянии распознать поток, даже если тип MIME, возвращаемый HTTP-сервером, правильно установлен). См

https://github.com/rauljim/tgs-android/blob/integrate_record/src/com/tudelft/triblerdroid/first/VideoPlayerActivity.java#L211

для примера о том, как создать намерение, которое запустит VLC.

Примечание. Необработанный H.264, по-видимому, не имеет информации о времени, поэтому VLC будет играть как можно быстрее. Первое внедрение его в MPEGTS будет лучше. Не нашли Android-версию, которая будет делать это еще.

Ответ 3

Вот ресурсы, которые я нашел полезными в аналогичном проекте:

  • Это видео было очень проницательным в понимании того, как MediaCodec обрабатывает сырые потоки h.264 на высоком уровне.
  • Этот поток более подробно описывает обработку SAL/PPS NALUs. Как уже упоминалось выше, вам нужно отделить отдельные блоки NAL с помощью префикса старта, а затем передать оставшиеся данные в MediaCodec.