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 #include "pv_avifile_header.h"
19
PVAviFileHeader(PVFile * aFp,uint32 aHdrSize)20 PVAviFileHeader::PVAviFileHeader(PVFile *aFp, uint32 aHdrSize)
21 {
22 iHeaderTotalSize = aHdrSize;
23 uint32 bytesRead = 0;
24 uint32 chunkType = 0;
25 uint32 oldChkType = 0;
26 iError = PV_AVI_FILE_PARSER_SUCCESS;
27
28 for (uint32 ii = 0; ii < iStreamList.size(); ii++)
29 {
30 iStreamList.pop_back();
31 }
32
33 uint32 streamListSz = 0;
34
35 while (bytesRead < iHeaderTotalSize)
36 {
37 oldChkType = chunkType;
38 if ((iError = PVAviFileParserUtils::ReadNextChunkType(aFp, chunkType)) != PV_AVI_FILE_PARSER_SUCCESS)
39 {
40 if ((PV_AVI_FILE_PARSER_UNSUPPORTED_CHUNK == iError))
41 {
42 PVAVIFILE_LOGINFO((0, "PVAviFileHeader::PVAviFileHeader: Unsupported chunk"));
43
44 uint32 chksz = 0;
45 if (oldChkType != LIST)
46 {
47 //get the size of unsupported chunk and skip it.
48 if (PVAviFileParserUtils::read32(aFp, chksz, true) != PV_AVI_FILE_PARSER_SUCCESS)
49 {
50 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Read Error"));
51 iError = PV_AVI_FILE_PARSER_READ_ERROR;
52 break;
53 }
54
55 aFp->Seek(chksz, Oscl_File::SEEKCUR);
56 bytesRead += chksz + CHUNK_SIZE + CHUNK_SIZE; //data + chunk size + chunk type
57 }
58 else
59 {
60 //skip the entire list if not supported
61 aFp->Seek((streamListSz - CHUNK_SIZE), Oscl_File::SEEKCUR); //subtract list name read above
62 bytesRead += streamListSz;
63 }
64
65 PVAVIFILE_LOGINFO((0, "PVAviFileHeader::PVAviFileHeader: Unsupported chunk skipped"));
66 iError = PV_AVI_FILE_PARSER_SUCCESS;
67 continue;
68 }
69 else
70 {
71 break;
72 }
73 }
74
75 bytesRead += CHUNK_SIZE;
76
77 if (bytesRead > iHeaderTotalSize)
78 {
79 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
80 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
81 break;
82 }
83
84 if (AVIH == chunkType)
85 {
86 uint32 aviStrSize = 0;
87 if (PVAviFileParserUtils::read32(aFp, aviStrSize, true) != PV_AVI_FILE_PARSER_SUCCESS)
88 {
89 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Read Error"));
90 iError = PV_AVI_FILE_PARSER_READ_ERROR;
91 break;
92 }
93
94 bytesRead += CHUNK_SIZE;
95
96 if (bytesRead > iHeaderTotalSize)
97 {
98 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
99 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
100 break;
101 }
102
103 if ((aviStrSize <= 0) || (aviStrSize > iHeaderTotalSize))
104 {
105 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: AVIH size greater than file header size"));
106 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
107 break;
108 }
109
110 if ((iError = ParseMainHeader(aFp)) != PV_AVI_FILE_PARSER_SUCCESS)
111 {
112 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: Error encountered while parsing File Header"));
113 break;
114 }
115
116 bytesRead += aviStrSize;
117 if (bytesRead > iHeaderTotalSize)
118 {
119 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
120 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
121 break;
122 }
123 }
124 else if (LIST == chunkType)
125 {
126 if (PVAviFileParserUtils::read32(aFp, streamListSz, true) != PV_AVI_FILE_PARSER_SUCCESS)
127 {
128 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Read Error"));
129 iError = PV_AVI_FILE_PARSER_READ_ERROR;
130 break;
131 }
132
133 bytesRead += CHUNK_SIZE;
134
135 if (bytesRead > iHeaderTotalSize)
136 {
137 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
138 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
139 break;
140 }
141
142 if ((streamListSz <= 0) || (streamListSz > iHeaderTotalSize))
143 {
144 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: stream list soze greater tha file header size"));
145 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
146 break;
147 }
148
149 }
150 else if (STRL == chunkType)
151 {
152 PVAVIFILE_LOGINFO((0, "PVAviFileHeader::PVAviFileHeader: Found stream list"));
153
154 PVAviFileStreamlist* strlst = OSCL_NEW(PVAviFileStreamlist, (aFp, (streamListSz - CHUNK_SIZE))); //subtract 4 bytes of List type from list size
155 if (strlst != NULL)
156 {
157 if ((iError = strlst->GetStatus()) != PV_AVI_FILE_PARSER_SUCCESS)
158 {
159 OSCL_DELETE(strlst);
160 strlst = NULL;
161 break;
162 }
163 }
164
165 iStreamList.push_back(*strlst);
166 bytesRead += streamListSz - CHUNK_SIZE;
167 if (bytesRead > iHeaderTotalSize)
168 {
169 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
170 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
171 break;
172 }
173
174 OSCL_DELETE(strlst);
175 }
176 else if (JUNK == chunkType)
177 {
178 PVAVIFILE_LOGINFO((0, "PVAviFileParser::ParseFile: Skip Junk data"));
179
180 uint32 junkSize = 0;
181 if (PVAviFileParserUtils::read32(aFp, junkSize, true) != PV_AVI_FILE_PARSER_SUCCESS)
182 {
183 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Read Error"));
184 iError = PV_AVI_FILE_PARSER_READ_ERROR;
185 break;
186 }
187
188 bytesRead += CHUNK_SIZE;
189 if (bytesRead > iHeaderTotalSize)
190 {
191 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
192 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
193 break;
194 }
195
196 if ((junkSize <= 0) || (junkSize > iHeaderTotalSize))
197 {
198 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: Junk data size more than file header size"));
199 iError = PV_AVI_FILE_PARSER_WRONG_SIZE;
200 break;
201 }
202
203 aFp->Seek(junkSize, Oscl_File::SEEKCUR);
204 bytesRead += junkSize;
205 if (bytesRead > iHeaderTotalSize)
206 {
207 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: File Size & Byte Count mismatch"));
208 iError = PV_AVI_FILE_PARSER_BYTE_COUNT_ERROR;
209 break;
210 }
211
212 }
213 else
214 {
215 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: Chunk not supported in file main header"));
216 iError = PV_AVI_FILE_PARSER_WRONG_CHUNK;
217 break;
218 }
219
220 }
221
222 if ((PV_AVI_FILE_PARSER_SUCCESS == iError) && (iStreamList.size() != iMainHeader.iStreams))
223 {
224 PVAVIFILE_LOGERROR((0, "PVAviFileHeader::PVAviFileHeader: "));
225 iError = PV_AVI_FILE_PARSER_ERROR_NUM_STREAM;
226 }
227
228
229 }
230
231 PV_AVI_FILE_PARSER_ERROR_TYPE
ParseMainHeader(PVFile * aFp)232 PVAviFileHeader::ParseMainHeader(PVFile *aFp)
233 {
234 //Read avi main header
235
236 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iMicroSecPerFrame, true)))
237 {
238 return PV_AVI_FILE_PARSER_READ_ERROR;
239 }
240
241 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iMaxBytesPerSec, true)))
242 {
243 return PV_AVI_FILE_PARSER_READ_ERROR;
244 }
245
246 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iPadding, true)))
247 {
248 return PV_AVI_FILE_PARSER_READ_ERROR;
249 }
250
251 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iFlags)))
252 {
253 return PV_AVI_FILE_PARSER_READ_ERROR;
254 }
255
256 if (iMainHeader.iFlags != 0)
257 {
258 if (iMainHeader.iFlags & AVIF_COPYRIGHTED)
259 iMainHeader.iIsAVIFileCopyrighted = true;
260
261 if (iMainHeader.iFlags & AVIF_HASINDEX)
262 iMainHeader.iAVIFileHasIndxTbl = true;
263
264 if (iMainHeader.iFlags & AVIF_ISINTERLEAVED)
265 iMainHeader.iISAVIFileInterleaved = true;
266
267 if (iMainHeader.iFlags & AVIF_MUSTUSEINDEX)
268 iMainHeader.iAVIFileMustUseIndex = true;
269
270 if (iMainHeader.iFlags & AVIF_WASCAPTUREFILE)
271 iMainHeader.iAVIFileWasCaptureFile = true;
272 }
273 else
274 {
275 iMainHeader.iIsAVIFileCopyrighted = false;
276 iMainHeader.iAVIFileHasIndxTbl = false;
277 iMainHeader.iISAVIFileInterleaved = false;
278 iMainHeader.iAVIFileMustUseIndex = false;
279 iMainHeader.iAVIFileWasCaptureFile = false;
280 }
281
282
283 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iTotalFrames, true)))
284 {
285 return PV_AVI_FILE_PARSER_READ_ERROR;
286
287 }
288
289 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iInitialFrames, true)))
290 {
291 return PV_AVI_FILE_PARSER_READ_ERROR;
292
293 }
294
295 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iStreams, true)))
296 {
297 return PV_AVI_FILE_PARSER_READ_ERROR;
298
299 }
300
301 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iSuggestedBufferSize, true)))
302 {
303 return PV_AVI_FILE_PARSER_READ_ERROR;
304
305 }
306
307 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iWidth, true)))
308 {
309 return PV_AVI_FILE_PARSER_READ_ERROR;
310
311 }
312
313 if (PV_AVI_FILE_PARSER_SUCCESS != (PVAviFileParserUtils::read32(aFp, iMainHeader.iHeight, true)))
314 {
315 return PV_AVI_FILE_PARSER_READ_ERROR;
316
317 }
318
319 for (uint32 ii = 0; ii < RES_BYTES_SZ; ii++)
320 {
321 if (PV_AVI_FILE_PARSER_SUCCESS != PVAviFileParserUtils::read32(aFp, iMainHeader.iReserved[ii], true))
322 {
323 return PV_AVI_FILE_PARSER_READ_ERROR;
324 }
325 }
326 return PV_AVI_FILE_PARSER_SUCCESS;
327 }
328
329
GetAudioFormat(uint32 aStreamNo)330 uint32 PVAviFileHeader::GetAudioFormat(uint32 aStreamNo)
331 {
332 uint32 strnum = GetNumStreams();
333 uint32 retType = WAVE_FORMAT_UNKNOWN;
334 uint32 ii = 0;
335
336 for (ii = 0; ii < strnum; ii++)
337 {
338 if ((iStreamList[ii].GetStreamType() == PV_2_AUDIO) && (aStreamNo == ii))
339 {
340 retType = iStreamList[ii].GetAudioFormat();
341 }
342 }
343
344 return retType;
345 }
346
347
GetNumAudioChannels(uint32 aStreamNo)348 uint32 PVAviFileHeader::GetNumAudioChannels(uint32 aStreamNo)
349 {
350 uint32 strnum = GetNumStreams();
351 uint32 retType = 0;
352 uint32 ii = 0;
353
354 for (ii = 0; ii < strnum; ii++)
355 {
356 if ((iStreamList[ii].GetStreamType() == PV_2_AUDIO) && (ii == aStreamNo))
357 {
358 retType = iStreamList[ii].GetNumAudioChannels();
359 }
360 }
361 return retType;
362
363 }
364
365