1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "Main.h"
#include "AudioThread.h"
#include "AudioLayer.h"
#include <assert.h>
extern unsigned long endTime;
DWORD WINAPI AudThread_stub(void *ptr)
{
((AudioThread *)ptr)->AudThread();
return 0;
}
void AudioThread::Start(WMHandler *_output)
{
assert(_output);
output = _output;
eof=0;
ResetEvent(stopped);
QueueUserAPC(MediaThread_StartAPC, thread, reinterpret_cast<ULONG_PTR>(static_cast<MediaThread *>(this)));
}
AudioThread::AudioThread(AudioLayer *audio) : output(0), audioLayer(audio)
{
DWORD id;
thread = CreateThread(NULL, 256*1024, AudThread_stub, (void *)this, NULL, &id);
SetThreadPriority(thread, AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST));
}
void AudioThread::AudThread()
{
int endbreak=0;
while (true)
{
switch (WaitForSingleObjectEx(killEvent, wait, TRUE))
{
case WAIT_OBJECT_0:
//StopAPC();
return;
case WAIT_TIMEOUT:
{
if (buffers.empty() || endbreak)
{
SetEvent(bufferFreed);
if (eof==1)
{
eof=2;
output->EndOfFile();
}
endbreak = 0;
continue;
}
MediaBuffer *buffer = buffers.front();
DWORD length;
void *data;
buffer->buffer->GetBufferAndLength((BYTE **)&data, &length);
//if (out->CanWrite() >= length)
{
QWORD timestamptemp = buffer->timestamp/10000LL;
DWORD timestamp = static_cast<DWORD>(timestamptemp);
if (buffer->flags & WM_SF_DISCONTINUITY)
{
// fill with silence!
int msToFill = timestamp - out->GetWrittenTime(); // TODO: maybe use microsoft's time resolution?
if (msToFill > 0 && msToFill < 2000)
{
int bytes = audioLayer->AudioMillisecondsToBytes(msToFill);
__int8 *zeroes = (__int8 *)calloc(bytes, 1);
if (zeroes)
{
output->AudioDataReceived(zeroes, bytes, timestamp);
free(zeroes);
}
else
{
out->Flush(timestamp);
}
}
else if (msToFill > 0)
{
out->Flush(timestamp);
}
}
output->AudioDataReceived(data, length, timestamp);
// TODO seen a few crash reports failing around here
// might be the cause of the random wma fails
// but crash dump doesn't help too much afaict
try {
buffer->buffer->Release();
delete buffer;
} catch (...) {}
//buffers.pop_front();
if (buffers.size())
{
buffers.erase(buffers.begin());
}
unsigned long x = endTime;
if (x && timestamp > x)
{
eof = 1; // reached the end baby....
endbreak = 1;
}
}
if (buffers.size() < config_audio_cache_frames)
SetEvent(bufferFreed);
}
continue;
default:
continue;
}
}
}
void AudioThread::AddAPC(MediaBuffer *buffer)
{
OrderedInsert(buffer);
if (buffers.size() >= config_audio_cache_frames)
ResetEvent(bufferFreed);
}
|