Skip to content

Commit 29058e6

Browse files
author
Xia Ning
committed
align with media-layer 1.2.2
1 parent ade9434 commit 29058e6

File tree

6 files changed

+213
-30
lines changed

6 files changed

+213
-30
lines changed

iOS/APIExample/Common/RtcChannelPublishPlugin/AgoraRtcChannelPublishHelper.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Created by zhanxiaochao on 2020/1/13.
66
// Copyright © 2020 agora. All rights reserved.
77
//
8-
#ifdef MEDIAPLAYER
8+
99
#import <Foundation/Foundation.h>
1010
#import <AgoraMediaPlayer/AgoraMediaPlayerKit.h>
1111
#import <AgoraRtcKit/AgoraRtcEngineKit.h>
@@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
1717
/// Description of state of Mediaplayer's state
1818
/// @param playerKit AgoraMediaPlayer
1919
/// @param state AgoraMediaPlayerState
20+
/// @param reason AgoraMediaPlayerStateReason
2021
/// @param error AgoraMediaPlayerError
2122
- (void)AgoraRtcChannelPublishHelperDelegate:(AgoraMediaPlayer *_Nonnull)playerKit
2223
didChangedToState:(AgoraMediaPlayerState)state
@@ -29,13 +30,13 @@ NS_ASSUME_NONNULL_BEGIN
2930
didChangedToPosition:(NSInteger)position;
3031

3132
/// callback of seek state
32-
/// @param playerKit AgoraMediaPlayer
33+
/// @param playerkit AgoraMediaPlayer
3334
/// @param state Description of seek state
3435
- (void)AgoraRtcChannelPublishHelperDelegate:(AgoraMediaPlayer *_Nonnull)playerKit
3536
didOccureEvent:(AgoraMediaPlayerEvent)state;
3637

3738
/// callback of SEI
38-
/// @param playerKit AgoraMediaPlayer
39+
/// @param playerkit AgoraMediaPlayer
3940
/// @param data SEI's data
4041
- (void)AgoraRtcChannelPublishHelperDelegate:(AgoraMediaPlayer *_Nonnull)playerKit
4142
didReceiveData:(NSString *)data
@@ -46,10 +47,10 @@ NS_ASSUME_NONNULL_BEGIN
4647
@interface AgoraRtcChannelPublishHelper : NSObject
4748

4849
+(instancetype)shareInstance;
49-
5050
// 连接 MediaPlayer 到主版本 RTC SDK
5151
- (void)registerRtcChannelPublishHelperDelegate:(id<AgoraRtcChannelPublishHelperDelegate>)delegate;
5252
- (void)attachPlayerToRtc:(AgoraMediaPlayer *)playerKit RtcEngine:(AgoraRtcEngineKit *)rtcEngine enableVideoSource:(bool)enable;
53+
- (void)enableOnlyLocalAudioPlay:(bool)isEnable;
5354
// 启动/停止推送音频流到频道
5455
- (void)publishAudio;
5556
- (void)unpublishAudio;
@@ -66,4 +67,3 @@ NS_ASSUME_NONNULL_BEGIN
6667
@end
6768

6869
NS_ASSUME_NONNULL_END
69-
#endif

iOS/APIExample/Common/RtcChannelPublishPlugin/AgoraRtcChannelPublishHelper.mm

Lines changed: 193 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,190 @@
66
// Copyright © 2020 agora. All rights reserved.
77
//
88

9-
#ifdef MEDIAPLAYER
109
#import "AgoraRtcChannelPublishHelper.h"
1110
#import <AgoraRtcKit/IAgoraRtcEngine.h>
1211
#import <AgoraRtcKit/IAgoraMediaEngine.h>
13-
#import "AudioFrameObserver.h"
12+
#import "AudioCircularBuffer.h"
13+
#import "scoped_ptr.h"
1414
#import <mutex>
1515
using namespace AgoraRTC;
16+
static NSObject *threadLockPush = [[NSObject alloc] init];
17+
static NSObject *threadLockPlay = [[NSObject alloc] init];
1618

