[C/C++] ffmpeg小试

此代码在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
  6 #pragma comment(lib,  " winmm.lib " )
  7
  8 #ifdef __cplusplus
  9 extern   " C "   {
 10#endif
 11
 12#include "./include/avcodec.h"
 13#include "./include/avformat.h"
 14#include "./include/avutil.h"
 15#include "./include/mem.h"
 16
 17#ifdef __cplusplus
 18}

 19 #endif
 20
 21 #define  BLOCK_SIZE  4608
 22 #define  BLOCK_COUNT 20
 23
 24 HWAVEOUT hWaveOut  =  NULL;
 25
 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
 31 static  CRITICAL_SECTION waveCriticalSection;
 32 static  WAVEHDR *          waveBlocks;
 33 static   volatile  unsigned  int      waveFreeBlockCount;
 34 static   int               waveCurrentBlock;
 35
 36 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
 51 int  audio_decode_frame(AudioState *  pState)  {
 52
 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
 59    for( ; ; ) {
 60        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            if (len < 0{
 64                pkt_temp->size = 0;
 65                break;
 66            }

 67
 68            pkt_temp->data += len;
 69            pkt_temp->size -= len;
 70
 71            if (data_size <= 0)
 72                continue;
 73
 74            pState->audio_buf = pState->audio_buf1;
 75            return data_size;
 76        }

 77
 78        if (pkt->data)
 79            av_free_packet(pkt);
 80
 81        if((err = av_read_frame(pState->pFmtCtx, pkt)) < 0)
 82            return -1;
 83
 84        pkt_temp->data = pkt->data;
 85        pkt_temp->size = pkt->size;
 86    }

 87
 88    return -1;
 89}

 90
 91 int  main( int  argc,  char *  argv[])  {
 92    int err = 0;
 93    AudioState audio_state = {0};
 94    unsigned int i = 0;
 95    unsigned int ready = 0;
 96
 97    OPENFILENAME ofn = {0};
 98    char filename[MAX_PATH];
 99    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
107    memset(&ofn, 0sizeof(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
120    if (GetOpenFileName(&ofn) == FALSE)
121        return 0;
122
123    av_register_all();
124
125    err = av_open_input_file(&audio_state.pFmtCtx, filename, NULL, 0, NULL);
126    if(err < 0{
127        printf("can not open file %s.\n", filename);
128        return -1;
129    }

130
131    err = av_find_stream_info(audio_state.pFmtCtx);
132    if(err < 0{
133        printf("can not find stream info of file %s.\n", filename);
134        return -1;
135    }

136
137    for(i = 0; i < audio_state.pFmtCtx->nb_streams; i++{
138        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
146    if(!ready)
147        return -1;
148
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
153    wfx.nSamplesPerSec  = audio_state.pCodecCtx->sample_rate;
154    switch(audio_state.pCodecCtx->sample_fmt)
155    {
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
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
179    waveBlocks         = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
180    waveFreeBlockCount = BLOCK_COUNT;
181    waveCurrentBlock   = 0;
182
183    InitializeCriticalSection(&waveCriticalSection);
184
185    // open wave out device
186    if(waveOutOpen(&hWaveOut, WAVE_MAPPER,  &wfx, (DWORD_PTR)waveOutProc, 
187        (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
192    // play loop
193    for( ; ; ) {
194
195        len = BLOCK_SIZE;
196        size = 0;
197        pbuffer = buffer;
198
199        if(eof)
200            break;
201
202        while(len > 0{
203            if(audio_state.audio_buf_index >= (int)audio_state.audio_buf_size) {
204                audio_size = audio_decode_frame(&audio_state);
205                if(audio_size < 0{
206                    if(size > 0)
207                        break;
208
209                    eof = 1;
210                    break;
211                }

212
213                audio_state.audio_buf_size = audio_size;
214                audio_state.audio_buf_index = 0;
215            }

216
217            len1 = audio_state.audio_buf_size - audio_state.audio_buf_index;
218            if(len1 > len)
219                len1 = len;
220
221            memcpy(pbuffer, (uint8_t *)audio_state.audio_buf + audio_state.audio_buf_index, len1);
222
223            len -= len1;
224            pbuffer += len1;
225            size += len1;
226            audio_state.audio_buf_index += len1;
227        }

228
229        writeAudio(hWaveOut, (char*)buffer, size);
230    }

231
232    // wait for complete
233    for( ; ; ) {
234        if(waveFreeBlockCount >= BLOCK_COUNT)
235            break;
236
237        Sleep(10);
238    }

239
240    for(i = 0; i < waveFreeBlockCount; i++)
241        if(waveBlocks[i].dwFlags & WHDR_PREPARED)
242            waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));
243
244    DeleteCriticalSection(&waveCriticalSection);
245    freeBlocks(waveBlocks);
246    waveOutClose(hWaveOut);
247
248    avcodec_close(audio_state.pCodecCtx);
249
250    system("pause");
251    return 0;
252}

253
254 static   void  writeAudio(HWAVEOUT hWaveOut, LPSTR data,  int  size)
255 {
256    WAVEHDR* current;
257    int remain;
258
259    current = &waveBlocks[waveCurrentBlock];
260
261    while(size > 0{
262        /**//* 
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
268        if(size < (int)(BLOCK_SIZE - current->dwUser)) {
269            memcpy(current->lpData + current->dwUser, data, size);
270            current->dwUser += size;
271            break;
272        }

273
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
280        waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
281        waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
282
283        EnterCriticalSection(&waveCriticalSection);
284        waveFreeBlockCount--;
285        LeaveCriticalSection(&waveCriticalSection);
286
287        /**//*
288        * wait for a block to become free
289        */

290        while(!waveFreeBlockCount)
291            Sleep(10);
292
293        /**//*
294        * point to the next block
295        */

296        waveCurrentBlock++;
297        waveCurrentBlock %= BLOCK_COUNT;
298
299        current = &waveBlocks[waveCurrentBlock];
300        current->dwUser = 0;
301    }

302}

303
304 static  WAVEHDR *  allocateBlocks( int  size,  int  count)
305 {
306    char* buffer;
307    int i;
308    WAVEHDR* blocks;
309    DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count;
310
311    /**//*
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        )) == NULL) {
319            fprintf(stderr, "Memory allocation error\n");
320            ExitProcess(1);
321    }

322
323    /**//*
324    * and set up the pointers to each bit
325    */

326    blocks = (WAVEHDR*)buffer;
327    buffer += sizeof(WAVEHDR) * count;
328    for(i = 0; i < count; i++{
329        blocks[i].dwBufferLength = size;
330        blocks[i].lpData = buffer;
331        buffer += size;
332    }

333
334    return blocks;
335}

336
337 static   void  freeBlocks(WAVEHDR *  blockArray)
338 {
339    /**//* 
340    * and this is why allocateBlocks works the way it does
341    */
 
342    HeapFree(GetProcessHeap(), 0, blockArray);
343}

344
345 static   void  CALLBACK waveOutProc(
346                                  HWAVEOUT hWaveOut, 
347                                  UINT uMsg, 
348                                  DWORD dwInstance,  
349                                  DWORD dwParam1,    
350                                  DWORD dwParam2     
351                                  )
352 {
353    int* freeBlockCounter = (int*)dwInstance;
354    /**//*
355    * ignore calls that occur due to opening and closing the
356    * device.
357    */

358    if(uMsg != WOM_DONE)
359        return;
360
361    EnterCriticalSection(&waveCriticalSection);
362    (*freeBlockCounter)++;
363    LeaveCriticalSection(&waveCriticalSection);
364}

你可能感兴趣的:([C/C++] ffmpeg小试)