LINUX.ORG.RU

Разделитель x0 x0 x0 x1 NAL units

 , , ,


0

1

Ковыряю h264 bitstream, в частности разделитель (start code) границы NAL unit. Никогда не копался в этих битах и байтах, но нужно доковырять кодировщик
Везде пишут (например ), что разделитель, стартовый код (start code), от которого начинается последовательность NAL блоков(units?) это

1 байт - 00000000
2 байт - 00000000
3 байт - 00000000
4 байт - 00000001

Ну или 3 байта бывает, но последний 00000001 должен.
Смотрю потом hex редактором сохраненный поток h264 (в FLV формате)

0000 00 00 00 0E 67 42 C0 29 8C 8D 40 5E 1A 90 0F 08
0010 84 6A 00 00 00 04 68 CE 3C 80 00 00 36 E1 65 B8
0020 00 03 00 00 03 01 0F FF F8 70 B4 50 00 21 7E F8
0030 E0 0C 73 08 7A FF FE 4E 10 CE BF FF F7 08 65 51


и вижу что верно, первые 3 байта - нулевые, а четвертый вовсе не 1 (как предпологалось), а некое другое число (x0E), который указывает длинну NAL unit"a (это я понял эксперементально и вроде это так, если отсчитать от него 14 байтов, то мы перейдем к следующему NAL - PPS), дальше, после x0E уже идет заголовок NAL (x67 - 01100111 - его заголовок, который указывает что NAL ref -3 (биты 11) и NAL type - 7 (SPS) (биты 00111)), дальше идет другой NAL блок - PPS (начитается от x68, 01101000 - тут 11 - 3 (NAL ref) и 01000 - 8 (код PPS)). Три байта нули...

Дальше идет сам IDR (x65 - 01100101 - 00101 - 5 (IDR nal)), тут уже разделитель 2 нулевых байта...

Не понятно с разделителями и не понятно где укзано про длинну.

Также заметил, что мой кодировщик(MediaCodec android) правильно ставит стартовые коды, а именно
00000000
00000000
00000000
00000001

но потом в коде эти коды вырезаются и вместо них устанавливаюся новые, тоже 4 байта
0
0
0
последний байт это длинна NAL блока

Тут тогда понятно, откуда берутся такие разделители. Но не понятно почему ставят длинну, а не просто 00000001 в конце

Может кто знает про разделители?

★★★★

Последнее исправление: gobot (всего исправлений: 1)

Есть разные форматы h264 потока. Не во всех есть маркер границы nal unit. Тебе попался без. В gstreamer есть элемент h264parse, который умеет конвертировать поток в разные форматы

ox55ff ★★★★★
()
Ответ на: комментарий от gobot

Я опять тебе отвечу в стиле gstreamer, т.к. только с ним работал. Смотри на параметры stream-format и alignment. При stream-format=byte-stream,alignment=nal в файле будут маркеры из нулей с единичкой на конце, как ты хочешь. stream-format avc не будет маркера. Я уже ушёл из темы и могу что-то напутать. Вроде alignment не должен отразится на файле на диске. Это внутреннее разбиение на буферы в gstreamer. Запусти команды и скорми файлы из /tmp в свою прогу. Посмотри точно где что. Файлы сырые, без контейнера.

gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! filesink location=/tmp/avc_au.h264

gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! h264parse ! video/x-h264,stream-format=avc,alignment=nal ! filesink location=/tmp/avc_nal.h264

gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! h264parse ! video/x-h264,stream-format=byte-stream,alignment=au ! filesink location=/tmp/byte-stream_au.h264

gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! h264parse ! video/x-h264,stream-format=byte-stream,alignment=nal ! filesink location=/tmp/byte-stream_nal.h264
ox55ff ★★★★★
()

ну судя по интернетам в flv надо ложить не в annex b, а в avcc; не пробовал спеку на flv почитать?

Смотрю потом hex редактором сохраненный поток h264 (в FLV формате)

эм, смотри в h264 формате ffmpeg -i flv -c copy out.h264

hizel ★★★★★
()
Ответ на: комментарий от hizel

also, разделитель, открой еще спеку h264, раздел B и почитай какой в annexb может быть разделитель; B.1.1 Byte stream NAL unit syntax

