OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / hardware / qcom / media / mm-video / vidc / vdec / src / h264_utils.cpp
1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of Code Aurora nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 /*========================================================================
29
30                       O p e n M M
31          V i d e o   U t i l i t i e s
32
33 *//** @file VideoUtils.cpp
34   This module contains utilities and helper routines.
35
36 @par EXTERNALIZED FUNCTIONS
37
38 @par INITIALIZATION AND SEQUENCING REQUIREMENTS
39   (none)
40
41 *//*====================================================================== */
42
43 /* =======================================================================
44
45                      INCLUDE FILES FOR MODULE
46
47 ========================================================================== */
48 #include "h264_utils.h"
49 #include "omx_vdec.h"
50 #include <string.h>
51 #include <stdlib.h>
52
53 /* =======================================================================
54
55                 DEFINITIONS AND DECLARATIONS FOR MODULE
56
57 This section contains definitions for constants, macros, types, variables
58 and other items needed by this module.
59
60 ========================================================================== */
61
62 #define SIZE_NAL_FIELD_MAX  4
63 #define BASELINE_PROFILE 66
64 #define MAIN_PROFILE     77
65 #define HIGH_PROFILE     100
66
67 #define MAX_SUPPORTED_LEVEL 32
68
69
70 RbspParser::RbspParser (const uint8 *_begin, const uint8 *_end)
71 : begin (_begin), end(_end), pos (- 1), bit (0),
72 cursor (0xFFFFFF), advanceNeeded (true)
73 {
74 }
75
76 // Destructor
77 /*lint -e{1540}  Pointer member neither freed nor zeroed by destructor
78  * No problem
79  */
80 RbspParser::~RbspParser () {}
81
82 // Return next RBSP byte as a word
83 uint32 RbspParser::next ()
84 {
85     if (advanceNeeded) advance ();
86     //return static_cast<uint32> (*pos);
87     return static_cast<uint32> (begin[pos]);
88 }
89
90 // Advance RBSP decoder to next byte
91 void RbspParser::advance ()
92 {
93     ++pos;
94     //if (pos >= stop)
95     if (begin + pos == end)
96     {
97         /*lint -e{730}  Boolean argument to function
98          * I don't see a problem here
99          */
100         //throw false;
101         DEBUG_PRINT_LOW("H264Parser-->NEED TO THROW THE EXCEPTION...\n");
102     }
103     cursor <<= 8;
104     //cursor |= static_cast<uint32> (*pos);
105     cursor |= static_cast<uint32> (begin[pos]);
106     if ((cursor & 0xFFFFFF) == 0x000003)
107     {
108         advance ();
109     }
110     advanceNeeded = false;
111 }
112
113 // Decode unsigned integer
114 uint32 RbspParser::u (uint32 n)
115 {
116     uint32 i, s, x = 0;
117     for (i = 0; i < n; i += s)
118     {
119         s = static_cast<uint32>STD_MIN(static_cast<int>(8 - bit),
120             static_cast<int>(n - i));
121         x <<= s;
122
123         x |= ((next () >> ((8 - static_cast<uint32>(bit)) - s)) &
124             ((1 << s) - 1));
125
126         bit = (bit + s) % 8;
127         if (!bit)
128         {
129             advanceNeeded = true;
130         }
131     }
132     return x;
133 }
134
135 // Decode unsigned integer Exp-Golomb-coded syntax element
136 uint32 RbspParser::ue ()
137 {
138     int leadingZeroBits = -1;
139     for (uint32 b = 0; !b; ++leadingZeroBits)
140     {
141         b = u (1);
142     }
143     return ((1 << leadingZeroBits) - 1) +
144         u (static_cast<uint32>(leadingZeroBits));
145 }
146
147 // Decode signed integer Exp-Golomb-coded syntax element
148 int32 RbspParser::se ()
149 {
150     const uint32 x = ue ();
151     if (!x) return 0;
152     else if (x & 1) return static_cast<int32> ((x >> 1) + 1);
153     else return - static_cast<int32> (x >> 1);
154 }
155
156 void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize)
157 {
158     m_rbspBytes = (byte *) calloc(1,inputBufferSize);
159     m_prv_nalu.nal_ref_idc = 0;
160     m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
161 }
162
163 H264_Utils::H264_Utils(): m_height(0),
164                           m_width(0),
165                           m_rbspBytes(NULL),
166                           m_au_data (false)
167 {
168     initialize_frame_checking_environment();
169 }
170
171 H264_Utils::~H264_Utils()
172 {
173 /*  if(m_pbits)
174   {
175     delete(m_pbits);
176     m_pbits = NULL;
177   }
178 */
179   if (m_rbspBytes)
180   {
181     free(m_rbspBytes);
182     m_rbspBytes = NULL;
183   }
184 }
185
186 /***********************************************************************/
187 /*
188 FUNCTION:
189   H264_Utils::initialize_frame_checking_environment
190
191 DESCRIPTION:
192   Extract RBSP data from a NAL
193
194 INPUT/OUTPUT PARAMETERS:
195   None
196
197 RETURN VALUE:
198   boolean
199
200 SIDE EFFECTS:
201   None.
202 */
203 /***********************************************************************/
204 void H264_Utils::initialize_frame_checking_environment()
205 {
206   m_forceToStichNextNAL = false;
207   m_au_data = false;
208   m_prv_nalu.nal_ref_idc = 0;
209   m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED;
210 }
211
212 /***********************************************************************/
213 /*
214 FUNCTION:
215   H264_Utils::extract_rbsp
216
217 DESCRIPTION:
218   Extract RBSP data from a NAL
219
220 INPUT/OUTPUT PARAMETERS:
221   <In>
222     buffer : buffer containing start code or nal length + NAL units
223     buffer_length : the length of the NAL buffer
224     start_code : If true, start code is detected,
225                  otherwise size nal length is detected
226     size_of_nal_length_field: size of nal length field
227
228   <Out>
229     rbsp_bistream : extracted RBSP bistream
230     rbsp_length : the length of the RBSP bitstream
231     nal_unit : decoded NAL header information
232
233 RETURN VALUE:
234   boolean
235
236 SIDE EFFECTS:
237   None.
238 */
239 /***********************************************************************/
240
241 boolean H264_Utils::extract_rbsp(OMX_IN   OMX_U8  *buffer,
242                                  OMX_IN   OMX_U32 buffer_length,
243                                  OMX_IN   OMX_U32 size_of_nal_length_field,
244                                  OMX_OUT  OMX_U8  *rbsp_bistream,
245                                  OMX_OUT  OMX_U32 *rbsp_length,
246                                  OMX_OUT  NALU    *nal_unit)
247 {
248   byte coef1, coef2, coef3;
249   uint32 pos = 0;
250   uint32 nal_len = buffer_length;
251   uint32 sizeofNalLengthField = 0;
252   uint32 zero_count;
253   boolean eRet = true;
254   boolean start_code = (size_of_nal_length_field==0)?true:false;
255
256   DEBUG_PRINT_LOW("extract_rbsp\n");
257
258   if(start_code) {
259     // Search start_code_prefix_one_3bytes (0x000001)
260     coef2 = buffer[pos++];
261     coef3 = buffer[pos++];
262     do {
263       if(pos >= buffer_length)
264       {
265         DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
266         return false;
267       }
268
269       coef1 = coef2;
270       coef2 = coef3;
271       coef3 = buffer[pos++];
272     } while(coef1 || coef2 || coef3 != 1);
273   }
274   else if (size_of_nal_length_field)
275   {
276     /* This is the case to play multiple NAL units inside each access unit*/
277     /* Extract the NAL length depending on sizeOfNALength field */
278     sizeofNalLengthField = size_of_nal_length_field;
279     nal_len = 0;
280     while(size_of_nal_length_field--)
281     {
282       nal_len |= buffer[pos++]<<(size_of_nal_length_field<<3);
283     }
284     if (nal_len >= buffer_length)
285     {
286       DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
287       return false;
288     }
289   }
290
291   if (nal_len > buffer_length)
292   {
293     DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
294     return false;
295   }
296   if(pos + 1 > (nal_len + sizeofNalLengthField))
297   {
298     DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
299     return false;
300   }
301   if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80))
302   {
303     DEBUG_PRINT_ERROR("ERROR: In %s() - line %d", __func__, __LINE__);
304   }
305   nal_unit->nal_ref_idc   = (buffer[pos] & 0x60) >> 5;
306   nal_unit->nalu_type = buffer[pos++] & 0x1f;
307   DEBUG_PRINT_LOW("\n@#@# Pos = %x NalType = %x buflen = %d",pos-1,nal_unit->nalu_type,buffer_length);
308   *rbsp_length = 0;
309
310
311   if( nal_unit->nalu_type == NALU_TYPE_EOSEQ ||
312       nal_unit->nalu_type == NALU_TYPE_EOSTREAM)
313     return (nal_len + sizeofNalLengthField);
314
315   zero_count = 0;
316   while (pos < (nal_len+sizeofNalLengthField))    //similar to for in p-42
317    {
318     if( zero_count == 2 ) {
319       if( buffer[pos] == 0x03 ) {
320         pos ++;
321         zero_count = 0;
322         continue;
323       }
324       if( buffer[pos] <= 0x01 ) {
325         if( start_code ) {
326           *rbsp_length -= 2;
327           pos -= 2;
328           return pos;
329         }
330       }
331       zero_count = 0;
332     }
333     zero_count ++;
334     if( buffer[pos] != 0 )
335       zero_count = 0;
336
337     rbsp_bistream[(*rbsp_length)++] = buffer[pos++];
338   }
339
340   return eRet;
341 }
342
343 /*===========================================================================
344 FUNCTION:
345   H264_Utils::iSNewFrame
346
347 DESCRIPTION:
348   Returns true if NAL parsing successfull otherwise false.
349
350 INPUT/OUTPUT PARAMETERS:
351   <In>
352     buffer : buffer containing start code or nal length + NAL units
353     buffer_length : the length of the NAL buffer
354     start_code : If true, start code is detected,
355                  otherwise size nal length is detected
356     size_of_nal_length_field: size of nal length field
357   <out>
358     isNewFrame: true if the NAL belongs to a differenet frame
359                 false if the NAL belongs to a current frame
360
361 RETURN VALUE:
362   boolean  true, if nal parsing is successful
363            false, if the nal parsing has errors
364
365 SIDE EFFECTS:
366   None.
367 ===========================================================================*/
368 bool H264_Utils::isNewFrame(OMX_IN OMX_U8 *buffer,
369                             OMX_IN OMX_U32 buffer_length,
370                             OMX_IN OMX_U32 size_of_nal_length_field,
371                             OMX_OUT OMX_BOOL &isNewFrame)
372 {
373     NALU nal_unit;
374     uint16 first_mb_in_slice = 0;
375     uint32 numBytesInRBSP = 0;
376     bool eRet = true;
377
378     DEBUG_PRINT_LOW("get_h264_nal_type %p nal_length %d nal_length_field %d\n",
379                  buffer, buffer_length, size_of_nal_length_field);
380
381     if ( false == extract_rbsp(buffer, buffer_length, size_of_nal_length_field,
382                                m_rbspBytes, &numBytesInRBSP, &nal_unit) )
383     {
384         DEBUG_PRINT_ERROR("ERROR: In %s() - extract_rbsp() failed", __func__);
385         isNewFrame = OMX_FALSE;
386         eRet = false;
387     }
388     else
389     {
390       switch (nal_unit.nalu_type)
391       {
392         case NALU_TYPE_IDR:
393         case NALU_TYPE_NON_IDR:
394         {
395           DEBUG_PRINT_LOW("\n Found a AU Boundary %d ",nal_unit.nalu_type);
396           if (m_forceToStichNextNAL)
397           {
398             isNewFrame = OMX_FALSE;
399           }
400           else
401           {
402             RbspParser rbsp_parser(m_rbspBytes, (m_rbspBytes+numBytesInRBSP));
403             first_mb_in_slice = rbsp_parser.ue();
404
405             if((!first_mb_in_slice) || /*(slice.prv_frame_num != slice.frame_num ) ||*/
406                ( (m_prv_nalu.nal_ref_idc != nal_unit.nal_ref_idc) && ( nal_unit.nal_ref_idc * m_prv_nalu.nal_ref_idc == 0 ) ) ||
407                /*( ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) && (nal_unit.nalu_type == NALU_TYPE_IDR)) && (slice.idr_pic_id != slice.prv_idr_pic_id) ) || */
408                ( (m_prv_nalu.nalu_type != nal_unit.nalu_type ) && ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) || (nal_unit.nalu_type == NALU_TYPE_IDR)) ) )
409             {
410               //DEBUG_PRINT_LOW("Found a New Frame due to NALU_TYPE_IDR/NALU_TYPE_NON_IDR");
411               isNewFrame = OMX_TRUE;
412             }
413             else
414             {
415               isNewFrame = OMX_FALSE;
416             }
417           }
418           m_au_data = true;
419           m_forceToStichNextNAL = false;
420           break;
421         }
422         case NALU_TYPE_SPS:
423         case NALU_TYPE_PPS:
424         case NALU_TYPE_SEI:
425         case NALU_TYPE_UNSPECIFIED:
426         case NALU_TYPE_EOSEQ:
427         case NALU_TYPE_EOSTREAM:
428         {
429           DEBUG_PRINT_LOW("\n Non AU boundary NAL %d",nal_unit.nalu_type);
430           if(m_au_data)
431           {
432             isNewFrame = OMX_TRUE;
433             m_au_data = false;
434           }
435           else
436           {
437             isNewFrame =  OMX_FALSE;
438           }
439
440           m_forceToStichNextNAL = true;
441           break;
442         }
443         case NALU_TYPE_ACCESS_DELIM:
444         default:
445         {
446           isNewFrame =  OMX_FALSE;
447           // Do not update m_forceToStichNextNAL
448           break;
449         }
450       } // end of switch
451     } // end of if
452     m_prv_nalu = nal_unit;
453     DEBUG_PRINT_LOW("get_h264_nal_type - newFrame value %d\n",isNewFrame);
454     return eRet;
455 }