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
ti_video_config_parser(tiVideoConfigParserInputs * aInputs,tiVideoConfigParserOutputs * aOutputs,char * pComponentName)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 */
GetNAL_Config(uint8 ** bitstream,int32 * size)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