这是一个基于Ffmpeg解码器的简单播放器,怎么在Windows上编译Ffmpeg可以在网上找到很多,开发环境是Windows XP SP3+VS,其中DirectSound控制单元来自jdk1.6源码。我的Ffmpeg编译环境是MSYS+MinGW,GCC版本为4.4.0,采取静态无DEBUG方式编译,得到libavcodec.a、libavformat.a和libavutil.a三个静态库,将静态库引入工程,代码如下:
1 #pragmaonce
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 #pragmacomment(lib, " winmm.lib " )
23 #pragmacomment(lib, " dsound.lib " )
24 #pragmacomment(lib, " msimg32.lib " )
25 #pragmacomment(lib, " wsock32.lib " )
26 #pragmacomment(lib, " comctl32.lib " )
27
28 #ifdef__cplusplus
29 extern " C " {
30 #endif
31
32 #pragmawarning(disable: 4005 )
33 #pragmawarning(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 #pragmacomment(lib, " ./lib/libgcc.a " )
41 #pragmacomment(lib, " ./lib/libmingwex.a " )
42 #pragmacomment(lib, " ./lib/libcoldname.a " )
43
44 #pragmacomment(lib, " ./lib/libavcodec.a " )
45 #pragmacomment(lib, " ./lib/libavformat.a " )
46 #pragmacomment(lib, " ./lib/libavutil.a " )
47
48
49 #ifdef__cplusplus
50 }
51 #endif
52
53 #define USE_DAUDIOTRUE
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_LOADSTRING100
6 #define BLOCK_SIZE4608
7
8 // ThreadMessageDefineHere
9 #define TM_PLAY0
10 #define TM_PAUSE1
11 #define TM_RESUME2
12 #define TM_SEEK3
13 #define TM_STOP4
14 #define TM_OPENFILE5
15 #define TM_PREVIOUS6
16 #define TM_NEXT7
17 #define TM_EOF8
18 #define TM_PLAYITEM9
19
20 struct StartParameter
21 {
22 HWNDhMainWnd;
23 HANDLEhThreadReadyEvent;
24 };
25
26 HINSTANCEhInst;
27 TCHARszTitle[MAX_LOADSTRING];
28 TCHARszWindowClass[MAX_LOADSTRING];
29 HWNDhMainWindow = NULL;
30 HWNDhTrackBar = NULL;
31 HWNDhStatic = NULL;
32
33 DWORDdwMainLoopThreadId = 0 ;
34 HANDLEhMainLoopThread = NULL;
35
36 BOOLPlaying = FALSE;
37
38 TCHARszFileName[MAX_PATH];
39 int gTotalSeconds;
40 int gCurPlaySeconds;
41 int gPosition;
42
43 HFONThFont;
44
45 ATOMMyRegisterClass(HINSTANCEhInstance);
46 BOOLInitInstance(HINSTANCE, int );
47 LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
48 INT_PTRCALLBACKAbout(HWND,UINT,WPARAM,LPARAM);
49 DWORDWINAPIMainLoopThreadProc(VOID * );
50 LRESULTCALLBACKStaticWndProc(HWND,UINT,WPARAM,LPARAM);
51
52 #define SUPPORT_FILTER_TEXT("Allsupportedfiles\0*.aac;*.ape;*.flac;*.mp3;*.mpc;*.ogg;*.tta;*.wav;*.wma;*.wv\0")\
53 _TEXT( " AACfiles(*.aac)\0*.aac\0 " )\
54 _TEXT( " APEfiles(*.ape)\0*.ape\0 " )\
55 _TEXT( " FLACfiles(*.flac)\0*.flac\0 " )\
56 _TEXT( " MP3files(*.mp3)\0*.mp3\0 " )\
57 _TEXT( " MPCfiles(*.mpc)\0*.mpc\0 " )\
58 _TEXT( " Oggvorbisfiles(*.ogg)\0*.ogg\0 " )\
59 _TEXT( " TTAfiles(*.tta)\0*.tta\0 " )\
60 _TEXT( " Wavefiles(*.wav)\0*.wav\0 " )\
61 _TEXT( " WMAfiles(*.wma)\0*.wma\0 " )\
62 _TEXT( " Wavpackfiles(*.wv)\0*.wv\0 " )\
63 _TEXT( " Allfiles(*.*)\0*.*\0 " )
64
65 typedef struct AudioState
66 {
67 AVFormatContext * pFmtCtx;
68 AVCodecContext * pCodecCtx;
69 AVCodec * pCodec;
70
71 #ifdefOUTPUT_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 AVPacketaudio_pkt_temp;
81 AVPacketaudio_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 // preventnullpointers
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 /* iferror,weskiptheframe */
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(HINSTANCEhInstance,
186 HINSTANCEhPrevInstance,
187 LPTSTRlpCmdLine,
188 int nCmdShow)
189 {
190 UNREFERENCED_PARAMETER(hPrevInstance);
191 UNREFERENCED_PARAMETER(lpCmdLine);
192
193 MSGmsg;
194 HACCELhAccelTable;
195
196 INITCOMMONCONTROLSEXcex = {sizeof (INITCOMMONCONTROLSEX),
197 ICC_BAR_CLASSES | ICC_PROGRESS_CLASS};
198 BOOLret = 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 ATOMMyRegisterClass(HINSTANCEhInstance)
224 {
225 WNDCLASSEXwcex;
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 BOOLInitInstance(HINSTANCEhInstance, int nCmdShow)
245 {
246 HWNDhWnd;
247
248 hInst = hInstance;
249
250 DWORDdwStyle = 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 RECTr = {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 LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
286 {
287 int wmId,wmEvent;
288 PAINTSTRUCTps;
289 HDChdc;
290 TCHARbuffer[ 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 OPENFILENAMEofn = {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 LRESULTret = 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 // startmainplayloopthread
374 HANDLEhThreadReadyEvent = CreateEvent(NULL,TRUE,FALSE,_T( " ThreadReadyEvent " ));
375
376 StartParameterstartParam = {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 LRESULTCALLBACKStaticWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
396 {
397 PAINTSTRUCTps;
398 HDChdc;
399 HFONTholdfont;
400 TCHARbuffer[MAX_PATH] = {0 };
401 RECTr = {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_PTRCALLBACKAbout(HWNDhDlg,UINTmessage,WPARAMwParam,LPARAMlParam)
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 DWORDWINAPIMainLoopThreadProc(VOID * pParam)
451 {
452 StartParameter * pStartParam = (StartParameter * )pParam;
453 BOOLbTerminateThread = FALSE;
454
455 // registerallcodecs.
456 av_register_all();
457 SetEvent(pStartParam -> hThreadReadyEvent);
458
459 AudioStatestate = {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 __int64duration = 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 DWORDreadBytes = 0 ;
485 char input_buffer[BLOCK_SIZE] = {0 };
486 TCHARszTime[ 20 ] = {0 };
487 TCHARszPosition[ 10 ] = {0 };
488
489 do
490 {
491 MSGmsg = {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 TCHARbuffer[ 2 * MAX_PATH];
509 _stprintf_s(buffer, sizeof (TCHAR) * ( 2 * MAX_PATH),_T( " cannotopenfile%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 TCHARbuffer[ 2 * MAX_PATH];
524 _stprintf_s(buffer, sizeof (TCHAR) * ( 2 * MAX_PATH),_T( " cannotfindstreaminfooffile%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( " cannotgetcodeccontext. " ),_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( " cannotopencodec. " ),_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 RECTr = {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 MSGmsg2;
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 RECTr = {0 };
718 GetClientRect(hStatic, & r);
719 InvalidateRect(hStatic, & r,FALSE);
720
721 goto NextLoop;
722 }
723
724 DWORDlen = readBytes;
725 DWORDoffset = 0 ;
726 DWORDwritten = 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 // updateprogress
745 {
746 __int64wFp = DAUDIO_GetLongFramePosition(( void * )info,TRUE);
747 __int64byteLen = 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 RECTr = {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 }