65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 Intel® RealSense™ SDK 中录制和回放流式传输序列

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2015 年 10 月 27 日

CPOL

4分钟阅读

viewsIcon

19579

Intel® RealSense™ SDK 为开发人员提供了一项新功能,可以将摄像机流序列录制到磁盘文件以供将来播放。此功能在调试和故障排除应用程序中的摄像机问题时非常有用。

Intel® RealSense™ SDK 为开发人员提供了一项新功能,可以将摄像机流序列录制到磁盘文件以供将来播放。此功能在调试和故障排除应用程序中的摄像机问题时非常有用。

将原始彩色和深度流录制到磁盘文件会对主机系统的磁盘 IO 带宽提出挑战。例如,对于彩色配置 RGB32 1920x1080x30fps 和深度配置 640x480x30fps,SDK 需要约 272MB/s 的磁盘 I/O 带宽才能将样本写入磁盘。这使得大多数旋转硬盘和某些慢速 SSD 无法进行此类文件录制作业。

为了解决这个问题,SDK 提供了一项实验性功能,可以在将样本写入磁盘之前对其进行压缩。该功能基于 H.264 编码(仅 I 帧,恒定 QP)彩色样本和无损 Lempel–Ziv–Oberhumer (LZO) 编码深度样本。彩色样本的压缩率约为 10:1,深度样本的压缩率约为 2:1。对于前面的示例,磁盘 I/O 带宽现已降至约 32MB/s。要使用此功能,您需要使用带有最新 Intel Iris 图形驱动程序的 Intel® Iris™ 图形。您可以使用以下注册表设置来控制录制功能

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Intel\RSSDK\FileRecording]
"DisableH264Compression"=dword:0
"H264_QPI"=dword:8
"DisableLZOCompression"=dword:0

默认情况下,H.264 压缩在彩色流上启用,LZO 压缩在所有其他流上启用。H.264 QPI(I 帧量化参数)值范围从 0(压缩最少)到 51(压缩最多)。

重要提示:带有 H.264 压缩的录制文件只能在具有 Intel Iris 图形的系统上播放。

在 C++、C# 或 Java 代码中,使用 `CaptureManager` 实例的 `SetFileName` 来设置文件名和模式(录制或播放)

C++ pxcStatus SetFileName(pxcCHAR *file, pxcBool record);
C# pxcmStatus SetFileName(String file, Boolean record);
Java pxcmStatus SetFileName(string file, boolean record);

参数
file 要播放或要录制的文件的完整路径。
record 如果为 true,则设置录制模式。否则,设置播放模式。

将流序列录制到文件的步骤

  • 使用 `CaptureManager` 实例的 `SetFileName` 函数。
  • 提供文件名并将录制模式设置为 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` 用于帧索引

播放流序列文件的步骤

  • 使用 `CaptureManager` 实例的 `SetFileName` 函数。
  • 提供 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 功能,开发人员可以嵌入代码将摄像机流序列录制到磁盘上的压缩文件中,并在之后进行播放。此功能在调试和故障排除应用程序问题时非常有用。

© . All rights reserved.