mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-03 08:57:32 +08:00
初始提交
This commit is contained in:
256
src/Device/Device.cpp
Normal file
256
src/Device/Device.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Device.cpp
|
||||
*
|
||||
* Created on: 2016年8月10日
|
||||
* Author: xzl
|
||||
*/
|
||||
|
||||
#include "Device.h"
|
||||
#include "Util/logger.h"
|
||||
#include <stdio.h>
|
||||
#include "Util/util.h"
|
||||
#include <cstdio>
|
||||
#include "base64.h"
|
||||
|
||||
#include "Util/TimeTicker.h"
|
||||
using namespace ZL::Util;
|
||||
|
||||
namespace ZL {
|
||||
namespace DEV {
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef ENABLE_RTSP2RTMP
|
||||
DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) :
|
||||
m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId , bLiveStream)) {
|
||||
#else
|
||||
DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) :
|
||||
m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId )) {
|
||||
#endif //ENABLE_RTSP2RTMP
|
||||
m_strSDP = "v=0\r\n";
|
||||
m_strSDP += "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
|
||||
m_strSDP += "s=RTSP Session, streamed by the ZL\r\n";
|
||||
m_strSDP += "i=ZL Live Stream\r\n";
|
||||
m_strSDP += "c=IN IP4 0.0.0.0\r\n";
|
||||
m_strSDP += "t=0 0\r\n";
|
||||
//直播,时间长度永远
|
||||
if(fDuration <= 0 || bLiveStream){
|
||||
m_strSDP += "a=range:npt=0-\r\n";
|
||||
}else{
|
||||
m_strSDP += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl;
|
||||
}
|
||||
m_strSDP += "a=control:*\r\n";
|
||||
}
|
||||
DevChannel::~DevChannel() {
|
||||
}
|
||||
|
||||
void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
|
||||
//TimeTicker1(50);
|
||||
#ifdef ENABLE_X264
|
||||
if (!m_pH264Enc) {
|
||||
m_pH264Enc.reset(new H264Encoder());
|
||||
if (!m_pH264Enc->init(m_video->iWidth, m_video->iHeight, m_video->iFrameRate)) {
|
||||
m_pH264Enc.reset();
|
||||
WarnL << "H264Encoder init failed!";
|
||||
}
|
||||
}
|
||||
if (m_pH264Enc) {
|
||||
H264Encoder::H264Frame *pOut;
|
||||
int iFrames = m_pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
|
||||
for (int i = 0; i < iFrames; i++) {
|
||||
inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
ErrorL << "libx264 was not enabled!";
|
||||
#endif //ENABLE_X264
|
||||
}
|
||||
|
||||
void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
|
||||
#ifdef ENABLE_FAAC
|
||||
if (!m_pAacEnc) {
|
||||
m_pAacEnc.reset(new AACEncoder());
|
||||
if (!m_pAacEnc->init(m_audio->iSampleRate, m_audio->iChannel, m_audio->iSampleBit)) {
|
||||
m_pAacEnc.reset();
|
||||
WarnL << "AACEncoder init failed!";
|
||||
}
|
||||
}
|
||||
if (m_pAacEnc) {
|
||||
unsigned char *pucOut;
|
||||
int iRet = m_pAacEnc->inputData(pcData, iDataLen, &pucOut);
|
||||
if (iRet > 0) {
|
||||
inputAAC((char *) pucOut, iRet, uiStamp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
ErrorL << "libfaac was not enabled!";
|
||||
#endif //ENABLE_FAAC
|
||||
}
|
||||
|
||||
void DevChannel::inputH264(char* pcData, int iDataLen, uint32_t uiStamp) {
|
||||
if (!m_pRtpMaker_h264) {
|
||||
uint32_t ui32Ssrc;
|
||||
memcpy(&ui32Ssrc, makeRandStr(4, false).data(), 4);
|
||||
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
|
||||
m_mediaSrc->onGetRTP(pkt,bKeyPos);
|
||||
};
|
||||
static uint32_t videoMtu = mINI::Instance()[Config::Rtp::kVideoMtuSize].as<uint32_t>();
|
||||
m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
|
||||
}
|
||||
if (!m_bSdp_gotH264 && m_video) {
|
||||
makeSDP_264((unsigned char*) pcData, iDataLen);
|
||||
}
|
||||
int iOffset = 4;
|
||||
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
|
||||
iOffset = 3;
|
||||
}
|
||||
m_pRtpMaker_h264->makeRtp(pcData + iOffset, iDataLen - iOffset, uiStamp);
|
||||
}
|
||||
|
||||
void DevChannel::inputAAC(char* pcData, int iDataLen, uint32_t uiStamp) {
|
||||
if (!m_pRtpMaker_aac) {
|
||||
uint32_t ssrc;
|
||||
memcpy(&ssrc, makeRandStr(8, false).data() + 4, 4);
|
||||
auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) {
|
||||
m_mediaSrc->onGetRTP(pkt,keyPos);
|
||||
};
|
||||
static uint32_t audioMtu = mINI::Instance()[Config::Rtp::kAudioMtuSize].as<uint32_t>();
|
||||
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate));
|
||||
}
|
||||
if (!m_bSdp_gotAAC && m_audio) {
|
||||
makeSDP_AAC((unsigned char*) pcData, iDataLen);
|
||||
}
|
||||
m_pRtpMaker_aac->makeRtp(pcData + 7, iDataLen - 7, uiStamp);
|
||||
|
||||
}
|
||||
|
||||
inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) {
|
||||
int offset = 4;
|
||||
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
|
||||
offset = 3;
|
||||
}
|
||||
switch (pcData[offset] & 0x1F) {
|
||||
case 7:/*SPS frame*/
|
||||
{
|
||||
if (m_uiSPSLen != 0) {
|
||||
break;
|
||||
}
|
||||
memcpy(m_aucSPS, pcData + offset, iDataLen - offset);
|
||||
m_uiSPSLen = iDataLen - offset;
|
||||
}
|
||||
break;
|
||||
case 8:/*PPS frame*/
|
||||
{
|
||||
if (m_uiPPSLen != 0) {
|
||||
break;
|
||||
}
|
||||
memcpy(m_aucPPS, pcData + offset, iDataLen - offset);
|
||||
m_uiPPSLen = iDataLen - offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!m_uiSPSLen || !m_uiPPSLen) {
|
||||
return;
|
||||
}
|
||||
|
||||
char acTmp[256];
|
||||
int profile_level_id = 0;
|
||||
if (m_uiSPSLen >= 4) { // sanity check
|
||||
profile_level_id = (m_aucSPS[1] << 16) | (m_aucSPS[2] << 8) | m_aucSPS[3]; // profile_idc|constraint_setN_flag|level_idc
|
||||
}
|
||||
|
||||
//视频通道
|
||||
m_strSDP += StrPrinter << "m=video 0 RTP/AVP "
|
||||
<< m_pRtpMaker_h264->getPlayloadType() << "\r\n" << endl;
|
||||
m_strSDP += "b=AS:5100\r\n";
|
||||
m_strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_h264->getPlayloadType()
|
||||
<< " H264/" << m_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
|
||||
m_strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_h264->getPlayloadType()
|
||||
<< " packetization-mode=1;profile-level-id=" << endl;
|
||||
|
||||
memset(acTmp, 0, sizeof(acTmp));
|
||||
sprintf(acTmp, "%06X", profile_level_id);
|
||||
m_strSDP += acTmp;
|
||||
m_strSDP += ";sprop-parameter-sets=";
|
||||
memset(acTmp, 0, sizeof(acTmp));
|
||||
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucSPS, m_uiSPSLen);
|
||||
//WarnL<<"SPS base64:"<<strTemp;
|
||||
//WarnL<<"SPS hexdump:"<<hexdump(SPS_BUF, SPS_LEN);
|
||||
m_strSDP += acTmp;
|
||||
m_strSDP += ",";
|
||||
memset(acTmp, 0, sizeof(acTmp));
|
||||
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucPPS, m_uiPPSLen);
|
||||
m_strSDP += acTmp;
|
||||
m_strSDP += "\r\n";
|
||||
if (m_video->iFrameRate > 0 && m_video->iHeight > 0 && m_video->iWidth > 0) {
|
||||
m_strSDP += "a=framerate:";
|
||||
m_strSDP += StrPrinter << m_video->iFrameRate << endl;
|
||||
m_strSDP += StrPrinter << "\r\na=framesize:"
|
||||
<< m_pRtpMaker_h264->getPlayloadType() << " " << endl;
|
||||
m_strSDP += StrPrinter << m_video->iWidth << endl;
|
||||
m_strSDP += "-";
|
||||
m_strSDP += StrPrinter << m_video->iHeight << endl;
|
||||
m_strSDP += "\r\n";
|
||||
}
|
||||
m_strSDP += StrPrinter << "a=control:trackID="
|
||||
<< m_pRtpMaker_h264->getInterleaved() / 2 << "\r\n" << endl;
|
||||
m_bSdp_gotH264 = true;
|
||||
if (m_audio) {
|
||||
if (m_bSdp_gotAAC) {
|
||||
makeSDP(m_strSDP);
|
||||
}
|
||||
} else {
|
||||
makeSDP(m_strSDP);
|
||||
}
|
||||
}
|
||||
|
||||
inline void DevChannel::makeSDP_AAC(unsigned char *fixedHeader, int dataLen) {
|
||||
auto audioSpecificConfig = makeAdtsConfig(fixedHeader);
|
||||
if (audioSpecificConfig.size() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
char fConfigStr[5] = { 0 };
|
||||
sprintf(fConfigStr, "%02X%02x", (uint8_t)audioSpecificConfig[0],(uint8_t)audioSpecificConfig[1]);
|
||||
|
||||
m_strSDP += StrPrinter << "m=audio 0 RTP/AVP "
|
||||
<< m_pRtpMaker_aac->getPlayloadType() << "\r\n" << endl;
|
||||
m_strSDP += "b=AS:96\r\n";
|
||||
m_strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType()
|
||||
<< " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n"
|
||||
<< endl;
|
||||
m_strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType()
|
||||
<< " streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
|
||||
<< endl;
|
||||
m_strSDP += fConfigStr;
|
||||
m_strSDP += "\r\n";
|
||||
m_strSDP += StrPrinter << "a=control:trackID="
|
||||
<< m_pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl;
|
||||
|
||||
m_bSdp_gotAAC = true;
|
||||
if (m_video) {
|
||||
if (m_bSdp_gotH264) {
|
||||
makeSDP(m_strSDP);
|
||||
}
|
||||
} else {
|
||||
makeSDP(m_strSDP);
|
||||
}
|
||||
}
|
||||
|
||||
void DevChannel::makeSDP(const string& strSdp) {
|
||||
m_mediaSrc->onGetSDP(strSdp);
|
||||
m_mediaSrc->regist();
|
||||
}
|
||||
|
||||
void DevChannel::initVideo(const VideoInfo& info) {
|
||||
m_video.reset(new VideoInfo(info));
|
||||
}
|
||||
|
||||
void DevChannel::initAudio(const AudioInfo& info) {
|
||||
m_audio.reset(new AudioInfo(info));
|
||||
}
|
||||
} /* namespace DEV */
|
||||
} /* namespace ZL */
|
||||
|
||||
108
src/Device/Device.h
Normal file
108
src/Device/Device.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Device.h
|
||||
*
|
||||
* Created on: 2016年8月10日
|
||||
* Author: xzl
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_DEVICE_H_
|
||||
#define DEVICE_DEVICE_H_
|
||||
#include <sys/time.h>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "Util/util.h"
|
||||
#include "RTP/RtpMakerAAC.h"
|
||||
#include "RTP/RtpMakerH264.h"
|
||||
#include "Rtsp/RtspToRtmpMediaSource.h"
|
||||
using namespace std;
|
||||
using namespace ZL::Rtsp;
|
||||
using namespace ZL::Util;
|
||||
|
||||
#ifdef ENABLE_FAAC
|
||||
#include "Codec/AACEncoder.h"
|
||||
using namespace ZL::Codec;
|
||||
#endif //ENABLE_FAAC
|
||||
|
||||
#ifdef ENABLE_X264
|
||||
#include "Codec/H264Encoder.h"
|
||||
using namespace ZL::Codec;
|
||||
#endif //ENABLE_X264
|
||||
|
||||
using namespace ZL::Rtsp;
|
||||
namespace ZL {
|
||||
namespace DEV {
|
||||
|
||||
class VideoInfo {
|
||||
public:
|
||||
int iWidth;
|
||||
int iHeight;
|
||||
float iFrameRate;
|
||||
};
|
||||
class AudioInfo {
|
||||
public:
|
||||
int iChannel;
|
||||
int iSampleBit;
|
||||
int iSampleRate;
|
||||
};
|
||||
|
||||
|
||||
class DevChannel {
|
||||
public:
|
||||
typedef std::shared_ptr<DevChannel> Ptr;
|
||||
DevChannel(const char *strApp, const char *strId,float fDuration = 0,bool bLiveStream = true);
|
||||
virtual ~DevChannel();
|
||||
|
||||
void initVideo(const VideoInfo &info);
|
||||
void initAudio(const AudioInfo &info);
|
||||
|
||||
void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp);
|
||||
void inputPCM(char *pcData, int iDataLen, uint32_t uiStamp);
|
||||
|
||||
void inputH264(char *pcData, int iDataLen, uint32_t uiStamp);
|
||||
void inputAAC(char *pcData, int iDataLen, uint32_t uiStamp);
|
||||
#ifdef ENABLE_RTSP2RTMP
|
||||
int readerCount() {
|
||||
return m_mediaSrc ? m_mediaSrc->readerCount() : 0;
|
||||
}
|
||||
void updateTimeStamp(uint32_t uiStamp){
|
||||
m_mediaSrc->updateTimeStamp(uiStamp);
|
||||
}
|
||||
#endif //ENABLE_RTSP2RTMP
|
||||
void setOnSeek(const function<bool(uint32_t)> &onSeek){
|
||||
m_mediaSrc->setOnSeek(onSeek);
|
||||
}
|
||||
void setOnStamp(const function<uint32_t()> &cb) {
|
||||
m_mediaSrc->setOnStamp(cb);
|
||||
}
|
||||
private:
|
||||
inline void makeSDP_264(unsigned char *pucData, int iDataLen);
|
||||
inline void makeSDP_AAC(unsigned char *pucData, int iDataLen);
|
||||
inline void makeSDP(const string& strSdp);
|
||||
#ifdef ENABLE_X264
|
||||
std::shared_ptr<H264Encoder> m_pH264Enc;
|
||||
#endif //ENABLE_X264
|
||||
|
||||
#ifdef ENABLE_FAAC
|
||||
std::shared_ptr<AACEncoder> m_pAacEnc;
|
||||
#endif //ENABLE_FAAC
|
||||
RtpMaker_AAC::Ptr m_pRtpMaker_aac;
|
||||
RtpMaker_H264::Ptr m_pRtpMaker_h264;
|
||||
RtspToRtmpMediaSource::Ptr m_mediaSrc;
|
||||
string m_strSDP;
|
||||
bool m_bSdp_gotH264 = false;
|
||||
bool m_bSdp_gotAAC = false;
|
||||
|
||||
unsigned char m_aucSPS[256];
|
||||
unsigned int m_uiSPSLen = 0;
|
||||
unsigned char m_aucPPS[256];
|
||||
unsigned int m_uiPPSLen = 0;
|
||||
std::shared_ptr<VideoInfo> m_video;
|
||||
std::shared_ptr<AudioInfo> m_audio;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace DEV */
|
||||
} /* namespace ZL */
|
||||
|
||||
#endif /* DEVICE_DEVICE_H_ */
|
||||
153
src/Device/PlayerProxy.cpp
Normal file
153
src/Device/PlayerProxy.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* PlyerProxy.cpp
|
||||
*
|
||||
* Created on: 2016年12月6日
|
||||
* Author: xzl
|
||||
*/
|
||||
|
||||
#include "PlayerProxy.h"
|
||||
#include "Thread/AsyncTaskThread.h"
|
||||
#include "Util/MD5.h"
|
||||
#include "Util/logger.h"
|
||||
#include "config.h"
|
||||
#include "Util/mini.hpp"
|
||||
|
||||
using namespace ZL::Util;
|
||||
using namespace ZL::Thread;
|
||||
|
||||
namespace ZL {
|
||||
namespace DEV {
|
||||
|
||||
PlayerProxy::PlayerProxy(const char *strApp,const char *strSrc){
|
||||
m_strApp = strApp;
|
||||
m_strSrc = strSrc;
|
||||
}
|
||||
|
||||
void PlayerProxy::play(const char* strUrl, const char *strUser,
|
||||
const char *strPwd, PlayerBase::eRtpType eType, uint32_t iSecond) {
|
||||
m_aliveSecond = iSecond;
|
||||
string strUrlTmp(strUrl);
|
||||
string strUserTmp(strUser);
|
||||
string strPwdTmp(strPwd);
|
||||
|
||||
m_pPlayer.reset(new MediaPlayer());
|
||||
m_pPlayer->play(strUrl, strUser, strPwd, eType);
|
||||
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
|
||||
m_pPlayer->setOnVideoCB( [weakSelf,strUrlTmp](const H264Frame &data ) {
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
if(strongSelf->m_pChn){
|
||||
strongSelf->m_pChn->inputH264((char *)data.data.data(), data.data.size(), data.timeStamp);
|
||||
}else{
|
||||
strongSelf->initMedia();
|
||||
}
|
||||
strongSelf->checkExpired();
|
||||
});
|
||||
m_pPlayer->setOnAudioCB( [weakSelf,strUrlTmp](const AdtsFrame &data ) {
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf){
|
||||
return;
|
||||
}
|
||||
if(strongSelf->m_pChn){
|
||||
strongSelf->m_pChn->inputAAC((char *)data.data, data.aac_frame_length, data.timeStamp);
|
||||
}else{
|
||||
strongSelf->initMedia();
|
||||
}
|
||||
strongSelf->checkExpired();
|
||||
});
|
||||
|
||||
std::shared_ptr<uint64_t> piFailedCnt(new uint64_t(0)); //连续播放失败次数
|
||||
m_pPlayer->setOnPlayResult([weakSelf,strUrlTmp,strUserTmp,strPwdTmp,eType,piFailedCnt](const SockException &err) {
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf) {
|
||||
return;
|
||||
}
|
||||
static uint64_t replayCnt = mINI::Instance()[Config::Proxy::kReplayCount].as<uint64_t>();
|
||||
if(!err) {
|
||||
// 播放成功
|
||||
*piFailedCnt = 0;//连续播放失败次数清0
|
||||
}else if(*piFailedCnt < replayCnt) {
|
||||
// 播放失败,延时重试播放
|
||||
strongSelf->rePlay(strUrlTmp, strUserTmp, strPwdTmp, eType,(*piFailedCnt)++);
|
||||
}else{
|
||||
strongSelf->expired();
|
||||
}
|
||||
});
|
||||
weak_ptr<MediaPlayer> weakPtr= m_pPlayer;
|
||||
m_pPlayer->setOnShutdown([weakSelf,weakPtr,strUrlTmp,strUserTmp,strPwdTmp,eType,piFailedCnt](const SockException &err) {
|
||||
auto strongSelf = weakSelf.lock();
|
||||
if(!strongSelf) {
|
||||
return;
|
||||
}
|
||||
if(strongSelf->m_pChn) {
|
||||
strongSelf->m_pChn.reset();
|
||||
}
|
||||
//播放异常中断,延时重试播放
|
||||
static uint64_t replayCnt = mINI::Instance()[Config::Proxy::kReplayCount].as<uint64_t>();
|
||||
if(*piFailedCnt < replayCnt) {
|
||||
strongSelf->rePlay(strUrlTmp, strUserTmp, strPwdTmp, eType,(*piFailedCnt)++);
|
||||
}else{
|
||||
strongSelf->expired();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
PlayerProxy::~PlayerProxy() {
|
||||
auto iTaskId = reinterpret_cast<uint64_t>(this);
|
||||
AsyncTaskThread::Instance().CancelTask(iTaskId);
|
||||
}
|
||||
void PlayerProxy::rePlay(const string &strUrl, const string &strUser, const string &strPwd, PlayerBase::eRtpType eType, uint64_t iFailedCnt){
|
||||
checkExpired();
|
||||
auto iTaskId = reinterpret_cast<uint64_t>(this);
|
||||
auto iDelay = MAX((uint64_t)2 * 1000, MIN(iFailedCnt * 3000,(uint64_t)60*1000));
|
||||
weak_ptr<MediaPlayer> weakPtr = m_pPlayer;
|
||||
AsyncTaskThread::Instance().CancelTask(iTaskId);
|
||||
AsyncTaskThread::Instance().DoTaskDelay(iTaskId, iDelay, [weakPtr,strUrl,strUser,strPwd,eType,iFailedCnt]() {
|
||||
//播放失败次数越多,则延时越长
|
||||
auto strongPlayer = weakPtr.lock();
|
||||
if(!strongPlayer) {
|
||||
return false;
|
||||
}
|
||||
WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl;
|
||||
strongPlayer->play(strUrl.data(), strUser.data(), strPwd.data(), eType);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
void PlayerProxy::initMedia() {
|
||||
if (!m_pPlayer->isInited()) {
|
||||
return;
|
||||
}
|
||||
m_pChn.reset(new DevChannel(m_strApp.data(),m_strSrc.data(),m_pPlayer->getDuration()));
|
||||
if (m_pPlayer->containVideo()) {
|
||||
VideoInfo info;
|
||||
info.iFrameRate = m_pPlayer->getVideoFps();
|
||||
info.iWidth = m_pPlayer->getVideoWidth();
|
||||
info.iHeight = m_pPlayer->getVideoHeight();
|
||||
m_pChn->initVideo(info);
|
||||
}
|
||||
if (m_pPlayer->containAudio()) {
|
||||
AudioInfo info;
|
||||
info.iSampleRate = m_pPlayer->getAudioSampleRate();
|
||||
info.iChannel = m_pPlayer->getAudioChannel();
|
||||
info.iSampleBit = m_pPlayer->getAudioSampleBit();
|
||||
m_pChn->initAudio(info);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerProxy::checkExpired() {
|
||||
if(m_aliveSecond && m_aliveTicker.elapsedTime() > m_aliveSecond * 1000){
|
||||
//到期
|
||||
expired();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerProxy::expired() {
|
||||
if(onExpired){
|
||||
onExpired();
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace Player */
|
||||
} /* namespace ZL */
|
||||
48
src/Device/PlayerProxy.h
Normal file
48
src/Device/PlayerProxy.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* PlyerProxy.h
|
||||
*
|
||||
* Created on: 2016年12月6日
|
||||
* Author: xzl
|
||||
*/
|
||||
|
||||
#ifndef SRC_DEVICE_PLAYERPROXY_H_
|
||||
#define SRC_DEVICE_PLAYERPROXY_H_
|
||||
|
||||
#include "Device.h"
|
||||
#include <memory>
|
||||
#include "Player/MediaPlayer.h"
|
||||
#include "Util/TimeTicker.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ZL::Player;
|
||||
|
||||
namespace ZL {
|
||||
namespace DEV {
|
||||
|
||||
class PlayerProxy : public std::enable_shared_from_this<PlayerProxy>{
|
||||
public:
|
||||
typedef std::shared_ptr<PlayerProxy> Ptr;
|
||||
PlayerProxy(const char *strApp, const char *strSrc);
|
||||
void play(const char* strUrl, const char *strUser = "", const char *strPwd = "",PlayerBase::eRtpType eType = PlayerBase::RTP_TCP,uint32_t iSecond = 0);
|
||||
virtual ~PlayerProxy();
|
||||
void setOnExpired(const function<void()> &cb){
|
||||
onExpired = cb;
|
||||
}
|
||||
private :
|
||||
MediaPlayer::Ptr m_pPlayer;
|
||||
DevChannel::Ptr m_pChn;
|
||||
Ticker m_aliveTicker;
|
||||
uint32_t m_aliveSecond = 0;
|
||||
function<void()> onExpired;
|
||||
string m_strApp;
|
||||
string m_strSrc;
|
||||
void initMedia();
|
||||
void rePlay(const string &strUrl, const string &strUser, const string &strPwd, PlayerBase::eRtpType eType,uint64_t iFailedCnt);
|
||||
void checkExpired();
|
||||
void expired();
|
||||
};
|
||||
|
||||
} /* namespace Player */
|
||||
} /* namespace ZL */
|
||||
|
||||
#endif /* SRC_DEVICE_PLAYERPROXY_H_ */
|
||||
167
src/Device/base64.cpp
Normal file
167
src/Device/base64.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Base64 encode/decode
|
||||
* @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
|
||||
*/
|
||||
|
||||
//#include "common.h"
|
||||
#include "stdio.h"
|
||||
#include "base64.h"
|
||||
|
||||
#include <limits.h>
|
||||
/* ---------------- private code */
|
||||
static const uint8_t map2[] =
|
||||
{
|
||||
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
|
||||
};
|
||||
|
||||
int av_base64_decode(uint8_t *out, const char *in, int out_size)
|
||||
{
|
||||
int i, v;
|
||||
uint8_t *dst = out;
|
||||
|
||||
v = 0;
|
||||
for (i = 0; in[i] && in[i] != '='; i++) {
|
||||
unsigned int index= in[i]-43;
|
||||
if (index>=FF_ARRAY_ELEMS(map2) || map2[index] == 0xff)
|
||||
return -1;
|
||||
v = (v << 6) + map2[index];
|
||||
if (i & 3) {
|
||||
if (dst - out < out_size) {
|
||||
*dst++ = v >> (6 - 2 * (i & 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dst - out;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* b64_encode: Stolen from VLC's http.c.
|
||||
* Simplified by Michael.
|
||||
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
|
||||
*****************************************************************************/
|
||||
|
||||
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
|
||||
{
|
||||
static const char b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char *ret, *dst;
|
||||
unsigned i_bits = 0;
|
||||
int i_shift = 0;
|
||||
int bytes_remaining = in_size;
|
||||
|
||||
if (in_size >= UINT_MAX / 4 || out_size < AV_BASE64_SIZE(in_size))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ret = dst = out;
|
||||
while (bytes_remaining) {
|
||||
i_bits = (i_bits << 8) + *in++;
|
||||
bytes_remaining--;
|
||||
i_shift += 8;
|
||||
|
||||
do {
|
||||
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
|
||||
i_shift -= 6;
|
||||
} while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
|
||||
}
|
||||
while ((dst - ret) & 3)
|
||||
*dst++ = '=';
|
||||
*dst = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#undef printf
|
||||
|
||||
#define MAX_DATA_SIZE 1024
|
||||
#define MAX_ENCODED_SIZE 2048
|
||||
|
||||
static int test_encode_decode(const uint8_t *data, unsigned int data_size,
|
||||
const char *encoded_ref)
|
||||
{
|
||||
char encoded[MAX_ENCODED_SIZE];
|
||||
uint8_t data2[MAX_DATA_SIZE];
|
||||
int data2_size, max_data2_size = MAX_DATA_SIZE;
|
||||
|
||||
if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
|
||||
printf("Failed: cannot encode the input data\n");
|
||||
return 1;
|
||||
}
|
||||
if (encoded_ref && strcmp(encoded, encoded_ref)) {
|
||||
printf("Failed: encoded string differs from reference\n"
|
||||
"Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) {
|
||||
printf("Failed: cannot decode the encoded string\n"
|
||||
"Encoded:\n%s\n", encoded);
|
||||
return 1;
|
||||
}
|
||||
if (memcmp(data2, data, data_size)) {
|
||||
printf("Failed: encoded/decoded data differs from original data\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Passed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, error_count = 0;
|
||||
struct test {
|
||||
const uint8_t *data;
|
||||
const char *encoded_ref;
|
||||
} tests[] = {
|
||||
{ "", ""},
|
||||
{ "1", "MQ=="},
|
||||
{ "22", "MjI="},
|
||||
{ "333", "MzMz"},
|
||||
{ "4444", "NDQ0NA=="},
|
||||
{ "55555", "NTU1NTU="},
|
||||
{ "666666", "NjY2NjY2"},
|
||||
{ "abc:def", "YWJjOmRlZg=="},
|
||||
};
|
||||
|
||||
printf("Encoding/decoding tests\n");
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
|
||||
error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
#endif
|
||||
55
src/Device/base64.h
Normal file
55
src/Device/base64.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#ifndef AVUTIL_BASE64_H
|
||||
#define AVUTIL_BASE64_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Decode a base64-encoded string.
|
||||
*
|
||||
* @param out buffer for decoded data
|
||||
* @param in null-terminated input string
|
||||
* @param out_size size in bytes of the out buffer, must be at
|
||||
* least 3/4 of the length of in
|
||||
* @return number of bytes written, or a negative value in case of
|
||||
* invalid input
|
||||
*/
|
||||
int av_base64_decode(uint8_t *out, const char *in, int out_size);
|
||||
|
||||
/**
|
||||
* Encode data to base64 and null-terminate.
|
||||
*
|
||||
* @param out buffer for encoded data
|
||||
* @param out_size size in bytes of the output buffer, must be at
|
||||
* least AV_BASE64_SIZE(in_size)
|
||||
* @param in_size size in bytes of the 'in' buffer
|
||||
* @return 'out' or NULL in case of error
|
||||
*/
|
||||
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
|
||||
|
||||
/**
|
||||
* Calculate the output size needed to base64-encode x bytes.
|
||||
*/
|
||||
#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
|
||||
|
||||
#endif /* AVUTIL_BASE64_H */
|
||||
Reference in New Issue
Block a user