-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathXAudioThread.cpp
More file actions
168 lines (151 loc) · 2.89 KB
/
XAudioThread.cpp
File metadata and controls
168 lines (151 loc) · 2.89 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include "XAudioThread.h"
#include "XDecode.h"
#include "XAudioPlay.h"
#include "XResample.h"
#include <iostream>
extern "C" {
#include <libswresample/swresample.h>
#include <libavcodec/avcodec.h>
}
using namespace std;
void XAudioThread::Clear()
{
XDecodeThread::Clear();
mux.lock();
if (ap) ap->Clear();
mux.unlock();
}
//停止线程、关闭相关资源
void XAudioThread::Close()
{
//先调用父类的Close方法
XDecodeThread::Close();
if (res)
{
res->Close();
amux.lock();
delete res;
res = NULL;
amux.unlock();
}
if (ap)
{
ap->Close();
amux.lock();
ap = NULL;//不需要delete
amux.unlock();
}
}
bool XAudioThread::Open(AVCodecParameters* para, int sampleRate, int channels)
{
if (!para) return false;
Clear();
amux.lock();
//不受上一次的影响
pts = 0;
/*if (!decode) decode = new XDecode();
if (!res) res = new XResample();
if (!ap) ap = XAudioPlay::Get();*/
bool re = true;
if (!res->Open(para,false)) {
//mux.unlock();
//return false;
cout << "XResample open failed !" << endl;
re = false;
}
ap->sampleRate = sampleRate;
ap->channels = channels;
if (!ap->Open()) {
cout << "XAudioPlay open failed !" << endl;
//mux.unlock();
//return false;
re = false;
}
if (!decode->Open(para)) {
cout << "audio XDecode open failed !" << endl;
//mux.unlock();
//return false;
re = false;
}
amux.unlock();
//cout << "XAudioThread open :" << re << endl;
return re;
};
void XAudioThread::SetPause(bool isPause)
{
//amux.lock();
this->isPause = isPause;
if (ap) ap->SetPause(isPause);
//amux.unlock();
}
//音频不需要考虑同步问题,采用的是视频同步音频的方案
void XAudioThread::run()
{
unsigned char* pcm = new unsigned char[1024 * 1024 * 10];
while (!isExit) {
amux.lock();
if (isPause) {
amux.unlock();
msleep(5);
continue;
}
////如果没有数据
//if (packs.empty() || !decode || !res || !ap) {
// amux.unlock();
// msleep(1);
// continue;
//}
//AVPacket *pkt = packs.front();
//packs.pop_front();
AVPacket* pkt = Pop();
/*if (!pkt) {
amux.unlock();
msleep(5);
continue;
}*/
bool re = decode->Send(pkt);
if (!re) {
amux.unlock();
msleep(1);
continue;
}
//一次send,多次recv
while (!isExit)
{
AVFrame* frame = decode->Recv();
if (!frame) break;
//减去缓冲中未播放的时间
pts = decode->pts - ap->GetNoPlayMs();
//cout << "audio pts = " << pts << endl;
//重采样
int size = res->Resample(frame,pcm);//会释放frame空间,此处不需要释放
av_frame_free(&frame);
//播放音频
while (!isExit)
{
if (size <= 0) break;
//缓冲未播放完,空间不够
if (ap->GetFree() < size || isPause) {
msleep(1);
continue;
}
ap->Write(pcm,size);
break;
}
}
amux.unlock();
}
delete []pcm;
//delete pcm;
};
XAudioThread::XAudioThread()
{
if (!res) res = new XResample();
if (!ap) ap = XAudioPlay::Get();
};
XAudioThread::~XAudioThread()
{
//等待线程退出
isExit = true;
wait();
};