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
intel_video_config_parser(pvVideoConfigParserInputs * aInputs,pvVideoConfigParserOutputs * aOutputs)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 */
GetNAL_Config(uint8 ** bitstream,int32 * size)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