Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
61625f45
Commit
61625f45
authored
Apr 01, 2022
by
xgj
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
for webapi startsendrtp can send raw rtp
parent
d5b86138
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
206 行增加
和
18 行删除
+206
-18
server/WebApi.cpp
+5
-2
src/Common/MediaSource.cpp
+5
-5
src/Common/MediaSource.h
+3
-3
src/Common/MultiMediaSourceMuxer.cpp
+2
-2
src/Common/MultiMediaSourceMuxer.h
+1
-1
src/Rtp/RawEncoder.cpp
+102
-0
src/Rtp/RawEncoder.h
+59
-0
src/Rtp/RtpCache.cpp
+7
-0
src/Rtp/RtpCache.h
+11
-0
src/Rtp/RtpSender.cpp
+8
-4
src/Rtp/RtpSender.h
+3
-1
没有找到文件。
server/WebApi.cpp
查看文件 @
61625f45
...
...
@@ -1104,7 +1104,10 @@ void installWebApi() {
if
(
!
src
)
{
throw
ApiRetException
(
"该媒体流不存在"
,
API
::
OtherFailed
);
}
uint8_t
pt
=
allArgs
[
"pt"
].
empty
()
?
96
:
allArgs
[
"pt"
].
as
<
uint8_t
>
();
bool
use_ps
=
allArgs
[
"use_ps"
].
empty
()
?
true
:
allArgs
[
"use_ps"
].
as
<
bool
>
();
bool
only_audio
=
allArgs
[
"only_audio"
].
empty
()
?
true
:
allArgs
[
"only_audio"
].
as
<
bool
>
();
//src_port为空时,则随机本地端口
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
allArgs
[
"src_port"
],
[
val
,
headerOut
,
invoker
](
uint16_t
local_port
,
const
SockException
&
ex
)
mutable
{
if
(
ex
)
{
...
...
@@ -1113,7 +1116,7 @@ void installWebApi() {
}
val
[
"local_port"
]
=
local_port
;
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
}
,
pt
,
use_ps
,
only_audio
);
});
api_regist
(
"/index/api/stopSendRtp"
,[](
API_ARGS_MAP
){
...
...
src/Common/MediaSource.cpp
查看文件 @
61625f45
...
...
@@ -237,13 +237,13 @@ bool MediaSource::isRecording(Recorder::type type){
return
listener
->
isRecording
(
*
this
,
type
);
}
void
MediaSource
::
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
){
void
MediaSource
::
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
,
bool
use_ps
,
bool
only_audio
){
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
cb
(
0
,
SockException
(
Err_other
,
"尚未设置事件监听器"
));
return
;
}
return
listener
->
startSendRtp
(
*
this
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
return
listener
->
startSendRtp
(
*
this
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
,
use_ps
,
only_audio
);
}
bool
MediaSource
::
stopSendRtp
(
const
string
&
ssrc
)
{
...
...
@@ -720,12 +720,12 @@ vector<Track::Ptr> MediaSourceEventInterceptor::getMediaTracks(MediaSource &send
return
listener
->
getMediaTracks
(
sender
,
trackReady
);
}
void
MediaSourceEventInterceptor
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
){
void
MediaSourceEventInterceptor
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
,
bool
use_ps
,
bool
only_audio
){
auto
listener
=
_listener
.
lock
();
if
(
listener
)
{
listener
->
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
listener
->
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
,
pt
,
use_ps
,
only_audio
);
}
else
{
MediaSourceEvent
::
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
MediaSourceEvent
::
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
,
pt
,
use_ps
,
only_audio
);
}
}
...
...
src/Common/MediaSource.h
查看文件 @
61625f45
...
...
@@ -86,7 +86,7 @@ public:
// 获取所有track相关信息
virtual
std
::
vector
<
Track
::
Ptr
>
getMediaTracks
(
MediaSource
&
sender
,
bool
trackReady
=
true
)
const
{
return
std
::
vector
<
Track
::
Ptr
>
();
};
// 开始发送ps-rtp
virtual
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
)
{
cb
(
0
,
toolkit
::
SockException
(
toolkit
::
Err_other
,
"not implemented"
));};
virtual
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
=
96
,
bool
use_ps
=
true
,
bool
only_audio
=
true
)
{
cb
(
0
,
toolkit
::
SockException
(
toolkit
::
Err_other
,
"not implemented"
));};
// 停止发送ps-rtp
virtual
bool
stopSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
ssrc
)
{
return
false
;
}
...
...
@@ -117,7 +117,7 @@ public:
bool
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
std
::
string
&
custom_path
,
size_t
max_second
)
override
;
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
override
;
std
::
vector
<
Track
::
Ptr
>
getMediaTracks
(
MediaSource
&
sender
,
bool
trackReady
=
true
)
const
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
)
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
=
96
,
bool
use_ps
=
true
,
bool
only_audio
=
true
)
override
;
bool
stopSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
ssrc
)
override
;
private
:
...
...
@@ -269,7 +269,7 @@ public:
// 获取录制状态
bool
isRecording
(
Recorder
::
type
type
);
// 开始发送ps-rtp
void
startSendRtp
(
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
);
void
startSendRtp
(
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
=
96
,
bool
use_ps
=
true
,
bool
only_audio
=
true
);
// 停止发送ps-rtp
bool
stopSendRtp
(
const
std
::
string
&
ssrc
);
...
...
src/Common/MultiMediaSourceMuxer.cpp
查看文件 @
61625f45
...
...
@@ -213,9 +213,9 @@ bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type
}
}
void
MultiMediaSourceMuxer
::
startSendRtp
(
MediaSource
&
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
){
void
MultiMediaSourceMuxer
::
startSendRtp
(
MediaSource
&
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
uint16_t
local_port
,
const
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
,
bool
use_ps
,
bool
only_audio
){
#if defined(ENABLE_RTPPROXY)
RtpSender
::
Ptr
rtp_sender
=
std
::
make_shared
<
RtpSender
>
(
atoi
(
ssrc
.
data
()));
RtpSender
::
Ptr
rtp_sender
=
std
::
make_shared
<
RtpSender
>
(
atoi
(
ssrc
.
data
())
,
pt
,
use_ps
,
only_audio
);
weak_ptr
<
MultiMediaSourceMuxer
>
weak_self
=
shared_from_this
();
rtp_sender
->
startSend
(
dst_url
,
dst_port
,
is_udp
,
src_port
,
[
weak_self
,
rtp_sender
,
cb
,
ssrc
](
uint16_t
local_port
,
const
SockException
&
ex
)
{
cb
(
local_port
,
ex
);
...
...
src/Common/MultiMediaSourceMuxer.h
查看文件 @
61625f45
...
...
@@ -134,7 +134,7 @@ public:
* @param is_udp 是否为udp
* @param cb 启动成功或失败回调
*/
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
)
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
std
::
string
&
dst_url
,
uint16_t
dst_port
,
const
std
::
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
std
::
function
<
void
(
uint16_t
local_port
,
const
toolkit
::
SockException
&
ex
)
>
&
cb
,
uint8_t
pt
=
96
,
bool
use_ps
=
true
,
bool
only_audio
=
true
)
override
;
/**
* 停止ps-rtp发送
...
...
src/Rtp/RawEncoder.cpp
0 → 100644
查看文件 @
61625f45
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#if defined(ENABLE_RTPPROXY)
#include "RawEncoder.h"
#include "Extension/H264Rtp.h"
#include "Extension/AACRtp.h"
#include "Extension/H265Rtp.h"
#include "Extension/CommonRtp.h"
#include "Extension/G711Rtp.h"
#include "Rtsp/RtspMuxer.h"
using
namespace
toolkit
;
namespace
mediakit
{
RawEncoderImp
::
RawEncoderImp
(
uint32_t
ssrc
,
uint8_t
payload_type
,
bool
sendAudio
)
:
_ssrc
(
ssrc
),
_payload_type
(
payload_type
),
_sendAudio
(
sendAudio
)
{
}
RawEncoderImp
::~
RawEncoderImp
()
{
InfoL
<<
this
<<
" "
<<
printSSRC
(
_ssrc
);
}
bool
RawEncoderImp
::
addTrack
(
const
Track
::
Ptr
&
track
){
if
(
_sendAudio
&&
track
->
getTrackType
()
==
TrackType
::
TrackAudio
&&
!
_rtp_encoder
){
// audio
_rtp_encoder
=
createRtpEncoder
(
track
);
_rtp_encoder
->
setRtpRing
(
std
::
make_shared
<
RtpRing
::
RingType
>
());
_rtp_encoder
->
getRtpRing
()
->
setDelegate
(
std
::
make_shared
<
RingDelegateHelper
>
([
this
](
RtpPacket
::
Ptr
rtp
,
bool
is_key
){
onRTP
(
std
::
move
(
rtp
));
}));
return
true
;
}
if
(
!
_sendAudio
&&
track
->
getTrackType
()
==
TrackType
::
TrackVideo
&&
!
_rtp_encoder
){
_rtp_encoder
=
createRtpEncoder
(
track
);
_rtp_encoder
->
setRtpRing
(
std
::
make_shared
<
RtpRing
::
RingType
>
());
_rtp_encoder
->
getRtpRing
()
->
setDelegate
(
std
::
make_shared
<
RingDelegateHelper
>
([
this
](
RtpPacket
::
Ptr
rtp
,
bool
is_key
){
onRTP
(
std
::
move
(
rtp
));
}));
return
true
;
}
return
true
;
}
void
RawEncoderImp
::
resetTracks
(){
return
;
}
bool
RawEncoderImp
::
inputFrame
(
const
Frame
::
Ptr
&
frame
){
if
(
frame
->
getTrackType
()
==
TrackType
::
TrackAudio
&&
_sendAudio
&&
_rtp_encoder
){
_rtp_encoder
->
inputFrame
(
frame
);
}
if
(
frame
->
getTrackType
()
==
TrackType
::
TrackVideo
&&
!
_sendAudio
&&
_rtp_encoder
){
_rtp_encoder
->
inputFrame
(
frame
);
}
return
true
;
}
RtpCodec
::
Ptr
RawEncoderImp
::
createRtpEncoder
(
const
Track
::
Ptr
&
track
){
GET_CONFIG
(
uint32_t
,
audio_mtu
,
Rtp
::
kAudioMtuSize
);
GET_CONFIG
(
uint32_t
,
video_mtu
,
Rtp
::
kVideoMtuSize
);
auto
codec_id
=
track
->
getCodecId
();
uint32_t
sample_rate
=
90000
;
int
channels
=
1
;
auto
mtu
=
(
track
->
getTrackType
()
==
TrackVideo
?
video_mtu
:
audio_mtu
);
if
(
track
->
getTrackType
()
==
TrackType
::
TrackAudio
){
AudioTrack
::
Ptr
audioTrack
=
std
::
dynamic_pointer_cast
<
AudioTrack
>
(
track
);
sample_rate
=
audioTrack
->
getAudioSampleRate
();
channels
=
audioTrack
->
getAudioChannel
();
}
switch
(
codec_id
){
case
CodecH264
:
return
std
::
make_shared
<
H264RtpEncoder
>
(
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
);
case
CodecH265
:
return
std
::
make_shared
<
H265RtpEncoder
>
(
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
);
case
CodecAAC
:
return
std
::
make_shared
<
AACRtpEncoder
>
(
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
);
case
CodecL16
:
case
CodecOpus
:
return
std
::
make_shared
<
CommonRtpEncoder
>
(
codec_id
,
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
);
case
CodecG711A
:
case
CodecG711U
:
{
if
(
_payload_type
==
Rtsp
::
PT_PCMA
||
_payload_type
==
Rtsp
::
PT_PCMU
)
{
return
std
::
make_shared
<
G711RtpEncoder
>
(
codec_id
,
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
,
channels
);
}
return
std
::
make_shared
<
CommonRtpEncoder
>
(
codec_id
,
_ssrc
,
mtu
,
sample_rate
,
_payload_type
,
0
);
}
default
:
WarnL
<<
"暂不支持该CodecId:"
<<
codec_id
;
return
nullptr
;
}
}
}
//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)
src/Rtp/RawEncoder.h
0 → 100644
查看文件 @
61625f45
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_RAWENCODER_H
#define ZLMEDIAKIT_RAWENCODER_H
#if defined(ENABLE_RTPPROXY)
#include "Common/MediaSink.h"
#include "Common/Stamp.h"
#include "Extension/CommonRtp.h"
namespace
mediakit
{
class
RawEncoderImp
:
public
MediaSinkInterface
{
public
:
RawEncoderImp
(
uint32_t
ssrc
,
uint8_t
payload_type
=
96
,
bool
sendAudio
=
true
);
~
RawEncoderImp
()
override
;
/**
* 添加音视频轨道
*/
bool
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
/**
* 重置音视频轨道
*/
void
resetTracks
()
override
;
/**
* 输入帧数据
*/
bool
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
protected
:
//rtp打包后回调
virtual
void
onRTP
(
toolkit
::
Buffer
::
Ptr
rtp
)
=
0
;
private
:
RtpCodec
::
Ptr
createRtpEncoder
(
const
Track
::
Ptr
&
track
);
uint32_t
_ssrc
;
uint8_t
_payload_type
;
bool
_sendAudio
;
RtpCodec
::
Ptr
_rtp_encoder
;
};
}
//namespace mediakit
#endif //ENABLE_RTPPROXY
#endif //ZLMEDIAKIT_RAWENCODER_H
src/Rtp/RtpCache.cpp
查看文件 @
61625f45
...
...
@@ -34,6 +34,12 @@ void RtpCachePS::onRTP(Buffer::Ptr buffer) {
input
(
stamp
,
std
::
move
(
buffer
));
}
void
RtpCacheRaw
::
onRTP
(
Buffer
::
Ptr
buffer
)
{
auto
rtp
=
std
::
static_pointer_cast
<
RtpPacket
>
(
buffer
);
auto
stamp
=
rtp
->
getStampMS
();
input
(
stamp
,
std
::
move
(
buffer
));
}
}
//namespace mediakit
#endif//#if defined(ENABLE_RTPPROXY)
\ No newline at end of file
src/Rtp/RtpCache.h
查看文件 @
61625f45
...
...
@@ -14,6 +14,7 @@
#if defined(ENABLE_RTPPROXY)
#include "PSEncoder.h"
#include "RawEncoder.h"
#include "Extension/CommonRtp.h"
namespace
mediakit
{
...
...
@@ -47,6 +48,16 @@ protected:
void
onRTP
(
toolkit
::
Buffer
::
Ptr
rtp
)
override
;
};
class
RtpCacheRaw
:
public
RtpCache
,
public
RawEncoderImp
{
public
:
RtpCacheRaw
(
onFlushed
cb
,
uint32_t
ssrc
,
uint8_t
payload_type
=
96
,
bool
sendAudio
=
true
)
:
RtpCache
(
std
::
move
(
cb
)),
RawEncoderImp
(
ssrc
,
payload_type
,
sendAudio
)
{};
~
RtpCacheRaw
()
override
=
default
;
protected
:
void
onRTP
(
toolkit
::
Buffer
::
Ptr
rtp
)
override
;
};
}
//namespace mediakit
#endif//ENABLE_RTPPROXY
#endif //ZLMEDIAKIT_RTPCACHE_H
src/Rtp/RtpSender.cpp
查看文件 @
61625f45
...
...
@@ -19,11 +19,15 @@ using namespace toolkit;
namespace
mediakit
{
RtpSender
::
RtpSender
(
uint32_t
ssrc
,
uint8_t
payload_type
)
{
RtpSender
::
RtpSender
(
uint32_t
ssrc
,
uint8_t
payload_type
,
bool
use_ps
,
bool
only_audio
)
{
_poller
=
EventPollerPool
::
Instance
().
getPoller
();
_interface
=
std
::
make_shared
<
RtpCachePS
>
([
this
](
std
::
shared_ptr
<
List
<
Buffer
::
Ptr
>
>
list
)
{
onFlushRtpList
(
std
::
move
(
list
));
},
ssrc
,
payload_type
);
if
(
use_ps
)
{
_interface
=
std
::
make_shared
<
RtpCachePS
>
(
[
this
](
std
::
shared_ptr
<
List
<
Buffer
::
Ptr
>>
list
)
{
onFlushRtpList
(
std
::
move
(
list
));
},
ssrc
,
payload_type
);
}
else
{
_interface
=
std
::
make_shared
<
RtpCacheRaw
>
(
[
this
](
std
::
shared_ptr
<
List
<
Buffer
::
Ptr
>>
list
)
{
onFlushRtpList
(
std
::
move
(
list
));
},
ssrc
,
payload_type
,
only_audio
);
}
}
RtpSender
::~
RtpSender
()
{}
...
...
src/Rtp/RtpSender.h
查看文件 @
61625f45
...
...
@@ -27,8 +27,10 @@ public:
* 构造函数,创建GB28181 RTP发送客户端
* @param ssrc rtp的ssrc
* @param payload_type 国标中ps-rtp的pt一般为96
* @param use_ps 是否打包为PS然后发送
* @param only_audio use_ps 为false 时有效,指定发送音频还是视频
*/
RtpSender
(
uint32_t
ssrc
,
uint8_t
payload_type
=
96
);
RtpSender
(
uint32_t
ssrc
,
uint8_t
payload_type
=
96
,
bool
use_ps
=
true
,
bool
only_audio
=
true
);
/**
* 开始发送ps-rtp包
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论