完善对无metadata的rtmp流的兼容性

This commit is contained in:
xiongziliang 2020-05-28 17:03:12 +08:00
parent e7f263b046
commit 41509800bc
10 changed files with 88 additions and 87 deletions

View File

@ -221,13 +221,27 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int
return getTrackByCodecId(codecId, sample_rate, channels, sample_bit);
}
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode) {
switch (track->getCodecId()){
case CodecH264 : return std::make_shared<H264RtmpEncoder>(track);
case CodecAAC : return std::make_shared<AACRtmpEncoder>(track);
case CodecH265 : return std::make_shared<H265RtmpEncoder>(track);
case CodecG711A :
case CodecG711U : return std::make_shared<G711RtmpEncoder>(track);
case CodecG711U : {
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
if (is_encode && (audio_track->getAudioSampleRate() != 8000 ||
audio_track->getAudioChannel() != 1 ||
audio_track->getAudioSampleBit() != 16)) {
//rtmp对g711只支持8000/1/16规格但是ZLMediaKit可以解析其他规格的G711
WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:"
<< audio_track->getAudioSampleRate() << "/"
<< audio_track->getAudioChannel() << "/"
<< audio_track->getAudioSampleBit()
<< ",该音频已被忽略";
return nullptr;
}
return std::make_shared<G711RtmpEncoder>(track);
}
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
}
}

View File

@ -59,8 +59,9 @@ public:
/**
* Track获取Rtmp的编解码器
* @param track
* @param is_encode
*/
static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track);
static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode);
/**
* codecId获取rtmp的codec描述

View File

@ -100,4 +100,23 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track){
}
void Metadata::addTrack(AMFValue &metadata, const Track::Ptr &track) {
Metadata::Ptr new_metadata;
switch (track->getTrackType()) {
case TrackVideo: {
new_metadata = std::make_shared<VideoMeta>(dynamic_pointer_cast<VideoTrack>(track));
}
break;
case TrackAudio: {
new_metadata = std::make_shared<AudioMeta>(dynamic_pointer_cast<AudioTrack>(track));
}
break;
default:
return;
}
new_metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value) {
metadata.set(key, value);
});
}
}//namespace mediakit

View File

@ -220,6 +220,8 @@ public:
const AMFValue &getMetadata() const{
return _metadata;
}
static void addTrack(AMFValue &metadata, const Track::Ptr &track);
protected:
AMFValue _metadata;
};
@ -261,7 +263,6 @@ private:
CodecId _codecId;
};
class AudioMeta : public Metadata{
public:
typedef std::shared_ptr<AudioMeta> Ptr;

View File

@ -13,60 +13,56 @@
namespace mediakit {
void RtmpDemuxer::loadMetaData(const AMFValue &val){
bool RtmpDemuxer::loadMetaData(const AMFValue &val){
bool ret = false;
try {
int audiosamplerate = 0;
int audiochannels = 0;
int audiosamplesize = 0;
const AMFValue *audiocodecid = nullptr;
const AMFValue *videocodecid = nullptr;
val.object_for_each([&](const string &key, const AMFValue &val) {
if (key == "duration") {
_fDuration = val.as_number();
return;
}
if(key == "audiosamplerate"){
if (key == "audiosamplerate") {
audiosamplerate = val.as_integer();
return;
}
if(key == "audiosamplesize"){
if (key == "audiosamplesize") {
audiosamplesize = val.as_integer();
return;
}
if(key == "stereo"){
if (key == "stereo") {
audiochannels = val.as_boolean() ? 2 : 1;
return;
}
if(key == "videocodecid"){
if (key == "videocodecid") {
//找到视频
videocodecid = &val;
return;
}
if(key == "audiocodecid"){
if (key == "audiocodecid") {
//找到音频
audiocodecid = &val;
return;
}
});
if(videocodecid){
if (videocodecid) {
//有视频
ret = true;
makeVideoTrack(*videocodecid);
}
if(audiocodecid){
if (audiocodecid) {
//有音频
ret = true;
makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize);
}
}catch (std::exception &ex){
} catch (std::exception &ex) {
WarnL << ex.what();
}
return ret;
}
bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
@ -105,7 +101,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
_videoTrack = dynamic_pointer_cast<VideoTrack>(Factory::getVideoTrackByAmf(videoCodec));
if (_videoTrack) {
//生成rtmpCodec对象以便解码rtmp
_videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack);
_videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack, false);
if (_videoRtmpDecoder) {
//设置rtmp解码器代理生成的frame写入该Track
_videoRtmpDecoder->addDelegate(_videoTrack);
@ -123,7 +119,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit));
if (_audioTrack) {
//生成rtmpCodec对象以便解码rtmp
_audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack);
_audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack, false);
if (_audioRtmpDecoder) {
//设置rtmp解码器代理生成的frame写入该Track
_audioRtmpDecoder->addDelegate(_audioTrack);

View File

@ -30,7 +30,7 @@ public:
RtmpDemuxer() = default;
virtual ~RtmpDemuxer() = default;
void loadMetaData(const AMFValue &metadata);
bool loadMetaData(const AMFValue &metadata);
/**
*

View File

@ -49,9 +49,14 @@ public:
* metadata
*/
void setMetaData(const AMFValue &metadata) override{
_demuxer->loadMetaData(metadata);
if(!_demuxer->loadMetaData(metadata)){
//该metadata无效需要重新生成
_metadata = metadata;
_recreate_metadata = true;
}else{
RtmpMediaSource::setMetaData(metadata);
}
}
/**
* rtmp并解析
@ -138,6 +143,11 @@ public:
_muxer->addTrack(track);
track->addDelegate(_muxer);
}
if(_recreate_metadata){
//需要重新生成metadata
Metadata::addTrack(_metadata,track);
}
}
/**
@ -146,11 +156,19 @@ public:
void onAllTrackReady() override{
setTrackSource(_muxer);
_all_track_ready = true;
if(_recreate_metadata){
//需要重新生成metadata
RtmpMediaSource::setMetaData(_metadata);
}
}
private:
RtmpDemuxer::Ptr _demuxer;
MultiMediaSourceMuxer::Ptr _muxer;
AMFValue _metadata;
bool _all_track_ready = false;
bool _recreate_metadata = false;
};
} /* namespace mediakit */

