mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
rtsp/rtmp/mp4支持opus并整理代码
This commit is contained in:
parent
b4a3b608ab
commit
a22f97c777
@ -54,7 +54,7 @@ API_EXPORT void API_CALL mk_media_init_video(mk_media ctx, int track_id, int wid
|
|||||||
/**
|
/**
|
||||||
* 添加音频轨道
|
* 添加音频轨道
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param track_id 2:CodecAAC/3:CodecG711A/4:CodecG711U
|
* @param track_id 2:CodecAAC/3:CodecG711A/4:CodecG711U/5:OPUS
|
||||||
* @param channel 通道数
|
* @param channel 通道数
|
||||||
* @param sample_bit 采样位数,只支持16
|
* @param sample_bit 采样位数,只支持16
|
||||||
* @param sample_rate 采样率
|
* @param sample_rate 采样率
|
||||||
@ -95,7 +95,7 @@ API_EXPORT void API_CALL mk_media_input_h265(mk_media ctx, void *data, int len,
|
|||||||
* @param data 不包含adts头的单帧AAC数据
|
* @param data 不包含adts头的单帧AAC数据
|
||||||
* @param len 单帧AAC数据字节数
|
* @param len 单帧AAC数据字节数
|
||||||
* @param dts 时间戳,毫秒
|
* @param dts 时间戳,毫秒
|
||||||
* @param adts adts头
|
* @param adts adts头,可以为null
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, uint32_t dts, void *adts);
|
API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, uint32_t dts, void *adts);
|
||||||
|
|
||||||
@ -109,13 +109,13 @@ API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, u
|
|||||||
API_EXPORT void API_CALL mk_media_input_pcm(mk_media ctx, void *data, int len, uint32_t pts);
|
API_EXPORT void API_CALL mk_media_input_pcm(mk_media ctx, void *data, int len, uint32_t pts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入单帧G711音频
|
* 输入单帧OPUS/G711音频帧
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param data 单帧G711数据
|
* @param data 单帧音频数据
|
||||||
* @param len 单帧G711数据字节数
|
* @param len 单帧音频数据字节数
|
||||||
* @param dts 时间戳,毫秒
|
* @param dts 时间戳,毫秒
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_media_input_g711(mk_media ctx, void* data, int len, uint32_t dts);
|
API_EXPORT void API_CALL mk_media_input_audio(mk_media ctx, void* data, int len, uint32_t dts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediaSource.close()回调事件
|
* MediaSource.close()回调事件
|
||||||
|
@ -31,7 +31,7 @@ typedef void(API_CALL *on_mk_play_event)(void *user_data,int err_code,const char
|
|||||||
* 收到音视频数据回调
|
* 收到音视频数据回调
|
||||||
* @param user_data 用户数据指针
|
* @param user_data 用户数据指针
|
||||||
* @param track_type 0:视频,1:音频
|
* @param track_type 0:视频,1:音频
|
||||||
* @param codec_id 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
* @param codec_id 0:H264,1:H265,2:AAC 3.G711A 4.G711U 5.OPUS
|
||||||
* @param data 数据指针
|
* @param data 数据指针
|
||||||
* @param len 数据长度
|
* @param len 数据长度
|
||||||
* @param dts 解码时间戳,单位毫秒
|
* @param dts 解码时间戳,单位毫秒
|
||||||
|
@ -188,8 +188,8 @@ API_EXPORT void API_CALL mk_media_input_pcm(mk_media ctx, void *data , int len,
|
|||||||
#endif //ENABLE_FAAC
|
#endif //ENABLE_FAAC
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_input_g711(mk_media ctx, void* data, int len, uint32_t dts){
|
API_EXPORT void API_CALL mk_media_input_audio(mk_media ctx, void* data, int len, uint32_t dts){
|
||||||
assert(ctx && data && len > 0);
|
assert(ctx && data && len > 0);
|
||||||
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
||||||
(*obj)->getChannel()->inputG711((char*)data, len, dts);
|
(*obj)->getChannel()->inputAudio((char*)data, len, dts);
|
||||||
}
|
}
|
||||||
|
@ -12,22 +12,16 @@
|
|||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
#include "Util/base64.h"
|
#include "Util/base64.h"
|
||||||
#include "Extension/AAC.h"
|
#include "Extension/AAC.h"
|
||||||
|
#include "Extension/Opus.h"
|
||||||
#include "Extension/G711.h"
|
#include "Extension/G711.h"
|
||||||
#include "Extension/H264.h"
|
#include "Extension/H264.h"
|
||||||
#include "Extension/H265.h"
|
#include "Extension/H265.h"
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
DevChannel::DevChannel(const string &vhost,
|
DevChannel::DevChannel(const string &vhost, const string &app, const string &stream_id, float duration,
|
||||||
const string &app,
|
bool enable_rtsp, bool enable_rtmp, bool enable_hls, bool enable_mp4) :
|
||||||
const string &stream_id,
|
|
||||||
float duration,
|
|
||||||
bool enable_rtsp,
|
|
||||||
bool enable_rtmp,
|
|
||||||
bool enable_hls,
|
|
||||||
bool enable_mp4) :
|
|
||||||
MultiMediaSourceMuxer(vhost, app, stream_id, duration, enable_rtsp, enable_rtmp, enable_hls, enable_mp4) {}
|
MultiMediaSourceMuxer(vhost, app, stream_id, duration, enable_rtsp, enable_rtmp, enable_hls, enable_mp4) {}
|
||||||
|
|
||||||
DevChannel::~DevChannel() {}
|
DevChannel::~DevChannel() {}
|
||||||
@ -109,11 +103,12 @@ void DevChannel::inputH265(const char *data, int len, uint32_t dts, uint32_t pts
|
|||||||
inputFrame(frame);
|
inputFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AACFrameCacheAble : public AACFrameNoCacheAble{
|
class FrameAutoDelete : public FrameFromPtr{
|
||||||
public:
|
public:
|
||||||
template <typename ... ARGS>
|
template <typename ... ARGS>
|
||||||
AACFrameCacheAble(ARGS && ...args) : AACFrameNoCacheAble(std::forward<ARGS>(args)...){};
|
FrameAutoDelete(ARGS && ...args) : FrameFromPtr(std::forward<ARGS>(args)...){}
|
||||||
virtual ~AACFrameCacheAble() {
|
|
||||||
|
~FrameAutoDelete() override {
|
||||||
delete [] _ptr;
|
delete [] _ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,26 +123,27 @@ void DevChannel::inputAAC(const char *data_without_adts, int len, uint32_t dts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (adts_header) {
|
if (adts_header) {
|
||||||
if(adts_header + 7 == data_without_adts){
|
if (adts_header + ADTS_HEADER_LEN == data_without_adts) {
|
||||||
//adts头和帧在一起
|
//adts头和帧在一起
|
||||||
inputFrame(std::make_shared<AACFrameNoCacheAble>((char *)data_without_adts - 7, len + 7, dts, 0, 7));
|
inputFrame(std::make_shared<FrameFromPtr>(_audio->codecId, (char *) data_without_adts - ADTS_HEADER_LEN, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN));
|
||||||
} else {
|
} else {
|
||||||
//adts头和帧不在一起
|
//adts头和帧不在一起
|
||||||
char *dataWithAdts = new char[len + 7];
|
char *data_with_adts = new char[len + ADTS_HEADER_LEN];
|
||||||
memcpy(dataWithAdts, adts_header, 7);
|
memcpy(data_with_adts, adts_header, ADTS_HEADER_LEN);
|
||||||
memcpy(dataWithAdts + 7 , data_without_adts , len);
|
memcpy(data_with_adts + ADTS_HEADER_LEN, data_without_adts, len);
|
||||||
inputFrame(std::make_shared<AACFrameCacheAble>(dataWithAdts, len + 7, dts, 0, 7));
|
inputFrame(std::make_shared<FrameAutoDelete>(_audio->codecId, data_with_adts, len + ADTS_HEADER_LEN, dts, 0, ADTS_HEADER_LEN));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//没有adts头
|
||||||
|
inputFrame(std::make_shared<FrameFromPtr>(_audio->codecId, (char *) data_without_adts, len, dts, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevChannel::inputG711(const char *data, int len, uint32_t dts){
|
void DevChannel::inputAudio(const char *data, int len, uint32_t dts){
|
||||||
if (dts == 0) {
|
if (dts == 0) {
|
||||||
dts = (uint32_t) _aTicker[1].elapsedTime();
|
dts = (uint32_t) _aTicker[1].elapsedTime();
|
||||||
}
|
}
|
||||||
auto frame = std::make_shared<G711FrameNoCacheAble>((char*)data, len, dts, 0);
|
inputFrame(std::make_shared<FrameFromPtr>(_audio->codecId, (char *) data, len, dts, 0));
|
||||||
frame->setCodec(_audio->codecId);
|
|
||||||
inputFrame(frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevChannel::initVideo(const VideoInfo &info) {
|
void DevChannel::initVideo(const VideoInfo &info) {
|
||||||
@ -165,6 +161,7 @@ void DevChannel::initAudio(const AudioInfo &info) {
|
|||||||
case CodecAAC : addTrack(std::make_shared<AACTrack>()); break;
|
case CodecAAC : addTrack(std::make_shared<AACTrack>()); break;
|
||||||
case CodecG711A :
|
case CodecG711A :
|
||||||
case CodecG711U : addTrack(std::make_shared<G711Track>(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); break;
|
case CodecG711U : addTrack(std::make_shared<G711Track>(info.codecId, info.iSampleRate, info.iChannel, info.iSampleBit)); break;
|
||||||
|
case CodecOpus : addTrack(std::make_shared<OpusTrack>()); break;
|
||||||
default: WarnL << "不支持该类型的音频编码类型:" << info.codecId; break;
|
default: WarnL << "不支持该类型的音频编码类型:" << info.codecId; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,9 @@
|
|||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
#include "Common/MultiMediaSourceMuxer.h"
|
#include "Common/MultiMediaSourceMuxer.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_FAAC
|
#ifdef ENABLE_FAAC
|
||||||
#include "Codec/AACEncoder.h"
|
#include "Codec/AACEncoder.h"
|
||||||
#endif //ENABLE_FAAC
|
#endif //ENABLE_FAAC
|
||||||
@ -55,16 +53,10 @@ class DevChannel : public MultiMediaSourceMuxer{
|
|||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<DevChannel> Ptr;
|
typedef std::shared_ptr<DevChannel> Ptr;
|
||||||
//fDuration<=0为直播,否则为点播
|
//fDuration<=0为直播,否则为点播
|
||||||
DevChannel(const string &vhost,
|
DevChannel(const string &vhost, const string &app, const string &stream_id, float duration = 0,
|
||||||
const string &app,
|
bool enable_rtsp = true, bool enable_rtmp = true, bool enable_hls = true, bool enable_mp4 = false);
|
||||||
const string &stream_id,
|
|
||||||
float duration = 0,
|
|
||||||
bool enable_rtsp = true,
|
|
||||||
bool enable_rtmp = true,
|
|
||||||
bool enable_hls = true,
|
|
||||||
bool enable_mp4 = false);
|
|
||||||
|
|
||||||
virtual ~DevChannel();
|
~DevChannel() override ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化视频Track
|
* 初始化视频Track
|
||||||
@ -108,12 +100,12 @@ public:
|
|||||||
void inputAAC(const char *data_without_adts, int len, uint32_t dts, const char *adts_header);
|
void inputAAC(const char *data_without_adts, int len, uint32_t dts, const char *adts_header);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* G711音频帧
|
* 输入OPUS/G711音频帧
|
||||||
* @param data 音频帧
|
* @param data 音频帧
|
||||||
* @param len 帧数据长度
|
* @param len 帧数据长度
|
||||||
* @param dts 时间戳,单位毫秒
|
* @param dts 时间戳,单位毫秒
|
||||||
*/
|
*/
|
||||||
void inputG711(const char* data, int len, uint32_t dts);
|
void inputAudio(const char *data, int len, uint32_t dts);
|
||||||
|
|
||||||
#ifdef ENABLE_X264
|
#ifdef ENABLE_X264
|
||||||
/**
|
/**
|
||||||
|
@ -21,41 +21,6 @@ string makeAacConfig(const uint8_t *hex, int length);
|
|||||||
int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size);
|
int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size);
|
||||||
bool parseAacConfig(const string &config, int &samplerate, int &channels);
|
bool parseAacConfig(const string &config, int &samplerate, int &channels);
|
||||||
|
|
||||||
/**
|
|
||||||
* aac帧,包含adts头
|
|
||||||
*/
|
|
||||||
class AACFrame : public FrameImp {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<AACFrame> Ptr;
|
|
||||||
AACFrame(){
|
|
||||||
_codecid = CodecAAC;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AACFrameNoCacheAble : public FrameFromPtr {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<AACFrameNoCacheAble> Ptr;
|
|
||||||
|
|
||||||
AACFrameNoCacheAble(char *ptr,uint32_t size,uint32_t dts,uint32_t pts = 0,int prefix_size = ADTS_HEADER_LEN){
|
|
||||||
_ptr = ptr;
|
|
||||||
_size = size;
|
|
||||||
_dts = dts;
|
|
||||||
_prefix_size = prefix_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return CodecAAC;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool keyFrame() const override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configFrame() const override{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aac音频通道
|
* aac音频通道
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,9 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) {
|
void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) {
|
||||||
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
|
auto frame = ResourcePoolHelper<FrameImp>::obtainObj();
|
||||||
|
frame->_codec_id = CodecAAC;
|
||||||
|
|
||||||
//生成adts头
|
//生成adts头
|
||||||
char adts_header[32] = {0};
|
char adts_header[32] = {0};
|
||||||
auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header));
|
auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header));
|
||||||
|
@ -19,7 +19,7 @@ namespace mediakit{
|
|||||||
/**
|
/**
|
||||||
* aac Rtmp转adts类
|
* aac Rtmp转adts类
|
||||||
*/
|
*/
|
||||||
class AACRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<AACFrame> {
|
class AACRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<FrameImp> {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<AACRtmpDecoder> Ptr;
|
typedef std::shared_ptr<AACRtmpDecoder> Ptr;
|
||||||
|
|
||||||
|
@ -67,19 +67,19 @@ AACRtpDecoder::AACRtpDecoder(const Track::Ptr &track) {
|
|||||||
} else {
|
} else {
|
||||||
_aac_cfg = aacTrack->getAacCfg();
|
_aac_cfg = aacTrack->getAacCfg();
|
||||||
}
|
}
|
||||||
_frame = obtainFrame();
|
obtainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
AACRtpDecoder::AACRtpDecoder() {
|
AACRtpDecoder::AACRtpDecoder() {
|
||||||
_frame = obtainFrame();
|
obtainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
AACFrame::Ptr AACRtpDecoder::obtainFrame() {
|
void AACRtpDecoder::obtainFrame() {
|
||||||
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
|
_frame = ResourcePoolHelper<FrameImp>::obtainObj();
|
||||||
frame->_prefix_size = 0;
|
_frame->_prefix_size = 0;
|
||||||
frame->_buffer.clear();
|
_frame->_buffer.clear();
|
||||||
return frame;
|
_frame->_codec_id = CodecAAC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
|
bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
|
||||||
@ -143,11 +143,7 @@ void AACRtpDecoder::flushData() {
|
|||||||
_frame->_prefix_size = size;
|
_frame->_prefix_size = size;
|
||||||
}
|
}
|
||||||
RtpCodec::inputFrame(_frame);
|
RtpCodec::inputFrame(_frame);
|
||||||
_frame = obtainFrame();
|
obtainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace mediakit{
|
|||||||
/**
|
/**
|
||||||
* aac rtp转adts类
|
* aac rtp转adts类
|
||||||
*/
|
*/
|
||||||
class AACRtpDecoder : public RtpCodec , public ResourcePoolHelper<AACFrame> {
|
class AACRtpDecoder : public RtpCodec , public ResourcePoolHelper<FrameImp> {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<AACRtpDecoder> Ptr;
|
typedef std::shared_ptr<AACRtpDecoder> Ptr;
|
||||||
|
|
||||||
@ -39,11 +39,11 @@ protected:
|
|||||||
AACRtpDecoder();
|
AACRtpDecoder();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AACFrame::Ptr obtainFrame();
|
void obtainFrame();
|
||||||
void flushData();
|
void flushData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AACFrame::Ptr _frame;
|
FrameImp::Ptr _frame;
|
||||||
string _aac_cfg;
|
string _aac_cfg;
|
||||||
uint32_t _last_dts = 0;
|
uint32_t _last_dts = 0;
|
||||||
};
|
};
|
||||||
|
67
src/Extension/CommonRtmp.cpp
Normal file
67
src/Extension/CommonRtmp.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CommonRtmp.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
CommonRtmpDecoder::CommonRtmpDecoder(CodecId codec) {
|
||||||
|
_codec = codec;
|
||||||
|
obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId CommonRtmpDecoder::getCodecId() const {
|
||||||
|
return _codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonRtmpDecoder::obtainFrame() {
|
||||||
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
|
_frame = ResourcePoolHelper<FrameImp>::obtainObj();
|
||||||
|
_frame->_buffer.clear();
|
||||||
|
_frame->_codec_id = _codec;
|
||||||
|
_frame->_prefix_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool) {
|
||||||
|
//拷贝负载
|
||||||
|
_frame->_buffer.assign(rtmp->strBuf.data() + 1, rtmp->strBuf.size() - 1);
|
||||||
|
_frame->_dts = rtmp->timeStamp;
|
||||||
|
//写入环形缓存
|
||||||
|
RtmpCodec::inputFrame(_frame);
|
||||||
|
//创建下一帧
|
||||||
|
obtainFrame();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CommonRtmpEncoder::CommonRtmpEncoder(const Track::Ptr &track) : CommonRtmpDecoder(track->getCodecId()) {
|
||||||
|
_audio_flv_flags = getAudioRtmpFlags(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
|
||||||
|
if (!_audio_flv_flags) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RtmpPacket::Ptr rtmp = ResourcePoolHelper<RtmpPacket>::obtainObj();
|
||||||
|
rtmp->strBuf.clear();
|
||||||
|
//header
|
||||||
|
rtmp->strBuf.push_back(_audio_flv_flags);
|
||||||
|
//data
|
||||||
|
rtmp->strBuf.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
|
rtmp->bodySize = rtmp->strBuf.size();
|
||||||
|
rtmp->chunkId = CHUNK_AUDIO;
|
||||||
|
rtmp->streamId = STREAM_MEDIA;
|
||||||
|
rtmp->timeStamp = frame->dts();
|
||||||
|
rtmp->typeId = MSG_AUDIO;
|
||||||
|
RtmpCodec::inputRtmp(rtmp, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
74
src/Extension/CommonRtmp.h
Normal file
74
src/Extension/CommonRtmp.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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_COMMONRTMP_H
|
||||||
|
#define ZLMEDIAKIT_COMMONRTMP_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Rtmp/RtmpCodec.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 rtmp解码类
|
||||||
|
*/
|
||||||
|
class CommonRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<FrameImp> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<CommonRtmpDecoder> Ptr;
|
||||||
|
|
||||||
|
~CommonRtmpDecoder() override {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param codec 编码id
|
||||||
|
*/
|
||||||
|
CommonRtmpDecoder(CodecId codec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回编码类型ID
|
||||||
|
*/
|
||||||
|
CodecId getCodecId() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入Rtmp并解码
|
||||||
|
* @param rtmp Rtmp数据包
|
||||||
|
* @param key_pos 此参数内部强制转换为false,请忽略之
|
||||||
|
*/
|
||||||
|
bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos = false) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void obtainFrame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CodecId _codec;
|
||||||
|
FrameImp::Ptr _frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 rtmp编码类
|
||||||
|
*/
|
||||||
|
class CommonRtmpEncoder : public CommonRtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<CommonRtmpEncoder> Ptr;
|
||||||
|
|
||||||
|
CommonRtmpEncoder(const Track::Ptr &track);
|
||||||
|
~CommonRtmpEncoder() override{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入帧数据
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _audio_flv_flags = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
#endif //ZLMEDIAKIT_COMMONRTMP_H
|
87
src/Extension/CommonRtp.cpp
Normal file
87
src/Extension/CommonRtp.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CommonRtp.h"
|
||||||
|
|
||||||
|
#define MAX_FRAME_SIZE 2 * 1024
|
||||||
|
|
||||||
|
CommonRtpDecoder::CommonRtpDecoder(CodecId codec){
|
||||||
|
_codec = codec;
|
||||||
|
obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId CommonRtpDecoder::getCodecId() const {
|
||||||
|
return _codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonRtpDecoder::obtainFrame() {
|
||||||
|
_frame = ResourcePoolHelper<FrameImp>::obtainObj();
|
||||||
|
_frame->_buffer.clear();
|
||||||
|
_frame->_prefix_size = 0;
|
||||||
|
_frame->_dts = 0;
|
||||||
|
_frame->_codec_id = _codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){
|
||||||
|
auto payload = rtp->data() + rtp->offset;
|
||||||
|
auto size = rtp->size() - rtp->offset;
|
||||||
|
if (size <= 0) {
|
||||||
|
//无实际负载
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_frame->_dts != rtp->timeStamp || _frame->_buffer.size() > MAX_FRAME_SIZE) {
|
||||||
|
//时间戳发生变化或者缓存超过MAX_FRAME_SIZE,则清空上帧数据
|
||||||
|
if (!_frame->_buffer.empty()) {
|
||||||
|
//有有效帧,则输出
|
||||||
|
RtpCodec::inputFrame(_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
//新的一帧数据
|
||||||
|
obtainFrame();
|
||||||
|
_frame->_dts = rtp->timeStamp;
|
||||||
|
_drop_flag = false;
|
||||||
|
} else if (_last_seq != 0 && _last_seq + (uint16_t) 1 != rtp->sequence) {
|
||||||
|
//时间戳未发生变化,但是seq却不连续,说明中间rtp丢包了,那么整帧应该废弃
|
||||||
|
WarnL << "rtp丢包:" << _last_seq << " -> " << rtp->sequence;
|
||||||
|
_drop_flag = true;
|
||||||
|
_frame->_buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_drop_flag) {
|
||||||
|
_frame->_buffer.append(payload, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
_last_seq = rtp->sequence;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CommonRtpEncoder::CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size,
|
||||||
|
uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved)
|
||||||
|
: CommonRtpDecoder(codec), RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){
|
||||||
|
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
|
||||||
|
auto stamp = frame->dts() % cycleMS;
|
||||||
|
auto ptr = frame->data() + frame->prefixSize();
|
||||||
|
auto len = frame->size() - frame->prefixSize();
|
||||||
|
auto remain_size = len;
|
||||||
|
const auto max_rtp_size = _ui32MtuSize - 20;
|
||||||
|
|
||||||
|
while (remain_size > 0) {
|
||||||
|
auto rtp_size = remain_size > max_rtp_size ? max_rtp_size : remain_size;
|
||||||
|
RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, false, stamp), false);
|
||||||
|
ptr += rtp_size;
|
||||||
|
remain_size -= rtp_size;
|
||||||
|
}
|
||||||
|
}
|
83
src/Extension/CommonRtp.h
Normal file
83
src/Extension/CommonRtp.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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_COMMONRTP_H
|
||||||
|
#define ZLMEDIAKIT_COMMONRTP_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Rtsp/RtpCodec.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 rtp解码类
|
||||||
|
*/
|
||||||
|
class CommonRtpDecoder : public RtpCodec, public ResourcePoolHelper<FrameImp> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr <CommonRtpDecoder> Ptr;
|
||||||
|
|
||||||
|
~CommonRtpDecoder() override {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param codec 编码id
|
||||||
|
*/
|
||||||
|
CommonRtpDecoder(CodecId codec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回编码类型ID
|
||||||
|
*/
|
||||||
|
CodecId getCodecId() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入rtp并解码
|
||||||
|
* @param rtp rtp数据包
|
||||||
|
* @param key_pos 此参数内部强制转换为false,请忽略之
|
||||||
|
*/
|
||||||
|
bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void obtainFrame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CodecId _codec;
|
||||||
|
FrameImp::Ptr _frame;
|
||||||
|
uint16_t _last_seq = 0;
|
||||||
|
bool _drop_flag = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用 rtp编码类
|
||||||
|
*/
|
||||||
|
class CommonRtpEncoder : public CommonRtpDecoder, public RtpInfo {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr <CommonRtpEncoder> Ptr;
|
||||||
|
|
||||||
|
~CommonRtpEncoder() override {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param codec 编码类型
|
||||||
|
* @param ssrc ssrc
|
||||||
|
* @param mtu_size mtu 大小
|
||||||
|
* @param sample_rate 采样率
|
||||||
|
* @param payload_type pt类型
|
||||||
|
* @param interleaved rtsp interleaved 值
|
||||||
|
*/
|
||||||
|
CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入帧数据并编码成rtp
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
#endif //ZLMEDIAKIT_COMMONRTP_H
|
@ -13,11 +13,13 @@
|
|||||||
#include "H264Rtmp.h"
|
#include "H264Rtmp.h"
|
||||||
#include "H265Rtmp.h"
|
#include "H265Rtmp.h"
|
||||||
#include "AACRtmp.h"
|
#include "AACRtmp.h"
|
||||||
#include "G711Rtmp.h"
|
#include "CommonRtmp.h"
|
||||||
#include "H264Rtp.h"
|
#include "H264Rtp.h"
|
||||||
#include "AACRtp.h"
|
#include "AACRtp.h"
|
||||||
#include "G711Rtp.h"
|
|
||||||
#include "H265Rtp.h"
|
#include "H265Rtp.h"
|
||||||
|
#include "CommonRtp.h"
|
||||||
|
#include "Opus.h"
|
||||||
|
#include "G711.h"
|
||||||
#include "Common/Parser.h"
|
#include "Common/Parser.h"
|
||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
@ -42,6 +44,10 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
return std::make_shared<AACTrack>(aac_cfg);
|
return std::make_shared<AACTrack>(aac_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(track->_codec.data(), "opus") == 0) {
|
||||||
|
return std::make_shared<OpusTrack>();
|
||||||
|
}
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "PCMA") == 0) {
|
if (strcasecmp(track->_codec.data(), "PCMA") == 0) {
|
||||||
return std::make_shared<G711Track>(CodecG711A, track->_samplerate, track->_channel, 16);
|
return std::make_shared<G711Track>(CodecG711A, track->_samplerate, track->_channel, 16);
|
||||||
}
|
}
|
||||||
@ -117,8 +123,9 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
|
|||||||
case CodecH264 : return std::make_shared<H264RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
case CodecH264 : return std::make_shared<H264RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
||||||
case CodecH265 : return std::make_shared<H265RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
case CodecH265 : return std::make_shared<H265RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
||||||
case CodecAAC : return std::make_shared<AACRtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
case CodecAAC : return std::make_shared<AACRtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
||||||
|
case CodecOpus :
|
||||||
case CodecG711A :
|
case CodecG711A :
|
||||||
case CodecG711U : return std::make_shared<G711RtpEncoder>(codec_id, ssrc, mtu, sample_rate, pt, interleaved);
|
case CodecG711U : return std::make_shared<CommonRtpEncoder>(codec_id, ssrc, mtu, sample_rate, pt, interleaved);
|
||||||
default : WarnL << "暂不支持该CodecId:" << codec_id; return nullptr;
|
default : WarnL << "暂不支持该CodecId:" << codec_id; return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,8 +135,9 @@ RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
|
|||||||
case CodecH264 : return std::make_shared<H264RtpDecoder>();
|
case CodecH264 : return std::make_shared<H264RtpDecoder>();
|
||||||
case CodecH265 : return std::make_shared<H265RtpDecoder>();
|
case CodecH265 : return std::make_shared<H265RtpDecoder>();
|
||||||
case CodecAAC : return std::make_shared<AACRtpDecoder>(track->clone());
|
case CodecAAC : return std::make_shared<AACRtpDecoder>(track->clone());
|
||||||
|
case CodecOpus :
|
||||||
case CodecG711A :
|
case CodecG711A :
|
||||||
case CodecG711U : return std::make_shared<G711RtpDecoder>(track->getCodecId());
|
case CodecG711U : return std::make_shared<CommonRtpDecoder>(track->getCodecId());
|
||||||
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
|
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,13 +150,10 @@ static CodecId getVideoCodecIdByAmf(const AMFValue &val){
|
|||||||
if (str == "avc1") {
|
if (str == "avc1") {
|
||||||
return CodecH264;
|
return CodecH264;
|
||||||
}
|
}
|
||||||
if(str == "mp4a"){
|
|
||||||
return CodecAAC;
|
|
||||||
}
|
|
||||||
if (str == "hev1" || str == "hvc1") {
|
if (str == "hev1" || str == "hvc1") {
|
||||||
return CodecH265;
|
return CodecH265;
|
||||||
}
|
}
|
||||||
WarnL << "暂不支持该Amf:" << str;
|
WarnL << "暂不支持该视频Amf:" << str;
|
||||||
return CodecInvalid;
|
return CodecInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,21 +161,19 @@ static CodecId getVideoCodecIdByAmf(const AMFValue &val){
|
|||||||
auto type_id = val.as_integer();
|
auto type_id = val.as_integer();
|
||||||
switch (type_id) {
|
switch (type_id) {
|
||||||
case FLV_CODEC_H264 : return CodecH264;
|
case FLV_CODEC_H264 : return CodecH264;
|
||||||
case FLV_CODEC_AAC: return CodecAAC;
|
|
||||||
case FLV_CODEC_H265 : return CodecH265;
|
case FLV_CODEC_H265 : return CodecH265;
|
||||||
default : WarnL << "暂不支持该Amf:" << type_id; return CodecInvalid;
|
default : WarnL << "暂不支持该视频Amf:" << type_id; return CodecInvalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CodecInvalid;
|
return CodecInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Track::Ptr getTrackByCodecId(CodecId codecId, int sample_rate = 0, int channels = 0, int sample_bit = 0) {
|
Track::Ptr getTrackByCodecId(CodecId codecId, int sample_rate = 0, int channels = 0, int sample_bit = 0) {
|
||||||
switch (codecId){
|
switch (codecId){
|
||||||
case CodecH264 : return std::make_shared<H264Track>();
|
case CodecH264 : return std::make_shared<H264Track>();
|
||||||
case CodecH265 : return std::make_shared<H265Track>();
|
case CodecH265 : return std::make_shared<H265Track>();
|
||||||
case CodecAAC : return std::make_shared<AACTrack>();
|
case CodecAAC : return std::make_shared<AACTrack>();
|
||||||
|
case CodecOpus: return std::make_shared<OpusTrack>();
|
||||||
case CodecG711A :
|
case CodecG711A :
|
||||||
case CodecG711U : return (sample_rate && channels && sample_bit) ? std::make_shared<G711Track>(codecId, sample_rate, channels, sample_bit) : nullptr;
|
case CodecG711U : return (sample_rate && channels && sample_bit) ? std::make_shared<G711Track>(codecId, sample_rate, channels, sample_bit) : nullptr;
|
||||||
default : WarnL << "暂不支持该CodecId:" << codecId; return nullptr;
|
default : WarnL << "暂不支持该CodecId:" << codecId; return nullptr;
|
||||||
@ -191,7 +194,7 @@ static CodecId getAudioCodecIdByAmf(const AMFValue &val) {
|
|||||||
if (str == "mp4a") {
|
if (str == "mp4a") {
|
||||||
return CodecAAC;
|
return CodecAAC;
|
||||||
}
|
}
|
||||||
WarnL << "暂不支持该Amf:" << str;
|
WarnL << "暂不支持该音频Amf:" << str;
|
||||||
return CodecInvalid;
|
return CodecInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +204,8 @@ static CodecId getAudioCodecIdByAmf(const AMFValue &val) {
|
|||||||
case FLV_CODEC_AAC : return CodecAAC;
|
case FLV_CODEC_AAC : return CodecAAC;
|
||||||
case FLV_CODEC_G711A : return CodecG711A;
|
case FLV_CODEC_G711A : return CodecG711A;
|
||||||
case FLV_CODEC_G711U : return CodecG711U;
|
case FLV_CODEC_G711U : return CodecG711U;
|
||||||
default : WarnL << "暂不支持该Amf:" << type_id; return CodecInvalid;
|
case FLV_CODEC_OPUS : return CodecOpus;
|
||||||
|
default : WarnL << "暂不支持该音频Amf:" << type_id; return CodecInvalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +225,7 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_enc
|
|||||||
case CodecH264 : return std::make_shared<H264RtmpEncoder>(track);
|
case CodecH264 : return std::make_shared<H264RtmpEncoder>(track);
|
||||||
case CodecAAC : return std::make_shared<AACRtmpEncoder>(track);
|
case CodecAAC : return std::make_shared<AACRtmpEncoder>(track);
|
||||||
case CodecH265 : return std::make_shared<H265RtmpEncoder>(track);
|
case CodecH265 : return std::make_shared<H265RtmpEncoder>(track);
|
||||||
|
case CodecOpus : return std::make_shared<CommonRtmpEncoder>(track);
|
||||||
case CodecG711A :
|
case CodecG711A :
|
||||||
case CodecG711U : {
|
case CodecG711U : {
|
||||||
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
|
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
|
||||||
@ -235,7 +240,7 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_enc
|
|||||||
<< ",该音频已被忽略";
|
<< ",该音频已被忽略";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return std::make_shared<G711RtmpEncoder>(track);
|
return std::make_shared<CommonRtmpEncoder>(track);
|
||||||
}
|
}
|
||||||
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
|
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
|
||||||
}
|
}
|
||||||
@ -248,6 +253,7 @@ AMFValue Factory::getAmfByCodecId(CodecId codecId) {
|
|||||||
case CodecH265: return AMFValue(FLV_CODEC_H265);
|
case CodecH265: return AMFValue(FLV_CODEC_H265);
|
||||||
case CodecG711A: return AMFValue(FLV_CODEC_G711A);
|
case CodecG711A: return AMFValue(FLV_CODEC_G711A);
|
||||||
case CodecG711U: return AMFValue(FLV_CODEC_G711U);
|
case CodecG711U: return AMFValue(FLV_CODEC_G711U);
|
||||||
|
case CodecOpus: return AMFValue(FLV_CODEC_OPUS);
|
||||||
default: return AMFValue(AMF_NULL);
|
default: return AMFValue(AMF_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,12 @@ public:
|
|||||||
_dts = frame->dts();
|
_dts = frame->dts();
|
||||||
_pts = frame->pts();
|
_pts = frame->pts();
|
||||||
_prefix_size = frame->prefixSize();
|
_prefix_size = frame->prefixSize();
|
||||||
_codecid = frame->getCodecId();
|
_codec_id = frame->getCodecId();
|
||||||
_key = frame->keyFrame();
|
_key = frame->keyFrame();
|
||||||
_config = frame->configFrame();
|
_config = frame->configFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FrameCacheAble() = default;
|
~FrameCacheAble() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可以被缓存
|
* 可以被缓存
|
||||||
@ -49,10 +49,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return _codecid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool keyFrame() const override{
|
bool keyFrame() const override{
|
||||||
return _key;
|
return _key;
|
||||||
}
|
}
|
||||||
@ -60,10 +56,10 @@ public:
|
|||||||
bool configFrame() const override{
|
bool configFrame() const override{
|
||||||
return _config;
|
return _config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Frame::Ptr _frame;
|
Frame::Ptr _frame;
|
||||||
BufferRaw::Ptr _buffer;
|
BufferRaw::Ptr _buffer;
|
||||||
CodecId _codecid;
|
|
||||||
bool _key;
|
bool _key;
|
||||||
bool _config;
|
bool _config;
|
||||||
};
|
};
|
||||||
|
@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
CodecId getCodecId() const override{
|
||||||
return _codecid;
|
return _codec_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyFrame() const override {
|
bool keyFrame() const override {
|
||||||
@ -160,7 +160,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CodecId _codecid = CodecInvalid;
|
CodecId _codec_id = CodecInvalid;
|
||||||
string _buffer;
|
string _buffer;
|
||||||
uint32_t _dts = 0;
|
uint32_t _dts = 0;
|
||||||
uint32_t _pts = 0;
|
uint32_t _pts = 0;
|
||||||
@ -314,9 +314,19 @@ private:
|
|||||||
class FrameFromPtr : public Frame{
|
class FrameFromPtr : public Frame{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<FrameFromPtr> Ptr;
|
typedef std::shared_ptr<FrameFromPtr> Ptr;
|
||||||
|
FrameFromPtr(CodecId codec_id, char *ptr, uint32_t size, uint32_t dts, uint32_t pts = 0, int prefix_size = 0){
|
||||||
|
_codec_id = codec_id;
|
||||||
|
_ptr = ptr;
|
||||||
|
_size = size;
|
||||||
|
_dts = dts;
|
||||||
|
_pts = pts;
|
||||||
|
_prefix_size = prefix_size;
|
||||||
|
}
|
||||||
|
|
||||||
char *data() const override{
|
char *data() const override{
|
||||||
return _ptr;
|
return _ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size() const override {
|
uint32_t size() const override {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
@ -336,12 +346,29 @@ public:
|
|||||||
bool cacheAble() const override {
|
bool cacheAble() const override {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return _codec_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configFrame() const override{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FrameFromPtr() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char *_ptr;
|
char *_ptr;
|
||||||
uint32_t _size;
|
uint32_t _size;
|
||||||
uint32_t _dts;
|
uint32_t _dts;
|
||||||
uint32_t _pts = 0;
|
uint32_t _pts = 0;
|
||||||
uint32_t _prefix_size;
|
uint32_t _prefix_size;
|
||||||
|
CodecId _codec_id = CodecInvalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
@ -16,47 +16,6 @@
|
|||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
/**
|
|
||||||
* G711帧
|
|
||||||
*/
|
|
||||||
class G711Frame : public FrameImp {
|
|
||||||
public:
|
|
||||||
G711Frame(){
|
|
||||||
_codecid = CodecG711A;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class G711FrameNoCacheAble : public FrameFromPtr {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<G711FrameNoCacheAble> Ptr;
|
|
||||||
|
|
||||||
G711FrameNoCacheAble(char *ptr,uint32_t size,uint32_t dts, uint32_t pts = 0,int prefix_size = 0){
|
|
||||||
_ptr = ptr;
|
|
||||||
_size = size;
|
|
||||||
_dts = dts;
|
|
||||||
_prefix_size = prefix_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCodec(CodecId codecId){
|
|
||||||
_codecId = codecId;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return _codecId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool keyFrame() const override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configFrame() const override{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CodecId _codecId;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* G711音频通道
|
* G711音频通道
|
||||||
*/
|
*/
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "G711Rtmp.h"
|
|
||||||
|
|
||||||
namespace mediakit{
|
|
||||||
|
|
||||||
G711RtmpDecoder::G711RtmpDecoder(CodecId codecId) {
|
|
||||||
_frame = obtainFrame();
|
|
||||||
_codecId = codecId;
|
|
||||||
}
|
|
||||||
|
|
||||||
G711Frame::Ptr G711RtmpDecoder::obtainFrame() {
|
|
||||||
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
|
||||||
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
|
|
||||||
frame->_buffer.clear();
|
|
||||||
frame->_codecid = _codecId;
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool G711RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
|
|
||||||
//拷贝G711负载
|
|
||||||
_frame->_buffer.assign(pkt->strBuf.data() + 1, pkt->strBuf.size() - 1);
|
|
||||||
_frame->_dts = pkt->timeStamp;
|
|
||||||
//写入环形缓存
|
|
||||||
RtmpCodec::inputFrame(_frame);
|
|
||||||
_frame = obtainFrame();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
G711RtmpEncoder::G711RtmpEncoder(const Track::Ptr &track) : G711RtmpDecoder(track->getCodecId()) {
|
|
||||||
_audio_flv_flags = getAudioRtmpFlags(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void G711RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
|
|
||||||
if(!_audio_flv_flags){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
|
|
||||||
rtmpPkt->strBuf.clear();
|
|
||||||
//header
|
|
||||||
rtmpPkt->strBuf.push_back(_audio_flv_flags);
|
|
||||||
|
|
||||||
//g711 data
|
|
||||||
rtmpPkt->strBuf.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
|
||||||
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
|
|
||||||
rtmpPkt->chunkId = CHUNK_AUDIO;
|
|
||||||
rtmpPkt->streamId = STREAM_MEDIA;
|
|
||||||
rtmpPkt->timeStamp = frame->dts();
|
|
||||||
rtmpPkt->typeId = MSG_AUDIO;
|
|
||||||
RtmpCodec::inputRtmp(rtmpPkt, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}//namespace mediakit
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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_G711RTMPCODEC_H
|
|
||||||
#define ZLMEDIAKIT_G711RTMPCODEC_H
|
|
||||||
|
|
||||||
#include "Rtmp/RtmpCodec.h"
|
|
||||||
#include "Extension/Track.h"
|
|
||||||
#include "Extension/G711.h"
|
|
||||||
|
|
||||||
namespace mediakit{
|
|
||||||
/**
|
|
||||||
* G711 Rtmp转G711 Frame类
|
|
||||||
*/
|
|
||||||
class G711RtmpDecoder : public RtmpCodec , public ResourcePoolHelper<G711Frame> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<G711RtmpDecoder> Ptr;
|
|
||||||
|
|
||||||
G711RtmpDecoder(CodecId codecId);
|
|
||||||
~G711RtmpDecoder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入Rtmp并解码
|
|
||||||
* @param Rtmp Rtmp数据包
|
|
||||||
* @param key_pos 此参数内部强制转换为false,请忽略之
|
|
||||||
*/
|
|
||||||
bool inputRtmp(const RtmpPacket::Ptr &Rtmp, bool key_pos = false) override;
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return _codecId;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
G711Frame::Ptr obtainFrame();
|
|
||||||
private:
|
|
||||||
G711Frame::Ptr _frame;
|
|
||||||
CodecId _codecId;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* G711 RTMP打包类
|
|
||||||
*/
|
|
||||||
class G711RtmpEncoder : public G711RtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<G711RtmpEncoder> Ptr;
|
|
||||||
|
|
||||||
G711RtmpEncoder(const Track::Ptr &track);
|
|
||||||
~G711RtmpEncoder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入G711 数据
|
|
||||||
*/
|
|
||||||
void inputFrame(const Frame::Ptr &frame) override;
|
|
||||||
private:
|
|
||||||
uint8_t _audio_flv_flags = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}//namespace mediakit
|
|
||||||
|
|
||||||
#endif //ZLMEDIAKIT_G711RTMPCODEC_H
|
|
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "G711Rtp.h"
|
|
||||||
|
|
||||||
namespace mediakit{
|
|
||||||
|
|
||||||
G711RtpDecoder::G711RtpDecoder(CodecId codecid){
|
|
||||||
_codecid = codecid;
|
|
||||||
_frame = obtainFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
G711Frame::Ptr G711RtpDecoder::obtainFrame() {
|
|
||||||
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
|
||||||
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
|
|
||||||
frame->_buffer.clear();
|
|
||||||
frame->_codecid = _codecid;
|
|
||||||
frame->_dts = 0;
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool G711RtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool) {
|
|
||||||
// 获取rtp数据长度
|
|
||||||
int length = rtppack->size() - rtppack->offset;
|
|
||||||
// 获取rtp数据
|
|
||||||
const char *rtp_packet_buf = rtppack->data() + rtppack->offset;
|
|
||||||
|
|
||||||
if (rtppack->timeStamp != _frame->_dts) {
|
|
||||||
//时间戳变更,清空上一帧
|
|
||||||
onGetG711(_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
//追加数据
|
|
||||||
_frame->_buffer.append(rtp_packet_buf, length);
|
|
||||||
//赋值时间戳
|
|
||||||
_frame->_dts = rtppack->timeStamp;
|
|
||||||
|
|
||||||
if (rtppack->mark || _frame->_buffer.size() > 10 * 1024) {
|
|
||||||
//标记为mark时,或者内存快溢出时,我们认为这是该帧最后一个包
|
|
||||||
onGetG711(_frame);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void G711RtpDecoder::onGetG711(const G711Frame::Ptr &frame) {
|
|
||||||
if(!frame->_buffer.empty()){
|
|
||||||
//写入环形缓存
|
|
||||||
RtpCodec::inputFrame(frame);
|
|
||||||
_frame = obtainFrame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
G711RtpEncoder::G711RtpEncoder(CodecId codecid, uint32_t ui32Ssrc, uint32_t ui32MtuSize,
|
|
||||||
uint32_t ui32SampleRate, uint8_t ui8PayloadType, uint8_t ui8Interleaved) :
|
|
||||||
G711RtpDecoder(codecid),
|
|
||||||
RtpInfo(ui32Ssrc, ui32MtuSize, ui32SampleRate, ui8PayloadType, ui8Interleaved) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void G711RtpEncoder::inputFrame(const Frame::Ptr &frame) {
|
|
||||||
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
|
|
||||||
auto uiStamp = frame->dts();
|
|
||||||
auto pcData = frame->data() + frame->prefixSize();
|
|
||||||
auto iLen = frame->size() - frame->prefixSize();
|
|
||||||
|
|
||||||
uiStamp %= cycleMS;
|
|
||||||
char *ptr = (char *) pcData;
|
|
||||||
int iSize = iLen;
|
|
||||||
while (iSize > 0) {
|
|
||||||
if (iSize <= _ui32MtuSize - 20) {
|
|
||||||
makeG711Rtp(ptr, iSize, true, uiStamp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
makeG711Rtp(ptr, _ui32MtuSize - 20, false, uiStamp);
|
|
||||||
ptr += (_ui32MtuSize - 20);
|
|
||||||
iSize -= (_ui32MtuSize - 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void G711RtpEncoder::makeG711Rtp(const void *data, unsigned int len, bool mark, uint32_t uiStamp) {
|
|
||||||
RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, mark, uiStamp), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}//namespace mediakit
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/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_G711RTPCODEC_H
|
|
||||||
#define ZLMEDIAKIT_G711RTPCODEC_H
|
|
||||||
#include "Rtsp/RtpCodec.h"
|
|
||||||
#include "Extension/G711.h"
|
|
||||||
namespace mediakit{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rtp转G711类
|
|
||||||
*/
|
|
||||||
class G711RtpDecoder : public RtpCodec , public ResourcePoolHelper<G711Frame> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<G711RtpDecoder> Ptr;
|
|
||||||
|
|
||||||
G711RtpDecoder(CodecId codecid);
|
|
||||||
~G711RtpDecoder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入rtp并解码
|
|
||||||
* @param rtp rtp数据包
|
|
||||||
* @param key_pos 此参数内部强制转换为false,请忽略之
|
|
||||||
*/
|
|
||||||
bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override;
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return _codecid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void onGetG711(const G711Frame::Ptr &frame);
|
|
||||||
G711Frame::Ptr obtainFrame();
|
|
||||||
|
|
||||||
private:
|
|
||||||
G711Frame::Ptr _frame;
|
|
||||||
CodecId _codecid;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* g711 转rtp类
|
|
||||||
*/
|
|
||||||
class G711RtpEncoder : public G711RtpDecoder , public RtpInfo {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<G711RtpEncoder> Ptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ui32Ssrc ssrc
|
|
||||||
* @param ui32MtuSize mtu 大小
|
|
||||||
* @param ui32SampleRate 采样率
|
|
||||||
* @param ui8PayloadType pt类型
|
|
||||||
* @param ui8Interleaved rtsp interleaved 值
|
|
||||||
*/
|
|
||||||
G711RtpEncoder(CodecId codecid,
|
|
||||||
uint32_t ui32Ssrc,
|
|
||||||
uint32_t ui32MtuSize,
|
|
||||||
uint32_t ui32SampleRate,
|
|
||||||
uint8_t ui8PayloadType = 0,
|
|
||||||
uint8_t ui8Interleaved = TrackAudio * 2);
|
|
||||||
~G711RtpEncoder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param frame g711数据
|
|
||||||
*/
|
|
||||||
void inputFrame(const Frame::Ptr &frame) override;
|
|
||||||
private:
|
|
||||||
void makeG711Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
|
||||||
};
|
|
||||||
|
|
||||||
}//namespace mediakit
|
|
||||||
|
|
||||||
#endif //ZLMEDIAKIT_G711RTPCODEC_H
|
|
@ -37,7 +37,7 @@ public:
|
|||||||
} NalType;
|
} NalType;
|
||||||
|
|
||||||
H264Frame(){
|
H264Frame(){
|
||||||
_codecid = CodecH264;
|
_codec_id = CodecH264;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyFrame() const override {
|
bool keyFrame() const override {
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
} NaleType;
|
} NaleType;
|
||||||
|
|
||||||
H265Frame(){
|
H265Frame(){
|
||||||
_codecid = CodecH265;
|
_codec_id = CodecH265;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyFrame() const override {
|
bool keyFrame() const override {
|
||||||
|
@ -16,52 +16,13 @@
|
|||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
|
|
||||||
/**
|
|
||||||
* Opus帧
|
|
||||||
*/
|
|
||||||
class OpusFrame : public FrameImp {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<OpusFrame> Ptr;
|
|
||||||
|
|
||||||
OpusFrame(){
|
|
||||||
_codecid = CodecOpus;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 不可缓存的Opus帧
|
|
||||||
*/
|
|
||||||
class OpusFrameNoCacheAble : public FrameFromPtr {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<OpusFrameNoCacheAble> Ptr;
|
|
||||||
|
|
||||||
OpusFrameNoCacheAble(char *ptr,uint32_t size,uint32_t dts, uint32_t pts = 0,int prefix_size = 0){
|
|
||||||
_ptr = ptr;
|
|
||||||
_size = size;
|
|
||||||
_dts = dts;
|
|
||||||
_prefix_size = prefix_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecId getCodecId() const override{
|
|
||||||
return CodecOpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool keyFrame() const override {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configFrame() const override{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opus帧音频通道
|
* Opus帧音频通道
|
||||||
*/
|
*/
|
||||||
class OpusTrack : public AudioTrackImp{
|
class OpusTrack : public AudioTrackImp{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<OpusTrack> Ptr;
|
typedef std::shared_ptr<OpusTrack> Ptr;
|
||||||
OpusTrack(int sample_rate, int channels, int sample_bit) : AudioTrackImp(CodecOpus,sample_rate,channels,sample_bit){}
|
OpusTrack() : AudioTrackImp(CodecOpus,48000,2,16){}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//克隆该Track
|
//克隆该Track
|
||||||
|
@ -46,31 +46,25 @@ static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00,
|
|||||||
#define MUTE_ADTS_DATA_LEN sizeof(s_mute_adts)
|
#define MUTE_ADTS_DATA_LEN sizeof(s_mute_adts)
|
||||||
#define MUTE_ADTS_DATA_MS 130
|
#define MUTE_ADTS_DATA_MS 130
|
||||||
|
|
||||||
PlayerProxy::PlayerProxy(const string &strVhost,
|
PlayerProxy::PlayerProxy(const string &vhost, const string &app, const string &stream_id,
|
||||||
const string &strApp,
|
bool enable_rtsp, bool enable_rtmp, bool enable_hls, bool enable_mp4,
|
||||||
const string &strSrc,
|
int retry_count, const EventPoller::Ptr &poller) : MediaPlayer(poller){
|
||||||
bool bEnableRtsp,
|
_vhost = vhost;
|
||||||
bool bEnableRtmp,
|
_app = app;
|
||||||
bool bEnableHls,
|
_stream_id = stream_id;
|
||||||
bool bEnableMp4,
|
_enable_rtsp = enable_rtsp;
|
||||||
int iRetryCount,
|
_enable_rtmp = enable_rtmp;
|
||||||
const EventPoller::Ptr &poller) : MediaPlayer(poller){
|
_enable_hls = enable_hls;
|
||||||
_strVhost = strVhost;
|
_enable_mp4 = enable_mp4;
|
||||||
_strApp = strApp;
|
_retry_count = retry_count;
|
||||||
_strSrc = strSrc;
|
|
||||||
_bEnableRtsp = bEnableRtsp;
|
|
||||||
_bEnableRtmp = bEnableRtmp;
|
|
||||||
_bEnableHls = bEnableHls;
|
|
||||||
_bEnableMp4 = bEnableMp4;
|
|
||||||
_iRetryCount = iRetryCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerProxy::setPlayCallbackOnce(const function<void(const SockException &ex)> &cb){
|
void PlayerProxy::setPlayCallbackOnce(const function<void(const SockException &ex)> &cb){
|
||||||
_playCB = cb;
|
_on_play = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerProxy::setOnClose(const function<void()> &cb){
|
void PlayerProxy::setOnClose(const function<void()> &cb){
|
||||||
_onClose = cb;
|
_on_close = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerProxy::play(const string &strUrlTmp) {
|
void PlayerProxy::play(const string &strUrlTmp) {
|
||||||
@ -82,16 +76,16 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strongSelf->_playCB) {
|
if(strongSelf->_on_play) {
|
||||||
strongSelf->_playCB(err);
|
strongSelf->_on_play(err);
|
||||||
strongSelf->_playCB = nullptr;
|
strongSelf->_on_play = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!err) {
|
if(!err) {
|
||||||
// 播放成功
|
// 播放成功
|
||||||
*piFailedCnt = 0;//连续播放失败次数清0
|
*piFailedCnt = 0;//连续播放失败次数清0
|
||||||
strongSelf->onPlaySuccess();
|
strongSelf->onPlaySuccess();
|
||||||
}else if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
|
}else if(*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
|
||||||
// 播放失败,延时重试播放
|
// 播放失败,延时重试播放
|
||||||
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
|
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
|
||||||
}
|
}
|
||||||
@ -101,21 +95,21 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
|||||||
if(!strongSelf) {
|
if(!strongSelf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(strongSelf->_mediaMuxer) {
|
if(strongSelf->_muxer) {
|
||||||
auto tracks = strongSelf->getTracks(false);
|
auto tracks = strongSelf->getTracks(false);
|
||||||
for (auto & track : tracks){
|
for (auto & track : tracks){
|
||||||
track->delDelegate(strongSelf->_mediaMuxer.get());
|
track->delDelegate(strongSelf->_muxer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
|
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
|
||||||
if (resetWhenRePlay) {
|
if (resetWhenRePlay) {
|
||||||
strongSelf->_mediaMuxer.reset();
|
strongSelf->_muxer.reset();
|
||||||
} else {
|
} else {
|
||||||
strongSelf->_mediaMuxer->resetTracks();
|
strongSelf->_muxer->resetTracks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//播放异常中断,延时重试播放
|
//播放异常中断,延时重试播放
|
||||||
if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
|
if(*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
|
||||||
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
|
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -125,13 +119,14 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
|||||||
if(dynamic_pointer_cast<RtspPlayer>(_delegate)){
|
if(dynamic_pointer_cast<RtspPlayer>(_delegate)){
|
||||||
//rtsp拉流
|
//rtsp拉流
|
||||||
GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy);
|
GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy);
|
||||||
if(directProxy && _bEnableRtsp){
|
if(directProxy && _enable_rtsp){
|
||||||
mediaSource = std::make_shared<RtspMediaSource>(_strVhost,_strApp,_strSrc);
|
mediaSource = std::make_shared<RtspMediaSource>(_vhost, _app, _stream_id);
|
||||||
}
|
}
|
||||||
} else if(dynamic_pointer_cast<RtmpPlayer>(_delegate)){
|
} else if(dynamic_pointer_cast<RtmpPlayer>(_delegate)){
|
||||||
//rtmp拉流
|
//rtmp拉流
|
||||||
if(_bEnableRtmp){
|
if(_enable_rtmp){
|
||||||
mediaSource = std::make_shared<RtmpMediaSource>(_strVhost,_strApp,_strSrc);
|
//rtmp强制直接代理
|
||||||
|
mediaSource = std::make_shared<RtmpMediaSource>(_vhost, _app, _stream_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mediaSource){
|
if(mediaSource){
|
||||||
@ -143,6 +138,7 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
|||||||
PlayerProxy::~PlayerProxy() {
|
PlayerProxy::~PlayerProxy() {
|
||||||
_timer.reset();
|
_timer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){
|
void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){
|
||||||
auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60*1000));
|
auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60*1000));
|
||||||
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
|
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
|
||||||
@ -164,16 +160,17 @@ bool PlayerProxy::close(MediaSource &sender,bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//通知其停止推流
|
//通知其停止推流
|
||||||
weak_ptr<PlayerProxy> weakSlef = dynamic_pointer_cast<PlayerProxy>(shared_from_this());
|
weak_ptr<PlayerProxy> weakSelf = dynamic_pointer_cast<PlayerProxy>(shared_from_this());
|
||||||
getPoller()->async_first([weakSlef]() {
|
getPoller()->async_first([weakSelf]() {
|
||||||
auto stronSelf = weakSlef.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if (stronSelf) {
|
if (!strongSelf) {
|
||||||
stronSelf->_mediaMuxer.reset();
|
return;
|
||||||
stronSelf->setMediaSouce(nullptr);
|
|
||||||
stronSelf->teardown();
|
|
||||||
if(stronSelf->_onClose){
|
|
||||||
stronSelf->_onClose();
|
|
||||||
}
|
}
|
||||||
|
strongSelf->_muxer.reset();
|
||||||
|
strongSelf->setMediaSouce(nullptr);
|
||||||
|
strongSelf->teardown();
|
||||||
|
if (strongSelf->_on_close) {
|
||||||
|
strongSelf->_on_close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force;
|
WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force;
|
||||||
@ -181,7 +178,7 @@ bool PlayerProxy::close(MediaSource &sender,bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PlayerProxy::totalReaderCount(){
|
int PlayerProxy::totalReaderCount(){
|
||||||
return (_mediaMuxer ? _mediaMuxer->totalReaderCount() : 0) + (_pMediaSrc ? _pMediaSrc->readerCount() : 0);
|
return (_muxer ? _muxer->totalReaderCount() : 0) + (_pMediaSrc ? _pMediaSrc->readerCount() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PlayerProxy::totalReaderCount(MediaSource &sender) {
|
int PlayerProxy::totalReaderCount(MediaSource &sender) {
|
||||||
@ -193,59 +190,61 @@ public:
|
|||||||
typedef std::shared_ptr<MuteAudioMaker> Ptr;
|
typedef std::shared_ptr<MuteAudioMaker> Ptr;
|
||||||
|
|
||||||
MuteAudioMaker(){};
|
MuteAudioMaker(){};
|
||||||
virtual ~MuteAudioMaker(){}
|
~MuteAudioMaker() override {}
|
||||||
|
|
||||||
void inputFrame(const Frame::Ptr &frame) override {
|
void inputFrame(const Frame::Ptr &frame) override {
|
||||||
if(frame->getTrackType() == TrackVideo){
|
if(frame->getTrackType() == TrackVideo){
|
||||||
auto iAudioIndex = frame->dts() / MUTE_ADTS_DATA_MS;
|
auto audio_idx = frame->dts() / MUTE_ADTS_DATA_MS;
|
||||||
if(_iAudioIndex != iAudioIndex){
|
if(_audio_idx != audio_idx){
|
||||||
_iAudioIndex = iAudioIndex;
|
_audio_idx = audio_idx;
|
||||||
auto aacFrame = std::make_shared<AACFrameCacheAble>((char *)MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS, 0);
|
auto aacFrame = std::make_shared<FrameFromStaticPtr>(CodecAAC, (char *)MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, _audio_idx * MUTE_ADTS_DATA_MS);
|
||||||
FrameDispatcher::inputFrame(aacFrame);
|
FrameDispatcher::inputFrame(aacFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class AACFrameCacheAble : public AACFrameNoCacheAble{
|
class FrameFromStaticPtr : public FrameFromPtr{
|
||||||
public:
|
public:
|
||||||
template <typename ... ARGS>
|
template <typename ... ARGS>
|
||||||
AACFrameCacheAble(ARGS && ...args) : AACFrameNoCacheAble(std::forward<ARGS>(args)...){};
|
FrameFromStaticPtr(ARGS && ...args) : FrameFromPtr(std::forward<ARGS>(args)...) {};
|
||||||
virtual ~AACFrameCacheAble() = default;
|
~FrameFromStaticPtr() override = default;
|
||||||
|
|
||||||
bool cacheAble() const override {
|
bool cacheAble() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _iAudioIndex = 0;
|
int _audio_idx = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void PlayerProxy::onPlaySuccess() {
|
void PlayerProxy::onPlaySuccess() {
|
||||||
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
|
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
|
||||||
if (dynamic_pointer_cast<RtspMediaSource>(_pMediaSrc)) {
|
if (dynamic_pointer_cast<RtspMediaSource>(_pMediaSrc)) {
|
||||||
//rtsp拉流代理
|
//rtsp拉流代理
|
||||||
if (resetWhenRePlay || !_mediaMuxer) {
|
if (resetWhenRePlay || !_muxer) {
|
||||||
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4));
|
_muxer.reset(new MultiMediaSourceMuxer(_vhost, _app, _stream_id, getDuration(), false, _enable_rtmp, _enable_hls, _enable_mp4));
|
||||||
}
|
}
|
||||||
} else if (dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc)) {
|
} else if (dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc)) {
|
||||||
//rtmp拉流代理
|
//rtmp拉流代理
|
||||||
if (resetWhenRePlay || !_mediaMuxer) {
|
if (resetWhenRePlay || !_muxer) {
|
||||||
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4));
|
_muxer.reset(new MultiMediaSourceMuxer(_vhost, _app, _stream_id, getDuration(), _enable_rtsp, false, _enable_hls, _enable_mp4));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//其他拉流代理
|
//其他拉流代理
|
||||||
if (resetWhenRePlay || !_mediaMuxer) {
|
if (resetWhenRePlay || !_muxer) {
|
||||||
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4));
|
_muxer.reset(new MultiMediaSourceMuxer(_vhost, _app, _stream_id, getDuration(), _enable_rtsp, _enable_rtmp, _enable_hls, _enable_mp4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_mediaMuxer->setMediaListener(shared_from_this());
|
_muxer->setMediaListener(shared_from_this());
|
||||||
|
|
||||||
auto videoTrack = getTrack(TrackVideo, false);
|
auto videoTrack = getTrack(TrackVideo, false);
|
||||||
if (videoTrack) {
|
if (videoTrack) {
|
||||||
//添加视频
|
//添加视频
|
||||||
_mediaMuxer->addTrack(videoTrack);
|
_muxer->addTrack(videoTrack);
|
||||||
//视频数据写入_mediaMuxer
|
//视频数据写入_mediaMuxer
|
||||||
videoTrack->addDelegate(_mediaMuxer);
|
videoTrack->addDelegate(_muxer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//是否添加静音音频
|
//是否添加静音音频
|
||||||
@ -254,27 +253,26 @@ void PlayerProxy::onPlaySuccess() {
|
|||||||
auto audioTrack = getTrack(TrackAudio, false);
|
auto audioTrack = getTrack(TrackAudio, false);
|
||||||
if (audioTrack) {
|
if (audioTrack) {
|
||||||
//添加音频
|
//添加音频
|
||||||
_mediaMuxer->addTrack(audioTrack);
|
_muxer->addTrack(audioTrack);
|
||||||
//音频数据写入_mediaMuxer
|
//音频数据写入_mediaMuxer
|
||||||
audioTrack->addDelegate(_mediaMuxer);
|
audioTrack->addDelegate(_muxer);
|
||||||
} else if (addMuteAudio && videoTrack) {
|
} else if (addMuteAudio && videoTrack) {
|
||||||
//没有音频信息,产生一个静音音频
|
//没有音频信息,产生一个静音音频
|
||||||
MuteAudioMaker::Ptr audioMaker = std::make_shared<MuteAudioMaker>();
|
MuteAudioMaker::Ptr audioMaker = std::make_shared<MuteAudioMaker>();
|
||||||
//videoTrack把数据写入MuteAudioMaker
|
//videoTrack把数据写入MuteAudioMaker
|
||||||
videoTrack->addDelegate(audioMaker);
|
videoTrack->addDelegate(audioMaker);
|
||||||
//添加一个静音Track至_mediaMuxer
|
//添加一个静音Track至_mediaMuxer
|
||||||
_mediaMuxer->addTrack(std::make_shared<AACTrack>());
|
_muxer->addTrack(std::make_shared<AACTrack>());
|
||||||
//MuteAudioMaker生成静音音频然后写入_mediaMuxer;
|
//MuteAudioMaker生成静音音频然后写入_mediaMuxer;
|
||||||
audioMaker->addDelegate(_mediaMuxer);
|
audioMaker->addDelegate(_muxer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加完毕所有track,防止单track情况下最大等待3秒
|
//添加完毕所有track,防止单track情况下最大等待3秒
|
||||||
_mediaMuxer->addTrackCompleted();
|
_muxer->addTrackCompleted();
|
||||||
|
|
||||||
if (_pMediaSrc) {
|
if (_pMediaSrc) {
|
||||||
_pMediaSrc->setTrackSource(_mediaMuxer);
|
_pMediaSrc->setTrackSource(_muxer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
@ -15,32 +15,22 @@
|
|||||||
#include "Common/Device.h"
|
#include "Common/Device.h"
|
||||||
#include "Player/MediaPlayer.h"
|
#include "Player/MediaPlayer.h"
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
class PlayerProxy :public MediaPlayer,
|
class PlayerProxy : public MediaPlayer, public MediaSourceEvent, public std::enable_shared_from_this<PlayerProxy> {
|
||||||
public std::enable_shared_from_this<PlayerProxy> ,
|
|
||||||
public MediaSourceEvent{
|
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<PlayerProxy> Ptr;
|
typedef std::shared_ptr<PlayerProxy> Ptr;
|
||||||
|
|
||||||
//如果iRetryCount<0,则一直重试播放;否则重试iRetryCount次数
|
//如果retry_count<0,则一直重试播放;否则重试retry_count次数
|
||||||
//默认一直重试
|
//默认一直重试
|
||||||
PlayerProxy(const string &strVhost,
|
PlayerProxy(const string &vhost, const string &app, const string &stream_id,
|
||||||
const string &strApp,
|
bool enable_rtsp = true, bool enable_rtmp = true, bool enable_hls = true, bool enable_mp4 = false,
|
||||||
const string &strSrc,
|
int retry_count = -1, const EventPoller::Ptr &poller = nullptr);
|
||||||
bool bEnableRtsp = true,
|
|
||||||
bool bEnableRtmp = true,
|
|
||||||
bool bEnableHls = true,
|
|
||||||
bool bEnableMp4 = false,
|
|
||||||
int iRetryCount = -1,
|
|
||||||
const EventPoller::Ptr &poller = nullptr);
|
|
||||||
|
|
||||||
virtual ~PlayerProxy();
|
~PlayerProxy() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置play结果回调,只触发一次;在play执行之前有效
|
* 设置play结果回调,只触发一次;在play执行之前有效
|
||||||
@ -64,27 +54,28 @@ public:
|
|||||||
* 获取观看总人数
|
* 获取观看总人数
|
||||||
*/
|
*/
|
||||||
int totalReaderCount() ;
|
int totalReaderCount() ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//MediaSourceEvent override
|
//MediaSourceEvent override
|
||||||
bool close(MediaSource &sender,bool force) override;
|
bool close(MediaSource &sender,bool force) override;
|
||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
void rePlay(const string &strUrl,int iFailedCnt);
|
void rePlay(const string &strUrl,int iFailedCnt);
|
||||||
void onPlaySuccess();
|
void onPlaySuccess();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _bEnableRtsp;
|
bool _enable_rtsp;
|
||||||
bool _bEnableRtmp;
|
bool _enable_rtmp;
|
||||||
bool _bEnableHls;
|
bool _enable_hls;
|
||||||
bool _bEnableMp4;
|
bool _enable_mp4;
|
||||||
int _iRetryCount;
|
int _retry_count;
|
||||||
MultiMediaSourceMuxer::Ptr _mediaMuxer;
|
string _vhost;
|
||||||
string _strVhost;
|
string _app;
|
||||||
string _strApp;
|
string _stream_id;
|
||||||
string _strSrc;
|
|
||||||
Timer::Ptr _timer;
|
Timer::Ptr _timer;
|
||||||
function<void(const SockException &ex)> _playCB;
|
function<void()> _on_close;
|
||||||
function<void()> _onClose;
|
function<void(const SockException &ex)> _on_play;
|
||||||
|
MultiMediaSourceMuxer::Ptr _muxer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
||||||
#endif /* SRC_DEVICE_PLAYERPROXY_H_ */
|
#endif /* SRC_DEVICE_PLAYERPROXY_H_ */
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Extension/H264.h"
|
#include "Extension/H264.h"
|
||||||
#include "Extension/AAC.h"
|
#include "Extension/AAC.h"
|
||||||
#include "Extension/G711.h"
|
#include "Extension/G711.h"
|
||||||
|
#include "Extension/Opus.h"
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
@ -119,14 +120,22 @@ void MP4Demuxer::onAudioTrack(uint32_t track_id, uint8_t object, int channel_cou
|
|||||||
case MOV_OBJECT_AAC:{
|
case MOV_OBJECT_AAC:{
|
||||||
auto audio = std::make_shared<AACTrack>(bytes > 0 ? string((char *)extra,bytes) : "");
|
auto audio = std::make_shared<AACTrack>(bytes > 0 ? string((char *)extra,bytes) : "");
|
||||||
_track_to_codec.emplace(track_id, audio);
|
_track_to_codec.emplace(track_id, audio);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MOV_OBJECT_G711a:
|
case MOV_OBJECT_G711a:
|
||||||
case MOV_OBJECT_G711u:{
|
case MOV_OBJECT_G711u:{
|
||||||
auto audio = std::make_shared<G711Track>(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count );
|
auto audio = std::make_shared<G711Track>(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count );
|
||||||
_track_to_codec.emplace(track_id, audio);
|
_track_to_codec.emplace(track_id, audio);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MOV_OBJECT_OPUS: {
|
||||||
|
auto audio = std::make_shared<OpusTrack>();
|
||||||
|
_track_to_codec.emplace(track_id, audio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object);
|
WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object);
|
||||||
break;
|
break;
|
||||||
@ -196,6 +205,11 @@ public:
|
|||||||
FrameWrapper(const Buffer::Ptr &buf, int64_t pts, int64_t dts, int prefix) : Parent(buf->data(), buf->size(), dts, pts, prefix){
|
FrameWrapper(const Buffer::Ptr &buf, int64_t pts, int64_t dts, int prefix) : Parent(buf->data(), buf->size(), dts, pts, prefix){
|
||||||
_buf = buf;
|
_buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameWrapper(CodecId codec,const Buffer::Ptr &buf, int64_t pts, int64_t dts, int prefix) : Parent(codec, buf->data(), buf->size(), dts, pts, prefix){
|
||||||
|
_buf = buf;
|
||||||
|
}
|
||||||
|
|
||||||
bool cacheAble() const override {
|
bool cacheAble() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -231,14 +245,11 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6
|
|||||||
return std::make_shared<FrameWrapper<H265FrameNoCacheAble> >(buf, pts, dts, 4);
|
return std::make_shared<FrameWrapper<H265FrameNoCacheAble> >(buf, pts, dts, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CodecOpus:
|
||||||
case CodecAAC:
|
case CodecAAC:
|
||||||
return std::make_shared<FrameWrapper<AACFrameNoCacheAble> >(buf, pts, dts, 0);
|
|
||||||
|
|
||||||
case CodecG711A:
|
case CodecG711A:
|
||||||
case CodecG711U: {
|
case CodecG711U: {
|
||||||
auto frame = std::make_shared<FrameWrapper<G711FrameNoCacheAble> >(buf, pts, dts, 0);
|
return std::make_shared<FrameWrapper<FrameFromPtr> >(codec, buf, pts, dts, 0);
|
||||||
frame->setCodec(codec);
|
|
||||||
return frame;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -58,6 +58,14 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track){
|
|||||||
switch (track->getCodecId()){
|
switch (track->getCodecId()){
|
||||||
case CodecG711A : flvAudioType = FLV_CODEC_G711A; break;
|
case CodecG711A : flvAudioType = FLV_CODEC_G711A; break;
|
||||||
case CodecG711U : flvAudioType = FLV_CODEC_G711U; break;
|
case CodecG711U : flvAudioType = FLV_CODEC_G711U; break;
|
||||||
|
case CodecOpus : {
|
||||||
|
flvAudioType = FLV_CODEC_OPUS;
|
||||||
|
//opus不通过flags获取音频相关信息
|
||||||
|
iSampleRate = 44100;
|
||||||
|
iSampleBit = 16;
|
||||||
|
iChannel = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CodecAAC : {
|
case CodecAAC : {
|
||||||
flvAudioType = FLV_CODEC_AAC;
|
flvAudioType = FLV_CODEC_AAC;
|
||||||
//aac不通过flags获取音频相关信息
|
//aac不通过flags获取音频相关信息
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
@ -74,10 +74,12 @@ using namespace toolkit;
|
|||||||
|
|
||||||
#define FLV_CODEC_AAC 10
|
#define FLV_CODEC_AAC 10
|
||||||
#define FLV_CODEC_H264 7
|
#define FLV_CODEC_H264 7
|
||||||
|
//金山扩展: https://github.com/ksvc/FFmpeg/wiki
|
||||||
#define FLV_CODEC_H265 12
|
#define FLV_CODEC_H265 12
|
||||||
#define FLV_CODEC_G711A 7
|
#define FLV_CODEC_G711A 7
|
||||||
#define FLV_CODEC_G711U 8
|
#define FLV_CODEC_G711U 8
|
||||||
|
//参考学而思网校: https://github.com/notedit/rtmp/commit/6e314ac5b29611431f8fb5468596b05815743c10
|
||||||
|
#define FLV_CODEC_OPUS 13
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
|||||||
WarnL<< "audio track change to AAC from codecid:" << getCodecName(_codecid_audio);
|
WarnL<< "audio track change to AAC from codecid:" << getCodecName(_codecid_audio);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onFrame(std::make_shared<AACFrameNoCacheAble>((char *) data, bytes, dts, 0, 7));
|
onFrame(std::make_shared<FrameFromPtr>(CodecAAC, (char *) data, bytes, dts, 0, ADTS_HEADER_LEN));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,9 +195,7 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d
|
|||||||
WarnL<< "audio track change to G711 from codecid:" << getCodecName(_codecid_audio);
|
WarnL<< "audio track change to G711 from codecid:" << getCodecName(_codecid_audio);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto frame = std::make_shared<G711FrameNoCacheAble>((char *) data, bytes, dts);
|
onFrame(std::make_shared<FrameFromPtr>(codec, (char *) data, bytes, dts));
|
||||||
frame->setCodec(codec);
|
|
||||||
onFrame(frame);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -106,6 +106,7 @@ public:
|
|||||||
return _ui32MtuSize;
|
return _ui32MtuSize;
|
||||||
}
|
}
|
||||||
RtpPacket::Ptr makeRtp(TrackType type,const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
RtpPacket::Ptr makeRtp(TrackType type,const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t _ui32Ssrc;
|
uint32_t _ui32Ssrc;
|
||||||
uint32_t _ui32SampleRate;
|
uint32_t _ui32SampleRate;
|
||||||
|
Loading…
Reference in New Issue
Block a user