Commit ad83b39b by baiyfcu Committed by GitHub

Merge pull request #3 from zlmediakit/master

update
parents 16db0034 2e95c3b2
Subproject commit fe572323b10d72819a4d69b326dd70e73c7bf1a6 Subproject commit 936d3c05b183cba279bb348f8eac9eca0cc810c2
...@@ -128,13 +128,14 @@ public: ...@@ -128,13 +128,14 @@ public:
* 一个复合帧可以通过无内存拷贝的方式切割成多个H264FrameSubFrame * 一个复合帧可以通过无内存拷贝的方式切割成多个H264FrameSubFrame
* 提供该类的目的是切换复合帧时防止内存拷贝,提高性能 * 提供该类的目的是切换复合帧时防止内存拷贝,提高性能
*/ */
class H264FrameSubFrame : public H264FrameNoCacheAble{ template<typename Parent>
class FrameInternal : public Parent{
public: public:
typedef std::shared_ptr<H264FrameSubFrame> Ptr; typedef std::shared_ptr<FrameInternal> Ptr;
H264FrameSubFrame(const Frame::Ptr &parent_frame, FrameInternal(const Frame::Ptr &parent_frame,
char *ptr, char *ptr,
uint32_t size, uint32_t size,
int prefixeSize) : H264FrameNoCacheAble(ptr,size,parent_frame->dts(),parent_frame->pts(),prefixeSize){ int prefixeSize) : Parent(ptr,size,parent_frame->dts(),parent_frame->pts(),prefixeSize){
_parent_frame = parent_frame; _parent_frame = parent_frame;
} }
bool cacheAble() const override { bool cacheAble() const override {
...@@ -144,6 +145,8 @@ private: ...@@ -144,6 +145,8 @@ private:
Frame::Ptr _parent_frame; Frame::Ptr _parent_frame;
}; };
typedef FrameInternal<H264FrameNoCacheAble> H264FrameInternal;
/** /**
* 264视频通道 * 264视频通道
*/ */
...@@ -243,21 +246,21 @@ public: ...@@ -243,21 +246,21 @@ public:
splitH264(frame->data() + frame->prefixSize(), splitH264(frame->data() + frame->prefixSize(),
frame->size() - frame->prefixSize(), frame->size() - frame->prefixSize(),
[&](const char *ptr, int len){ [&](const char *ptr, int len){
if(first_frame){ if(first_frame){
H264FrameSubFrame::Ptr sub_frame = std::make_shared<H264FrameSubFrame>(frame, H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame,
frame->data(), frame->data(),
len + frame->prefixSize(), len + frame->prefixSize(),
frame->prefixSize()); frame->prefixSize());
inputFrame_l(sub_frame); inputFrame_l(sub_frame);
first_frame = false; first_frame = false;
}else{ }else{
H264FrameSubFrame::Ptr sub_frame = std::make_shared<H264FrameSubFrame>(frame, H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame,
(char *)ptr, (char *)ptr,
len , len ,
3); 3);
inputFrame_l(sub_frame); inputFrame_l(sub_frame);
} }
}); });
} else{ } else{
inputFrame_l(frame); inputFrame_l(frame);
} }
......
...@@ -51,6 +51,8 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) { ...@@ -51,6 +51,8 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
//缓存sps pps,后续插入到I帧之前 //缓存sps pps,后续插入到I帧之前
_sps = pkt->getH264SPS(); _sps = pkt->getH264SPS();
_pps = pkt->getH264PPS(); _pps = pkt->getH264PPS();
onGetH264(_sps.data(), _sps.size(), pkt->timeStamp , pkt->timeStamp);
onGetH264(_pps.data(), _pps.size(), pkt->timeStamp , pkt->timeStamp);
return false; return false;
} }
...@@ -69,44 +71,13 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) { ...@@ -69,44 +71,13 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
if(iFrameLen + iOffset > iTotalLen){ if(iFrameLen + iOffset > iTotalLen){
break; break;
} }
onGetH264_l(pkt->strBuf.data() + iOffset, iFrameLen, pkt->timeStamp , pts); onGetH264(pkt->strBuf.data() + iOffset, iFrameLen, pkt->timeStamp , pts);
iOffset += iFrameLen; iOffset += iFrameLen;
} }
} }
return pkt->isVideoKeyFrame(); return pkt->isVideoKeyFrame();
} }
inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t dts,uint32_t pts) {
switch (H264_TYPE(pcData[0])) {
case H264Frame::NAL_IDR: {
//I frame
if(_sps.length()){
onGetH264(_sps.data(), _sps.length(), dts , pts);
}
if(_pps.length()){
onGetH264(_pps.data(), _pps.length(), dts , pts);
}
onGetH264(pcData, iLen, dts , pts);
}
break;
case H264Frame::NAL_B_P: {
//I or P or B frame
onGetH264(pcData, iLen, dts , pts);
}
break;
case H264Frame::NAL_SPS: {
_sps.assign(pcData, iLen);
}
break;
case H264Frame::NAL_PPS:{
_pps.assign(pcData, iLen);
}
break;
default:
break;
}
}
inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t dts,uint32_t pts) { inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t dts,uint32_t pts) {
#if 1 #if 1
_h264frame->type = H264_TYPE(pcData[0]); _h264frame->type = H264_TYPE(pcData[0]);
......
...@@ -60,7 +60,6 @@ public: ...@@ -60,7 +60,6 @@ public:
} }
protected: protected:
bool decodeRtmp(const RtmpPacket::Ptr &Rtmp); bool decodeRtmp(const RtmpPacket::Ptr &Rtmp);
void onGetH264_l(const char *pcData, int iLen, uint32_t dts,uint32_t pts);
void onGetH264(const char *pcData, int iLen, uint32_t dts,uint32_t pts); void onGetH264(const char *pcData, int iLen, uint32_t dts,uint32_t pts);
H264Frame::Ptr obtainFrame(); H264Frame::Ptr obtainFrame();
protected: protected:
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "Frame.h" #include "Frame.h"
#include "Track.h" #include "Track.h"
#include "Util/base64.h" #include "Util/base64.h"
#include "H264.h"
using namespace toolkit; using namespace toolkit;
#define H265_TYPE(v) (((uint8_t)(v) >> 1) & 0x3f) #define H265_TYPE(v) (((uint8_t)(v) >> 1) & 0x3f)
...@@ -147,6 +148,7 @@ public: ...@@ -147,6 +148,7 @@ public:
} }
}; };
typedef FrameInternal<H265FrameNoCacheAble> H265FrameInternal;
/** /**
* 265视频通道 * 265视频通道
...@@ -210,10 +212,37 @@ public: ...@@ -210,10 +212,37 @@ public:
/** /**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
*/
void inputFrame(const Frame::Ptr &frame) override{
bool first_frame = true;
splitH264(frame->data() + frame->prefixSize(),
frame->size() - frame->prefixSize(),
[&](const char *ptr, int len){
if(first_frame){
H265FrameInternal::Ptr sub_frame = std::make_shared<H265FrameInternal>(frame,
frame->data(),
len + frame->prefixSize(),
frame->prefixSize());
inputFrame_l(sub_frame);
first_frame = false;
}else{
H265FrameInternal::Ptr sub_frame = std::make_shared<H265FrameInternal>(frame,
(char *)ptr,
len ,
3);
inputFrame_l(sub_frame);
}
});
}
private:
/**
* 输入数据帧,并获取sps pps * 输入数据帧,并获取sps pps
* @param frame 数据帧 * @param frame 数据帧
*/ */
void inputFrame(const Frame::Ptr &frame) override { void inputFrame_l(const Frame::Ptr &frame) {
int type = H265_TYPE(((uint8_t *) frame->data() + frame->prefixSize())[0]); int type = H265_TYPE(((uint8_t *) frame->data() + frame->prefixSize())[0]);
if (H265Frame::isKeyFrame(type)) { if (H265Frame::isKeyFrame(type)) {
insertConfigFrame(frame); insertConfigFrame(frame);
...@@ -250,7 +279,7 @@ public: ...@@ -250,7 +279,7 @@ public:
break; break;
} }
} }
private:
Track::Ptr clone() override { Track::Ptr clone() override {
return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this); return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this);
} }
......
...@@ -134,7 +134,10 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) { ...@@ -134,7 +134,10 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
return 0; return 0;
} }
//默认后面数据不是content而是header //跨域
_origin = _parser["Origin"];
//默认后面数据不是content而是header
int64_t content_len = 0; int64_t content_len = 0;
auto &fun = it->second; auto &fun = it->second;
try { try {
...@@ -775,6 +778,11 @@ inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iC ...@@ -775,6 +778,11 @@ inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iC
if(iContentSize > 0){ if(iContentSize > 0){
headerOut.emplace("Content-Length", StrPrinter<<iContentSize<<endl); headerOut.emplace("Content-Length", StrPrinter<<iContentSize<<endl);
} }
if(!_origin.empty()){
headerOut.emplace("Access-Control-Allow-Origin",_origin);
headerOut.emplace("Access-Control-Allow-Credentials", "true");
}
return headerOut; return headerOut;
} }
...@@ -802,20 +810,19 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){ ...@@ -802,20 +810,19 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){
GET_CONFIG(uint32_t,reqCnt,Http::kMaxReqCount); GET_CONFIG(uint32_t,reqCnt,Http::kMaxReqCount);
bool bClose = (strcasecmp(_parser["Connection"].data(),"close") == 0) || ( ++_iReqCnt > reqCnt); bool bClose = (strcasecmp(_parser["Connection"].data(),"close") == 0) || ( ++_iReqCnt > reqCnt);
auto Origin = _parser["Origin"];
/////////////////////异步回复Invoker/////////////////////////////// /////////////////////异步回复Invoker///////////////////////////////
weak_ptr<HttpSession> weakSelf = dynamic_pointer_cast<HttpSession>(shared_from_this()); weak_ptr<HttpSession> weakSelf = dynamic_pointer_cast<HttpSession>(shared_from_this());
HttpResponseInvoker invoker = [weakSelf,bClose,Origin](const string &codeOut, const KeyValue &headerOut, const string &contentOut){ HttpResponseInvoker invoker = [weakSelf,bClose](const string &codeOut, const KeyValue &headerOut, const string &contentOut){
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
return; return;
} }
strongSelf->async([weakSelf,bClose,codeOut,headerOut,contentOut,Origin]() { strongSelf->async([weakSelf,bClose,codeOut,headerOut,contentOut]() {
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
return; return;
} }
strongSelf->responseDelay(Origin,bClose,codeOut,headerOut,contentOut); strongSelf->responseDelay(bClose,codeOut,headerOut,contentOut);
if(bClose){ if(bClose){
strongSelf->shutdown(SockException(Err_shutdown,"Connection: close")); strongSelf->shutdown(SockException(Err_shutdown,"Connection: close"));
} }
...@@ -906,19 +913,15 @@ inline void HttpSession::Handle_Req_POST(int64_t &content_len) { ...@@ -906,19 +913,15 @@ inline void HttpSession::Handle_Req_POST(int64_t &content_len) {
} }
//有后续content数据要处理,暂时不关闭连接 //有后续content数据要处理,暂时不关闭连接
} }
void HttpSession::responseDelay(const string &Origin,bool bClose, void HttpSession::responseDelay(bool bClose,
const string &codeOut,const KeyValue &headerOut, const string &codeOut,
const KeyValue &headerOut,
const string &contentOut){ const string &contentOut){
if(codeOut.empty()){ if(codeOut.empty()){
sendNotFound(bClose); sendNotFound(bClose);
return; return;
} }
auto headerOther=makeHttpHeader(bClose,contentOut.size(),"text/plain"); auto headerOther = makeHttpHeader(bClose,contentOut.size(),"text/plain");
if(!Origin.empty()){
headerOther["Access-Control-Allow-Origin"] = Origin;
headerOther["Access-Control-Allow-Credentials"] = "true";
}
for (auto &pr : headerOther){ for (auto &pr : headerOther){
//添加默认http头,默认http头不能覆盖用户自定义的头 //添加默认http头,默认http头不能覆盖用户自定义的头
const_cast<KeyValue &>(headerOut).emplace(pr.first,pr.second); const_cast<KeyValue &>(headerOut).emplace(pr.first,pr.second);
......
...@@ -111,9 +111,8 @@ private: ...@@ -111,9 +111,8 @@ private:
inline void urlDecode(Parser &parser); inline void urlDecode(Parser &parser);
inline void sendNotFound(bool bClose); inline void sendNotFound(bool bClose);
inline void sendResponse(const char *pcStatus,const KeyValue &header,const string &strContent); inline void sendResponse(const char *pcStatus,const KeyValue &header,const string &strContent);
inline static KeyValue makeHttpHeader(bool bClose=false,int64_t iContentSize=-1,const char *pcContentType="text/html"); inline KeyValue makeHttpHeader(bool bClose=false,int64_t iContentSize=-1,const char *pcContentType="text/html");
void responseDelay(const string &Origin, void responseDelay(bool bClose,
bool bClose,
const string &codeOut, const string &codeOut,
const KeyValue &headerOut, const KeyValue &headerOut,
const string &contentOut); const string &contentOut);
...@@ -139,6 +138,7 @@ private: ...@@ -139,6 +138,7 @@ private:
*/ */
inline string getClientUid(); inline string getClientUid();
private: private:
string _origin;
Parser _parser; Parser _parser;
Ticker _ticker; Ticker _ticker;
uint32_t _iReqCnt = 0; uint32_t _iReqCnt = 0;
......
...@@ -245,14 +245,9 @@ protected: ...@@ -245,14 +245,9 @@ protected:
_playResultCB = nullptr; _playResultCB = nullptr;
return; return;
} }
//播放成功后,我们还必须等待各个Track初始化完毕才能回调告知已经初始化完毕 //播放成功
if(isInited(0xFFFF)){ _playResultCB(ex);
//初始化完毕则立即回调 _playResultCB = nullptr;
_playResultCB(ex);
_playResultCB = nullptr;
return;
}
//播放成功却未初始化完毕,这个时候不回调汇报播放成功
} }
void onResume() override{ void onResume() override{
...@@ -260,16 +255,6 @@ protected: ...@@ -260,16 +255,6 @@ protected:
_resumeCB(); _resumeCB();
} }
} }
void checkInited(int analysisMs){
if(!_playResultCB){
return;
}
if(isInited(analysisMs)){
_playResultCB(SockException(Err_success,"play success"));
_playResultCB = nullptr;
}
}
protected: protected:
function<void(const SockException &ex)> _shutdownCB; function<void(const SockException &ex)> _shutdownCB;
function<void(const SockException &ex)> _playResultCB; function<void(const SockException &ex)> _playResultCB;
......
...@@ -321,7 +321,6 @@ void RtmpPlayer::onCmd_onMetaData(AMFDecoder &dec) { ...@@ -321,7 +321,6 @@ void RtmpPlayer::onCmd_onMetaData(AMFDecoder &dec) {
if(!onCheckMeta(val)){ if(!onCheckMeta(val)){
throw std::runtime_error("onCheckMeta faied"); throw std::runtime_error("onCheckMeta faied");
} }
onPlayResult_l(SockException(Err_success,"play rtmp success"));
} }
void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) { void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) {
...@@ -329,6 +328,25 @@ void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) { ...@@ -329,6 +328,25 @@ void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) {
onPlayResult_l(SockException(Err_other,"rtmp stream dry")); onPlayResult_l(SockException(Err_other,"rtmp stream dry"));
} }
void RtmpPlayer::onMediaData_l(const RtmpPacket::Ptr &packet) {
_mediaTicker.resetTime();
if(!_pPlayTimer){
//已经触发了onPlayResult事件,直接触发onMediaData事件
onMediaData(packet);
return;
}
if(packet->isCfgFrame()){
//输入配置帧以便初始化完成各个track
onMediaData(packet);
}else{
//先触发onPlayResult事件,这个时候解码器才能初始化完毕
onPlayResult_l(SockException(Err_success,"play rtmp success"));
//触发onPlayResult事件后,再把帧数据输入到解码器
onMediaData(packet);
}
}
void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) { void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
switch (chunkData.typeId) { switch (chunkData.typeId) {
...@@ -351,6 +369,7 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) { ...@@ -351,6 +369,7 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
case MSG_VIDEO: { case MSG_VIDEO: {
auto idx = chunkData.typeId%2; auto idx = chunkData.typeId%2;
if (_aNowStampTicker[idx].elapsedTime() > 500) { if (_aNowStampTicker[idx].elapsedTime() > 500) {
//计算播放进度时间轴用
_aiNowStamp[idx] = chunkData.timeStamp; _aiNowStamp[idx] = chunkData.timeStamp;
} }
onMediaData_l(std::make_shared<RtmpPacket>(std::move(chunkData))); onMediaData_l(std::make_shared<RtmpPacket>(std::move(chunkData)));
......
...@@ -60,11 +60,7 @@ protected: ...@@ -60,11 +60,7 @@ protected:
uint32_t getProgressMilliSecond() const; uint32_t getProgressMilliSecond() const;
void seekToMilliSecond(uint32_t ms); void seekToMilliSecond(uint32_t ms);
protected: protected:
void onMediaData_l(const RtmpPacket::Ptr &chunkData) { void onMediaData_l(const RtmpPacket::Ptr &chunkData);
_mediaTicker.resetTime();
onMediaData(chunkData);
}
void onPlayResult_l(const SockException &ex); void onPlayResult_l(const SockException &ex);
//for Tcpclient //for Tcpclient
...@@ -97,7 +93,7 @@ protected: ...@@ -97,7 +93,7 @@ protected:
inline void send_createStream(); inline void send_createStream();
inline void send_play(); inline void send_play();
inline void send_pause(bool bPause); inline void send_pause(bool bPause);
private:
string _strApp; string _strApp;
string _strStream; string _strStream;
string _strTcUrl; string _strTcUrl;
......
...@@ -58,7 +58,6 @@ public: ...@@ -58,7 +58,6 @@ public:
seekToMilliSecond(fProgress * getDuration() * 1000); seekToMilliSecond(fProgress * getDuration() * 1000);
}; };
void play(const string &strUrl) override { void play(const string &strUrl) override {
_analysisMs = (*this)[kMaxAnalysisMS].as<int>();
PlayerImp<RtmpPlayer,RtmpDemuxer>::play(strUrl); PlayerImp<RtmpPlayer,RtmpDemuxer>::play(strUrl);
} }
private: private:
...@@ -76,16 +75,13 @@ private: ...@@ -76,16 +75,13 @@ private:
_pRtmpMediaSrc->onWrite(chunkData); _pRtmpMediaSrc->onWrite(chunkData);
} }
if(!_parser){ if(!_parser){
//这个流没有metedata,那么尝试在音视频包里面还原出相关信息 //这个流没有metedata
_parser.reset(new RtmpDemuxer()); _parser.reset(new RtmpDemuxer());
onPlayResult_l(SockException(Err_success,"play rtmp success"));
} }
_parser->inputRtmp(chunkData); _parser->inputRtmp(chunkData);
checkInited(_analysisMs);
} }
private: private:
RtmpMediaSource::Ptr _pRtmpMediaSrc; RtmpMediaSource::Ptr _pRtmpMediaSrc;
int _analysisMs;
}; };
......
...@@ -39,9 +39,9 @@ using namespace std; ...@@ -39,9 +39,9 @@ using namespace std;
using namespace toolkit; using namespace toolkit;
using namespace mediakit; using namespace mediakit;
std::string Utf8ToGbk(std::string src_str)
{
#ifdef WIN32 #ifdef WIN32
std::string Utf8ToGbk(std::string src_str){
int len = MultiByteToWideChar(CP_UTF8, 0, src_str.c_str(), -1, NULL, 0); int len = MultiByteToWideChar(CP_UTF8, 0, src_str.c_str(), -1, NULL, 0);
wchar_t* wszGBK = new wchar_t[len + 1]; wchar_t* wszGBK = new wchar_t[len + 1];
memset(wszGBK, 0, len * 2 + 2); memset(wszGBK, 0, len * 2 + 2);
...@@ -54,9 +54,6 @@ std::string Utf8ToGbk(std::string src_str) ...@@ -54,9 +54,6 @@ std::string Utf8ToGbk(std::string src_str)
if (wszGBK) delete[] wszGBK; if (wszGBK) delete[] wszGBK;
if (szGBK) delete[] szGBK; if (szGBK) delete[] szGBK;
return strTemp; return strTemp;
#else
return src_str;
#endif
} }
class log4Channel : public LogChannel { class log4Channel : public LogChannel {
...@@ -75,6 +72,9 @@ public: ...@@ -75,6 +72,9 @@ public:
printf("%s %s\n", logContext->_function, Utf8ToGbk(logContext->str()).c_str()); printf("%s %s\n", logContext->_function, Utf8ToGbk(logContext->str()).c_str());
} }
}; };
#else
typedef ConsoleChannel log4Channel;
#endif
#ifdef WIN32 #ifdef WIN32
#include <TCHAR.h> #include <TCHAR.h>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论