Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      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
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 
     19 #include "ti_video_config_parser.h"
     20 #include "ti_m4v_config_parser.h"
     21 #include "oscl_mem.h"
     22 
     23 #include "oscl_dll.h"
     24 
     25 #define GetUnalignedWord( pb, w ) \
     26             (w) = ((uint16) *(pb + 1) << 8) + *pb;
     27 
     28 #define GetUnalignedDword( pb, dw ) \
     29             (dw) = ((uint32) *(pb + 3) << 24) + \
     30                    ((uint32) *(pb + 2) << 16) + \
     31                    ((uint16) *(pb + 1) << 8) + *pb;
     32 
     33 #define GetUnalignedWordEx( pb, w )     GetUnalignedWord( pb, w ); (pb) += sizeof(uint16);
     34 #define GetUnalignedDwordEx( pb, dw )   GetUnalignedDword( pb, dw ); (pb) += sizeof(uint32);
     35 #define GetUnalignedQwordEx( pb, qw )   GetUnalignedQword( pb, qw ); (pb) += sizeof(uint64);
     36 
     37 #define LoadBYTE( b, p )    b = *(uint8 *)p;  p += sizeof( uint8 )
     38 
     39 #define LoadWORD( w, p )    GetUnalignedWordEx( p, w )
     40 #define LoadDWORD( dw, p )  GetUnalignedDwordEx( p, dw )
     41 #define LoadQWORD( qw, p )  GetUnalignedQwordEx( p, qw )
     42 
     43 #ifndef MAKEFOURCC_WMC
     44 #define MAKEFOURCC_WMC(ch0, ch1, ch2, ch3) \
     45         ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) |   \
     46         ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
     47 
     48 #define mmioFOURCC_WMC(ch0, ch1, ch2, ch3)  MAKEFOURCC_WMC(ch0, ch1, ch2, ch3)
     49 #endif
     50 
     51 #define FOURCC_WMV2     mmioFOURCC_WMC('W','M','V','2')
     52 #define FOURCC_WMV3     mmioFOURCC_WMC('W','M','V','3')
     53 #define FOURCC_WMVA		mmioFOURCC_WMC('W','M','V','A')
     54 #define FOURCC_WVC1		mmioFOURCC_WMC('W','V','C','1')
     55 //For WMVA
     56 #define ASFBINDING_SIZE                   1   // size of ASFBINDING is 1 byte
     57 #define FOURCC_MP42		mmioFOURCC_WMC('M','P','4','2')
     58 #define FOURCC_MP43		mmioFOURCC_WMC('M','P','4','3')
     59 #define FOURCC_mp42		mmioFOURCC_WMC('m','p','4','2')
     60 #define FOURCC_mp43		mmioFOURCC_WMC('m','p','4','3')
     61 
     62 OSCL_DLL_ENTRY_POINT_DEFAULT()
     63 
     64 int32 GetNAL_Config(uint8** bitstream, int32* size);
     65 
     66 OSCL_EXPORT_REF int16 ti_video_config_parser(tiVideoConfigParserInputs *aInputs, tiVideoConfigParserOutputs *aOutputs, char* pComponentName)
     67 {
     68     if (aInputs->iMimeType == PVMF_MIME_M4V) //m4v
     69     {
     70         mp4StreamType psBits;
     71         psBits.data = aInputs->inPtr;
     72         if (aInputs->inBytes <= 0)
     73         {
     74             return -1;
     75         }
     76         psBits.numBytes = aInputs->inBytes;
     77         psBits.bytePos = 0;
     78         psBits.bitBuf = 0;
     79         psBits.dataBitPos = 0;
     80         psBits.bitPos = 32;
     81 
     82         int32 width, height, display_width, display_height = 0;
     83         int32 profile_level = 0;
     84         int16 retval = 0;
     85         retval = iDecodeVOLHeader(&psBits, &width, &height, &display_width, &display_height, &profile_level);
     86         if (retval != 0)
     87         {
     88             return retval;
     89         }
     90         aOutputs->width  = (uint32)display_width;
     91         aOutputs->height = (uint32)display_height;
     92         aOutputs->profile = (uint32)profile_level; // for mp4, profile/level info is packed
     93         aOutputs->level = 0;
     94 
     95     }
     96     else if (aInputs->iMimeType == PVMF_MIME_H2631998 ||
     97              aInputs->iMimeType == PVMF_MIME_H2632000)//h263
     98     {
     99         // Nothing to do for h263
    100         aOutputs->width  = 0;
    101         aOutputs->height = 0;
    102         aOutputs->profile = 0;
    103         aOutputs->level = 0;
    104     }
    105     else if (aInputs->iMimeType == PVMF_MIME_H264_VIDEO ||
    106              aInputs->iMimeType == PVMF_MIME_H264_VIDEO_MP4) //avc
    107     {
    108         int32 width, height, display_width, display_height = 0;
    109         int32 profile_idc, level_idc = 0;
    110         uint32 entropy_coding_mode_flag = 0;
    111 
    112         uint8 *tp = aInputs->inPtr;
    113 
    114         if (aInputs->inBytes > 1)
    115         {
    116             if (tp[0] == 0 && tp[1] == 0)
    117             {
    118                 // ByteStream Format
    119                 uint8* tmp_ptr = tp;
    120                 uint8* buffer_begin = tp;
    121                 int16 length = 0;
    122                 int initbufsize = aInputs->inBytes;
    123                 int tConfigSize = 0;
    124                 do
    125                 {
    126                     tmp_ptr += length;
    127                     length = GetNAL_Config(&tmp_ptr, &initbufsize);
    128                     buffer_begin[0] = length & 0xFF;
    129                     buffer_begin[1] = (length >> 8) & 0xFF;
    130                     oscl_memcpy(buffer_begin + 2, tmp_ptr, length);
    131                     buffer_begin += (length + 2);
    132                     tConfigSize += (length + 2);
    133                 }
    134                 while (initbufsize > 0);
    135             }
    136         }
    137 
    138         // check codec info and get settings
    139         int16 retval;
    140         retval = iGetAVCConfigInfo(tp,
    141                                    aInputs->inBytes,
    142                                    (int*) & width,
    143                                    (int*) & height,
    144                                    (int*) & display_width,
    145                                    (int*) & display_height,
    146                                    (int*) & profile_idc,
    147                                    (int*) & level_idc,
    148                                    (uint*) & entropy_coding_mode_flag);
    149         if (retval != 0)
    150         {
    151             return retval;
    152         }
    153         aOutputs->width  = (uint32)display_width;
    154         aOutputs->height = (uint32)display_height;
    155         aOutputs->profile = (uint32)profile_idc;
    156         aOutputs->level = (uint32) level_idc;
    157 
    158         /*When 720p and other profiles may be handled by other Video Decoder OMX Component,
    159           this will let PV know that it will need to load other compponent*/
    160         if ( 0 == oscl_strncmp (pComponentName, TI_VID_DEC, oscl_strlen (TI_VID_DEC)) )
    161         {
    162             if( ((width > WVGA_MAX_WIDTH) || (height > WVGA_MAX_HEIGHT)) ||
    163                 (profile_idc != H264_PROFILE_IDC_BASELINE) ||
    164                 entropy_coding_mode_flag )
    165             {
    166                 return -1;
    167             }
    168         }
    169 
    170     }
    171     else if (aInputs->iMimeType == PVMF_MIME_WMV) //wmv
    172     {
    173         uint32 dwdat;
    174         uint16 wdat;
    175         uint8 bdat;
    176         uint8 *pData = aInputs->inPtr;
    177 
    178         LoadDWORD(dwdat, pData); // Window width
    179         LoadDWORD(dwdat, pData); // Window height
    180         LoadBYTE(bdat, pData);
    181         LoadWORD(wdat, pData);  // Size of image info.
    182 
    183         // BITMAPINFOHEADER
    184         LoadDWORD(dwdat, pData); // Size of BMAPINFOHDR
    185         LoadDWORD(dwdat, pData);
    186         aOutputs->width = dwdat;
    187         LoadDWORD(dwdat, pData);
    188         aOutputs->height = dwdat;
    189 
    190         /* WMV1 and WMV2 are not supported. Rejected here. */
    191         /* Code to Check if comp is WMV1 then return not supported */
    192         pData += 4;
    193         LoadDWORD(dwdat, pData);
    194         uint32 NewCompression = dwdat;
    195         uint32 NewSeqHeader = 0;
    196         uint32 NewProfile = 0;
    197         // in case of WMV store "Compression Type as Level"
    198         aOutputs->level = NewCompression;
    199 
    200         if (NewCompression != FOURCC_WMV2 &&
    201                 NewCompression != FOURCC_WMV3 &&
    202                 NewCompression != FOURCC_WVC1 &&
    203                 NewCompression != FOURCC_WMVA &&
    204                 NewCompression != FOURCC_MP42 &&
    205                 NewCompression != FOURCC_MP43 &&
    206                 NewCompression != FOURCC_mp42 &&
    207                 NewCompression != FOURCC_mp43)
    208         {
    209             return -1;
    210         }
    211         // get profile etc.
    212         // Check sequence header
    213         switch (NewCompression)
    214         {
    215             case FOURCC_WMV3:
    216             {
    217                 // start fresh
    218                 pData = aInputs->inPtr;
    219                 pData += (11 + 40); //sizeof(BITMAPINFOHEADER); // position to sequence header
    220 
    221                 LoadDWORD(dwdat, pData);
    222                 NewSeqHeader = dwdat; // this is little endian read sequence header
    223 
    224                 NewProfile = (NewSeqHeader & 0xC0) >> 6; // 0 - simple , 1- main, 3 - complex, 2-forbidden
    225 
    226                 break;
    227             }
    228             case FOURCC_WMVA:
    229             {
    230                 pData = aInputs->inPtr;
    231                 pData += (11 + 40 + ASFBINDING_SIZE); //sizeof(BITMAPINFOHEADER); // position to sequence header
    232 
    233                 LoadDWORD(dwdat, pData); // prefix	// this is little endian read sequence header
    234                 LoadDWORD(dwdat, pData);
    235                 NewSeqHeader = dwdat;
    236 
    237                 NewProfile = (NewSeqHeader & 0xC0) >> 6; // this must be 3
    238             }
    239             break;
    240 
    241             default:
    242 
    243                 NewProfile = 0;
    244                 break;
    245         }
    246 
    247         aOutputs->profile = NewProfile;
    248 
    249     }
    250     else
    251     {
    252         return -1;
    253     }
    254     return 0;
    255 }
    256 
    257 
    258 /* This function finds a nal from the SC's, moves the bitstream pointer to the beginning of the NAL unit, returns the
    259 size of the NAL, and at the same time, updates the remaining size in the bitstream buffer that is passed in */
    260 int32 GetNAL_Config(uint8** bitstream, int32* size)
    261 {
    262     int i = 0;
    263     int j;
    264     uint8* nal_unit = *bitstream;
    265     int count = 0;
    266 
    267     /* find SC at the beginning of the NAL */
    268     while (nal_unit[i++] == 0 && i < *size)
    269     {
    270     }
    271 
    272     if (nal_unit[i-1] == 1)
    273     {
    274         *bitstream = nal_unit + i;
    275     }
    276     else
    277     {
    278         j = *size;
    279         *size = 0;
    280         return j;  // no SC at the beginning, not supposed to happen
    281     }
    282 
    283     j = i;
    284 
    285     /* found the SC at the beginning of the NAL, now find the SC at the beginning of the next NAL */
    286     while (i < *size)
    287     {
    288         if (count == 2 && nal_unit[i] == 0x01)
    289         {
    290             i -= 2;
    291             break;
    292         }
    293 
    294         if (nal_unit[i])
    295             count = 0;
    296         else
    297             count++;
    298         i++;
    299     }
    300 
    301     *size -= i;
    302     return (i -j);
    303 }
    304