Skip to content

Commit 7e79778

Browse files
author
zhaoyongqiang
committed
添加SimpleFilter文件
1 parent fb46aa2 commit 7e79778

16 files changed

Lines changed: 972 additions & 63 deletions

macOS/APIExample.xcodeproj/project.pbxproj

Lines changed: 62 additions & 62 deletions
Large diffs are not rendered by default.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Created by DYF on 2020/7/13.
3+
//
4+
5+
#ifndef AGORA_AUDIOPROCESSOR_H
6+
#define AGORA_AUDIOPROCESSOR_H
7+
8+
#include <thread>
9+
#include <string>
10+
#include <mutex>
11+
#include <vector>
12+
#include <AgoraRtcKit/AgoraRefPtr.h>
13+
#include "AgoraRtcKit/NGIAgoraMediaNode.h"
14+
#include "AgoraRtcKit/AgoraMediaBase.h"
15+
16+
namespace agora {
17+
namespace extension {
18+
class AdjustVolumeAudioProcessor : public RefCountInterface {
19+
public:
20+
int processFrame(const agora::media::base::AudioPcmFrame &audioPcmFrame,
21+
media::base::AudioPcmFrame& adaptedPcmFrame);
22+
23+
void dataCallback(const char* data);
24+
25+
void setVolume(int volume) { volume_ = volume / 100.0f; }
26+
27+
int setExtensionControl(agora::agora_refptr<rtc::IExtensionVideoFilter::Control> control){
28+
control_ = control;
29+
return 0;
30+
};
31+
protected:
32+
~AdjustVolumeAudioProcessor() {}
33+
private:
34+
static int16_t FloatS16ToS16(float v);
35+
private:
36+
std::atomic<float> volume_ = {1.0f};
37+
agora::agora_refptr<rtc::IExtensionVideoFilter::Control> control_;
38+
};
39+
}
40+
}
41+
42+
43+
#endif //AGORA_AUDIOPROCESSOR_H
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Created by DYF on 2020/7/13.
3+
//
4+
5+
#include "AudioProcessor.hpp"
6+
#include <chrono>
7+
8+
9+
namespace agora {
10+
namespace extension {
11+
using limits_int16 = std::numeric_limits<int16_t>;
12+
int16_t AdjustVolumeAudioProcessor::FloatS16ToS16(float v) {
13+
static const float kMaxRound = (limits_int16::max)() - 0.5f;
14+
static const float kMinRound = (limits_int16::min)() + 0.5f;
15+
if (v > 0) {
16+
return v >= kMaxRound ? (limits_int16::max)() : static_cast<int16_t>(v + 0.5f);
17+
}
18+
return v <= kMinRound ? (limits_int16::min)() : static_cast<int16_t>(v - 0.5f);
19+
}
20+
21+
int AdjustVolumeAudioProcessor::processFrame(const media::base::AudioPcmFrame& inAudioPcmFrame,
22+
media::base::AudioPcmFrame& adaptedPcmFrame) {
23+
// PRINTF_ERROR("adaptAudioFrame %f", volume_.load());
24+
size_t length = inAudioPcmFrame.samples_per_channel_ * inAudioPcmFrame.num_channels_;
25+
for (int idx = 0; idx < length; idx++) {
26+
adaptedPcmFrame.data_[idx] = FloatS16ToS16(inAudioPcmFrame.data_[idx] * volume_);
27+
}
28+
return 0;
29+
}
30+
31+
void AdjustVolumeAudioProcessor::dataCallback(const char* data){
32+
if (control_) {
33+
control_->postEvent("volume", data);
34+
}
35+
}
36+
}
37+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//
2+
// Created by 张涛 on 2020/4/26.
3+
//
4+
5+
#include "ExtensionAudioFilter.hpp"
6+
#include <sstream>
7+
8+
namespace agora {
9+
namespace extension {
10+
ExtensionAudioFilter::ExtensionAudioFilter(const char* name, agora_refptr<AdjustVolumeAudioProcessor> audioProcessor) {
11+
filterName_ = name;
12+
audioProcessor_ = audioProcessor;
13+
}
14+
15+
ExtensionAudioFilter::~ExtensionAudioFilter() {
16+
17+
}
18+
19+
bool ExtensionAudioFilter::adaptAudioFrame(const media::base::AudioPcmFrame& inAudioPcmFrame,
20+
media::base::AudioPcmFrame& adaptedPcmFrame) {
21+
return audioProcessor_->processFrame(inAudioPcmFrame, adaptedPcmFrame) == 0;
22+
}
23+
24+
int ExtensionAudioFilter::setProperty(const char* key, const void* buf, int buf_size) {
25+
std::string str_volume = "100";
26+
if (std::string(key) == "volume") {
27+
str_volume = std::string(static_cast<const char*>(buf), buf_size);
28+
}
29+
30+
int int_volume_ = atoi(str_volume.c_str());
31+
audioProcessor_->setVolume(int_volume_);
32+
return ERR_OK;
33+
}
34+
}
35+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Created by 张涛 on 2020/4/26.
3+
//
4+
5+
#ifndef AGORA_EXTENSIONAUDIOFILTER_H
6+
#define AGORA_EXTENSIONAUDIOFILTER_H
7+
8+
#include "AgoraRtcKit/NGIAgoraMediaNode.h"
9+
#include <AgoraRtcKit/AgoraRefCountedObject.h>
10+
#include "AgoraRtcKit/AgoraRefPtr.h"
11+
#include "AudioProcessor.hpp"
12+
13+
namespace agora {
14+
namespace extension {
15+
class ExtensionAudioFilter : public agora::rtc::IAudioFilter {
16+
public:
17+
ExtensionAudioFilter(const char* name, agora_refptr<AdjustVolumeAudioProcessor> processor);
18+
~ExtensionAudioFilter();
19+
bool adaptAudioFrame(const media::base::AudioPcmFrame& inAudioPcmFrame,
20+
media::base::AudioPcmFrame& adaptedPcmFrame) override;
21+
void setEnabled(bool enable) override { enabled_ = enable; }
22+
bool isEnabled() const override { return enabled_; }
23+
int setProperty(const char* key, const void* buf, int buf_size) override;
24+
int getProperty(const char* key, void* buf, int buf_size) const override { return ERR_OK; }
25+
const char* getName() const override { return filterName_.c_str(); }
26+
private:
27+
std::atomic_bool enabled_ = {true};
28+
std::string filterName_;
29+
agora_refptr<AdjustVolumeAudioProcessor> audioProcessor_;
30+
protected:
31+
ExtensionAudioFilter() = default;
32+
};
33+
}
34+
}
35+
36+
37+
#endif //AGORA_EXTENSIONAUDIOFILTER_H
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// Created by 张涛 on 2020/4/26.
3+
//
4+
5+
#include "ExtensionProvider.hpp"
6+
7+
namespace agora {
8+
namespace extension {
9+
ExtensionProvider::ExtensionProvider() {
10+
audioProcessor_ = new agora::RefCountedObject<AdjustVolumeAudioProcessor>();
11+
YUVProcessor_ = new agora::RefCountedObject<YUVImageProcessor>();
12+
}
13+
14+
ExtensionProvider::~ExtensionProvider() {
15+
audioProcessor_.reset();
16+
YUVProcessor_.reset();
17+
}
18+
19+
// Provide information about all plug-ins that support packaging.
20+
// When the SDK loads the plug-in, it will call this method to send a callback to the plug-in.
21+
// You need to provide information about all plug-ins that support encapsulation.
22+
void ExtensionProvider::enumerateExtensions(ExtensionMetaInfo* extension_list,
23+
int& extension_count) {
24+
extension_count = 2;
25+
//Declare a Video Filter, and IExtensionProvider::createVideoFilter will be called
26+
ExtensionMetaInfo i;
27+
i.type = EXTENSION_TYPE::VIDEO_PRE_PROCESSING_FILTER;
28+
i.extension_name = agora::extension::VIDEO_FILTER_NAME;
29+
extension_list[0] = i;
30+
31+
//Declare an Audio Filter, and IExtensionProvider::createAudioFilter will be called
32+
ExtensionMetaInfo j;
33+
j.type = EXTENSION_TYPE::AUDIO_FILTER;
34+
j.extension_name = agora::extension::AUDIO_FILTER_NAME;
35+
extension_list[1] = j;
36+
}
37+
38+
// Create a video plug-in. After the SDK calls this method, you need to return the IExtensionVideoFilter instance
39+
agora_refptr<agora::rtc::IExtensionVideoFilter> ExtensionProvider::createVideoFilter(const char* name) {
40+
auto videoFilter = new agora::RefCountedObject<agora::extension::ExtensionVideoFilter>(YUVProcessor_);
41+
return videoFilter;
42+
}
43+
44+
// Create a video plug-in. After the SDK calls this method, you need to return the IAudioFilter instance
45+
agora_refptr<agora::rtc::IAudioFilter> ExtensionProvider::createAudioFilter(const char* name) {
46+
auto audioFilter = new agora::RefCountedObject<agora::extension::ExtensionAudioFilter>(name, audioProcessor_);
47+
return audioFilter;
48+
}
49+
50+
agora_refptr<agora::rtc::IVideoSinkBase> ExtensionProvider::createVideoSink(const char* name) {
51+
return nullptr;
52+
}
53+
54+
void ExtensionProvider::setExtensionControl(rtc::IExtensionControl* control){
55+
}
56+
}
57+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// Created by 张涛 on 2020/4/26.
3+
//
4+
5+
#ifndef AGORA_EXTENSION_PROVIDER_H
6+
#define AGORA_EXTENSION_PROVIDER_H
7+
8+
#include "AgoraRtcKit/NGIAgoraExtensionProvider.h"
9+
#include "ExtensionAudioFilter.hpp"
10+
#include "ExtensionVideoFilter.hpp"
11+
12+
namespace agora {
13+
namespace extension {
14+
static const char* AUDIO_FILTER_NAME = "VolumeChange";
15+
static const char* VIDEO_FILTER_NAME = "Grey";
16+
17+
class ExtensionProvider : public agora::rtc::IExtensionProvider {
18+
private:
19+
agora_refptr<AdjustVolumeAudioProcessor> audioProcessor_;
20+
agora_refptr<YUVImageProcessor> YUVProcessor_;
21+
public:
22+
ExtensionProvider();
23+
24+
~ExtensionProvider();
25+
26+
void setExtensionControl(rtc::IExtensionControl* control) override;
27+
void enumerateExtensions(ExtensionMetaInfo* extension_list, int& extension_count) override;
28+
agora_refptr<rtc::IAudioFilter> createAudioFilter(const char* name) override;
29+
agora_refptr<rtc::IExtensionVideoFilter> createVideoFilter(const char* name) override;
30+
agora_refptr<rtc::IVideoSinkBase> createVideoSink(const char* name) override;
31+
};
32+
}
33+
}
34+
#endif //AGORA_EXTENSION_PROVIDER_H
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Created by 张涛 on 2020/4/26.
3+
//
4+
5+
#include "ExtensionVideoFilter.hpp"
6+
#include <sstream>
7+
8+
namespace agora {
9+
namespace extension {
10+
11+
ExtensionVideoFilter::ExtensionVideoFilter(agora_refptr<YUVImageProcessor> processor):threadPool_(1) {
12+
YUVProcessor = processor;
13+
}
14+
15+
ExtensionVideoFilter::~ExtensionVideoFilter() {
16+
YUVProcessor->releaseOpenGL();
17+
}
18+
19+
//Set the process mode between the SDK and the video plug-in
20+
//If set ProcessMode to Sync mode, Agora SDK and video extension will pass data through adaptVideoFrame
21+
//If set ProcessMode to Async mode, Agora SDK and video extension will pass data through pendVideoFrame and deliverVideoFrame
22+
//If set independent_thread to false, all callbacks sent by Agora SDK are performed on the internal video processing thread
23+
//If set independent_thread to true, all callbacks sent by Agora SDK are performed on a separate thread
24+
void ExtensionVideoFilter::getProcessMode(ProcessMode& mode, bool& independent_thread) {
25+
mode = ProcessMode::kSync;
26+
independent_thread = false;
27+
mode_ = mode;
28+
}
29+
30+
//Set the type and format of the video data to be processed
31+
void ExtensionVideoFilter::getVideoFormatWanted(rtc::VideoFrameData::Type& type,
32+
rtc::RawPixelBuffer::Format& format) {
33+
type = rtc::VideoFrameData::Type::kRawPixels;
34+
format = rtc::RawPixelBuffer::Format::kI420;
35+
}
36+
37+
int ExtensionVideoFilter::start(agora::agora_refptr<Control> control) {
38+
printf("ExtensionVideoFilter::start\n");
39+
if (!YUVProcessor) {
40+
return -1;
41+
}
42+
if (control) {
43+
control_ = control;
44+
YUVProcessor->setExtensionControl(control);
45+
}
46+
if (mode_ == ProcessMode::kAsync){
47+
invoker_id = threadPool_.RegisterInvoker("thread_videofilter");
48+
auto res = threadPool_.PostTaskWithRes(invoker_id, [yuvProcessor=YUVProcessor] {
49+
return yuvProcessor->initOpenGL();
50+
});
51+
isInitOpenGL = res.get();
52+
} else {
53+
isInitOpenGL = YUVProcessor->initOpenGL();
54+
}
55+
return 0;
56+
}
57+
58+
int ExtensionVideoFilter::stop() {
59+
printf("ExtensionVideoFilter::stop\n");
60+
if (YUVProcessor) {
61+
YUVProcessor->releaseOpenGL();
62+
isInitOpenGL = false;
63+
}
64+
return 0;
65+
}
66+
67+
rtc::IExtensionVideoFilter::ProcessResult ExtensionVideoFilter::pendVideoFrame(agora::agora_refptr<rtc::IVideoFrame> frame) {
68+
if (!frame || !isInitOpenGL) {
69+
return kBypass;
70+
}
71+
72+
bool isAsyncMode = (mode_ == ProcessMode::kAsync);
73+
if (isAsyncMode && YUVProcessor && control_ && invoker_id >= 0) {
74+
threadPool_.PostTask(invoker_id, [videoFrame=frame, processor=YUVProcessor, control=control_] {
75+
rtc::VideoFrameData srcData;
76+
videoFrame->getVideoFrameData(srcData);
77+
processor->processFrame(srcData);
78+
// In asynchronous mode (mode is set to Async),
79+
// the plug-in needs to call this method to return the processed video frame to the SDK.
80+
control->deliverVideoFrame(videoFrame);
81+
});
82+
return kSuccess;
83+
}
84+
return kBypass;
85+
}
86+
87+
rtc::IExtensionVideoFilter::ProcessResult ExtensionVideoFilter::adaptVideoFrame(agora::agora_refptr<rtc::IVideoFrame> src,
88+
agora::agora_refptr<rtc::IVideoFrame>& dst) {
89+
if (!isInitOpenGL) {
90+
return kBypass;
91+
}
92+
bool isSyncMode = (mode_ == ProcessMode::kSync);
93+
if (isSyncMode && YUVProcessor) {
94+
rtc::VideoFrameData srcData;
95+
src->getVideoFrameData(srcData);
96+
YUVProcessor->processFrame(srcData);
97+
dst = src;
98+
return kSuccess;
99+
}
100+
return kBypass;
101+
}
102+
103+
// When the app developer calls RtcEngine.setExtensionProperty,
104+
// Agora SDK will call this method to set video plug-in properties
105+
int ExtensionVideoFilter::setProperty(const char *key, const void *buf,
106+
size_t buf_size) {
107+
printf("setProperty %s %s\n", key, buf);
108+
std::string stringParameter((char*)buf);
109+
YUVProcessor->setParameters(stringParameter);
110+
return 0;
111+
}
112+
113+
// When the app developer calls getExtensionProperty,
114+
// Agora SDK will call this method to get the properties of the video plug-in
115+
int ExtensionVideoFilter::getProperty(const char *key, void *buf, size_t buf_size) {
116+
return -1;
117+
}
118+
119+
void ExtensionVideoFilter::setEnabled(bool enable) {
120+
}
121+
122+
bool ExtensionVideoFilter::isEnabled() {
123+
return true;
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)