[C/C++] 基于Ffmpeg解码器的简单播放器(a simple audio player based on Ffmpeg)

这是一个基于Ffmpeg解码器的简单播放器,怎么在Windows上编译Ffmpeg可以在网上找到很多,开发环境是Windows XP SP3+VS2008,其中DirectSound控制单元来自jdk1.6源码。我的Ffmpeg编译环境是MSYS+MinGW,GCC版本为4.4.0,采取静态无DEBUG方式编译,得到libavcodec.a、libavformat.a和libavutil.a三个静态库,将静态库引入工程,代码如下:
 1  #pragma once
 2 
 3  #define  WIN32_LEAN_AND_MEAN
 4 
 5  #include  " targetver.h "
 6  #include  < windows.h >
 7  #include  < commdlg.h >
 8 
 9  #include  < stdlib.h >
10  #include  < malloc.h >
11  #include  < memory.h >
12  #include  < tchar.h >
13  #include  < math.h >
14  #include  < mmsystem.h >
15  #include  < dsound.h >
16  #include  < commctrl.h >
17 
18  #include  < list >
19  #include  < vector >
20  using   namespace  std;
21 
22  #pragma comment(lib,  " winmm.lib " )
23  #pragma comment(lib,  " dsound.lib " )
24  #pragma comment(lib,  " msimg32.lib " )
25  #pragma comment(lib,  " wsock32.lib " )
26  #pragma comment(lib,  " comctl32.lib " )
27 
28  #ifdef __cplusplus
29  extern   " C "  {
30  #endif
31 
32  #pragma warning(disable :  4005 )
33  #pragma warning(disable :  4049 )
34 
35  #include  " ./include/avcodec.h "
36  #include  " ./include/avformat.h "
37  #include  " ./include/avutil.h "
38  #include  " ./include/mem.h "
39 
40  #pragma comment(lib,  " ./lib/libgcc.a " )
41  #pragma comment(lib,  " ./lib/libmingwex.a " )
42  #pragma comment(lib,  " ./lib/libcoldname.a " )
43 
44  #pragma comment(lib,  " ./lib/libavcodec.a " )
45  #pragma comment(lib,  " ./lib/libavformat.a " )
46  #pragma comment(lib,  " ./lib/libavutil.a " )
47 
48 
49  #ifdef __cplusplus
50  }
51  #endif
52 
53  #define  USE_DAUDIO TRUE
54  #define  round(a) ((long)floor((a) + 0.5f))
主程序代码如下:
  1  #include  " stdafx.h "
  2  #include  " SimpleFfmpegPlayer.h "
  3  #include  " DirectSound.h "
  4 
  5  #define  MAX_LOADSTRING 100
  6  #define  BLOCK_SIZE        4608
  7 
  8  //  Thread Message Define Here
  9  #define  TM_PLAY            0
 10  #define  TM_PAUSE        1
 11  #define  TM_RESUME        2
 12  #define  TM_SEEK            3
 13  #define  TM_STOP            4
 14  #define  TM_OPENFILE        5
 15  #define  TM_PREVIOUS        6
 16  #define  TM_NEXT            7
 17  #define  TM_EOF            8
 18  #define  TM_PLAYITEM        9
 19 
 20  struct  StartParameter
 21  {
 22      HWND hMainWnd;
 23      HANDLE hThreadReadyEvent;
 24  };
 25 
 26  HINSTANCE hInst;
 27  TCHAR szTitle[MAX_LOADSTRING];
 28  TCHAR szWindowClass[MAX_LOADSTRING];
 29  HWND hMainWindow  =  NULL;
 30  HWND hTrackBar  =  NULL;
 31  HWND hStatic  =  NULL;
 32 
 33  DWORD dwMainLoopThreadId  =   0 ;
 34  HANDLE hMainLoopThread  =  NULL;
 35 
 36  BOOL Playing  =  FALSE;
 37 
 38  TCHAR szFileName[MAX_PATH];
 39  int  gTotalSeconds;
 40  int  gCurPlaySeconds;
 41  int  gPosition;
 42 
 43  HFONT hFont;
 44 
 45  ATOM                MyRegisterClass(HINSTANCE hInstance);
 46  BOOL                InitInstance(HINSTANCE,  int );
 47  LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 48  INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 49  DWORD WINAPI        MainLoopThreadProc(VOID * );
 50  LRESULT CALLBACK    StaticWndProc(HWND, UINT, WPARAM, LPARAM);
 51 
 52  #define  SUPPORT_FILTER _TEXT("All supported files\0*.aac;*.ape;*.flac;*.mp3;*.mpc;*.ogg;*.tta;*.wav;*.wma;*.wv\0") \
 53      _TEXT( " AAC files(*.aac)\0*.aac\0 " ) \
 54      _TEXT( " APE files(*.ape)\0*.ape\0 " ) \
 55      _TEXT( " FLAC files(*.flac)\0*.flac\0 " ) \
 56      _TEXT( " MP3 files(*.mp3)\0*.mp3\0 " ) \
 57      _TEXT( " MPC files(*.mpc)\0*.mpc\0 " ) \
 58      _TEXT( " Ogg vorbis files(*.ogg)\0*.ogg\0 " ) \
 59      _TEXT( " TTA files(*.tta)\0*.tta\0 " ) \
 60      _TEXT( " Wave files(*.wav)\0*.wav\0 " ) \
 61      _TEXT( " WMA files(*.wma)\0*.wma\0 " ) \
 62      _TEXT( " Wavpack files(*.wv)\0*.wv\0 " ) \
 63      _TEXT( " All files(*.*)\0*.*\0 " )
 64 
 65  typedef  struct  AudioState
 66  {
 67      AVFormatContext *  pFmtCtx;
 68      AVCodecContext *  pCodecCtx;
 69      AVCodec *  pCodec;
 70 
 71  #ifdef OUTPUT_INFORMATS
 72      AVInputFormat *  ifmt;
 73  #endif
 74 
 75      uint8_t *  audio_buf1;
 76      uint8_t *  audio_buf;
 77      unsigned  int  audio_buf_size;
 78      unsigned  int  buffer_size;
 79       int  audio_buf_index;
 80      AVPacket audio_pkt_temp;
 81      AVPacket audio_pkt;
 82      uint8_t *  audio_pkt_data;
 83       int  audio_pkt_size;
 84       int  stream_index;
 85  } AudioState;
 86 
 87  long  align( long  bytes,  int  blockSize) {
 88       //  prevent null pointers
 89       if  (blockSize  <=   1 )
 90           return  bytes;
 91 
 92       return  bytes  -  (bytes  %  blockSize);
 93  }
 94 
 95  long  millis2bytes( int  samplerate,  long  millis,  int  frameSize)
 96  {
 97       long  result  =  ( long ) (millis  *  samplerate  /   1000.0f   *  frameSize);
 98       return  align(result, frameSize);
 99  }