19+
class AgoraAudioFrameObserver:public agora::media::IAudioFrameObserver
20+
{
21+
private:
22+
int16_t * record_buf_tmp_ = nullptr;
23+
char * record_audio_mix_ = nullptr;
24+
int16_t * record_send_buf_ = nullptr;
25+
26+
int16_t * play_buf_tmp_ = nullptr;
27+
char * play_audio_mix_ = nullptr;
28+
int16_t * play_send_buf_ = nullptr;
29+
scoped_ptr<AudioCircularBuffer<char>> record_audio_buf_;
30+
scoped_ptr<AudioCircularBuffer<char>> play_audio_buf_;
31+
public:
32+
std::atomic<float> publishSignalValue_{1.0f};
33+
std::atomic<float> playOutSignalValue_{1.0f};
34+
std::atomic<bool> isOnlyAudioPlay_{false};
35+
AgoraAudioFrameObserver(){
36+
record_audio_buf_.reset(new AudioCircularBuffer<char>(true,2048));
37+
play_audio_buf_.reset(new AudioCircularBuffer<char>(true,2048));
38+
}
39+
~AgoraAudioFrameObserver()
40+
{
41+
if (record_buf_tmp_) {
42+
free(record_buf_tmp_);
43+
}
44+
if(record_audio_mix_){
45+
free(record_audio_mix_);
46+
}
47+
if(record_send_buf_){
48+
free(record_send_buf_);
49+
}
50+
51+
if (play_buf_tmp_) {
52+
free(play_buf_tmp_);
53+
}
54+
if(play_audio_mix_){
55+
free(play_audio_mix_);
56+
}
57+
if (play_send_buf_) {
58+
free(play_send_buf_);
59+
}
60+
}
61+
void resetAudioBuffer(){
62+
63+
record_audio_buf_.reset(new AudioCircularBuffer<char>(2048,true));
64+
play_audio_buf_.reset(new AudioCircularBuffer<char>(2048,true));
65+
}
66+
void setPublishSignalVolume(int volume){
67+
@synchronized (threadLockPush) {
68+
publishSignalValue_ = volume/100.0f;
69+
}
70+
}
71+
void enableOnlyAudioPlay(bool isEnable){
72+
isOnlyAudioPlay_ = isEnable;
73+
}
74+
void setPlayoutSignalVolume(int volume){
75+
@synchronized (threadLockPlay) {
76+
playOutSignalValue_ = volume/100.0f;
77+
}
78+
}
79+
void pushData(char *data,int length){
80+
{
81+
if (!isOnlyAudioPlay_) {
82+
record_audio_buf_->Push(data, length);
83+
}
84+
}
85+
{
86+
play_audio_buf_->Push(data, length);
87+
}
88+
89+
}
90+
virtual bool onRecordAudioFrame(AudioFrame& audioFrame){
91+
@synchronized (threadLockPush) {
92+
int bytes = audioFrame.samples * audioFrame.channels * audioFrame.bytesPerSample;
93+
int ret = record_audio_buf_->mAvailSamples - bytes;
94+
if ( ret < 0) {
95+
return false;
96+
}
97+
//计算重采样钱的数据大小 重采样的采样率 * SDK回调时间 * 声道数 * 字节数
98+
if (!record_buf_tmp_) {
99+
record_buf_tmp_ = (int16_t *)malloc(bytes);
100+
}
101+
if(!record_audio_mix_){
102+
record_audio_mix_ = (char *)malloc(bytes);
103+
}
104+
if(!record_send_buf_){
105+
record_send_buf_ = (int16_t *)malloc(bytes);
106+
}
107+
record_audio_buf_->Pop(record_audio_mix_, bytes);
108+
int16_t* p16 = (int16_t*) record_audio_mix_;
109+
memcpy(record_buf_tmp_, audioFrame.buffer, bytes);
110+
for (int i = 0; i < bytes / 2; ++i) {
111+
record_buf_tmp_[i] += (p16[i] * publishSignalValue_);
112+
//audio overflow
113+
if (record_buf_tmp_[i] > 32767) {
114+
record_send_buf_[i] = 32767;
115+
}
116+
else if (record_buf_tmp_[i] < -32768) {
117+
record_send_buf_[i] = -32768;
118+
}
119+
else {
120+
record_send_buf_[i] = record_buf_tmp_[i];
121+
}
122+
}
123+
memcpy(audioFrame.buffer, record_send_buf_,bytes);
124+
}
125+
return true;
126+
}
127+
/**
128+
* Occurs when the playback audio frame is received.
129+
* @param audioframe The reference to the audio frame: AudioFrame.
130+
* @return
131+
* - true: The playback audio frame is valid and is encoded and sent.
132+
* - false: The playback audio frame is invalid and is not encoded or sent.
133+
*/
134+
virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame){
135+
@synchronized (threadLockPlay) {
136+
137+
int bytes = audioFrame.samples * audioFrame.channels * audioFrame.bytesPerSample;
138+
int ret = play_audio_buf_->mAvailSamples - bytes;
139+
if (ret < 0) {
140+
return false;
141+
}
142+
//计算重采样钱的数据大小 重采样的采样率 * SDK回调时间 * 声道数 * 字节数
143+
if(!play_buf_tmp_){
144+
play_buf_tmp_ = (int16_t *)malloc(bytes);
145+
}
146+
if(!play_audio_mix_){
147+
play_audio_mix_ = (char *)malloc(bytes);
148+
}
149+
if(!play_send_buf_){
150+
play_send_buf_ = (int16_t *)malloc(bytes);
151+
}
152+
play_audio_buf_->Pop(play_audio_mix_, bytes);
153+
int16_t* p16 = (int16_t*) play_audio_mix_;
154+
memcpy(play_buf_tmp_, audioFrame.buffer, bytes);
155+
for (int i = 0; i < bytes / 2; ++i) {
156+
play_buf_tmp_[i] += (p16[i] * playOutSignalValue_);
157+
//audio overflow
158+
if (play_buf_tmp_[i] > 32767) {
159+
play_send_buf_[i] = 32767;
160+
}
161+
else if (play_buf_tmp_[i] < -32768) {
162+
play_send_buf_[i] = -32768;
163+
}
164+
else {
165+
play_send_buf_[i] = play_buf_tmp_[i];
166+
}
167+
}
168+
memcpy(audioFrame.buffer, play_buf_tmp_,bytes);
169+
}
170+
return true;
171+
}
172+
/**
173+
* Occurs when the mixed audio data is received.
174+
* @param audioframe The reference to the audio frame: AudioFrame.
175+
* @return
176+
* - true: The mixed audio data is valid and is encoded and sent.
177+
* - false: The mixed audio data is invalid and is not encoded or sent.
178+
*/
179+
virtual bool onMixedAudioFrame(AudioFrame& audioFrame){
180+
return false;
181+
}
182+
/**
183+
* Occurs when the playback audio frame before mixing is received.
184+
* @param audioframe The reference to the audio frame: AudioFrame.
185+
* @return
186+
* - true: The playback audio frame before mixing is valid and is encoded and sent.
187+
* - false: The playback audio frame before mixing is invalid and is not encoded or sent.
188+
*/
189+
virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame){
190+
return false;
191+
}
192+
};
17193
@interface AgoraRtcChannelPublishHelper()<AgoraMediaPlayerDelegate,AgoraVideoSourceProtocol>
18194
{
19195
std::unique_ptr<AgoraAudioFrameObserver> audioFrameObserver;
@@ -39,7 +215,7 @@ + (instancetype)shareInstance{
39215
}
40216
// 连接 MediaPlayer 到主版本 RTC SDK
41217
- (void)attachPlayerToRtc:(AgoraMediaPlayer *)playerKit RtcEngine:(AgoraRtcEngineKit *)rtcEngine enableVideoSource:(bool)enable{
42-
audioFrameObserver.reset(new AgoraAudioFrameObserver);
218+
audioFrameObserver = std::make_unique<AgoraAudioFrameObserver>();
43219
isPublishVideo = false;
44220
audioFrameObserver->setPublishSignalVolume(0);
45221
self.isDispatchMainQueue = false;
@@ -48,7 +224,7 @@ - (void)attachPlayerToRtc:(AgoraMediaPlayer *)playerKit RtcEngine:(AgoraRtcEngin
48224
[rtcEngine setVideoSource:self];
49225
}
50226
[rtcEngine setParameters:@"{\"che.audio.keep.audiosession\":true}"];
51-
[rtcEngine setAudioProfile:AgoraAudioProfileMusicStandardStereo scenario:AgoraAudioScenarioGameStreaming];
227+
[rtcEngine setAudioProfile:AgoraAudioProfileMusicStandardStereo scenario:AgoraAudioScenarioChatRoomEntertainment];
52228
[rtcEngine setRecordingAudioFrameParametersWithSampleRate:48000 channel:2 mode:AgoraAudioRawFrameOperationModeReadWrite samplesPerCall:960];
53229
[rtcEngine setPlaybackAudioFrameParametersWithSampleRate:48000 channel:2 mode:AgoraAudioRawFrameOperationModeReadWrite samplesPerCall:960];
54230

@@ -70,6 +246,13 @@ - (void)unpublishAudio{
70246
}
71247

72248
}
249+
- (void)enableOnlyLocalAudioPlay:(bool)isEnable
250+
251+
{
252+
@synchronized (self) {
253+
audioFrameObserver->enableOnlyAudioPlay(isEnable);
254+
}
255+
}
73256
// 启动/停止推送视频流到频道
74257
- (void)publishVideo{
75258
@synchronized (self) {
@@ -99,15 +282,15 @@ - (void)detachPlayerFromRtc{
99282
@synchronized (self) {
100283
isPublishVideo=false;
101284
audioFrameObserver->setPublishSignalVolume(0);
102-
_playerKit.delegate = NULL;
103-
[_rtcEngineKit setVideoSource:NULL];
104285
[self unregisterRtcEngine:_rtcEngineKit];
105-
286+
[_rtcEngineKit setVideoSource:NULL];
287+
_playerKit.delegate = NULL;
288+
106289
}
107290
}
108291
- (void)resetAudioBuf{
109292
@synchronized (self) {
110-
audioFrameObserver->resetAudioBuf();
293+
audioFrameObserver->resetAudioBuffer();
111294
}
112295
}
113296
- (void)AgoraMediaPlayer:(AgoraMediaPlayer *_Nonnull)playerKit
@@ -178,19 +361,10 @@ - (void)shouldStop {
178361

179362
}
180363

181-
- (AgoraVideoCaptureType)captureType {
182-
return AgoraVideoCaptureTypeUnknown;
183-
}
184-
185-
186-
- (AgoraVideoContentHint)contentHint {
187-
return AgoraVideoContentHintDetails;
188-
}
189-
190-
191364
/// Description of state of Mediaplayer's state
192365
/// @param playerKit AgoraMediaPlayer
193366
/// @param state AgoraMediaPlayerState
367+
/// @param reason AgoraMediaPlayerStateReason
194368
/// @param error AgoraMediaPlayerError
195369
- (void)AgoraMediaPlayer:(AgoraMediaPlayer *_Nonnull)playerKit
196370
didChangedToState:(AgoraMediaPlayerState)state
@@ -272,4 +446,4 @@ - (void)executeBlock:(void (^)())block {
272446

273447
@end
274448

275-
#endif
449+

iOS/APIExample/Common/RtcChannelPublishPlugin/utils/AudioCircularBuffer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
#include "scoped_ptr.h"
1515
#include <string.h>
16+
#include <mutex>
17+
18+
19+
1620
template <typename Ty>
1721

1822
class AudioCircularBuffer {
@@ -23,6 +27,7 @@ class AudioCircularBuffer {
2327
: pInt16BufferPtr(nullptr),
2428
bNewWayProcessing(newWay)
2529
{
30+
std::lock_guard<std::mutex> _(mtx_);
2631
mInt16BufferLength = initSize;
2732
if (bNewWayProcessing) {
2833
pInt16BufferPtr = new value[sizeof(value) * mInt16BufferLength];
@@ -36,6 +41,7 @@ class AudioCircularBuffer {
3641

3742
~AudioCircularBuffer()
3843
{
44+
std::lock_guard<std::mutex> _(mtx_);
3945
if (pInt16BufferPtr) {
4046
delete [] pInt16BufferPtr;
4147
pInt16BufferPtr = nullptr;
@@ -44,6 +50,7 @@ class AudioCircularBuffer {
4450

4551
void Push(value* data, int length)
4652
{
53+
std::lock_guard<std::mutex> _(mtx_);
4754
if (bNewWayProcessing) {
4855
// If the internal buffer is not large enough, first enlarge the buffer
4956
if (mAvailSamples + length > mInt16BufferLength) {
@@ -106,6 +113,7 @@ class AudioCircularBuffer {
106113

107114
void Pop(value* data, int length)
108115
{
116+
std::lock_guard<std::mutex> _(mtx_);
109117
if (bNewWayProcessing) {
110118
int availSlots = mInt16BufferLength - mReadPtrPosition;
111119
if (availSlots < length) {
@@ -139,6 +147,7 @@ class AudioCircularBuffer {
139147

140148
void Reset()
141149
{
150+
std::lock_guard<std::mutex> _(mtx_);
142151
mAvailSamples = 0;
143152
mReadPtrPosition = 0;
144153
mWritePtrPosition = 0;
@@ -164,6 +173,7 @@ class AudioCircularBuffer {
164173
AgoraRTC::scoped_array<value> pInt16Buffer;
165174

166175
private:
176+
std::mutex mtx_;
167177
bool bNewWayProcessing;
168178

169179
};

0 commit comments

Comments
 (0)