|
Posted on 2009-11-24 17:44 jacky_zz 阅读(4877) 评论(13) 编辑 收藏 引用 所属分类: C/C++
此代码在vs2008下编译,基于最新的ffmpeg版本(svn下载),搭建MSYS+MinGW编译环境编译,如何搭建,在google上能搜索到。 源码可在此 下载。 但除了aac和ogg格式播放出错,其余格式正常,不知为何,有ffmpeg开发经验的朋友请给予帮助,谢谢。代码贴于下方。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <windows.h> 4 #include <mmsystem.h> 5![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 6 #pragma comment(lib, "winmm.lib") 7![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 8 #ifdef __cplusplus 9![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) extern "C" { 10 #endif 11![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 12 #include "./include/avcodec.h" 13 #include "./include/avformat.h" 14 #include "./include/avutil.h" 15 #include "./include/mem.h" 16![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 17 #ifdef __cplusplus 18 } 19 #endif 20![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 21 #define BLOCK_SIZE 4608 22 #define BLOCK_COUNT 20 23![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 24 HWAVEOUT hWaveOut = NULL; 25![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 26 static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD, DWORD, DWORD); 27 static WAVEHDR* allocateBlocks(int size, int count); 28 static void freeBlocks(WAVEHDR* blockArray); 29 static void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size); 30![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 31 static CRITICAL_SECTION waveCriticalSection; 32 static WAVEHDR* waveBlocks; 33 static volatile unsigned int waveFreeBlockCount; 34 static int waveCurrentBlock; 35![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 36![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) typedef struct AudioState { 37 AVFormatContext* pFmtCtx; 38 AVCodecContext* pCodecCtx; 39 AVCodec* pCodec; 40 uint8_t audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 41 uint8_t* audio_buf; 42 unsigned int audio_buf_size; 43 int audio_buf_index; 44 AVPacket audio_pkt_temp; 45 AVPacket audio_pkt; 46 uint8_t* audio_pkt_data; 47 int audio_pkt_size; 48 int stream_index; 49 } AudioState; 50![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 51![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) int audio_decode_frame(AudioState* pState) { 52![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 53 AVPacket* pkt_temp = &pState->audio_pkt_temp; 54 AVPacket* pkt = &pState->audio_pkt; 55 AVCodecContext* dec= pState->pCodecCtx; 56 int len = 0, data_size = sizeof(pState->audio_buf1); 57 int err = 0; 58![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 59![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for( ; ; ) { 60![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) while (pkt_temp->size > 0) { 61 data_size = sizeof(pState->audio_buf1); 62 len = avcodec_decode_audio3(dec, (int16_t*)pState->audio_buf1, &data_size, pkt_temp); 63![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if (len < 0) { 64 pkt_temp->size = 0; 65 break; 66 } 67![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 68 pkt_temp->data += len; 69 pkt_temp->size -= len; 70![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 71 if (data_size <= 0) 72 continue; 73![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 74 pState->audio_buf = pState->audio_buf1; 75 return data_size; 76 } 77![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 78 if (pkt->data) 79 av_free_packet(pkt); 80![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 81 if((err = av_read_frame(pState->pFmtCtx, pkt)) < 0) 82 return -1; 83![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 84 pkt_temp->data = pkt->data; 85 pkt_temp->size = pkt->size; 86 } 87![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 88 return -1; 89 } 90![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 91![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) int main(int argc, char* argv[]) { 92 int err = 0; 93![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) AudioState audio_state = {0}; 94 unsigned int i = 0; 95 unsigned int ready = 0; 96![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 97![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) OPENFILENAME ofn = {0}; 98 char filename[MAX_PATH]; 99![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) WAVEFORMATEX wfx = {0}; 100 uint8_t buffer[BLOCK_SIZE]; 101 uint8_t* pbuffer = buffer; 102 AVInputFormat* iformat = NULL; 103 104 int audio_size = 0, data_size = 0; 105 int len = 0, len1 = 0, eof = 0, size = 0; 106![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 107 memset(&ofn, 0, sizeof(OPENFILENAME)); 108 ofn.lStructSize = sizeof(ofn); 109 ofn.hwndOwner = GetDesktopWindow(); 110 ofn.lpstrFile = filename; 111 ofn.lpstrFile[0] = '\0'; 112 ofn.nMaxFile = sizeof(filename) / sizeof(filename[0]); 113 ofn.lpstrFilter = _TEXT("All support files\0*.aac;*.ape;*.flac;*.mp3;*.mp4;*.mpc;*.ogg;*.tta;*.wma;*.wav\0"); 114 ofn.nFilterIndex = 1; 115 ofn.lpstrFileTitle = NULL; 116 ofn.nMaxFileTitle = 0; 117 ofn.lpstrInitialDir = NULL; 118 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 119![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 120 if (GetOpenFileName(&ofn) == FALSE) 121 return 0; 122![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 123 av_register_all(); 124![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 125 err = av_open_input_file(&audio_state.pFmtCtx, filename, NULL, 0, NULL); 126![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(err < 0) { 127 printf("can not open file %s.\n", filename); 128 return -1; 129 } 130![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 131 err = av_find_stream_info(audio_state.pFmtCtx); 132![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(err < 0) { 133 printf("can not find stream info of file %s.\n", filename); 134 return -1; 135 } 136![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 137![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for(i = 0; i < audio_state.pFmtCtx->nb_streams; i++) { 138![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(audio_state.pFmtCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) { 139 audio_state.pCodecCtx = audio_state.pFmtCtx->streams[i]->codec; 140 audio_state.stream_index = i; 141 ready = 1; 142 break; 143 } 144 } 145![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 146 if(!ready) 147 return -1; 148![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 149 audio_state.pCodec = avcodec_find_decoder(audio_state.pCodecCtx->codec_id); 150 if(!audio_state.pCodec || avcodec_open(audio_state.pCodecCtx, audio_state.pCodec) < 0) 151 return -1; 152![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 153 wfx.nSamplesPerSec = audio_state.pCodecCtx->sample_rate; 154 switch(audio_state.pCodecCtx->sample_fmt) 155![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) { 156 case SAMPLE_FMT_U8: 157 wfx.wBitsPerSample = 8; 158 break; 159 case SAMPLE_FMT_S16: 160 wfx.wBitsPerSample = 16; 161 break; 162 case SAMPLE_FMT_S32: 163 wfx.wBitsPerSample = 32; 164 break; 165 case SAMPLE_FMT_FLT: 166 wfx.wBitsPerSample = sizeof(double) * 8; 167 break; 168 default: 169 wfx.wBitsPerSample = 0; 170 break; 171 } 172![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 173 wfx.nChannels = FFMIN(2, audio_state.pCodecCtx->channels); 174 wfx.cbSize = 0; 175 wfx.wFormatTag = WAVE_FORMAT_PCM; 176 wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3; 177 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; 178![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 179 waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT); 180 waveFreeBlockCount = BLOCK_COUNT; 181 waveCurrentBlock = 0; 182![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 183 InitializeCriticalSection(&waveCriticalSection); 184![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 185 // open wave out device 186 if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, 187![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { 188 fprintf(stderr, "%s: unable to open wave mapper device\n", argv[0]); 189 ExitProcess(1); 190 } 191![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 192 // play loop 193![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for( ; ; ) { 194![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 195 len = BLOCK_SIZE; 196 size = 0; 197 pbuffer = buffer; 198![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 199 if(eof) 200 break; 201![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 202![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) while(len > 0) { 203![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(audio_state.audio_buf_index >= (int)audio_state.audio_buf_size) { 204 audio_size = audio_decode_frame(&audio_state); 205![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(audio_size < 0) { 206 if(size > 0) 207 break; 208![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 209 eof = 1; 210 break; 211 } 212![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 213 audio_state.audio_buf_size = audio_size; 214 audio_state.audio_buf_index = 0; 215 } 216![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 217 len1 = audio_state.audio_buf_size - audio_state.audio_buf_index; 218 if(len1 > len) 219 len1 = len; 220![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 221 memcpy(pbuffer, (uint8_t *)audio_state.audio_buf + audio_state.audio_buf_index, len1); 222![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 223 len -= len1; 224 pbuffer += len1; 225 size += len1; 226 audio_state.audio_buf_index += len1; 227 } 228![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 229 writeAudio(hWaveOut, (char*)buffer, size); 230 } 231![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 232 // wait for complete 233![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for( ; ; ) { 234 if(waveFreeBlockCount >= BLOCK_COUNT) 235 break; 236![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 237 Sleep(10); 238 } 239![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 240 for(i = 0; i < waveFreeBlockCount; i++) 241 if(waveBlocks[i].dwFlags & WHDR_PREPARED) 242 waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR)); 243![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 244 DeleteCriticalSection(&waveCriticalSection); 245 freeBlocks(waveBlocks); 246 waveOutClose(hWaveOut); 247![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 248 avcodec_close(audio_state.pCodecCtx); 249![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 250 system("pause"); 251 return 0; 252 } 253![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 254 static void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size) 255![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 256 WAVEHDR* current; 257 int remain; 258![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 259 current = &waveBlocks[waveCurrentBlock]; 260![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 261![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) while(size > 0) { 262![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 263 * first make sure the header we're going to use is unprepared 264 */ 265 if(current->dwFlags & WHDR_PREPARED) 266 waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 267![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 268![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if(size < (int)(BLOCK_SIZE - current->dwUser)) { 269 memcpy(current->lpData + current->dwUser, data, size); 270 current->dwUser += size; 271 break; 272 } 273![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 274 remain = BLOCK_SIZE - current->dwUser; 275 memcpy(current->lpData + current->dwUser, data, remain); 276 size -= remain; 277 data += remain; 278 current->dwBufferLength = BLOCK_SIZE; 279![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 280 waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); 281 waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); 282![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 283 EnterCriticalSection(&waveCriticalSection); 284 waveFreeBlockCount--; 285 LeaveCriticalSection(&waveCriticalSection); 286![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 287![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 288 * wait for a block to become free 289 */ 290 while(!waveFreeBlockCount) 291 Sleep(10); 292![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 293![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 294 * point to the next block 295 */ 296 waveCurrentBlock++; 297 waveCurrentBlock %= BLOCK_COUNT; 298![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 299 current = &waveBlocks[waveCurrentBlock]; 300 current->dwUser = 0; 301 } 302 } 303![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 304 static WAVEHDR* allocateBlocks(int size, int count) 305![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 306 char* buffer; 307 int i; 308 WAVEHDR* blocks; 309 DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count; 310![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 311![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 312 * allocate memory for the entire set in one go 313 */ 314 if((buffer = (char*)HeapAlloc( 315 GetProcessHeap(), 316 HEAP_ZERO_MEMORY, 317 totalBufferSize 318![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) )) == NULL) { 319 fprintf(stderr, "Memory allocation error\n"); 320 ExitProcess(1); 321 } 322![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 323![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 324 * and set up the pointers to each bit 325 */ 326 blocks = (WAVEHDR*)buffer; 327 buffer += sizeof(WAVEHDR) * count; 328![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for(i = 0; i < count; i++) { 329 blocks[i].dwBufferLength = size; 330 blocks[i].lpData = buffer; 331 buffer += size; 332 } 333![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 334 return blocks; 335 } 336![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 337 static void freeBlocks(WAVEHDR* blockArray) 338![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 339![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 340 * and this is why allocateBlocks works the way it does 341 */ 342 HeapFree(GetProcessHeap(), 0, blockArray); 343 } 344![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 345 static void CALLBACK waveOutProc( 346 HWAVEOUT hWaveOut, 347 UINT uMsg, 348 DWORD dwInstance, 349 DWORD dwParam1, 350 DWORD dwParam2 351 ) 352![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 353 int* freeBlockCounter = (int*)dwInstance; 354![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) /**//* 355 * ignore calls that occur due to opening and closing the 356 * device. 357 */ 358 if(uMsg != WOM_DONE) 359 return; 360![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 361 EnterCriticalSection(&waveCriticalSection); 362 (*freeBlockCounter)++; 363 LeaveCriticalSection(&waveCriticalSection); 364 }
Feedback
# re: ffmpeg小试 回复 更多评论
2009-11-24 17:47 by
最近开始研究 ffmpeg,关注一下博主。
# re: ffmpeg小试[未登录] 回复 更多评论
2009-11-24 20:05 by
FFmpeg有个耻辱名单,LZ听所过吗(⊙_⊙)?
# re: ffmpeg小试 回复 更多评论
2009-11-24 21:02 by
和我的程序有关系吗?况且我的这个程序附带了源码,虽然简单。
# re: ffmpeg小试 回复 更多评论
2009-11-24 21:19 by
不错,收藏,学习
# re: ffmpeg小试 回复 更多评论
2009-11-25 11:03 by
找到不能播放aac和ogg的问题了,原因是在ffmpeg里分配内存需要用av_malloc,释放内存要用av_free,因为windows和linux下内存分配存在不同,而ffmpeg在解码的时候是要检查内存是否对齐(内存对齐可以加快CPU的处理速度),所以在程序里在window环境下通过malloc或者通过数组的方式分配的内存不完全是内存对齐的,所以在遇到aac和ogg这种帧长度与其它音频格式帧长度不一致时,就有可能在运行时出错。修改后的代码如下,读者参照着自己修改即可。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#ifdef __cplusplus
extern "C" {
#endif
#include "./include/avcodec.h"
#include "./include/avformat.h"
#include "./include/avutil.h"
#include "./include/mem.h"
#ifdef __cplusplus
}
#endif
#define BLOCK_SIZE 4608
#define BLOCK_COUNT 20
HWAVEOUT hWaveOut = NULL;
static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD, DWORD, DWORD);
static WAVEHDR* allocateBlocks(int size, int count);
static void freeBlocks(WAVEHDR* blockArray);
static void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size);
static CRITICAL_SECTION waveCriticalSection;
static WAVEHDR* waveBlocks;
static volatile unsigned int waveFreeBlockCount;
static int waveCurrentBlock;
typedef struct AudioState {
AVFormatContext* pFmtCtx;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
//uint8_t* audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
uint8_t* audio_buf1;
uint8_t* audio_buf;
unsigned int audio_buf_size; /* in bytes */
unsigned int buffer_size;
int audio_buf_index; /* in bytes */
AVPacket audio_pkt_temp;
AVPacket audio_pkt;
uint8_t* audio_pkt_data;
int audio_pkt_size;
int stream_index;
} AudioState;
int audio_decode_frame(AudioState* pState) {
AVPacket* pkt_temp = &pState->audio_pkt_temp;
AVPacket* pkt = &pState->audio_pkt;
AVCodecContext* dec= pState->pCodecCtx;
int len = 0, data_size = sizeof(pState->audio_buf1);
int err = 0;
for( ; ; ) {
while (pkt_temp->size > 0) {
// data_size = sizeof(pState->audio_buf1);
data_size = pState->buffer_size;
len = avcodec_decode_audio3(dec, (int16_t*)pState->audio_buf1, &data_size, pkt_temp);
if (len < 0) {
pkt_temp->size = 0;
break;
}
pkt_temp->data += len;
pkt_temp->size -= len;
if (data_size <= 0)
continue;
pState->audio_buf = pState->audio_buf1;
return data_size;
}
if (pkt->data)
av_free_packet(pkt);
if((err = av_read_frame(pState->pFmtCtx, pkt)) < 0)
return -1;
pkt_temp->data = pkt->data;
pkt_temp->size = pkt->size;
}
return -1;
}
int main(int argc, char* argv[]) {
int err = 0;
AudioState audio_state = {0};
unsigned int i = 0;
unsigned int ready = 0;
OPENFILENAME ofn = {0};
char filename[MAX_PATH];
WAVEFORMATEX wfx = {0};
uint8_t buffer[BLOCK_SIZE];
uint8_t* pbuffer = buffer;
AVInputFormat* iformat = NULL;
int audio_size = 0, data_size = 0;
int len = 0, len1 = 0, eof = 0, size = 0;
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = GetDesktopWindow();
ofn.lpstrFile = filename;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(filename) / sizeof(filename[0]);
ofn.lpstrFilter = _TEXT("All support files\0*.aac;*.ape;*.flac;*.mp3;*.mp4;*.mpc;*.ogg;*.tta;*.wma;*.wav\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == FALSE)
return 0;
av_register_all();
err = av_open_input_file(&audio_state.pFmtCtx, filename, NULL, 0, NULL);
if(err < 0) {
printf("can not open file %s.\n", filename);
return -1;
}
err = av_find_stream_info(audio_state.pFmtCtx);
if(err < 0) {
printf("can not find stream info of file %s.\n", filename);
return -1;
}
for(i = 0; i < audio_state.pFmtCtx->nb_streams; i++) {
if(audio_state.pFmtCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
audio_state.pCodecCtx = audio_state.pFmtCtx->streams[i]->codec;
audio_state.stream_index = i;
ready = 1;
break;
}
}
if(!ready)
return -1;
audio_state.pCodec = avcodec_find_decoder(audio_state.pCodecCtx->codec_id);
if(!audio_state.pCodec || avcodec_open(audio_state.pCodecCtx, audio_state.pCodec) < 0)
return -1;
wfx.nSamplesPerSec = audio_state.pCodecCtx->sample_rate;
switch(audio_state.pCodecCtx->sample_fmt)
{
case SAMPLE_FMT_U8:
wfx.wBitsPerSample = 8;
break;
case SAMPLE_FMT_S16:
wfx.wBitsPerSample = 16;
break;
case SAMPLE_FMT_S32:
wfx.wBitsPerSample = 32;
break;
case SAMPLE_FMT_FLT:
wfx.wBitsPerSample = sizeof(double) * 8;
break;
default:
wfx.wBitsPerSample = 0;
break;
}
wfx.nChannels = FFMIN(2, audio_state.pCodecCtx->channels);
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
waveFreeBlockCount = BLOCK_COUNT;
waveCurrentBlock = 0;
InitializeCriticalSection(&waveCriticalSection);
// open wave out device
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc,
(DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
fprintf(stderr, "%s: unable to open wave mapper device\n", argv[0]);
ExitProcess(1);
}
// allocate memory
audio_state.audio_buf1 =(uint8_t*)av_malloc(buffer_size);
audio_state.buffer_size = buffer_size;
// play loop
for( ; ; ) {
len = BLOCK_SIZE;
size = 0;
pbuffer = buffer;
if(eof)
break;
while(len > 0) {
if(audio_state.audio_buf_index >= (int)audio_state.audio_buf_size) {
audio_size = audio_decode_frame(&audio_state);
if(audio_size < 0) {
if(size > 0)
break;
eof = 1;
break;
}
audio_state.audio_buf_size = audio_size;
audio_state.audio_buf_index = 0;
}
len1 = audio_state.audio_buf_size - audio_state.audio_buf_index;
if(len1 > len)
len1 = len;
memcpy(pbuffer, (uint8_t *)audio_state.audio_buf + audio_state.audio_buf_index, len1);
len -= len1;
pbuffer += len1;
size += len1;
audio_state.audio_buf_index += len1;
}
writeAudio(hWaveOut, (char*)buffer, size);
}
// free allocated memory
av_free(audio_state.audio_buf1);
audio_state.audio_buf1 = NULL;
// wait for complete
for( ; ; ) {
if(waveFreeBlockCount >= BLOCK_COUNT)
break;
Sleep(10);
}
for(i = 0; i < waveFreeBlockCount; i++)
if(waveBlocks[i].dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));
DeleteCriticalSection(&waveCriticalSection);
freeBlocks(waveBlocks);
waveOutClose(hWaveOut);
avcodec_close(audio_state.pCodecCtx);
system("pause");
return 0;
}
static void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size)
{
WAVEHDR* current;
int remain;
current = &waveBlocks[waveCurrentBlock];
while(size > 0) {
/*
* first make sure the header we're going to use is unprepared
*/
if(current->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));
if(size < (int)(BLOCK_SIZE - current->dwUser)) {
memcpy(current->lpData + current->dwUser, data, size);
current->dwUser += size;
break;
}
remain = BLOCK_SIZE - current->dwUser;
memcpy(current->lpData + current->dwUser, data, remain);
size -= remain;
data += remain;
current->dwBufferLength = BLOCK_SIZE;
waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
EnterCriticalSection(&waveCriticalSection);
waveFreeBlockCount--;
LeaveCriticalSection(&waveCriticalSection);
/*
* wait for a block to become free
*/
while(!waveFreeBlockCount)
Sleep(10);
/*
* point to the next block
*/
waveCurrentBlock++;
waveCurrentBlock %= BLOCK_COUNT;
current = &waveBlocks[waveCurrentBlock];
current->dwUser = 0;
}
}
static WAVEHDR* allocateBlocks(int size, int count)
{
char* buffer;
int i;
WAVEHDR* blocks;
DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count;
/*
* allocate memory for the entire set in one go
*/
if((buffer = (char*)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
totalBufferSize
)) == NULL) {
fprintf(stderr, "Memory allocation error\n");
ExitProcess(1);
}
/*
* and set up the pointers to each bit
*/
blocks = (WAVEHDR*)buffer;
buffer += sizeof(WAVEHDR) * count;
for(i = 0; i < count; i++) {
blocks[i].dwBufferLength = size;
blocks[i].lpData = buffer;
buffer += size;
}
return blocks;
}
static void freeBlocks(WAVEHDR* blockArray)
{
/*
* and this is why allocateBlocks works the way it does
*/
HeapFree(GetProcessHeap(), 0, blockArray);
}
static void CALLBACK waveOutProc(
HWAVEOUT hWaveOut,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2
)
{
int* freeBlockCounter = (int*)dwInstance;
/*
* ignore calls that occur due to opening and closing the
* device.
*/
if(uMsg != WOM_DONE)
return;
EnterCriticalSection(&waveCriticalSection);
(*freeBlockCounter)++;
LeaveCriticalSection(&waveCriticalSection);
}
# re: ffmpeg小试 回复 更多评论
2009-12-21 18:44 by
你的下载包里面,没有.avcodec-52.dll 所以无法运行.
# re: ffmpeg小试 回复 更多评论
2009-12-22 11:41 by
当初我也做了一个MSYS+MinGW,想研究一下ffmpeg.发现MSYS本质不是应用于linux的,如果做windows开发,用ffmpeg sdk好像足够了。
偶没有时间做了,那位大虾搭建了cygwin+MinGW,希望共同研究一下ffmpeg在linux下特别时嵌入式下的应用。
# re: ffmpeg小试 回复 更多评论
2011-06-17 00:13 by
谢谢你的代码。问题已经解决了。
# re: ffmpeg小试 回复 更多评论
2011-07-09 23:20 by
感谢楼主的代码。把av_read_frame那两行改成下面这样,就可以直接播绝大部分视频文件了(声音部分)。
pkt->stream_index = -1; while(pkt->stream_index != pState->stream_index) { if((err = av_read_frame(pState->pFmtCtx, pkt)) < 0) return -1; }
# re: ffmpeg小试 回复 更多评论
2011-12-13 17:44 by
暴风是不是你弄的
# re: ffmpeg小试[未登录] 回复 更多评论
2011-12-26 15:34 by
@glueless lace wigs
不是,要是有那本事,就不玩了。
# re: ffmpeg小试[未登录] 回复 更多评论
2012-01-25 01:57 by
谢谢jackzz,在我眼里你已经很牛了,刚刚在WinCE上用你的修正后代码测试了一下mp3、flac、ape、ogg、wma、wav,都播得很happy,不错不错。
# re: ffmpeg小试 回复 更多评论
2013-01-05 21:45 by
我的QQ是475316440~麻烦加一下,关于解码,我有一些疑问~thanks~ 简述就是avcodec_decode_audio3((AVCodecContext *avctx, int16_t *samples,int *frame_size_ptr,AVPacket *avpkt))解出一帧的数据,这写数据,不总是在samples的最前面顺序排列?
|