先介紹幾個api函數:
AVIFileOpen
AVIFileCreateStream
AVIStreamSetFormat
AVIStreamWrite
字面意思大家都應該理解,就不多說了。AVIFileCreateStream ,AVIStreamSetFormat這兩個東西很重要,對於流方式操作大家都明白,可是設置流的格式不一定懂,這個是api根據avi文件格式提出的一個特殊概念,因爲avi如同一個建立好的抽屜,每個抽屜裏面放什麼東西,需要個說明,這個AVIStreamSetFormat就是在寫入數據前先寫個標籤進去,以方便播放器調用正確的解碼。
OpenMp3File的功能是打開mp3文件,並讀取一個幀的幀頭信息,本程序只考慮了bitrate恆定的mp3的讀寫,不考慮變體。
對於mp3幀頭的讀寫,大家可以在網上找mp3格式自己解讀,如果有需要詳細說明的朋友,請留言。
BOOL AddMp3ToAvi(const char *pStrAvi,const char *pStrMp3,int StartTime)
{
PAVIFILE aviFile;
FILE* mp3File;
DscHeader fHeader;
/*打開AVIFILE和MP3 FILE,進行時間判斷*/
int Ret =
AVIFileOpen(&aviFile,pStrAvi,OF_READWRITE|OF_SHARE_EXCLUSIVE,NULL);
if(Ret != 0)
{
AfxMessageBox("Failed to Open the AVI File!");
return FALSE;
}
mp3File = OpenMp3File(pStrMp3,&fHeader);
if(mp3File == NULL)
{
AfxMessageBox("Failed to Open the MP3 File!");
AVIFileRelease(aviFile);
return FALSE;
}
/*獲得 AVI 視頻流的信息*/
PAVISTREAM videoStream;
AVIFileGetStream(aviFile,&videoStream,streamtypeVIDEO,0);
VERIFY(videoStream);
/*獲得相配的MP3 禎數:26ms / frame*/
double VideoFrmTime = (double)
AVIStreamLengthTime(videoStream) / AVIStreamLength(videoStream);
/*新建音頻流爲寫入作準備*/
PAVISTREAM audioStream;
AVISTREAMINFO audioInf;
ZeroMemory(&audioInf,sizeof(AVISTREAMINFO));
audioInf.fccType
= streamtypeAUDIO;
audioInf.dwRate =
(fHeader.dwBitRate *1000) / 8;
//Ret = *fHeader.dwChannel;
audioInf.dwScale =1;
audioInf.dwSampleSize = 1;
audioInf.dwQuality = (DWORD)-1;
Ret =
AVIFileCreateStream(aviFile,&audioStream,&audioInf);
#ifdef _DEBUG
if(Ret != 0)
{
TRACE("AVIFileCreateStream Failure!!/n");
}
#endif
MPEGLAYER3WAVEFORMAT mp3fmt;
ZeroMemory(&mp3fmt,sizeof(MPEGLAYER3WAVEFORMAT));
mp3fmt.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3 ;
mp3fmt.wfx.nChannels = fHeader.dwChannel;
mp3fmt.wfx.nSamplesPerSec = fHeader.dwSampleRate;
mp3fmt.wfx.wBitsPerSample = 0;
mp3fmt.wfx.nAvgBytesPerSec = audioInf.dwRate ;
mp3fmt.wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;/**/
mp3fmt.wfx.nBlockAlign = 1;// ((fHeader.dwBitRate *1000 )/
fHeader.dwSampleRate);// (0 ==Ret)? 1:Ret;;
mp3fmt.wID = 1;
mp3fmt.fdwFlags = 2;
mp3fmt.nBlockSize = fHeader.dwFSize;
mp3fmt.nFramesPerBlock = 1;
mp3fmt.nCodecDelay = 0 ;
Ret =
AVIStreamSetFormat(audioStream,0,&mp3fmt,sizeof(MPEGLAYER3WAVEFORMAT));
#ifdef _DEBUG
if(Ret != 0)
{
TRACE("Set Avi Mp3 Format Failure!!/n");
}
#endif
int frSize;
int audioFrmNum =0;
double escTime = 0;
double blocktimesize = (double)1000.0 * ((fHeader.dwVersion
== VERSION1)?1152:576) / fHeader.dwSampleRate ;
char *buf = new char[2048];
#ifdef _DEBUG
static double vtotal;
static double atotal;
#endif
//int num = AVIStreamLength(videoStream);
//int CacheFrames =
0;//(AVIStreamLength(videoStream) > 1000)?(int)(1000/VideoFrmTime):2
;/*一秒鐘的緩衝*/
for(int i =AVIStreamStart(videoStream);i
<AVIStreamEnd(videoStream);i++ )
{
#ifdef _DEBUG
vtotal += VideoFrmTime;
#endif
escTime += VideoFrmTime;
while(1)
{
if(escTime -blocktimesize <0)
break;
frSize = fHeader.dwFSize;
if(GetMp3Frame(mp3File,(UCHAR
*)buf,&fHeader) == ENDFILE)
{
AVIStreamWrite(audioStream,audioFrmNum,1,buf,frSize,AVIIF_KEYFRAME,NULL,NULL);
goto L;
}
Ret =
AVIStreamWrite(audioStream,audioFrmNum,1,buf,frSize,NULL,NULL,NULL);
escTime -= blocktimesize;
#ifdef _DEBUG
atotal += blocktimesize;
#endif
audioFrmNum++;
#ifdef _DEBUG
if(Ret != 0)
{
TRACE("Write To Avi
Failure:%d!!/n",Ret);
break;
}
#endif
}
}
L:
fclose(mp3File);
AVIStreamRelease(audioStream);
AVIStreamRelease(videoStream);
AVIFileRelease(aviFile);
delete []buf;
return (Ret == 0);