这是一个基于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
}