Image Support
This page describes how VRS handles content blocks using the Datalayout Conventions.
Prerequisite: Understanding how RecordFormat
works.
Image content blocks can be any of the following different subtypes:
image/raw
The image is stored as a buffer of raw pixels, which might a compacted pixel format such as RAW10, but not compressed using aPixelFormat
.
The exact list of pixel formats grows over time.image/jpg
andimage/png
The image is compressed using jpeg or png compression. The payload of the image content block contains exactly what a jpg or png file would contain.image/video
The image is compressed according to the spec of a video codec standard, such as H.264 or H.265.
Note that the list of supported video codecs is deliberately not part of the spec, but rather, is meant to be implementation dependent, part of a VRS extension. VRS Open Source does not currently provide any implementation.
Additional Image Properties
To be complete, image content blocks, in particular image/raw
content blocks, may require the following complementary properties for an image:
- Resolution
- Stride
- Pixel format
Without these properties, image/raw
images cannot be interpreted safely. These properties can be provided in two distinct ways:
- The image properties can be part of the
RecordFormat
description itself, meaning that the records using thatRecordFormat
will all be using the exact same pixel format.
The content block description might look like this:image/raw/640x480/pixel=grey8
image/raw/640x480/pixel=yuv_i420_split/stride=640
- The image properties can be provided in the datalayout content block found either before the
image
content block in the same record, or in the stream’s last configuration record. When using this method, the properties must be specified using the Datalayout Conventions, which are merely a collection of data types and labels to use in yourDataLayout
to specify properties.
Whichever method you use, VRS collects the image properties for you, so that the RecordFormatStreamPlayer::onImageRead()
callback can directly provide a content block object that you can query for the image format, regardless of how or where it was specified.
Specifying Additional Image Properties
For image/raw
and image/video
images, use a vrs::DataLayoutConventions::ImageSpec
to describe your image in a configuration record, or in a DataLayout
block just before the image content block of your data records.
The DataLayout
fields are:
DataPieceValue<ImageSpecType> width{kImageWidth};
DataPieceValue<ImageSpecType> height{kImageHeight};
DataPieceValue<ImageSpecType> stride{kImageStride};
DataPieceEnum<PixelFormat, ImageSpecType> pixelFormat{kImagePixelFormat};
// For image/video only
DataPieceString codecName{kImageCodecName}; // required
DataPieceValue<ImageSpecType> codecQuality{kImageCodecQuality}; // optional
For image/video
images, specify the keyframe timestamp and the keyframe index, using the following DataLayout
fields:
DataPieceValue<double> keyFrameTimestamp{kImageKeyFrameTimeStamp};
DataPieceValue<ImageSpecType> keyFrameIndex{kImageKeyFrameIndex};
Image Format Differences
image/raw
Without the following properties, image/raw
image content blocks can not be interpreted:
- Required properties: width, height, pixel format.
- Optional properties: stride.
When properties are provided using the Datalayout Conventions, all additional properties must be provided by a single DataLayout
structure in one record. For example, you must not put the pixel format in the configuration record, and then put the image dimensions in the data record. You must either put both the pixel format and the image dimensions in a configuration record's DataLayout
, or you must put them both in a DataLayout
just before the image content block.
image/jpg
and image/png
jpg and png payloads are exactly the same as jpg and png files, which are fully self-described. Therefore, when those image formats are used, properties specified using the Datalayout Conventions are ignored by VRS.
image/video
Support for image/video
images is not ready for open sourcing at this time.
Video image content blocks require additional properties to decode images:
- Required properties: width, height, pixel format, codec name, keyframe timestamp, keyframe index.
- Optional properties: compression quality, which may affect how to decode the image.
Similar to image/raw
images, pixel format and image dimension information must be provided in a single DataLayout
, either in the configuration record or in the data record of the image. Typically, the pixel format and image resolution will not change without a configuration change. Therefore, they are best stored in a configuration record.
On the other hand, the keyframe timestamp and the keyframe index properties change with every frame, and are therefore searched only in a DataLayout
that must be immediately before the image/video
content block.
Reading Images
Image data is received by the RecordFormatStreamPlayer::onImageRead()
callback:
bool onImageRead(
const CurrentRecord& record,
size_t blockIndex,
const ContentBlock& contentBlock);
The RecordFormatStreamPlayer::onDataLayoutRead()
callback happens after the DataLayout
data has been read from disk.
The RecordFormatStreamPlayer::onImageRead()
callback happens before any image data has been read. However, the provided contentBlock
object holds all the image properties, so the following information can be found:
- For all types: the
contentBlock
size is known. That's the size of the buffer you will need to read the image data stored in the image content block. - For
image/raw
images: the pixel format and resolution are defined. - For
image/video
images: the pixel format, resolution, keyframe timestamp, and keyframe index are defined.
The image data itself can be read using the RecordReader
object provided by the CurrentRecord
object. The image is described by an ImageContentBlockSpec
object provided by contentBlock.image()
.
image/raw
images
Allocate or reuse a buffer where you can read the image data. Beware of the image’s stride, which is how it was when the image was saved.
image/jpg
and image/png
images
You will need to read and decode the compressed image data using a standard jpg or png library.
image/video
images
Support for image/video
images is not currently ready for open sourcing. Stay tuned!