各位大哥帮个忙,小弟写的avi播放时没有视频只有音频啊~~~~
//格式转换线程void CodecThread (void * param)
{
CKPlayerDlg * pDlg = (CKPlayerDlg *)param;
AVCodec *decoder = NULL;
AVCodec *encoder = NULL;
AVCodecContext *pCodecCtx264 = NULL;
AVCodecContext *pCodecCtxMpeg = NULL;
AVFrame * picture1 = NULL; //从264解出的yuv数据
AVFrame * picture2 = NULL; //从yuv向MPEG2输入的数据
unsigned int out_size = 0;
int outbuf_size = 200000; //mpeg2编码后一帧最大长度
BYTE * outbuf = NULL;
BYTE * yuv = NULL;
BYTE *dst_ori = NULL;
int videoWidth = 0;
int videoHeight = 0;
int bpp = 24;
FILE * fp264 = NULL;
FILE * fpspx = NULL;
FILE * fppcm = NULL;
POSITION pos = 0;
CString FileName;
int remain_264 = 0;
unsigned int i = 0;
int frame_count = 0;
int bytes_used = 0;
int got_picture = 0;
int total_frame = 0;
int play_time = 0;
KONESTREAMHEADER File_head = {0};
WAVEFILEHEAD m_wavhead;
WAVEFORMATEX wfx;
int m_Size = 0;
int Vedio_enable = 1;
/*Holds the audio that will be written to file (16 bits per sample)*/
short pcm_buf [160*3] = {0};
/*Speex handle samples as float, so we need an array of floats*/
int frame_len = 60;
char spx_buf [100] = {0};
/*Holds the state of the decoder*/
void * state = NULL;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;
int tmp = 0;
BOOL firstrun = TRUE;
CString m_strPath;
CString file;
GetModuleFileName(NULL,m_strPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
m_strPath.ReleaseBuffer();
int nPos;
nPos=m_strPath.ReverseFind('\\');
m_strPath=m_strPath.Left(nPos);
BYTE *buf_264;
buf_264 = new BYTE[1024*100];
if (!buf_264)
{
AfxMessageBox("申请内存失败!");
return;
}
// wav头初始化
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 1;
wfx.nSamplesPerSec = WISA_POOR;
wfx.nAvgBytesPerSec = 1 * WISA_POOR * 16 / 8;
wfx.nBlockAlign = 16 * 1 / 8;
wfx.wBitsPerSample = 16;
wfx.cbSize = 0;
memcpy(m_wavhead.szRIFF, "RIFF", 4);
m_wavhead.dwTotalSize = m_Size + sizeof(WAVEFILEHEAD) - 8;
memcpy(m_wavhead.szWAVE, "WAVE", 4);
memcpy(m_wavhead.szFMT, "fmt ", 4);
m_wavhead.dwChunk0Size = 16;
memcpy(m_wavhead.Format, &wfx, 16);
memcpy(m_wavhead.szDATA, "data", 4);
m_wavhead.dwChunk1Size = m_Size;
//音频初始化
/*Create a new decoder state in narrowband mode*/
state = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));
/*Set the perceptual enhancement on*/
tmp = 1;
speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp);
/*Initialization of the structure that holds the bits*/
speex_bits_init(&bits);
//音频初始化
//解码H.264
decoder = avcodec_find_decoder(CODEC_ID_H264);
if (!decoder)
{
AfxMessageBox ("加载解码器失败");
goto exit0;
}
pCodecCtx264 = avcodec_alloc_context();
pCodecCtxMpeg = avcodec_alloc_context();
picture1 = avcodec_alloc_frame();
picture2 = avcodec_alloc_frame();
if (decoder->capabilities & CODEC_CAP_TRUNCATED)
pCodecCtx264->flags |= CODEC_FLAG_TRUNCATED; //we dont send complete frames
// for some codecs, such as msmpeg4 and mpeg4, width and height
// MUST be initialized there because these info are not available
// in the bitstream
if (avcodec_open(pCodecCtx264, decoder) < 0)
{
AfxMessageBox ("打开解码器失败");
goto exit1;
}
encoder = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
if (!encoder)
{
AfxMessageBox ("加载编码器失败\n");
goto exit2;
}
pDlg->m_playprogress.ShowWindow(SW_SHOW);
////////////////////////////////////////////打开文件///////////////////////////////////////
FileName = pDlg->m_FileName;
fp264 = fopen (FileName.LockBuffer(), "rb");
if (!fp264)
{
AfxMessageBox ("打开原始视频文件失败");
Vedio_enable = 0;
goto exit2;
}
else
{
Vedio_enable = 1;
// Vedio_enable = 0;
// FileName = FileName.Left(FileName.GetLength()-4);
}
// if(Vedio_enable)
{
FileName = FileName.Left(FileName.GetLength()-4);
file = FileName;
int pp=0,ll=0;
while ((ll=file.Find('\\',pp+1))>0)
{
pp = ll;
}
file = file.Right(file.GetLength()-pp);
m_strPath += file;
FileName += ".aud"; //将扩展名替换为".spx"
fpspx = fopen (FileName.LockBuffer(), "rb");
if (!fpspx)
{
AfxMessageBox ("打开原始音频文件失败");
pDlg->m_bAudioEnable=FALSE;
// goto exit2;
}
else
{
pDlg->m_bAudioEnable=TRUE;
}
if (pDlg->m_bAudioEnable)
{
fseek (fpspx, sizeof(KONESTREAMHEADER), SEEK_CUR);
// m_strPath = m_strPath.Left(m_strPath.GetLength()-4);
m_strPath += ".wav"; //将扩展名替换为".spx"
fppcm = fopen (m_strPath.LockBuffer(), "wb");
if (!fppcm)
{
AfxMessageBox ("打开原始音频文件失败");
goto exit2;
}
fwrite(&m_wavhead,1, sizeof(WAVEFILEHEAD),fppcm);
}
if(Vedio_enable)
{
if (1 != fread (&File_head, sizeof(KONESTREAMHEADER), 1, fp264)) //读取文件头
{
AfxMessageBox ("读取原始视频文件失败");
goto exit2;
}
if (NULL == strstr (File_head.fcc, "KONE"))
{
AfxMessageBox("原始视频文件已损坏");
goto exit2;
}
//put sample parameters
pCodecCtxMpeg->bit_rate = 4000000;
//resolution must be a multiple of two
pCodecCtxMpeg->width = File_head.width;
pCodecCtxMpeg->height = File_head.height;
//frames per second
pCodecCtxMpeg->time_base.num = 1;
pCodecCtxMpeg->time_base.den = 25;
pCodecCtxMpeg->gop_size = 10; //emit one intra frame every ten frames
pCodecCtxMpeg->max_b_frames = 1;
pCodecCtxMpeg->pix_fmt = PIX_FMT_YUV420P; // PIX_FMT_BGR24
m_Size = 0;
}
//avi初始化
AVIFileInit();
//
// Create AVI file
//
if (pDlg->m_bAudioEnable)
{
m_strPath = m_strPath.Left(m_strPath.GetLength()-4);
}
m_strPath += ".avi";
PAVIFILE pAviFile = NULL;
HRESULT hr = AVIFileOpen( &pAviFile, m_strPath, OF_WRITE | OF_CREATE, NULL );
if ( 0 != hr )
{
ASSERT( FALSE );
return;
}
//
// Create AVI video stream
//
AVISTREAMINFO strhdr;
PAVISTREAM pAviStream = NULL;
BITMAPINFOHEADER bih;
int nFrames = 0;
UINT pitch;
UINT biSizeImage;
memset( &strhdr, 0, sizeof( strhdr ) );
fseek (fp264, sizeof(KONESTREAMHEADER), SEEK_SET);
if (1 != fread (&i, 4, 1, fp264))
{
// break;
}
fseek (fp264, 4, SEEK_CUR); //忽略时间戳
i -= 4; //去除时间戳长度
if (i<0 || i>102400)
{
AfxMessageBox ("视频文件异常");
goto exit2;
}
if (i != fread(buf_264+remain_264, 1, i, fp264))
{
// break;
}
remain_264 += i;
bytes_used = avcodec_decode_video(pCodecCtx264, picture1, &got_picture, buf_264, remain_264);
//avi 视频初始化
// Calc image size
videoWidth = pCodecCtx264->width;
videoHeight = pCodecCtx264->height;
strhdr.fccType = streamtypeVIDEO;
strhdr.fccHandler = 0;
strhdr.dwScale = 1;
strhdr.dwRate = 25;
pitch = ( videoWidth * bpp + 31 ) / 32 * 4;
biSizeImage = ( videoWidth * bpp + 31 ) / 32 * 4 * videoHeight;
strhdr.dwSuggestedBufferSize = biSizeImage;
SetRect( &strhdr.rcFrame, 0, 0, videoWidth, videoHeight );
// And create the stream;
hr = AVIFileCreateStream( pAviFile, &pAviStream, &strhdr );
if ( 0 != hr )
{
ASSERT( FALSE );
AVIFileRelease( pAviFile );
pAviFile = NULL;
return;
}
//
// Set stream format
//
memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = videoWidth;
bih.biHeight = videoHeight;
bih.biBitCount = 0;
bih.biCompression = '462H';
bih.biSizeImage = 0;
bih.biPlanes = 1;
hr = AVIStreamSetFormat( pAviStream, 0, &bih, sizeof( bih ) );
if ( 0 != hr )
{
ASSERT( FALSE );
AVIStreamClose( pAviStream );
pAviStream = NULL;
AVIFileRelease( pAviFile );
pAviFile = NULL;
}
//
// Create AVI Audio stream
//
AVISTREAMINFO m_AVIAudioStreamInfo;
PAVISTREAM m_aviAudeoStream;
int nAudios = 0;
//设置音频流格式
m_AVIAudioStreamInfo.fccType = streamtypeAUDIO;
m_AVIAudioStreamInfo.dwScale = 1; //声道数
m_AVIAudioStreamInfo.dwRate = 8000; //Hz
m_AVIAudioStreamInfo.dwSuggestedBufferSize = 32768;
m_AVIAudioStreamInfo.dwSampleSize = 1;
// m_AVIAudioStreamInfo.fccHandler = mmioFOURCC('g','7','1','1');
m_AVIAudioStreamInfo.fccHandler = 0;
m_AVIAudioStreamInfo.dwFlags = 0;
m_AVIAudioStreamInfo.dwCaps = 0;
m_AVIAudioStreamInfo.wPriority = 0;
m_AVIAudioStreamInfo.wLanguage = 0;
m_AVIAudioStreamInfo.dwStart = 0;
m_AVIAudioStreamInfo.dwInitialFrames = 1;
m_AVIAudioStreamInfo.dwQuality = 0;
m_AVIAudioStreamInfo.rcFrame.bottom = 0;
m_AVIAudioStreamInfo.rcFrame.left = 0;
m_AVIAudioStreamInfo.rcFrame.right = 0;
m_AVIAudioStreamInfo.rcFrame.top = 0;
m_AVIAudioStreamInfo.dwEditCount = 0;
m_AVIAudioStreamInfo.dwFormatChangeCount = 0;
m_AVIAudioStreamInfo.dwLength = 0;
if (pDlg->m_bAudioEnable)
{
AVIFileCreateStream(pAviFile,&m_aviAudeoStream,(AVISTREAMINFO *)&m_AVIAudioStreamInfo);
}
//音频
if (pDlg->m_bAudioEnable)
{
WAVEFORMATEX waveFormat;
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 1;
waveFormat.nSamplesPerSec = WISA_POOR;
waveFormat.nAvgBytesPerSec = WISA_POOR * 16 * 1 / 8;
waveFormat.nBlockAlign = 16 * 1 / 8;
waveFormat.wBitsPerSample = 16;
waveFormat.cbSize = 0;
AVIStreamSetFormat(m_aviAudeoStream,0,&waveFormat,sizeof(waveFormat));
//音频格式转换
while (1)
{
/*Read the "packet" encoded by sampleenc*/
if (fseek (fpspx, 4, SEEK_CUR)) //跳过帧长度4字节
{
break;
}
if (fseek (fpspx, 4, SEEK_CUR)) //跳过时间戳
{
break;
}
if (1 != fread (spx_buf, frame_len, 1, fpspx)) //读取一帧20字节
{
break;
}
for (int j=0; j<3; j++) //分三次解码,每次20字节
{
/*Copy the data into the bit-stream struct*/
speex_bits_read_from (&bits, spx_buf+j*20, 20);
/*Decode the data*/
speex_decode_int (state, &bits, (__int16 *)pcm_buf+j*160);
}
if (0 >= fwrite ((char *)pcm_buf, 1, 160*2*3, fppcm)) // pcmbuf是short类型的
{
break;
}
m_Size += 160*2*3;
hr = AVIStreamWrite( m_aviAudeoStream, nAudios, 1, pcm_buf, 160*2*3, AVIIF_KEYFRAME, NULL, NULL );
nAudios++;
}
m_wavhead.dwTotalSize = m_Size + sizeof(WAVEFILEHEAD) - 8;
m_wavhead.dwChunk1Size = m_Size;
fseek(fppcm,0, SEEK_SET);
fwrite(&m_wavhead,1, sizeof(WAVEFILEHEAD),fppcm);
AVIStreamClose( m_aviAudeoStream );
m_aviAudeoStream = NULL;
}
//视频
if(Vedio_enable)
{
//设置进度条
if (!pDlg->m_bVideoEnable)
{
total_frame = GetTotalFrame (fp264);
//总进度
pDlg->m_pro.SetRange(0,(short)File_head.totalFrames*5/3);
pDlg->m_pro.SetStep(1);
pDlg->m_pro.SetPos(0);
frame_count = 0;
::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_TISHI, "转换进度");
//pDlg->m_playprogress.SetRange(0,total_frame);
//pDlg->m_playprogress.SetPos(1);
}
fseek (fp264, sizeof(KONESTREAMHEADER), SEEK_SET); //忽略视频文件头
int aa=1;
//开始解码
while (1)
{
//读取第二帧
if (1 != fread (&i, 4, 1, fp264))
{
break;
}
fseek (fp264, 4, SEEK_CUR); //忽略时间戳
i -= 4; //去除时间戳长度
if (i<0 || i>102400)
{
AfxMessageBox ("视频文件异常");
goto exit2;
}
memset(buf_264,0,1024*3);
if (i != fread(buf_264, 1, i, fp264))
{
break;
}
hr = AVIStreamWrite( pAviStream, nFrames, 1, buf_264, i, AVIIF_KEYFRAME, NULL, NULL );
remain_264 -= i;
if (!pDlg->m_bVideoEnable)
{
pDlg->m_pro.StepIt();
}
nFrames++;
}
AVIStreamClose( pAviStream );
pAviStream = NULL;
}
::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_TISHI, "转换完成");
// some codecs, such as MPEG, transmit the I and P frame with a latency of one frame.
// You must do the following to have a chance to get the last frame of the video
if ( pAviFile )
{
AVIFileRelease( pAviFile );
pAviFile = NULL;
}
AVIFileExit();
if (fp264)
{
fclose (fp264);
}
// if (fpmpeg)
// {
// fclose (fpmpeg);
// }
if (fpspx)
{
fclose (fpspx);
}
if (fppcm)
{
fclose (fppcm);
}
AfxMessageBox("格式转换完成");
pDlg->CodecEnable = FALSE;
return;
}
exit2:
avcodec_close(pCodecCtxMpeg);
av_free(pCodecCtxMpeg);
exit1:
avcodec_close(pCodecCtx264);
av_free(pCodecCtx264);
exit0:
/*Destroy the decoder state*/
speex_decoder_destroy(state);
/*Destroy the bit-stream truct*/
speex_bits_destroy(&bits);
delete [] buf_264;
if (picture1)
{
av_free (picture1);
}
if (picture2)
{
av_free (picture2);
}
if (yuv)
{
free (yuv);
}
if (outbuf)
{
free (outbuf);
}
if (fp264)
{
fclose (fp264);
}
// if (fpmpeg)
// {
// fclose (fpmpeg);
// }
if (fpspx)
{
fclose (fpspx);
}
if (fppcm)
{
fclose (fppcm);
}
if (pDlg->FullWindows)
{
pDlg->OnFullScreen();
}
::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_STATIC_STATUS, "转换格式完成");
pDlg->CodecEnable = FALSE;
}