View File

@ -23,47 +23,9 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
}
void RtmpMuxer::addTrack(const Track::Ptr &track) {
//根据track生产metadata
Metadata::Ptr metadata;
switch (track->getTrackType()){
case TrackVideo:{
metadata = std::make_shared<VideoMeta>(dynamic_pointer_cast<VideoTrack>(track));
}
break;
case TrackAudio:{
metadata = std::make_shared<AudioMeta>(dynamic_pointer_cast<AudioTrack>(track));
}
break;
default:
return;
}
switch (track->getCodecId()){
case CodecG711A:
case CodecG711U:{
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
if(!audio_track){
return;
}
if (audio_track->getAudioSampleRate() != 8000 ||
audio_track->getAudioChannel() != 1 ||
audio_track->getAudioSampleBit() != 16) {
WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:"
<< audio_track->getAudioSampleRate() << "/"
<< audio_track->getAudioChannel() << "/"
<< audio_track->getAudioSampleBit()
<< ",该音频已被忽略";
return;
}
break;
}
default : break;
}
auto &encoder = _encoder[track->getTrackType()];
//生成rtmp编码器,克隆该Track防止循环引用
encoder = Factory::getRtmpCodecByTrack(track->clone());
encoder = Factory::getRtmpCodecByTrack(track->clone(), true);
if (!encoder) {
return;
}
@ -71,10 +33,8 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) {
//设置rtmp输出环形缓存
encoder->setRtmpRing(_rtmpRing);
//添加其metadata
metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value){
_metadata.set(key,value);
});
//添加metadata
Metadata::addTrack(_metadata,track);
}
void RtmpMuxer::inputFrame(const Frame::Ptr &frame) {

View File

@ -44,6 +44,7 @@ inline void AMFValue::destroy() {
break;
}
}
inline void AMFValue::init() {
switch (_type) {
case AMF_OBJECT:
@ -60,14 +61,13 @@ inline void AMFValue::init() {
default:
break;
}
}
AMFValue::AMFValue(AMFType type) :
_type(type) {
init();
}
AMFValue::~AMFValue() {
destroy();
}
@ -78,7 +78,6 @@ AMFValue::AMFValue(const char *s) :
*_value.string = s;
}
AMFValue::AMFValue(const std::string &s) :
_type(AMF_STRING) {
init();
@ -108,15 +107,7 @@ AMFValue::AMFValue(const AMFValue &from) :
*this = from;
}
AMFValue::AMFValue(AMFValue &&from) {
*this = std::forward<AMFValue>(from);
}
AMFValue& AMFValue::operator =(const AMFValue &from) {
return *this = const_cast<AMFValue &&>(from);
}
AMFValue& AMFValue::operator =(AMFValue &&from) {
AMFValue& AMFValue::operator = (const AMFValue &from) {
destroy();
_type = from._type;
init();
@ -144,7 +135,6 @@ AMFValue& AMFValue::operator =(AMFValue &&from) {
break;
}
return *this;
}
void AMFValue::clear() {
@ -236,7 +226,6 @@ string AMFValue::to_string() const{
}
}
const AMFValue& AMFValue::operator[](const char *str) const {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object");
@ -338,6 +327,7 @@ AMFEncoder & AMFEncoder::operator <<(const char *s) {
}
return *this;
}
AMFEncoder & AMFEncoder::operator <<(const std::string &s) {
if (!s.empty()) {
buf += char(AMF0_STRING);
@ -349,18 +339,22 @@ AMFEncoder & AMFEncoder::operator <<(const std::string &s) {
}
return *this;
}
AMFEncoder & AMFEncoder::operator <<(std::nullptr_t) {
buf += char(AMF0_NULL);
return *this;
}
AMFEncoder & AMFEncoder::write_undefined() {
buf += char(AMF0_UNDEFINED);
return *this;
}
AMFEncoder & AMFEncoder::operator <<(const int n){
return (*this) << (double)n;
}
AMFEncoder & AMFEncoder::operator <<(const double n) {
buf += char(AMF0_NUMBER);
uint64_t encoded = 0;

View File

@ -40,6 +40,7 @@ public:
typedef std::map<std::string, AMFValue> mapType;
typedef std::vector<AMFValue> arrayType;
~AMFValue();
AMFValue(AMFType type = AMF_NULL);
AMFValue(const char *s);
AMFValue(const std::string &s);
@ -47,10 +48,7 @@ public:
AMFValue(int i);
AMFValue(bool b);
AMFValue(const AMFValue &from);
AMFValue(AMFValue &&from);
AMFValue &operator =(const AMFValue &from);
AMFValue &operator =(AMFValue &&from);
~AMFValue();
AMFValue &operator = (const AMFValue &from);
void clear();
AMFType type() const ;