hizel ★★★★★
()
Ответ на: комментарий от hizel

Да, верно. У меня как раз в коде идет конвертация annex b в avcc. Тогда вопрос закрыт.

Кстати, где указано что в flv нужно avcc? Не нашел. Можно ссылку?

gobot ★★★★
() автор топика
Ответ на: комментарий от anonymous

А, ну понятно. AvcC box это запись в начале файла. А ещё есть avcc формат записи NALU?

Вот что удалось найти

NALU is basic unit.

Then,

annexb format:

([start code] NALU) | ( [start code] NALU) |

avcc format:

([extradata]) | ([length] NALU) | ([length] NALU) |

In annexb, [start code] may be 0x000001 or 0x00000001.

In avcc, the bytes of [length] depends on NALULengthSizeMinusOne in avcc extradata, the value of [length] depends on the size of following NALU and in both annexb and avcc format, the NALUs are no different.


Кое что проясняется. Но не могу найти источника

gobot ★★★★
() автор топика
Ответ на: комментарий от gobot

nalu универсальные

для avcc есть формат extradata где там avcc header описывающий размер длинны и sps pps размеры

anonymous
()
Ответ на: комментарий от anonymous

для avcc есть формат extradata

Это (5.2.4.1.1)? Advanced Video Coding (AVC) file format:

aligned(8) class AVCDecoderConfigurationRecord {
 unsigned int(8) configurationVersion = 1;
 unsigned int(8) AVCProfileIndication;
 unsigned int(8) profile_compatibility;
 unsigned int(8) AVCLevelIndication;
 bit(6) reserved = ‘111111’b;
 unsigned int(2) lengthSizeMinusOne;
 bit(3) reserved = ‘111’b;
 unsigned int(5) numOfSequenceParameterSets;
 for (i=0; i< numOfSequenceParameterSets; i++) {
 unsigned int(16) sequenceParameterSetLength ;
 bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
 }
 unsigned int(8) numOfPictureParameterSets;
 for (i=0; i< numOfPictureParameterSets; i++) {
 unsigned int(16) pictureParameterSetLength;
 bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
 }
 if( profile_idc == 100 || profile_idc == 110 ||
 profile_idc == 122 || profile_idc == 144 )
 {
 bit(6) reserved = ‘111111’b;
 unsigned int(2) chroma_format;
 bit(5) reserved = ‘11111’b;
 unsigned int(3) bit_depth_luma_minus8;
 bit(5) reserved = ‘11111’b;
 unsigned int(3) bit_depth_chroma_minus8;
 unsigned int(8) numOfSequenceParameterSetExt;
 for (i=0; i< numOfSequenceParameterSetExt; i++) {
 unsigned int(16) sequenceParameterSetExtLength;
 bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit;
 }
 }
} 


Этот заголовок я заполняю и отправляю

там avcc header описывающий размер длинны

это lengthSizeMinusOne? У меня это поле статично (byte) 0x03. Или numOfSequenceParameterSets? Тоже всегда (byte) 0x01. Размер длинны чего?

и sps pps размеры

?

gobot ★★★★
() автор топика
Ответ на: комментарий от gobot

А, ну понятно. AvcC box это запись в начале файла. А ещё есть avcc формат записи NALU?

а, ну понятно спеку ты хуем читал, конечно стэковерлоу рулет

алло, смотри в спеку: FLV tags -> VIDEODATA -> AVCVIDEOPACKET

anonymous
()
Ответ на: комментарий от anonymous

И? Что? Я отправляю AVCSequenceHeader (тип 0 в flv). Вопрос в NAL, а не в AVC заголовке

gobot ★★★★
() автор топика
Последнее исправление: gobot (всего исправлений: 1)
Ответ на: комментарий от gobot

lengthSizeMinusOne это размер длинны [length] перед NALU

а length это длинна самого NALU

4-1=3 это длинна в 4 байта

а если у вас NALU 200 байт к примеру, зачем забивать все 4 байта ? тогда lengthSizeMinusOne будет 0, т.е. 1 байт в который помещается длинна NALU

ps странно что такие очевидные вещи которые уже описаны и на том же стековерфолв приходится так разжевывать

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.