[*] 视频采集编码
This commit is contained in:
@@ -40,6 +40,7 @@ add_library(
|
|||||||
media/Capturer.cpp
|
media/Capturer.cpp
|
||||||
media/AudioCapturer.cpp
|
media/AudioCapturer.cpp
|
||||||
media/VideoCapturer.cpp
|
media/VideoCapturer.cpp
|
||||||
|
media/VideoEncoder.cpp
|
||||||
media/MediaManager.cpp
|
media/MediaManager.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* 方法绑定
|
* NAPI(NODE-API)
|
||||||
|
*
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/native-lib/napi.md
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -80,7 +82,13 @@ static napi_value shutdown(napi_env env, napi_callback_info info) {
|
|||||||
OH_LOG_INFO(LOG_APP, "卸载libtaoyao");
|
OH_LOG_INFO(LOG_APP, "卸载libtaoyao");
|
||||||
OH_LOG_INFO(LOG_APP, "释放mediasoupclient");
|
OH_LOG_INFO(LOG_APP, "释放mediasoupclient");
|
||||||
mediasoupclient::Cleanup();
|
mediasoupclient::Cleanup();
|
||||||
// this->roomMap
|
// 删除房间
|
||||||
|
for(auto iterator = roomMap.begin(); iterator != roomMap.end(); ++iterator) {
|
||||||
|
delete iterator->second;
|
||||||
|
iterator->second = nullptr;
|
||||||
|
}
|
||||||
|
roomMap.clear();
|
||||||
|
// 关闭媒体
|
||||||
if (mediaManager != nullptr) {
|
if (mediaManager != nullptr) {
|
||||||
delete mediaManager;
|
delete mediaManager;
|
||||||
mediaManager = nullptr;
|
mediaManager = nullptr;
|
||||||
@@ -90,6 +98,9 @@ static napi_value shutdown(napi_env env, napi_callback_info info) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
*/
|
||||||
static void send(const std::string& signal, const std::string& body) {
|
static void send(const std::string& signal, const std::string& body) {
|
||||||
napi_value ret;
|
napi_value ret;
|
||||||
napi_value callback = nullptr;
|
napi_value callback = nullptr;
|
||||||
@@ -101,6 +112,9 @@ static void send(const std::string& signal, const std::string& body) {
|
|||||||
// napi_get_undefined(acgist::env, &ret);
|
// napi_get_undefined(acgist::env, &ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送请求
|
||||||
|
*/
|
||||||
static std::string request(const std::string& signal, const std::string& body) {
|
static std::string request(const std::string& signal, const std::string& body) {
|
||||||
napi_value ret;
|
napi_value ret;
|
||||||
napi_value callback = nullptr;
|
napi_value callback = nullptr;
|
||||||
@@ -115,34 +129,27 @@ static std::string request(const std::string& signal, const std::string& body) {
|
|||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
static napi_value mediaConsume(napi_env env, napi_callback_info info) { return 0; }
|
/**
|
||||||
|
* 房间关闭
|
||||||
static napi_value mediaConsumerClose(napi_env env, napi_callback_info info) { return 0; }
|
*/
|
||||||
|
|
||||||
static napi_value mediaConsumerPause(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value mediaConsumerResume(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value mediaProducerClose(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value mediaProducerPause(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value mediaProducerResume(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value roomClientList(napi_env env, napi_callback_info info) { return 0; }
|
|
||||||
|
|
||||||
static napi_value roomClose(napi_env env, napi_callback_info info) { return 0; }
|
static napi_value roomClose(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 其他终端进入房间
|
* 进入房间
|
||||||
|
* 其他终端进入房间,自己进入房间逻辑参考房间邀请。
|
||||||
*/
|
*/
|
||||||
static napi_value roomEnter(napi_env env, napi_callback_info info) {
|
static napi_value roomEnter(napi_env env, napi_callback_info info) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 踢出房间
|
||||||
|
* 踢出房间以后终端离开房间
|
||||||
|
*/
|
||||||
static napi_value roomExpel(napi_env env, napi_callback_info info) { return 0; }
|
static napi_value roomExpel(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 房间邀请
|
||||||
* 邀请终端进入房间
|
* 邀请终端进入房间
|
||||||
*/
|
*/
|
||||||
static napi_value roomInvite(napi_env env, napi_callback_info info) {
|
static napi_value roomInvite(napi_env env, napi_callback_info info) {
|
||||||
@@ -174,8 +181,56 @@ static napi_value roomInvite(napi_env env, napi_callback_info info) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 离开房间
|
||||||
|
* 其他终端离开房间
|
||||||
|
*/
|
||||||
static napi_value roomLeave(napi_env env, napi_callback_info info) { return 0; }
|
static napi_value roomLeave(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 终端列表
|
||||||
|
* 房间所有终端列表首次进入方便加载终端列表信息
|
||||||
|
*/
|
||||||
|
static napi_value roomClientList(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体消费(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaConsume(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费者关闭(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaConsumerClose(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费者暂停(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaConsumerPause(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费者恢复(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaConsumerResume(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产者关闭(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaProducerClose(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产者暂停(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaProducerPause(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生产者恢复(被动通知)
|
||||||
|
*/
|
||||||
|
static napi_value mediaProducerResume(napi_env env, napi_callback_info info) { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册发送回调
|
||||||
|
*/
|
||||||
static napi_value registerSend(napi_env env, napi_callback_info info) {
|
static napi_value registerSend(napi_env env, napi_callback_info info) {
|
||||||
size_t argc = 1;
|
size_t argc = 1;
|
||||||
napi_value args[1] = { nullptr };
|
napi_value args[1] = { nullptr };
|
||||||
@@ -184,6 +239,9 @@ static napi_value registerSend(napi_env env, napi_callback_info info) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册请求回调
|
||||||
|
*/
|
||||||
static napi_value registerRequest(napi_env env, napi_callback_info info) {
|
static napi_value registerRequest(napi_env env, napi_callback_info info) {
|
||||||
size_t argc = 1;
|
size_t argc = 1;
|
||||||
napi_value args[1] = { nullptr };
|
napi_value args[1] = { nullptr };
|
||||||
@@ -200,6 +258,13 @@ EXTERN_C_START
|
|||||||
static napi_value Init(napi_env env, napi_value exports) {
|
static napi_value Init(napi_env env, napi_value exports) {
|
||||||
acgist::env = env;
|
acgist::env = env;
|
||||||
napi_property_descriptor desc[] = {
|
napi_property_descriptor desc[] = {
|
||||||
|
{ "shutdown", nullptr, acgist::shutdown, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomClose", nullptr, acgist::roomClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomEnter", nullptr, acgist::roomEnter, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomExpel", nullptr, acgist::roomExpel, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomInvite", nullptr, acgist::roomInvite, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomLeave", nullptr, acgist::roomLeave, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
|
{ "roomClientList", nullptr, acgist::roomClientList, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "mediaConsume", nullptr, acgist::mediaConsume, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaConsume", nullptr, acgist::mediaConsume, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "mediaConsumerClose", nullptr, acgist::mediaConsumerClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaConsumerClose", nullptr, acgist::mediaConsumerClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "mediaConsumerPause", nullptr, acgist::mediaConsumerPause, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaConsumerPause", nullptr, acgist::mediaConsumerPause, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
@@ -207,13 +272,6 @@ static napi_value Init(napi_env env, napi_value exports) {
|
|||||||
{ "mediaProducerClose", nullptr, acgist::mediaProducerClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaProducerClose", nullptr, acgist::mediaProducerClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "mediaProducerPause", nullptr, acgist::mediaProducerPause, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaProducerPause", nullptr, acgist::mediaProducerPause, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "mediaProducerResume", nullptr, acgist::mediaProducerResume, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "mediaProducerResume", nullptr, acgist::mediaProducerResume, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "roomClientList", nullptr, acgist::roomClientList, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "roomClose", nullptr, acgist::roomClose, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "roomEnter", nullptr, acgist::roomEnter, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "roomExpel", nullptr, acgist::roomExpel, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "roomInvite", nullptr, acgist::roomInvite, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "roomLeave", nullptr, acgist::roomLeave, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "shutdown", nullptr, acgist::shutdown, nullptr, nullptr, nullptr, napi_default, nullptr },
|
|
||||||
{ "registerSend", nullptr, acgist::registerSend, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "registerSend", nullptr, acgist::registerSend, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
{ "registerRequest", nullptr, acgist::registerRequest, nullptr, nullptr, nullptr, napi_default, nullptr },
|
{ "registerRequest", nullptr, acgist::registerRequest, nullptr, nullptr, nullptr, napi_default, nullptr },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,16 +3,15 @@
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*
|
*
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/media/audio-encoding.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/audio-encoding.md
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/media/video-encoding.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/video-encoding.md
|
||||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/avscreen-capture.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/avscreen-capture.md
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/media/obtain-supported-codecs.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/native-lib/opengles.md
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/native-lib/opensles.md
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/obtain-supported-codecs.md
|
||||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/camera/native-camera-recording.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/camera/native-camera-recording.md
|
||||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/using-ohaudio-for-recording.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/using-ohaudio-for-recording.md
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/reference/native-lib/third_party_opengl/opengles.md
|
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/reference/native-lib/third_party_opensles/opensles.md
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef taoyao_Capturer_HPP
|
#ifndef taoyao_Capturer_HPP
|
||||||
#define taoyao_Capturer_HPP
|
#define taoyao_Capturer_HPP
|
||||||
|
|
||||||
@@ -26,6 +25,8 @@
|
|||||||
#include <ohaudio/native_audiocapturer.h>
|
#include <ohaudio/native_audiocapturer.h>
|
||||||
#include <ohaudio/native_audiostreambuilder.h>
|
#include <ohaudio/native_audiostreambuilder.h>
|
||||||
|
|
||||||
|
#include <multimedia/player_framework/native_avcodec_videoencoder.h>
|
||||||
|
|
||||||
namespace acgist {
|
namespace acgist {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +38,7 @@ template <typename Sink>
|
|||||||
class Capturer {
|
class Capturer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// rtc::scoped_refptr
|
||||||
std::map<std::string, Sink*> map;
|
std::map<std::string, Sink*> map;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -44,6 +46,10 @@ public:
|
|||||||
virtual ~Capturer();
|
virtual ~Capturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// 添加管道
|
||||||
|
virtual bool add(const std::string& id, Sink* sink);
|
||||||
|
// 删除管道
|
||||||
|
virtual bool remove(const std::string& id);
|
||||||
// 开始采集
|
// 开始采集
|
||||||
virtual bool start() = 0;
|
virtual bool start() = 0;
|
||||||
// 结束采集
|
// 结束采集
|
||||||
@@ -51,6 +57,38 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
acgist::Capturer<Sink>::Capturer() {}
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
acgist::Capturer<Sink>::~Capturer() {
|
||||||
|
for (auto iterator = this->map.begin(); iterator != this->map.end(); ++iterator) {
|
||||||
|
// TODO:释放
|
||||||
|
// delete iterator->second;
|
||||||
|
// iterator->second = nullptr;
|
||||||
|
}
|
||||||
|
this->map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
bool acgist::Capturer<Sink>::add(const std::string& id, Sink* sink) {
|
||||||
|
this->map.insert(std::make_pair(id, sink));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
bool acgist::Capturer<Sink>::remove(const std::string& id) {
|
||||||
|
auto iterator = this->map.find(id);
|
||||||
|
if (iterator == this->map.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO:释放
|
||||||
|
// delete iterator->second;
|
||||||
|
// iterator->second = nullptr;
|
||||||
|
this->map.erase(iterator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 音频采集器
|
* 音频采集器
|
||||||
*/
|
*/
|
||||||
@@ -67,30 +105,69 @@ public:
|
|||||||
virtual ~AudioCapturer();
|
virtual ~AudioCapturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool start();
|
virtual bool start() override;
|
||||||
virtual bool stop();
|
virtual bool stop() override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频编码
|
||||||
|
*/
|
||||||
|
class VideoEncoder {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 视频编码器
|
||||||
|
OH_AVCodec* avCodec;
|
||||||
|
// 视频窗口
|
||||||
|
OHNativeWindow* nativeWindow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VideoEncoder();
|
||||||
|
virtual ~VideoEncoder();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 重新开始
|
||||||
|
void restart();
|
||||||
|
// 动态配置
|
||||||
|
void reset(OH_AVFormat *format);
|
||||||
|
// 动态配置
|
||||||
|
void resetIntConfig(const char* key, int32_t value);
|
||||||
|
// 动态配置
|
||||||
|
void resetLongConfig(const char* key, int64_t value);
|
||||||
|
// 动态配置
|
||||||
|
void resetDoubleConfig(const char* key, double value);
|
||||||
|
// 开始编码
|
||||||
|
bool start();
|
||||||
|
// 结束编码
|
||||||
|
bool stop();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频采集器
|
* 视频采集器
|
||||||
*/
|
*/
|
||||||
class VideoCapturer: public Capturer<rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>> {
|
class VideoCapturer: public Capturer<rtc::VideoSinkInterface<webrtc::VideoFrame>> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Camera_Device* camera_Device;
|
// 摄像头设备数量
|
||||||
Camera_Manager* camera_Manager;
|
uint32_t size = 0;
|
||||||
Camera_VideoOutput* camera_VideoOutput;
|
// 摄像头索引
|
||||||
Camera_VideoProfile* camera_VideoProfile;
|
uint32_t cameraIndex = 0;
|
||||||
Camera_OutputCapability* camera_OutputCapability;
|
// 摄像头设备列表
|
||||||
|
Camera_Device* cameraDevice = nullptr;
|
||||||
|
// 摄像头管理器
|
||||||
|
Camera_Manager* cameraManager = nullptr;
|
||||||
|
// 摄像头视频输出
|
||||||
|
Camera_VideoOutput* cameraVideoOutput = nullptr;
|
||||||
|
// 摄像头输出能力
|
||||||
|
Camera_OutputCapability* cameraOutputCapability = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VideoCapturer();
|
VideoCapturer();
|
||||||
virtual ~VideoCapturer();
|
virtual ~VideoCapturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool start();
|
virtual bool start() override;
|
||||||
virtual bool stop();
|
virtual bool stop() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef taoyao_Client_HPP
|
#ifndef taoyao_Client_HPP
|
||||||
#define taoyao_Client_HPP
|
#define taoyao_Client_HPP
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*
|
*
|
||||||
* https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/media/obtain-supported-codecs.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/obtain-supported-codecs.md
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef taoyao_MediaManager_HPP
|
#ifndef taoyao_MediaManager_HPP
|
||||||
#define taoyao_MediaManager_HPP
|
#define taoyao_MediaManager_HPP
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/audio-playback-overview.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/audio-playback-overview.md
|
||||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/using-ndk-avplayer-for-playerback.md
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/using-ndk-avplayer-for-playerback.md
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TAOYAO_PALYER_H
|
#ifndef TAOYAO_PALYER_H
|
||||||
#define TAOYAO_PALYER_H
|
#define TAOYAO_PALYER_H
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef taoyao_Room_HPP
|
#ifndef taoyao_Room_HPP
|
||||||
#define taoyao_Room_HPP
|
#define taoyao_Room_HPP
|
||||||
|
|
||||||
|
|||||||
@@ -19,23 +19,22 @@ static int32_t OnStreamEvent(OH_AudioCapturer* capturer, void* userData, OH_Audi
|
|||||||
static int32_t OnInterruptEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioInterrupt_ForceType type, OH_AudioInterrupt_Hint hint);
|
static int32_t OnInterruptEvent(OH_AudioCapturer* capturer, void* userData, OH_AudioInterrupt_ForceType type, OH_AudioInterrupt_Hint hint);
|
||||||
|
|
||||||
acgist::AudioCapturer::AudioCapturer() {
|
acgist::AudioCapturer::AudioCapturer() {
|
||||||
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
|
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Create(&this->builder, AUDIOSTREAM_TYPE_RENDERER);
|
||||||
OH_LOG_INFO(LOG_APP, "构造音频采集:%o", ret);
|
OH_LOG_INFO(LOG_APP, "构造音频采集:%o", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
acgist::AudioCapturer::~AudioCapturer() {
|
acgist::AudioCapturer::~AudioCapturer() {
|
||||||
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Destroy(builder);
|
OH_AudioStream_Result ret = OH_AudioStreamBuilder_Destroy(this->builder);
|
||||||
// TODO: 是否需要delete
|
this->builder = nullptr;
|
||||||
builder = nullptr;
|
|
||||||
OH_LOG_INFO(LOG_APP, "释放音频采集:%o", ret);
|
OH_LOG_INFO(LOG_APP, "释放音频采集:%o", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acgist::AudioCapturer::start() {
|
bool acgist::AudioCapturer::start() {
|
||||||
// 配置采集参数
|
// 配置采集参数
|
||||||
OH_AudioStreamBuilder_SetSamplingRate(builder, samplingRate);
|
OH_AudioStreamBuilder_SetSamplingRate(this->builder, samplingRate);
|
||||||
OH_AudioStreamBuilder_SetChannelCount(builder, channelCount);
|
OH_AudioStreamBuilder_SetChannelCount(this->builder, channelCount);
|
||||||
OH_AudioStreamBuilder_SetLatencyMode(builder, latencyMode);
|
OH_AudioStreamBuilder_SetLatencyMode(this->builder, latencyMode);
|
||||||
OH_AudioStreamBuilder_SetSampleFormat(builder, sampleFormat);
|
OH_AudioStreamBuilder_SetSampleFormat(this->builder, sampleFormat);
|
||||||
OH_LOG_DEBUG(LOG_APP, "配置音频格式:%d %d %o %o", samplingRate, channelCount, latencyMode, sampleFormat);
|
OH_LOG_DEBUG(LOG_APP, "配置音频格式:%d %d %o %o", samplingRate, channelCount, latencyMode, sampleFormat);
|
||||||
// 设置回调函数
|
// 设置回调函数
|
||||||
OH_AudioCapturer_Callbacks callbacks;
|
OH_AudioCapturer_Callbacks callbacks;
|
||||||
@@ -43,24 +42,24 @@ bool acgist::AudioCapturer::start() {
|
|||||||
callbacks.OH_AudioCapturer_OnReadData = OnReadData;
|
callbacks.OH_AudioCapturer_OnReadData = OnReadData;
|
||||||
callbacks.OH_AudioCapturer_OnStreamEvent = OnStreamEvent;
|
callbacks.OH_AudioCapturer_OnStreamEvent = OnStreamEvent;
|
||||||
callbacks.OH_AudioCapturer_OnInterruptEvent = OnInterruptEvent;
|
callbacks.OH_AudioCapturer_OnInterruptEvent = OnInterruptEvent;
|
||||||
OH_AudioStream_Result ret = OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, this);
|
OH_AudioStream_Result ret = OH_AudioStreamBuilder_SetCapturerCallback(this->builder, callbacks, this);
|
||||||
OH_LOG_DEBUG(LOG_APP, "设置回调函数:%o", ret);
|
OH_LOG_DEBUG(LOG_APP, "设置回调函数:%o", ret);
|
||||||
// 构造音频采集器
|
// 构造音频采集器
|
||||||
ret = OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);
|
ret = OH_AudioStreamBuilder_GenerateCapturer(this->builder, &this->audioCapturer);
|
||||||
OH_LOG_DEBUG(LOG_APP, "构造音频采集器:%o", ret);
|
OH_LOG_DEBUG(LOG_APP, "构造音频采集器:%o", ret);
|
||||||
// 开始录制
|
// 开始录制
|
||||||
ret = OH_AudioCapturer_Start(audioCapturer);
|
ret = OH_AudioCapturer_Start(this->audioCapturer);
|
||||||
OH_LOG_DEBUG(LOG_APP, "开始录制:%o", ret);
|
OH_LOG_DEBUG(LOG_APP, "开始录制:%o", ret);
|
||||||
return ret == OH_AudioStream_Result::AUDIOSTREAM_SUCCESS;
|
return ret == OH_AudioStream_Result::AUDIOSTREAM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acgist::AudioCapturer::stop() {
|
bool acgist::AudioCapturer::stop() {
|
||||||
// 停止录制
|
// 停止录制
|
||||||
OH_AudioStream_Result ret = OH_AudioCapturer_Stop(audioCapturer);
|
OH_AudioStream_Result ret = OH_AudioCapturer_Stop(this->audioCapturer);
|
||||||
OH_LOG_DEBUG(LOG_APP, "停止录制:%o", ret);
|
OH_LOG_DEBUG(LOG_APP, "停止录制:%o", ret);
|
||||||
// 释放音频采集器
|
// 释放音频采集器
|
||||||
ret = OH_AudioCapturer_Release(audioCapturer);
|
ret = OH_AudioCapturer_Release(this->audioCapturer);
|
||||||
audioCapturer = nullptr;
|
this->audioCapturer = nullptr;
|
||||||
OH_LOG_DEBUG(LOG_APP, "释放音频采集器:%o", ret);
|
OH_LOG_DEBUG(LOG_APP, "释放音频采集器:%o", ret);
|
||||||
return ret == OH_AudioStream_Result::AUDIOSTREAM_SUCCESS;
|
return ret == OH_AudioStream_Result::AUDIOSTREAM_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -73,11 +72,7 @@ static int32_t OnError(OH_AudioCapturer* capturer, void* userData, OH_AudioStrea
|
|||||||
static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buffer, int32_t length) {
|
static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buffer, int32_t length) {
|
||||||
acgist::AudioCapturer* audioCapturer = (acgist::AudioCapturer*) userData;
|
acgist::AudioCapturer* audioCapturer = (acgist::AudioCapturer*) userData;
|
||||||
int64_t timeMillis = rtc::TimeMillis();
|
int64_t timeMillis = rtc::TimeMillis();
|
||||||
for (
|
for (auto iterator = audioCapturer->map.begin(); iterator != audioCapturer->map.end(); ++iterator) {
|
||||||
auto iterator = audioCapturer->map.begin();
|
|
||||||
iterator != audioCapturer->map.end();
|
|
||||||
++iterator
|
|
||||||
) {
|
|
||||||
iterator->second->OnData(buffer, 16, samplingRate, channelCount, sizeof(buffer) / 2, timeMillis);
|
iterator->second->OnData(buffer, 16, samplingRate, channelCount, sizeof(buffer) / 2, timeMillis);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#include "../include/Capturer.hpp"
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ bool acgist::MediaManager::startAudioCapture() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool acgist::MediaManager::startVideoCapture() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> acgist::MediaManager::getAudioTrack() {
|
rtc::scoped_refptr<webrtc::AudioTrackInterface> acgist::MediaManager::getAudioTrack() {
|
||||||
cricket::AudioOptions options;
|
cricket::AudioOptions options;
|
||||||
options.highpass_filter = true;
|
options.highpass_filter = true;
|
||||||
|
|||||||
@@ -1,8 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-camera-kit/camera_8h.md
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-camera-kit/video__output_8h.md
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-camera-kit/camera__manager_8h.md
|
||||||
|
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-camera-kit/capture__session_8h.md
|
||||||
|
*/
|
||||||
#include "../include/Capturer.hpp"
|
#include "../include/Capturer.hpp"
|
||||||
|
|
||||||
#include "hilog/log.h"
|
#include "hilog/log.h"
|
||||||
|
|
||||||
#include "ohcamera/camera_input.h"
|
#include "ohcamera/camera_input.h"
|
||||||
#include "ohcamera/camera_manager.h"
|
#include "ohcamera/camera_manager.h"
|
||||||
#include "ohcamera/capture_session.h"
|
#include "ohcamera/capture_session.h"
|
||||||
|
|
||||||
|
static void onError(Camera_VideoOutput* videoOutput, Camera_ErrorCode errorCode);
|
||||||
|
static void onFrameEnd(Camera_VideoOutput* videoOutput, int32_t frameCount);
|
||||||
|
static void onFrameStart(Camera_VideoOutput* videoOutput);
|
||||||
|
|
||||||
|
acgist::VideoCapturer::VideoCapturer() {
|
||||||
|
Camera_ErrorCode ret = OH_Camera_GetCameraManager(&this->cameraManager);
|
||||||
|
OH_LOG_INFO(LOG_APP, "构造摄像头管理器:%o", ret);
|
||||||
|
ret = OH_CameraManager_GetSupportedCameras(this->cameraManager, &this->cameraDevice, &this->size);
|
||||||
|
OH_LOG_INFO(LOG_APP, "摄像头设备列表:%o %d", ret, size);
|
||||||
|
ret = OH_CameraManager_GetSupportedCameraOutputCapability(this->cameraManager, &this->cameraDevice[this->cameraIndex], &this->cameraOutputCapability);
|
||||||
|
OH_LOG_INFO(LOG_APP, "摄像头输出功能:%o %d %d", ret, this->cameraIndex, this->cameraOutputCapability->videoProfilesSize);
|
||||||
|
// 二次处理:createImageReceiver/getReceivingSurfaceId
|
||||||
|
// ret = OH_CameraManager_CreateVideoOutput(this->cameraManager, this->cameraOutputCapability->videoProfiles[0],
|
||||||
|
// this->nativeWindow, &this->cameraVideoOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
acgist::VideoCapturer::~VideoCapturer() {
|
||||||
|
Camera_ErrorCode ret = OH_VideoOutput_Release(this->cameraVideoOutput);
|
||||||
|
this->cameraVideoOutput = nullptr;
|
||||||
|
OH_LOG_INFO(LOG_APP, "释放摄像头视频输出:%o", ret);
|
||||||
|
ret = OH_CameraManager_DeleteSupportedCameraOutputCapability(this->cameraManager, this->cameraOutputCapability);
|
||||||
|
this->cameraOutputCapability = nullptr;
|
||||||
|
OH_LOG_INFO(LOG_APP, "释放摄像头输出能力:%o", ret);
|
||||||
|
ret = OH_CameraManager_DeleteSupportedCameras(this->cameraManager, this->cameraDevice, this->size);
|
||||||
|
this->cameraDevice = nullptr;
|
||||||
|
OH_LOG_INFO(LOG_APP, "释放摄像头设备列表:%o", ret);
|
||||||
|
ret = OH_Camera_DeleteCameraManager(this->cameraManager);
|
||||||
|
this->cameraManager = nullptr;
|
||||||
|
OH_LOG_INFO(LOG_APP, "释放摄像头管理器:%o", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acgist::VideoCapturer::start() {
|
||||||
|
Camera_ErrorCode ret = OH_VideoOutput_Start(this->cameraVideoOutput);
|
||||||
|
OH_LOG_INFO(LOG_APP, "开始视频捕获:%o", ret);
|
||||||
|
VideoOutput_Callbacks callbacks;
|
||||||
|
callbacks.onError = onError;
|
||||||
|
callbacks.onFrameEnd = onFrameEnd;
|
||||||
|
callbacks.onFrameStart = onFrameStart;
|
||||||
|
ret = OH_VideoOutput_RegisterCallback(this->cameraVideoOutput, &callbacks);
|
||||||
|
OH_LOG_INFO(LOG_APP, "视频捕获回调:%o", ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acgist::VideoCapturer::stop() {
|
||||||
|
Camera_ErrorCode ret = OH_VideoOutput_Stop(this->cameraVideoOutput);
|
||||||
|
OH_LOG_INFO(LOG_APP, "结束视频捕获:%o", ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onError(Camera_VideoOutput* videoOutput, Camera_ErrorCode errorCode) {
|
||||||
|
OH_LOG_WARN(LOG_APP, "视频捕获数据帧失败:%d", errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onFrameEnd(Camera_VideoOutput* videoOutput, int32_t frameCount) {
|
||||||
|
OH_LOG_DEBUG(LOG_APP, "结束视频捕获数据帧");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onFrameStart(Camera_VideoOutput* videoOutput) {
|
||||||
|
OH_LOG_DEBUG(LOG_APP, "开始视频捕获数据帧");
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
#include "../include/Capturer.hpp"
|
||||||
|
|
||||||
|
#include "hilog/log.h"
|
||||||
|
|
||||||
|
#include "rtc_base/time_utils.h"
|
||||||
|
|
||||||
|
#include "api/video/nv12_buffer.h"
|
||||||
|
#include "api/video/i420_buffer.h"
|
||||||
|
|
||||||
|
#include <multimedia/player_framework/native_avbuffer.h>
|
||||||
|
#include <multimedia/player_framework/native_avformat.h>
|
||||||
|
#include <multimedia/player_framework/native_avcodec_base.h>
|
||||||
|
#include <multimedia/player_framework/native_avcapability.h>
|
||||||
|
|
||||||
|
static uint32_t width = 720;
|
||||||
|
static uint32_t height = 480;
|
||||||
|
static uint64_t bitrate = 3'000'000L;
|
||||||
|
static double frameRate = 30.0;
|
||||||
|
|
||||||
|
static void OnError(OH_AVCodec* codec, int32_t errorCode, void* userData);
|
||||||
|
static void OnStreamChanged(OH_AVCodec* codec, OH_AVFormat* format, void* userData);
|
||||||
|
static void OnNeedInputBuffer(OH_AVCodec* codec, uint32_t index, OH_AVBuffer* buffer, void* userData);
|
||||||
|
static void OnNewOutputBuffer(OH_AVCodec* codec, uint32_t index, OH_AVBuffer* buffer, void* userData);
|
||||||
|
|
||||||
|
acgist::VideoEncoder::VideoEncoder() {
|
||||||
|
OH_AVCapability* capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
|
||||||
|
const char* codecName = OH_AVCapability_GetName(capability);
|
||||||
|
this->avCodec = OH_VideoEncoder_CreateByName(codecName);
|
||||||
|
OH_LOG_INFO(LOG_APP, "视频编码格式:%s", codecName);
|
||||||
|
// 注册回调
|
||||||
|
OH_AVCodecCallback callback = { &OnError, &OnStreamChanged, &OnNeedInputBuffer, &OnNewOutputBuffer };
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_RegisterCallback(this->avCodec, callback, this);
|
||||||
|
OH_LOG_INFO(LOG_APP, "注册编码回调:%o", ret);
|
||||||
|
// 配置编码参数:https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/video-encoding.md
|
||||||
|
OH_AVFormat* format = OH_AVFormat_Create();
|
||||||
|
// 配置视频帧宽度(必须)
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, width);
|
||||||
|
// 配置视频帧高度(必须)
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, height);
|
||||||
|
// 配置视频颜色格式(必须)
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_YUVI420);
|
||||||
|
// OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
|
||||||
|
// 配置视频帧速率
|
||||||
|
OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
|
||||||
|
// 配置视频YUV值范围标志
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, false);
|
||||||
|
// 配置视频原色
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709));
|
||||||
|
// 配置传输特性
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709));
|
||||||
|
// 配置最大矩阵系数
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY));
|
||||||
|
// 配置关键帧的间隔(单位为:毫秒)
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, 5000);
|
||||||
|
// 配置编码Profile
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE));
|
||||||
|
// 配置编码比特率模式
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR));
|
||||||
|
// 配置比特率
|
||||||
|
OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitrate);
|
||||||
|
// 配置所需的编码质量:只有在恒定质量模式下配置的编码器才支持此配置
|
||||||
|
OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, 0);
|
||||||
|
ret = OH_VideoEncoder_Configure(this->avCodec, format);
|
||||||
|
OH_AVFormat_Destroy(format);
|
||||||
|
OH_LOG_INFO(LOG_APP, "配置编码参数:%o %d %d %f %ld", ret, width, height, frameRate, bitrate);
|
||||||
|
ret = OH_VideoEncoder_Prepare(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "视频编码准备就绪:%o", ret);
|
||||||
|
ret = OH_VideoEncoder_GetSurface(this->avCodec, &this->nativeWindow);
|
||||||
|
OH_LOG_INFO(LOG_APP, "配置surface:%o", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
acgist::VideoEncoder::~VideoEncoder() {
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_Destroy(this->avCodec);
|
||||||
|
this->avCodec = nullptr;
|
||||||
|
OH_LOG_INFO(LOG_APP, "释放视频编码器:%o", ret);
|
||||||
|
// TODO: delete nativeWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
void acgist::VideoEncoder::restart() {
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_Flush(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "清空编码队列:%o", ret);
|
||||||
|
ret = OH_VideoEncoder_Start(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "开始视频编码:%o", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acgist::VideoEncoder::reset(OH_AVFormat* format) {
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_Reset(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "重置视频编码:%o", ret);
|
||||||
|
ret = OH_VideoEncoder_Configure(this->avCodec, format);
|
||||||
|
OH_LOG_INFO(LOG_APP, "配置视频编码:%o", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acgist::VideoEncoder::resetIntConfig(const char* key, int32_t value) {
|
||||||
|
OH_AVFormat* format = OH_AVFormat_Create();
|
||||||
|
OH_AVFormat_SetIntValue(format, key, value);
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_SetParameter(this->avCodec, format);
|
||||||
|
OH_LOG_INFO(LOG_APP, "动态配置视频编码:%o %s %d", ret, key, value);
|
||||||
|
OH_AVFormat_Destroy(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acgist::VideoEncoder::resetLongConfig(const char* key, int64_t value) {
|
||||||
|
OH_AVFormat* format = OH_AVFormat_Create();
|
||||||
|
OH_AVFormat_SetLongValue(format, key, value);
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_SetParameter(this->avCodec, format);
|
||||||
|
OH_LOG_INFO(LOG_APP, "动态配置视频编码:%o %s %ld", ret, key, value);
|
||||||
|
OH_AVFormat_Destroy(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acgist::VideoEncoder::resetDoubleConfig(const char* key, double value) {
|
||||||
|
OH_AVFormat* format = OH_AVFormat_Create();
|
||||||
|
OH_AVFormat_SetDoubleValue(format, key, value);
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_SetParameter(this->avCodec, format);
|
||||||
|
OH_LOG_INFO(LOG_APP, "动态配置视频编码:%o %s %f", ret, key, value);
|
||||||
|
OH_AVFormat_Destroy(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acgist::VideoEncoder::start() {
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_Start(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "开始视频编码:%o", ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool acgist::VideoEncoder::stop() {
|
||||||
|
OH_AVErrCode ret = OH_VideoEncoder_NotifyEndOfStream(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "通知视频编码结束:%o", ret);
|
||||||
|
ret = OH_VideoEncoder_Stop(this->avCodec);
|
||||||
|
OH_LOG_INFO(LOG_APP, "结束视频编码:%o", ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnError(OH_AVCodec* codec, int32_t errorCode, void* userData) {
|
||||||
|
OH_LOG_WARN(LOG_APP, "视频编码发送错误:%d", errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnStreamChanged(OH_AVCodec* codec, OH_AVFormat* format, void* userData) {
|
||||||
|
OH_LOG_DEBUG(LOG_APP, "视频编码配置变化");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnNeedInputBuffer(OH_AVCodec* codec, uint32_t index, OH_AVBuffer* buffer, void* userData) {
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnNewOutputBuffer(OH_AVCodec* codec, uint32_t index, OH_AVBuffer* buffer, void* userData) {
|
||||||
|
acgist::VideoCapturer* videoCapturer = (acgist::VideoCapturer*) userData;
|
||||||
|
// TODO: 全局是否性能更好
|
||||||
|
OH_AVCodecBufferAttr info;
|
||||||
|
OH_AVErrCode ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
|
||||||
|
char* data = reinterpret_cast<char*>(OH_AVBuffer_GetAddr(buffer));
|
||||||
|
// TODO: 解析
|
||||||
|
rtc::scoped_refptr<webrtc::I420Buffer> videoFrameBuffer = webrtc::I420Buffer::Copy(width, height, (uint8_t*)data, 0, (uint8_t*)data, 0, (uint8_t*)data, 0);
|
||||||
|
// webrtc::NV12Buffer::Create(width, height);
|
||||||
|
webrtc::VideoFrame::Builder builder;
|
||||||
|
webrtc::VideoFrame videoFrame = builder
|
||||||
|
.set_timestamp_ms(rtc::TimeMillis())
|
||||||
|
.set_video_frame_buffer(videoFrameBuffer)
|
||||||
|
.set_rotation(webrtc::VideoRotation::kVideoRotation_0)
|
||||||
|
.build();
|
||||||
|
for (auto iterator = videoCapturer->map.begin(); iterator != videoCapturer->map.end(); ++iterator) {
|
||||||
|
iterator->second->OnFrame(videoFrame);
|
||||||
|
}
|
||||||
|
// TODO: 释放webrtc
|
||||||
|
videoFrameBuffer->Release();
|
||||||
|
ret = OH_VideoEncoder_FreeOutputBuffer(codec, index);
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
export const mediaConsume : () => number;
|
export const shutdown : (json: string) => number;
|
||||||
export const mediaConsumerClose : () => number;
|
export const roomClose : (json: string) => number;
|
||||||
export const mediaConsumerPause : () => number;
|
export const roomEnter : (json: string) => number;
|
||||||
export const mediaConsumerResume: () => number;
|
export const roomExpel : (json: string) => number;
|
||||||
export const mediaProducerClose : () => number;
|
|
||||||
export const mediaProducerPause : () => number;
|
|
||||||
export const mediaProducerResume: () => number;
|
|
||||||
export const roomClientList : () => number;
|
|
||||||
export const roomClose : () => number;
|
|
||||||
export const roomEnter : () => number;
|
|
||||||
export const roomExpel : () => number;
|
|
||||||
export const roomInvite: (json: string) => number;
|
export const roomInvite: (json: string) => number;
|
||||||
export const roomLeave : () => number;
|
export const roomLeave : (json: string) => number;
|
||||||
export const shutdown : () => number;
|
export const roomClientList : (json: string) => number;
|
||||||
|
export const mediaConsume : (json: string) => number;
|
||||||
|
export const mediaConsumerClose : (json: string) => number;
|
||||||
|
export const mediaConsumerPause : (json: string) => number;
|
||||||
|
export const mediaConsumerResume: (json: string) => number;
|
||||||
|
export const mediaProducerClose : (json: string) => number;
|
||||||
|
export const mediaProducerPause : (json: string) => number;
|
||||||
|
export const mediaProducerResume: (json: string) => number;
|
||||||
export const registerSend : (callback: (signal: string, body: string) => void) => number;
|
export const registerSend : (callback: (signal: string, body: string) => void) => number;
|
||||||
export const registerRequest: (callback: (signal: string, body: string) => string) => number;
|
export const registerRequest: (callback: (signal: string, body: string) => Promise<string>) => number;
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ class TaoyaoSignal {
|
|||||||
"body" : body
|
"body" : body
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
|
hilog.debug(0x0000, "TaoyaoSignal", "发送消息:%o", message);
|
||||||
this.socket?.send(JSON.stringify(message));
|
this.socket?.send(JSON.stringify(message));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
hilog.error(0x0000, "TaoyaoSignal", "发送消息异常:%o", message, error);
|
hilog.error(0x0000, "TaoyaoSignal", "发送消息异常:%o", message, error);
|
||||||
@@ -206,6 +207,7 @@ class TaoyaoSignal {
|
|||||||
});
|
});
|
||||||
// 发送消息
|
// 发送消息
|
||||||
try {
|
try {
|
||||||
|
hilog.debug(0x0000, "TaoyaoSignal", "发送请求:%o", message);
|
||||||
this.socket?.send(JSON.stringify(message));
|
this.socket?.send(JSON.stringify(message));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
hilog.error(0x0000, "TaoyaoSignal", "发送消息异常:%o", message, error);
|
hilog.error(0x0000, "TaoyaoSignal", "发送消息异常:%o", message, error);
|
||||||
@@ -251,8 +253,8 @@ class TaoyaoSignal {
|
|||||||
this.send(signal, JSON.parse(body));
|
this.send(signal, JSON.parse(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeRequest(signal: string, body: string): string {
|
async nativeRequest(signal: string, body: string): Promise<string> {
|
||||||
const response = this.request(signal, JSON.parse(body));
|
const response = await this.request(signal, JSON.parse(body));
|
||||||
return JSON.stringify(response);
|
return JSON.stringify(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,42 +36,36 @@
|
|||||||
"requestPermissions": [
|
"requestPermissions": [
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.CAMERA",
|
"name": "ohos.permission.CAMERA",
|
||||||
"reason": "视频",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.INTERNET",
|
"name": "ohos.permission.INTERNET",
|
||||||
"reason": "网络",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.MICROPHONE",
|
"name": "ohos.permission.MICROPHONE",
|
||||||
"reason": "音频",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.READ_MEDIA",
|
"name": "ohos.permission.READ_MEDIA",
|
||||||
"reason": "录制文件",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.WRITE_MEDIA",
|
"name": "ohos.permission.WRITE_MEDIA",
|
||||||
"reason": "录制文件",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ohos.permission.MEDIA_LOCATION",
|
"name": "ohos.permission.MEDIA_LOCATION",
|
||||||
"reason": "地理位置",
|
|
||||||
"usedScene": {
|
"usedScene": {
|
||||||
"when": "always"
|
"when": "always"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user