Можно ли удалить стартовые коды с помощью NVENC?
Я использую NVENC SDK для кодирования кадров OpenGL и их потоковой передачи по RTSP. NVENC дает мне закодированные данные в виде нескольких блоков NAL. Чтобы транслировать их с Live555, мне нужно найти стартовый код (0x00 0x00 0x01) и удалить его. Я хочу избежать этой операции.
У NVENC есть атрибут sliceOffset, с которым я могу ознакомиться, но он указывает на кусочки, а не на блоки NAL. Он указывает только конец заголовков SPS и PPS, где начинаются фактические данные. Я понимаю, что срез не равен NAL (поправьте меня, если я ошибаюсь). Я уже заставляю отдельные кусочки для закодированных данных.
Возможно ли что-либо из следующего?
- Заставить NVENC кодировать отдельные блоки NAL
- Заставить NVENC указать, где находятся блоки NAL в каждом блоке кодированных данных
- Заставьте Live555 принять параметры последовательности для потоковой передачи
1 ответ
Кажется, есть момент, когда каждый, кто пытается сделать H.264 поверх RTSP/RTP, приходит к этому вопросу. Ну вот мои два цента:
1) Есть понятие блока доступа. Единица доступа - это набор единиц NAL (может быть также и один), которые представляют кодированный кадр. Это тот уровень логики, на котором вы должны работать. Если вы говорите, что хотите, чтобы кодер выдавал вам отдельные блоки NAL, то какое поведение вы ожидаете, когда в результате процедуры кодирования получается несколько блоков NAL из одного необработанного кадра (например, SPS + PPS + кодированное изображение). Тем не менее, существуют способы настройки кодера для уменьшения количества блоков NAL в блоке доступа (например, не включая AUD NAL, не повторяя SPS/PPS, исключая SEI NAL) - с этим знанием вы действительно можете знать, что ожидайте и отчасти заставляйте кодировщик выдавать вам один NAL на кадр (конечно, это будет работать не для всех кадров, но со знанием, имеющимся у вас о декодере, вы можете справиться с этим). Я не эксперт по NVENC API, я только начал его использовать, но по крайней мере, что касается Intel Quick Sync, отключение AUD,SEI и отключение повторения PPS/SPS дало мне примерно 1 NAL на кадр для кадры 2... N.
2) Я не смогу ответить на этот вопрос, так как, как я уже говорил, я не знаком с API, но я сильно сомневаюсь в этом.
3) SPS и PPS должны быть в первом блоке доступа (первый битовый поток, который вы получаете от кодера), и вы можете просто найти нужные NAL в битовом потоке и извлечь их, или может быть специальный вызов API для получить их из кодировщика.
Несмотря на все сказанное, я не думаю, что на самом деле так сложно пробежать поток битов, проанализировать стартовые коды и извлечь модули NAL и передать их в Live555 один за другим. Конечно, если кодер предлагает выводить поток битов в формате AVCC (по сравнению со стартовыми кодами или Приложением B он использует значение длины с чередованием между единицами NAL, так что вы можете просто перейти к следующему, не ища префикс) тогда ты должен использовать это. Когда это просто RTP, достаточно легко реализовать транспорт самостоятельно, поскольку мне не повезло с GStreamer, у которого не было надлежащей поддержки пакетирования FU-A, в случае RTSP издержки транспортной инфраструктуры больше, и это Разумно использовать сторонние библиотеки, такие как Live555.