Commit a22f97c7 by xiongziliang

rtsp/rtmp/mp4支持opus并整理代码

parent b4a3b608
...@@ -54,7 +54,7 @@ API_EXPORT void API_CALL mk_media_init_video(mk_media ctx, int track_id, int wid ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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 @@ ...@@ -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 ...@@ -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;
}; };
...@@ -123,31 +118,32 @@ public: ...@@ -123,31 +118,32 @@ public:
}; };
void DevChannel::inputAAC(const char *data_without_adts, int len, uint32_t dts, const char *adts_header){ void DevChannel::inputAAC(const char *data_without_adts, int len, uint32_t dts, const char *adts_header){
if(dts == 0){ if (dts == 0) {
dts = (uint32_t)_aTicker[1].elapsedTime(); dts = (uint32_t) _aTicker[1].elapsedTime();
} }
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) { ...@@ -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 @@ ...@@ -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{ ...@@ -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: ...@@ -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
/** /**
......
...@@ -22,41 +22,6 @@ int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size); ...@@ -22,41 +22,6 @@ 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音频通道
*/ */
class AACTrack : public AudioTrack{ class AACTrack : public AudioTrack{
......
...@@ -43,7 +43,9 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) { ...@@ -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{ ...@@ -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) { ...@@ -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() { ...@@ -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 \ No newline at end of file
...@@ -17,7 +17,7 @@ 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: ...@@ -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;
}; };
......
/*
* 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
\ No newline at end of file
/* /*
* 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).
...@@ -8,59 +8,67 @@ ...@@ -8,59 +8,67 @@
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef ZLMEDIAKIT_G711RTMPCODEC_H #ifndef ZLMEDIAKIT_COMMONRTMP_H
#define ZLMEDIAKIT_G711RTMPCODEC_H #define ZLMEDIAKIT_COMMONRTMP_H
#include "Frame.h"
#include "Rtmp/RtmpCodec.h" #include "Rtmp/RtmpCodec.h"
#include "Extension/Track.h"
#include "Extension/G711.h"
namespace mediakit{ namespace mediakit{
/** /**
* G711 Rtmp转G711 Frame * 通用 rtmp解码
*/ */
class G711RtmpDecoder : public RtmpCodec , public ResourcePoolHelper<G711Frame> { class CommonRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<FrameImp> {
public: public:
typedef std::shared_ptr<G711RtmpDecoder> Ptr; typedef std::shared_ptr<CommonRtmpDecoder> Ptr;
~CommonRtmpDecoder() override {}
/**
* 构造函数
* @param codec 编码id
*/
CommonRtmpDecoder(CodecId codec);
G711RtmpDecoder(CodecId codecId); /**
~G711RtmpDecoder() {} * 返回编码类型ID
*/
CodecId getCodecId() const override;
/** /**
* 输入Rtmp并解码 * 输入Rtmp并解码
* @param Rtmp Rtmp数据包 * @param rtmp Rtmp数据包
* @param key_pos 此参数内部强制转换为false,请忽略之 * @param key_pos 此参数内部强制转换为false,请忽略之
*/ */
bool inputRtmp(const RtmpPacket::Ptr &Rtmp, bool key_pos = false) override; bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos = false) override;
CodecId getCodecId() const override{
return _codecId;
}
private: private:
G711Frame::Ptr obtainFrame(); void obtainFrame();
private: private:
G711Frame::Ptr _frame; CodecId _codec;
CodecId _codecId; FrameImp::Ptr _frame;
}; };
/** /**
* G711 RTMP打包 * 通用 rtmp编码
*/ */
class G711RtmpEncoder : public G711RtmpDecoder , public ResourcePoolHelper<RtmpPacket> { class CommonRtmpEncoder : public CommonRtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
public: public:
typedef std::shared_ptr<G711RtmpEncoder> Ptr; typedef std::shared_ptr<CommonRtmpEncoder> Ptr;
G711RtmpEncoder(const Track::Ptr &track); CommonRtmpEncoder(const Track::Ptr &track);
~G711RtmpEncoder() {} ~CommonRtmpEncoder() override{}
/** /**
* 输入G711 数据 * 输入数据
*/ */
void inputFrame(const Frame::Ptr &frame) override; void inputFrame(const Frame::Ptr &frame) override;
private: private:
uint8_t _audio_flv_flags = 0; uint8_t _audio_flv_flags = 0;
}; };
}//namespace mediakit }//namespace mediakit
#endif //ZLMEDIAKIT_COMMONRTMP_H
#endif //ZLMEDIAKIT_G711RTMPCODEC_H
/*
* 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;
}
}
\ No newline at end of file
/*
* 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 @@ ...@@ -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) { ...@@ -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);
} }
...@@ -114,11 +120,12 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) { ...@@ -114,11 +120,12 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
auto interleaved = sdp->getTrackType() * 2; auto interleaved = sdp->getTrackType() * 2;
auto codec_id = sdp->getCodecId(); auto codec_id = sdp->getCodecId();
switch (codec_id){ switch (codec_id){
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) { ...@@ -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;
} }
} }
...@@ -137,40 +145,35 @@ RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) { ...@@ -137,40 +145,35 @@ RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
/////////////////////////////rtmp相关/////////////////////////////////////////// /////////////////////////////rtmp相关///////////////////////////////////////////
static CodecId getVideoCodecIdByAmf(const AMFValue &val){ static CodecId getVideoCodecIdByAmf(const AMFValue &val){
if (val.type() == AMF_STRING){ if (val.type() == AMF_STRING) {
auto str = val.as_string(); auto str = val.as_string();
if(str == "avc1"){ if (str == "avc1") {
return CodecH264; return CodecH264;
} }
if(str == "mp4a"){ if (str == "hev1" || str == "hvc1") {
return CodecAAC;
}
if(str == "hev1" || str == "hvc1"){
return CodecH265; return CodecH265;
} }
WarnL << "暂不支持该Amf:" << str; WarnL << "暂不支持该视频Amf:" << str;
return CodecInvalid; return CodecInvalid;
} }
if (val.type() != AMF_NULL){ if (val.type() != AMF_NULL) {
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) { ...@@ -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) { ...@@ -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 ...@@ -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 ...@@ -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) { ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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
......
...@@ -17,47 +17,6 @@ ...@@ -17,47 +17,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音频通道
*/ */
class G711Track : public AudioTrackImp{ class G711Track : public AudioTrackImp{
......
/*
* 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
\ No newline at end of file
/*
* 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
/*
* 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: ...@@ -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: ...@@ -61,7 +61,7 @@ public:
} NaleType; } NaleType;
H265Frame(){ H265Frame(){
_codecid = CodecH265; _codec_id = CodecH265;
} }
bool keyFrame() const override { bool keyFrame() const override {
......
...@@ -17,51 +17,12 @@ ...@@ -17,51 +17,12 @@
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
......
...@@ -15,32 +15,22 @@ ...@@ -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: ...@@ -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 @@ ...@@ -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 ...@@ -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;
} }
case MOV_OBJECT_OPUS: {
auto audio = std::make_shared<OpusTrack>();
_track_to_codec.emplace(track_id, audio);
break; break;
}
default: default:
WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object);
break; break;
...@@ -196,6 +205,11 @@ public: ...@@ -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 ...@@ -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 CodecAAC : case CodecOpus:
return std::make_shared<FrameWrapper<AACFrameNoCacheAble> >(buf, pts, dts, 0); case CodecAAC:
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){ ...@@ -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获取音频相关信息
......
/* /*
* 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; ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论