/H264Dec/source/h264bsd_byte_stream.c

http://github.com/mbebenita/Broadway · C · 237 lines · 115 code · 32 blank · 90 comment · 43 complexity · 9cb18fa22ff7453447111b1434b903b0 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*------------------------------------------------------------------------------
  17. Table of contents
  18. 1. Include headers
  19. 2. External compiler flags
  20. 3. Module defines
  21. 4. Local function prototypes
  22. 5. Functions
  23. ExtractNalUnit
  24. ------------------------------------------------------------------------------*/
  25. /*------------------------------------------------------------------------------
  26. 1. Include headers
  27. ------------------------------------------------------------------------------*/
  28. #include "h264bsd_byte_stream.h"
  29. #include "h264bsd_util.h"
  30. /*------------------------------------------------------------------------------
  31. 2. External compiler flags
  32. --------------------------------------------------------------------------------
  33. --------------------------------------------------------------------------------
  34. 3. Module defines
  35. ------------------------------------------------------------------------------*/
  36. #define BYTE_STREAM_ERROR 0xFFFFFFFF
  37. /*------------------------------------------------------------------------------
  38. 4. Local function prototypes
  39. ------------------------------------------------------------------------------*/
  40. /*------------------------------------------------------------------------------
  41. Function name: ExtractNalUnit
  42. Functional description:
  43. Extracts one NAL unit from the byte stream buffer. Removes
  44. emulation prevention bytes if present. The original stream buffer
  45. is used directly and is therefore modified if emulation prevention
  46. bytes are present in the stream.
  47. Stream buffer is assumed to contain either exactly one NAL unit
  48. and nothing else, or one or more NAL units embedded in byte
  49. stream format described in the Annex B of the standard. Function
  50. detects which one is used based on the first bytes in the buffer.
  51. Inputs:
  52. pByteStream pointer to byte stream buffer
  53. len length of the stream buffer (in bytes)
  54. Outputs:
  55. pStrmData stream information is stored here
  56. readBytes number of bytes "consumed" from the stream buffer
  57. Returns:
  58. HANTRO_OK success
  59. HANTRO_NOK error in byte stream
  60. ------------------------------------------------------------------------------*/
  61. u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData,
  62. u32 *readBytes)
  63. {
  64. /* Variables */
  65. u32 i, tmp;
  66. u32 byteCount,initByteCount;
  67. u32 zeroCount;
  68. u8 byte;
  69. u32 hasEmulation = HANTRO_FALSE;
  70. u32 invalidStream = HANTRO_FALSE;
  71. u8 *readPtr, *writePtr;
  72. /* Code */
  73. ASSERT(pByteStream);
  74. ASSERT(len);
  75. ASSERT(len < BYTE_STREAM_ERROR);
  76. ASSERT(pStrmData);
  77. /* byte stream format if starts with 0x000001 or 0x000000 */
  78. if (len > 3 && pByteStream[0] == 0x00 && pByteStream[1] == 0x00 &&
  79. (pByteStream[2]&0xFE) == 0x00)
  80. {
  81. /* search for NAL unit start point, i.e. point after first start code
  82. * prefix in the stream */
  83. zeroCount = byteCount = 2;
  84. readPtr = pByteStream + 2;
  85. /*lint -e(716) while(1) used consciously */
  86. while (1)
  87. {
  88. byte = *readPtr++;
  89. byteCount++;
  90. if (byteCount == len)
  91. {
  92. /* no start code prefix found -> error */
  93. *readBytes = len;
  94. return(HANTRO_NOK);
  95. }
  96. if (!byte)
  97. zeroCount++;
  98. else if ((byte == 0x01) && (zeroCount >= 2))
  99. break;
  100. else
  101. zeroCount = 0;
  102. }
  103. initByteCount = byteCount;
  104. /* determine size of the NAL unit. Search for next start code prefix
  105. * or end of stream and ignore possible trailing zero bytes */
  106. zeroCount = 0;
  107. /*lint -e(716) while(1) used consciously */
  108. while (1)
  109. {
  110. byte = *readPtr++;
  111. byteCount++;
  112. if (!byte)
  113. zeroCount++;
  114. if ( (byte == 0x03) && (zeroCount == 2) )
  115. {
  116. hasEmulation = HANTRO_TRUE;
  117. }
  118. if ( (byte == 0x01) && (zeroCount >= 2 ) )
  119. {
  120. pStrmData->strmBuffSize =
  121. byteCount - initByteCount - zeroCount - 1;
  122. zeroCount -= MIN(zeroCount, 3);
  123. break;
  124. }
  125. else if (byte)
  126. {
  127. if (zeroCount >= 3)
  128. invalidStream = HANTRO_TRUE;
  129. zeroCount = 0;
  130. }
  131. if (byteCount == len)
  132. {
  133. pStrmData->strmBuffSize = byteCount - initByteCount - zeroCount;
  134. break;
  135. }
  136. }
  137. }
  138. /* separate NAL units as input -> just set stream params */
  139. else
  140. {
  141. initByteCount = 0;
  142. zeroCount = 0;
  143. pStrmData->strmBuffSize = len;
  144. hasEmulation = HANTRO_TRUE;
  145. }
  146. pStrmData->pStrmBuffStart = pByteStream + initByteCount;
  147. pStrmData->pStrmCurrPos = pStrmData->pStrmBuffStart;
  148. pStrmData->bitPosInWord = 0;
  149. pStrmData->strmBuffReadBits = 0;
  150. /* return number of bytes "consumed" */
  151. *readBytes = pStrmData->strmBuffSize + initByteCount + zeroCount;
  152. if (invalidStream)
  153. {
  154. return(HANTRO_NOK);
  155. }
  156. /* remove emulation prevention bytes before rbsp processing */
  157. if (hasEmulation)
  158. {
  159. tmp = pStrmData->strmBuffSize;
  160. readPtr = writePtr = pStrmData->pStrmBuffStart;
  161. zeroCount = 0;
  162. for (i = tmp; i--;)
  163. {
  164. if ((zeroCount == 2) && (*readPtr == 0x03))
  165. {
  166. /* emulation prevention byte shall be followed by one of the
  167. * following bytes: 0x00, 0x01, 0x02, 0x03. This implies that
  168. * emulation prevention 0x03 byte shall not be the last byte
  169. * of the stream. */
  170. if ( (i == 0) || (*(readPtr+1) > 0x03) )
  171. return(HANTRO_NOK);
  172. /* do not write emulation prevention byte */
  173. readPtr++;
  174. zeroCount = 0;
  175. }
  176. else
  177. {
  178. /* NAL unit shall not contain byte sequences 0x000000,
  179. * 0x000001 or 0x000002 */
  180. if ( (zeroCount == 2) && (*readPtr <= 0x02) )
  181. return(HANTRO_NOK);
  182. if (*readPtr == 0)
  183. zeroCount++;
  184. else
  185. zeroCount = 0;
  186. *writePtr++ = *readPtr++;
  187. }
  188. }
  189. /* (readPtr - writePtr) indicates number of "removed" emulation
  190. * prevention bytes -> subtract from stream buffer size */
  191. pStrmData->strmBuffSize -= (u32)(readPtr - writePtr);
  192. }
  193. return(HANTRO_OK);
  194. }