[*] 音频采集

This commit is contained in:
acgist
2024-05-06 08:12:06 +08:00
parent 84d9d5c71e
commit 6085696aeb
5 changed files with 213 additions and 12 deletions

View File

@@ -38,7 +38,15 @@ static std::map<std::string, acgist::Room*> roomMap;
* 支持的编解码
*/
static void printSupportCodec() {
// TODO是否需要释放
OH_AVCapability* opus = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_OPUS, false);
OH_LOG_INFO(LOG_APP, "是否支持OPUS%o", OH_AVCapability_IsHardware(opus));
OH_AVCapability* pcmu = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_G711MU, false);
OH_LOG_INFO(LOG_APP, "是否支持PCMU%o", OH_AVCapability_IsHardware(pcmu));
OH_AVCapability* h264 = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false);
OH_LOG_INFO(LOG_APP, "是否支持H264%o", OH_AVCapability_IsHardware(h264));
OH_AVCapability* h265 = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, false);
OH_LOG_INFO(LOG_APP, "是否支持H264%o", OH_AVCapability_IsHardware(h265));
}
/**

View File

@@ -14,21 +14,73 @@
#ifndef taoyao_Capturer_HPP
#define taoyao_Capturer_HPP
#include <map>
#include "api/media_stream_track.h"
#include <ohaudio/native_audiocapturer.h>
#include <ohaudio/native_audiostreambuilder.h>
namespace acgist {
/**
* 采集器
*
* @tparam Sink 输出管道
*/
template <typename Sink>
class Capturer {
public:
std::map<std::string, Sink*> map;
public:
Capturer();
virtual ~Capturer();
public:
// 开始采集
virtual bool start() = 0;
// 结束采集
virtual bool stop() = 0;
};
/**
* 音频采集器
*/
class AudioCapturer: public Capturer<webrtc::AudioTrackSinkInterface> {
public:
// 音频流构造器
OH_AudioStreamBuilder* builder = nullptr;
// 音频采集器
OH_AudioCapturer* audioCapturer = nullptr;
public:
AudioCapturer();
virtual ~AudioCapturer();
public:
virtual bool start();
virtual bool stop();
};
class AudioCapturer {};
class VideoCapturer {};
/**
* 视频采集器
*/
class VideoCapturer: public Capturer<rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>> {
public:
VideoCapturer();
virtual ~VideoCapturer();
public:
virtual bool start();
virtual bool stop();
};
}

View File

@@ -13,11 +13,25 @@
#include <memory>
#include <thread>
#include "pc/peer_connection.h"
#include "pc/peer_connection_factory.h"
#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "api/video/video_sink_interface.h"
#include "api/video/video_source_interface.h"
namespace acgist {
class TaoyaoAudioSink : public webrtc::AudioTrackSinkInterface {
};
class TaoyaoVideoSource : public webrtc::VideoTrackSourceInterface {
};
class TaoyaoVideoSink : public rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame> {
};
class MediaManager {
public:
MediaManager();
@@ -35,12 +49,22 @@ public:
int newLocalClient();
// 释放本地终端
int releaseLocalClient();
void startCapture();
void startAudioCapture();
void startVideoCapture();
void stopCapture();
void stopAudioCapture();
void stopVideoCapture();
// 开始采集
bool startCapture();
// 开始采集音频
bool startAudioCapture();
// 开始采集视频
bool startVideoCapture();
// 结束采集
bool stopCapture();
// 结束采集音频
bool stopAudioCapture();
// 结束采集视频
bool stopVideoCapture();
// 音频来源
rtc::scoped_refptr<webrtc::AudioTrackInterface> getAudioTrack();
// 视频来源
rtc::scoped_refptr<webrtc::VideoTrackInterface> getVideoTrack();
};
}

View File

