• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&copy
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&copy 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