Add new output format OUTPUT_NALLENGTHS_PREFIXED
BZ: 156038
this new format structure is like:
[out-band data] + bitstream
[out-band data] is fixed 256 bytes, contains:
'nall' + nalnum + nallength[nalnum]
each one is 4 bytes aligned, out-band data is marked with offset.
VideoEncOutputBuffer structure is also extended to support offset.
Change-Id: I572c547be606afe3f7e658e2ef08507f97ff2f3f
Signed-off-by: Zhao Liang <leo.zhao@intel.com>
diff --git a/videoencoder/VideoEncoderAVC.cpp b/videoencoder/VideoEncoderAVC.cpp
index 0c021dc..85c1315 100644
--- a/videoencoder/VideoEncoderAVC.cpp
+++ b/videoencoder/VideoEncoderAVC.cpp
@@ -326,6 +326,13 @@
break;
}
+ case OUTPUT_NALULENGTHS_PREFIXED: {
+ // Output nalu lengths ahead of bitstream
+ ret = outputNaluLengthsPrefixed(outBuffer);
+ CHECK_ENCODE_STATUS_CLEANUP("outputNaluLengthsPrefixed");
+ break;
+ }
+
default:
LOG_E("Invalid buffer mode\n");
ret = ENCODE_FAIL;
@@ -496,8 +503,8 @@
if (headerSize <= outBuffer->bufferSize) {
memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize);
-// mTotalSizeCopied += headerSize;
-// mOffsetInSeg += headerSize;
+ mTotalSizeCopied += headerSize;
+ mOffsetInSeg += headerSize;
outBuffer->dataSize = headerSize;
outBuffer->remainingSize = 0;
outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
@@ -642,6 +649,84 @@
return ENCODE_SUCCESS;
}
+Encode_Status VideoEncoderAVC::outputNaluLengthsPrefixed(VideoEncOutputBuffer *outBuffer) {
+
+ Encode_Status ret = ENCODE_SUCCESS;
+ uint32_t nalType = 0;
+ uint32_t nalSize = 0;
+ uint32_t nalOffset = 0;
+ uint32_t sizeCopiedHere = 0;
+ const uint32_t NALUINFO_OFFSET = 256;
+ uint32_t nalNum = 0;
+
+ CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
+ LOG_I("outputNaluLengthsPrefixed\n");
+
+ while (1) {
+
+ if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
+ LOG_E("mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere\n");
+ return ENCODE_FAIL;
+ }
+
+ // we need to handle the whole bitstream NAL by NAL
+ ret = getOneNALUnit(
+ (uint8_t *)mCurSegment->buf + mOffsetInSeg,
+ mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
+ CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
+
+ if (nalSize + 4 <= outBuffer->bufferSize - NALUINFO_OFFSET - sizeCopiedHere) {
+ LOG_I("zhaoliang nalSize=%d, nalOffset=%d\n", nalSize, nalOffset);
+
+ memcpy(outBuffer->data + NALUINFO_OFFSET + sizeCopiedHere,
+ (uint8_t *)mCurSegment->buf + mOffsetInSeg, nalSize + nalOffset);
+
+ sizeCopiedHere += nalSize + nalOffset;
+ mTotalSizeCopied += nalSize + nalOffset;
+ mOffsetInSeg += (nalSize + nalOffset);
+
+ } else {
+ outBuffer->dataSize = sizeCopiedHere;
+ // In case the start code is 3-byte length but we use 4-byte for length prefixed
+ // so the remainingSize size may larger than the remaining data size
+ outBuffer->remainingSize = mTotalSize - mTotalSizeCopied + 100;
+ outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
+ LOG_E("Buffer size too small\n");
+ return ENCODE_BUFFER_TOO_SMALL;
+ }
+
+ nalNum ++;
+ uint32_t *nalLength = (uint32_t *) (outBuffer->data + (nalNum+1) * 4);
+
+ *nalLength = nalSize + nalOffset;
+
+ LOG_I("nalLength=%d\n", nalSize + nalOffset);
+
+ // check if all data in current segment has been copied out
+ if (mCurSegment->size == mOffsetInSeg) {
+ if (mCurSegment->next != NULL) {
+ mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+ mOffsetInSeg = 0;
+ } else {
+ LOG_V("End of stream\n");
+ outBuffer->dataSize = sizeCopiedHere;
+ outBuffer->remainingSize = 0;
+ outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+ mCurSegment = NULL;
+ break;
+ }
+ }
+ }
+
+ outBuffer->offset = NALUINFO_OFFSET;
+ uint32_t *nalHead = (uint32_t *) outBuffer->data;
+ LOG_I("zhaoliang nalHead =%x\n", nalHead);
+ *nalHead = 0x4E414C4C; //'nall'
+ *(++nalHead) = nalNum;
+
+ return ENCODE_SUCCESS;
+}
+
Encode_Status VideoEncoderAVC::sendEncodeCommand(EncodeTask *task) {
Encode_Status ret = ENCODE_SUCCESS;
diff --git a/videoencoder/VideoEncoderAVC.h b/videoencoder/VideoEncoderAVC.h
index f33755b..c66acc3 100644
--- a/videoencoder/VideoEncoderAVC.h
+++ b/videoencoder/VideoEncoderAVC.h
@@ -37,6 +37,7 @@
Encode_Status outputCodecData(VideoEncOutputBuffer *outBuffer);
Encode_Status outputOneNALU(VideoEncOutputBuffer *outBuffer, bool startCode);
Encode_Status outputLengthPrefixed(VideoEncOutputBuffer *outBuffer);
+ Encode_Status outputNaluLengthsPrefixed(VideoEncOutputBuffer *outBuffer);
Encode_Status renderMaxSliceSize();
Encode_Status renderAIR();
diff --git a/videoencoder/VideoEncoderBase.cpp b/videoencoder/VideoEncoderBase.cpp
index 52e68a1..47b3f19 100644
--- a/videoencoder/VideoEncoderBase.cpp
+++ b/videoencoder/VideoEncoderBase.cpp
@@ -489,6 +489,7 @@
CHECK_ENCODE_STATUS_CLEANUP("prepareForOutput");
//copy all flags to outBuffer
+ outBuffer->offset = 0;
outBuffer->flag = mCurOutputTask->flag;
outBuffer->type = mCurOutputTask->type;
outBuffer->timeStamp = mCurOutputTask->timestamp;
diff --git a/videoencoder/VideoEncoderDef.h b/videoencoder/VideoEncoderDef.h
index 0b11b05..2b48104 100644
--- a/videoencoder/VideoEncoderDef.h
+++ b/videoencoder/VideoEncoderDef.h
@@ -45,6 +45,7 @@
OUTPUT_ONE_NAL_WITHOUT_STARTCODE = 8,
OUTPUT_LENGTH_PREFIXED = 16,
OUTPUT_CODEDBUFFER = 32,
+ OUTPUT_NALULENGTHS_PREFIXED = 64,
OUTPUT_BUFFER_LAST
} VideoOutputFormat;
@@ -138,7 +139,8 @@
typedef struct {
uint8_t *data;
uint32_t bufferSize; //buffer size
- uint32_t dataSize; //actuall size
+ uint32_t dataSize; //actual size
+ uint32_t offset; //buffer offset
uint32_t remainingSize;
int flag; //Key frame, Codec Data etc
VideoOutputFormat format; //output format