100 
101  long  bytes2millis( int  samplerate,  long  bytes,  int  frameSize) {
102       return  ( long ) (bytes  /  samplerate  *   1000.0f   /  frameSize);
103  }
104 
105  int  audio_decode_frame(AudioState *  pState)
106  {
107 
108      AVPacket *  pkt_temp  =   & pState -> audio_pkt_temp;
109      AVPacket *  pkt  =   & pState -> audio_pkt;
110      AVCodecContext *  dec =  pState -> pCodecCtx;
111       int  len  =   0 , data_size  =   sizeof (pState -> audio_buf1);
112       int  err  =   0 ;
113 
114       for ( ; ; )
115      {
116           while  (pkt_temp -> size  >   0 )
117          {
118              data_size  =  pState -> buffer_size;
119              len  =  avcodec_decode_audio3(dec, (int16_t * )pState -> audio_buf1,  & data_size, pkt_temp);
120               if  (len  <   0 )
121              {
122                   /*  if error, we skip the frame  */
123                  pkt_temp -> size  =   0 ;
124                   break ;
125              }
126 
127              pkt_temp -> data  +=  len;
128              pkt_temp -> size  -=  len;
129 
130               if  (data_size  <=   0 )
131                   continue ;
132 
133              pState -> audio_buf  =  pState -> audio_buf1;
134               return  data_size;
135          }
136 
137           if  (pkt -> data)
138              av_free_packet(pkt);
139 
140           if ((err  =  av_read_frame(pState -> pFmtCtx, pkt))  <   0 )
141               return   - 1 ;
142 
143          pkt_temp -> data  =  pkt -> data;
144          pkt_temp -> size  =  pkt -> size;
145      }
146 
147       return   - 1 ;
148  }
149 
150  int  read_buffer(AudioState *  pState,  void *  buffer,  int  buf_size)
151  {
152       int  len  =  buf_size;
153      uint8_t *  pbuffer  =  (uint8_t * )buffer;
154       int  audio_size  =   0 ;
155       int  len1  =   0 ;
156       int  size  =   0 ;
157 
158       while (len  >   0 )
159      {
160           if (pState -> audio_buf_index  >=  ( int )pState -> audio_buf_size)
161          {
162              audio_size  =  audio_decode_frame(pState);
163               if (audio_size  <   0 )
164                   return  (size  >   0 ?  size :  - 1 ;
165 
166              pState -> audio_buf_size  =  audio_size;
167              pState -> audio_buf_index  =   0 ;
168          }
169 
170          len1  =  pState -> audio_buf_size  -  pState -> audio_buf_index;
171           if (len1  >  len)
172              len1  =  len;
173 
174          memcpy(pbuffer, (uint8_t  * )pState -> audio_buf  +  pState -> audio_buf_index, len1);
175 
176          len  -=  len1;
177          pbuffer  +=  len1;
178          size  +=  len1;
179          pState -> audio_buf_index  +=  len1;
180      }
181 
182       return  size;
183  }
184 
185  int  APIENTRY _tWinMain(HINSTANCE hInstance,
186                       HINSTANCE hPrevInstance,
187                       LPTSTR    lpCmdLine,
188                        int        nCmdShow)
189  {
190      UNREFERENCED_PARAMETER(hPrevInstance);
191      UNREFERENCED_PARAMETER(lpCmdLine);
192 
193      MSG msg;
194      HACCEL hAccelTable;
195 
196      INITCOMMONCONTROLSEX cex  =  { sizeof (INITCOMMONCONTROLSEX),
197          ICC_BAR_CLASSES  |  ICC_PROGRESS_CLASS};
198      BOOL ret  =  InitCommonControlsEx( & cex);
199 
200      LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
201      LoadString(hInstance, IDC_SIMPLEFFMPEGPLAYER, szWindowClass, MAX_LOADSTRING);
202      MyRegisterClass(hInstance);
203 
204       if  ( ! InitInstance (hInstance, nCmdShow))
205      {
206           return  FALSE;
207      }
208 
209      hAccelTable  =  LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SIMPLEFFMPEGPLAYER));
210 
211       while  (GetMessage( & msg, NULL,  0 0 ))
212      {
213           if  ( ! TranslateAccelerator(msg.hwnd, hAccelTable,  & msg))
214          {
215              TranslateMessage( & msg);
216              DispatchMessage( & msg);
217          }
218      }
219 
220       return  ( int ) msg.wParam;
221  }
222 
223  ATOM MyRegisterClass(HINSTANCE hInstance)
224  {
225      WNDCLASSEX wcex;
226 
227      wcex.cbSize  =   sizeof (WNDCLASSEX);
228 
229      wcex.style             =  CS_HREDRAW  |  CS_VREDRAW;
230      wcex.lpfnWndProc     =  WndProc;
231      wcex.cbClsExtra         =   0 ;
232      wcex.cbWndExtra         =   0 ;
233      wcex.hInstance         =  hInstance;
234      wcex.hIcon             =  LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SIMPLEFFMPEGPLAYER));
235      wcex.hCursor         =  LoadCursor(NULL, IDC_ARROW);
236      wcex.hbrBackground     =  (HBRUSH)(COLOR_BTNFACE + 1 );
237      wcex.lpszMenuName     =  MAKEINTRESOURCE(IDC_SIMPLEFFMPEGPLAYER);
238      wcex.lpszClassName     =  szWindowClass;
239      wcex.hIconSm         =  LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
240 
241       return  RegisterClassEx( & wcex);
242  }
243 
244  BOOL InitInstance(HINSTANCE hInstance,  int  nCmdShow)
245  {
246     HWND hWnd;
247 
248     hInst  =  hInstance;
249 
250     DWORD dwStyle  =  WS_OVERLAPPED  |  WS_CAPTION  |  WS_SYSMENU  |  WS_MINIMIZEBOX;
251     hWnd  =  CreateWindow(szWindowClass, szTitle, dwStyle,
252         0 0 320 100 , NULL, NULL, hInstance, NULL);
253 
254      if  ( ! hWnd)
255     {
256         return  FALSE;
257     }
258 
259     hMainWindow  =  hWnd;
260 
261     hFont  =  CreateFont( 18 , 0 , 0 , 0 ,FW_BLACK,FALSE,FALSE,FALSE,
262         GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
263         DEFAULT_QUALITY,FIXED_PITCH  |  FF_MODERN,_T( " Tahoma " ));
264 
265     RECT r  =  { 0 0 0 0 };
266     GetWindowRect(hMainWindow,  & r);
267     hTrackBar  =  CreateWindowEx( 0 , TRACKBAR_CLASS, _T( "" ), WS_CHILD  |  WS_VISIBLE  |  TBS_BOTH  |  TBS_NOTICKS,
268         r.left  +   4 , (r.bottom  -  r.top)  /   6   +   4 300 18 , hMainWindow, NULL, hInstance, NULL);
269     SendMessage(hTrackBar, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM) MAKELONG ( 0 100 ));
270     SendMessage(hTrackBar, TBM_SETLINESIZE, (WPARAM) 0 , (LPARAM) 5 );
271     SendMessage(hTrackBar, TBM_SETPAGESIZE, (WPARAM) 0 , (LPARAM) 5 );
272 
273     GetClientRect(hMainWindow,  & r);
274     hStatic  =  CreateWindowEx( 0 , WC_STATIC, _T( " 00:00/00:00 " ), WS_CHILD  |  WS_VISIBLE  |  WS_OVERLAPPED  |  SS_CENTER  |  SS_LEFT,
275         (r.right  -  r.left)  /   4   +   11 0 100 18 , hMainWindow, NULL, hInstance, NULL);
276 
277     SetWindowLong(hStatic, GWL_WNDPROC, (LONG)StaticWndProc);
278 
279     ShowWindow(hWnd, nCmdShow);
280     UpdateWindow(hWnd);
281 
282      return  TRUE;
283  }
284 
285  LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
286  {
287       int  wmId, wmEvent;
288      PAINTSTRUCT ps;
289      HDC hdc;
290      TCHAR buffer[ 128 =  { 0 };
291 
292       switch  (message)
293      {
294       case  WM_COMMAND:
295          wmId     =  LOWORD(wParam);
296          wmEvent  =  HIWORD(wParam);
297 
298           switch  (wmId)
299          {
300           case  IDM_ABOUT:
301              DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
302               break ;
303           case  IDM_EXIT:
304              DestroyWindow(hWnd);
305               break ;
306           case  ID_PLAY:
307              {
308                   if (Playing  ==  TRUE)
309                       break ;
310 
311                  OPENFILENAME ofn  =  { 0 };
312                  ofn.lStructSize  =   sizeof (ofn);
313                  ofn.hwndOwner  =  hMainWindow;
314                  ofn.lpstrFile  =  szFileName;
315                  ofn.lpstrFile[ 0 =  _T( ' \0 ' );
316                  ofn.nMaxFile  =   sizeof (szFileName)  /   sizeof (szFileName[ 0 ]);
317                  ofn.lpstrFilter  =  SUPPORT_FILTER;
318                  ofn.nFilterIndex  =   1 ;
319                  ofn.lpstrFileTitle  =  NULL;
320                  ofn.nMaxFileTitle  =   0 ;
321                  ofn.lpstrInitialDir  =  NULL;
322                  ofn.Flags  =  OFN_PATHMUSTEXIST  |  OFN_FILEMUSTEXIST  |  OFN_EXPLORER;
323 
324                   if (GetOpenFileName( & ofn)  ==  TRUE)
325                  {
326                       if (hMainLoopThread  &&  dwMainLoopThreadId  &&  Playing  ==  FALSE)
327                          PostThreadMessage(dwMainLoopThreadId, TM_PLAY,  0 0 );
328                  }
329              }
330               break ;
331           case  ID_STOP:
332              {
333                   if (Playing  ==  TRUE  &&  hMainLoopThread  &&  dwMainLoopThreadId)
334                      PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
335              }
336               break ;
337           default :
338               return  DefWindowProc(hWnd, message, wParam, lParam);
339          }
340           break ;
341       case  WM_PAINT:
342          hdc  =  BeginPaint(hWnd,  & ps);
343 
344          EndPaint(hWnd,  & ps);
345           break ;
346       case  WM_DESTROY:
347           if (hMainLoopThread  &&  dwMainLoopThreadId)
348          {
349              PostThreadMessage(dwMainLoopThreadId, TM_STOP,  0 0 );
350 
351              CloseHandle(hMainLoopThread);
352              hMainLoopThread  =  NULL;
353          }
354 
355          DeleteObject(hFont);
356          DestroyWindow(hTrackBar);
357          DestroyWindow(hStatic);
358          PostQuitMessage( 0 );
359           break ;
360       case  WM_NOTIFY:
361          {
362              NMHDR *  pNMHDR  =  (NMHDR * )lParam;
363               if (pNMHDR -> hwndFrom  ==  hTrackBar)
364              {
365                  LRESULT ret  =  SendMessage(hTrackBar, TBM_GETPOS,  0 0 );
366                   if ( ret  !=  gPosition  &&  Playing)
367                      PostThreadMessage(dwMainLoopThreadId, TM_SEEK, (WPARAM)ret,  0 );
368              }
369          }
370           break ;
371       case  WM_CREATE:
372          {
373               //  start main play loop thread
374              HANDLE hThreadReadyEvent  =  CreateEvent(NULL, TRUE, FALSE, _T( " ThreadReadyEvent " ));
375 
376              StartParameter startParam  =  {hWnd, hThreadReadyEvent};
377 
378              dwMainLoopThreadId  =   0 ;
379              hMainLoopThread  =  CreateThread(NULL,  0 , MainLoopThreadProc,  & startParam, 
380                  CREATE_SUSPENDED,  & dwMainLoopThreadId);
381 
382              ResumeThread(hMainLoopThread);
383              WaitForSingleObject(hThreadReadyEvent, INFINITE);
384 
385              CloseHandle(hThreadReadyEvent);
386              hThreadReadyEvent  =  NULL;
387          }
388           break ;
389       default :
390           return  DefWindowProc(hWnd, message, wParam, lParam);
391      }
392       return   0 ;
393  }
394 
395  LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
396  {
397      PAINTSTRUCT ps;
398      HDC hdc;
399      HFONT holdfont;
400      TCHAR buffer[MAX_PATH]  =  { 0 };
401      RECT r  =  { 0 };
402 
403       switch (message)
404      {
405       case  WM_PAINT :
406          {
407              hdc  =  BeginPaint(hWnd,  & ps);
408 
409              GetClientRect(hWnd,  & r);
410              FillRect(hdc,  & r, (HBRUSH)(COLOR_BTNFACE + 1 ));
411              
412              SetBkMode(hdc, TRANSPARENT);
413 
414              GetWindowText(hWnd, buffer, MAX_PATH);
415              holdfont  =  (HFONT)SelectObject(hdc, hFont);
416              TextOut(hdc,  0 0 , buffer, _tcslen(buffer));
417              SelectObject(hdc, holdfont);
418 
419              EndPaint(hWnd,  & ps);
420          }
421           break ;
422       case  WM_ERASEBKGND:
423           return   1 ;
424       default :
425           return  DefWindowProc(hWnd, message, wParam, lParam);
426      }
427 
428       return   0 ;
429  }
430 
431  INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
432  {
433      UNREFERENCED_PARAMETER(lParam);
434       switch  (message)
435      {
436       case  WM_INITDIALOG:
437           return  (INT_PTR)TRUE;
438 
439       case  WM_COMMAND:
440           if  (LOWORD(wParam)  ==  IDOK  ||  LOWORD(wParam)  ==  IDCANCEL)
441          {
442              EndDialog(hDlg, LOWORD(wParam));
443               return  (INT_PTR)TRUE;
444          }
445           break ;
446      }
447       return  (INT_PTR)FALSE;
448  }
449 
450  DWORD WINAPI MainLoopThreadProc(VOID *  pParam)
451  {
452      StartParameter *  pStartParam  =  (StartParameter * )pParam;
453      BOOL bTerminateThread  =  FALSE;
454 
455       //  register all codecs.
456      av_register_all();
457      SetEvent(pStartParam -> hThreadReadyEvent);
458 
459      AudioState state  =  { 0 };
460       int  buffer_size  =  (AVCODEC_MAX_AUDIO_FRAME_SIZE  *   3 /   2 ;
461      memset( & state,  0 sizeof (AudioState));
462 
463       int  err  =   0 ;
464       char  filepath[MAX_PATH]  =  { 0 };
465 
466      __int64 duration  =   0 ;
467       int  totalSeconds  =   0 ;
468       int  minute  =   0 ;
469       int  second  =   0 ;
470       int  totalMinute  =   0 ;
471       int  totalSecond  =   0 ;
472 
473       int  channels  =   0 ;
474       int  samplerate  =   0 ;
475       int  bitpersample  =   16 ;
476 
477      DS_Info *  info  =  NULL;
478       int  frameSize  =   0 ;
479       long  bufferSize  =   0 ;
480       int  bytesPerSec  =   0 ;
481       long  waitTime  =   0 ;
482       int  deviceCount  =   0 ;
483 
484      DWORD readBytes  =   0 ;
485       char  input_buffer[BLOCK_SIZE]  =  { 0 };
486      TCHAR szTime[ 20 =  { 0 };
487      TCHAR szPosition[ 10 =  { 0 };
488 
489       do  
490      {
491          MSG msg  =  { 0 };
492           while  (PeekMessage( & msg, NULL,  0 0 , PM_REMOVE))
493          {
494               switch (msg.message)
495              {
496               case  TM_PLAY:
497                  {
498 
499  #ifdef _UNICODE
500                      WideCharToMultiByte(CP_ACP,  0 , szFileName,  - 1 , filepath,  sizeof (filepath)  /   sizeof ( char ), NULL, NULL);
501  #else
502                      memcpy(filepath, szFileName,  sizeof (filepath)  /   sizeof ( char ));
503  #endif
504 
505                      err  =  av_open_input_file( & state.pFmtCtx, filepath, NULL,  0 , NULL);
506                       if (err  <   0 )
507                      {
508                          TCHAR buffer[ 2 * MAX_PATH];
509                          _stprintf_s(buffer,  sizeof (TCHAR)  *  ( 2   *  MAX_PATH), _T( " can not open file %s. " ), filepath);
510                          MessageBox(hMainWindow, buffer, _T( " Error " ), MB_OK  |  MB_ICONEXCLAMATION);
511 
512                          Playing  =  FALSE;
513 
514                           if (hMainLoopThread  &&  dwMainLoopThreadId)
515                              PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
516 
517                           break ;
518                      }
519 
520                      err  =  av_find_stream_info(state.pFmtCtx);
521                       if (err  <   0 )
522                      {
523                          TCHAR buffer[ 2 * MAX_PATH];
524                          _stprintf_s(buffer,  sizeof (TCHAR)  *  ( 2   *  MAX_PATH), _T( " can not find stream info of file %s. " ), filepath);
525                          MessageBox(hMainWindow, buffer, _T( " Error " ), MB_OK  |  MB_ICONEXCLAMATION);
526 
527                          Playing  =  FALSE;
528 
529                           if (hMainLoopThread  &&  dwMainLoopThreadId)
530                              PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
531 
532                           break ;
533                      }
534 
535                       int  index  =   - 1 ;
536                       for (unsigned  int  i  =   0 ; i  <  state.pFmtCtx -> nb_streams; i ++ )
537                      {
538                           if (state.pFmtCtx -> streams[i] -> codec -> codec_type  ==  CODEC_TYPE_AUDIO)
539                          {
540                              state.pCodecCtx  =  state.pFmtCtx -> streams[i] -> codec;
541                              index  =  i;
542                              state.stream_index  =  i;
543                               break ;
544                          }
545                      }
546 
547                       if ( ! state.pCodecCtx)
548                      {
549                          MessageBox(hMainWindow, _T( " can not get codec context. " ), _T( " Error " ), MB_OK  |  MB_ICONEXCLAMATION);
550                          av_close_input_file(state.pFmtCtx);
551 
552                          Playing  =  FALSE;
553 
554                           if (hMainLoopThread  &&  dwMainLoopThreadId)
555                              PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
556 
557                           break ;
558                      }
559 
560                      state.pCodec  =  avcodec_find_decoder(state.pCodecCtx -> codec_id);
561                       if ( ! state.pCodec  ||  avcodec_open(state.pCodecCtx, state.pCodec)  <   0 )
562                      {
563                          MessageBox(hMainWindow, _T( " can not open codec. " ), _T( " Error " ), MB_OK  |  MB_ICONEXCLAMATION);
564                          av_close_input_file(state.pFmtCtx);
565 
566                          Playing  =  FALSE;
567 
568                           if (hMainLoopThread  &&  dwMainLoopThreadId)
569                              PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
570 
571                           break ;
572                      }
573 
574                      duration  =  state.pFmtCtx -> duration;
575                      totalSeconds  =  ( int )(duration  /   1000000L );
576                      gTotalSeconds  =  totalSeconds;
577                      totalMinute  =  ( int )(totalSeconds  /   60 );
578                      totalSecond  =  ( int )(totalSeconds  %   60 );
579 
580                      state.audio_buf1  =  (uint8_t * )av_mallocz(buffer_size);
581                      state.buffer_size  =  buffer_size;
582 
583                      channels  =  state.pCodecCtx -> channels;
584                      samplerate  =  state.pCodecCtx -> sample_rate;
585 
586                      bitpersample  =   16 ;
587                       switch (state.pCodecCtx -> sample_fmt)
588                      {
589                       case  SAMPLE_FMT_U8:
590                          bitpersample  =   8 ;
591                           break ;
592                       case  SAMPLE_FMT_S16:
593                          bitpersample  =   16 ;
594                           break ;
595                       case  SAMPLE_FMT_S32:
596                          bitpersample  =   32 ;
597                           break ;
598                       case  SAMPLE_FMT_FLT:
599                          bitpersample  =   sizeof ( double *   8 ;
600                           break ;
601                       default :
602                          bitpersample  =   0 ;
603                           break ;
604                      }
605 
606                      frameSize  =  (channels  ==   1 ?   2  :  4 ;
607                      bufferSize  =  millis2bytes(samplerate,  500 , frameSize);
608                      bytesPerSec  =  samplerate  *  frameSize;
609 
610                      waitTime  =  bytes2millis(samplerate, bufferSize, frameSize)  /   4 ;
611                       if (waitTime  <   10 ) waitTime  =   1 ;
612                       if (waitTime  >   1000 ) waitTime  =   1000 ;
613 
614                      deviceCount  =  DAUDIO_GetDirectAudioDeviceCount();
615                      info  =  (DS_Info * )DAUDIO_Open( 0 0 1 , DAUDIO_PCM, ( float )samplerate,
616                          bitpersample, frameSize, channels, TRUE, FALSE, bufferSize);
617 
618                       if (info  !=  NULL  &&  DAUDIO_Start(( void * )info, TRUE))
619                      {
620                          Playing  =  TRUE;
621                          PostMessage(hTrackBar, TBM_SETPOS, (WPARAM)TRUE, (LPARAM) 0 );
622                      }
623                  }
624                   break ;
625               case  TM_STOP:
626                  {
627                       if (info)
628                      {
629                          DAUDIO_Stop(( void * )info, TRUE);
630                          DAUDIO_Close(( void * )info, TRUE);
631                          info  =  NULL;
632 
633                          av_free(state.audio_buf1);
634                          state.audio_buf1  =  NULL;
635 
636                          avcodec_close(state.pCodecCtx);
637                          av_close_input_file(state.pFmtCtx);
638                      }
639 
640                      Playing  =  FALSE;
641                      bTerminateThread  =  TRUE;
642                  }
643                   break ;
644               case  TM_EOF:
645                  {
646                       if (info)
647                      {
648                          DAUDIO_Stop(( void * )info, TRUE);
649                          DAUDIO_Close(( void * )info, TRUE);
650                          info  =  NULL;
651 
652                          av_free(state.audio_buf1);
653                          state.audio_buf1  =  NULL;
654 
655                          avcodec_close(state.pCodecCtx);
656                          av_close_input_file(state.pFmtCtx);
657                      }
658 
659                      SendMessage(hTrackBar, TBM_SETPOS, (WPARAM)TRUE, (LPARAM) 0 );
660 
661                      _stprintf_s(szTime,  sizeof (szTime) / sizeof (szTime[ 0 ]), _T( " %02d:%02d/%02d:%02d " ), 
662                           0 0 0 0 );
663                      SendMessage(hStatic, WM_SETTEXT, (WPARAM) 0 , (LPARAM)szTime);
664 
665                      RECT r  =  { 0 };
666                      GetClientRect(hStatic,  & r);
667                      InvalidateRect(hStatic,  & r, FALSE);
668 
669                      Playing  =  FALSE;
670                  }
671                   break ;
672               case  TM_SEEK:
673                  {
674                       if (Playing  ==  TRUE  &&  info  !=  NULL)
675                      {
676                          MSG msg2;
677                           if  (PeekMessage( & msg2, NULL, TM_SEEK, TM_SEEK, PM_NOREMOVE)  ==  FALSE)
678                          {
679                               int  seekPosition  =  ( int )msg.wParam;
680                               int  timestamp  =  ( int )(gTotalSeconds  *  ( float )seekPosition / 100 );
681                               int  ret  =  av_seek_frame(state.pFmtCtx,  - 1 , timestamp  *  AV_TIME_BASE,  0 );
682                              avcodec_flush_buffers(state.pCodecCtx);
683                              info -> bytesPos  =  timestamp  *  bytesPerSec;
684                              DAUDIO_Flush(( void * )info, TRUE);
685                          }
686                      }
687                  }
688                   break ;
689               default :
690                   break ;
691              }
692          }
693 
694           if (bTerminateThread  ==  TRUE)
695               break ;
696 
697           if (Playing  ==  TRUE  &&  info  !=  NULL)
698          {
699              memset(input_buffer,  0 sizeof (input_buffer));
700              readBytes  =   0 ;
701 
702              readBytes  =  read_buffer( & state, input_buffer, BLOCK_SIZE);
703               if (readBytes  ==   - 1 )
704              {
705                  Sleep( 250 );
706                  Playing  =  FALSE;
707 
708                   if (hMainLoopThread  &&  dwMainLoopThreadId)
709                      PostThreadMessage(dwMainLoopThreadId, TM_EOF,  0 0 );
710 
711                  SendMessage(hTrackBar, TBM_SETPOS, (WPARAM)TRUE, (LPARAM) 0 );
712 
713                  _stprintf_s(szTime,  sizeof (szTime) / sizeof (szTime[ 0 ]), _T( " %02d:%02d/%02d:%02d " ), 
714                       0 0 0 0 );
715                  SendMessage(hStatic, WM_SETTEXT, (WPARAM) 0 , (LPARAM)szTime);
716 
717                  RECT r  =  { 0 };
718                  GetClientRect(hStatic,  & r);
719                  InvalidateRect(hStatic,  & r, FALSE);
720 
721                   goto  NextLoop;
722              }
723 
724              DWORD len  =  readBytes;
725              DWORD offset  =   0 ;
726              DWORD written  =   0 ;
727 
728               for ( ; ; )
729              {
730                   int  thisWritten  =  DAUDIO_Write(( void * )info, input_buffer + offset, len);
731                   if (thisWritten  <   0 )
732                       break ;
733 
734                  len  -=  thisWritten;
735                  written  +=  thisWritten;
736                   if (len  >   0 )
737                  {
738                      offset  +=  thisWritten;
739                      Sleep(waitTime);
740                  }
741                   else   break ;
742              }
743 
744               //  update progress
745              {
746                  __int64 wFp  =  DAUDIO_GetLongFramePosition(( void * )info, TRUE);
747                  __int64 byteLen  =  wFp  *  frameSize;
748                  gCurPlaySeconds  =  ( int )byteLen  /  bytesPerSec;
749 
750                   int  seconds  =  ( int )byteLen  /  bytesPerSec;
751                  minute  =  ( int )(seconds  /   60 );
752                  second  =  ( int )(seconds  %   60 );
753 
754                  _stprintf_s(szTime,  sizeof (szTime) / sizeof (szTime[ 0 ]), _T( " %02d:%02d/%02d:%02d " ), 
755                      minute, second, totalMinute, totalSecond);
756                  SendMessage(hStatic, WM_SETTEXT, (WPARAM) 0 , (LPARAM)szTime);
757 
758                  RECT r  =  { 0 };
759                  GetClientRect(hStatic,  & r);
760                  InvalidateRect(hStatic,  & r, FALSE);
761 
762                   float  percent  =  ( float )seconds  /  totalSeconds;
763                   int  position  =  round(percent  *   100 );
764                   if (position  >=   100 )
765                      position  =   100 ;
766 
767                  gPosition  =  position;
768                  PostMessage(hTrackBar, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)position);
769 
770                   //  _stprintf_s(szPosition, 10, _T("%02d\n"), position);
771                   //  OutputDebugString(szPosition);
772              }
773          }
774           else
775          {
776              WaitMessage();
777          }
778 
779  NextLoop:
780          ;
781      }  while  (bTerminateThread  ==  FALSE);
782 
783       return   0 ;
784  }
由于是新近开发,代码注释不多,敬请原谅。
源码下载:
  源码1  源码2 源码3

你可能感兴趣的:([C/C++] 基于Ffmpeg解码器的简单播放器(a simple audio player based on Ffmpeg))