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