No. You are to lock buffer to access data, but to unlock when you are to wait/poll for update.
NV_ENC_LOCK_BITSTREAM lockBitstreamData = { NV_ENC_LOCK_BITSTREAM_VER };
lockBitstreamData.outputBitstream = pEnc->m_vBitstreamOutputBuffer[pEnc->m_iToSend % pEnc->m_nEncoderBuffer];
lockBitstreamData.doNotWait = true;
pEnc->m_nvenc.nvEncUnlockBitstream(pEnc->m_hEncoder, lockBitstreamData.outputBitstream)
while (lockBitstreamData.hwEncodeStatus != 2)
{
uint8_t *pData = (uint8_t *)lockBitstreamData.bitstreamBufferPtr;
if (vPacket.size() < i + 1)
{
vPacket.push_back(std::vector<uint8_t>());
}
vPacket[i].clear();
vPacket[i].insert(vPacket[i].end(), &pData[0], &pData[lockBitstreamData.bitstreamSizeInBytes]);
i++;
}
Is it right?
But I find in the official samples, before read data, it first lock the bitstream:
for (; m_iGot < iEnd; m_iGot++)
{
WaitForCompletionEvent(m_iGot % m_nEncoderBuffer);
NV_ENC_LOCK_BITSTREAM lockBitstreamData = { NV_ENC_LOCK_BITSTREAM_VER };
lockBitstreamData.outputBitstream = vOutputBuffer[m_iGot % m_nEncoderBuffer];
NVENC_API_CALL(m_nvenc.nvEncLockBitstream(m_hEncoder, &lockBitstreamData));
uint8_t *pData = (uint8_t *)lockBitstreamData.bitstreamBufferPtr;
if (vPacket.size() < i + 1)
{
vPacket.push_back(std::vector<uint8_t>());
}
vPacket[i].clear();
vPacket[i].insert(vPacket[i].end(), &pData[0], &pData[lockBitstreamData.bitstreamSizeInBytes]);
i++;
NVENC_API_CALL(m_nvenc.nvEncUnlockBitstream(m_hEncoder, lockBitstreamData.outputBitstream));
if (m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer])
{
NVENC_API_CALL(m_nvenc.nvEncUnmapInputResource(m_hEncoder, m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer]));
m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer] = nullptr;
}
if (m_bMotionEstimationOnly && m_vMappedRefBuffers[m_iGot % m_nEncoderBuffer])
{
NVENC_API_CALL(m_nvenc.nvEncUnmapInputResource(m_hEncoder, m_vMappedRefBuffers[m_iGot % m_nEncoderBuffer]));
m_vMappedRefBuffers[m_iGot % m_nEncoderBuffer] = nullptr;
}
int cnt = lockBitstreamData.numSlices;
}
According to nvenc comment, lock the bitsreambuffer is necessary before reading encoded data.
// NvEncLockBitstream
/**
- \brief Lock output bitstream buffer
- This function is used to lock the bitstream buffer to read the encoded data.
- The client can only access the encoded data by calling this function.
- The pointer to client accessible encoded data is returned in the
- NV_ENC_LOCK_BITSTREAM::bitstreamBufferPtr field. The size of the encoded data
- in the output buffer is returned in the NV_ENC_LOCK_BITSTREAM::bitstreamSizeInBytes
- The NvEncodeAPI interface also returns the output picture type and picture structure
- of the encoded frame in NV_ENC_LOCK_BITSTREAM::pictureType and
- NV_ENC_LOCK_BITSTREAM::pictureStruct fields respectively. If the client has
- set NV_ENC_LOCK_BITSTREAM::doNotWait to 1, the function might return
- ::NV_ENC_ERR_LOCK_BUSY if client is operating in synchronous mode. This is not
- a fatal failure if NV_ENC_LOCK_BITSTREAM::doNotWait is set to 1. In the above case the client can
- retry the function after few milliseconds.
No, you should put the lock and unlock into the while loop.
Use another parameter to record the encodeStatus.
uint32_t encodeStatus = 0;
while(encodeStatus != 2) {
NV_ENC_LOCK_BITSTREAM lockBitstreamData = { NV_ENC_LOCK_BITSTREAM_VER };
lockBitstreamData.outputBitstream = pEnc->m_vBitstreamOutputBuffer[pEnc->m_iToSend % pEnc->m_nEncoderBuffer];
lockBitstreamData.doNotWait = true;
pEnc->m_nvenc.nvEncLockBitstream(pEnc->m_hEncoder, &lockBitstreamData);
uint8_t *pData = (uint8_t *)lockBitstreamData.bitstreamBufferPtr;
if (vPacket.size() < i + 1)
{
vPacket.push_back(std::vector<uint8_t>());
}
vPacket[i].clear();
vPacket[i].insert(vPacket[i].end(), &pData[0], &pData[lockBitstreamData.bitstreamSizeInBytes]);
pEnc->m_nvenc.nvEncUnlockBitstream(pEnc->m_hEncoder, lockBitstreamData.outputBitstream)
encodeStatus = lockBitstreamData.hwEncodeStatus;
}
Then is it right?
But if as this, can the encoder continue encoding other slices?
How do I know EncodeStatus has been updated?
The code should be worked.
If you want each slice buffer, you should consider about NV_ENC_LOCK_BITSTREAM ::sliceOffsets.
Should I be worked under async mode? I run but it doesn’t work as I expect.
I use another thread to read output buffer, but the output is not in accordance with the sliceMode I have set.