Расшифруйте h264 с помощью MediaCodec - PullRequest
0 голосов
/ 08 мая 2018

Я декодирую сырой h264, полученный от Wi-Fi камеры на Android.

Получение необработанных пакетов с использованием сокета и анализ полученных данных для блоков NAL.

У меня также есть модули SPS и PPS (установите как csd-0 и csd-1 в MediaFormat).

Из всех сообщений и информации, которую я читаю онлайн, я все равно не смогу получить, если я передаю декодеру правильные данные.

Это пример результирующего видео при декодировании , которое, кроме нижней части, выглядит нормально.

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

Я анализирую данные h264 на фрагменты, которые начинаются с AUD, каждый блок начинается с AUD и заканчивается, когда начинается другой.

Пример:

[0, 0, 0, 1, 9, 48, 0, 0, 0, 1, 6, 1, 9, 0, 12, 8, 36, 104, 0, 0, 3, 0, 1, -128, 0, 0, 0, 1, 33, -32, 96, 97, 92, -97, 71, 89, -31, 127, -120, 11, 23, ..., 0, 0, 1, -64, ... , -59, 2, -32, 62, -111, -64, 0, 0, 1, -32, 0, 0, -124, -128, 5, 33, 0, 1, -60, -31]

[0, 0, 0, 1, 9, 48, 0, 0, 0, 1, 6, 1, 9, 0, 14, 8, 36, 104, 0, 0, 3, 0, 1, -128, 0, 0, 0, 1, 33, -32, 112, 113, 92, -97, 72, 24, 96, 80, 2, 88, 70, ..., 98, -75, 27, 0, 0, 1, -64, 1, 82, ... , 119, 2, -32, 62, -111, -64, 0, 0, 1, -32, 0, 0, -124, -128, 5, 33, 0, 1, -31, 1]

И каждые несколько кадров я получаю кусок с SPS и PPS

0, 0, 0, 1, 9, 16, 0, 0, 0, 1, 39, SPS, 0, 0, 0, 1, 40, PPS, 0, 0, 0, 1, 6, 0, 13, -128, -89, 89, -128, 8, 117, 0, -89, 89, -128, 8, 117, 64, 1, 9, 0, 16, 8, 36, 104, 0, 0, 3, 0, 1, 6, 1, -60, -128, 0, 0, 0, 1, 37, -72, 1, 0, 1, -1, -16, 13, ... , 108, 60, -83, 101, 0, 0, 1, -32, 0, 0, -124, -128, 5, 33, 0, 3, 25, 65

Насколько я понял, каждый проанализированный «кусок» (начиная с AUD) является модулем доступа, и это то, что я помещаю в буфер и передаю в декодер.

Правильно ли я подаю на вход декодер?

Как мне избавиться от ненужного видео внизу?

Что может вызвать нежелательную часть?

Я также пробовал обрезать части каждого куска, как обрезку начала - [0, 0, 0, 1, 9, 48, 0, 0, 0, 1, 6, 1, 9, 0, 12, 8, 36, 104, 0, 0, 3, 0, 1, -128] и переход только от части 0 ,0 ,0 ,1, 33, но это не имеет большого значения.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Если вы принимаете поток через соединение RTP / UDP, мой опыт показал, что некоторые пакеты будут потеряны по Wi-Fi и могут вызвать некоторые искажения. Если вы попытаетесь использовать RTP через TCP (чередующийся формат), то у вас должен быть очень надежный поток без потери пакетов. Это может показать, связана ли проблема с вашим разбором или с потерей пакета.

0 голосов
/ 08 мая 2018

"Junky part" выглядит как часть заполнения энкодера. Внутренне все видео h264 закодированы с размерами, кратными 16, но отдельно помечают точные размеры, которые должны быть показаны.

Вы не описываете, как отображать декодированные данные на экране, используете ли вы SurfaceTexture для вывода или вручную интерпретируете буфер YUV.

Если вы вручную интерпретируете буферы, вам нужно применить поля кадрирования, как описано здесь: https://developer.android.com/reference/android/media/MediaCodec#data-types

Необходимая часть такова:

Размер видеокадра (до поворота) можно рассчитать следующим образом:

MediaFormat format = decoder.getOutputFormat(…);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
if (format.containsKey("crop-left") && format.containsKey("crop-right")) {
    width = format.getInteger("crop-right") + 1 - format.getInteger("crop-left");
}
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
if (format.containsKey("crop-top") && format.containsKey("crop-bottom")) {
    height = format.getInteger("crop-bottom") + 1 - format.getInteger("crop-top");
}
...