@@ -0,0 +1,91 @@
#include "../include/Capturer.hpp"
#include <hilog/log.h>
#include "rtc_base/time_utils.h"
#include <ohaudio/native_audiocapturer.h>
#include <ohaudio/native_audiostreambuilder.h>
// 采样率
static int32_t samplingRate = 48000;
// 声道数
static int32_t channelCount = 2;
// 音频场景
static OH_AudioStream_LatencyMode latencyMode = OH_AudioStream_LatencyMode::AUDIOSTREAM_LATENCY_MODE_NORMAL;
// 音频格式
static OH_AudioStream_SampleFormat sampleFormat = OH_AudioStream_SampleFormat::AUDIOSTREAM_SAMPLE_S16LE;
static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buffer, int32_t length);
static int32_t OnError(OH_AudioCapturer* capturer, void* userData, OH_AudioStream_Result error);
static int32_t OnStreamEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioStream_Event event);
static int32_t OnInterruptEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioInterrupt_ForceType type, OH_AudioInterrupt_Hint hint);
acgist::AudioCapturer::AudioCapturer() {
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
OH_LOG_INFO(LOG_APP, "构造音频采集:%o", ret);
}
acgist::AudioCapturer::~AudioCapturer() {
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Destroy(builder);
// TODO: 是否需要delete
builder = nullptr;
OH_LOG_INFO(LOG_APP, "释放音频采集:%o", ret);
}
bool acgist::AudioCapturer::start() {
// 配置采集参数
OH_AudioStreamBuilder_SetSamplingRate(builder, samplingRate);
OH_AudioStreamBuilder_SetChannelCount(builder, channelCount);
OH_AudioStreamBuilder_SetLatencyMode(builder, latencyMode);
OH_AudioStreamBuilder_SetSampleFormat(builder, sampleFormat);
OH_LOG_DEBUG(LOG_APP, "配置音频格式:%d %d %o %o", samplingRate, channelCount, latencyMode, sampleFormat);
// 设置回调函数
OH_AudioCapturer_Callbacks callbacks;
callbacks.OH_AudioCapturer_OnReadData = OnReadData;
callbacks.OH_AudioCapturer_OnError = OnError;
callbacks.OH_AudioCapturer_OnStreamEvent = OnStreamEvent;
callbacks.OH_AudioCapturer_OnInterruptEvent = OnInterruptEvent;
OH_AudioStream_Result ret = OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, this);
OH_LOG_DEBUG(LOG_APP, "设置回调函数:%o", ret);
// 构造音频采集器
ret = OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);
OH_LOG_DEBUG(LOG_APP, "构造音频采集器:%o", ret);
// 开始录制
ret = OH_AudioCapturer_Start(audioCapturer);
OH_LOG_DEBUG(LOG_APP, "开始录制:%o", ret);
}
bool acgist::AudioCapturer::stop() {
// 停止录制
OH_AudioStream_Result ret = OH_AudioCapturer_Stop(audioCapturer);
OH_LOG_DEBUG(LOG_APP, "停止录制:%o", ret);
// 释放音频采集器
ret = OH_AudioCapturer_Release(audioCapturer);
audioCapturer = nullptr;
OH_LOG_DEBUG(LOG_APP, "释放音频采集器:%o", ret);
}
static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buffer, int32_t length) {
acgist::AudioCapturer* audioCapturer = (acgist::AudioCapturer*) userData;
int64_t timeMillis = rtc::TimeMillis();
for (
auto iterator = audioCapturer->map.begin();
iterator != audioCapturer->map.end();
++iterator
) {
iterator->second->OnData(buffer, 16, samplingRate, channelCount, sizeof(buffer) / 2, timeMillis);
}
}
static int32_t OnError(OH_AudioCapturer* capturer, void* userData, OH_AudioStream_Result error) {
OH_LOG_ERROR(LOG_APP, "音频采集发生异常:%o", error);
}
static int32_t OnStreamEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioStream_Event event) {
OH_LOG_DEBUG(LOG_APP, "音频采集事件:%o", event);
}
static int32_t OnInterruptEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioInterrupt_ForceType type, OH_AudioInterrupt_Hint hint) {
OH_LOG_DEBUG(LOG_APP, "音频采集打断:%o %o", type, hint);
}

View File

@@ -54,3 +54,29 @@ bool acgist::MediaManager::initPeerConnectionFactory() {
int acgist::MediaManager::newLocalClient() {
this->localClientRef++;
}
bool acgist::MediaManager::startCapture() {
this->startAudioCapture();
this->startVideoCapture();
}
bool acgist::MediaManager::startAudioCapture() {
return true;
}
rtc::scoped_refptr<webrtc::AudioTrackInterface> acgist::MediaManager::getAudioTrack() {
cricket::AudioOptions options;
options.highpass_filter = true;
options.auto_gain_control = true;
options.echo_cancellation = true;
options.noise_suppression = true;
auto audioSource = this->peerConnectionFactory->CreateAudioSource(options);
return this->peerConnectionFactory->CreateAudioTrack("taoyao-audio", audioSource.get());
}
rtc::scoped_refptr<webrtc::VideoTrackInterface> acgist::MediaManager::getVideoTrack() {
// webrtc::VideoTrackSourceInterface videoSource;
// this->peerConnectionFactory->CreateVideoTrack("taoyao-video", videoSource);
return nullptr;
}