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 #include "frameparser.h"
     29 #include "omx_vdec.h"
     30 
     31 #ifdef _ANDROID_
     32     extern "C"{
     33         #include<utils/Log.h>
     34     }
     35 #endif//_ANDROID_
     36 
     37 static unsigned char H264_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
     38 static unsigned char H264_start_code[4] = {0x00,0x00,0x00,0x01};
     39 
     40 static unsigned char MPEG4_start_code[4] = {0x00,0x00,0x01,0xB6};
     41 static unsigned char MPEG4_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
     42 
     43 static unsigned char H263_start_code[4] = {0x00,0x00,0x80,0x00};
     44 static unsigned char H263_mask_code[4] = {0xFF,0xFF,0xFC,0x00};
     45 
     46 static unsigned char VC1_AP_start_code[4] = {0x00,0x00,0x01,0x0D};
     47 static unsigned char VC1_AP_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
     48 
     49 frame_parse::frame_parse():mutils(NULL),
     50                            parse_state(A0),
     51                            last_byte(0),
     52                            prev_one(0),
     53                            state_nal(NAL_LENGTH_ACC),
     54                            nal_length(0),
     55                            accum_length(0),
     56                            bytes_tobeparsed(0),
     57                            time_stamp (0),
     58                            flags (0)
     59 {
     60     memset (start_code,0,sizeof (start_code));
     61     memset (mask_code,0,sizeof (mask_code));
     62 }
     63 
     64 frame_parse::~frame_parse ()
     65 {
     66     if (mutils)
     67         delete mutils;
     68 
     69     mutils = NULL;
     70 }
     71 
     72 int frame_parse::init_start_codes (codec_type codec_type_parse)
     73 {
     74 	/*Check if Codec Type is proper and we are in proper state*/
     75 	if (codec_type_parse > CODEC_TYPE_VC1 || parse_state != A0)
     76 	{
     77 	  return -1;
     78 	}
     79 
     80 	switch (codec_type_parse)
     81 	{
     82 	case CODEC_TYPE_MPEG4:
     83 		memcpy (start_code,MPEG4_start_code,4);
     84 		memcpy (mask_code,MPEG4_mask_code,4);
     85 		break;
     86 	case CODEC_TYPE_H263:
     87 		memcpy (start_code,H263_start_code,4);
     88 		memcpy (mask_code,H263_mask_code,4);
     89 		break;
     90 	case CODEC_TYPE_H264:
     91 		memcpy (start_code,H264_start_code,4);
     92 		memcpy (mask_code,H264_mask_code,4);
     93 		break;
     94 	case CODEC_TYPE_VC1:
     95 		memcpy (start_code,VC1_AP_start_code,4);
     96 		memcpy (mask_code,VC1_AP_mask_code,4);
     97 		break;
     98 	}
     99 	return 1;
    100 }
    101 
    102 
    103 int frame_parse::init_nal_length (unsigned int nal_len)
    104 {
    105     if (nal_len == 0 || nal_len > 4 || state_nal != NAL_LENGTH_ACC)
    106     {
    107        return -1;
    108     }
    109     nal_length = nal_len;
    110 
    111     return 1;
    112 }
    113 
    114 int frame_parse::parse_mpeg4_frame ( OMX_BUFFERHEADERTYPE *source,
    115                                      OMX_BUFFERHEADERTYPE *dest ,
    116                                      OMX_U32 *partialframe)
    117 {
    118     OMX_U8 *pdest = NULL,*psource = NULL;
    119     OMX_U32 dest_len =0, source_len = 0, temp_len = 0;
    120     OMX_U32 parsed_length = 0,i=0;
    121     int residue_byte = 0;
    122 
    123     if (source == NULL || dest == NULL || partialframe == NULL)
    124     {
    125         return -1;
    126     }
    127 
    128   /*Calculate how many bytes are left in source and destination*/
    129     dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
    130     psource = source->pBuffer + source->nOffset;
    131     pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
    132     source_len = source->nFilledLen;
    133 
    134     /*Need Minimum of 4 for destination to copy atleast Start code*/
    135     if (dest_len < 4 || source_len == 0)
    136     {
    137         DEBUG_PRINT_LOW("\n Dest_len %d source_len %d",dest_len,source_len);
    138         if (source_len == 0 && (source->nFlags & 0x01))
    139         {
    140             DEBUG_PRINT_LOW("\n EOS condition Inform Client that it is complete frame");
    141             *partialframe = 0;
    142             return 1;
    143         }
    144         DEBUG_PRINT_LOW("\n Error in Parsing bitstream");
    145         return -1;
    146     }
    147 
    148     /*Check if State of the previous find is a Start code*/
    149     if (parse_state == A4)
    150     {
    151         /*Check for minimun size should be 4*/
    152         dest->nFlags = flags;
    153         dest->nTimeStamp = time_stamp;
    154         update_metadata(source->nTimeStamp,source->nFlags);
    155         memcpy (pdest,start_code,4);
    156         pdest [2] = prev_one;
    157         pdest [3] = last_byte;
    158         dest->nFilledLen += 4;
    159         pdest += 4;
    160         parse_state = A0;
    161     }
    162 
    163     /*Entry State Machine*/
    164     while ( source->nFilledLen > 0 && parse_state != A0
    165             && parse_state != A4 && dest_len > 0
    166           )
    167     {
    168         //printf ("\n In the Entry Loop");
    169         switch (parse_state)
    170         {
    171          case A3:
    172              /*If fourth Byte is matching then start code is found*/
    173              if ((*psource & mask_code [3]) == start_code [3])
    174              {
    175                last_byte = *psource;
    176                parse_state = A4;
    177                source->nFilledLen--;
    178                source->nOffset++;
    179                psource++;
    180              }
    181              else if ((start_code [1] == start_code [0]) && (start_code [2]  == start_code [1]))
    182              {
    183                  parse_state = A2;
    184                  memcpy (pdest,start_code,1);
    185                  pdest++;
    186                  dest->nFilledLen++;
    187                  dest_len--;
    188              }
    189              else if (start_code [2] == start_code [0])
    190              {
    191                  parse_state = A1;
    192                  memcpy (pdest,start_code,2);
    193                  pdest += 2;
    194                  dest->nFilledLen += 2;
    195                  dest_len -= 2;
    196              }
    197              else
    198              {
    199                  parse_state = A0;
    200                  memcpy (pdest,start_code,3);
    201                  pdest += 3;
    202                  dest->nFilledLen +=3;
    203                  dest_len -= 3;
    204              }
    205              break;
    206 
    207              case A2:
    208                  if ((*psource & mask_code [2])  == start_code [2])
    209                  {
    210                      prev_one = *psource;
    211                      parse_state = A3;
    212                      source->nFilledLen--;
    213                      source->nOffset++;
    214                      psource++;
    215                  }
    216                  else if ( start_code [1] == start_code [0])
    217                  {
    218                      parse_state = A1;
    219                      memcpy (pdest,start_code,1);
    220                      dest->nFilledLen +=1;
    221                      dest_len--;
    222                      pdest++;
    223                  }
    224                  else
    225                  {
    226                      parse_state = A0;
    227                      memcpy (pdest,start_code,2);
    228                      dest->nFilledLen +=2;
    229                      dest_len -= 2;
    230                      pdest += 2;
    231                  }
    232              break;
    233 
    234          case A1:
    235              if ((*psource & mask_code [1]) == start_code [1])
    236              {
    237                  parse_state = A2;
    238                  source->nFilledLen--;
    239                  source->nOffset++;
    240                  psource++;
    241              }
    242              else
    243              {
    244                  memcpy (pdest,start_code,1);
    245                  dest->nFilledLen +=1;
    246                  pdest++;
    247                  dest_len--;
    248                  parse_state = A0;
    249              }
    250              break;
    251          case A4:
    252          case A0:
    253              break;
    254         }
    255         dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
    256     }
    257 
    258      if (parse_state == A4)
    259      {
    260          *partialframe = 0;
    261          DEBUG_PRINT_LOW("\n Nal Found length is %d",dest->nFilledLen);
    262          return 1;
    263      }
    264 
    265      /*Partial Frame is true*/
    266      *partialframe = 1;
    267 
    268     /*Calculate how many bytes are left in source and destination*/
    269     dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
    270     psource = source->pBuffer + source->nOffset;
    271     pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
    272     source_len = source->nFilledLen;
    273 
    274     temp_len = (source_len < dest_len)?source_len:dest_len;
    275 
    276     /*Check if entry state machine consumed source or destination*/
    277     if (temp_len == 0)
    278     {
    279         return 1;
    280     }
    281 
    282     /*Parsing State Machine*/
    283     while  (parsed_length < temp_len)
    284     {
    285       switch (parse_state)
    286       {
    287       case A0:
    288           if ((psource [parsed_length] & mask_code [0])  == start_code[0])
    289           {
    290             parse_state = A1;
    291           }
    292           parsed_length++;
    293           break;
    294       case A1:
    295           if ((psource [parsed_length] & mask_code [1]) == start_code [1])
    296           {
    297             parsed_length++;
    298             parse_state = A2;
    299           }
    300           else
    301           {
    302             parse_state = A0;
    303           }
    304       break;
    305       case A2:
    306           if ((psource [parsed_length] & mask_code [2]) == start_code [2])
    307           {
    308             prev_one = psource [parsed_length];
    309             parsed_length++;
    310             parse_state = A3;
    311           }
    312           else if (start_code [1] == start_code [0])
    313           {
    314             parse_state = A1;
    315           }
    316           else
    317           {
    318             parse_state = A0;
    319           }
    320           break;
    321       case A3:
    322           if ((psource [parsed_length] & mask_code [3]) == start_code [3])
    323           {
    324             last_byte = psource [parsed_length];
    325             parsed_length++;
    326             parse_state = A4;
    327           }
    328           else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1]))
    329           {
    330              parse_state = A2;
    331           }
    332           else if (start_code [2] == start_code [0])
    333           {
    334               parse_state = A1;
    335           }
    336           else
    337           {
    338               parse_state = A0;
    339           }
    340           break;
    341       default:
    342           break;
    343       }
    344 
    345       /*Found the code break*/
    346       if (parse_state == A4)
    347       {
    348           break;
    349       }
    350     }
    351 
    352     /*Exit State Machine*/
    353     psource = source->pBuffer + source->nOffset;
    354     switch (parse_state)
    355     {
    356     case A4:
    357       *partialframe = 0;
    358       if (parsed_length > 4)
    359       {
    360         memcpy (pdest,psource,(parsed_length-4));
    361         dest->nFilledLen += (parsed_length-4);
    362       }
    363       break;
    364     case A3:
    365       if (parsed_length > 3)
    366       {
    367         memcpy (pdest,psource,(parsed_length-3));
    368         dest->nFilledLen += (parsed_length-3);
    369       }
    370       break;
    371     case A2:
    372         if (parsed_length > 2)
    373         {
    374           memcpy (pdest,psource,(parsed_length-2));
    375           dest->nFilledLen += (parsed_length-2);
    376         }
    377       break;
    378     case A1:
    379         if (parsed_length > 1)
    380         {
    381           memcpy (pdest,psource,(parsed_length-1));
    382           dest->nFilledLen += (parsed_length-1);
    383         }
    384       break;
    385     case A0:
    386       memcpy (pdest,psource,(parsed_length));
    387       dest->nFilledLen += (parsed_length);
    388       break;
    389     }
    390 
    391      if (source->nFilledLen < parsed_length)
    392      {
    393          printf ("\n FATAL Error");
    394          return -1;
    395      }
    396       source->nFilledLen -= parsed_length;
    397       source->nOffset += parsed_length;
    398 
    399     return 1;
    400 }
    401 
    402 
    403 int frame_parse::parse_h264_nallength (OMX_BUFFERHEADERTYPE *source,
    404                                        OMX_BUFFERHEADERTYPE *dest ,
    405                                        OMX_U32 *partialframe)
    406 {
    407     OMX_U8 *pdest = NULL,*psource = NULL;
    408     OMX_U32 dest_len =0, source_len = 0, temp_len = 0,parsed_length = 0;
    409 
    410    if (source == NULL || dest == NULL || partialframe == NULL)
    411    {
    412        return -1;
    413    }
    414 
    415    /*Calculate the length's*/
    416    dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
    417    source_len = source->nFilledLen;
    418 
    419    if (dest_len < 4 || source_len == 0 || nal_length == 0)
    420    {
    421        DEBUG_PRINT_LOW("\n Destination %d source %d nal length %d",\
    422                                     dest_len,source_len,nal_length);
    423        return -1;
    424    }
    425    *partialframe = 1;
    426    temp_len = (source_len < dest_len)?source_len:dest_len;
    427    psource = source->pBuffer + source->nOffset;
    428    pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
    429 
    430    /* Find the Bytes to Accumalte*/
    431    if (state_nal == NAL_LENGTH_ACC)
    432    {
    433       while (parsed_length < temp_len )
    434       {
    435         bytes_tobeparsed |= (((OMX_U32)(*psource))) << (((nal_length-accum_length-1) << 3));
    436 
    437         /*COPY THE DATA FOR C-SIM TO BE REOMVED ON TARGET*/
    438         //*pdest = *psource;
    439         accum_length++;
    440         source->nFilledLen--;
    441         source->nOffset++;
    442         psource++;
    443         //dest->nFilledLen++;
    444         //pdest++;
    445         parsed_length++;
    446 
    447         if (accum_length == nal_length)
    448         {
    449             accum_length = 0;
    450             state_nal = NAL_PARSING;
    451             memcpy (pdest,H264_start_code,4);
    452             dest->nFilledLen += 4;
    453             break;
    454         }
    455       }
    456    }
    457 
    458    dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
    459    source_len = source->nFilledLen;
    460    temp_len = (source_len < dest_len)?source_len:dest_len;
    461 
    462    psource = source->pBuffer + source->nOffset;
    463    pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
    464 
    465    /*Already in Parsing state go ahead and copy*/
    466    if(state_nal == NAL_PARSING && temp_len > 0)
    467    {
    468      if (temp_len < bytes_tobeparsed)
    469      {
    470          memcpy (pdest,psource,temp_len);
    471          dest->nFilledLen += temp_len;
    472          source->nOffset += temp_len;
    473          source->nFilledLen -= temp_len;
    474          bytes_tobeparsed -= temp_len;
    475      }
    476      else
    477      {
    478          memcpy (pdest,psource,bytes_tobeparsed);
    479          temp_len -= bytes_tobeparsed;
    480          dest->nFilledLen += bytes_tobeparsed;
    481          source->nOffset += bytes_tobeparsed;
    482          source->nFilledLen -= bytes_tobeparsed;
    483          bytes_tobeparsed = 0;
    484      }
    485    }
    486 
    487    if (bytes_tobeparsed == 0 && state_nal == NAL_PARSING)
    488    {
    489        *partialframe = 0;
    490        state_nal = NAL_LENGTH_ACC;
    491    }
    492 
    493    return 1;
    494 }
    495 
    496 void frame_parse::flush ()
    497 {
    498     parse_state = A0;
    499     state_nal = NAL_LENGTH_ACC;
    500     accum_length = 0;
    501     bytes_tobeparsed = 0;
    502 }
    503 
    504 void frame_parse::update_metadata (unsigned int ts ,unsigned int flgs)
    505 {
    506     time_stamp = ts;
    507     flags = flgs;
    508 }
    509