Перейти до основного вмісту

Атрибути для кожного кадру.

Деякі камери описують кожен кадр у потоці даних, який його передає: номер послідовності, мітку часу захоплення, назву каналу. Neat може передавати вибраний набір цих значень під час декодування та повертати їх для кадру, якому вони належать, у Sample.

Sample::attributes — це просте відображення рядків у рядки. Neat копіює його, зберігає зв’язок із відповідним кадром і очищає, коли буфер призначення повторно використовується. Він ніколи не розбирає, не об’єднує та не переінтерпретує значення. Ключі та значення повинні бути дійсним форматом UTF-8 і не можуть містити вбудований нульовий байт, оскільки GStreamer не може зберегти їх у рядковому представленні.

Що гарантується?

Обрані заголовки окремих частин багатокомпонентного повідомлення залишаються пов’язаними з відповідними декодованими кадрами через шлях за замовчуванням для HttpMjpegDecodedInput, чергу/гілку та матеріалізовані межі Core Sample-to-GStreamer.

Це вся суть цієї версії. Все, що виходить за її межі, перелічено в розділі Непідтримувані шляхи., і Neat не зможе створити граф, а натомість просто видалить атрибути.

Увімкнення режиму запису

За замовчуванням функція захоплення вимкнена. Щоб її ввімкнути, потрібно вказати назви заголовків, які ви хочете використовувати.

#include "nodes/groups/HttpMjpegDecodedInput.h"

simaai::neat::nodes::groups::HttpMjpegDecodedInputOptions opt;
opt.url = "http://camera.local/stream";
opt.header_capture.headers = {"Image-Index", "Image-Time"};

auto source = simaai::neat::nodes::groups::HttpMjpegDecodedInput(opt);

Перечитуючи їх:

simaai::neat::Sample sample;
if (run.pull(1000, sample) == simaai::neat::PullStatus::Ok) {
const auto it = sample.attributes.find("image-index");
if (it != sample.attributes.end()) {
// it->second is the value this frame was sent with.
}
}

Те саме відбувається в Python, де attributes є динамічною структурою даних — призначення елементів впливає на основний Sample, і призначення словника замінює його вміст:

import pyneat

opt = pyneat.HttpMjpegDecodedInputOptions()
opt.url = "http://camera.local/stream"
opt.header_capture.headers = ["Image-Index", "Image-Time"]
source = pyneat.groups.http_mjpeg_decoded_input(opt)

# ... later, on a pulled sample:
index = sample.attributes.get("image-index")

sample.attributes["image-index"] = "42" # reaches the Sample
sample.attributes = {"image-time": "..."} # replaces the whole map

Правила для заголовків

Налаштований список є списком дозволених елементів. Порожній список повністю вимикає функцію збору даних і не змінює наявну топологію та поведінку.

ПравилоПоведінка
ВипадокНалаштовані імена та згенеровані ключі приводяться до стандартного вигляду ASCII у нижньому регістрі; порівняння не враховує регістр. Зчитуйте атрибути, використовуючи ключі в нижньому регістрі.
Дублікати в списку дозволених елементів.Згортання після нормалізації.
Заголовок повторюється в межах однієї частини.Останнє значення має пріоритет.
Заголовок відсутній у частині [документа/файлу].Ключ не вказано. Він ніколи не передається з попереднього кадру.
Заголовок присутній, але порожній.Збережено як порожній рядок.
ПробілиОбрізається лише навколишній простір SP/HTAB. Інші значення не переінтерпретуються.
Тип MIMEПоданий Content-Type має бути image/jpeg (допускаються параметри). Якщо його немає, перевірка корисного навантаження JPEG визначає тип частини.
Дані, що містяться в файлі JPEG.Частина має містити рівно одне повне зображення у форматі JPEG, починаючи з SOI і закінчуючи EOI. Обрізані, порожні або з’єднані зображення призводять до помилки в потоці даних.
Неправильний вхідний параметр.Недопустимі імена заголовків, згорнуті рядки заголовків і впровадження символів CR/LF/NUL відхиляються — замість того, щоб їх нормалізували та перетворили на щось, що виглядає безпечно, виникають помилки в потоці даних.

Розрізняйте поняття «відсутній» і «порожній», використовуючи count() / get(), а не перевіряючи наявність порожнього рядка.

Обмеження

Замість обрізання даних, обробка завершується з помилкою, якщо будь-яке з цих значень перевищено:

ОбмеженняЦінність
kMultipartHeaderCaptureMaxHeaders64 обрані назви заголовків
kMultipartHeaderCaptureMaxNameBytes128 байтів на кожне ім’я.
kMultipartHeaderCaptureMaxLineBytes8 кілобайт на рядок заголовка.
kMultipartHeaderCaptureMaxBlockBytes64 кілобайт на блок заголовка частини
Багатокомпонентне зображення у форматі JPEG.64 МіБ на кожну частину MIME

Неправильно сформований список дозволених елементів відхиляється під час створення з помилкою std::invalid_argument.

Непідтримувані шляхи.

Поки ввімкнено захоплення, HttpMjpegDecodedInput відмовляється створювати граф, який містить use_videoconvert, use_videoscale, use_videorate або extra_fragment. Не було доведено, що збереження даних за допомогою цих елементів є ефективним, і краще мати чітку помилку під час створення, ніж метадані, які непомітно зникають у процесі.

Атрибути також не визначаються для вузлів, які створюють новий логічний зразок із кількох вхідних даних — моделей, об’єднань, агрегаторів. Ці вузли не об’єднують атрибути.

Як зберігається зв’язок.

Графи, для яких увімкнено функцію захоплення, використовують приватний внутрішньопроцесний елемент, який аналізує межі частин та заголовки частин в одному скінченному автоматі, тому заголовки частини приєднуються безпосередньо до буфера, який містить її байти; немає жодного додаткового каналу, який би міг спричинити збій. Цей елемент генерує повні, проаналізовані JPEG-кадри, тому jpegparse не вставляється в шлях, для якого увімкнено функцію захоплення. Якщо приєднання вибраних атрибутів не вдається, кадр не передається, і потік повідомляє про помилку.

Під час декодування плагін робить знімки атрибутів кожного прийнятого закодованого зображення та відновлює їх у декодованому вихідному потоці, до якого декодер їх прив’язує — а не до будь-якого наступного вихідного потоку. Кожне прийняте зображення досягає лише одного кінцевого результату, тому перевпорядкування, втрати та повторне використання вихідного пулу не можуть перемістити значення в інший кадр. Механізм не залежить від кодека та транспортного протоколу, що дозволяє в майбутньому розширити його на інші джерела кодування без переробки.

Сумісність

Sample та структури параметрів джерела отримали додаткові поля. Вихідний код, який використовує їх за назвою поля або за допомогою агрегатної ініціалізації, продовжує компілюватися.

Двійкове представлення цих публічних структур змінилося, тому вже створені компоненти необхідно перебудувати. Neat ABI/SOVERSION залишається на рівні 4: версія 0.4.0 ще не випущена, тому всі компоненти ABI-4 перебудовуються та випускаються разом, а не відбувається збільшення версії ABI.

Додавання іншого джерела пізніше.

Шлях декодера є загальним. Нове кодоване джерело повинно лише додати вкладену структуру атрибутів до буфера, який воно передає декодеру; нічого в декодері чи в межах зразка не залежить від конкретного протоколу передачі даних. Те, що все ще належить кожному новому джерелу, це власне правило вилучення даних і власне чітке визначення того, які форми графа воно гарантує.