Menu:
- 1. Introduction
- 2. Video Decoder Configuraion
- 3. QC VideoDecoder Data Structures
- 4. QC VideoDecoder APIs
- 5. Typical Use Case
The QC VideoDecoder node provides APIs for video decoding. It calls vidc library to process video frames based on video hardware. This node supports QNX and HGY Linux/Ubuntu platforms.
| Parameter | Required | Type | Default | Description |
|----------------------|-----------|-------------|------------------------|
| name | true | string | | The Node unique name. |
| id | true | uint32_t | | The Node unique ID. |
| width | true | uint32_t | | Video frame width. |
| height | true | uint32_t | | Video frame height. |
| frameRate | true | uint32_t | | Frames per second. |
| format | false | string | h265 | The image format, options from [nv12, nv12_ubwc] |
| output_format | false | string | nv12 | The output image format, options from [h264, h265] |
| bInputDynamicMode | false | bool | true | Input frame dynamic mode |
| bOutputDynamicMode | false | bool | false | Output frame dynamic mode |
| numInputBufferReq | false | uint32_t | 4 | Number of input buffers |
| numOutputBufferReq | false | uint32_t | 4 | Number of output buffers |
- Example Configurations
{
"static": {
"name": "VDEC0",
"id": 0,
"width": 1920,
"height": 1024,
"frameRate": 30,
"format": "h265",
"output_format": "nv12",
"bInputDynamicMode": true,
"bOutputDynamicMode": false,
"numOutputBufferReq": 4,
"numInputBufferReq": 4,
}
}
# 3. QC VideoDecoder Data Structures
- [VideoFrameDescriptor_t](../include/QC/Infras/Memory/VideoFrameDescriptor.hpp#L50)
## 3.1 The details of VideoFrameDescriptor_t
VideoFrameDescriptor_t contains all the parameters of input and output video frame:
- ImageDescriptor: Image buffer of input video frame
- timestampNs: Timestamp in nanoseconds of frame data
- appMarkData: Mark data of frame data
- frameType: Indication of I/P/B/IDR frame, used by encoder
- frameFlag: Indication of whether some error occurred during decoding this frame
# 4. QC VideoDecoder APIs
- [Initialize the VideoDecoder node](../include/QC/Node/VideoDecoder.hpp#L209)
- [Start the VideoDecoder pipeline](../include/QC/Node/VideoDecoder.hpp#L250)
- [Stop the VideoDecoder pipeline](../include/QC/Node/VideoDecoder.hpp#L251)
- [Submit Input and Output Frames to VideoDecoder](../include/QC/Node/VideoDecoder.hpp#L242)
# 5. Typical Use Case
## 5.1 Typical use case of dynamic mode
- Step 1: Configure parameters
```c++
QCStatus_e ret;
char pName[20] = "VidcDecoder";
uint32_t bufferNum = 4;
uint32_t frameNum = 10;
VideoDecoder vidcDecoder;
VideoDecoder_Config_t vidcDecoderConfig;
vidcDecoderConfig.bInputDynamicMode = true;
vidcDecoderConfig.bOutputDynamicMode = true;
vidcDecoderConfig.numInputBuffer = bufferNum;
vidcDecoderConfig.numOutputBuffer = bufferNum;
QCImageProps_t inputImgProps;
inputImgProps.batchSize = 1;
inputImgProps.width = 1920;
inputImgProps.height = 1024;
inputImgProps.numPlanes = 1;
inputImgProps.planeBufSize[0] = 2961408;
inputImgProps.format = QC_IMAGE_FORMAT_COMPRESSED_H265;
vidcDecoderConfig.width = 1920;
vidcDecoderConfig.height = 1024;
vidcDecoderConfig.inFormat = QC_IMAGE_FORMAT_COMPRESSED_H265;
vidcDecoderConfig.outFormat = QC_IMAGE_FORMAT_NV12;
vidcDecoderConfig.frameRate = 30;
vidcDecoderConfig.pInputBufferList = nullptr;
vidcDecoderConfig.pOutputBufferList = nullptr;
// Define callback:
void VdInputDoneCb( VideoFrameDescriptor_t &inFrameDesc, void *pPrivData ) {}
void VdOutputDoneCb( VideoFrameDescriptor_t &inFrameDesc, void *pPrivData ) {}
void VdEventCb( conVideoCodec_EventType_e eventId, const void *pEvent, void *pPrivData ) {}- Step 2: Allocate buffers
ret = m_imagePool.Init( name, m_nodeId, LOGGER_LEVEL_INFO, m_numOutputBufferReq, m_width,
m_height, m_outFormat, QC_MEMORY_ALLOCATOR_DMA_GPU );
if ( QC_STATUS_OK == ret )
{
ret = m_imagePool.GetBuffers( m_nodeCfg.buffers );
}
- Step 3: Init and Register callback
using std::placeholders::_1;
m_nodeCfg.config = m_dataTree.Dump();
m_nodeCfg.callback = std::bind( &SampleVideoDecoder::OnDoneCb, this, _1 );
ret = m_decoder.Initialize( m_nodeCfg );- Step 4: Submit input/output frame
for ( uint32_t i = 0; i < bufferNum; i++ )
{
inputs[bufferIdx].timestampNs = frameInfo.startTime;
inputs[bufferIdx].appMarkData = i;
ret = inFrameDesc.SetBuffer( QC_NODE_VIDEO_DECODER_INPUT_BUFF_ID, inputs[bufferIdx] );
ASSERT_EQ( QC_STATUS_OK, ret );
// Process the frame
ret = pNodeVide->ProcessFrameDescriptor( inFrameDesc );
ASSERT_EQ( QC_STATUS_OK, ret );
std::unique_lock<std::mutex> outLock( g_OutMutex );
g_OutCondVar.wait( outLock );
// Set up an output buffer for the frame
ret = outFrameDesc.SetBuffer( QC_NODE_VIDEO_DECODER_OUTPUT_BUFF_ID, outputs[bufferIdx] );
ASSERT_EQ( QC_STATUS_OK, ret );
// Process the frame
ret = pNodeVide->ProcessFrameDescriptor( outFrameDesc );
ASSERT_EQ( QC_STATUS_OK, ret );
}- Step 5: Stop and deinitialize the pipeline
ret = vidcDecoder.Stop();
ret = vidcDecoder.Deinit();
for ( auto &output : outputs )
{
ret = bufMgr.Free( output );
ASSERT_EQ( QC_STATUS_OK, ret );
}
for ( auto &input : inputs )
{
ret = bufMgr.Free( input );
ASSERT_EQ( QC_STATUS_OK, ret );
}Reference: