В Intel® RealSense™ SDK предусмотрена новая возможность для записи последовательности потоков с камеры на диск для дальнейшего воспроизведения. Это очень удобно для отладки и устранения проблем с камерой в приложениях.
Запись необработанных потоков цветного изображения и глубины налагает достаточно высокие требования на пропускную способность ввода-вывода дисков системы. Например, при конфигурации цветного изображения 1920 x 1080, 32 бита RGB, 30 кадров в секунду, и конфигурации канала глубины 640 х 480, 30 кадров в секунду, для записи на диск пропускная способность подсистемы ввода-вывода должна составлять около 272 МБ/с. Это значение превышает максимальную возможную скорость большинства обычных дисков и даже некоторых твердотельных накопителей.
Для решения этой проблемы в SDK реализована экспериментальная функция сжатия изображения перед записью на диск. Функция сжатия реализована на основе алгоритма H.264 (только I-кадры, постоянное значение параметра квантования) для цветного изображения и алгоритма сжатия без потерь LZO (по фамилиям разработчиков: Лемпель, Зив, Оберхумер) для канала глубины. Коэффициент сжатия составляет около 10:1 для цветного изображения и около 2:1 для канала глубины. Необходимая пропускная способность дисковой подсистемы ввода-вывода снижается до 32 МБ/с. Для использования этой функции требуется ГП Intel® Iris™ Graphics с последней версией соответствующего драйвера. Для управления функциями записи используются следующие параметры реестра:
WindowsRegistryEditorVersion 5.00
[HKEY_CURRENT_USER\SOFTWARE\Intel\RSSDK\FileRecording]
"DisableH264Compression"=dword:0
"H264_QPI"=dword:8
"DisableLZOCompression"=dword:0
По умолчанию сжатие H.264 включено для потока цветного изображения, а сжатие LZO включено для всех остальных потоков. Значение QPI алгоритма H.264 (значение параметра квантования I-кадров) задается в диапазоне от 0 (самое слабое сжатие) до 51 (самое сильное сжатие).
Важное примечание. Файл, записанный со сжатием по алгоритму H.264, можно воспроизводить только в системах с ГП IntelIrisGraphics.
В коде C++, C# или Java используйте SetFileName из экземпляра CaptureManager, чтобы задать имя файла и режим (запись или воспроизведение).
C++ pxcStatus SetFileName(pxcCHAR *file, pxcBool record);
C# pxcmStatus SetFileName(String file, Boolean record);
Java pxcmStatus SetFileName(string file, boolean record);
Параметры
file Полный путь к файлу для воспроизведения или для записи.
record При значении true устанавливается режим записи. В противном случае устанавливается режим воспроизведения.
Действия по записи последовательности в файл
- Используйте функцию SetFileName из экземпляра CaptureManager.
- Укажите имя файла и установите значение true для режима записи. Имена файлов устанавливаются без каких-либо ограничений. В режиме записи файл должен быть доступен для записи.
- Измените параметры реестра, если нужно записать поток без сжатия.
Вот образец кода для записи или воспроизведения последовательностей:
void RecordORPlayback(pxcCHAR *file, bool record) { // Create a SenseManager instance PXCSenseManager *sm=PXCSenseManager::CreateInstance(); // Set file recording or playback sm->QueryCaptureManager()->SetFileName(file,record); // Select the color stream sm->EnableStream(PXCCapture.STREAM_TYPE_COLOR,640,480,0); // Initialize and Record 300 frames sm->Init(); for (int i=0;i<300;i++) { // This function blocks until a color sample is ready if (sm->AcquireFrame(true)<PXC_STATUS_NO_ERROR) break; // Retrieve the sample PXCCapture::Sample *sample=sm->QuerySample(); // Work on the image sample->color ... // Go fetching the next sample sm->ReleaseFrame(); } // close down sm->Release(); }
При записи отснятые изображения записываются на диск в том виде, в каком они обрабатываются приложением. Например, если приложение записывает потоки цветного изображения и глубины без выравнивания, то и записанные на диск последовательности будут без выравнивания. Если приложение выравнивает записанные каналы, то и на диск будут записаны выровненные последовательности.
Записанный файл содержит заголовок фиксированного размера со следующей структурой:
struct Header { pxcI32 ID; // PXC_UID('R','S','C','F') pxcI32 fileVersion; // file version pxcI32 firstFrameOffset; // The byte offset to the meta data of the first frame. pxcI32 nstreams; // The number of streams. pxcI64 frameIndexingOffset; // Optional frame indexing offset, zero if not available. PXCSession::CoordinateSystem coordinateSystem; // The coordinate system setting. pxcI32 reserved[26]; };
Кадры изображения любого потока записываются последовательно после заголовка. Началом потока является тег ChunkFrameMetaData, окончанием — тег ChunkFrameData. Между ними может быть несколько кадров конфигурации, описывающих метаданные кадра изображения. Метаданные должны интерпретироваться как изменения (дельта) по сравнению с данными, указанными в заголовке файла. Это позволяет экономить размер, если некоторые метаданные являются общими для всех кадров. Структура кадра:
struct StreamFrame { ChunkFrameMetaData frame_header; // in no defined order ChunkImageMetaData image_meta_data; // if any. // there could be more chunks here. ChunkFrameData frame_data; } frames[]
Структура ChunkFrameMetaData:
struct ChunkFrameMetaData { ChunkId chunkId=CHUNK_FRAME_META_DATA; pxcI32 chunkSize=sizeof(metaData); struct { pxcI32 frameNumber; // frame number in the current stream PXCCapture::StreamType streamType; pxcI64 timeStamp; PXCImage::Option options; } metaData; };
Можно поместить ChunkImageMetaData в кадр со следующей структурой:
struct ChunkImageMetaData { ChunkId chunkId=CHUNK_IMAGE_META_DATA; pxcI32 chunkSize=sizeof(buffer)+sizeof(id); pxcUID id; // meta data identifier pxcBYTE buffer[chunkSize-sizeof(id)]; };
Структура потока без сжатия:
struct ChunkFrameDataUncompressed { ChunkId chunkId=CHUNK_FRAME_DATA; pxcI32 chunkSize=sizeof(imageData); struct { pxcI32 pitches[PXCImage::NUM_OF_PLANES]; pxcBYTE plane0[pitches[0]*height]; ... pxcBYTE planeN[pitches[PXCImage::NUM_OF_PLANES-1]*height]; } imageData };
Структура потока со сжатием:
struct ChunkFrameDataCompressed {
ChunkId chunkId=CHUNK_FRAME_DATA; pxcI32 chunkSize=sizeof(imageData); struct { pxcI32 pitches[PXCImage::NUM_OF_PLANES]; // pitches of uncompressed image planes. enum { H264=0x343632, LZO=0x4f5a4c, } CompressionIdentifier; pxcBYTE compressed_data[]; } imageData };
Модуль записи RealSense™ SDK добавит кадр конфигурации в файл. Кадр конфигурации может содержать любые произвольные данные, заданные посредством идентификатора фрагмента и размера фрагмента. Порядок данных фрагмента в файле не имеет значения, но есть общее правило: если между двумя фрагментами существуют зависимости, то зависимый фрагмент должен находиться в файле после фрагмента, от которого он зависит. Структура ChunkData:
struct ChunkData { enum ChunkId { CHUNK_DEVICEINFO = 1, CHUNK_STREAMINFO = 2, CHUNK_PROPERTIES = 3, CHUNK_PROFILES = 4, CHUNK_SERIALIZEABLE = 5, CHUNK_FRAME_META_DATA = 6, CHUNK_FRAME_DATA = 7, CHUNK_IMAGE_META_DATA = 8, CHUNK_FRAME_INDEXING = 9, }chunkId; // The chunk identifier pxcI32 chunkSize; // The chunk size in bytes-8. pxcBYTE chunkData[chunkSize]; // The chunk data buffer } chunks[];
Некоторые кадры конфигурации, которые должны быть в файлах:
- CHUNK_DEVICEINFO — информация об устройстве
- CHUNK_STREAMINFO — информация о потоке
- CHUNK_PROPERTIES — свойства устройства
- CHUNK_PROFILES — профили потока
- CHUNK_SERIALIZEABLE — калибровка устройства
- CHUNK_FRAME_INDEXING — индексирование кадров
Действия по воспроизведению записанного файла последовательности
- Используйте функцию SetFileName из экземпляра CaptureManager.
- Укажите имя файла в формате rssdk и установите значение false для режима записи.
Для воспроизведения файла SDK сразу же создает экземпляр Capture (с помощью функции QueryCapture), чтобы приложение могло опрашивать возможности записанного содержимого. Можно настроить воспроизведение файлов в SDK следующим образом.
Функция | Значение по умолчанию | Описание |
SetPause | false | Если задано значение true, при воспроизведении возвращается одна и та же выборка текущего кадра. |
SetRealtime | true | Если задано значение true, при воспроизведении возвращается выборка текущего кадра на момент его демонстрации (согласно отметке времени выборки). Если задано значение false, при воспроизведении сразу же возвращается выборка. |
Выберите pause=true и realtime=false, если нужно с точностью найти какие-либо данные кадра при воспроизведении. Вот образец кода с демонстрацией использования SetRealtime и SetPause:
// Create a SenseManager instance
PXCSenseManager* sm = PXCSenseManager::CreateInstance(); // Set file playback name sm->QueryCaptureManager()->SetFileName(filename, false); // Enable stream and Initialize sm->EnableStream(PXCCapture::STREAM_TYPE_COLOR, 0, 0); sm->Init(); // Set realtime=false and pause=true sm->QueryCaptureManager()->SetRealtime(false); sm->QueryCaptureManager()->SetPause(true); // Streaming loop for (int i = 0; i < nframes; i+=3) { // Set to work on every 3rd frame of data sm->QueryCaptureManager()->SetFrameByIndex(i); sm->FlushFrame(); // Ready for the frame to be ready pxcStatus sts = sm->AcquireFrame(true); if (sts < PXC_STATUS_NO_ERROR) break; // Retrieve the sample and work on it. The image is in sample->color. PXCCapture::Sample* sample = sm->QuerySample(); .... // Resume processing the next frame sm->ReleaseFrame(); } // Clean up sm->Release();
Итак, как описано в этой статье, новая функция Intel® RealSense™ SDK дает разработчикам возможность встраивать код для записи последовательностей с камеры на диск со сжатием и для воспроизведения записанных файлов. Это очень удобно для отладки и устранения неполадок в приложениях.