1 /*!
2 * \copy
3 * Copyright (c) 2009-2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *
32 * \file nal_encap.c
33 *
34 * \brief NAL pRawNal pData encapsulation
35 *
36 * \date 5/25/2009 Created
37 *
38 *************************************************************************************/
39 #include "nal_encap.h"
40 #include "svc_enc_golomb.h"
41 #include "ls_defines.h"
42 namespace WelsEnc {
43 /*!
44 * \brief load an initialize NAL pRawNal pData
45 */
WelsLoadNal(SWelsEncoderOutput * pEncoderOuput,const int32_t kiType,const int32_t kiNalRefIdc)46 void WelsLoadNal (SWelsEncoderOutput* pEncoderOuput, const int32_t/*EWelsNalUnitType*/ kiType,
47 const int32_t/*EWelsNalRefIdc*/ kiNalRefIdc) {
48 SWelsEncoderOutput* pWelsEncoderOuput = pEncoderOuput;
49 SWelsNalRaw* pRawNal = &pWelsEncoderOuput->sNalList[ pWelsEncoderOuput->iNalIndex ];
50 SNalUnitHeader* sNalUnitHeader = &pRawNal->sNalExt.sNalUnitHeader;
51 const int32_t kiStartPos = (BsGetBitsPos (&pWelsEncoderOuput->sBsWrite) >> 3);
52
53 sNalUnitHeader->eNalUnitType = (EWelsNalUnitType)kiType;
54 sNalUnitHeader->uiNalRefIdc = (EWelsNalRefIdc)kiNalRefIdc;
55 sNalUnitHeader->uiForbiddenZeroBit = 0;
56
57 pRawNal->pRawData = &pWelsEncoderOuput->pBsBuffer[kiStartPos];
58 pRawNal->iStartPos = kiStartPos;
59 pRawNal->iPayloadSize = 0;
60 }
61
62 /*!
63 * \brief unload pRawNal NAL
64 */
WelsUnloadNal(SWelsEncoderOutput * pEncoderOuput)65 void WelsUnloadNal (SWelsEncoderOutput* pEncoderOuput) {
66 SWelsEncoderOutput* pWelsEncoderOuput = pEncoderOuput;
67 int32_t* pIdx = &pWelsEncoderOuput->iNalIndex;
68 SWelsNalRaw* pRawNal = &pWelsEncoderOuput->sNalList[ *pIdx ];
69 const int32_t kiEndPos = (BsGetBitsPos (&pWelsEncoderOuput->sBsWrite) >> 3);
70
71 /* count payload size of pRawNal NAL */
72 pRawNal->iPayloadSize = kiEndPos - pRawNal->iStartPos;
73
74 ++ (*pIdx);
75 }
76
77 /*!
78 * \brief load an initialize NAL pRawNal pData
79 */
WelsLoadNalForSlice(SWelsSliceBs * pSliceBs,const int32_t kiType,const int32_t kiNalRefIdc)80 void WelsLoadNalForSlice (SWelsSliceBs* pSliceBs, const int32_t/*EWelsNalUnitType*/ kiType,
81 const int32_t/*EWelsNalRefIdc*/ kiNalRefIdc) {
82 SWelsNalRaw* pRawNal = &pSliceBs->sNalList[ pSliceBs->iNalIndex ];
83 SNalUnitHeader* sNalUnitHeader = &pRawNal->sNalExt.sNalUnitHeader;
84 SBitStringAux* pBitStringAux = &pSliceBs->sBsWrite;
85 const int32_t kiStartPos = (BsGetBitsPos (pBitStringAux) >> 3);
86
87 sNalUnitHeader->eNalUnitType = (EWelsNalUnitType)kiType;
88 sNalUnitHeader->uiNalRefIdc = (EWelsNalRefIdc)kiNalRefIdc;
89 sNalUnitHeader->uiForbiddenZeroBit = 0;
90
91 pRawNal->pRawData = &pSliceBs->pBsBuffer[kiStartPos];
92 pRawNal->iStartPos = kiStartPos;
93 pRawNal->iPayloadSize = 0;
94 }
95
96 /*!
97 * \brief unload pRawNal NAL
98 */
WelsUnloadNalForSlice(SWelsSliceBs * pSliceBs)99 void WelsUnloadNalForSlice (SWelsSliceBs* pSliceBs) {
100 int32_t* pIdx = &pSliceBs->iNalIndex;
101 SWelsNalRaw* pRawNal = &pSliceBs->sNalList[ *pIdx ];
102 SBitStringAux* pBitStringAux = &pSliceBs->sBsWrite;
103 const int32_t kiEndPos = (BsGetBitsPos (pBitStringAux) >> 3);
104
105 /* count payload size of pRawNal NAL */
106 pRawNal->iPayloadSize = kiEndPos - pRawNal->iStartPos;
107 ++ (*pIdx);
108 }
109
110 /*!
111 * \brief encode NAL with emulation forbidden three bytes checking
112 * \param pDst pDst NAL pData
113 * \param pDstLen length of pDst NAL output
114 * \param annexeb annexeb flag
115 * \param pRawNal pRawNal NAL pData
116 * \return ERRCODE
117 */
118 //TODO 1: refactor the calling of this func in multi-thread
119 //TODO 2: complete the realloc©
WelsEncodeNal(SWelsNalRaw * pRawNal,void * pNalHeaderExt,const int32_t kiDstBufferLen,void * pDst,int32_t * pDstLen)120 int32_t WelsEncodeNal (SWelsNalRaw* pRawNal, void* pNalHeaderExt, const int32_t kiDstBufferLen, void* pDst,
121 int32_t* pDstLen) {
122 const bool kbNALExt = pRawNal->sNalExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_PREFIX
123 || pRawNal->sNalExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_EXT;
124 int32_t iAssumedNeededLength = NAL_HEADER_SIZE + (kbNALExt ? 3 : 0) + pRawNal->iPayloadSize + 1;
125 WELS_VERIFY_RETURN_IF (ENC_RETURN_UNEXPECTED, (iAssumedNeededLength <= 0))
126
127 //since for each 0x000 need a 0x03, so the needed length will not exceed (iAssumeNeedLenth + iAssumeNeedLength/3), here adjust to >>1 to omit division
128 if (kiDstBufferLen < (iAssumedNeededLength + (iAssumedNeededLength >> 1))) {
129 return ENC_RETURN_MEMALLOCERR;
130 //TODO: call the realloc© instead
131 }
132 uint8_t* pDstStart = (uint8_t*)pDst;
133 uint8_t* pDstPointer = pDstStart;
134 uint8_t* pSrcPointer = pRawNal->pRawData;
135 uint8_t* pSrcEnd = pRawNal->pRawData + pRawNal->iPayloadSize;
136 int32_t iZeroCount = 0;
137 int32_t iNalLength = 0;
138 *pDstLen = 0;
139
140 static const uint8_t kuiStartCodePrefix[NAL_HEADER_SIZE] = { 0, 0, 0, 1 };
141 ST32 (pDstPointer, LD32 (&kuiStartCodePrefix[0]));
142 pDstPointer += 4;
143
144 /* NAL Unit Header */
145 *pDstPointer++ = (pRawNal->sNalExt.sNalUnitHeader.uiNalRefIdc << 5) | (pRawNal->sNalExt.sNalUnitHeader.eNalUnitType &
146 0x1f);
147
148 if (kbNALExt) {
149 SNalUnitHeaderExt* sNalExt = (SNalUnitHeaderExt*)pNalHeaderExt;
150
151 /* NAL UNIT Extension Header */
152 *pDstPointer++ = (0x80) |
153 (sNalExt->bIdrFlag << 6);
154
155 *pDstPointer++ = (0x80) |
156 (sNalExt->uiDependencyId << 4);
157
158 *pDstPointer++ = (sNalExt->uiTemporalId << 5) |
159 (sNalExt->bDiscardableFlag << 3) |
160 (0x07);
161 }
162
163 while (pSrcPointer < pSrcEnd) {
164 if (iZeroCount == 2 && *pSrcPointer <= 3) {
165 //add the code 03
166 *pDstPointer++ = 3;
167 iZeroCount = 0;
168 }
169 if (*pSrcPointer == 0) {
170 ++ iZeroCount;
171 } else {
172 iZeroCount = 0;
173 }
174 *pDstPointer++ = *pSrcPointer++;
175 }
176
177 /* count length of NAL Unit */
178 iNalLength = (int32_t) (pDstPointer - pDstStart);
179 if (NULL != pDstLen)
180 *pDstLen = iNalLength;
181
182 return ENC_RETURN_SUCCESS;
183 }
184
185 /*!
186 * \brief write prefix nal
187 */
WelsWriteSVCPrefixNal(SBitStringAux * pBitStringAux,const int32_t kiNalRefIdc,const bool kbIdrFlag)188 int32_t WelsWriteSVCPrefixNal (SBitStringAux* pBitStringAux, const int32_t kiNalRefIdc,
189 const bool kbIdrFlag) {
190 if (0 < kiNalRefIdc) {
191 BsWriteOneBit (pBitStringAux, false/*bStoreRefBasePicFlag*/);
192 BsWriteOneBit (pBitStringAux, false);
193 BsRbspTrailingBits (pBitStringAux);
194 }
195 return 0;
196 }
197
198 } // namespace WelsEnc
199