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 "intel_video_config_parser.h"
     20 #include "intel_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 
     63 OSCL_DLL_ENTRY_POINT_DEFAULT()
     64 
     65 int32 GetNAL_Config(uint8** bitstream, int32* size);
     66 
     67 OSCL_EXPORT_REF int16 intel_video_config_parser(pvVideoConfigParserInputs *aInputs, pvVideoConfigParserOutputs *aOutputs)
     68 {
     69     if (aInputs->iMimeType == PVMF_MIME_M4V) //m4v
     70     {
     71         mp4StreamType psBits;
     72         psBits.data = aInputs->inPtr;
     73         if (aInputs->inBytes <= 0)
     74         {
     75             return -1;
     76         }
     77         psBits.numBytes = aInputs->inBytes;
     78         psBits.bytePos = 0;
     79         psBits.bitBuf = 0;
     80         psBits.dataBitPos = 0;
     81         psBits.bitPos = 32;
     82 
     83         int32 width, height, display_width, display_height = 0;
     84         int32 profile_level = 0;
     85         int16 retval = 0;
     86         retval = iDecodeVOLHeader(&psBits, &width, &height, &display_width, &display_height, &profile_level);
     87         if (retval != 0)
     88         {
     89             return retval;
     90         }
     91         aOutputs->width  = (uint32)display_width;
     92         aOutputs->height = (uint32)display_height;
     93         aOutputs->profile = (uint32)profile_level; // for mp4, profile/level info is packed
     94         aOutputs->level = 0;
     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 
    111         uint8 *tp = aInputs->inPtr;
    112 
    113         if (aInputs->inBytes > 1)
    114         {
    115             if (tp[0] == 0 && tp[1] == 0)
    116             {
    117                 // ByteStream Format
    118                 uint8* tmp_ptr = tp;
    119                 uint8* buffer_begin = tp;
    120                 int16 length = 0;
    121                 int initbufsize = aInputs->inBytes;
    122                 int tConfigSize = 0;
    123                 do
    124                 {
    125                     tmp_ptr += length;
    126                     length = GetNAL_Config(&tmp_ptr, &initbufsize);
    127                     buffer_begin[0] = length & 0xFF;
    128                     buffer_begin[1] = (length >> 8) & 0xFF;
    129                     oscl_memcpy(buffer_begin + 2, tmp_ptr, length);
    130                     buffer_begin += (length + 2);
    131                     tConfigSize += (length + 2);
    132                 }
    133                 while (initbufsize > 0);
    134             }
    135         }
    136 
    137         // check codec info and get settings
    138         int16 retval;
    139         retval = iGetAVCConfigInfo(tp,
    140                                    aInputs->inBytes,
    141                                    (int*) & width,
    142                                    (int*) & height,
    143                                    (int*) & display_width,
    144                                    (int*) & display_height,
    145                                    (int*) & profile_idc,
    146                                    (int*) & level_idc);
    147         if (retval != 0)
    148         {
    149             return retval;
    150         }
    151         aOutputs->width  = (uint32)display_width;
    152         aOutputs->height = (uint32)display_height;
    153         aOutputs->profile = (uint32)profile_idc;
    154         aOutputs->level = (uint32) level_idc;
    155     }
    156     else if (aInputs->iMimeType == PVMF_MIME_WMV) //wmv
    157     {
    158         uint32 dwdat;
    159         uint16 wdat;
    160         uint8 bdat;
    161         uint8 *pData = aInputs->inPtr;
    162 
    163         LoadDWORD(dwdat, pData); // Window width
    164         LoadDWORD(dwdat, pData); // Window height
    165         LoadBYTE(bdat, pData);
    166         LoadWORD(wdat, pData);  // Size of image info.
    167 
    168         // BITMAPINFOHEADER
    169         LoadDWORD(dwdat, pData); // Size of BMAPINFOHDR
    170         LoadDWORD(dwdat, pData);
    171         aOutputs->width = dwdat;
    172         LoadDWORD(dwdat, pData);
    173         aOutputs->height = dwdat;
    174 
    175         /* WMV1 and WMV2 are not supported. Rejected here. */
    176         /* Code to Check if comp is WMV1 then return not supported */
    177         pData += 4;
    178         LoadDWORD(dwdat, pData);
    179         uint32 NewCompression = dwdat;
    180         uint32 NewSeqHeader = 0;
    181         uint32 NewProfile = 0;
    182         // in case of WMV store "Compression Type as Level"
    183         aOutputs->level = NewCompression;
    184 
    185         if (NewCompression != FOURCC_WMV2 &&
    186                 NewCompression != FOURCC_WMV3 &&
    187                 NewCompression != FOURCC_WVC1 &&
    188                 NewCompression != FOURCC_WMVA &&
    189                 NewCompression != FOURCC_MP42 &&
    190                 NewCompression != FOURCC_MP43 &&
    191                 NewCompression != FOURCC_mp42 &&
    192                 NewCompression != FOURCC_mp43)
    193         {
    194             return -1;
    195         }
    196         // get profile etc.
    197         // Check sequence header
    198         switch (NewCompression)
    199         {
    200             case FOURCC_WMV3:
    201             {
    202                 // start fresh
    203                 pData = aInputs->inPtr;
    204                 pData += (11 + 40); //sizeof(BITMAPINFOHEADER); // position to sequence header
    205 
    206                 LoadDWORD(dwdat, pData);
    207                 NewSeqHeader = dwdat; // this is little endian read sequence header
    208 
    209                 NewProfile = (NewSeqHeader & 0xC0) >> 6; // 0 - simple , 1- main, 3 - complex, 2-forbidden
    210 
    211                 break;
    212             }
    213             case FOURCC_WMVA:
    214             {
    215                 pData = aInputs->inPtr;
    216                 pData += (11 + 40 + ASFBINDING_SIZE); //sizeof(BITMAPINFOHEADER); // position to sequence header
    217 
    218                 LoadDWORD(dwdat, pData); // prefix  // this is little endian read sequence header
    219                 LoadDWORD(dwdat, pData);
    220                 NewSeqHeader = dwdat;
    221 
    222                 NewProfile = (NewSeqHeader & 0xC0) >> 6; // this must be 3
    223             }
    224             break;
    225 
    226             default:
    227 
    228                 NewProfile = 0;
    229                 break;
    230         }
    231 
    232         aOutputs->profile = NewProfile;
    233 
    234     }
    235     else
    236     {
    237         return -1;
    238     }
    239     return 0;
    240 }
    241 
    242 
    243 /* This function finds a nal from the SC's, moves the bitstream pointer to the beginning of the NAL unit, returns the
    244     size of the NAL, and at the same time, updates the remaining size in the bitstream buffer that is passed in */
    245 int32 GetNAL_Config(uint8** bitstream, int32* size)
    246 {
    247     int i = 0;
    248     int j;
    249     uint8* nal_unit = *bitstream;
    250     int count = 0;
    251 
    252     /* find SC at the beginning of the NAL */
    253     while (nal_unit[i++] == 0 && i < *size)
    254     {
    255     }
    256 
    257     if (nal_unit[i-1] == 1)
    258     {
    259         *bitstream = nal_unit + i;
    260     }
    261     else
    262     {
    263         j = *size;
    264         *size = 0;
    265         return j;  // no SC at the beginning, not supposed to happen
    266     }
    267 
    268     j = i;
    269 
    270     /* found the SC at the beginning of the NAL, now find the SC at the beginning of the next NAL */
    271     while (i < *size)
    272     {
    273         if (count == 2 && nal_unit[i] == 0x01)
    274         {
    275             i -= 2;
    276             break;
    277         }
    278 
    279         if (nal_unit[i])
    280             count = 0;
    281         else
    282             count++;
    283         i++;
    284     }
    285 
    286     *size -= i;
    287     return (i - j);
    288 }
    289