Home | History | Annotate | Download | only in src
      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 }
    456