1 /*
2  * MP3val - a program for MPEG audio file validation
3  * Copyright (C) 2005-2009 Alexey Kuznetsov (ring0) and Eugen Tikhonov (jetsys)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 
20 #include "crossapi.h"
21 #include "mpegparse.h"
22 #include "report.h"
23 #include "out.h"
24 #include "crc.h"
25 #include <cstring>
26 #include <iostream>
27 #include <fstream>
28 
29 using namespace std;
30 
31 int mpeg1layer1_bitrates[]={-1,32,64,96,128,160,192,224,256,288,320,352,384,416,448,-1};
32 int mpeg1layer2_bitrates[]={-1,32,48,56,64,80,96,112,128,160,192,224,256,320,384,-1};
33 int mpeg1layer3_bitrates[]={-1,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1};
34 int mpeg2layer1_bitrates[]={-1,32,48,56,64,80,96,112,128,144,160,176,192,224,256,-1};
35 int mpeg2layers23_bitrates[]={-1,8,16,24,32,40,48,56,64,80,96,112,128,144,160,-1};
36 
37 int ValidateMPEGFrame(unsigned char *baseptr,int index, MPEGINFO *mpginfo);
38 int CheckMP3CRC(unsigned char *baseptr,int index,MPEGINFO *mpginfo,bool fix);
39 int ValidateID3v2Tag(unsigned char *baseptr,int index, MPEGINFO *mpginfo);
40 int ValidateAPEv2Tag(unsigned char *baseptr,int index, MPEGINFO *mpginfo);
41 
42 int ParseXingHeader(unsigned char *baseptr,int index,MPEGINFO *mpginfo);
43 int ParseVBRIHeader(unsigned char *baseptr,int index,MPEGINFO *mpginfo);
44 
45 int ParseRIFFHeader(unsigned char *baseptr,int index,int iFileSize,int *iNewFileSize);
46 
47 int MPEGResync(unsigned char *baseptr,int index,int iFileSize,int frames);
48 
49 DWORD rotate_dword(DWORD x);
50 
ValidateFile(unsigned char * baseptr,int iFileSize,MPEGINFO * mpginfo,ostream * out,char * filename,bool fix,int hFile)51 int ValidateFile(unsigned char *baseptr,int iFileSize,MPEGINFO *mpginfo,ostream *out,char *filename,bool fix,int hFile) {
52 	int iFrame;
53 	int iFrameSize=0;
54 	int iLastMPEGFrame=0,iNewFrame;
55 	bool WasFirstFrame=false;
56 	int iXingOffset=0;
57 	int iID3v1Offset=0;
58 	int iFirstMPEGFrameOffset=0;
59 	DWORD dwTemp;
60 	int mpeg_total;
61 	bool LastFrameWasMPEG=false;
62 
63 	iFrame=0;
64 
65 	mpginfo->clear();
66 
67 	if(iFileSize>=128&&!memcmp(&baseptr[iFileSize-128],"TAG",3)) {
68 		mpginfo->id3v1=1;
69 		iFileSize-=128;
70 		iID3v1Offset=iFileSize;
71 	}
72 
73 	if((iFileSize>=4)&&!memcmp(&baseptr[iFrame],"ID3",3)) {
74 		if(iFrame+10>iFileSize) {
75 			mpginfo->truncated=iFrame;
76 		}
77 		else {
78 			iFrame+=ValidateID3v2Tag(baseptr,iFrame,mpginfo);
79 			if(fix) {
80 				if(WriteToFile(hFile,(char *)baseptr,0,iFrame,iFileSize)==-1) return -1;
81 				LastFrameWasMPEG=false;
82 			}
83 		}
84 	}
85 
86 	while(iFrame!=iFileSize) {
87 		if(iFrame+4>iFileSize) {
88 //Bad (unknown) frame
89 			mpginfo->truncated=iFrame;
90 			break;
91 		}
92 		if(!memcmp(&baseptr[iFrame],"RIFF",4)) {
93 			if(!WasFirstFrame) {
94 //This is actually a WAV file, not MPEG. Parsing RIFF header
95 				mpginfo->riff=iFrame;
96 				iNewFrame=ParseRIFFHeader(baseptr,iFrame,iFileSize,&iFileSize);
97 				if(iNewFrame!=-1) {
98 					iFrame=iNewFrame;
99 					continue;
100 				}
101 			}
102 		}
103 
104 		if((baseptr[iFrame]==0xFF)&&((baseptr[iFrame+1]&0xE0)==0xE0)) {
105 //MPEG frame
106 			iFrameSize=ValidateMPEGFrame(baseptr,iFrame,mpginfo);
107 			if(iFrameSize!=-1) {
108 				if(iFrameSize+iFrame<=iFileSize&&mpginfo->iLastMPEGLayer==3&&mpginfo->bLastFrameCRC) CheckMP3CRC(baseptr,iFrame,mpginfo,fix);
109 				if(fix&&!WasFirstFrame) iFirstMPEGFrameOffset=CrossAPI_SetFilePointer(hFile,0,true);
110 				if(fix) {
111 					if(WriteToFile(hFile,(char *)baseptr,iFrame,iFrameSize,iFileSize)==-1) return -1;
112 					LastFrameWasMPEG=true;
113 				}
114 				if(!WasFirstFrame) {
115 					WasFirstFrame=true;
116 					mpginfo->iFirstMPEGFrameSize=iFrameSize;
117 					if(mpginfo->iLastMPEGVersion==1) {
118 						if(mpginfo->LastFrameStereo) {
119 							iXingOffset=32;
120 						}
121 						else {
122 							iXingOffset=17;
123 						}
124 					}
125 					else {
126 						if(mpginfo->LastFrameStereo) {
127 							iXingOffset=17;
128 						}
129 						else {
130 							iXingOffset=9;
131 						}
132 					}
133 					ParseXingHeader(baseptr,iFrame+4+iXingOffset,mpginfo);
134 					if(!mpginfo->VBRHeaderPresent) ParseVBRIHeader(baseptr,iFrame+4+32,mpginfo);
135 				}
136 				iLastMPEGFrame=iFrame;
137 				iFrame+=iFrameSize;
138 				continue;
139 			}
140 		}
141 //APEv2 tag
142 		if(!memcmp(&baseptr[iFrame],"APET",4)) {
143 			if(iFrame+16>iFileSize) {
144 				mpginfo->truncated=iFrame;
145 				break;
146 			}
147 			iFrameSize=ValidateAPEv2Tag(baseptr,iFrame,mpginfo);
148 			if(fix) {
149 				if(WriteToFile(hFile,(char *)baseptr,iFrame,iFrameSize,iFileSize)==-1) return -1;
150 				LastFrameWasMPEG=false;
151 			}
152 			iFrame+=iFrameSize;
153 			continue;
154 		}
155 
156 		if(fix) {
157 			if(LastFrameWasMPEG) {
158 				mpginfo->iDeletedFrames++;
159 				mpginfo->iTotalMPEGBytes-=WriteToFile(hFile,NULL,0,-1,-1);
160 			}
161 /*			else {
162 				if(WriteToFile(hFile,NULL,0,-1,-1)==-1) return -1;
163 			}*/
164 		}
165 		else if(LastFrameWasMPEG) {
166 			mpginfo->iDeletedFrames++;
167 			mpginfo->iTotalMPEGBytes-=GetLastFrameSize();
168 		}
169 
170 		if(!iFrame) {
171 			iNewFrame=MPEGResync(baseptr,iFrame,iFileSize,8);
172 			if(iNewFrame==-1) {
173 				mpginfo->unknown_format=0;
174 				break;
175 			}
176 			mpginfo->garbage_at_the_begin=0;
177 			if(!fix) PrintMessage(out,"WARNING",filename,"Garbage at the beginning of the file",mpginfo->garbage_at_the_begin);
178 			mpginfo->iErrors++;
179 			iFrame=iNewFrame;
180 		}
181 		else {
182 			iNewFrame=MPEGResync(baseptr,iLastMPEGFrame?(iLastMPEGFrame+1):iFrame,iFileSize,6);
183 			if(iNewFrame==-1) {
184 				mpginfo->garbage_at_the_end=iFrame;
185 				if(!fix) PrintMessage(out,"WARNING",filename,"Garbage at the end of the file",mpginfo->garbage_at_the_end);
186 				mpginfo->iErrors++;
187 				break;
188 			}
189 			mpginfo->mpeg_stream_error=iFrame;
190 			if(!fix) PrintMessage(out,"WARNING",filename,"MPEG stream error, resynchronized successfully",mpginfo->mpeg_stream_error);
191 			mpginfo->iErrors++;
192 			iFrame=iNewFrame;
193 		}
194 
195 	}
196 
197 	mpeg_total=
198 		mpginfo->mpeg1layer1+
199 		mpginfo->mpeg1layer2+
200 		mpginfo->mpeg1layer3+
201 		mpginfo->mpeg2layer1+
202 		mpginfo->mpeg2layer2+
203 		mpginfo->mpeg2layer3+
204 		mpginfo->mpeg25layer1+
205 		mpginfo->mpeg25layer2+
206 		mpginfo->mpeg25layer3;
207 
208 	if(mpginfo->truncated>=0) {
209 		if(fix) {
210 			if(WriteToFile(hFile,NULL,0,-1,-1)==-1) return -1;
211 			if(LastFrameWasMPEG) {
212 				mpginfo->iTotalMPEGBytes-=iFrameSize;
213 				mpginfo->iDeletedFrames++;
214 			}
215 		}
216 		else if(LastFrameWasMPEG) {
217 			mpginfo->iTotalMPEGBytes-=iFrameSize;
218 			mpginfo->iDeletedFrames++;
219 		}
220 	}
221 
222 	if(fix&&mpginfo->id3v1) {
223 		if(WriteToFile(hFile,(char *)baseptr,iID3v1Offset,128,-1)==-1) return -1;
224 	}
225 
226 	if(fix) CrossAPI_SetEndOfFile(hFile);
227 
228 	if(fix&&mpginfo->VBRHeaderPresent) {
229 		if(mpginfo->IsXingHeader) {
230 			if(mpginfo->BytesPresent&&mpginfo->FramesPresent) {
231 				CrossAPI_SetFilePointer(hFile,iFirstMPEGFrameOffset+iXingOffset+12,false);
232 				dwTemp=rotate_dword(mpeg_total-mpginfo->iDeletedFrames);
233 				if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
234 				dwTemp=rotate_dword(mpginfo->iTotalMPEGBytes);
235 				if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
236 			}
237 			else if(mpginfo->BytesPresent) {
238 				CrossAPI_SetFilePointer(hFile,iFirstMPEGFrameOffset+iXingOffset+12,false);
239 				dwTemp=rotate_dword(mpginfo->iTotalMPEGBytes);
240 				if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
241 			}
242 			else if(mpginfo->FramesPresent) {
243 				CrossAPI_SetFilePointer(hFile,iFirstMPEGFrameOffset+iXingOffset+12,false);
244 				dwTemp=rotate_dword(mpeg_total-mpginfo->iDeletedFrames);
245 				if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
246 			}
247 		}
248 		else {
249 			CrossAPI_SetFilePointer(hFile,iFirstMPEGFrameOffset+46,false);
250 			dwTemp=rotate_dword(mpginfo->iTotalMPEGBytes);
251 			if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
252 			dwTemp=rotate_dword(mpeg_total-mpginfo->iDeletedFrames);
253 			if(WriteToFile(hFile,(char *)&dwTemp,0,4,-1)==-1) return -1;
254 		}
255 	}
256 
257 	if(fix) mpginfo->iErrors=1;
258 
259 	return 0;
260 }
261 
ValidateMPEGFrame(unsigned char * baseptr,int index,MPEGINFO * mpginfo)262 int ValidateMPEGFrame(unsigned char *baseptr,int index, MPEGINFO *mpginfo) {
263 	int mpeg_version, mpeg_layer;
264 	int mpeg_bitrate, mpeg_sampling_rate, mpeg_padding;
265 
266 	int bitrate_index=0;
267 	int iFrameSize;
268 
269 //Check if the frame contains CRC
270 	if(baseptr[index+1]&0x01) {
271 		mpginfo->bLastFrameCRC=false;
272 	}
273 	else {
274 		mpginfo->bLastFrameCRC=true;
275 		mpginfo->bCRC=true;
276 	}
277 
278 // Determine MPEG version and layer
279 	switch((baseptr[index+1]>>1)&0x0F) {
280 	case 0x0F:
281 		mpginfo->mpeg1layer1++;
282 		mpeg_version=1;
283 		mpeg_layer=1;
284 		break;
285 	case 0x0E:
286 		mpginfo->mpeg1layer2++;
287 		mpeg_version=1;
288 		mpeg_layer=2;
289 		break;
290 	case 0x0D:
291 		mpginfo->mpeg1layer3++;
292 		mpeg_version=1;
293 		mpeg_layer=3;
294 		break;
295 	case 0x0B:
296 		mpginfo->mpeg2layer1++;
297 		mpeg_version=2;
298 		mpeg_layer=1;
299 		break;
300 	case 0x0A:
301 		mpginfo->mpeg2layer2++;
302 		mpeg_version=2;
303 		mpeg_layer=2;
304 		break;
305 	case 0x09:
306 		mpginfo->mpeg2layer3++;
307 		mpeg_version=2;
308 		mpeg_layer=3;
309 		break;
310 	case 0x03:
311 		mpginfo->mpeg25layer1++;
312 		mpeg_version=25;
313 		mpeg_layer=1;
314 		break;
315 	case 0x02:
316 		mpginfo->mpeg25layer2++;
317 		mpeg_version=25;
318 		mpeg_layer=2;
319 		break;
320 	case 0x01:
321 		mpginfo->mpeg25layer3++;
322 		mpeg_version=25;
323 		mpeg_layer=3;
324 		break;
325 	default:
326 		mpginfo->mpeg_stream_error=index;
327 		return -1;
328 	}
329 // Calculate bit rate
330 	*((unsigned char *)&bitrate_index)=((baseptr[index+2])>>4)&0x0F;
331 	if(mpeg_version==1) {
332 		if(mpeg_layer==1) {
333 			mpeg_bitrate=mpeg1layer1_bitrates[bitrate_index];
334 		}
335 		else if(mpeg_layer==2) {
336 			mpeg_bitrate=mpeg1layer2_bitrates[bitrate_index];
337 		}
338 		else {
339 			mpeg_bitrate=mpeg1layer3_bitrates[bitrate_index];
340 		}
341 	}
342 	else {
343 		if(mpeg_layer==1) {
344 			mpeg_bitrate=mpeg2layer1_bitrates[bitrate_index];
345 		}
346 		else {
347 			mpeg_bitrate=mpeg2layers23_bitrates[bitrate_index];
348 		}
349 	}
350 
351 	if(mpeg_bitrate==-1) {
352 		mpginfo->mpeg_stream_error=index;
353 		return -1;
354 	}
355 
356 	if(mpginfo->iLastBitrate>0&&mpginfo->iLastBitrate!=mpeg_bitrate) mpginfo->bVariableBitrate=true;
357 	mpginfo->iLastBitrate=mpeg_bitrate;
358 
359 //Determine sampling rate
360 	switch((baseptr[index+2]>>2)&0x03) {
361 	case 0x00:
362 		if(mpeg_version==1) mpeg_sampling_rate=44100;
363 		else if(mpeg_version==2) mpeg_sampling_rate=22050;
364 		else mpeg_sampling_rate=11025;
365 		break;
366 	case 0x01:
367 		if(mpeg_version==1) mpeg_sampling_rate=48000;
368 		else if(mpeg_version==2) mpeg_sampling_rate=24000;
369 		else mpeg_sampling_rate=12000;
370 		break;
371 	case 0x02:
372 		if(mpeg_version==1) mpeg_sampling_rate=32000;
373 		else if(mpeg_version==2) mpeg_sampling_rate=16000;
374 		else mpeg_sampling_rate=8000;
375 		break;
376 	default:
377 		mpginfo->mpeg_stream_error=index;
378 		return -1;
379 	}
380 
381 //Check if padding is being used
382 	if((baseptr[index+2]>>1)&0x01) mpeg_padding=1;
383 	else mpeg_padding=0;
384 
385 //Check if frame is stereo
386 	if((baseptr[index+3]&0xC0)==0xC0) mpginfo->LastFrameStereo=false;
387 	else mpginfo->LastFrameStereo=true;
388 
389 	mpginfo->iLastMPEGVersion=mpeg_version;
390 	mpginfo->iLastMPEGLayer=mpeg_layer;
391 
392 	if(mpeg_layer==1) iFrameSize=(12*mpeg_bitrate*1000/mpeg_sampling_rate+mpeg_padding)*4;
393 	else if(mpeg_layer==2) iFrameSize=144*mpeg_bitrate*1000/mpeg_sampling_rate+mpeg_padding;
394 	else if(mpeg_layer==3&&mpeg_version==1)	iFrameSize=144*mpeg_bitrate*1000/mpeg_sampling_rate+mpeg_padding;
395 	else iFrameSize=72*mpeg_bitrate*1000/mpeg_sampling_rate+mpeg_padding;
396 
397 	mpginfo->iTotalMPEGBytes+=iFrameSize;
398 
399 	return iFrameSize;
400 }
401 
CheckMP3CRC(unsigned char * baseptr,int index,MPEGINFO * mpginfo,bool fix)402 int CheckMP3CRC(unsigned char *baseptr,int index,MPEGINFO *mpginfo,bool fix) {
403 	int crc=0xFFFF;
404 	int storedcrc=0;
405 	int iSideInfoSize;
406 	crc=CalculateCRC16(crc,0x8005,(char *)&baseptr[index+2],2);
407 
408 	if(mpginfo->LastFrameStereo) {
409 		if(mpginfo->iLastMPEGVersion==1) {
410 			iSideInfoSize=32;
411 		}
412 		else {
413 			iSideInfoSize=17;
414 		}
415 	}
416 	else {
417 		if(mpginfo->iLastMPEGVersion==1) {
418 			iSideInfoSize=17;
419 		}
420 		else {
421 			iSideInfoSize=9;
422 		}
423 	}
424 
425 	crc=CalculateCRC16(crc,0x8005,(char *)&baseptr[index+6],iSideInfoSize);
426 
427 	((char *)&storedcrc)[1]=baseptr[index+4];
428 	((char *)&storedcrc)[0]=baseptr[index+5];
429 
430 	if(storedcrc!=crc) {
431 		mpginfo->bCRCError=true;
432 		mpginfo->iCRCErrors++;
433 		if(fix) {
434 			baseptr[index+4]=((char *)&crc)[1];
435 			baseptr[index+5]=((char *)&crc)[0];
436 		}
437 	}
438 
439 	return 0;
440 }
441 
ValidateID3v2Tag(unsigned char * baseptr,int index,MPEGINFO * mpginfo)442 int ValidateID3v2Tag(unsigned char *baseptr,int index, MPEGINFO *mpginfo) {
443 	int iDataSize;
444 
445 	mpginfo->id3v2++;
446 
447 	iDataSize=baseptr[index+9];
448 	iDataSize+=128*baseptr[index+8];
449 	iDataSize+=16384*baseptr[index+7];
450 	iDataSize+=2097152*baseptr[index+6];
451 
452 	if(baseptr[index+5]&0x10) return iDataSize+20;
453 	return iDataSize+10;
454 }
455 
ValidateAPEv2Tag(unsigned char * baseptr,int index,MPEGINFO * mpginfo)456 int ValidateAPEv2Tag(unsigned char *baseptr,int index, MPEGINFO *mpginfo) {
457 	mpginfo->apev2++;
458 	return *((int *)&baseptr[index+12])+32;
459 }
460 
MPEGResync(unsigned char * baseptr,int index,int iFileSize,int frames)461 int MPEGResync(unsigned char *baseptr,int index,int iFileSize,int frames) {
462 	unsigned char *p=&baseptr[index];
463 	int sync_frames=0;
464 	int new_frame=0;
465 	int iFrameSize;
466 	MPEGINFO tmp_mpginfo;
467 	int iMPEGVersion=0,iMPEGLayer=0;
468 
469 	do {
470 		if(iFileSize-(p-baseptr)-3<=0) return -1;
471 		p=(unsigned char *)memchr(p,'\xFF',iFileSize-(p-baseptr)-3);
472 		if(!p) break;
473 		if((p[1]&0xE0)!=0xE0) {
474 			p++;
475 			sync_frames=0;
476 			iMPEGVersion=0;
477 			iMPEGLayer=0;
478 			continue;
479 		}
480 		iFrameSize=ValidateMPEGFrame(baseptr,p-baseptr,&tmp_mpginfo);
481 		if(iFrameSize==-1) {
482 			p++;
483 			sync_frames=0;
484 			iMPEGVersion=0;
485 			iMPEGLayer=0;
486 			continue;
487 		}
488 		new_frame=iFrameSize+(p-baseptr);
489 		sync_frames++;
490 		iMPEGVersion=tmp_mpginfo.iLastMPEGVersion;
491 		iMPEGLayer=tmp_mpginfo.iLastMPEGLayer;
492 		while(sync_frames<frames) {
493 			if(new_frame+4>iFileSize) {
494 				sync_frames=0;
495 				iMPEGVersion=0;
496 				iMPEGLayer=0;
497 				p++;
498 				break;
499 			}
500 			iFrameSize=ValidateMPEGFrame(baseptr,new_frame,&tmp_mpginfo);
501 			if(iFrameSize==-1) {
502 				sync_frames=0;
503 				iMPEGVersion=0;
504 				iMPEGLayer=0;
505 				p++;
506 				break;
507 			}
508 			new_frame+=iFrameSize;
509 			sync_frames++;
510 			if(iMPEGVersion&&iMPEGVersion!=tmp_mpginfo.iLastMPEGVersion) {
511 				sync_frames=0;
512 				iMPEGVersion=0;
513 				iMPEGLayer=0;
514 				p++;
515 				break;
516 			}
517 			if(iMPEGLayer&&iMPEGLayer!=tmp_mpginfo.iLastMPEGLayer) {
518 				sync_frames=0;
519 				iMPEGVersion=0;
520 				iMPEGLayer=0;
521 				p++;
522 				break;
523 			}
524 		}
525 	} while(sync_frames<frames);
526 
527 	if(sync_frames>=frames) return (p-baseptr);
528 	return -1;
529 }
530 
ParseXingHeader(unsigned char * baseptr,int index,MPEGINFO * mpginfo)531 int ParseXingHeader(unsigned char *baseptr,int index,MPEGINFO *mpginfo) {
532 	if(memcmp(&baseptr[index],"Xing",4)&&memcmp(&baseptr[index],"Info",4)) return 0;
533 	mpginfo->VBRHeaderPresent=true;
534 	mpginfo->IsXingHeader=true;
535 	switch(baseptr[index+7]&0x03) {
536 	case 0x00:
537 		return 0;
538 	case 0x01:
539 		mpginfo->iFrames=16777216*baseptr[index+8]+65536*baseptr[index+9]+256*baseptr[index+10]+baseptr[index+11];
540 		mpginfo->FramesPresent=true;
541 		mpginfo->BytesPresent=false;
542 		return 0;
543 	case 0x02:
544 		mpginfo->iBytes=16777216*baseptr[index+8]+65536*baseptr[index+9]+256*baseptr[index+10]+baseptr[index+11];
545 		mpginfo->FramesPresent=false;
546 		mpginfo->BytesPresent=true;
547 		return 0;
548 	case 0x03:
549 		mpginfo->iFrames=16777216*baseptr[index+8]+65536*baseptr[index+9]+256*baseptr[index+10]+baseptr[index+11];
550 		mpginfo->iBytes=16777216*baseptr[index+12]+65536*baseptr[index+13]+256*baseptr[index+14]+baseptr[index+15];
551 		mpginfo->FramesPresent=true;
552 		mpginfo->BytesPresent=true;
553 		return 0;
554 	}
555 
556 	return 0;
557 }
558 
ParseVBRIHeader(unsigned char * baseptr,int index,MPEGINFO * mpginfo)559 int ParseVBRIHeader(unsigned char *baseptr,int index,MPEGINFO *mpginfo) {
560 	if(memcmp(&baseptr[index],"VBRI",4)) return 0;
561 	mpginfo->VBRHeaderPresent=true;
562 	mpginfo->IsXingHeader=false;
563 	mpginfo->iBytes=16777216*baseptr[index+10]+65536*baseptr[index+11]+256*baseptr[index+12]+baseptr[index+13];
564 	mpginfo->iFrames=16777216*baseptr[index+14]+65536*baseptr[index+15]+256*baseptr[index+16]+baseptr[index+17];
565 	mpginfo->FramesPresent=true;
566 	mpginfo->BytesPresent=true;
567 	return 0;
568 }
569 
ParseRIFFHeader(unsigned char * baseptr,int index,int iFileSize,int * iNewFileSize)570 int ParseRIFFHeader(unsigned char *baseptr,int index,int iFileSize,int *iNewFileSize) {
571 	int iDataLength;
572 
573 	if(index+11>iFileSize) return -1;
574 	if(memcmp(&baseptr[index],"RIFF",4)) return -1;
575 
576 	if(memcmp(&baseptr[index+8],"WAVE",4)) return -1;
577 
578 	index+=12;
579 
580 	do {
581 		if(index+7>iFileSize) return -1;
582 		iDataLength=*(int *)&baseptr[index+4];
583 		if(memcmp(&baseptr[index],"data",4)) {
584 			index+=iDataLength+8;
585 			continue;
586 		}
587 
588 		*iNewFileSize=index+8+iDataLength;
589 		if(*iNewFileSize>iFileSize) *iNewFileSize=iFileSize;
590 		return index+8;
591 	}while(true);
592 }
593 
rotate_dword(DWORD x)594 DWORD rotate_dword(DWORD x) {
595 	DWORD res;
596 
597 	((unsigned char *)&res)[0]=((unsigned char *)&x)[3];
598 	((unsigned char *)&res)[1]=((unsigned char *)&x)[2];
599 	((unsigned char *)&res)[2]=((unsigned char *)&x)[1];
600 	((unsigned char *)&res)[3]=((unsigned char *)&x)[0];
601 
602 	return res;
603 }
604