?? avifile.c
字號:
AviFseek(AviVideoFile, tmpIndex.dwOffset, SEEK_SET);
AviFread(&tmpFcc, sizeof(FOURCC), 1, AviVideoFile);
AviIdxFile->Clus = tmpIdxFile.Clus;
AviIdxFile->Offset = tmpIdxFile.Offset;
AviVideoFile->Clus = tmpVideoFile.Clus;
AviVideoFile->Offset = tmpVideoFile.Offset;
if (IS_VIDEO_IDX(tmpFcc))
return 1;
return 0;
}
/********************************************************************************************
Func:
AviFileParsing()
Description:
Parse AVI file .
Param:
AviFilePointer *aviPointer - avi file pointer.
MainAVIHeader *avihdr - Pointer of avi file header struct.
Return:
0: Success.
-1: File format error.
-2: Not have index.
-3: Can not find 'movi' chunk.
-4: Resolution is not supported.
-5: Codec is not supported.
Author:
ljn
Date:
2007-9-17 15:53
Log:
********************************************************************************************/
int AviFileParsing(AviFilePointer *aviPointer, MainAVIHeader *avihdr)
{
DWORD riffType;
int chunkSize;
int i;
AVI_FILE *file = aviPointer->AudioData;
struct
{
FOURCC CkID;
DWORD Size;
DWORD Type;
} list;
/*************************************************
[1] Read AVI header.
**************************************************/
/* Get AVI header list pointer. */
if (AviGetChunkPointer(file, SIGN_HDRL))
return AVI_FILE_FORMAT_ERR;
/* Seek Main AVI header. */
if (AviSeek(file, SIGN_AVIH) != sizeof(MainAVIHeader))
return AVI_FILE_FORMAT_ERR;
/* Read header. */
if (AviFread(avihdr, sizeof(MainAVIHeader), 1, file) < sizeof(MainAVIHeader))
return AVI_FILE_FORMAT_ERR;
/*************************************************
[2] Check if audio stream is included.
**************************************************/
stream_supported_flag.VideoSupportedFlag = TRUE;
/* We judge by AVI stream number here. It may be wrong. */
if (avihdr->dwStreams == 1)
{
stream_supported_flag.AudioSupportedFlag = FALSE;
}
else
{
stream_supported_flag.AudioSupportedFlag = TRUE;
}
/**************************************************
[3] Check if resolution and frame rate is supported.
***************************************************/
if ((avihdr->dwWidth > MAX_FRAME_WIDTH) || (avihdr->dwWidth * avihdr->dwHeight > MAX_FRAME_HEIGHT * MAX_FRAME_WIDTH))
return AVI_FILE_RESOLUTION_ERR;
/* Max frame rate: 100fps. */
if (avihdr->dwMicroSecPerFrame < 10000)
return AVI_FILE_FORMAT_ERR;
/*************************************************
[4] Check if index is included.
**************************************************/
if ((avihdr->dwFlags & FLAG_INDEX) == 0)
return AVI_FILE_INDX_ERR;
/*************************************************
[5] Read stream header.
**************************************************/
aviWavex.nBlockAlign = 0;
audioSteamID = 1;
for (i = 0; i < avihdr->dwStreams; i++)
{
/* Only two streams(a video stream, an audio stream) are supported now. */
if (i >= AVI_SUPPORT_STREAM_NUM)
break;
/* Seek stream list. */
do
{
if (!AviSeek(file, SIGN_LIST))
return AVI_FILE_FORMAT_ERR;
if (AviFread(&riffType, 1, sizeof(riffType), file) < sizeof(riffType))
return AVI_FILE_FORMAT_ERR;
}
while (riffType != SIGN_STRL);
/* Seek stream header. */
if (AviSeek(file, SIGN_STRH) != sizeof(AVISTREAMHEADER))
return AVI_FILE_FORMAT_ERR;
/* Read stream header. */
if (AviFread(&aviStrHdr[i], sizeof(AVISTREAMHEADER), 1, file) < sizeof(AVISTREAMHEADER))
return AVI_FILE_FORMAT_ERR;
if (aviStrHdr[i].fccType == SIGN_VIDS)
{
if (!(chunkSize = AviSeek(file, SIGN_STRF)))
return AVI_FILE_FORMAT_ERR;
/* Read wave header. */
if (AviFread(&aviBmpInfoHdr, sizeof(BITMAPINFOHEADER), 1, file) != sizeof(BITMAPINFOHEADER))
return AVI_FILE_FORMAT_ERR;
switch (aviBmpInfoHdr.biCompression)
{
case fccDIVX:
case fccdivx:
case fccDivX:
case fccDX50:
case fccdx50:
case fccXVID:
case fccxvid:
case fccXviD:
case fccFMP4:
case fccfmp4:
case fccMP4V:
stream_supported_flag.VideoCodecLib = VIDEO_CODEC_LIB_XVID;
stream_supported_flag.VideoSupportedFlag = TRUE;
break;
case fccdiv3:
case fccDIV3:
case fccDIV4:
case fccdiv4:
case fccDIV5:
case fccdiv5:
case fccDIV6:
case fccdiv6:
case fccMP43:
case fccmp43:
case fccMP42:
case fccmp42:
case fccDIV2:
case fccAP41:
stream_supported_flag.VideoCodecLib = VIDEO_CODEC_LIB_DIV3;
stream_supported_flag.VideoSupportedFlag = TRUE;
break;
case fccMJPG:
stream_supported_flag.VideoCodecLib = VIDEO_CODEC_LIB_MJPG;
stream_supported_flag.VideoSupportedFlag = TRUE;
break;
default:
stream_supported_flag.VideoCodecLib = VIDEO_CODEC_LIB_NULL;
stream_supported_flag.VideoSupportedFlag = FALSE;
return AVI_FILE_VIDEO_CODEC_ERR;
}
//----------------------------------------------
/*
請注意:讀取完BITMAPINFOHEADER後,不一定就過渡到了AUDIO的STRF,而且也不一定屬于vprp或者indx chunk,
因此,要特別注意,這里只有chunkSize是可靠的!
*/
AviFseek(file, chunkSize - sizeof(BITMAPINFOHEADER), SEEK_CUR);
//----------------------------------------------
}
else if (aviStrHdr[i].fccType == SIGN_AUDS)
{
/* Audio stream header. */
audioSteamID = i;
/******************************
Read wave format header.
*******************************/
/* Seek strf. */
if (!AviSeek(file, SIGN_STRF))
return AVI_FILE_FORMAT_ERR;
/* Read wave header. */
if (AviFread(&aviWavex, sizeof(WAVEFORMATEX), 1, file) < sizeof(WAVEFORMATEX))
return AVI_FILE_FORMAT_ERR;
/* Check audio codec. */
if(!((aviWavex.wFormatTag == SIGN_WAVE_FORMAT_MPEG)||(aviWavex.wFormatTag == SIGN_WAVE_FORAMT_MPEGLAYER3)
||(aviWavex.wFormatTag == SIGN_WAVE_FORAMT_AC3)||(aviWavex.wFormatTag == SIGN_WAVE_FORAMT_ADPCM)
||(aviWavex.wFormatTag == SIGN_WAVE_FORAMT_PCM))) //check audio codec
stream_supported_flag.AudioSupportedFlag = FALSE;
if (stream_supported_flag.VideoCodecLib == VIDEO_CODEC_LIB_MJPG)
if (aviWavex.wFormatTag == SIGN_WAVE_FORAMT_ADPCM)
{
stream_supported_flag.AudioSupportedFlag = TRUE;
aviStrHdr[i].dwSampleSize = 0; // 解決FFD/FFW錯誤
}
}
}
/* MJPG only support 320x240 */
if (stream_supported_flag.VideoCodecLib == VIDEO_CODEC_LIB_MJPG)
{
long avi_width, avi_height;
AviGetResolution(&avi_width, &avi_height);
if (avi_width != 320 || avi_height != 240)
return AVI_FILE_VIDEO_CODEC_ERR;
}
/*************************************************
[6] Get file pointer of 'idx1'.
**************************************************/
/*Get file pointer of 'idx1' for audio. */
if (AviGetChunkPointer(aviPointer->AudioIndex, SIGN_IDX1))
return AVI_FILE_INDX_ERR;
/* Get file pointer of 'idx1' for video. */
#ifdef ON_RKFS
aviPointer->VideoIndex->Clus = aviPointer->AudioIndex->Clus;
aviPointer->VideoIndex->Offset = aviPointer->AudioIndex->Offset;
#else
if (AviGetChunkPointer(aviPointer->VideoIndex, SIGN_IDX1))
return AVI_FILE_INDX_ERR;
#endif
/*************************************************
[7] Get file pointer of 'movi'.
**************************************************/
/* Get file pointer of 'movi' for audio. */
if (AviGetChunkPointer(aviPointer->AudioData, SIGN_MOVI))
return AVI_FILE_NO_MOVI_CHUNK;
/* Seek to start of bit stream. */
AviFseek(aviPointer->AudioData, 4, SEEK_CUR);
/* Get file pointer of 'movi' for video. */
#ifdef ON_RKFS
aviPointer->VideoData->Clus = aviPointer->AudioData->Clus;
aviPointer->VideoData->Offset = aviPointer->AudioData->Offset;
#else
if (AviGetChunkPointer(aviPointer->VideoData, SIGN_MOVI))
return AVI_FILE_NO_MOVI_CHUNK;
/* Seek to start of bit stream. */
AviFseek(aviPointer->VideoData, 4, SEEK_CUR);
#endif
/*************************************************
[8] Initialize.
**************************************************/
idx1Pos.Clus = aviPointer->VideoIndex->Clus;
idx1Pos.Offset = aviPointer->VideoIndex->Offset;
#if 0
if (AviIdxOffset(aviPointer->VideoIndex))
{
AviFseek(aviPointer->VideoData, 8, SEEK_SET);
}
#else
if (IsOdmlAvi(aviPointer->VideoIndex, aviPointer->VideoData))
{
AviFseek(aviPointer->VideoData, 8, SEEK_SET);
}
#endif
#ifdef ON_RKFS
/* Initialize file position information. */
moviPos.Clus = aviPointer->VideoData->Clus;
moviPos.Offset = aviPointer->VideoData->Offset;
/* Initialize video data position information, which is used for ffd/ffw. */
videoDataPosInfo[0].Clus = moviPos.Clus;
videoDataPosInfo[0].Offset = moviPos.Offset;
/* Initialize audio index position information, which is used for ffd/ffw. */
audioIndexPosInfo[0].filePos.Clus = aviPointer->VideoIndex->Clus;
audioIndexPosInfo[0].filePos.Offset = aviPointer->VideoIndex->Offset;
audioIndexPosInfo[0].audioBytePos = 0;
for (i = 0; i < AVI_AUDIO_POS_INFO_NUM; i ++)
{
audioIndexPosInfo[i].streamChunkNum = 0;
}
#endif
/* Initialize current chunk information. */
aviPointer->Video->ReadSize = 0;
aviPointer->Video->CurOffset = 0;
aviPointer->Video->CurChunkSize = 0;
aviPointer->Audio->ReadSize = 0;
aviPointer->Audio->CurOffset = 0;
aviPointer->Audio->CurChunkSize = 0;
/* Initialize chunk number. */
aviPointer->KeyFrameNum = 0;
aviPointer->TotalChunkNum = 0;
aviPointer->VideoChunkNum = 0;
aviPointer->AudioChunkNum = 0;
/* Initialize avi gobal variables. */
beingSkip = AVI_FRAME_SKIP_NONE; //Skip_mode 2 @LJN
skipResume = AVI_RESUME_OK;
audioBytePos = 0;
lastSkipPoint = 0;
/**********************************************
[NOTE] It may be wrong to calculate total audio
chunk number in this method.
***********************************************/
if (stream_supported_flag.AudioSupportedFlag == TRUE)
{
audioChunkNum = (indexSize / (sizeof(idx1))) - avih.dwTotalFrames;
if (!audioChunkNum)
{
audioChunkNum = 1;
}
else if (audioChunkNum > (indexSize / (sizeof(idx1))))
{
audioChunkNum = (indexSize / (sizeof(idx1)));
}
//audioTimePerChunk = (((avih.dwMicroSecPerFrame + 4)>>3)*avih.dwTotalFrames + (audioChunkNum >> 1))/(audioChunkNum-1);
}
else
{
audioChunkNum = 1;
}
/* Create seek table. */
#ifdef SEEK_TABLE
AviCreateSeekTab(aviPointer, indexSize);
if (totalKeyFrmNum == 0)
return AVI_FILE_INDX_ERR;
/* reset index file pointer */
#ifdef ON_RKFS
aviPointer->VideoIndex->Clus = idx1Pos.Clus;
aviPointer->VideoIndex->Offset = idx1Pos.Offset;
aviPointer->AudioIndex->Clus = idx1Pos.Clus;
aviPointer->AudioIndex->Offset = idx1Pos.Offset;
aviPointer->VideoData->Clus = moviPos.Clus;
aviPointer->VideoData->Offset = moviPos.Offset;
#else
if (AviGetChunkPointer(aviPointer->AudioIndex, SIGN_IDX1))
return AVI_FILE_INDX_ERR;
if (AviGetChunkPointer(aviPointer->AudioIndex, SIGN_IDX1))
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -