mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-23 03:10:04 +08:00
修正metadata拼写错误,优化RtmpMediaSource注册机制,修复及时拉流不出画面的bug
This commit is contained in:
parent
8ae9f56110
commit
cb7c72d9d9
@ -45,7 +45,7 @@ public:
|
||||
bool bEnableMp4 = false
|
||||
){
|
||||
if (bEanbleRtmp) {
|
||||
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, strApp, strId, std::make_shared<TitleMete>(dur_sec));
|
||||
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, strApp, strId, std::make_shared<TitleMeta>(dur_sec));
|
||||
}
|
||||
if (bEanbleRtsp) {
|
||||
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, strApp, strId, std::make_shared<TitleSdp>(dur_sec));
|
||||
|
@ -197,7 +197,7 @@ CodecId Factory::getCodecIdByAmf(const AMFValue &val){
|
||||
return CodecInvalid;
|
||||
}
|
||||
}else{
|
||||
WarnL << "Metedata不存在相应的Track";
|
||||
WarnL << "Metadata不存在相应的Track";
|
||||
}
|
||||
|
||||
return CodecInvalid;
|
||||
|
@ -73,14 +73,14 @@ public:
|
||||
|
||||
/**
|
||||
* 根据amf对象获取响应的Track
|
||||
* @param amf rtmp metedata中的videocodecid或audiocodecid的值
|
||||
* @param amf rtmp metadata中的videocodecid或audiocodecid的值
|
||||
* @return
|
||||
*/
|
||||
static Track::Ptr getTrackByAmf(const AMFValue &amf);
|
||||
|
||||
/**
|
||||
* 根据amf对象获取相应的CodecId
|
||||
* @param val rtmp metedata中的videocodecid或audiocodecid的值
|
||||
* @param val rtmp metadata中的videocodecid或audiocodecid的值
|
||||
* @return
|
||||
*/
|
||||
static CodecId getCodecIdByAmf(const AMFValue &val);
|
||||
|
@ -27,35 +27,35 @@
|
||||
#include "Extension/Factory.h"
|
||||
namespace mediakit{
|
||||
|
||||
VideoMete::VideoMete(const VideoTrack::Ptr &video,int datarate ){
|
||||
VideoMeta::VideoMeta(const VideoTrack::Ptr &video,int datarate ){
|
||||
if(video->getVideoWidth() > 0 ){
|
||||
_metedata.set("width", video->getVideoWidth());
|
||||
_metadata.set("width", video->getVideoWidth());
|
||||
}
|
||||
if(video->getVideoHeight() > 0 ){
|
||||
_metedata.set("height", video->getVideoHeight());
|
||||
_metadata.set("height", video->getVideoHeight());
|
||||
}
|
||||
if(video->getVideoFps() > 0 ){
|
||||
_metedata.set("framerate", video->getVideoFps());
|
||||
_metadata.set("framerate", video->getVideoFps());
|
||||
}
|
||||
_metedata.set("videodatarate", datarate);
|
||||
_metadata.set("videodatarate", datarate);
|
||||
_codecId = video->getCodecId();
|
||||
_metedata.set("videocodecid", Factory::getAmfByCodecId(_codecId));
|
||||
_metadata.set("videocodecid", Factory::getAmfByCodecId(_codecId));
|
||||
}
|
||||
|
||||
AudioMete::AudioMete(const AudioTrack::Ptr &audio,int datarate){
|
||||
_metedata.set("audiodatarate", datarate);
|
||||
AudioMeta::AudioMeta(const AudioTrack::Ptr &audio,int datarate){
|
||||
_metadata.set("audiodatarate", datarate);
|
||||
if(audio->getAudioSampleRate() > 0){
|
||||
_metedata.set("audiosamplerate", audio->getAudioSampleRate());
|
||||
_metadata.set("audiosamplerate", audio->getAudioSampleRate());
|
||||
}
|
||||
if(audio->getAudioSampleBit() > 0){
|
||||
_metedata.set("audiosamplesize", audio->getAudioSampleBit());
|
||||
_metadata.set("audiosamplesize", audio->getAudioSampleBit());
|
||||
}
|
||||
if(audio->getAudioChannel() > 0){
|
||||
_metedata.set("audiochannels", audio->getAudioChannel());
|
||||
_metedata.set("stereo", audio->getAudioChannel() > 1);
|
||||
_metadata.set("audiochannels", audio->getAudioChannel());
|
||||
_metadata.set("stereo", audio->getAudioChannel() > 1);
|
||||
}
|
||||
_codecId = audio->getCodecId();
|
||||
_metedata.set("audiocodecid", Factory::getAmfByCodecId(_codecId));
|
||||
_metadata.set("audiocodecid", Factory::getAmfByCodecId(_codecId));
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
@ -298,36 +298,36 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* rtmp metedata基类,用于描述rtmp格式信息
|
||||
* rtmp metadata基类,用于描述rtmp格式信息
|
||||
*/
|
||||
class Metedata : public CodecInfo{
|
||||
class Metadata : public CodecInfo{
|
||||
public:
|
||||
typedef std::shared_ptr<Metedata> Ptr;
|
||||
typedef std::shared_ptr<Metadata> Ptr;
|
||||
|
||||
Metedata():_metedata(AMF_OBJECT){}
|
||||
virtual ~Metedata(){}
|
||||
const AMFValue &getMetedata() const{
|
||||
return _metedata;
|
||||
Metadata():_metadata(AMF_OBJECT){}
|
||||
virtual ~Metadata(){}
|
||||
const AMFValue &getMetadata() const{
|
||||
return _metadata;
|
||||
}
|
||||
protected:
|
||||
AMFValue _metedata;
|
||||
AMFValue _metadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* metedata中除音视频外的其他描述部分
|
||||
* metadata中除音视频外的其他描述部分
|
||||
*/
|
||||
class TitleMete : public Metedata{
|
||||
class TitleMeta : public Metadata{
|
||||
public:
|
||||
typedef std::shared_ptr<TitleMete> Ptr;
|
||||
typedef std::shared_ptr<TitleMeta> Ptr;
|
||||
|
||||
TitleMete(float dur_sec = 0,
|
||||
TitleMeta(float dur_sec = 0,
|
||||
uint64_t fileSize = 0,
|
||||
const map<string,string> &header = map<string,string>()){
|
||||
_metedata.set("duration", dur_sec);
|
||||
_metedata.set("fileSize", 0);
|
||||
_metedata.set("server","ZLMediaKit");
|
||||
_metadata.set("duration", dur_sec);
|
||||
_metadata.set("fileSize", 0);
|
||||
_metadata.set("server","ZLMediaKit");
|
||||
for (auto &pr : header){
|
||||
_metedata.set(pr.first, pr.second);
|
||||
_metadata.set(pr.first, pr.second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,12 +348,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class VideoMete : public Metedata{
|
||||
class VideoMeta : public Metadata{
|
||||
public:
|
||||
typedef std::shared_ptr<VideoMete> Ptr;
|
||||
typedef std::shared_ptr<VideoMeta> Ptr;
|
||||
|
||||
VideoMete(const VideoTrack::Ptr &video,int datarate = 5000);
|
||||
virtual ~VideoMete(){}
|
||||
VideoMeta(const VideoTrack::Ptr &video,int datarate = 5000);
|
||||
virtual ~VideoMeta(){}
|
||||
|
||||
/**
|
||||
* 返回音频或视频类型
|
||||
@ -375,13 +375,13 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class AudioMete : public Metedata{
|
||||
class AudioMeta : public Metadata{
|
||||
public:
|
||||
typedef std::shared_ptr<AudioMete> Ptr;
|
||||
typedef std::shared_ptr<AudioMeta> Ptr;
|
||||
|
||||
AudioMete(const AudioTrack::Ptr &audio,int datarate = 160);
|
||||
AudioMeta(const AudioTrack::Ptr &audio,int datarate = 160);
|
||||
|
||||
virtual ~AudioMete(){}
|
||||
virtual ~AudioMeta(){}
|
||||
|
||||
/**
|
||||
* 返回音频或视频类型
|
||||
|
@ -45,8 +45,8 @@ RtmpDemuxer::RtmpDemuxer(const AMFValue &val) {
|
||||
}
|
||||
}
|
||||
|
||||
int RtmpDemuxer::getTrackCount(const AMFValue &metedata) {
|
||||
return (int)(metedata["videocodecid"].type() != AMF_NULL) + (int)(metedata["audiocodecid"].type() != AMF_NULL);
|
||||
int RtmpDemuxer::getTrackCount(const AMFValue &metadata) {
|
||||
return (int)(metadata["videocodecid"].type() != AMF_NULL) + (int)(metadata["audiocodecid"].type() != AMF_NULL);
|
||||
}
|
||||
|
||||
bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
RtmpDemuxer(){}
|
||||
/**
|
||||
* 构造rtmp解复用器
|
||||
* @param val rtmp的metedata,可以传入null类型,
|
||||
* @param val rtmp的metadata,可以传入null类型,
|
||||
* 这样就会在inputRtmp时异步探测媒体编码格式
|
||||
*/
|
||||
RtmpDemuxer(const AMFValue &val);
|
||||
@ -58,10 +58,10 @@ public:
|
||||
/**
|
||||
*
|
||||
* 获取rtmp track 数
|
||||
* @param metedata rtmp的metedata
|
||||
* @param metadata rtmp的metadata
|
||||
* @return
|
||||
*/
|
||||
static int getTrackCount(const AMFValue &metedata);
|
||||
static int getTrackCount(const AMFValue &metadata);
|
||||
|
||||
/**
|
||||
* 开始解复用
|
||||
|
@ -86,6 +86,9 @@ public:
|
||||
virtual void onGetMetaData(const AMFValue &metadata) {
|
||||
lock_guard<recursive_mutex> lock(_mtxMap);
|
||||
_metadata = metadata;
|
||||
if(_pRing){
|
||||
regist();
|
||||
}
|
||||
}
|
||||
|
||||
void onWrite(const RtmpPacket::Ptr &pkt,bool isKey = true) override {
|
||||
@ -107,8 +110,10 @@ public:
|
||||
strongSelf->onReaderChanged(size);
|
||||
});
|
||||
onReaderChanged(0);
|
||||
if(_metadata){
|
||||
regist();
|
||||
}
|
||||
}
|
||||
_pRing->write(pkt,pkt->isVideoKeyFrame());
|
||||
checkNoneReader();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
RtmpMediaSourceMuxer(const string &vhost,
|
||||
const string &strApp,
|
||||
const string &strId,
|
||||
const TitleMete::Ptr &title = nullptr) : RtmpMuxer(title){
|
||||
const TitleMeta::Ptr &title = nullptr) : RtmpMuxer(title){
|
||||
_mediaSouce = std::make_shared<RtmpMediaSource>(vhost,strApp,strId);
|
||||
getRtmpRing()->setDelegate(_mediaSouce);
|
||||
}
|
||||
@ -53,7 +53,7 @@ public:
|
||||
}
|
||||
private:
|
||||
void onAllTrackReady() override {
|
||||
_mediaSouce->onGetMetaData(getMetedata());
|
||||
_mediaSouce->onGetMetaData(getMetadata());
|
||||
}
|
||||
private:
|
||||
RtmpMediaSource::Ptr _mediaSouce;
|
||||
|
@ -29,11 +29,11 @@
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
RtmpMuxer::RtmpMuxer(const TitleMete::Ptr &title) {
|
||||
RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
|
||||
if(!title){
|
||||
_metedata = std::make_shared<TitleMete>()->getMetedata();
|
||||
_metadata = std::make_shared<TitleMeta>()->getMetadata();
|
||||
}else{
|
||||
_metedata = title->getMetedata();
|
||||
_metadata = title->getMetadata();
|
||||
}
|
||||
_rtmpRing = std::make_shared<RtmpRingInterface::RingType>();
|
||||
}
|
||||
@ -45,24 +45,24 @@ void RtmpMuxer::onTrackReady(const Track::Ptr &track) {
|
||||
if (!encoder) {
|
||||
return;
|
||||
}
|
||||
//根据track生产metedata
|
||||
Metedata::Ptr metedate;
|
||||
//根据track生产metadata
|
||||
Metadata::Ptr metadata;
|
||||
switch (track->getTrackType()){
|
||||
case TrackVideo:{
|
||||
metedate = std::make_shared<VideoMete>(dynamic_pointer_cast<VideoTrack>(track));
|
||||
metadata = std::make_shared<VideoMeta>(dynamic_pointer_cast<VideoTrack>(track));
|
||||
}
|
||||
break;
|
||||
case TrackAudio:{
|
||||
metedate = std::make_shared<AudioMete>(dynamic_pointer_cast<AudioTrack>(track));
|
||||
metadata = std::make_shared<AudioMeta>(dynamic_pointer_cast<AudioTrack>(track));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;;
|
||||
|
||||
}
|
||||
//添加其metedata
|
||||
metedate->getMetedata().object_for_each([&](const std::string &key, const AMFValue &value){
|
||||
_metedata.set(key,value);
|
||||
//添加其metadata
|
||||
metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value){
|
||||
_metadata.set(key,value);
|
||||
});
|
||||
//设置Track的代理,这样输入frame至Track时,最终数据将输出到RtmpEncoder中
|
||||
track->addDelegate(encoder);
|
||||
@ -71,13 +71,13 @@ void RtmpMuxer::onTrackReady(const Track::Ptr &track) {
|
||||
}
|
||||
|
||||
|
||||
const AMFValue &RtmpMuxer::getMetedata() const {
|
||||
const AMFValue &RtmpMuxer::getMetadata() const {
|
||||
if(!isAllTrackReady()){
|
||||
//尚未就绪
|
||||
static AMFValue s_amf;
|
||||
return s_amf;
|
||||
}
|
||||
return _metedata;
|
||||
return _metadata;
|
||||
}
|
||||
|
||||
RtmpRingInterface::RingType::Ptr RtmpMuxer::getRtmpRing() const {
|
||||
|
@ -41,14 +41,14 @@ public:
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
RtmpMuxer(const TitleMete::Ptr &title);
|
||||
RtmpMuxer(const TitleMeta::Ptr &title);
|
||||
virtual ~RtmpMuxer(){}
|
||||
|
||||
/**
|
||||
* 获取完整的SDP字符串
|
||||
* @return SDP字符串
|
||||
*/
|
||||
const AMFValue &getMetedata() const ;
|
||||
const AMFValue &getMetadata() const ;
|
||||
|
||||
/**
|
||||
* 获取rtmp环形缓存
|
||||
@ -64,7 +64,7 @@ protected:
|
||||
void onTrackReady(const Track::Ptr & track) override ;
|
||||
private:
|
||||
RtmpRingInterface::RingType::Ptr _rtmpRing;
|
||||
AMFValue _metedata;
|
||||
AMFValue _metadata;
|
||||
};
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ private:
|
||||
_pRtmpMediaSrc->onWrite(chunkData);
|
||||
}
|
||||
if(!_parser){
|
||||
//这个流没有metedata
|
||||
//这个流没有metadata
|
||||
_parser.reset(new RtmpDemuxer());
|
||||
}
|
||||
_parser->inputRtmp(chunkData);
|
||||
|
@ -431,6 +431,7 @@ void RtmpSession::setMetaData(AMFDecoder &dec) {
|
||||
}
|
||||
auto metadata = dec.load<AMFValue>();
|
||||
//dumpMetadata(metadata);
|
||||
_metadata_got = true;
|
||||
_pPublisherSrc->onGetMetaData(metadata);
|
||||
}
|
||||
|
||||
@ -488,6 +489,11 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
|
||||
_stamp[chunkData.typeId % 2].revise(0, 0, dts_out, dts_out);
|
||||
chunkData.timeStamp = dts_out;
|
||||
}
|
||||
if(!_metadata_got){
|
||||
//有些rtmp推流客户端不产生metadata,我们产生一个默认的metadata,目的是为了触发注册操作
|
||||
_metadata_got = true;
|
||||
_pPublisherSrc->onGetMetaData(TitleMeta().getMetadata());
|
||||
}
|
||||
_pPublisherSrc->onWrite(std::make_shared<RtmpPacket>(std::move(chunkData)));
|
||||
}
|
||||
break;
|
||||
@ -553,7 +559,7 @@ void RtmpSession::setSocketFlags(){
|
||||
|
||||
void RtmpSession::dumpMetadata(const AMFValue &metadata) {
|
||||
if(metadata.type() != AMF_OBJECT && metadata.type() != AMF_ECMA_ARRAY){
|
||||
WarnL << "invalid metedata type:" << metadata.type();
|
||||
WarnL << "invalid metadata type:" << metadata.type();
|
||||
return ;
|
||||
}
|
||||
_StrPrinter printer;
|
||||
|
@ -87,8 +87,9 @@ private:
|
||||
void onNoneReader(MediaSource &sender) override;
|
||||
void setSocketFlags();
|
||||
string getStreamId(const string &str);
|
||||
void dumpMetadata(const AMFValue &metedata);
|
||||
void dumpMetadata(const AMFValue &metadata);
|
||||
private:
|
||||
bool _metadata_got = false;
|
||||
std::string _strTcUrl;
|
||||
MediaInfo _mediaInfo;
|
||||
double _dNowReqID = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user