mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-06 03:28:09 +08:00
整理优化代码
This commit is contained in:
237
src/Rtmp/FlvMuxer.cpp
Normal file
237
src/Rtmp/FlvMuxer.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "FlvMuxer.h"
|
||||
#include "Util/File.h"
|
||||
#include "Rtmp/utils.h"
|
||||
|
||||
#define FILE_BUF_SIZE (64 * 1024)
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
|
||||
FlvMuxer::FlvMuxer() {
|
||||
}
|
||||
FlvMuxer::~FlvMuxer() {
|
||||
}
|
||||
|
||||
void FlvMuxer::start(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &media) {
|
||||
if(!media){
|
||||
throw std::runtime_error("RtmpMediaSource 无效");
|
||||
}
|
||||
if(!poller->isCurrentThread()){
|
||||
weak_ptr<FlvMuxer> weakSelf = getSharedPtr();
|
||||
//延时两秒启动录制,目的是为了等待config帧收集完毕
|
||||
poller->doDelayTask(2000,[weakSelf,poller,media](){
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(strongSelf){
|
||||
strongSelf->start(poller,media);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
onWriteFlvHeader(media);
|
||||
|
||||
std::weak_ptr<FlvMuxer> weakSelf = getSharedPtr();
|
||||
_ring_reader = media->getRing()->attach(poller);
|
||||
_ring_reader->setDetachCB([weakSelf](){
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
strongSelf->onDetach();
|
||||
});
|
||||
_ring_reader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt){
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
strongSelf->onWriteRtmp(pkt);
|
||||
});
|
||||
}
|
||||
|
||||
void FlvMuxer::onWriteFlvHeader(const RtmpMediaSource::Ptr &mediaSrc) {
|
||||
CLEAR_ARR(_aui32FirstStamp);
|
||||
|
||||
//发送flv文件头
|
||||
char flv_file_header[] = "FLV\x1\x5\x0\x0\x0\x9"; // have audio and have video
|
||||
bool is_have_audio = false,is_have_video = false;
|
||||
|
||||
mediaSrc->getConfigFrame([&](const RtmpPacket::Ptr &pkt){
|
||||
if(pkt->typeId == MSG_VIDEO){
|
||||
is_have_video = true;
|
||||
}
|
||||
if(pkt->typeId == MSG_AUDIO){
|
||||
is_have_audio = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (is_have_audio && is_have_video) {
|
||||
flv_file_header[4] = 0x05;
|
||||
} else if (is_have_audio && !is_have_video) {
|
||||
flv_file_header[4] = 0x04;
|
||||
} else if (!is_have_audio && is_have_video) {
|
||||
flv_file_header[4] = 0x01;
|
||||
} else {
|
||||
flv_file_header[4] = 0x00;
|
||||
}
|
||||
|
||||
//flv header
|
||||
onWrite(std::make_shared<BufferRaw>(flv_file_header, sizeof(flv_file_header) - 1));
|
||||
|
||||
auto size = htonl(0);
|
||||
//PreviousTagSize0 Always 0
|
||||
onWrite(std::make_shared<BufferRaw>((char *)&size,4));
|
||||
|
||||
//metadata
|
||||
AMFEncoder invoke;
|
||||
invoke << "onMetaData" << mediaSrc->getMetaData();
|
||||
onWriteFlvTag(MSG_DATA, std::make_shared<BufferString>(invoke.data()), 0);
|
||||
|
||||
//config frame
|
||||
mediaSrc->getConfigFrame([&](const RtmpPacket::Ptr &pkt){
|
||||
onWriteRtmp(pkt);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(push, 1)
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
class RtmpTagHeader {
|
||||
public:
|
||||
uint8_t type = 0;
|
||||
uint8_t data_size[3] = {0};
|
||||
uint8_t timestamp[3] = {0};
|
||||
uint8_t timestamp_ex = 0;
|
||||
uint8_t streamid[3] = {0}; /* Always 0. */
|
||||
}PACKED;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(pop)
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
void FlvMuxer::onWriteFlvTag(const RtmpPacket::Ptr &pkt, uint32_t ui32TimeStamp) {
|
||||
onWriteFlvTag(pkt->typeId,pkt,ui32TimeStamp);
|
||||
}
|
||||
|
||||
void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const Buffer::Ptr &buffer, uint32_t ui32TimeStamp) {
|
||||
RtmpTagHeader header;
|
||||
header.type = ui8Type;
|
||||
set_be24(header.data_size, buffer->size());
|
||||
header.timestamp_ex = (uint8_t) ((ui32TimeStamp >> 24) & 0xff);
|
||||
set_be24(header.timestamp,ui32TimeStamp & 0xFFFFFF);
|
||||
//tag header
|
||||
onWrite(std::make_shared<BufferRaw>((char *)&header, sizeof(header)));
|
||||
//tag data
|
||||
onWrite(buffer);
|
||||
auto size = htonl((buffer->size() + sizeof(header)));
|
||||
//PreviousTagSize
|
||||
onWrite(std::make_shared<BufferRaw>((char *)&size,4));
|
||||
}
|
||||
|
||||
void FlvMuxer::onWriteRtmp(const RtmpPacket::Ptr &pkt) {
|
||||
auto modifiedStamp = pkt->timeStamp;
|
||||
auto &firstStamp = _aui32FirstStamp[pkt->typeId % 2];
|
||||
if(!firstStamp){
|
||||
firstStamp = modifiedStamp;
|
||||
}
|
||||
if(modifiedStamp >= firstStamp){
|
||||
//计算时间戳增量
|
||||
modifiedStamp -= firstStamp;
|
||||
}else{
|
||||
//发生回环,重新计算时间戳增量
|
||||
CLEAR_ARR(_aui32FirstStamp);
|
||||
modifiedStamp = 0;
|
||||
}
|
||||
onWriteFlvTag(pkt, modifiedStamp);
|
||||
}
|
||||
|
||||
void FlvMuxer::stop() {
|
||||
if(_ring_reader){
|
||||
_ring_reader.reset();
|
||||
onDetach();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////FlvRecorder/////////////////////////////////////////////////////
|
||||
void FlvRecorder::startRecord(const EventPoller::Ptr &poller,const string &vhost, const string &app, const string &stream,const string &file_path) {
|
||||
startRecord(poller,dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,vhost,app,stream,false)),file_path);
|
||||
}
|
||||
|
||||
void FlvRecorder::startRecord(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &media, const string &file_path) {
|
||||
stop();
|
||||
lock_guard<recursive_mutex> lck(_file_mtx);
|
||||
//开辟文件写缓存
|
||||
std::shared_ptr<char> fileBuf(new char[FILE_BUF_SIZE],[](char *ptr){
|
||||
if(ptr){
|
||||
delete [] ptr;
|
||||
}
|
||||
});
|
||||
//新建文件
|
||||
_file.reset(File::createfile_file(file_path.data(),"wb"),[fileBuf](FILE *fp){
|
||||
if(fp){
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
});
|
||||
if (!_file){
|
||||
throw std::runtime_error( StrPrinter << "打开文件失败:" << file_path);
|
||||
}
|
||||
|
||||
//设置文件写缓存
|
||||
setvbuf( _file.get(), fileBuf.get(),_IOFBF, FILE_BUF_SIZE);
|
||||
start(poller,media);
|
||||
}
|
||||
|
||||
void FlvRecorder::onWrite(const Buffer::Ptr &data) {
|
||||
lock_guard<recursive_mutex> lck(_file_mtx);
|
||||
if(_file){
|
||||
fwrite(data->data(),data->size(),1,_file.get());
|
||||
}
|
||||
}
|
||||
|
||||
void FlvRecorder::onDetach() {
|
||||
lock_guard<recursive_mutex> lck(_file_mtx);
|
||||
_file.reset();
|
||||
}
|
||||
|
||||
std::shared_ptr<FlvMuxer> FlvRecorder::getSharedPtr() {
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FlvRecorder::FlvRecorder() {
|
||||
}
|
||||
|
||||
FlvRecorder::~FlvRecorder() {
|
||||
}
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
78
src/Rtmp/FlvMuxer.h
Normal file
78
src/Rtmp/FlvMuxer.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ZLMEDIAKIT_FLVMUXER_H
|
||||
#define ZLMEDIAKIT_FLVMUXER_H
|
||||
|
||||
#include "Rtmp/Rtmp.h"
|
||||
#include "Rtmp/RtmpMediaSource.h"
|
||||
#include "Network/Socket.h"
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class FlvMuxer{
|
||||
public:
|
||||
typedef std::shared_ptr<FlvMuxer> Ptr;
|
||||
FlvMuxer();
|
||||
virtual ~FlvMuxer();
|
||||
void stop();
|
||||
protected:
|
||||
void start(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &media);
|
||||
virtual void onWrite(const Buffer::Ptr &data) = 0;
|
||||
virtual void onDetach() = 0;
|
||||
virtual std::shared_ptr<FlvMuxer> getSharedPtr() = 0;
|
||||
private:
|
||||
void onWriteFlvHeader(const RtmpMediaSource::Ptr &media);
|
||||
void onWriteRtmp(const RtmpPacket::Ptr &pkt);
|
||||
void onWriteFlvTag(const RtmpPacket::Ptr &pkt, uint32_t ui32TimeStamp);
|
||||
void onWriteFlvTag(uint8_t ui8Type, const Buffer::Ptr &buffer, uint32_t ui32TimeStamp);
|
||||
private:
|
||||
RtmpMediaSource::RingType::RingReader::Ptr _ring_reader;
|
||||
uint32_t _aui32FirstStamp[2] = {0};
|
||||
|
||||
};
|
||||
|
||||
class FlvRecorder : public FlvMuxer , public std::enable_shared_from_this<FlvRecorder>{
|
||||
public:
|
||||
typedef std::shared_ptr<FlvRecorder> Ptr;
|
||||
FlvRecorder();
|
||||
virtual ~FlvRecorder();
|
||||
void startRecord(const EventPoller::Ptr &poller,const string &vhost,const string &app,const string &stream,const string &file_path);
|
||||
void startRecord(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &media,const string &file_path);
|
||||
private:
|
||||
virtual void onWrite(const Buffer::Ptr &data) override ;
|
||||
virtual void onDetach() override;
|
||||
virtual std::shared_ptr<FlvMuxer> getSharedPtr() override;
|
||||
private:
|
||||
std::shared_ptr<FILE> _file;
|
||||
recursive_mutex _file_mtx;
|
||||
};
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_FLVMUXER_H
|
||||
103
src/Rtmp/RtmpCodec.h
Normal file
103
src/Rtmp/RtmpCodec.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ZLMEDIAKIT_RTMPCODEC_H
|
||||
#define ZLMEDIAKIT_RTMPCODEC_H
|
||||
|
||||
#include "Rtmp/Rtmp.h"
|
||||
#include "Extension/Frame.h"
|
||||
#include "Util/RingBuffer.h"
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
class RtmpRingInterface {
|
||||
public:
|
||||
typedef RingBuffer<RtmpPacket::Ptr> RingType;
|
||||
typedef std::shared_ptr<RtmpRingInterface> Ptr;
|
||||
|
||||
RtmpRingInterface(){}
|
||||
virtual ~RtmpRingInterface(){}
|
||||
|
||||
/**
|
||||
* 获取rtmp环形缓存
|
||||
* @return
|
||||
*/
|
||||
virtual RingType::Ptr getRtmpRing() const = 0;
|
||||
|
||||
/**
|
||||
* 设置rtmp环形缓存
|
||||
* @param ring
|
||||
*/
|
||||
virtual void setRtmpRing(const RingType::Ptr &ring) = 0;
|
||||
|
||||
/**
|
||||
* 输入rtmp包
|
||||
* @param rtmp rtmp包
|
||||
* @param key_pos 是否为关键帧
|
||||
* @return 是否为关键帧
|
||||
*/
|
||||
virtual bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) = 0;
|
||||
};
|
||||
|
||||
class RtmpRing : public RtmpRingInterface {
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpRing> Ptr;
|
||||
|
||||
RtmpRing(){
|
||||
}
|
||||
virtual ~RtmpRing(){}
|
||||
|
||||
RingType::Ptr getRtmpRing() const override {
|
||||
return _rtmpRing;
|
||||
}
|
||||
|
||||
void setRtmpRing(const RingType::Ptr &ring) override {
|
||||
_rtmpRing = ring;
|
||||
}
|
||||
|
||||
bool inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) override{
|
||||
if(_rtmpRing){
|
||||
_rtmpRing->write(rtmp,key_pos);
|
||||
}
|
||||
return key_pos;
|
||||
}
|
||||
protected:
|
||||
RingType::Ptr _rtmpRing;
|
||||
};
|
||||
|
||||
|
||||
class RtmpCodec : public RtmpRing, public FrameRingInterfaceDelegate , public CodecInfo{
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpCodec> Ptr;
|
||||
RtmpCodec(){}
|
||||
virtual ~RtmpCodec(){}
|
||||
};
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#endif //ZLMEDIAKIT_RTMPCODEC_H
|
||||
116
src/Rtmp/RtmpDemuxer.cpp
Normal file
116
src/Rtmp/RtmpDemuxer.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "RtmpDemuxer.h"
|
||||
#include "Extension/Factory.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
|
||||
RtmpDemuxer::RtmpDemuxer(const AMFValue &val) {
|
||||
try {
|
||||
makeVideoTrack(val["videocodecid"]);
|
||||
makeAudioTrack(val["audiocodecid"]);
|
||||
val.object_for_each([&](const string &key, const AMFValue &val) {
|
||||
if (key == "duration") {
|
||||
_fDuration = val.as_number();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}catch (std::exception &ex){
|
||||
WarnL << ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
int RtmpDemuxer::getTrackCount(const AMFValue &metedata) {
|
||||
return (int)(metedata["videocodecid"].type() != AMF_NULL) + (int)(metedata["audiocodecid"].type() != AMF_NULL);
|
||||
}
|
||||
|
||||
bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
|
||||
switch (pkt->typeId) {
|
||||
case MSG_VIDEO: {
|
||||
if(!_tryedGetVideoTrack){
|
||||
_tryedGetVideoTrack = true;
|
||||
auto codec = AMFValue(pkt->getMediaType());
|
||||
makeVideoTrack(codec);
|
||||
}
|
||||
if(_videoRtmpDecoder){
|
||||
return _videoRtmpDecoder->inputRtmp(pkt, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
case MSG_AUDIO: {
|
||||
if(!_tryedGetAudioTrack) {
|
||||
_tryedGetAudioTrack = true;
|
||||
auto codec = AMFValue(pkt->getMediaType());
|
||||
makeAudioTrack(codec);
|
||||
}
|
||||
if(_audioRtmpDecoder){
|
||||
_audioRtmpDecoder->inputRtmp(pkt, false);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
|
||||
//生成Track对象
|
||||
_videoTrack = dynamic_pointer_cast<VideoTrack>(Factory::getTrackByAmf(videoCodec));
|
||||
if (_videoTrack) {
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack);
|
||||
if (_videoRtmpDecoder) {
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_videoRtmpDecoder->addDelegate(_videoTrack);
|
||||
} else {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_videoTrack.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec) {
|
||||
//生成Track对象
|
||||
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getTrackByAmf(audioCodec));
|
||||
if (_audioTrack) {
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack);
|
||||
if (_audioRtmpDecoder) {
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_audioRtmpDecoder->addDelegate(_audioTrack);
|
||||
} else {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_audioTrack.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} /* namespace mediakit */
|
||||
84
src/Rtmp/RtmpDemuxer.h
Normal file
84
src/Rtmp/RtmpDemuxer.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRC_RTMP_RTMPDEMUXER_H_
|
||||
#define SRC_RTMP_RTMPDEMUXER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include "Rtmp/amf.h"
|
||||
#include "Rtmp/Rtmp.h"
|
||||
#include "Player/PlayerBase.h"
|
||||
#include "Util/TimeTicker.h"
|
||||
#include "RtmpCodec.h"
|
||||
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class RtmpDemuxer : public Demuxer{
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpDemuxer> Ptr;
|
||||
|
||||
/**
|
||||
* 等效于RtmpDemuxer(AMFValue(AMF_NULL))
|
||||
*/
|
||||
RtmpDemuxer(){}
|
||||
/**
|
||||
* 构造rtmp解复用器
|
||||
* @param val rtmp的metedata,可以传入null类型,
|
||||
* 这样就会在inputRtmp时异步探测媒体编码格式
|
||||
*/
|
||||
RtmpDemuxer(const AMFValue &val);
|
||||
virtual ~RtmpDemuxer(){};
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取rtmp track 数
|
||||
* @param metedata rtmp的metedata
|
||||
* @return
|
||||
*/
|
||||
static int getTrackCount(const AMFValue &metedata);
|
||||
|
||||
/**
|
||||
* 开始解复用
|
||||
* @param pkt rtmp包
|
||||
* @return true 代表是i帧
|
||||
*/
|
||||
bool inputRtmp(const RtmpPacket::Ptr &pkt);
|
||||
private:
|
||||
void makeVideoTrack(const AMFValue &val);
|
||||
void makeAudioTrack(const AMFValue &val);
|
||||
private:
|
||||
bool _tryedGetVideoTrack = false;
|
||||
bool _tryedGetAudioTrack = false;
|
||||
RtmpCodec::Ptr _audioRtmpDecoder;
|
||||
RtmpCodec::Ptr _videoRtmpDecoder;
|
||||
};
|
||||
|
||||
} /* namespace mediakit */
|
||||
|
||||
#endif /* SRC_RTMP_RTMPDEMUXER_H_ */
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <unordered_map>
|
||||
#include "amf.h"
|
||||
#include "Rtmp.h"
|
||||
#include "RtmpMuxer/RtmpDemuxer.h"
|
||||
#include "RtmpDemuxer.h"
|
||||
#include "Common/config.h"
|
||||
#include "Common/MediaSource.h"
|
||||
#include "Util/util.h"
|
||||
|
||||
64
src/Rtmp/RtmpMediaSourceMuxer.h
Normal file
64
src/Rtmp/RtmpMediaSourceMuxer.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ZLMEDIAKIT_RTMPMEDIASOURCEMUXER_H
|
||||
#define ZLMEDIAKIT_RTMPMEDIASOURCEMUXER_H
|
||||
|
||||
#include "RtmpMuxer.h"
|
||||
#include "Rtmp/RtmpMediaSource.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class RtmpMediaSourceMuxer : public RtmpMuxer {
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpMediaSourceMuxer> Ptr;
|
||||
|
||||
RtmpMediaSourceMuxer(const string &vhost,
|
||||
const string &strApp,
|
||||
const string &strId,
|
||||
const TitleMete::Ptr &title = nullptr) : RtmpMuxer(title){
|
||||
_mediaSouce = std::make_shared<RtmpMediaSource>(vhost,strApp,strId);
|
||||
getRtmpRing()->setDelegate(_mediaSouce);
|
||||
}
|
||||
virtual ~RtmpMediaSourceMuxer(){}
|
||||
|
||||
void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
|
||||
_mediaSouce->setListener(listener);
|
||||
}
|
||||
int readerCount() const{
|
||||
return _mediaSouce->readerCount();
|
||||
}
|
||||
private:
|
||||
void onAllTrackReady() override {
|
||||
_mediaSouce->onGetMetaData(getMetedata());
|
||||
}
|
||||
private:
|
||||
RtmpMediaSource::Ptr _mediaSouce;
|
||||
};
|
||||
|
||||
|
||||
}//namespace mediakit
|
||||
#endif //ZLMEDIAKIT_RTMPMEDIASOURCEMUXER_H
|
||||
87
src/Rtmp/RtmpMuxer.cpp
Normal file
87
src/Rtmp/RtmpMuxer.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "RtmpMuxer.h"
|
||||
#include "Extension/Factory.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
RtmpMuxer::RtmpMuxer(const TitleMete::Ptr &title) {
|
||||
if(!title){
|
||||
_metedata = std::make_shared<TitleMete>()->getMetedata();
|
||||
}else{
|
||||
_metedata = title->getMetedata();
|
||||
}
|
||||
_rtmpRing = std::make_shared<RtmpRingInterface::RingType>();
|
||||
}
|
||||
|
||||
void RtmpMuxer::onTrackReady(const Track::Ptr &track) {
|
||||
//生成rtmp编码器
|
||||
//克隆该Track,防止循环引用
|
||||
auto encoder = Factory::getRtmpCodecByTrack(track->clone());
|
||||
if (!encoder) {
|
||||
return;
|
||||
}
|
||||
//根据track生产metedata
|
||||
Metedata::Ptr metedate;
|
||||
switch (track->getTrackType()){
|
||||
case TrackVideo:{
|
||||
metedate = std::make_shared<VideoMete>(dynamic_pointer_cast<VideoTrack>(track));
|
||||
}
|
||||
break;
|
||||
case TrackAudio:{
|
||||
metedate = std::make_shared<AudioMete>(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);
|
||||
});
|
||||
//设置Track的代理,这样输入frame至Track时,最终数据将输出到RtmpEncoder中
|
||||
track->addDelegate(encoder);
|
||||
//Rtmp编码器共用同一个环形缓存
|
||||
encoder->setRtmpRing(_rtmpRing);
|
||||
}
|
||||
|
||||
|
||||
const AMFValue &RtmpMuxer::getMetedata() const {
|
||||
if(!isAllTrackReady()){
|
||||
//尚未就绪
|
||||
static AMFValue s_amf;
|
||||
return s_amf;
|
||||
}
|
||||
return _metedata;
|
||||
}
|
||||
|
||||
RtmpRingInterface::RingType::Ptr RtmpMuxer::getRtmpRing() const {
|
||||
return _rtmpRing;
|
||||
}
|
||||
|
||||
}/* namespace mediakit */
|
||||
73
src/Rtmp/RtmpMuxer.h
Normal file
73
src/Rtmp/RtmpMuxer.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ZLMEDIAKIT_RTMPMUXER_H
|
||||
#define ZLMEDIAKIT_RTMPMUXER_H
|
||||
|
||||
#include "Rtmp/Rtmp.h"
|
||||
#include "Extension/Frame.h"
|
||||
#include "Common/MediaSink.h"
|
||||
#include "RtmpCodec.h"
|
||||
|
||||
namespace mediakit{
|
||||
|
||||
class RtmpMuxer : public MediaSink{
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpMuxer> Ptr;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
RtmpMuxer(const TitleMete::Ptr &title);
|
||||
virtual ~RtmpMuxer(){}
|
||||
|
||||
/**
|
||||
* 获取完整的SDP字符串
|
||||
* @return SDP字符串
|
||||
*/
|
||||
const AMFValue &getMetedata() const ;
|
||||
|
||||
/**
|
||||
* 获取rtmp环形缓存
|
||||
* @return
|
||||
*/
|
||||
RtmpRingInterface::RingType::Ptr getRtmpRing() const;
|
||||
protected:
|
||||
/**
|
||||
* 某track已经准备好,其ready()状态返回true,
|
||||
* 此时代表可以获取其例如sps pps等相关信息了
|
||||
* @param track
|
||||
*/
|
||||
void onTrackReady(const Track::Ptr & track) override ;
|
||||
private:
|
||||
RtmpRingInterface::RingType::Ptr _rtmpRing;
|
||||
AMFValue _metedata;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace mediakit */
|
||||
|
||||
#endif //ZLMEDIAKIT_RTMPMUXER_H
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "Common/config.h"
|
||||
#include "RtmpPlayer.h"
|
||||
#include "RtmpMediaSource.h"
|
||||
#include "RtmpMuxer/RtmpDemuxer.h"
|
||||
#include "RtmpDemuxer.h"
|
||||
#include "Poller/Timer.h"
|
||||
#include "Util/TimeTicker.h"
|
||||
using namespace toolkit;
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#include "amf.h"
|
||||
#include "Rtmp.h"
|
||||
#include "RtmpMediaSource.h"
|
||||
#include "RtmpMuxer/RtmpDemuxer.h"
|
||||
#include "RtmpDemuxer.h"
|
||||
#include "MediaFile/MediaRecorder.h"
|
||||
#include "RtspMuxer/RtspMediaSourceMuxer.h"
|
||||
#include "Rtsp/RtspMediaSourceMuxer.h"
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user