mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
删除多余文件
This commit is contained in:
parent
25ec025553
commit
b0c567e49d
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* AACEncoder.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月11日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CODEC_AACENCODER_H_
|
|
||||||
#define CODEC_AACENCODER_H_
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Codec {
|
|
||||||
|
|
||||||
class AACEncoder {
|
|
||||||
public:
|
|
||||||
AACEncoder(void);
|
|
||||||
virtual ~AACEncoder(void);
|
|
||||||
bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit);
|
|
||||||
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned char *m_pucPcmBuf = nullptr;
|
|
||||||
unsigned int m_uiPcmLen = 0;
|
|
||||||
|
|
||||||
unsigned char *m_pucAacBuf = nullptr;
|
|
||||||
void *m_hEncoder = nullptr;
|
|
||||||
|
|
||||||
unsigned long m_ulInputSamples = 0;
|
|
||||||
unsigned long m_ulMaxInputBytes = 0;
|
|
||||||
unsigned long m_ulMaxOutputBytes = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Codec */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* CODEC_AACENCODER_H_ */
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* H264Encoder.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月11日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CODEC_H264ENCODER_H_
|
|
||||||
#define CODEC_H264ENCODER_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif //__cplusplus
|
|
||||||
#include <x264.h>
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Codec {
|
|
||||||
|
|
||||||
class H264Encoder {
|
|
||||||
public:
|
|
||||||
typedef struct {
|
|
||||||
int iType;
|
|
||||||
int iLength;
|
|
||||||
uint8_t *pucData;
|
|
||||||
} H264Frame;
|
|
||||||
|
|
||||||
H264Encoder(void);
|
|
||||||
virtual ~H264Encoder(void);
|
|
||||||
bool init(int iWidth, int iHeight, int iFps);
|
|
||||||
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
|
|
||||||
private:
|
|
||||||
x264_t* m_pX264Handle = nullptr;
|
|
||||||
x264_picture_t* m_pPicIn = nullptr;
|
|
||||||
x264_picture_t* m_pPicOut = nullptr;
|
|
||||||
H264Frame m_aFrames[10];
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Codec */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* CODEC_H264ENCODER_H_ */
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* MediaSender.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月1日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_MEDIASENDER_H_
|
|
||||||
#define SRC_MEDIASENDER_H_
|
|
||||||
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
class MediaSender {
|
|
||||||
public:
|
|
||||||
static ThreadPool & sendThread() {
|
|
||||||
static ThreadPool pool(1);
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MediaSender();
|
|
||||||
virtual ~MediaSender();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* SRC_MEDIASENDER_H_ */
|
|
@ -1,164 +0,0 @@
|
|||||||
//
|
|
||||||
// appConfig.h
|
|
||||||
// ZLMedia
|
|
||||||
//
|
|
||||||
// Created by lyl on 16/10/22.
|
|
||||||
// Copyright © 2016年 jizan. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef appConfig_h
|
|
||||||
#define appConfig_h
|
|
||||||
|
|
||||||
#include "Util/mini.h"
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace Config {
|
|
||||||
|
|
||||||
void loaIniConfig();
|
|
||||||
////////////TCP最大连接数///////////
|
|
||||||
#ifdef __x86_64__
|
|
||||||
#define MAX_TCP_SESSION 100000
|
|
||||||
#else
|
|
||||||
#define MAX_TCP_SESSION 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////其他宏定义///////////
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(a,b) ((a) > (b) ? (a) : (b) )
|
|
||||||
#endif //MAX
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a,b) ((a) < (b) ? (a) : (b) )
|
|
||||||
#endif //MIN
|
|
||||||
|
|
||||||
#ifndef CLEAR_ARR
|
|
||||||
#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;}
|
|
||||||
#endif //CLEAR_ARR
|
|
||||||
|
|
||||||
|
|
||||||
////////////广播名称///////////
|
|
||||||
namespace Broadcast {
|
|
||||||
extern const char kBroadcastRtspSessionPlay[];
|
|
||||||
#define BroadcastRtspSessionPlayArgs const char *app,const char *stream
|
|
||||||
|
|
||||||
extern const char kBroadcastRtspSrcRegisted[];
|
|
||||||
#define BroadcastRtspSrcRegistedArgs const char *app,const char *stream
|
|
||||||
|
|
||||||
extern const char kBroadcastRtmpSrcRegisted[];
|
|
||||||
#define BroadcastRtmpSrcRegistedArgs const char *app,const char *stream
|
|
||||||
|
|
||||||
extern const char kBroadcastRecordMP4[];
|
|
||||||
#define BroadcastRecordMP4Args const Mp4Info &info
|
|
||||||
|
|
||||||
extern const char kBroadcastHttpRequest[];
|
|
||||||
#define BroadcastHttpRequestArgs const Parser &parser,HttpSession::HttpResponseInvoker &invoker
|
|
||||||
|
|
||||||
} //namespace Broadcast
|
|
||||||
|
|
||||||
//代理失败最大重试次数
|
|
||||||
namespace Proxy {
|
|
||||||
extern const char kReplayCount[];
|
|
||||||
}//namespace Proxy
|
|
||||||
|
|
||||||
|
|
||||||
////////////HTTP配置///////////
|
|
||||||
namespace Http {
|
|
||||||
extern const char kPort[];
|
|
||||||
extern const char kSSLPort[];
|
|
||||||
//http 文件发送缓存大小
|
|
||||||
extern const char kSendBufSize[];
|
|
||||||
//http 最大请求字节数
|
|
||||||
extern const char kMaxReqSize[];
|
|
||||||
//http keep-alive秒数
|
|
||||||
extern const char kKeepAliveSecond[];
|
|
||||||
//http keep-alive最大请求数
|
|
||||||
extern const char kMaxReqCount[];
|
|
||||||
//http 字符编码
|
|
||||||
extern const char kCharSet[];
|
|
||||||
//http 服务器名称
|
|
||||||
extern const char kServerName[];
|
|
||||||
//http 服务器根目录
|
|
||||||
extern const char kRootPath[];
|
|
||||||
//http 404错误提示内容
|
|
||||||
extern const char kNotFound[];
|
|
||||||
//HTTP访问url前缀
|
|
||||||
extern const char kHttpPrefix[];
|
|
||||||
}//namespace Http
|
|
||||||
|
|
||||||
////////////SHELL配置///////////
|
|
||||||
namespace Shell {
|
|
||||||
extern const char kServerName[];
|
|
||||||
extern const char kMaxReqSize[];
|
|
||||||
extern const char kPort[];
|
|
||||||
} //namespace Shell
|
|
||||||
|
|
||||||
////////////RTSP服务器配置///////////
|
|
||||||
namespace Rtsp {
|
|
||||||
#define RTSP_VERSION 1.30
|
|
||||||
#define RTSP_BUILDTIME __DATE__" CST"
|
|
||||||
|
|
||||||
extern const char kServerName[];
|
|
||||||
extern const char kPort[];
|
|
||||||
} //namespace Rtsp
|
|
||||||
|
|
||||||
////////////RTMP服务器配置///////////
|
|
||||||
namespace Rtmp {
|
|
||||||
extern const char kPort[];
|
|
||||||
} //namespace RTMP
|
|
||||||
|
|
||||||
|
|
||||||
////////////RTP配置///////////
|
|
||||||
namespace Rtp {
|
|
||||||
//RTP打包最大MTU,公网情况下更小
|
|
||||||
extern const char kVideoMtuSize[];
|
|
||||||
//RTP打包最大MTU,公网情况下更小
|
|
||||||
extern const char kAudioMtuSize[];
|
|
||||||
//udp方式接受RTP包的最大缓存
|
|
||||||
extern const char kUdpBufSize[];
|
|
||||||
//RTP排序缓存最大个数
|
|
||||||
extern const char kMaxRtpCount[];
|
|
||||||
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
|
|
||||||
extern const char kClearCount[];
|
|
||||||
//最大RTP时间为13个小时,每13小时回环一次
|
|
||||||
extern const char kCycleMS[];
|
|
||||||
} //namespace Rtsp
|
|
||||||
|
|
||||||
////////////组播配置///////////
|
|
||||||
namespace MultiCast {
|
|
||||||
//组播分配起始地址
|
|
||||||
extern const char kAddrMin[];
|
|
||||||
//组播分配截止地址
|
|
||||||
extern const char kAddrMax[];
|
|
||||||
//组播TTL
|
|
||||||
extern const char kUdpTTL[];
|
|
||||||
} //namespace MultiCast
|
|
||||||
|
|
||||||
////////////录像配置///////////
|
|
||||||
namespace Record {
|
|
||||||
//查看录像的应用名称
|
|
||||||
extern const char kAppName[];
|
|
||||||
//每次流化MP4文件的时长,单位毫秒
|
|
||||||
extern const char kSampleMS[];
|
|
||||||
//MP4文件录制大小,不能太大,否则MP4Close函数执行事件太长
|
|
||||||
extern const char kFileSecond[];
|
|
||||||
//Rtsp访问url前缀
|
|
||||||
extern const char kRtspPrefix[];
|
|
||||||
//录制文件路径
|
|
||||||
extern const char kFilePath[];
|
|
||||||
} //namespace Record
|
|
||||||
|
|
||||||
////////////HLS相关配置///////////
|
|
||||||
namespace Hls {
|
|
||||||
//HLS切片时长,单位秒
|
|
||||||
extern const char kSegmentDuration[];
|
|
||||||
//HLS切片个数
|
|
||||||
extern const char kSegmentNum[];
|
|
||||||
//HLS文件写缓存大小
|
|
||||||
extern const char kFileBufSize[];
|
|
||||||
//录制文件路径
|
|
||||||
extern const char kFilePath[];
|
|
||||||
} //namespace Hls
|
|
||||||
|
|
||||||
} // namespace Config
|
|
||||||
|
|
||||||
#endif /* appConfig_h */
|
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* Device.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DEVICE_DEVICE_H_
|
|
||||||
#define DEVICE_DEVICE_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#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
|
|
||||||
|
|
||||||
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_ */
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* PlyerProxy.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月6日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_DEVICE_PLAYERPROXY_H_
|
|
||||||
#define SRC_DEVICE_PLAYERPROXY_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "Device.h"
|
|
||||||
#include "Player/MediaPlayer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace DEV {
|
|
||||||
|
|
||||||
class PlayerProxy :public MediaPlayer, public std::enable_shared_from_this<PlayerProxy>{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<PlayerProxy> Ptr;
|
|
||||||
//设置代理时间,0为永久,其他为代理秒数
|
|
||||||
//设置方法:proxy[PlayerProxy::kAliveSecond] = 100;
|
|
||||||
static const char kAliveSecond[];
|
|
||||||
|
|
||||||
PlayerProxy(const char *strApp, const char *strSrc);
|
|
||||||
virtual ~PlayerProxy();
|
|
||||||
void play(const char* strUrl) override;
|
|
||||||
void setOnExpired(const function<void()> &cb){
|
|
||||||
onExpired = cb;
|
|
||||||
}
|
|
||||||
private :
|
|
||||||
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,uint64_t iFailedCnt);
|
|
||||||
void checkExpired();
|
|
||||||
void expired();
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Player */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_DEVICE_PLAYERPROXY_H_ */
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 */
|
|
@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// H264Parser.h
|
|
||||||
// MediaPlayer
|
|
||||||
//
|
|
||||||
// Created by xzl on 2017/1/16.
|
|
||||||
// Copyright © 2017年 jizan. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef H264Parser_h
|
|
||||||
#define H264Parser_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include "h264_poc.h"
|
|
||||||
#include "h264_parser.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#ifndef INT32_MAX
|
|
||||||
#define INT32_MAX 0x7FFFFFFF
|
|
||||||
#endif//INT32_MAX
|
|
||||||
|
|
||||||
class H264Parser{
|
|
||||||
public:
|
|
||||||
H264Parser();
|
|
||||||
virtual ~H264Parser();
|
|
||||||
void inputH264(const string &h264,uint32_t dts);
|
|
||||||
|
|
||||||
int32_t getPOC() const{
|
|
||||||
return m_iNowPOC;
|
|
||||||
}
|
|
||||||
int getSliceType() const{
|
|
||||||
return m_shdr.slice_type;
|
|
||||||
}
|
|
||||||
int getNaluType() const{
|
|
||||||
return m_nalu.nal_unit_type;
|
|
||||||
}
|
|
||||||
uint32_t getPts() const{
|
|
||||||
return m_iNowPTS;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
media::H264Parser m_parser;
|
|
||||||
media::H264POC m_poc;
|
|
||||||
media::H264NALU m_nalu;
|
|
||||||
media::H264SliceHeader m_shdr;
|
|
||||||
|
|
||||||
int32_t m_iNowPOC = INT32_MAX;
|
|
||||||
int32_t m_iLastPOC = INT32_MAX;
|
|
||||||
|
|
||||||
uint32_t m_iNowPTS = INT32_MAX;
|
|
||||||
uint32_t m_iLastPTS = INT32_MAX;
|
|
||||||
int32_t m_iMsPerPOC = 30;
|
|
||||||
|
|
||||||
void computePts(uint32_t dts);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* H264Parser_hpp */
|
|
@ -1,192 +0,0 @@
|
|||||||
/***************************************************************************************
|
|
||||||
***************************************************************************************/
|
|
||||||
#ifndef _JZAN_SPS_PPS_H_
|
|
||||||
#define _JZAN_SPS_PPS_H_
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define QP_MAX_NUM (51 + 6*6) // The maximum supported qp
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chromaticity coordinates of the source primaries.
|
|
||||||
*/
|
|
||||||
enum T_AVColorPrimaries {
|
|
||||||
AVCOL_PRI_RESERVED0 = 0,
|
|
||||||
AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
|
|
||||||
AVCOL_PRI_UNSPECIFIED = 2,
|
|
||||||
AVCOL_PRI_RESERVED = 3,
|
|
||||||
AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
|
|
||||||
|
|
||||||
AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
|
|
||||||
AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
|
|
||||||
AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above
|
|
||||||
AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C
|
|
||||||
AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020
|
|
||||||
AVCOL_PRI_NB, ///< Not part of ABI
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Color Transfer Characteristic.
|
|
||||||
*/
|
|
||||||
enum T_AVColorTransferCharacteristic {
|
|
||||||
AVCOL_TRC_RESERVED0 = 0,
|
|
||||||
AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361
|
|
||||||
AVCOL_TRC_UNSPECIFIED = 2,
|
|
||||||
AVCOL_TRC_RESERVED = 3,
|
|
||||||
AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
|
|
||||||
AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG
|
|
||||||
AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
|
|
||||||
AVCOL_TRC_SMPTE240M = 7,
|
|
||||||
AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics"
|
|
||||||
AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)"
|
|
||||||
AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
|
|
||||||
AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
|
|
||||||
AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut
|
|
||||||
AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
|
|
||||||
AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10 bit system
|
|
||||||
AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12 bit system
|
|
||||||
AVCOL_TRC_NB, ///< Not part of ABI
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* YUV tColorspace type.
|
|
||||||
*/
|
|
||||||
enum T_AVColorSpace {
|
|
||||||
AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
|
|
||||||
AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
|
|
||||||
AVCOL_SPC_UNSPECIFIED = 2,
|
|
||||||
AVCOL_SPC_RESERVED = 3,
|
|
||||||
AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
|
|
||||||
AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
|
|
||||||
AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
|
|
||||||
AVCOL_SPC_SMPTE240M = 7,
|
|
||||||
AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
|
|
||||||
AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system
|
|
||||||
AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system
|
|
||||||
AVCOL_SPC_NB, ///< Not part of ABI
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rational number numerator/denominator
|
|
||||||
*/
|
|
||||||
typedef struct T_AVRational{
|
|
||||||
int num; ///< numerator
|
|
||||||
int den; ///< denominator
|
|
||||||
} T_AVRational;
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Sequence parameter set
|
|
||||||
* ¿É²Î¿¼H264±ê×¼µÚ7½ÚºÍ¸½Â¼D E
|
|
||||||
*/
|
|
||||||
#define Extended_SAR 255
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sequence parameter set
|
|
||||||
*/
|
|
||||||
typedef struct T_SPS {
|
|
||||||
unsigned int uiSpsId;
|
|
||||||
int iProfileIdc;
|
|
||||||
int iLevelIdc;
|
|
||||||
int iChromaFormatIdc;
|
|
||||||
int iTransformBypass; ///< qpprime_y_zero_transform_bypass_flag
|
|
||||||
int iLog2MaxFrameNum; ///< log2_max_frame_num_minus4 + 4
|
|
||||||
int iPocType; ///< pic_order_cnt_type
|
|
||||||
int iLog2MaxPocLsb; ///< log2_max_pic_order_cnt_lsb_minus4
|
|
||||||
int iDeltaPicOrderAlwaysZeroFlag;
|
|
||||||
int iOffsetForNonRefPic;
|
|
||||||
int iOffsetForTopToBottomField;
|
|
||||||
int iPocCycleLength; ///< num_ref_frames_in_pic_order_cnt_cycle
|
|
||||||
int iRefFrameCount; ///< num_ref_frames
|
|
||||||
int iGapsInFrameNumAllowedFlag;
|
|
||||||
int iMbWidth; ///< pic_width_in_mbs_minus1 + 1
|
|
||||||
int iMbHeight; ///< pic_height_in_map_units_minus1 + 1
|
|
||||||
int iFrameMbsOnlyFlag;
|
|
||||||
int iMbAff; ///< mb_adaptive_frame_field_flag
|
|
||||||
int iDirect8x8InferenceFlag;
|
|
||||||
int iCrop; ///< frame_cropping_flag
|
|
||||||
|
|
||||||
/* those 4 are already in luma samples */
|
|
||||||
unsigned int uiCropLeft; ///< frame_cropping_rect_left_offset
|
|
||||||
unsigned int uiCropRight; ///< frame_cropping_rect_right_offset
|
|
||||||
unsigned int uiCropTop; ///< frame_cropping_rect_top_offset
|
|
||||||
unsigned int uiCropBottom; ///< frame_cropping_rect_bottom_offset
|
|
||||||
int iVuiParametersPresentFlag;
|
|
||||||
T_AVRational tSar;
|
|
||||||
int iVideoSignalTypePresentFlag;
|
|
||||||
int iFullRange;
|
|
||||||
int iColourDescriptionPresentFlag;
|
|
||||||
enum T_AVColorPrimaries tColorPrimaries;
|
|
||||||
enum T_AVColorTransferCharacteristic tColorTrc;
|
|
||||||
enum T_AVColorSpace tColorspace;
|
|
||||||
int iTimingInfoPresentFlag;
|
|
||||||
uint32_t u32NumUnitsInTick;
|
|
||||||
uint32_t u32TimeScale;
|
|
||||||
int iFixedFrameRateFlag;
|
|
||||||
short asOffsetForRefFrame[256]; // FIXME dyn aloc?
|
|
||||||
int iBitstreamRestrictionFlag;
|
|
||||||
int iNumReorderFrames;
|
|
||||||
int iScalingMatrixPresent;
|
|
||||||
uint8_t aau8ScalingMatrix4[6][16];
|
|
||||||
uint8_t aau8ScalingMatrix8[6][64];
|
|
||||||
int iNalHrdParametersPresentFlag;
|
|
||||||
int iVclHrdParametersPresentFlag;
|
|
||||||
int iPicStructPresentFlag;
|
|
||||||
int iTimeOffsetLength;
|
|
||||||
int iCpbCnt; ///< See H.264 E.1.2
|
|
||||||
int iInitialCpbRemovalDelayLength; ///< initial_cpb_removal_delay_length_minus1 + 1
|
|
||||||
int iCpbRemovalDelayLength; ///< cpb_removal_delay_length_minus1 + 1
|
|
||||||
int iDpbOutputDelayLength; ///< dpb_output_delay_length_minus1 + 1
|
|
||||||
int iBitDepthLuma; ///< bit_depth_luma_minus8 + 8
|
|
||||||
int iBitDepthChroma; ///< bit_depth_chroma_minus8 + 8
|
|
||||||
int iResidualColorTransformFlag; ///< residual_colour_transform_flag
|
|
||||||
int iConstraintSetFlags; ///< constraint_set[0-3]_flag
|
|
||||||
int iNew; ///< flag to keep track if the decoder context needs re-init due to changed SPS
|
|
||||||
} T_SPS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Picture parameter set
|
|
||||||
*/
|
|
||||||
typedef struct T_PPS {
|
|
||||||
unsigned int uiSpsId;
|
|
||||||
int iCabac; ///< entropy_coding_mode_flag
|
|
||||||
int iPicOrderPresent; ///< pic_order_present_flag
|
|
||||||
int iSliceGroupCount; ///< num_slice_groups_minus1 + 1
|
|
||||||
int iMbSliceGroupMapType;
|
|
||||||
unsigned int auiRefCount[2]; ///< num_ref_idx_l0/1_active_minus1 + 1
|
|
||||||
int iWeightedPred; ///< weighted_pred_flag
|
|
||||||
int iWeightedBipredIdc;
|
|
||||||
int iInitQp; ///< pic_init_qp_minus26 + 26
|
|
||||||
int iInitQs; ///< pic_init_qs_minus26 + 26
|
|
||||||
int aiChromaQpIndexOffset[2];
|
|
||||||
int iDeblockingFilterParametersPresent; ///< deblocking_filter_parameters_present_flag
|
|
||||||
int iConstrainedIntraPred; ///< constrained_intra_pred_flag
|
|
||||||
int iRedundantPicCntPresent; ///< redundant_pic_cnt_present_flag
|
|
||||||
int iTransform8x8Mode; ///< transform_8x8_mode_flag
|
|
||||||
uint8_t aau8ScalingMatrix4[6][16];
|
|
||||||
uint8_t aau8ScalingMatrix8[6][64];
|
|
||||||
uint8_t u8ChromaQpTable[2][QP_MAX_NUM+1]; ///< pre-scaled (with aiChromaQpIndexOffset) version of qp_table
|
|
||||||
int iChromaQpDiff;
|
|
||||||
} T_PPS;
|
|
||||||
|
|
||||||
typedef struct T_GetBitContext{
|
|
||||||
uint8_t *pu8Buf; /*Ö¸ÏòSPS start*/
|
|
||||||
int iBufSize; /*SPS ³¤¶È*/
|
|
||||||
int iBitPos; /*bitÒѶÁȡλÖÃ*/
|
|
||||||
int iTotalBit; /*bit×ܳ¤¶È*/
|
|
||||||
int iCurBitPos; /*µ±Ç°¶ÁȡλÖÃ*/
|
|
||||||
}T_GetBitContext;
|
|
||||||
|
|
||||||
|
|
||||||
int h264DecSeqParameterSet(void *pvBuf, T_SPS *ptSps);
|
|
||||||
void h264GetWidthHeight(T_SPS *ptSps, int *piWidth, int *piHeight);
|
|
||||||
void h264GeFramerate(T_SPS *ptSps, float *pfFramerate);
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// This file contains an implementation of an H264 Annex-B video stream parser.
|
|
||||||
|
|
||||||
#ifndef MEDIA_FILTERS_H264_BIT_READER_H_
|
|
||||||
#define MEDIA_FILTERS_H264_BIT_READER_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "macros.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace media {
|
|
||||||
|
|
||||||
// A class to provide bit-granularity reading of H.264 streams.
|
|
||||||
// This is not a generic bit reader class, as it takes into account
|
|
||||||
// H.264 stream-specific constraints, such as skipping emulation-prevention
|
|
||||||
// bytes and stop bits. See spec for more details.
|
|
||||||
class MEDIA_EXPORT H264BitReader {
|
|
||||||
public:
|
|
||||||
H264BitReader();
|
|
||||||
~H264BitReader();
|
|
||||||
|
|
||||||
// Initialize the reader to start reading at |data|, |size| being size
|
|
||||||
// of |data| in bytes.
|
|
||||||
// Return false on insufficient size of stream..
|
|
||||||
// TODO(posciak,fischman): consider replacing Initialize() with
|
|
||||||
// heap-allocating and creating bit readers on demand instead.
|
|
||||||
bool Initialize(const uint8_t* data, off_t size);
|
|
||||||
|
|
||||||
// Read |num_bits| next bits from stream and return in |*out|, first bit
|
|
||||||
// from the stream starting at |num_bits| position in |*out|.
|
|
||||||
// |num_bits| may be 1-32, inclusive.
|
|
||||||
// Return false if the given number of bits cannot be read (not enough
|
|
||||||
// bits in the stream), true otherwise.
|
|
||||||
bool ReadBits(int num_bits, int* out);
|
|
||||||
|
|
||||||
// Return the number of bits left in the stream.
|
|
||||||
off_t NumBitsLeft();
|
|
||||||
|
|
||||||
// See the definition of more_rbsp_data() in spec.
|
|
||||||
bool HasMoreRBSPData();
|
|
||||||
|
|
||||||
// Return the number of emulation prevention bytes already read.
|
|
||||||
size_t NumEmulationPreventionBytesRead();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Advance to the next byte, loading it into curr_byte_.
|
|
||||||
// Return false on end of stream.
|
|
||||||
bool UpdateCurrByte();
|
|
||||||
|
|
||||||
// Pointer to the next unread (not in curr_byte_) byte in the stream.
|
|
||||||
const uint8_t* data_;
|
|
||||||
|
|
||||||
// Bytes left in the stream (without the curr_byte_).
|
|
||||||
off_t bytes_left_;
|
|
||||||
|
|
||||||
// Contents of the current byte; first unread bit starting at position
|
|
||||||
// 8 - num_remaining_bits_in_curr_byte_ from MSB.
|
|
||||||
int curr_byte_;
|
|
||||||
|
|
||||||
// Number of bits remaining in curr_byte_
|
|
||||||
int num_remaining_bits_in_curr_byte_;
|
|
||||||
|
|
||||||
// Used in emulation prevention three byte detection (see spec).
|
|
||||||
// Initially set to 0xffff to accept all initial two-byte sequences.
|
|
||||||
int prev_two_bytes_;
|
|
||||||
|
|
||||||
// Number of emulation preventation bytes (0x000003) we met.
|
|
||||||
size_t emulation_prevention_bytes_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(H264BitReader);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace media
|
|
||||||
|
|
||||||
#endif // MEDIA_FILTERS_H264_BIT_READER_H_
|
|
@ -1,491 +0,0 @@
|
|||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// This file contains an implementation of an H264 Annex-B video stream parser.
|
|
||||||
|
|
||||||
#ifndef MEDIA_FILTERS_H264_PARSER_H_
|
|
||||||
#define MEDIA_FILTERS_H264_PARSER_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "macros.h"
|
|
||||||
#include "h264_bit_reader.h"
|
|
||||||
#include "ranges.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace media {
|
|
||||||
|
|
||||||
struct SubsampleEntry {
|
|
||||||
uint32_t clear_bytes;
|
|
||||||
uint32_t cypher_bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// For explanations of each struct and its members, see H.264 specification
|
|
||||||
// at http://www.itu.int/rec/T-REC-H.264.
|
|
||||||
struct MEDIA_EXPORT H264NALU {
|
|
||||||
H264NALU();
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
kUnspecified = 0,
|
|
||||||
kNonIDRSlice = 1,
|
|
||||||
kSliceDataA = 2,
|
|
||||||
kSliceDataB = 3,
|
|
||||||
kSliceDataC = 4,
|
|
||||||
kIDRSlice = 5,
|
|
||||||
kSEIMessage = 6,
|
|
||||||
kSPS = 7,
|
|
||||||
kPPS = 8,
|
|
||||||
kAUD = 9,
|
|
||||||
kEOSeq = 10,
|
|
||||||
kEOStream = 11,
|
|
||||||
kFiller = 12,
|
|
||||||
kSPSExt = 13,
|
|
||||||
kReserved14 = 14,
|
|
||||||
kReserved15 = 15,
|
|
||||||
kReserved16 = 16,
|
|
||||||
kReserved17 = 17,
|
|
||||||
kReserved18 = 18,
|
|
||||||
kCodedSliceAux = 19,
|
|
||||||
kCodedSliceExtension = 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
// After (without) start code; we don't own the underlying memory
|
|
||||||
// and a shallow copy should be made when copying this struct.
|
|
||||||
const uint8_t* data;
|
|
||||||
off_t size; // From after start code to start code of next NALU (or EOS).
|
|
||||||
|
|
||||||
int nal_ref_idc;
|
|
||||||
int nal_unit_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kH264ScalingList4x4Length = 16,
|
|
||||||
kH264ScalingList8x8Length = 64,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264SPS {
|
|
||||||
H264SPS();
|
|
||||||
|
|
||||||
enum H264ProfileIDC {
|
|
||||||
kProfileIDCBaseline = 66,
|
|
||||||
kProfileIDCConstrainedBaseline = kProfileIDCBaseline,
|
|
||||||
kProfileIDCMain = 77,
|
|
||||||
kProfileIDScalableBaseline = 83,
|
|
||||||
kProfileIDScalableHigh = 86,
|
|
||||||
kProfileIDCHigh = 100,
|
|
||||||
kProfileIDHigh10 = 110,
|
|
||||||
kProfileIDSMultiviewHigh = 118,
|
|
||||||
kProfileIDHigh422 = 122,
|
|
||||||
kProfileIDStereoHigh = 128,
|
|
||||||
kProfileIDHigh444Predictive = 244,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AspectRatioIdc {
|
|
||||||
kExtendedSar = 255,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
// Constants for HRD parameters (spec ch. E.2.2).
|
|
||||||
kBitRateScaleConstantTerm = 6, // Equation E-37.
|
|
||||||
kCPBSizeScaleConstantTerm = 4, // Equation E-38.
|
|
||||||
kDefaultInitialCPBRemovalDelayLength = 24,
|
|
||||||
kDefaultDPBOutputDelayLength = 24,
|
|
||||||
kDefaultTimeOffsetLength = 24,
|
|
||||||
};
|
|
||||||
|
|
||||||
int profile_idc;
|
|
||||||
bool constraint_set0_flag;
|
|
||||||
bool constraint_set1_flag;
|
|
||||||
bool constraint_set2_flag;
|
|
||||||
bool constraint_set3_flag;
|
|
||||||
bool constraint_set4_flag;
|
|
||||||
bool constraint_set5_flag;
|
|
||||||
int level_idc;
|
|
||||||
int seq_parameter_set_id;
|
|
||||||
|
|
||||||
int chroma_format_idc;
|
|
||||||
bool separate_colour_plane_flag;
|
|
||||||
int bit_depth_luma_minus8;
|
|
||||||
int bit_depth_chroma_minus8;
|
|
||||||
bool qpprime_y_zero_transform_bypass_flag;
|
|
||||||
|
|
||||||
bool seq_scaling_matrix_present_flag;
|
|
||||||
int scaling_list4x4[6][kH264ScalingList4x4Length];
|
|
||||||
int scaling_list8x8[6][kH264ScalingList8x8Length];
|
|
||||||
|
|
||||||
int log2_max_frame_num_minus4;
|
|
||||||
int pic_order_cnt_type;
|
|
||||||
int log2_max_pic_order_cnt_lsb_minus4;
|
|
||||||
bool delta_pic_order_always_zero_flag;
|
|
||||||
int offset_for_non_ref_pic;
|
|
||||||
int offset_for_top_to_bottom_field;
|
|
||||||
int num_ref_frames_in_pic_order_cnt_cycle;
|
|
||||||
int expected_delta_per_pic_order_cnt_cycle; // calculated
|
|
||||||
int offset_for_ref_frame[255];
|
|
||||||
int max_num_ref_frames;
|
|
||||||
bool gaps_in_frame_num_value_allowed_flag;
|
|
||||||
int pic_width_in_mbs_minus1;
|
|
||||||
int pic_height_in_map_units_minus1;
|
|
||||||
bool frame_mbs_only_flag;
|
|
||||||
bool mb_adaptive_frame_field_flag;
|
|
||||||
bool direct_8x8_inference_flag;
|
|
||||||
bool frame_cropping_flag;
|
|
||||||
int frame_crop_left_offset;
|
|
||||||
int frame_crop_right_offset;
|
|
||||||
int frame_crop_top_offset;
|
|
||||||
int frame_crop_bottom_offset;
|
|
||||||
|
|
||||||
bool vui_parameters_present_flag;
|
|
||||||
int sar_width; // Set to 0 when not specified.
|
|
||||||
int sar_height; // Set to 0 when not specified.
|
|
||||||
bool bitstream_restriction_flag;
|
|
||||||
int max_num_reorder_frames;
|
|
||||||
int max_dec_frame_buffering;
|
|
||||||
bool timing_info_present_flag;
|
|
||||||
int num_units_in_tick;
|
|
||||||
int time_scale;
|
|
||||||
bool fixed_frame_rate_flag;
|
|
||||||
|
|
||||||
// TODO(posciak): actually parse these instead of ParseAndIgnoreHRDParameters.
|
|
||||||
bool nal_hrd_parameters_present_flag;
|
|
||||||
int cpb_cnt_minus1;
|
|
||||||
int bit_rate_scale;
|
|
||||||
int cpb_size_scale;
|
|
||||||
int bit_rate_value_minus1[32];
|
|
||||||
int cpb_size_value_minus1[32];
|
|
||||||
bool cbr_flag[32];
|
|
||||||
int initial_cpb_removal_delay_length_minus_1;
|
|
||||||
int cpb_removal_delay_length_minus1;
|
|
||||||
int dpb_output_delay_length_minus1;
|
|
||||||
int time_offset_length;
|
|
||||||
|
|
||||||
bool low_delay_hrd_flag;
|
|
||||||
|
|
||||||
int chroma_array_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264PPS {
|
|
||||||
H264PPS();
|
|
||||||
|
|
||||||
int pic_parameter_set_id;
|
|
||||||
int seq_parameter_set_id;
|
|
||||||
bool entropy_coding_mode_flag;
|
|
||||||
bool bottom_field_pic_order_in_frame_present_flag;
|
|
||||||
int num_slice_groups_minus1;
|
|
||||||
// TODO(posciak): Slice groups not implemented, could be added at some point.
|
|
||||||
int num_ref_idx_l0_default_active_minus1;
|
|
||||||
int num_ref_idx_l1_default_active_minus1;
|
|
||||||
bool weighted_pred_flag;
|
|
||||||
int weighted_bipred_idc;
|
|
||||||
int pic_init_qp_minus26;
|
|
||||||
int pic_init_qs_minus26;
|
|
||||||
int chroma_qp_index_offset;
|
|
||||||
bool deblocking_filter_control_present_flag;
|
|
||||||
bool constrained_intra_pred_flag;
|
|
||||||
bool redundant_pic_cnt_present_flag;
|
|
||||||
bool transform_8x8_mode_flag;
|
|
||||||
|
|
||||||
bool pic_scaling_matrix_present_flag;
|
|
||||||
int scaling_list4x4[6][kH264ScalingList4x4Length];
|
|
||||||
int scaling_list8x8[6][kH264ScalingList8x8Length];
|
|
||||||
|
|
||||||
int second_chroma_qp_index_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264ModificationOfPicNum {
|
|
||||||
int modification_of_pic_nums_idc;
|
|
||||||
union {
|
|
||||||
int abs_diff_pic_num_minus1;
|
|
||||||
int long_term_pic_num;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264WeightingFactors {
|
|
||||||
bool luma_weight_flag;
|
|
||||||
bool chroma_weight_flag;
|
|
||||||
int luma_weight[32];
|
|
||||||
int luma_offset[32];
|
|
||||||
int chroma_weight[32][2];
|
|
||||||
int chroma_offset[32][2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264DecRefPicMarking {
|
|
||||||
int memory_mgmnt_control_operation;
|
|
||||||
int difference_of_pic_nums_minus1;
|
|
||||||
int long_term_pic_num;
|
|
||||||
int long_term_frame_idx;
|
|
||||||
int max_long_term_frame_idx_plus1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264SliceHeader {
|
|
||||||
H264SliceHeader();
|
|
||||||
|
|
||||||
enum {
|
|
||||||
kRefListSize = 32,
|
|
||||||
kRefListModSize = kRefListSize
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
kPSlice = 0,
|
|
||||||
kBSlice = 1,
|
|
||||||
kISlice = 2,
|
|
||||||
kSPSlice = 3,
|
|
||||||
kSISlice = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool IsPSlice() const;
|
|
||||||
bool IsBSlice() const;
|
|
||||||
bool IsISlice() const;
|
|
||||||
bool IsSPSlice() const;
|
|
||||||
bool IsSISlice() const;
|
|
||||||
|
|
||||||
bool idr_pic_flag; // from NAL header
|
|
||||||
int nal_ref_idc; // from NAL header
|
|
||||||
const uint8_t* nalu_data; // from NAL header
|
|
||||||
off_t nalu_size; // from NAL header
|
|
||||||
off_t header_bit_size; // calculated
|
|
||||||
|
|
||||||
int first_mb_in_slice;
|
|
||||||
int slice_type;
|
|
||||||
int pic_parameter_set_id;
|
|
||||||
int colour_plane_id; // TODO(posciak): use this! http://crbug.com/139878
|
|
||||||
int frame_num;
|
|
||||||
bool field_pic_flag;
|
|
||||||
bool bottom_field_flag;
|
|
||||||
int idr_pic_id;
|
|
||||||
int pic_order_cnt_lsb;
|
|
||||||
int delta_pic_order_cnt_bottom;
|
|
||||||
int delta_pic_order_cnt0;
|
|
||||||
int delta_pic_order_cnt1;
|
|
||||||
int redundant_pic_cnt;
|
|
||||||
bool direct_spatial_mv_pred_flag;
|
|
||||||
|
|
||||||
bool num_ref_idx_active_override_flag;
|
|
||||||
int num_ref_idx_l0_active_minus1;
|
|
||||||
int num_ref_idx_l1_active_minus1;
|
|
||||||
bool ref_pic_list_modification_flag_l0;
|
|
||||||
bool ref_pic_list_modification_flag_l1;
|
|
||||||
H264ModificationOfPicNum ref_list_l0_modifications[kRefListModSize];
|
|
||||||
H264ModificationOfPicNum ref_list_l1_modifications[kRefListModSize];
|
|
||||||
|
|
||||||
int luma_log2_weight_denom;
|
|
||||||
int chroma_log2_weight_denom;
|
|
||||||
|
|
||||||
bool luma_weight_l0_flag;
|
|
||||||
bool chroma_weight_l0_flag;
|
|
||||||
H264WeightingFactors pred_weight_table_l0;
|
|
||||||
|
|
||||||
bool luma_weight_l1_flag;
|
|
||||||
bool chroma_weight_l1_flag;
|
|
||||||
H264WeightingFactors pred_weight_table_l1;
|
|
||||||
|
|
||||||
bool no_output_of_prior_pics_flag;
|
|
||||||
bool long_term_reference_flag;
|
|
||||||
|
|
||||||
bool adaptive_ref_pic_marking_mode_flag;
|
|
||||||
H264DecRefPicMarking ref_pic_marking[kRefListSize];
|
|
||||||
|
|
||||||
int cabac_init_idc;
|
|
||||||
int slice_qp_delta;
|
|
||||||
bool sp_for_switch_flag;
|
|
||||||
int slice_qs_delta;
|
|
||||||
int disable_deblocking_filter_idc;
|
|
||||||
int slice_alpha_c0_offset_div2;
|
|
||||||
int slice_beta_offset_div2;
|
|
||||||
|
|
||||||
// Calculated.
|
|
||||||
// Size in bits of dec_ref_pic_marking() syntax element.
|
|
||||||
size_t dec_ref_pic_marking_bit_size;
|
|
||||||
size_t pic_order_cnt_bit_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct H264SEIRecoveryPoint {
|
|
||||||
int recovery_frame_cnt;
|
|
||||||
bool exact_match_flag;
|
|
||||||
bool broken_link_flag;
|
|
||||||
int changing_slice_group_idc;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MEDIA_EXPORT H264SEIMessage {
|
|
||||||
H264SEIMessage();
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
kSEIRecoveryPoint = 6,
|
|
||||||
};
|
|
||||||
|
|
||||||
int type;
|
|
||||||
int payload_size;
|
|
||||||
union {
|
|
||||||
// Placeholder; in future more supported types will contribute to more
|
|
||||||
// union members here.
|
|
||||||
H264SEIRecoveryPoint recovery_point;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Class to parse an Annex-B H.264 stream,
|
|
||||||
// as specified in chapters 7 and Annex B of the H.264 spec.
|
|
||||||
class MEDIA_EXPORT H264Parser {
|
|
||||||
public:
|
|
||||||
enum Result {
|
|
||||||
kOk,
|
|
||||||
kInvalidStream, // error in stream
|
|
||||||
kUnsupportedStream, // stream not supported by the parser
|
|
||||||
kEOStream, // end of stream
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find offset from start of data to next NALU start code
|
|
||||||
// and size of found start code (3 or 4 bytes).
|
|
||||||
// If no start code is found, offset is pointing to the first unprocessed byte
|
|
||||||
// (i.e. the first byte that was not considered as a possible start of a start
|
|
||||||
// code) and |*start_code_size| is set to 0.
|
|
||||||
// Preconditions:
|
|
||||||
// - |data_size| >= 0
|
|
||||||
// Postconditions:
|
|
||||||
// - |*offset| is between 0 and |data_size| included.
|
|
||||||
// It is strictly less than |data_size| if |data_size| > 0.
|
|
||||||
// - |*start_code_size| is either 0, 3 or 4.
|
|
||||||
static bool FindStartCode(const uint8_t* data,
|
|
||||||
off_t data_size,
|
|
||||||
off_t* offset,
|
|
||||||
off_t* start_code_size);
|
|
||||||
|
|
||||||
// Wrapper for FindStartCode() that skips over start codes that
|
|
||||||
// may appear inside of |encrypted_ranges_|.
|
|
||||||
// Returns true if a start code was found. Otherwise returns false.
|
|
||||||
static bool FindStartCodeInClearRanges(const uint8_t* data,
|
|
||||||
off_t data_size,
|
|
||||||
const Ranges<const uint8_t*>& ranges,
|
|
||||||
off_t* offset,
|
|
||||||
off_t* start_code_size);
|
|
||||||
H264Parser();
|
|
||||||
~H264Parser();
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
// Set current stream pointer to |stream| of |stream_size| in bytes,
|
|
||||||
// |stream| owned by caller.
|
|
||||||
// |subsamples| contains information about what parts of |stream| are
|
|
||||||
// encrypted.
|
|
||||||
void SetStream(const uint8_t* stream, off_t stream_size);
|
|
||||||
void SetEncryptedStream(const uint8_t* stream,
|
|
||||||
off_t stream_size,
|
|
||||||
const std::vector<SubsampleEntry>& subsamples);
|
|
||||||
|
|
||||||
// Read the stream to find the next NALU, identify it and return
|
|
||||||
// that information in |*nalu|. This advances the stream to the beginning
|
|
||||||
// of this NALU, but not past it, so subsequent calls to NALU-specific
|
|
||||||
// parsing functions (ParseSPS, etc.) will parse this NALU.
|
|
||||||
// If the caller wishes to skip the current NALU, it can call this function
|
|
||||||
// again, instead of any NALU-type specific parse functions below.
|
|
||||||
Result AdvanceToNextNALU(H264NALU* nalu);
|
|
||||||
|
|
||||||
// NALU-specific parsing functions.
|
|
||||||
// These should be called after AdvanceToNextNALU().
|
|
||||||
|
|
||||||
// SPSes and PPSes are owned by the parser class and the memory for their
|
|
||||||
// structures is managed here, not by the caller, as they are reused
|
|
||||||
// across NALUs.
|
|
||||||
//
|
|
||||||
// Parse an SPS/PPS NALU and save their data in the parser, returning id
|
|
||||||
// of the parsed structure in |*pps_id|/|*sps_id|.
|
|
||||||
// To get a pointer to a given SPS/PPS structure, use GetSPS()/GetPPS(),
|
|
||||||
// passing the returned |*sps_id|/|*pps_id| as parameter.
|
|
||||||
// TODO(posciak,fischman): consider replacing returning Result from Parse*()
|
|
||||||
// methods with a scoped_ptr and adding an AtEOS() function to check for EOS
|
|
||||||
// if Parse*() return NULL.
|
|
||||||
Result ParseSPS(int* sps_id);
|
|
||||||
Result ParsePPS(int* pps_id);
|
|
||||||
|
|
||||||
// Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not
|
|
||||||
// present.
|
|
||||||
const H264SPS* GetSPS(int sps_id) const;
|
|
||||||
const H264PPS* GetPPS(int pps_id) const;
|
|
||||||
|
|
||||||
// Slice headers and SEI messages are not used across NALUs by the parser
|
|
||||||
// and can be discarded after current NALU, so the parser does not store
|
|
||||||
// them, nor does it manage their memory.
|
|
||||||
// The caller has to provide and manage it instead.
|
|
||||||
|
|
||||||
// Parse a slice header, returning it in |*shdr|. |*nalu| must be set to
|
|
||||||
// the NALU returned from AdvanceToNextNALU() and corresponding to |*shdr|.
|
|
||||||
Result ParseSliceHeader(const H264NALU& nalu, H264SliceHeader* shdr);
|
|
||||||
|
|
||||||
// Parse a SEI message, returning it in |*sei_msg|, provided and managed
|
|
||||||
// by the caller.
|
|
||||||
Result ParseSEI(H264SEIMessage* sei_msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Move the stream pointer to the beginning of the next NALU,
|
|
||||||
// i.e. pointing at the next start code.
|
|
||||||
// Return true if a NALU has been found.
|
|
||||||
// If a NALU is found:
|
|
||||||
// - its size in bytes is returned in |*nalu_size| and includes
|
|
||||||
// the start code as well as the trailing zero bits.
|
|
||||||
// - the size in bytes of the start code is returned in |*start_code_size|.
|
|
||||||
bool LocateNALU(off_t* nalu_size, off_t* start_code_size);
|
|
||||||
|
|
||||||
// Exp-Golomb code parsing as specified in chapter 9.1 of the spec.
|
|
||||||
// Read one unsigned exp-Golomb code from the stream and return in |*val|.
|
|
||||||
Result ReadUE(int* val);
|
|
||||||
|
|
||||||
// Read one signed exp-Golomb code from the stream and return in |*val|.
|
|
||||||
Result ReadSE(int* val);
|
|
||||||
|
|
||||||
// Parse scaling lists (see spec).
|
|
||||||
Result ParseScalingList(int size, int* scaling_list, bool* use_default);
|
|
||||||
Result ParseSPSScalingLists(H264SPS* sps);
|
|
||||||
Result ParsePPSScalingLists(const H264SPS& sps, H264PPS* pps);
|
|
||||||
|
|
||||||
// Parse optional VUI parameters in SPS (see spec).
|
|
||||||
Result ParseVUIParameters(H264SPS* sps);
|
|
||||||
// Set |hrd_parameters_present| to true only if they are present.
|
|
||||||
Result ParseAndIgnoreHRDParameters(bool* hrd_parameters_present);
|
|
||||||
|
|
||||||
// Parse reference picture lists' modifications (see spec).
|
|
||||||
Result ParseRefPicListModifications(H264SliceHeader* shdr);
|
|
||||||
Result ParseRefPicListModification(int num_ref_idx_active_minus1,
|
|
||||||
H264ModificationOfPicNum* ref_list_mods);
|
|
||||||
|
|
||||||
// Parse prediction weight table (see spec).
|
|
||||||
Result ParsePredWeightTable(const H264SPS& sps, H264SliceHeader* shdr);
|
|
||||||
|
|
||||||
// Parse weighting factors (see spec).
|
|
||||||
Result ParseWeightingFactors(int num_ref_idx_active_minus1,
|
|
||||||
int chroma_array_type,
|
|
||||||
int luma_log2_weight_denom,
|
|
||||||
int chroma_log2_weight_denom,
|
|
||||||
H264WeightingFactors* w_facts);
|
|
||||||
|
|
||||||
// Parse decoded reference picture marking information (see spec).
|
|
||||||
Result ParseDecRefPicMarking(H264SliceHeader* shdr);
|
|
||||||
|
|
||||||
// Pointer to the current NALU in the stream.
|
|
||||||
const uint8_t* stream_;
|
|
||||||
|
|
||||||
// Bytes left in the stream after the current NALU.
|
|
||||||
off_t bytes_left_;
|
|
||||||
|
|
||||||
H264BitReader br_;
|
|
||||||
|
|
||||||
// PPSes and SPSes stored for future reference.
|
|
||||||
typedef std::map<int, H264SPS*> SPSById;
|
|
||||||
typedef std::map<int, H264PPS*> PPSById;
|
|
||||||
SPSById active_SPSes_;
|
|
||||||
PPSById active_PPSes_;
|
|
||||||
|
|
||||||
// Ranges of encrypted bytes in the buffer passed to
|
|
||||||
// SetEncryptedStream().
|
|
||||||
Ranges<const uint8_t*> encrypted_ranges_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(H264Parser);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace media
|
|
||||||
|
|
||||||
#endif // MEDIA_FILTERS_H264_PARSER_H_
|
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef MEDIA_VIDEO_H264_POC_H_
|
|
||||||
#define MEDIA_VIDEO_H264_POC_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "macros.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace media {
|
|
||||||
|
|
||||||
struct H264SPS;
|
|
||||||
struct H264SliceHeader;
|
|
||||||
|
|
||||||
class MEDIA_EXPORT H264POC {
|
|
||||||
public:
|
|
||||||
H264POC();
|
|
||||||
~H264POC();
|
|
||||||
|
|
||||||
// Compute the picture order count for a slice, storing the result into
|
|
||||||
// |*pic_order_cnt|.
|
|
||||||
bool ComputePicOrderCnt(
|
|
||||||
const H264SPS* sps,
|
|
||||||
const H264SliceHeader& slice_hdr,
|
|
||||||
int32_t* pic_order_cnt);
|
|
||||||
|
|
||||||
// Reset computation state. It's best (although not strictly required) to call
|
|
||||||
// this after a seek.
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int32_t ref_pic_order_cnt_msb_;
|
|
||||||
int32_t ref_pic_order_cnt_lsb_;
|
|
||||||
int32_t prev_frame_num_;
|
|
||||||
int32_t prev_frame_num_offset_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(H264POC);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace media
|
|
||||||
|
|
||||||
#endif // MEDIA_VIDEO_H264_POC_H_
|
|
@ -1,100 +0,0 @@
|
|||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// This file contains macros and macro-like constructs (e.g., templates) that
|
|
||||||
// are commonly used throughout Chromium source. (It may also contain things
|
|
||||||
// that are closely related to things that are commonly used that belong in this
|
|
||||||
// file.)
|
|
||||||
|
|
||||||
#ifndef BASE_MACROS_H_
|
|
||||||
#define BASE_MACROS_H_
|
|
||||||
|
|
||||||
#include <stddef.h> // For size_t.
|
|
||||||
|
|
||||||
// Put this in the declarations for a class to be uncopyable.
|
|
||||||
#define DISALLOW_COPY(TypeName) \
|
|
||||||
TypeName(const TypeName&) = delete
|
|
||||||
|
|
||||||
// Put this in the declarations for a class to be unassignable.
|
|
||||||
#define DISALLOW_ASSIGN(TypeName) \
|
|
||||||
void operator=(const TypeName&) = delete
|
|
||||||
|
|
||||||
// A macro to disallow the copy constructor and operator= functions.
|
|
||||||
// This should be used in the private: declarations for a class.
|
|
||||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
|
||||||
TypeName(const TypeName&) = delete; \
|
|
||||||
void operator=(const TypeName&) = delete
|
|
||||||
|
|
||||||
// A macro to disallow all the implicit constructors, namely the
|
|
||||||
// default constructor, copy constructor and operator= functions.
|
|
||||||
//
|
|
||||||
// This should be used in the private: declarations for a class
|
|
||||||
// that wants to prevent anyone from instantiating it. This is
|
|
||||||
// especially useful for classes containing only static methods.
|
|
||||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
|
||||||
TypeName() = delete; \
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
|
||||||
|
|
||||||
// The arraysize(arr) macro returns the # of elements in an array arr. The
|
|
||||||
// expression is a compile-time constant, and therefore can be used in defining
|
|
||||||
// new arrays, for example. If you use arraysize on a pointer by mistake, you
|
|
||||||
// will get a compile-time error. For the technical details, refer to
|
|
||||||
// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx.
|
|
||||||
|
|
||||||
// This template function declaration is used in defining arraysize.
|
|
||||||
// Note that the function doesn't need an implementation, as we only
|
|
||||||
// use its type.
|
|
||||||
template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
|
|
||||||
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
|
||||||
|
|
||||||
// Used to explicitly mark the return value of a function as unused. If you are
|
|
||||||
// really sure you don't want to do anything with the return value of a function
|
|
||||||
// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:
|
|
||||||
//
|
|
||||||
// std::unique_ptr<MyType> my_var = ...;
|
|
||||||
// if (TakeOwnership(my_var.get()) == SUCCESS)
|
|
||||||
// ignore_result(my_var.release());
|
|
||||||
//
|
|
||||||
template<typename T>
|
|
||||||
inline void ignore_result(const T&) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following enum should be used only as a constructor argument to indicate
|
|
||||||
// that the variable has static storage class, and that the constructor should
|
|
||||||
// do nothing to its state. It indicates to the reader that it is legal to
|
|
||||||
// declare a static instance of the class, provided the constructor is given
|
|
||||||
// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a
|
|
||||||
// static variable that has a constructor or a destructor because invocation
|
|
||||||
// order is undefined. However, IF the type can be initialized by filling with
|
|
||||||
// zeroes (which the loader does for static variables), AND the destructor also
|
|
||||||
// does nothing to the storage, AND there are no virtual methods, then a
|
|
||||||
// constructor declared as
|
|
||||||
// explicit MyClass(base::LinkerInitialized x) {}
|
|
||||||
// and invoked as
|
|
||||||
// static MyClass my_variable_name(base::LINKER_INITIALIZED);
|
|
||||||
namespace base {
|
|
||||||
enum LinkerInitialized { LINKER_INITIALIZED };
|
|
||||||
|
|
||||||
// Use these to declare and define a static local variable (static T;) so that
|
|
||||||
// it is leaked so that its destructors are not called at exit. If you need
|
|
||||||
// thread-safe initialization, use base/lazy_instance.h instead.
|
|
||||||
#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
|
|
||||||
static type& name = *new type arguments
|
|
||||||
|
|
||||||
} // base
|
|
||||||
|
|
||||||
#define MEDIA_EXPORT
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "Util/logger.h"
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
|
|
||||||
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }
|
|
||||||
#define DCHECK_GE(x,y) if(!((x) >= (y))) { ErrorL << "DCHECK_GE:" << #x << #y << endl; }
|
|
||||||
#define DCHECK_LT(x,y) if(!((x) < (y))) { ErrorL << "DCHECK_LT:" << #x << #y << endl; }
|
|
||||||
#define NOTREACHED() ErrorL << "NOTREACHED" << endl;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BASE_MACROS_H_
|
|
@ -1,154 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef MEDIA_BASE_RANGES_H_
|
|
||||||
#define MEDIA_BASE_RANGES_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <ostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace media {
|
|
||||||
|
|
||||||
// Ranges allows holding an ordered list of ranges of [start,end) intervals.
|
|
||||||
// The canonical example use-case is holding the list of ranges of buffered
|
|
||||||
// bytes or times in a <video> tag.
|
|
||||||
template <typename T> // Endpoint type; typically a base::TimeDelta or an int64_t.
|
|
||||||
class Ranges {
|
|
||||||
public:
|
|
||||||
// Allow copy & assign.
|
|
||||||
|
|
||||||
// Add (start,end) to this object, coallescing overlaps as appropriate.
|
|
||||||
// Returns the number of stored ranges, post coallescing.
|
|
||||||
size_t Add(T start, T end);
|
|
||||||
|
|
||||||
// Return the number of disjoint ranges.
|
|
||||||
size_t size() const;
|
|
||||||
|
|
||||||
// Return the "i"'th range's start & end (0-based).
|
|
||||||
T start(size_t i) const;
|
|
||||||
T end(size_t i) const;
|
|
||||||
|
|
||||||
// Clear all ranges.
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
// Computes the intersection between this range and |other|.
|
|
||||||
Ranges<T> IntersectionWith(const Ranges<T>& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Wrapper around DCHECK_LT allowing comparisons of operator<<'able T's.
|
|
||||||
void DCheckLT(const T& lhs, const T& rhs) const;
|
|
||||||
|
|
||||||
// Disjoint, in increasing order of start.
|
|
||||||
std::vector<std::pair<T, T> > ranges_;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// EVERYTHING BELOW HERE IS IMPLEMENTATION DETAIL!!
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
size_t Ranges<T>::Add(T start, T end) {
|
|
||||||
if (start == end) // Nothing to be done with empty ranges.
|
|
||||||
return ranges_.size();
|
|
||||||
|
|
||||||
//DCheckLT(start, end);
|
|
||||||
size_t i;
|
|
||||||
// Walk along the array of ranges until |start| is no longer larger than the
|
|
||||||
// current interval's end.
|
|
||||||
for (i = 0; i < ranges_.size() && ranges_[i].second < start; ++i) {
|
|
||||||
// Empty body
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we know |start| belongs in the i'th slot.
|
|
||||||
// If i is the end of the range, append new range and done.
|
|
||||||
if (i == ranges_.size()) {
|
|
||||||
ranges_.push_back(std::make_pair(start, end));
|
|
||||||
return ranges_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If |end| is less than i->first, then [start,end) is a new (non-overlapping)
|
|
||||||
// i'th entry pushing everyone else back, and done.
|
|
||||||
if (end < ranges_[i].first) {
|
|
||||||
ranges_.insert(ranges_.begin() + i, std::make_pair(start, end));
|
|
||||||
return ranges_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Easy cases done. Getting here means there is overlap between [start,end)
|
|
||||||
// and the existing ranges.
|
|
||||||
|
|
||||||
// Now: start <= i->second && i->first <= end
|
|
||||||
if (start < ranges_[i].first)
|
|
||||||
ranges_[i].first = start;
|
|
||||||
if (ranges_[i].second < end)
|
|
||||||
ranges_[i].second = end;
|
|
||||||
|
|
||||||
// Now: [start,end) is contained in the i'th range, and we'd be done, except
|
|
||||||
// for the fact that the newly-extended i'th range might now overlap
|
|
||||||
// subsequent ranges. Merge until discontinuities appear. Note that there's
|
|
||||||
// no need to test/merge previous ranges, since needing that would mean the
|
|
||||||
// original loop went too far.
|
|
||||||
while ((i + 1) < ranges_.size() &&
|
|
||||||
ranges_[i + 1].first <= ranges_[i].second) {
|
|
||||||
ranges_[i].second = max(ranges_[i].second, ranges_[i + 1].second);
|
|
||||||
ranges_.erase(ranges_.begin() + i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ranges_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
size_t Ranges<T>::size() const {
|
|
||||||
return ranges_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T Ranges<T>::start(size_t i) const {
|
|
||||||
return ranges_[i].first;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T Ranges<T>::end(size_t i) const {
|
|
||||||
return ranges_[i].second;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void Ranges<T>::clear() {
|
|
||||||
ranges_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
Ranges<T> Ranges<T>::IntersectionWith(const Ranges<T>& other) const {
|
|
||||||
Ranges<T> result;
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
size_t j = 0;
|
|
||||||
|
|
||||||
while (i < size() && j < other.size()) {
|
|
||||||
T max_start = max(start(i), other.start(j));
|
|
||||||
T min_end = min(end(i), other.end(j));
|
|
||||||
|
|
||||||
// Add an intersection range to the result if the ranges overlap.
|
|
||||||
if (max_start < min_end)
|
|
||||||
result.Add(max_start, min_end);
|
|
||||||
|
|
||||||
if (end(i) < other.end(j))
|
|
||||||
++i;
|
|
||||||
else
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace media
|
|
||||||
|
|
||||||
#endif // MEDIA_BASE_RANGES_H_
|
|
@ -1,130 +0,0 @@
|
|||||||
//
|
|
||||||
// HttpClient.h
|
|
||||||
// ZLMediaKit
|
|
||||||
//
|
|
||||||
// Created by xzl on 2017/5/4.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef Http_HttpClient_h
|
|
||||||
#define Http_HttpClient_h
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include "Rtsp/Rtsp.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Network/TcpClient.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
class HttpArgs : public StrCaseMap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HttpArgs(){}
|
|
||||||
virtual ~HttpArgs(){}
|
|
||||||
string make() const {
|
|
||||||
string ret;
|
|
||||||
for(auto &pr : *this){
|
|
||||||
ret.append(pr.first);
|
|
||||||
ret.append("=");
|
|
||||||
ret.append(pr.second);
|
|
||||||
ret.append("&");
|
|
||||||
}
|
|
||||||
if(ret.size()){
|
|
||||||
ret.pop_back();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class HttpClient : public TcpClient
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef StrCaseMap HttpHeader;
|
|
||||||
typedef std::shared_ptr<HttpClient> Ptr;
|
|
||||||
HttpClient();
|
|
||||||
virtual ~HttpClient();
|
|
||||||
virtual void sendRequest(const string &url);
|
|
||||||
void clear(){
|
|
||||||
_header.clear();
|
|
||||||
_body.clear();
|
|
||||||
_method.clear();
|
|
||||||
_path.clear();
|
|
||||||
_recvedResponse.clear();
|
|
||||||
_parser.Clear();
|
|
||||||
}
|
|
||||||
void setMethod(const string &method){
|
|
||||||
_method = method;
|
|
||||||
}
|
|
||||||
void setHeader(const HttpHeader &header){
|
|
||||||
_header = header;
|
|
||||||
}
|
|
||||||
void addHeader(const string &key,const string &val){
|
|
||||||
_header.emplace(key,val);
|
|
||||||
}
|
|
||||||
void setBody(const string &body){
|
|
||||||
_body = body;
|
|
||||||
}
|
|
||||||
const string &responseStatus(){
|
|
||||||
return _parser.Url();
|
|
||||||
}
|
|
||||||
const HttpHeader &responseHeader(){
|
|
||||||
return _parser.getValues();
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
bool _isHttps;
|
|
||||||
|
|
||||||
virtual void onResponseHeader(const string &status,const HttpHeader &headers){
|
|
||||||
DebugL << status;
|
|
||||||
};
|
|
||||||
virtual void onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize){
|
|
||||||
DebugL << size << " " << recvedSize << " " << totalSize;
|
|
||||||
};
|
|
||||||
virtual void onResponseCompleted(){
|
|
||||||
DebugL;
|
|
||||||
}
|
|
||||||
virtual void onRecvBytes(const char *data,int size);
|
|
||||||
virtual void onDisconnect(const SockException &ex){}
|
|
||||||
private:
|
|
||||||
virtual void onConnect(const SockException &ex) override;
|
|
||||||
virtual void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
virtual void onErr(const SockException &ex) override;
|
|
||||||
|
|
||||||
//send
|
|
||||||
HttpHeader _header;
|
|
||||||
string _body;
|
|
||||||
string _method;
|
|
||||||
string _path;
|
|
||||||
|
|
||||||
//recv
|
|
||||||
string _recvedResponse;
|
|
||||||
size_t _recvedBodySize;
|
|
||||||
size_t _totalBodySize;
|
|
||||||
Parser _parser;
|
|
||||||
|
|
||||||
string _lastHost;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* Http_HttpClient_h */
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* HttpClientImp.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年5月4日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_HTTP_HTTPCLIENTIMP_H_
|
|
||||||
#define SRC_HTTP_HTTPCLIENTIMP_H_
|
|
||||||
|
|
||||||
#include "HttpClient.h"
|
|
||||||
#ifdef ENABLE_OPENSSL
|
|
||||||
#include "Util/SSLBox.h"
|
|
||||||
using namespace ZL::Util;
|
|
||||||
#endif //ENABLE_OPENSSL
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
class HttpClientImp: public HttpClient {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<HttpClientImp> Ptr;
|
|
||||||
HttpClientImp();
|
|
||||||
virtual ~HttpClientImp();
|
|
||||||
virtual void sendRequest(const string &url) override;
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
void public_onRecvBytes(const char *data,int len){
|
|
||||||
HttpClient::onRecvBytes(data,len);
|
|
||||||
}
|
|
||||||
void public_send(const char *data, uint32_t len){
|
|
||||||
HttpClient::send(data,len);
|
|
||||||
}
|
|
||||||
#endif //defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
private:
|
|
||||||
#ifdef ENABLE_OPENSSL
|
|
||||||
virtual void onRecvBytes(const char *data,int size) override;
|
|
||||||
virtual int send(const string &str) override;
|
|
||||||
virtual int send(const char *str, int len) override;
|
|
||||||
std::shared_ptr<SSL_Box> _sslBox;
|
|
||||||
#endif //ENABLE_OPENSSL
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_HTTP_HTTPCLIENTIMP_H_ */
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* HttpDownloader.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年5月5日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_HTTP_HTTPDOWNLOADER_H_
|
|
||||||
#define SRC_HTTP_HTTPDOWNLOADER_H_
|
|
||||||
|
|
||||||
#include "HttpClientImp.h"
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
class HttpDownloader: public HttpClientImp {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<HttpDownloader> Ptr;
|
|
||||||
typedef std::function<void(ErrCode code,const char *errMsg,const char *filePath)> onDownloadResult;
|
|
||||||
HttpDownloader();
|
|
||||||
virtual ~HttpDownloader();
|
|
||||||
//开始下载文件,默认断点续传方式下载
|
|
||||||
void startDownload(const string &url,const string &filePath = "",bool bAppend = false);
|
|
||||||
void startDownload(const string &url,const onDownloadResult &cb){
|
|
||||||
setOnResult(cb);
|
|
||||||
startDownload(url);
|
|
||||||
}
|
|
||||||
void setOnResult(const onDownloadResult &cb){
|
|
||||||
_onResult = cb;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void onResponseHeader(const string &status,const HttpHeader &headers) override;
|
|
||||||
void onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) override;
|
|
||||||
void onResponseCompleted() override;
|
|
||||||
void onDisconnect(const SockException &ex) override;
|
|
||||||
void closeFile();
|
|
||||||
|
|
||||||
FILE *_saveFile = nullptr;
|
|
||||||
string _filePath;
|
|
||||||
onDownloadResult _onResult;
|
|
||||||
bool _bDownloadSuccess = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_HTTP_HTTPDOWNLOADER_H_ */
|
|
@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// HttpRequester_h
|
|
||||||
// ZLMediaKit
|
|
||||||
//
|
|
||||||
// Created by xzl on 2017/5/5.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef Htt_HttpRequester_h
|
|
||||||
#define Htt_HttpRequester_h
|
|
||||||
|
|
||||||
#include "HttpClientImp.h"
|
|
||||||
|
|
||||||
namespace ZL{
|
|
||||||
namespace Http{
|
|
||||||
|
|
||||||
class HttpRequester : public HttpClientImp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<HttpRequester> Ptr;
|
|
||||||
typedef std::function<void(const SockException &ex,const string &status,const HttpHeader &header,const string &strRecvBody)> HttpRequesterResult;
|
|
||||||
HttpRequester();
|
|
||||||
virtual ~HttpRequester();
|
|
||||||
|
|
||||||
void startRequester(const string &url,const HttpRequesterResult &onResult);
|
|
||||||
private:
|
|
||||||
void onResponseHeader(const string &status,const HttpHeader &headers) override;
|
|
||||||
void onResponseBody(const char *buf,size_t size,size_t recvedSize,size_t totalSize) override;
|
|
||||||
void onResponseCompleted() override;
|
|
||||||
void onDisconnect(const SockException &ex) override;
|
|
||||||
|
|
||||||
string _strRecvBody;
|
|
||||||
HttpRequesterResult _onResult;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}//namespace Http
|
|
||||||
}//namespace ZL
|
|
||||||
|
|
||||||
#endif /* Htt_HttpRequester_h */
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* HttpSession.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月22日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_HTTP_HTTPSESSION_H_
|
|
||||||
#define SRC_HTTP_HTTPSESSION_H_
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Rtsp/Rtsp.h"
|
|
||||||
#include "Network/TcpLimitedSession.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
|
|
||||||
class HttpSession: public TcpLimitedSession<MAX_TCP_SESSION> {
|
|
||||||
public:
|
|
||||||
typedef StrCaseMap KeyValue;
|
|
||||||
typedef std::function<void(const string &codeOut,
|
|
||||||
const KeyValue &headerOut,
|
|
||||||
const string &contentOut)> HttpResponseInvoker;
|
|
||||||
|
|
||||||
HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock);
|
|
||||||
virtual ~HttpSession();
|
|
||||||
|
|
||||||
virtual void onRecv(const Socket::Buffer::Ptr &) override;
|
|
||||||
virtual void onError(const SockException &err) override;
|
|
||||||
virtual void onManager() override;
|
|
||||||
protected:
|
|
||||||
void onRecv(const char *data,int size);
|
|
||||||
private:
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
Http_success = 0,
|
|
||||||
Http_failed = 1,
|
|
||||||
Http_moreData = 2,
|
|
||||||
} HttpCode;
|
|
||||||
typedef HttpSession::HttpCode (HttpSession::*HttpCMDHandle)();
|
|
||||||
static unordered_map<string, HttpCMDHandle> g_mapCmdIndex;
|
|
||||||
|
|
||||||
Parser m_parser;
|
|
||||||
string m_strPath;
|
|
||||||
string m_strRcvBuf;
|
|
||||||
Ticker m_ticker;
|
|
||||||
uint32_t m_iReqCnt = 0;
|
|
||||||
|
|
||||||
|
|
||||||
inline HttpCode parserHttpReq(const string &);
|
|
||||||
inline HttpCode Handle_Req_GET();
|
|
||||||
inline HttpCode Handle_Req_POST();
|
|
||||||
inline bool makeMeun(const string &strFullPath, string &strRet);
|
|
||||||
inline void sendNotFound(bool bClose);
|
|
||||||
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");
|
|
||||||
void responseDelay(bool bClose,string &codeOut,KeyValue &headerOut, string &contentOut);
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_HTTP_HTTPSESSION_H_ */
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* HttpsSession.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年4月19日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_HTTP_HTTPSSESSION_H_
|
|
||||||
#define SRC_HTTP_HTTPSSESSION_H_
|
|
||||||
|
|
||||||
#include "HttpSession.h"
|
|
||||||
#include "Util/SSLBox.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
class HttpsSession: public HttpSession {
|
|
||||||
public:
|
|
||||||
HttpsSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock):
|
|
||||||
HttpSession(pTh,pSock){
|
|
||||||
m_sslBox.setOnEncData([&](const char *data, uint32_t len){
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
public_send(data,len);
|
|
||||||
#else//defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
HttpSession::send(data,len);
|
|
||||||
#endif//defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
});
|
|
||||||
m_sslBox.setOnDecData([&](const char *data, uint32_t len){
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
public_onRecv(data,len);
|
|
||||||
#else//defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
HttpSession::onRecv(data,len);
|
|
||||||
#endif//defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
virtual ~HttpsSession(){
|
|
||||||
//m_sslBox.shutdown();
|
|
||||||
}
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override{
|
|
||||||
TimeTicker();
|
|
||||||
m_sslBox.onRecv(pBuf->data(), pBuf->size());
|
|
||||||
}
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
int public_send(const char *data, uint32_t len){
|
|
||||||
return HttpSession::send(data,len);
|
|
||||||
}
|
|
||||||
void public_onRecv(const char *data, uint32_t len){
|
|
||||||
HttpSession::onRecv(data,len);
|
|
||||||
}
|
|
||||||
#endif//defined(__GNUC__) && (__GNUC__ < 5)
|
|
||||||
private:
|
|
||||||
virtual int send(const string &buf) override{
|
|
||||||
TimeTicker();
|
|
||||||
m_sslBox.onSend(buf.data(), buf.size());
|
|
||||||
return buf.size();
|
|
||||||
}
|
|
||||||
virtual int send(const char *buf, int size) override{
|
|
||||||
TimeTicker();
|
|
||||||
m_sslBox.onSend(buf, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
SSL_Box m_sslBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_HTTP_HTTPSSESSION_H_ */
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* strCoding.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月22日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_HTTP_STRCODING_H_
|
|
||||||
#define SRC_HTTP_STRCODING_H_
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Http {
|
|
||||||
|
|
||||||
class strCoding {
|
|
||||||
public:
|
|
||||||
static string UrlUTF8Encode(const char * str); //urlutf8 编码
|
|
||||||
static string UrlUTF8Decode(const string &str); //urlutf8解码
|
|
||||||
private:
|
|
||||||
strCoding(void);
|
|
||||||
virtual ~strCoding(void);
|
|
||||||
static inline char CharToInt(char ch);
|
|
||||||
static inline char StrToBin(const char *str);
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Http */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_HTTP_STRCODING_H_ */
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* HLSMaker.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-6-24
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HLSMAKER_H_
|
|
||||||
#define HLSMAKER_H_
|
|
||||||
|
|
||||||
#include "TSMaker.h"
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Util/File.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace MediaFile {
|
|
||||||
|
|
||||||
class HLSMaker {
|
|
||||||
public:
|
|
||||||
HLSMaker(const string &strM3u8File,
|
|
||||||
const string &strHttpUrl,
|
|
||||||
uint32_t ui32BufSize = 64 * 1024,
|
|
||||||
uint32_t ui32Duration = 5,
|
|
||||||
uint32_t ui32Num = 3);
|
|
||||||
|
|
||||||
virtual ~HLSMaker();
|
|
||||||
|
|
||||||
//时间戳:参考频率90000
|
|
||||||
void inputH264( void *pData,
|
|
||||||
uint32_t ui32Length,
|
|
||||||
uint32_t ui32TimeStamp,
|
|
||||||
int iType);
|
|
||||||
|
|
||||||
//时间戳:参考频率90000
|
|
||||||
void inputAAC( void *pData,
|
|
||||||
uint32_t ui32Length,
|
|
||||||
uint32_t ui32TimeStamp);
|
|
||||||
private:
|
|
||||||
TSMaker m_ts;
|
|
||||||
string m_strM3u8File;
|
|
||||||
string m_strHttpUrl;
|
|
||||||
string m_strFileName;
|
|
||||||
string m_strOutputPrefix;
|
|
||||||
string m_strTmpFileName;
|
|
||||||
uint32_t m_ui32SegmentDuration;
|
|
||||||
uint32_t m_ui32NumSegments;
|
|
||||||
uint64_t m_ui64TsCnt;
|
|
||||||
uint32_t m_ui32BufSize;
|
|
||||||
Ticker m_Timer;
|
|
||||||
|
|
||||||
int write_index_file(int iFirstSegment, unsigned int uiLastSegment, int iEnd);
|
|
||||||
void removets();
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace MediaFile */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* HLSMAKER_H_ */
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* MediaReader.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月14日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_MEDIAFILE_MEDIAREADER_H_
|
|
||||||
#define SRC_MEDIAFILE_MEDIAREADER_H_
|
|
||||||
|
|
||||||
#include "Device/Device.h"
|
|
||||||
#include "Rtsp/RtspMediaSource.h"
|
|
||||||
#include "Rtmp/RtmpMediaSource.h"
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4V2
|
|
||||||
#include <mp4v2/mp4v2.h>
|
|
||||||
#endif //ENABLE_MP4V2
|
|
||||||
|
|
||||||
using namespace ZL::DEV;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::Rtmp;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace MediaFile {
|
|
||||||
|
|
||||||
class MediaReader : public std::enable_shared_from_this<MediaReader>{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<MediaReader> Ptr;
|
|
||||||
MediaReader(const string &strApp, const string &strId);
|
|
||||||
virtual ~MediaReader();
|
|
||||||
static RtspMediaSource::Ptr onMakeRtsp(const string &strApp, const string &strId);
|
|
||||||
static RtmpMediaSource::Ptr onMakeRtmp(const string &strApp, const string &strId);
|
|
||||||
private:
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4V2
|
|
||||||
MP4FileHandle m_hMP4File = MP4_INVALID_FILE_HANDLE;
|
|
||||||
MP4TrackId m_video_trId = MP4_INVALID_TRACK_ID;
|
|
||||||
uint32_t m_video_ms = 0;
|
|
||||||
uint32_t m_video_num_samples = 0;
|
|
||||||
uint32_t m_video_sample_max_size = 0;
|
|
||||||
uint32_t m_video_width = 0;
|
|
||||||
uint32_t m_video_height = 0;
|
|
||||||
uint32_t m_video_framerate = 0;
|
|
||||||
string m_strPps;
|
|
||||||
string m_strSps;
|
|
||||||
bool m_bSyncSample = false;
|
|
||||||
|
|
||||||
MP4TrackId m_audio_trId = MP4_INVALID_TRACK_ID;
|
|
||||||
uint32_t m_audio_ms = 0;
|
|
||||||
uint32_t m_audio_num_samples = 0;
|
|
||||||
uint32_t m_audio_sample_max_size = 0;
|
|
||||||
uint32_t m_audio_sample_rate = 0;
|
|
||||||
uint32_t m_audio_num_channels = 0;
|
|
||||||
string m_strAacCfg;
|
|
||||||
AdtsFrame m_adts;
|
|
||||||
|
|
||||||
int m_iDuration = 0;
|
|
||||||
DevChannel::Ptr m_pChn;
|
|
||||||
MP4SampleId m_video_current = 0;
|
|
||||||
MP4SampleId m_audio_current = 0;
|
|
||||||
std::shared_ptr<uint8_t> m_pcVideoSample;
|
|
||||||
|
|
||||||
int m_iSeekTime = 0 ;
|
|
||||||
Ticker m_ticker;
|
|
||||||
Ticker m_alive;
|
|
||||||
recursive_mutex m_mtx;
|
|
||||||
|
|
||||||
void seek(int iSeekTime,bool bReStart = true);
|
|
||||||
inline void setSeekTime(int iSeekTime);
|
|
||||||
inline uint32_t getVideoCurrentTime();
|
|
||||||
void startReadMP4();
|
|
||||||
inline MP4SampleId getVideoSampleId(int iTimeInc = 0);
|
|
||||||
inline MP4SampleId getAudioSampleId(int iTimeInc = 0);
|
|
||||||
bool readSample(int iTimeInc = 0);
|
|
||||||
inline bool readVideoSample(int iTimeInc = 0);
|
|
||||||
inline bool readAudioSample(int iTimeInc = 0);
|
|
||||||
inline void writeH264(uint8_t *pucData,int iLen,uint32_t uiStamp);
|
|
||||||
inline void writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp);
|
|
||||||
#endif //ENABLE_MP4V2
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace MediaFile */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_MEDIAFILE_MEDIAREADER_H_ */
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* MediaRecorder.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月8日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_MEDIAFILE_MEDIARECORDER_H_
|
|
||||||
#define SRC_MEDIAFILE_MEDIARECORDER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4V2
|
|
||||||
#include "Mp4Maker.h"
|
|
||||||
#endif //ENABLE_MP4V2
|
|
||||||
|
|
||||||
#ifdef ENABLE_HLS
|
|
||||||
#include "HLSMaker.h"
|
|
||||||
#endif //ENABLE_HLS
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace MediaFile {
|
|
||||||
|
|
||||||
|
|
||||||
class MediaRecorder {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<MediaRecorder> Ptr;
|
|
||||||
MediaRecorder(const string &strApp,const string &strId,const std::shared_ptr<PlayerBase> &pPlayer);
|
|
||||||
virtual ~MediaRecorder();
|
|
||||||
|
|
||||||
void inputH264( void *pData,
|
|
||||||
uint32_t ui32Length,
|
|
||||||
uint32_t ui32TimeStamp,
|
|
||||||
int iType);
|
|
||||||
|
|
||||||
void inputAAC( void *pData,
|
|
||||||
uint32_t ui32Length,
|
|
||||||
uint32_t ui32TimeStamp);
|
|
||||||
private:
|
|
||||||
|
|
||||||
#ifdef ENABLE_HLS
|
|
||||||
std::shared_ptr<HLSMaker> m_hlsMaker;
|
|
||||||
#endif //ENABLE_HLS
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4V2
|
|
||||||
std::shared_ptr<Mp4Maker> m_mp4Maker;
|
|
||||||
#endif //ENABLE_MP4V2
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace MediaFile */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_MEDIAFILE_MEDIARECORDER_H_ */
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Mp4Maker.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-9-18
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MP4MAKER_H_
|
|
||||||
#define MP4MAKER_H_
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4V2
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <mp4v2/mp4v2.h>
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace MediaFile {
|
|
||||||
|
|
||||||
class Mp4Info
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
time_t ui64StartedTime; //GMT标准时间,单位秒
|
|
||||||
time_t ui64TimeLen;//录像长度,单位秒
|
|
||||||
off_t ui64FileSize;//文件大小,单位BYTE
|
|
||||||
string strFilePath;//文件路径
|
|
||||||
string strFileName;//文件名称
|
|
||||||
string strFolder;//文件夹路径
|
|
||||||
string strUrl;//播放路径
|
|
||||||
string strAppName;//应用名称
|
|
||||||
string strStreamId;//流ID
|
|
||||||
};
|
|
||||||
class Mp4Maker {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<Mp4Maker> Ptr;
|
|
||||||
Mp4Maker(const string &strPath,const string &strApp,const string &strStreamId, const PlayerBase::Ptr &pPlayer);
|
|
||||||
virtual ~Mp4Maker();
|
|
||||||
//时间戳:参考频率1000
|
|
||||||
void inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType);
|
|
||||||
//时间戳:参考频率1000
|
|
||||||
void inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
|
|
||||||
private:
|
|
||||||
MP4FileHandle m_hMp4 = MP4_INVALID_FILE_HANDLE;
|
|
||||||
MP4TrackId m_hVideo = MP4_INVALID_TRACK_ID;
|
|
||||||
MP4TrackId m_hAudio = MP4_INVALID_TRACK_ID;
|
|
||||||
PlayerBase::Ptr m_pPlayer;
|
|
||||||
string m_strPath;
|
|
||||||
string m_strFile;
|
|
||||||
string m_strFileTmp;
|
|
||||||
Ticker m_ticker;
|
|
||||||
SmoothTicker m_mediaTicker[2];
|
|
||||||
|
|
||||||
void createFile();
|
|
||||||
void closeFile();
|
|
||||||
void _inputH264(void *pData, uint32_t ui32Length, uint32_t ui64Duration, int iType);
|
|
||||||
void _inputAAC(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
|
|
||||||
|
|
||||||
string m_strLastVideo;
|
|
||||||
string m_strLastAudio;
|
|
||||||
|
|
||||||
uint32_t m_ui32LastVideoTime = 0;
|
|
||||||
uint32_t m_ui32LastAudioTime = 0;
|
|
||||||
int m_iLastVideoType = 0;
|
|
||||||
|
|
||||||
Mp4Info m_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace MediaFile */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif ///ENABLE_MP4V2
|
|
||||||
|
|
||||||
#endif /* MP4MAKER_H_ */
|
|
@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
* TSMaker.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-6-21
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TSMAKER_H_
|
|
||||||
#define TSMAKER_H_
|
|
||||||
|
|
||||||
#include "crc32.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include "Util/File.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
#define TS_PACKET_SIZE 188
|
|
||||||
#define TS_PACKET_HEADER 4
|
|
||||||
#define TS_SYNC_BYTE 0x47
|
|
||||||
#define TS_PAT_PID 0x00
|
|
||||||
#define TS_PMT_PID 0xFFF
|
|
||||||
#define TS_H264_PID 0x100
|
|
||||||
#define TS_AAC_PID 0x101
|
|
||||||
#define TS_H264_STREAM_ID 0xE0
|
|
||||||
#define TS_AAC_STREAM_ID 0xC0
|
|
||||||
#define PMT_STREAM_TYPE_VIDEO 0x1B
|
|
||||||
#define PMT_STREAM_TYPE_AUDIO 0x0F
|
|
||||||
|
|
||||||
//#define ES_BUF_SIZE 256*1024
|
|
||||||
|
|
||||||
//ts 包头
|
|
||||||
typedef struct Tag_PacketHeader {
|
|
||||||
unsigned char sync_byte :8; //同步字节, 固定为0x47,表示后面的是一个TS分组
|
|
||||||
unsigned char tras_error :1; //传输误码指示符
|
|
||||||
unsigned char play_init :1; //有效荷载单元起始指示符
|
|
||||||
unsigned char tras_prio :1; //传输优先, 1表示高优先级,传输机制可能用到,解码用不着
|
|
||||||
unsigned int PID :13; //PID
|
|
||||||
unsigned char tras_scramb :2; //传输加扰控制
|
|
||||||
unsigned char ada_field_C :2; //自适应控制 01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载,先调整字段然后有效负载。为00解码器不进行处理
|
|
||||||
unsigned char conti_cter :4; //连续计数器 一个4bit的计数器,范围0-15
|
|
||||||
} TsPacketHeader;
|
|
||||||
|
|
||||||
//连续性计数器,也就是说 有多少个 pat包,几个pmt包 ,几个MP3 包,几个 h264包,0x00 - 0x0f ,然后折回到0x00
|
|
||||||
typedef struct Tag_Continuity_Counter {
|
|
||||||
unsigned char continuity_counter_pat;
|
|
||||||
unsigned char continuity_counter_pmt;
|
|
||||||
unsigned char continuity_counter_video;
|
|
||||||
unsigned char continuity_counter_audio;
|
|
||||||
} Continuity_Counter;
|
|
||||||
|
|
||||||
//自适应段标志
|
|
||||||
typedef struct Tag_Ts_Adaptation_field {
|
|
||||||
unsigned char discontinuty_indicator :1; //1表明当前传送流分组的不连续状态为真
|
|
||||||
unsigned char random_access_indicator :1; //表明下一个有相同PID的PES分组应该含有PTS字段和一个原始流访问点
|
|
||||||
unsigned char elementary_stream_priority_indicator :1; //优先级
|
|
||||||
unsigned char PCR_flag :1; //包含pcr字段
|
|
||||||
unsigned char OPCR_flag :1; //包含opcr字段
|
|
||||||
unsigned char splicing_point_flag :1; //拼接点标志
|
|
||||||
unsigned char transport_private_data_flag :1; //私用字节
|
|
||||||
unsigned char adaptation_field_extension_flag :1; //调整字段有扩展
|
|
||||||
|
|
||||||
unsigned char adaptation_field_length; //自适应段长度
|
|
||||||
unsigned long long pcr; //自适应段中用到的的pcr
|
|
||||||
unsigned long long opcr; //自适应段中用到的的opcr
|
|
||||||
unsigned char splice_countdown;
|
|
||||||
unsigned char private_data_len;
|
|
||||||
unsigned char private_data[256];
|
|
||||||
} Ts_Adaptation_field;
|
|
||||||
|
|
||||||
//PAT结构体:节目相关表
|
|
||||||
typedef struct Tag_TsPat {
|
|
||||||
unsigned char table_id :8; //固定为0x00 ,标志是该表是PAT
|
|
||||||
unsigned char section_syntax_indicator :1; //段语法标志位,固定为1
|
|
||||||
unsigned char zero :1; //0
|
|
||||||
unsigned char reserved_1 :2; //保留位
|
|
||||||
unsigned int section_length :12; //表示这个字节后面有用的字节数,包括CRC32
|
|
||||||
unsigned int transport_stream_id :16; //该传输流的ID,区别于一个网络中其它多路复用的流
|
|
||||||
unsigned char reserved_2 :2; //保留位
|
|
||||||
unsigned char version_number :5; //范围0-31,表示PAT的版本号
|
|
||||||
unsigned char current_next_indicator :1; //发送的PAT是当前有效还是下一个PAT有效
|
|
||||||
unsigned char section_number :8; //分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段
|
|
||||||
unsigned char last_section_number :8; //最后一个分段的号码
|
|
||||||
unsigned int program_number :16; //节目号
|
|
||||||
unsigned char reserved_3 :3; //保留位
|
|
||||||
//unsigned int network_PID :13 ; //网络信息表(NIT)的PID,节目号为0时对应的PID为network_PID,本例中不含有 networke_pid
|
|
||||||
unsigned int program_map_PID :13; //节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个
|
|
||||||
unsigned long long CRC_32 :32; //CRC32校验码
|
|
||||||
} TsPat;
|
|
||||||
|
|
||||||
//PMT结构体:节目映射表
|
|
||||||
typedef struct Tag_TsPmt {
|
|
||||||
unsigned char table_id :8; //固定为0x02, 表示PMT表
|
|
||||||
unsigned char section_syntax_indicator :1; //固定为0x01
|
|
||||||
unsigned char zero :1; //0x00
|
|
||||||
unsigned char reserved_1 :2; //0x03
|
|
||||||
unsigned int section_length :12; //首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC。
|
|
||||||
unsigned int program_number :16; // 指出该节目对应于可应用的Program map PID
|
|
||||||
unsigned char reserved_2 :2; //0x03
|
|
||||||
unsigned char version_number :5; //指出TS流中Program map section的版本号
|
|
||||||
unsigned char current_next_indicator :1; //当该位置1时,当前传送的Program map section可用;当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效。
|
|
||||||
unsigned char section_number :8; //固定为0x00
|
|
||||||
unsigned char last_section_number :8; //固定为0x00
|
|
||||||
unsigned char reserved_3 :3; //0x07
|
|
||||||
unsigned int PCR_PID :13; //指明TS包的PID值,该TS包含有PCR域,该PCR值对应于由节目号指定的对应节目。如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。
|
|
||||||
unsigned char reserved_4 :4; //预留为0x0F
|
|
||||||
unsigned int program_info_length :12; //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。
|
|
||||||
unsigned char stream_type_video :8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定
|
|
||||||
unsigned char reserved_5_video :3; //0x07
|
|
||||||
unsigned int elementary_PID_video :13; //该域指示TS包的PID值。这些TS包含有相关的节目元素
|
|
||||||
unsigned char reserved_6_video :4; //0x0F
|
|
||||||
unsigned int ES_info_length_video :12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数
|
|
||||||
unsigned char stream_type_audio :8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定
|
|
||||||
unsigned char reserved_5_audio :3; //0x07
|
|
||||||
unsigned int elementary_PID_audio :13; //该域指示TS包的PID值。这些TS包含有相关的节目元素
|
|
||||||
unsigned char reserved_6_audio :4; //0x0F
|
|
||||||
unsigned int ES_info_length_audio :12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数
|
|
||||||
unsigned long long CRC_32 :32; //CRC32校验码
|
|
||||||
} TsPmt;
|
|
||||||
|
|
||||||
//PTS_DTS结构体:本程序设置都有 “11”
|
|
||||||
typedef struct Tag_TsPtsDts {
|
|
||||||
unsigned char reserved_1 :4;
|
|
||||||
unsigned char pts_32_30 :3; //显示时间戳
|
|
||||||
unsigned char marker_bit1 :1;
|
|
||||||
unsigned int pts_29_15 :15;
|
|
||||||
unsigned char marker_bit2 :1;
|
|
||||||
unsigned int pts_14_0 :15;
|
|
||||||
unsigned char marker_bit3 :1;
|
|
||||||
unsigned char reserved_2 :4;
|
|
||||||
unsigned char dts_32_30 :3; //解码时间戳
|
|
||||||
unsigned char marker_bit4 :1;
|
|
||||||
unsigned int dts_29_15 :15;
|
|
||||||
unsigned char marker_bit5 :1;
|
|
||||||
unsigned int dts_14_0 :15;
|
|
||||||
unsigned char marker_bit6 :1;
|
|
||||||
} TsPtsDts;
|
|
||||||
|
|
||||||
//PES包结构体,包括PES包头和ES数据 ,头 19 个字节
|
|
||||||
typedef struct Tag_TsPes {
|
|
||||||
unsigned int packet_start_code_prefix :24; //起始:0x000001
|
|
||||||
unsigned char stream_id :8; //基本流的类型和编号
|
|
||||||
unsigned int PES_packet_length :16; //包长度,就是帧数据的长度,可能为0,要自己算,做多16位,如果超出则需要自己算
|
|
||||||
unsigned char marker_bit :2; //必须是:'10'
|
|
||||||
unsigned char PES_scrambling_control :2; //pes包有效载荷的加扰方式
|
|
||||||
unsigned char PES_priority :1; //有效负载的优先级
|
|
||||||
unsigned char data_alignment_indicator :1; //如果设置为1表明PES包的头后面紧跟着视频或音频syncword开始的代码。
|
|
||||||
unsigned char copyright :1; //1:靠版权保护,0:不靠
|
|
||||||
unsigned char original_or_copy :1; //1;有效负载是原始的,0:有效负载时拷贝的
|
|
||||||
unsigned char PTS_DTS_flags :2; //'10':PTS字段存在,‘11’:PTD和DTS都存在,‘00’:都没有,‘01’:禁用。
|
|
||||||
unsigned char ESCR_flag :1; //1:escr基准字段 和 escr扩展字段均存在,0:无任何escr字段存在
|
|
||||||
unsigned char ES_rate_flag :1; //1:es_rate字段存在,0 :不存在
|
|
||||||
unsigned char DSM_trick_mode_flag :1; //1;8比特特接方式字段存在,0 :不存在
|
|
||||||
unsigned char additional_copy_info_flag :1; //1:additional_copy_info存在,0: 不存在
|
|
||||||
unsigned char PES_CRC_flag :1; //1:crc字段存在,0:不存在
|
|
||||||
unsigned char PES_extension_flag :1; //1:扩展字段存在,0:不存在
|
|
||||||
unsigned char PES_header_data_length :8; //后面数据的长度,
|
|
||||||
//TsPtsDts tsptsdts; //ptsdts结构体对象,10个字节
|
|
||||||
char *ES;
|
|
||||||
unsigned long ESlen;
|
|
||||||
} TsPes;
|
|
||||||
|
|
||||||
/*//H264一帧数据的结构体
|
|
||||||
typedef struct Tag_NALU_t {
|
|
||||||
unsigned char forbidden_bit; //! Should always be FALSE
|
|
||||||
unsigned char nal_reference_idc; //! NALU_PRIORITY_xxxx
|
|
||||||
unsigned char nal_unit_type; //! NALU_TYPE_xxxx
|
|
||||||
unsigned int startcodeprefix_len; //! 前缀字节数
|
|
||||||
unsigned int len; //! 包含nal 头的nal 长度,从第一个00000001到下一个000000001的长度
|
|
||||||
unsigned int max_size; //! 做多一个nal 的长度
|
|
||||||
unsigned char * buf; //! 包含nal 头的nal 数据
|
|
||||||
unsigned int lost_packets; //! 预留
|
|
||||||
} NALU_t;*/
|
|
||||||
|
|
||||||
//nal类型
|
|
||||||
typedef enum {
|
|
||||||
NALU_TYPE_SLICE = 1,
|
|
||||||
NALU_TYPE_DPA = 2,
|
|
||||||
NALU_TYPE_DPB = 3,
|
|
||||||
NALU_TYPE_DPC = 4,
|
|
||||||
NALU_TYPE_IDR = 5,
|
|
||||||
NALU_TYPE_SEI = 6,
|
|
||||||
NALU_TYPE_SPS = 7,
|
|
||||||
NALU_TYPE_PPS = 8,
|
|
||||||
NALU_TYPE_AUD = 9,
|
|
||||||
NALU_TYPE_EOSEQ = 10,
|
|
||||||
NALU_TYPE_EOSTREAM = 11,
|
|
||||||
NALU_TYPE_FILL = 12,
|
|
||||||
#if (MVC_EXTENSION_ENABLE)
|
|
||||||
NALU_TYPE_PREFIX = 14,
|
|
||||||
NALU_TYPE_SUB_SPS = 15,
|
|
||||||
NALU_TYPE_SLC_EXT = 20,
|
|
||||||
NALU_TYPE_VDRD = 24 // View and Dependency Representation Delimiter NAL Unit
|
|
||||||
#endif
|
|
||||||
} NaluType;
|
|
||||||
|
|
||||||
/*//MP3头结构体
|
|
||||||
typedef struct Tag_Mp3_Header {
|
|
||||||
unsigned int sync :11; //同步信息
|
|
||||||
unsigned char version :2; //版本
|
|
||||||
unsigned char layer :2; //层
|
|
||||||
unsigned char error_protection :1; //CRC校验
|
|
||||||
unsigned char bitrate_index :4; //位率
|
|
||||||
unsigned char sampling_frequency :2; //采样频率
|
|
||||||
unsigned char padding :1; //帧长调节
|
|
||||||
unsigned char private_t :1; //保留字
|
|
||||||
unsigned char mode :2; //声道模式
|
|
||||||
unsigned char mode_extension :2; //扩展模式
|
|
||||||
unsigned char copyright :1; //版权
|
|
||||||
unsigned char original :1; //原版标志
|
|
||||||
unsigned char emphasis :2; //强调模式
|
|
||||||
} Mp3_Header;*/
|
|
||||||
|
|
||||||
|
|
||||||
class TSMaker {
|
|
||||||
public:
|
|
||||||
TSMaker();
|
|
||||||
virtual ~TSMaker();
|
|
||||||
bool init(const string &strFilename, uint32_t ui32BufSize);
|
|
||||||
int inputH264(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
|
||||||
int inputAAC(const char *pcData, uint32_t ui32Len, uint64_t ui64Time);
|
|
||||||
void clear();
|
|
||||||
private:
|
|
||||||
string m_strFilename;
|
|
||||||
FILE *m_pOutVideoTs;
|
|
||||||
Continuity_Counter m_continuityCounter;
|
|
||||||
TsPes *m_pVideo_pes;
|
|
||||||
TsPes *m_pAudio_pes;
|
|
||||||
unsigned int m_uiWritePacketNum;
|
|
||||||
char *m_pcFileBuf;
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
void CreateTsHeader(TsPacketHeader * pTsHeader, unsigned int uiPID, unsigned char ucPlayInit, unsigned char ucAdaFieldC);
|
|
||||||
void TsHeader2buffer(TsPacketHeader * pTsHeader, unsigned char *pucBuffer);
|
|
||||||
void CreatePAT();
|
|
||||||
void CreatePMT();
|
|
||||||
|
|
||||||
void WriteAdaptive_flags_Head(Ts_Adaptation_field * pAdaptationField, uint64_t ui64VideoPts);
|
|
||||||
void WriteAdaptive_flags_Tail(Ts_Adaptation_field * pAdaptationField); //填写自适应段标志帧尾的
|
|
||||||
|
|
||||||
void PES2TS(TsPes * pPes, unsigned int uiPID, Ts_Adaptation_field * pAdaptationField, uint64_t ui64Pts);
|
|
||||||
void CreateAdaptive_Ts(Ts_Adaptation_field * pAdaptationField, unsigned char * pcTs, unsigned int uiAdaptiveLength);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* TSMAKER_H_ */
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* crc32.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-6-21
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CRC32_H_
|
|
||||||
#define CRC32_H_
|
|
||||||
|
|
||||||
unsigned int calc_crc32 (unsigned char *data, unsigned int datalen);
|
|
||||||
unsigned int Zwg_ntohl(unsigned int s);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* CRC32_H_ */
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* MediaPlayer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月5日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_PLAYER_MEDIAPLAYER_H_
|
|
||||||
#define SRC_PLAYER_MEDIAPLAYER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include "Player.h"
|
|
||||||
#include "PlayerBase.h"
|
|
||||||
#include "Rtsp/RtspPlayer.h"
|
|
||||||
#include "Rtmp/RtmpPlayer.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::Rtmp;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Player {
|
|
||||||
|
|
||||||
class MediaPlayer : public PlayerImp<PlayerBase,PlayerBase> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<MediaPlayer> Ptr;
|
|
||||||
|
|
||||||
MediaPlayer();
|
|
||||||
virtual ~MediaPlayer();
|
|
||||||
void play(const char* strUrl) override;
|
|
||||||
void pause(bool bPause) override;
|
|
||||||
void teardown() override;
|
|
||||||
private:
|
|
||||||
string m_strPrefix;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Player */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_PLAYER_MEDIAPLAYER_H_ */
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Player.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月2日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_PLAYER_PLAYER_H_
|
|
||||||
#define SRC_PLAYER_PLAYER_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t sequence;
|
|
||||||
uint32_t timeStamp;
|
|
||||||
unsigned char type;
|
|
||||||
string data;
|
|
||||||
} H264Frame;
|
|
||||||
|
|
||||||
//ADTS 头中相对有用的信息 采样率、声道数、帧长度
|
|
||||||
typedef struct {
|
|
||||||
unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
|
|
||||||
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
|
|
||||||
unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’
|
|
||||||
unsigned int protection_absent; //1 bslbf 表示是否误码校验
|
|
||||||
unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC
|
|
||||||
unsigned int sf_index; //4 uimsbf 表示使用的采样率下标
|
|
||||||
unsigned int private_bit; //1 bslbf
|
|
||||||
unsigned int channel_configuration; //3 uimsbf 表示声道数
|
|
||||||
unsigned int original; //1 bslbf
|
|
||||||
unsigned int home; //1 bslbf
|
|
||||||
//下面的为改变的参数即每一帧都不同
|
|
||||||
unsigned int copyright_identification_bit; //1 bslbf
|
|
||||||
unsigned int copyright_identification_start; //1 bslbf
|
|
||||||
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
|
|
||||||
unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流
|
|
||||||
//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
|
|
||||||
//所以说number_of_raw_data_blocks_in_frame == 0
|
|
||||||
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
|
|
||||||
unsigned int no_raw_data_blocks_in_frame; //2 uimsfb
|
|
||||||
unsigned char data[2 * 1024 + 7];
|
|
||||||
uint16_t sequence;
|
|
||||||
uint32_t timeStamp;
|
|
||||||
} AdtsFrame;
|
|
||||||
|
|
||||||
void makeAdtsHeader(const string &strAudioCfg,AdtsFrame &adts);
|
|
||||||
void writeAdtsHeader(const AdtsFrame &adts, uint8_t *pcAdts) ;
|
|
||||||
string makeAdtsConfig(const uint8_t *pcAdts);
|
|
||||||
void getAACInfo(const AdtsFrame &adts,int &iSampleRate,int &iChannel);
|
|
||||||
bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
|
|
||||||
|
|
||||||
#endif /* SRC_PLAYER_PLAYER_H_ */
|
|
@ -1,221 +0,0 @@
|
|||||||
/*
|
|
||||||
* PlayerBase.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月1日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_PLAYER_PLAYERBASE_H_
|
|
||||||
#define SRC_PLAYER_PLAYERBASE_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include "Player.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
#include "Util/mini.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Player {
|
|
||||||
|
|
||||||
class PlayerBase : public mINI{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<PlayerBase> Ptr;
|
|
||||||
typedef enum {
|
|
||||||
RTP_TCP = 0,
|
|
||||||
RTP_UDP = 1,
|
|
||||||
RTP_MULTICAST = 2,
|
|
||||||
} eRtpType;
|
|
||||||
static Ptr createPlayer(const char* strUrl);
|
|
||||||
|
|
||||||
PlayerBase(){};
|
|
||||||
virtual ~PlayerBase(){};
|
|
||||||
virtual void play(const char* strUrl) {};
|
|
||||||
virtual void pause(bool bPause) {};
|
|
||||||
virtual void teardown() {};
|
|
||||||
|
|
||||||
virtual void setOnShutdown( const function<void(const SockException &)> &cb) {};
|
|
||||||
virtual void setOnPlayResult( const function<void(const SockException &ex)> &cb) {};
|
|
||||||
virtual void setOnVideoCB( const function<void(const H264Frame &frame)> &cb) {};
|
|
||||||
virtual void setOnAudioCB( const function<void(const AdtsFrame &frame)> &cb) {};
|
|
||||||
|
|
||||||
virtual int getVideoHeight() const { return 0; };
|
|
||||||
virtual int getVideoWidth() const { return 0; };
|
|
||||||
virtual float getVideoFps() const { return 0; };
|
|
||||||
virtual int getAudioSampleRate() const { return 0; };
|
|
||||||
virtual int getAudioSampleBit() const { return 0; };
|
|
||||||
virtual int getAudioChannel() const { return 0; };
|
|
||||||
virtual float getRtpLossRate(int iTrackId) const {return 0; };
|
|
||||||
virtual const string& getPps() const { static string null;return null; };
|
|
||||||
virtual const string& getSps() const { static string null;return null; };
|
|
||||||
virtual const string& getAudioCfg() const { static string null;return null; };
|
|
||||||
virtual bool containAudio() const { return false; };
|
|
||||||
virtual bool containVideo() const { return false; };
|
|
||||||
virtual bool isInited() const { return true; };
|
|
||||||
virtual float getDuration() const { return 0;};
|
|
||||||
virtual float getProgresss() const { return 0;};
|
|
||||||
virtual void seekTo(float fProgress) {};
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void onShutdown(const SockException &ex) {};
|
|
||||||
virtual void onPlayResult(const SockException &ex) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Parent,typename Parser>
|
|
||||||
class PlayerImp : public Parent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<PlayerImp> Ptr;
|
|
||||||
PlayerImp(){};
|
|
||||||
virtual ~PlayerImp(){};
|
|
||||||
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
|
||||||
if (m_parser) {
|
|
||||||
m_parser->setOnShutdown(cb);
|
|
||||||
}
|
|
||||||
m_shutdownCB = cb;
|
|
||||||
}
|
|
||||||
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
|
||||||
if (m_parser) {
|
|
||||||
m_parser->setOnPlayResult(cb);
|
|
||||||
}
|
|
||||||
m_playResultCB = cb;
|
|
||||||
}
|
|
||||||
void setOnVideoCB(const function<void(const H264Frame &frame)> &cb) override{
|
|
||||||
if (m_parser) {
|
|
||||||
m_parser->setOnVideoCB(cb);
|
|
||||||
}
|
|
||||||
m_onGetVideoCB = cb;
|
|
||||||
}
|
|
||||||
void setOnAudioCB(const function<void(const AdtsFrame &frame)> &cb) override{
|
|
||||||
if (m_parser) {
|
|
||||||
m_parser->setOnAudioCB(cb);
|
|
||||||
}
|
|
||||||
m_onGetAudioCB = cb;
|
|
||||||
}
|
|
||||||
int getVideoHeight() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getVideoHeight();
|
|
||||||
}
|
|
||||||
return PlayerBase::getVideoHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVideoWidth() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getVideoWidth();
|
|
||||||
}
|
|
||||||
return PlayerBase::getVideoWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
float getVideoFps() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getVideoFps();
|
|
||||||
}
|
|
||||||
return PlayerBase::getVideoFps();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleRate() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getAudioSampleRate();
|
|
||||||
}
|
|
||||||
return PlayerBase::getAudioSampleRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleBit() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getAudioSampleBit();
|
|
||||||
}
|
|
||||||
return PlayerBase::getAudioSampleBit();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioChannel() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getAudioChannel();
|
|
||||||
}
|
|
||||||
return PlayerBase::getAudioChannel();
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getPps() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getPps();
|
|
||||||
}
|
|
||||||
return PlayerBase::getPps();
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getSps() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getSps();
|
|
||||||
}
|
|
||||||
return PlayerBase::getSps();
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getAudioCfg() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getAudioCfg();
|
|
||||||
}
|
|
||||||
return PlayerBase::getAudioCfg();
|
|
||||||
}
|
|
||||||
bool containAudio() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->containAudio();
|
|
||||||
}
|
|
||||||
return PlayerBase::containAudio();
|
|
||||||
}
|
|
||||||
bool containVideo() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->containVideo();
|
|
||||||
}
|
|
||||||
return PlayerBase::containVideo();
|
|
||||||
}
|
|
||||||
bool isInited() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->isInited();
|
|
||||||
}
|
|
||||||
return PlayerBase::isInited();
|
|
||||||
}
|
|
||||||
float getDuration() const override {
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getDuration();
|
|
||||||
}
|
|
||||||
return PlayerBase::getDuration();
|
|
||||||
}
|
|
||||||
float getProgresss() const override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->getProgresss();
|
|
||||||
}
|
|
||||||
return PlayerBase::getProgresss();
|
|
||||||
};
|
|
||||||
void seekTo(float fProgress) override{
|
|
||||||
if (m_parser) {
|
|
||||||
return m_parser->seekTo(fProgress);
|
|
||||||
}
|
|
||||||
return PlayerBase::seekTo(fProgress);
|
|
||||||
};
|
|
||||||
protected:
|
|
||||||
void onShutdown(const SockException &ex) override {
|
|
||||||
if (m_shutdownCB) {
|
|
||||||
m_shutdownCB(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void onPlayResult(const SockException &ex) override {
|
|
||||||
if (m_playResultCB) {
|
|
||||||
m_playResultCB(ex);
|
|
||||||
m_playResultCB = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function<void(const SockException &ex)> m_shutdownCB;
|
|
||||||
function<void(const SockException &ex)> m_playResultCB;
|
|
||||||
std::shared_ptr<Parser> m_parser;
|
|
||||||
function<void(const H264Frame &frame)> m_onGetVideoCB;
|
|
||||||
function<void(const AdtsFrame &frame)> m_onGetAudioCB;
|
|
||||||
|
|
||||||
};
|
|
||||||
} /* namespace Player */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_PLAYER_PLAYERBASE_H_ */
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtpMaker.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月12日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RTP_RTPMAKER_H_
|
|
||||||
#define RTP_RTPMAKER_H_
|
|
||||||
|
|
||||||
#include "Rtsp/RtspMediaSource.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/RingBuffer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Util/ResourcePool.h"
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtpMaker {
|
|
||||||
public:
|
|
||||||
typedef function<void(const RtpPacket::Ptr &pPkt, bool bKeyPos)> onGetRTP;
|
|
||||||
RtpMaker(const onGetRTP &cb, uint32_t ui32Ssrc, int iMtuSize,int iSampleRate,
|
|
||||||
uint8_t ui8PlayloadType, uint8_t ui8Interleaved) {
|
|
||||||
callBack = cb;
|
|
||||||
m_ui32Ssrc = ui32Ssrc;
|
|
||||||
m_ui32SampleRate = iSampleRate;
|
|
||||||
m_iMtuSize = iMtuSize;
|
|
||||||
m_ui8PlayloadType = ui8PlayloadType;
|
|
||||||
m_ui8Interleaved = ui8Interleaved;
|
|
||||||
}
|
|
||||||
virtual ~RtpMaker() {
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp)=0;
|
|
||||||
|
|
||||||
int getInterleaved() const {
|
|
||||||
return m_ui8Interleaved;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPlayloadType() const {
|
|
||||||
return m_ui8PlayloadType;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getSampleRate() const {
|
|
||||||
return m_ui32SampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getSsrc() const {
|
|
||||||
return m_ui32Ssrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getSeqence() const {
|
|
||||||
return m_ui16Sequence;
|
|
||||||
}
|
|
||||||
uint32_t getTimestamp() const {
|
|
||||||
return m_ui32TimeStamp;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
uint32_t m_ui32Ssrc;
|
|
||||||
uint32_t m_ui32SampleRate;
|
|
||||||
int m_iMtuSize;
|
|
||||||
uint8_t m_ui8PlayloadType;
|
|
||||||
uint8_t m_ui8Interleaved;
|
|
||||||
uint16_t m_ui16Sequence = 0;
|
|
||||||
uint32_t m_ui32TimeStamp = 0;
|
|
||||||
virtual void onMakeRtp(const RtpPacket::Ptr &pkt, bool bKeyPos = true) {
|
|
||||||
callBack(pkt, bKeyPos);
|
|
||||||
}
|
|
||||||
inline RtpPacket::Ptr obtainPkt() {
|
|
||||||
return m_pktPool.obtain();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
RtspMediaSource::PoolType m_pktPool;
|
|
||||||
onGetRTP callBack;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace RTP */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* RTP_RTPMAKER_H_ */
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtpMakerAAC.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月12日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RTP_RTPMAKERAAC_H_
|
|
||||||
#define RTP_RTPMAKERAAC_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "RtpMaker.h"
|
|
||||||
#include "Rtsp/RtspMediaSource.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/RingBuffer.h"
|
|
||||||
#include "Util/ResourcePool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtpMaker_AAC: public RtpMaker {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtpMaker_AAC> Ptr;
|
|
||||||
RtpMaker_AAC(const onGetRTP &cb,
|
|
||||||
uint32_t ui32Ssrc, int iMtuSize , int iSampleRate, uint8_t ui8PlayloadType = 97,
|
|
||||||
uint8_t ui8Interleaved = 2) :
|
|
||||||
RtpMaker(cb, ui32Ssrc, iMtuSize,iSampleRate, ui8PlayloadType, ui8Interleaved) {
|
|
||||||
}
|
|
||||||
virtual ~RtpMaker_AAC() {
|
|
||||||
}
|
|
||||||
void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp) override;
|
|
||||||
private:
|
|
||||||
inline void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
|
||||||
unsigned char m_aucSectionBuf[1600];
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace RTP */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* RTP_RTPMAKERAAC_H_ */
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtpMakerH264.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月12日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RTP_RTPMAKERH264_H_
|
|
||||||
#define RTP_RTPMAKERH264_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "RtpMaker.h"
|
|
||||||
#include "Rtsp/RtspMediaSource.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/RingBuffer.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtpMaker_H264: public RtpMaker {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtpMaker_H264> Ptr;
|
|
||||||
RtpMaker_H264(const onGetRTP &cb, uint32_t ui32Ssrc,int iMtuSize = 1400,int iSampleRate = 90000,
|
|
||||||
uint8_t ui8PlayloadType = 96, uint8_t ui8Interleaved = 0) :
|
|
||||||
RtpMaker(cb, ui32Ssrc, iMtuSize,iSampleRate, ui8PlayloadType, ui8Interleaved) {
|
|
||||||
}
|
|
||||||
virtual ~RtpMaker_H264() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp) override;
|
|
||||||
private:
|
|
||||||
inline void makeH264Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
|
||||||
unsigned char aucSectionBuf[1600];
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace RTP */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* RTP_RTPMAKERH264_H_ */
|
|
@ -1,236 +0,0 @@
|
|||||||
#ifndef __rtmp_h
|
|
||||||
#define __rtmp_h
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Network/sockutil.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
#define PORT 1935
|
|
||||||
#define DEFAULT_CHUNK_LEN 128
|
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
#define PACKED __attribute__((packed))
|
|
||||||
#else
|
|
||||||
#define PACKED
|
|
||||||
#endif //!defined(_WIN32)
|
|
||||||
|
|
||||||
|
|
||||||
#define HANDSHAKE_PLAINTEXT 0x03
|
|
||||||
#define RANDOM_LEN (1536 - 8)
|
|
||||||
|
|
||||||
#define MSG_SET_CHUNK 1 /*Set Chunk Size (1)*/
|
|
||||||
#define MSG_ABORT 2 /*Abort Message (2)*/
|
|
||||||
#define MSG_ACK 3 /*Acknowledgement (3)*/
|
|
||||||
#define MSG_USER_CONTROL 4 /*User Control Messages (4)*/
|
|
||||||
#define MSG_WIN_SIZE 5 /*Window Acknowledgement Size (5)*/
|
|
||||||
#define MSG_SET_PEER_BW 6 /*Set Peer Bandwidth (6)*/
|
|
||||||
#define MSG_AUDIO 8 /*Audio Message (8)*/
|
|
||||||
#define MSG_VIDEO 9 /*Video Message (9)*/
|
|
||||||
#define MSG_DATA 18 /*Data Message (18, 15) AMF0*/
|
|
||||||
#define MSG_DATA3 15 /*Data Message (18, 15) AMF3*/
|
|
||||||
#define MSG_CMD 20 /*Command Message AMF0 */
|
|
||||||
#define MSG_CMD3 17 /*Command Message AMF3 */
|
|
||||||
#define MSG_OBJECT3 16 /*Shared Object Message (19, 16) AMF3*/
|
|
||||||
#define MSG_OBJECT 19 /*Shared Object Message (19, 16) AMF0*/
|
|
||||||
#define MSG_AGGREGATE 22 /*Aggregate Message (22)*/
|
|
||||||
|
|
||||||
#define CONTROL_STREAM_BEGIN 0
|
|
||||||
#define CONTROL_STREAM_EOF 1
|
|
||||||
#define CONTROL_STREAM_DRY 2
|
|
||||||
#define CONTROL_SETBUFFER 3
|
|
||||||
#define CONTROL_STREAM_ISRECORDED 4
|
|
||||||
#define CONTROL_PING_REQUEST 6
|
|
||||||
#define CONTROL_PING_RESPONSE 7
|
|
||||||
|
|
||||||
#define STREAM_CONTROL 0
|
|
||||||
#define STREAM_MEDIA 1
|
|
||||||
|
|
||||||
#define CHUNK_SERVER_REQUEST 2 /*服务器像客户端发出请求时的chunkID*/
|
|
||||||
#define CHUNK_CLIENT_REQUEST_BEFORE 3 /*客户端在createStream前,向服务器发出请求的chunkID*/
|
|
||||||
#define CHUNK_CLIENT_REQUEST_AFTER 4 /*客户端在createStream后,向服务器发出请求的chunkID*/
|
|
||||||
#define CHUNK_AUDIO 6 /*音频chunkID*/
|
|
||||||
#define CHUNK_VIDEO 7 /*视频chunkID*/
|
|
||||||
|
|
||||||
#define FLV_KEY_FRAME 1
|
|
||||||
#define FLV_INTER_FRAME 2
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
class RtmpHandshake {
|
|
||||||
public:
|
|
||||||
RtmpHandshake(uint32_t _time, uint8_t *_random = nullptr) {
|
|
||||||
_time = htonl(_time);
|
|
||||||
memcpy(timeStamp, &_time, 4);
|
|
||||||
if (!_random) {
|
|
||||||
random_generate((char *) random, sizeof(random));
|
|
||||||
} else {
|
|
||||||
memcpy(random, _random, sizeof(random));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint8_t timeStamp[4];
|
|
||||||
uint8_t zero[4] = {0};
|
|
||||||
uint8_t random[RANDOM_LEN];
|
|
||||||
void random_generate(char* bytes, int size) {
|
|
||||||
static char cdata[] = { 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72,
|
|
||||||
0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
|
||||||
0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69,
|
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
|
||||||
0x40, 0x31, 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x6d };
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
bytes[i] = cdata[rand() % (sizeof(cdata) - 1)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}PACKED;
|
|
||||||
|
|
||||||
class RtmpHeader {
|
|
||||||
public:
|
|
||||||
uint8_t flags;
|
|
||||||
uint8_t timeStamp[3];
|
|
||||||
uint8_t bodySize[3];
|
|
||||||
uint8_t typeId;
|
|
||||||
uint8_t streamId[4]; /* Note, this is little-endian while others are BE */
|
|
||||||
}PACKED;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#pragma pack(pop)
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
class RtmpPacket {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpPacket> Ptr;
|
|
||||||
uint8_t typeId;
|
|
||||||
uint32_t bodySize = 0;
|
|
||||||
uint32_t timeStamp = 0;
|
|
||||||
bool hasAbsStamp = false;
|
|
||||||
bool hasExtStamp = false;
|
|
||||||
uint32_t deltaStamp = 0;
|
|
||||||
uint32_t streamId;
|
|
||||||
uint32_t chunkId;
|
|
||||||
std::string strBuf;
|
|
||||||
bool isVideoKeyFrame() const {
|
|
||||||
return typeId == MSG_VIDEO && (uint8_t) strBuf[0] >> 4 == FLV_KEY_FRAME
|
|
||||||
&& (uint8_t) strBuf[1] == 1;
|
|
||||||
}
|
|
||||||
bool isCfgFrame() const {
|
|
||||||
return (typeId == MSG_VIDEO || typeId == MSG_AUDIO)
|
|
||||||
&& (uint8_t) strBuf[1] == 0;
|
|
||||||
}
|
|
||||||
int getMediaType() const {
|
|
||||||
switch (typeId) {
|
|
||||||
case MSG_VIDEO: {
|
|
||||||
return (uint8_t) strBuf[0] & 0x0F;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MSG_AUDIO: {
|
|
||||||
return (uint8_t) strBuf[0] >> 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int getAudioSampleRate() const {
|
|
||||||
if (typeId != MSG_AUDIO) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int flvSampleRate = ((uint8_t) strBuf[0] & 0x0C) >> 2;
|
|
||||||
const static int sampleRate[] = { 5512, 11025, 22050, 44100 };
|
|
||||||
return sampleRate[flvSampleRate];
|
|
||||||
}
|
|
||||||
int getAudioSampleBit() const {
|
|
||||||
if (typeId != MSG_AUDIO) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int flvSampleBit = ((uint8_t) strBuf[0] & 0x02) >> 1;
|
|
||||||
const static int sampleBit[] = { 8, 16 };
|
|
||||||
return sampleBit[flvSampleBit];
|
|
||||||
}
|
|
||||||
int getAudioChannel() const {
|
|
||||||
if (typeId != MSG_AUDIO) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int flvStereoOrMono = (uint8_t) strBuf[0] & 0x01;
|
|
||||||
const static int channel[] = { 1, 2 };
|
|
||||||
return channel[flvStereoOrMono];
|
|
||||||
}
|
|
||||||
string getH264SPS() const {
|
|
||||||
string ret;
|
|
||||||
if (getMediaType() != 7) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (!isCfgFrame()) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (strBuf.size() < 13) {
|
|
||||||
WarnL << "bad H264 cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
uint16_t sps_size ;
|
|
||||||
memcpy(&sps_size,strBuf.data() + 11,2);
|
|
||||||
sps_size = ntohs(sps_size);
|
|
||||||
if ((int) strBuf.size() < 13 + sps_size) {
|
|
||||||
WarnL << "bad H264 cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret.assign(strBuf.data() + 13, sps_size);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
string getH264PPS() const {
|
|
||||||
string ret;
|
|
||||||
if (getMediaType() != 7) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (!isCfgFrame()) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (strBuf.size() < 13) {
|
|
||||||
WarnL << "bad H264 cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
uint16_t sps_size ;
|
|
||||||
memcpy(&sps_size,strBuf.data() + 11,2);
|
|
||||||
sps_size = ntohs(sps_size);
|
|
||||||
|
|
||||||
if ((int) strBuf.size() < 13 + sps_size + 1 + 2) {
|
|
||||||
WarnL << "bad H264 cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
uint16_t pps_size ;
|
|
||||||
memcpy(&pps_size,strBuf.data() + 13 + sps_size + 1,2);
|
|
||||||
pps_size = ntohs(pps_size);
|
|
||||||
|
|
||||||
if ((int) strBuf.size() < 13 + sps_size + 1 + 2 + pps_size) {
|
|
||||||
WarnL << "bad H264 cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret.assign(strBuf.data() + 13 + sps_size + 1 + 2, pps_size);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
string getAacCfg() const {
|
|
||||||
string ret;
|
|
||||||
if (getMediaType() != 10) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (!isCfgFrame()) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (strBuf.size() < 4) {
|
|
||||||
WarnL << "bad aac cfg!";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = strBuf.substr(2, 2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpMediaSource.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月1日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPMEDIASOURCE_H_
|
|
||||||
#define SRC_RTMP_RTMPMEDIASOURCE_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Common/MediaSender.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/RingBuffer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Util/ResourcePool.h"
|
|
||||||
#include "Util/NoticeCenter.h"
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
|
|
||||||
class RtmpMediaSource: public enable_shared_from_this<RtmpMediaSource> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpMediaSource> Ptr;
|
|
||||||
typedef RingBuffer<RtmpPacket> RingType;
|
|
||||||
RtmpMediaSource(const string &strApp, const string &strId) :
|
|
||||||
m_strApp(strApp),
|
|
||||||
m_strId(strId),
|
|
||||||
m_pRing(new RingBuffer<RtmpPacket>()),
|
|
||||||
m_thPool( MediaSender::sendThread()) {
|
|
||||||
}
|
|
||||||
virtual ~RtmpMediaSource() {
|
|
||||||
unregist();
|
|
||||||
}
|
|
||||||
const RingType::Ptr &getRing() const {
|
|
||||||
//获取媒体源的rtp环形缓冲
|
|
||||||
return m_pRing;
|
|
||||||
}
|
|
||||||
virtual void regist() {
|
|
||||||
//注册该源,注册后rtmp服务器才能找到该源
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
if (!g_mapMediaSrc[m_strApp].erase(m_strId)) {
|
|
||||||
InfoL << "Rtmp src:" << m_strApp << " " << m_strId;
|
|
||||||
}
|
|
||||||
g_mapMediaSrc[m_strApp].emplace(m_strId, shared_from_this());
|
|
||||||
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRtmpSrcRegisted,m_strApp.data(),m_strId.data());
|
|
||||||
}
|
|
||||||
virtual void unregist() {
|
|
||||||
//反注册该源
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
auto it = g_mapMediaSrc.find(m_strApp);
|
|
||||||
if (it == g_mapMediaSrc.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (it->second.erase(m_strId)) {
|
|
||||||
if (it->second.size() == 0) {
|
|
||||||
g_mapMediaSrc.erase(it);
|
|
||||||
}
|
|
||||||
InfoL << "Rtmp src:" << m_strApp << " " << m_strId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static set<string> getMediaSet() {
|
|
||||||
set<string> ret;
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
for (auto &pr0 : g_mapMediaSrc) {
|
|
||||||
for (auto &pr1 : pr0.second) {
|
|
||||||
if (pr1.second.lock()) {
|
|
||||||
ret.emplace(pr0.first + "/" + pr1.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static Ptr find(const string &strApp, const string &strId, bool bMake = true) ;
|
|
||||||
const string& getApp() const {
|
|
||||||
//获取该源的id
|
|
||||||
return m_strApp;
|
|
||||||
}
|
|
||||||
const string& getId() const {
|
|
||||||
//获取该源的id
|
|
||||||
return m_strId;
|
|
||||||
}
|
|
||||||
const AMFValue &getMetaData() const {
|
|
||||||
return m_metadata;
|
|
||||||
}
|
|
||||||
template<typename FUN>
|
|
||||||
void getConfigFrame(const FUN &f) {
|
|
||||||
lock_guard<recursive_mutex> lock(m_mtxMap);
|
|
||||||
for (auto &pr : m_mapCfgFrame) {
|
|
||||||
f(pr.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool ready() const {
|
|
||||||
lock_guard<recursive_mutex> lock(m_mtxMap);
|
|
||||||
return (m_mapCfgFrame.size() != 0);
|
|
||||||
}
|
|
||||||
virtual void onGetMetaData(const AMFValue &_metadata) {
|
|
||||||
m_metadata = _metadata;
|
|
||||||
}
|
|
||||||
virtual void onGetMedia(const RtmpPacket &_pkt) {
|
|
||||||
RtmpPacket & pkt = const_cast<RtmpPacket &>(_pkt);
|
|
||||||
if (pkt.isCfgFrame()) {
|
|
||||||
lock_guard<recursive_mutex> lock(m_mtxMap);
|
|
||||||
m_mapCfgFrame.emplace(pkt.typeId, pkt);
|
|
||||||
}
|
|
||||||
auto _ring = m_pRing;
|
|
||||||
m_thPool.async([_ring,pkt]() {
|
|
||||||
_ring->write(pkt,pkt.isVideoKeyFrame());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
bool seekTo(uint32_t ui32Stamp) {
|
|
||||||
if (!m_onSeek) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return m_onSeek(ui32Stamp);
|
|
||||||
}
|
|
||||||
virtual void setOnSeek(const function<bool(uint32_t)> &cb) {
|
|
||||||
m_onSeek = cb;
|
|
||||||
}
|
|
||||||
uint32_t getStamp() {
|
|
||||||
if (!m_onStamp) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_onStamp();
|
|
||||||
}
|
|
||||||
virtual void setOnStamp(const function<uint32_t()> &cb) {
|
|
||||||
m_onStamp = cb;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
function<bool(uint32_t)> m_onSeek;
|
|
||||||
function<uint32_t()> m_onStamp;
|
|
||||||
private:
|
|
||||||
AMFValue m_metadata;
|
|
||||||
unordered_map<int, RtmpPacket> m_mapCfgFrame;
|
|
||||||
mutable recursive_mutex m_mtxMap;
|
|
||||||
string m_strApp; //媒体app
|
|
||||||
string m_strId; //媒体id
|
|
||||||
RingBuffer<RtmpPacket>::Ptr m_pRing; //rtp环形缓冲
|
|
||||||
ThreadPool &m_thPool;
|
|
||||||
static unordered_map<string, unordered_map<string,weak_ptr<RtmpMediaSource> > > g_mapMediaSrc; //静态的媒体源表
|
|
||||||
static recursive_mutex g_mtxMediaSrc; ///访问静态的媒体源表的互斥锁
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPMEDIASOURCE_H_ */
|
|
@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpParser.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月2日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPPARSER_H_
|
|
||||||
#define SRC_RTMP_RTMPPARSER_H_
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "Player/Player.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
class RtmpParser : public PlayerBase{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpParser> Ptr;
|
|
||||||
RtmpParser(const AMFValue &val);
|
|
||||||
virtual ~RtmpParser();
|
|
||||||
|
|
||||||
bool inputRtmp(const RtmpPacket &pkt);
|
|
||||||
|
|
||||||
void setOnVideoCB(const function<void(const H264Frame &frame)> &cb) override{
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxCB);
|
|
||||||
onVideo = cb;
|
|
||||||
}
|
|
||||||
void setOnAudioCB(const function<void(const AdtsFrame &frame)> &cb) override{
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxCB);
|
|
||||||
onAudio = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVideoHeight() const override{
|
|
||||||
return m_iVideoHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVideoWidth() const override{
|
|
||||||
return m_iVideoWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getVideoFps() const override{
|
|
||||||
return m_fVideoFps;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleRate() const override{
|
|
||||||
return m_iSampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleBit() const override{
|
|
||||||
return m_iSampleBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioChannel() const override{
|
|
||||||
return m_iChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getPps() const override{
|
|
||||||
return m_strPPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getSps() const override{
|
|
||||||
return m_strSPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getAudioCfg() const override{
|
|
||||||
return m_strAudioCfg;
|
|
||||||
}
|
|
||||||
bool containAudio() const override{
|
|
||||||
return m_bHaveAudio;
|
|
||||||
}
|
|
||||||
bool containVideo () const override{
|
|
||||||
return m_bHaveVideo;
|
|
||||||
}
|
|
||||||
bool isInited() const override{
|
|
||||||
if (m_bHaveAudio && !m_strAudioCfg.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (m_bHaveVideo && !m_strSPS.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
float getDuration() const override{
|
|
||||||
return m_fDuration;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
inline void onCheckMedia(const AMFValue &obj);
|
|
||||||
|
|
||||||
//返回值:true 代表是i帧第一个rtp包
|
|
||||||
inline bool inputVideo(const RtmpPacket &pkt);
|
|
||||||
inline bool inputAudio(const RtmpPacket &pkt);
|
|
||||||
inline void _onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
|
|
||||||
inline void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
|
|
||||||
inline void onGetAAC(const char *pcData, int iLen, uint32_t ui32TimeStamp);
|
|
||||||
//video
|
|
||||||
H264Frame m_h264frame;
|
|
||||||
//aduio
|
|
||||||
AdtsFrame m_adts;
|
|
||||||
|
|
||||||
int m_iSampleRate = 44100;
|
|
||||||
int m_iSampleBit = 16;
|
|
||||||
int m_iChannel = 1;
|
|
||||||
|
|
||||||
string m_strSPS;
|
|
||||||
string m_strPPS;
|
|
||||||
string m_strAudioCfg;
|
|
||||||
int m_iVideoWidth = 0;
|
|
||||||
int m_iVideoHeight = 0;
|
|
||||||
float m_fVideoFps = 0;
|
|
||||||
bool m_bHaveAudio = false;
|
|
||||||
bool m_bHaveVideo = false;
|
|
||||||
float m_fDuration = 0;
|
|
||||||
function<void(const H264Frame &frame)> onVideo;
|
|
||||||
function<void(const AdtsFrame &frame)> onAudio;
|
|
||||||
recursive_mutex m_mtxCB;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPPARSER_H_ */
|
|
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpPlayer2.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年11月29日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RtmpPlayer2_H_
|
|
||||||
#define SRC_RTMP_RtmpPlayer2_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "RtmpProtocol.h"
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
#include "Network/TcpClient.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
class RtmpPlayer:public PlayerBase, public TcpClient, public RtmpProtocol{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpPlayer> Ptr;
|
|
||||||
RtmpPlayer();
|
|
||||||
virtual ~RtmpPlayer();
|
|
||||||
|
|
||||||
void play(const char* strUrl) override;
|
|
||||||
void pause(bool bPause) override;
|
|
||||||
void teardown() override;
|
|
||||||
protected:
|
|
||||||
virtual bool onCheckMeta(AMFValue &val) =0;
|
|
||||||
virtual void onMediaData(RtmpPacket &chunkData) =0;
|
|
||||||
float getProgressTime() const;
|
|
||||||
void seekToTime(float fTime);
|
|
||||||
private:
|
|
||||||
void _onShutdown(const SockException &ex) {
|
|
||||||
WarnL << ex.getErrCode() << " " << ex.what();
|
|
||||||
m_pPlayTimer.reset();
|
|
||||||
m_pMediaTimer.reset();
|
|
||||||
m_pBeatTimer.reset();
|
|
||||||
onShutdown(ex);
|
|
||||||
}
|
|
||||||
void _onMediaData(RtmpPacket &chunkData) {
|
|
||||||
m_mediaTicker.resetTime();
|
|
||||||
onMediaData(chunkData);
|
|
||||||
}
|
|
||||||
void _onPlayResult(const SockException &ex) {
|
|
||||||
WarnL << ex.getErrCode() << " " << ex.what();
|
|
||||||
m_pPlayTimer.reset();
|
|
||||||
m_pMediaTimer.reset();
|
|
||||||
if (!ex) {
|
|
||||||
m_mediaTicker.resetTime();
|
|
||||||
weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
|
|
||||||
m_pMediaTimer.reset( new Timer(5, [weakSelf]() {
|
|
||||||
auto strongSelf=weakSelf.lock();
|
|
||||||
if(!strongSelf) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(strongSelf->m_mediaTicker.elapsedTime()>10000) {
|
|
||||||
//recv media timeout!
|
|
||||||
strongSelf->_onShutdown(SockException(Err_timeout,"recv rtmp timeout"));
|
|
||||||
strongSelf->teardown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
onPlayResult(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
//for Tcpclient
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
void onConnect(const SockException &err) override;
|
|
||||||
void onErr(const SockException &ex) override;
|
|
||||||
//fro RtmpProtocol
|
|
||||||
void onRtmpChunk(RtmpPacket &chunkData) override;
|
|
||||||
void onStreamDry(uint32_t ui32StreamId) override;
|
|
||||||
void onSendRawData(const char *pcRawData, int iSize) override {
|
|
||||||
send(pcRawData, iSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FUN>
|
|
||||||
inline void addOnResultCB(const FUN &fun) {
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
|
|
||||||
m_mapOnResultCB.emplace(m_iReqID, fun);
|
|
||||||
}
|
|
||||||
template<typename FUN>
|
|
||||||
inline void addOnStatusCB(const FUN &fun) {
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
|
|
||||||
m_dqOnStatusCB.emplace_back(fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onCmd_result(AMFDecoder &dec);
|
|
||||||
void onCmd_onStatus(AMFDecoder &dec);
|
|
||||||
void onCmd_onMetaData(AMFDecoder &dec);
|
|
||||||
|
|
||||||
inline void send_connect();
|
|
||||||
inline void send_createStream();
|
|
||||||
inline void send_play();
|
|
||||||
inline void send_pause(bool bPause);
|
|
||||||
|
|
||||||
string m_strApp;
|
|
||||||
string m_strStream;
|
|
||||||
string m_strTcUrl;
|
|
||||||
bool m_bPaused = false;
|
|
||||||
|
|
||||||
unordered_map<int, function<void(AMFDecoder &dec)> > m_mapOnResultCB;
|
|
||||||
recursive_mutex m_mtxOnResultCB;
|
|
||||||
deque<function<void(AMFValue &dec)> > m_dqOnStatusCB;
|
|
||||||
recursive_mutex m_mtxOnStatusCB;
|
|
||||||
|
|
||||||
typedef void (RtmpPlayer::*rtmpCMDHandle)(AMFDecoder &dec);
|
|
||||||
static unordered_map<string, rtmpCMDHandle> g_mapCmd;
|
|
||||||
|
|
||||||
//超时功能实现
|
|
||||||
Ticker m_mediaTicker;
|
|
||||||
std::shared_ptr<Timer> m_pMediaTimer;
|
|
||||||
std::shared_ptr<Timer> m_pPlayTimer;
|
|
||||||
//心跳定时器
|
|
||||||
std::shared_ptr<Timer> m_pBeatTimer;
|
|
||||||
|
|
||||||
//播放进度控制
|
|
||||||
float m_fSeekTo = 0;
|
|
||||||
double m_adFistStamp[2] = { 0, 0 };
|
|
||||||
double m_adNowStamp[2] = { 0, 0 };
|
|
||||||
Ticker m_aNowStampTicker[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RtmpPlayer2_H_ */
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpPlayerImp.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月1日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPPLAYERIMP_H_
|
|
||||||
#define SRC_RTMP_RTMPPLAYERIMP_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "RtmpPlayer.h"
|
|
||||||
#include "RtmpParser.h"
|
|
||||||
#include "Poller/Timer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
class RtmpPlayerImp: public PlayerImp<RtmpPlayer,RtmpParser> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpPlayerImp> Ptr;
|
|
||||||
RtmpPlayerImp();
|
|
||||||
virtual ~RtmpPlayerImp();
|
|
||||||
float getProgresss() const override{
|
|
||||||
if(getDuration() > 0){
|
|
||||||
return getProgressTime() / getDuration();
|
|
||||||
}
|
|
||||||
return PlayerBase::getProgresss();
|
|
||||||
};
|
|
||||||
void seekTo(float fProgress) override{
|
|
||||||
fProgress = MAX(float(0),MIN(fProgress,float(1.0)));
|
|
||||||
seekToTime(fProgress * getDuration());
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
//派生类回调函数
|
|
||||||
bool onCheckMeta(AMFValue &val) override {
|
|
||||||
try {
|
|
||||||
m_parser.reset(new RtmpParser(val));
|
|
||||||
m_parser->setOnVideoCB(m_onGetVideoCB);
|
|
||||||
m_parser->setOnAudioCB(m_onGetAudioCB);
|
|
||||||
return true;
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
WarnL << ex.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void onMediaData(RtmpPacket &chunkData) override {
|
|
||||||
m_parser->inputRtmp(chunkData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPPLAYERIMP_H_ */
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpProtocol.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年2月7日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPPROTOCOL_H_
|
|
||||||
#define SRC_RTMP_RTMPPROTOCOL_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
class RtmpProtocol {
|
|
||||||
public:
|
|
||||||
RtmpProtocol();
|
|
||||||
virtual ~RtmpProtocol();
|
|
||||||
//作为客户端发送c0c1,等待s0s1s2并且回调
|
|
||||||
void startClientSession(const function<void()> &cb);
|
|
||||||
void onParseRtmp(const char *pcRawData,int iSize);
|
|
||||||
void reset();
|
|
||||||
protected:
|
|
||||||
virtual void onSendRawData(const char *pcRawData,int iSize) = 0;
|
|
||||||
virtual void onRtmpChunk(RtmpPacket &chunkData) = 0;
|
|
||||||
|
|
||||||
virtual void onStreamBegin(uint32_t ui32StreamId){
|
|
||||||
m_ui32StreamId = ui32StreamId;
|
|
||||||
}
|
|
||||||
virtual void onStreamEof(uint32_t ui32StreamId){};
|
|
||||||
virtual void onStreamDry(uint32_t ui32StreamId){};
|
|
||||||
protected:
|
|
||||||
void sendAcknowledgement(uint32_t ui32Size);
|
|
||||||
void sendAcknowledgementSize(uint32_t ui32Size);
|
|
||||||
void sendPeerBandwidth(uint32_t ui32Size);
|
|
||||||
void sendChunkSize(uint32_t ui32Size);
|
|
||||||
void sendPingRequest(uint32_t ui32TimeStamp = ::time(NULL));
|
|
||||||
void sendPingResponse(uint32_t ui32TimeStamp = ::time(NULL));
|
|
||||||
void sendSetBufferLength(uint32_t ui32StreamId, uint32_t ui32Length);
|
|
||||||
void sendUserControl(uint16_t ui16EventType, uint32_t ui32EventData);
|
|
||||||
void sendUserControl(uint16_t ui16EventType, const string &strEventData);
|
|
||||||
|
|
||||||
void sendInvoke(const string &strCmd, const AMFValue &val);
|
|
||||||
void sendRequest(int iCmd, const string &str);
|
|
||||||
void sendResponse(int iType, const string &str);
|
|
||||||
void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID);
|
|
||||||
protected:
|
|
||||||
int m_iReqID = 0;
|
|
||||||
uint32_t m_ui32StreamId = STREAM_CONTROL;
|
|
||||||
int m_iNowStreamID = 0;
|
|
||||||
int m_iNowChunkID = 0;
|
|
||||||
bool m_bDataStarted = false;
|
|
||||||
private:
|
|
||||||
void handle_S0S1S2(const function<void()> &cb);
|
|
||||||
void handle_C0C1();
|
|
||||||
|
|
||||||
void handle_C1_simple();
|
|
||||||
#ifdef ENABLE_OPENSSL
|
|
||||||
void handle_C1_complex();
|
|
||||||
string get_C1_digest(const uint8_t *ptr,char **digestPos);
|
|
||||||
string get_C1_key(const uint8_t *ptr);
|
|
||||||
void check_C1_Digest(const string &digest,const string &data);
|
|
||||||
void send_complex_S0S1S2(int schemeType,const string &digest);
|
|
||||||
#endif //ENABLE_OPENSSL
|
|
||||||
|
|
||||||
void handle_C2();
|
|
||||||
void handle_rtmp();
|
|
||||||
void handle_rtmpChunk(RtmpPacket &chunkData);
|
|
||||||
|
|
||||||
////////////ChunkSize////////////
|
|
||||||
size_t m_iChunkLenIn = DEFAULT_CHUNK_LEN;
|
|
||||||
size_t m_iChunkLenOut = DEFAULT_CHUNK_LEN;
|
|
||||||
////////////Acknowledgement////////////
|
|
||||||
uint32_t m_ui32ByteSent = 0;
|
|
||||||
uint32_t m_ui32LastSent = 0;
|
|
||||||
uint32_t m_ui32WinSize = 0;
|
|
||||||
///////////PeerBandwidth///////////
|
|
||||||
uint32_t m_ui32Bandwidth = 2500000;
|
|
||||||
uint8_t m_ui8LimitType = 2;
|
|
||||||
////////////Chunk////////////
|
|
||||||
unordered_map<int, RtmpPacket> m_mapChunkData;
|
|
||||||
//////////Rtmp parser//////////
|
|
||||||
string m_strRcvBuf;
|
|
||||||
function<void()> m_nextHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPPROTOCOL_H_ */
|
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpPusher.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年2月13日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPPUSHER_H_
|
|
||||||
#define SRC_RTMP_RTMPPUSHER_H_
|
|
||||||
|
|
||||||
#include "RtmpProtocol.h"
|
|
||||||
#include "RtmpMediaSource.h"
|
|
||||||
#include "Network/TcpClient.h"
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
class RtmpPusher: public RtmpProtocol , public TcpClient{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpPusher> Ptr;
|
|
||||||
typedef std::function<void(const SockException &ex)> Event;
|
|
||||||
RtmpPusher(const char *strApp,const char *strStream);
|
|
||||||
virtual ~RtmpPusher();
|
|
||||||
|
|
||||||
void publish(const char* strUrl);
|
|
||||||
void teardown();
|
|
||||||
|
|
||||||
void setOnPublished(Event onPublished) {
|
|
||||||
m_onPublished = onPublished;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOnShutdown(Event onShutdown) {
|
|
||||||
m_onShutdown = onShutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
//for Tcpclient
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
void onConnect(const SockException &err) override;
|
|
||||||
void onErr(const SockException &ex) override;
|
|
||||||
|
|
||||||
//fro RtmpProtocol
|
|
||||||
void onRtmpChunk(RtmpPacket &chunkData) override;
|
|
||||||
void onSendRawData(const char *pcRawData, int iSize) override {
|
|
||||||
send(pcRawData, iSize);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void onShutdown(const SockException &ex) {
|
|
||||||
m_pPublishTimer.reset();
|
|
||||||
if(m_onShutdown){
|
|
||||||
m_onShutdown(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void onPublishResult(const SockException &ex) {
|
|
||||||
m_pPublishTimer.reset();
|
|
||||||
if(m_onPublished){
|
|
||||||
m_onPublished(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FUN>
|
|
||||||
inline void addOnResultCB(const FUN &fun) {
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
|
|
||||||
m_mapOnResultCB.emplace(m_iReqID, fun);
|
|
||||||
}
|
|
||||||
template<typename FUN>
|
|
||||||
inline void addOnStatusCB(const FUN &fun) {
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
|
|
||||||
m_dqOnStatusCB.emplace_back(fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onCmd_result(AMFDecoder &dec);
|
|
||||||
void onCmd_onStatus(AMFDecoder &dec);
|
|
||||||
void onCmd_onMetaData(AMFDecoder &dec);
|
|
||||||
|
|
||||||
inline void send_connect();
|
|
||||||
inline void send_createStream();
|
|
||||||
inline void send_publish();
|
|
||||||
inline void send_metaData();
|
|
||||||
|
|
||||||
string m_strApp;
|
|
||||||
string m_strStream;
|
|
||||||
string m_strTcUrl;
|
|
||||||
|
|
||||||
unordered_map<int, function<void(AMFDecoder &dec)> > m_mapOnResultCB;
|
|
||||||
recursive_mutex m_mtxOnResultCB;
|
|
||||||
deque<function<void(AMFValue &dec)> > m_dqOnStatusCB;
|
|
||||||
recursive_mutex m_mtxOnStatusCB;
|
|
||||||
|
|
||||||
typedef void (RtmpPusher::*rtmpCMDHandle)(AMFDecoder &dec);
|
|
||||||
static unordered_map<string, rtmpCMDHandle> g_mapCmd;
|
|
||||||
|
|
||||||
//超时功能实现
|
|
||||||
std::shared_ptr<Timer> m_pPublishTimer;
|
|
||||||
|
|
||||||
//源
|
|
||||||
std::weak_ptr<RtmpMediaSource> m_pMediaSrc;
|
|
||||||
RtmpMediaSource::RingType::RingReader::Ptr m_pRtmpReader;
|
|
||||||
//事件监听
|
|
||||||
Event m_onShutdown;
|
|
||||||
Event m_onPublished;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPPUSHER_H_ */
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpSession.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年2月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPSESSION_H_
|
|
||||||
#define SRC_RTMP_RTMPSESSION_H_
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "RtmpProtocol.h"
|
|
||||||
#include "RtmpToRtspMediaSource.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Network/TcpLimitedSession.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
class RtmpSession: public TcpLimitedSession<MAX_TCP_SESSION> ,public RtmpProtocol{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpSession> Ptr;
|
|
||||||
RtmpSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock);
|
|
||||||
virtual ~RtmpSession();
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
void onError(const SockException &err) override;
|
|
||||||
void onManager() override;
|
|
||||||
private:
|
|
||||||
std::string m_strApp;
|
|
||||||
std::string m_strId;
|
|
||||||
double m_dNowReqID = 0;
|
|
||||||
Ticker m_ticker;//数据接收时间
|
|
||||||
typedef void (RtmpSession::*rtmpCMDHandle)(AMFDecoder &dec);
|
|
||||||
static unordered_map<string, rtmpCMDHandle> g_mapCmd;
|
|
||||||
|
|
||||||
RingBuffer<RtmpPacket>::RingReader::Ptr m_pRingReader;
|
|
||||||
std::shared_ptr<RtmpMediaSource> m_pPublisherSrc;
|
|
||||||
bool m_bPublisherSrcRegisted = false;
|
|
||||||
std::weak_ptr<RtmpMediaSource> m_pPlayerSrc;
|
|
||||||
uint32_t m_aui32FirstStamp[2] = {0};
|
|
||||||
|
|
||||||
void onProcessCmd(AMFDecoder &dec);
|
|
||||||
void onCmd_connect(AMFDecoder &dec);
|
|
||||||
void onCmd_createStream(AMFDecoder &dec);
|
|
||||||
|
|
||||||
void onCmd_publish(AMFDecoder &dec);
|
|
||||||
void onCmd_deleteStream(AMFDecoder &dec);
|
|
||||||
|
|
||||||
void onCmd_play(AMFDecoder &dec);
|
|
||||||
void onCmd_play2(AMFDecoder &dec);
|
|
||||||
void doPlay();
|
|
||||||
void onCmd_seek(AMFDecoder &dec);
|
|
||||||
void onCmd_pause(AMFDecoder &dec);
|
|
||||||
void setMetaData(AMFDecoder &dec);
|
|
||||||
|
|
||||||
void onSendMedia(const RtmpPacket &pkt);
|
|
||||||
void onSendRawData(const char *pcRawData,int iSize) override{
|
|
||||||
send(pcRawData, iSize);
|
|
||||||
}
|
|
||||||
void onRtmpChunk(RtmpPacket &chunkData) override;
|
|
||||||
|
|
||||||
template<typename first, typename second>
|
|
||||||
inline void sendReply(const char *str, const first &reply, const second &status) {
|
|
||||||
AMFEncoder invoke;
|
|
||||||
invoke << str << m_dNowReqID << reply << status;
|
|
||||||
sendResponse(MSG_CMD, invoke.data());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPSESSION_H_ */
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtmpToRtspMediaSource.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年10月20日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTMP_RTMPTORTSPMEDIASOURCE_H_
|
|
||||||
#define SRC_RTMP_RTMPTORTSPMEDIASOURCE_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "amf.h"
|
|
||||||
#include "Rtmp.h"
|
|
||||||
#include "RtmpParser.h"
|
|
||||||
#include "RtmpMediaSource.h"
|
|
||||||
#include "RTP/RtpMakerH264.h"
|
|
||||||
#include "RTP/RtpMakerAAC.h"
|
|
||||||
#include "Rtsp/RtpParser.h"
|
|
||||||
#include "Rtsp/RtspMediaSource.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "MediaFile/MediaRecorder.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::MediaFile;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtmp {
|
|
||||||
|
|
||||||
#ifdef ENABLE_RTMP2RTSP
|
|
||||||
class RtmpToRtspMediaSource: public RtmpMediaSource {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtmpToRtspMediaSource> Ptr;
|
|
||||||
RtmpToRtspMediaSource(const string &_app, const string &_id);
|
|
||||||
virtual ~RtmpToRtspMediaSource();
|
|
||||||
virtual void regist() override;
|
|
||||||
virtual void unregist() override;
|
|
||||||
|
|
||||||
virtual void onGetMetaData(const AMFValue &_metadata) override {
|
|
||||||
try {
|
|
||||||
m_pParser.reset(new RtmpParser(_metadata));
|
|
||||||
m_pRecorder.reset(new MediaRecorder(getApp(),getId(),m_pParser));
|
|
||||||
m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAdts, this, placeholders::_1));
|
|
||||||
m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
|
|
||||||
} catch (exception &ex) {
|
|
||||||
WarnL << ex.what();
|
|
||||||
}
|
|
||||||
RtmpMediaSource::onGetMetaData(_metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onGetMedia(const RtmpPacket &pkt) override {
|
|
||||||
if (m_pParser) {
|
|
||||||
if (!m_pRtspSrc && m_pParser->isInited()) {
|
|
||||||
makeSDP();
|
|
||||||
}
|
|
||||||
m_pParser->inputRtmp(pkt);
|
|
||||||
}
|
|
||||||
RtmpMediaSource::onGetMedia(pkt);
|
|
||||||
}
|
|
||||||
void setOnSeek(const function<bool(uint32_t)> &cb) override {
|
|
||||||
RtmpMediaSource::setOnSeek(cb);
|
|
||||||
if (m_pRtspSrc) {
|
|
||||||
m_pRtspSrc->setOnSeek(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setOnStamp(const function<uint32_t()> &cb) override{
|
|
||||||
RtmpMediaSource::setOnStamp(cb);
|
|
||||||
if (m_pRtspSrc) {
|
|
||||||
m_pRtspSrc->setOnStamp(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
RtmpParser::Ptr m_pParser;
|
|
||||||
RtspMediaSource::Ptr m_pRtspSrc;
|
|
||||||
RtpMaker_AAC::Ptr m_pRtpMaker_aac;
|
|
||||||
RtpMaker_H264::Ptr m_pRtpMaker_h264;
|
|
||||||
MediaRecorder::Ptr m_pRecorder;
|
|
||||||
|
|
||||||
void onGetH264(const H264Frame &frame);
|
|
||||||
void onGetAdts(const AdtsFrame &frame);
|
|
||||||
void makeSDP();
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
typedef RtmpMediaSource RtmpToRtspMediaSource;
|
|
||||||
#endif //ENABLE_RTMP2RTSP
|
|
||||||
|
|
||||||
} /* namespace Rtmp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTMP_RTMPTORTSPMEDIASOURCE_H_ */
|
|
@ -1,224 +0,0 @@
|
|||||||
#ifndef __amf_h
|
|
||||||
#define __amf_h
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <map>
|
|
||||||
enum AMFType {
|
|
||||||
AMF_NUMBER,
|
|
||||||
AMF_INTEGER,
|
|
||||||
AMF_BOOLEAN,
|
|
||||||
AMF_STRING,
|
|
||||||
AMF_OBJECT,
|
|
||||||
AMF_NULL,
|
|
||||||
AMF_UNDEFINED,
|
|
||||||
AMF_ECMA_ARRAY,
|
|
||||||
AMF_STRICT_ARRAY,
|
|
||||||
};
|
|
||||||
|
|
||||||
class AMFValue;
|
|
||||||
|
|
||||||
class AMFValue {
|
|
||||||
public:
|
|
||||||
|
|
||||||
AMFValue(AMFType type = AMF_NULL);
|
|
||||||
AMFValue(const char *s);
|
|
||||||
AMFValue(const std::string &s);
|
|
||||||
AMFValue(double n);
|
|
||||||
AMFValue(int i);
|
|
||||||
AMFValue(bool b);
|
|
||||||
AMFValue(const AMFValue &from);
|
|
||||||
AMFValue(AMFValue &&from);
|
|
||||||
AMFValue &operator =(const AMFValue &from);
|
|
||||||
AMFValue &operator =(AMFValue &&from);
|
|
||||||
~AMFValue();
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
switch (m_type) {
|
|
||||||
case AMF_STRING:
|
|
||||||
m_value.string->clear();
|
|
||||||
break;
|
|
||||||
case AMF_OBJECT:
|
|
||||||
case AMF_ECMA_ARRAY:
|
|
||||||
m_value.object->clear();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFType type() const {
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &as_string() const {
|
|
||||||
if(m_type != AMF_STRING){
|
|
||||||
throw std::runtime_error("AMF not a string");
|
|
||||||
}
|
|
||||||
return *m_value.string;
|
|
||||||
}
|
|
||||||
double as_number() const {
|
|
||||||
switch (m_type) {
|
|
||||||
case AMF_NUMBER:
|
|
||||||
return m_value.number;
|
|
||||||
case AMF_INTEGER:
|
|
||||||
return m_value.integer;
|
|
||||||
case AMF_BOOLEAN:
|
|
||||||
return m_value.boolean;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("AMF not a number");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int as_integer() const {
|
|
||||||
switch (m_type) {
|
|
||||||
case AMF_NUMBER:
|
|
||||||
return m_value.number;
|
|
||||||
case AMF_INTEGER:
|
|
||||||
return m_value.integer;
|
|
||||||
case AMF_BOOLEAN:
|
|
||||||
return m_value.boolean;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("AMF not a integer");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool as_boolean() const {
|
|
||||||
switch (m_type) {
|
|
||||||
case AMF_NUMBER:
|
|
||||||
return m_value.number;
|
|
||||||
case AMF_INTEGER:
|
|
||||||
return m_value.integer;
|
|
||||||
case AMF_BOOLEAN:
|
|
||||||
return m_value.boolean;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("AMF not a boolean");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AMFValue &operator[](const char *str) const {
|
|
||||||
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a object");
|
|
||||||
}
|
|
||||||
auto i = m_value.object->find(str);
|
|
||||||
if (i == m_value.object->end()) {
|
|
||||||
static AMFValue val(AMF_NULL);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
return i->second;
|
|
||||||
}
|
|
||||||
template<typename FUN>
|
|
||||||
void object_for_each(const FUN &fun) const {
|
|
||||||
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a object");
|
|
||||||
}
|
|
||||||
for (auto & pr : *(m_value.object)) {
|
|
||||||
fun(pr.first, pr.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const{
|
|
||||||
return m_type != AMF_NULL;
|
|
||||||
}
|
|
||||||
void set(const std::string &s, const AMFValue &val) {
|
|
||||||
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a object");
|
|
||||||
}
|
|
||||||
m_value.object->emplace(s, val);
|
|
||||||
}
|
|
||||||
void add(const AMFValue &val) {
|
|
||||||
if (m_type != AMF_STRICT_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a array");
|
|
||||||
}
|
|
||||||
assert(m_type == AMF_STRICT_ARRAY);
|
|
||||||
m_value.array->push_back(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::map<std::string, AMFValue> mapType;
|
|
||||||
typedef std::vector<AMFValue> arrayType;
|
|
||||||
|
|
||||||
AMFType m_type;
|
|
||||||
union {
|
|
||||||
std::string *string;
|
|
||||||
double number;
|
|
||||||
int integer;
|
|
||||||
bool boolean;
|
|
||||||
mapType *object;
|
|
||||||
arrayType *array;
|
|
||||||
} m_value;
|
|
||||||
|
|
||||||
friend class AMFEncoder;
|
|
||||||
const mapType &getMap() const {
|
|
||||||
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a object");
|
|
||||||
}
|
|
||||||
return *m_value.object;
|
|
||||||
}
|
|
||||||
const arrayType &getArr() const {
|
|
||||||
if (m_type != AMF_STRICT_ARRAY) {
|
|
||||||
throw std::runtime_error("AMF not a array");
|
|
||||||
}
|
|
||||||
return *m_value.array;
|
|
||||||
}
|
|
||||||
inline void destroy();
|
|
||||||
inline void init();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AMFDecoder {
|
|
||||||
public:
|
|
||||||
AMFDecoder(const std::string &_buf, size_t _pos, int _version = 0) :
|
|
||||||
buf(_buf), pos(_pos), version(_version) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVersion() const {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TP>
|
|
||||||
TP load();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string &buf;
|
|
||||||
size_t pos;
|
|
||||||
int version;
|
|
||||||
|
|
||||||
std::string load_key();
|
|
||||||
AMFValue load_object();
|
|
||||||
AMFValue load_ecma();
|
|
||||||
AMFValue load_arr();
|
|
||||||
uint8_t front();
|
|
||||||
uint8_t pop_front();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AMFEncoder {
|
|
||||||
public:
|
|
||||||
AMFEncoder & operator <<(const char *s);
|
|
||||||
AMFEncoder & operator <<(const std::string &s);
|
|
||||||
AMFEncoder & operator <<(std::nullptr_t);
|
|
||||||
AMFEncoder & operator <<(const int n);
|
|
||||||
AMFEncoder & operator <<(const double n);
|
|
||||||
AMFEncoder & operator <<(const bool b);
|
|
||||||
AMFEncoder & operator <<(const AMFValue &value);
|
|
||||||
const std::string data() const {
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
void clear() {
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void write_key(const std::string &s);
|
|
||||||
AMFEncoder &write_undefined();
|
|
||||||
std::string buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||||||
#ifndef __utils_h
|
|
||||||
#define __utils_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t load_be32(const void *p);
|
|
||||||
uint16_t load_be16(const void *p);
|
|
||||||
uint32_t load_be24(const void *p);
|
|
||||||
uint32_t load_le32(const void *p);
|
|
||||||
void set_be24(void *p, uint32_t val);
|
|
||||||
void set_le32(void *p, uint32_t val);
|
|
||||||
void set_be32(void *p, uint32_t val);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtpBroadCaster.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月23日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTSP_RTPBROADCASTER_H_
|
|
||||||
#define SRC_RTSP_RTPBROADCASTER_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "RtspMediaSource.h"
|
|
||||||
#include "Util/mini.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class MultiCastAddressMaker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static MultiCastAddressMaker &Instance(){
|
|
||||||
static MultiCastAddressMaker instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
static bool isMultiCastAddress(uint32_t iAddr){
|
|
||||||
static uint32_t addrMin = mINI::Instance()[Config::MultiCast::kAddrMin].as<uint32_t>();
|
|
||||||
static uint32_t addrMax = mINI::Instance()[Config::MultiCast::kAddrMax].as<uint32_t>();
|
|
||||||
return iAddr >= addrMin && iAddr <= addrMax;
|
|
||||||
}
|
|
||||||
static string toString(uint32_t iAddr){
|
|
||||||
iAddr = htonl(iAddr);
|
|
||||||
return ::inet_ntoa((struct in_addr &)(iAddr));
|
|
||||||
}
|
|
||||||
virtual ~MultiCastAddressMaker(){}
|
|
||||||
std::shared_ptr<uint32_t> obtain(uint32_t iTry = 10);
|
|
||||||
private:
|
|
||||||
MultiCastAddressMaker(){};
|
|
||||||
void release(uint32_t iAddr);
|
|
||||||
uint32_t m_iAddr = mINI::Instance()[Config::MultiCast::kAddrMin].as<uint32_t>();
|
|
||||||
recursive_mutex m_mtx;
|
|
||||||
unordered_set<uint32_t> m_setBadAddr;
|
|
||||||
};
|
|
||||||
class RtpBroadCaster {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtpBroadCaster> Ptr;
|
|
||||||
typedef function<void()> onDetach;
|
|
||||||
virtual ~RtpBroadCaster();
|
|
||||||
static Ptr get(const string &strLocalIp,const string &strApp,const string &strStream);
|
|
||||||
void setDetachCB(void *listener,const onDetach &cb);
|
|
||||||
uint16_t getPort(int iTrackId);
|
|
||||||
string getIP();
|
|
||||||
private:
|
|
||||||
static recursive_mutex g_mtx;
|
|
||||||
static unordered_map<string , weak_ptr<RtpBroadCaster> > g_mapBroadCaster;
|
|
||||||
static Ptr make(const string &strLocalIp,const string &strApp,const string &strStream);
|
|
||||||
|
|
||||||
std::shared_ptr<uint32_t> m_multiAddr;
|
|
||||||
recursive_mutex m_mtx;
|
|
||||||
unordered_map<void * , onDetach > m_mapDetach;
|
|
||||||
RtspMediaSource::RingType::RingReader::Ptr m_pReader;
|
|
||||||
Socket::Ptr m_apUdpSock[2];
|
|
||||||
struct sockaddr_in m_aPeerUdpAddr[2];
|
|
||||||
|
|
||||||
RtpBroadCaster(const string &strLocalIp,const string &strApp,const string &strStream);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTSP_RTPBROADCASTER_H_ */
|
|
@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtpPraser.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月5日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTP_RTPPARSER_H_
|
|
||||||
#define SRC_RTP_RTPPARSER_H_
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Rtsp/Rtsp.h"
|
|
||||||
#include "Player/Player.h"
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtpParser : public PlayerBase{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtpParser> Ptr;
|
|
||||||
RtpParser(const string &sdp);
|
|
||||||
virtual ~RtpParser();
|
|
||||||
//返回值:true 代表是i帧第一个rtp包
|
|
||||||
bool inputRtp(const RtpPacket &rtp);
|
|
||||||
void setOnVideoCB(const function<void(const H264Frame &frame)> &cb) override{
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxCB);
|
|
||||||
onVideo = cb;
|
|
||||||
}
|
|
||||||
void setOnAudioCB(const function<void(const AdtsFrame &frame)> &cb) override{
|
|
||||||
lock_guard<recursive_mutex> lck(m_mtxCB);
|
|
||||||
onAudio = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVideoHeight() const override{
|
|
||||||
return m_iVideoHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getVideoWidth() const override{
|
|
||||||
return m_iVideoWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getVideoFps() const override{
|
|
||||||
return m_fVideoFps;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleRate() const override{
|
|
||||||
return m_iSampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioSampleBit() const override{
|
|
||||||
return m_iSampleBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAudioChannel() const override{
|
|
||||||
return m_iChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getPps() const override{
|
|
||||||
return m_strPPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getSps() const override{
|
|
||||||
return m_strSPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getAudioCfg() const override{
|
|
||||||
return m_strAudioCfg;
|
|
||||||
}
|
|
||||||
bool containAudio() const override{
|
|
||||||
return m_bHaveAudio;
|
|
||||||
}
|
|
||||||
bool containVideo() const override{
|
|
||||||
return m_bHaveVideo;
|
|
||||||
}
|
|
||||||
bool isInited() const override{
|
|
||||||
if (m_bHaveAudio && !m_strAudioCfg.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (m_bHaveVideo && !m_strSPS.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
float getDuration() const override {
|
|
||||||
return m_fDuration;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::unordered_map<uint8_t, RtspTrack> m_mapTracks;
|
|
||||||
|
|
||||||
inline void onGetAudioTrack(const RtspTrack &audio);
|
|
||||||
inline void onGetVideoTrack(const RtspTrack &video);
|
|
||||||
|
|
||||||
//返回值:true 代表是i帧第一个rtp包
|
|
||||||
inline bool inputVideo(const RtpPacket &rtp, const RtspTrack &track);
|
|
||||||
inline bool inputAudio(const RtpPacket &rtp, const RtspTrack &track);
|
|
||||||
inline void _onGetH264(H264Frame &frame);
|
|
||||||
inline void onGetH264(H264Frame &frame);
|
|
||||||
inline void onGetAdts(AdtsFrame &frame);
|
|
||||||
//video
|
|
||||||
H264Frame m_h264frame;
|
|
||||||
//aduio
|
|
||||||
AdtsFrame m_adts;
|
|
||||||
|
|
||||||
int m_iSampleRate = 44100;
|
|
||||||
int m_iSampleBit = 16;
|
|
||||||
int m_iChannel = 1;
|
|
||||||
|
|
||||||
string m_strSPS;
|
|
||||||
string m_strPPS;
|
|
||||||
string m_strAudioCfg;
|
|
||||||
int m_iVideoWidth = 0;
|
|
||||||
int m_iVideoHeight = 0;
|
|
||||||
float m_fVideoFps = 0;
|
|
||||||
bool m_bHaveAudio = false;
|
|
||||||
bool m_bHaveVideo= false;
|
|
||||||
float m_fDuration = 0;
|
|
||||||
|
|
||||||
function<void(const H264Frame &frame)> onVideo;
|
|
||||||
function<void(const AdtsFrame &frame)> onAudio;
|
|
||||||
recursive_mutex m_mtxCB;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTP_RTPPARSER_H_ */
|
|
@ -1,169 +0,0 @@
|
|||||||
#ifndef RTSP_RTSP_H_
|
|
||||||
#define RTSP_RTSP_H_
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TrackVideo = 0, TrackAudio
|
|
||||||
} TrackType;
|
|
||||||
|
|
||||||
class RtspTrack{
|
|
||||||
public:
|
|
||||||
uint8_t PT;
|
|
||||||
uint8_t trackId;
|
|
||||||
uint8_t interleaved;
|
|
||||||
TrackType type = (TrackType) -1;
|
|
||||||
string trackSdp;
|
|
||||||
string trackStyle;
|
|
||||||
bool inited;
|
|
||||||
uint32_t ssrc = 0;
|
|
||||||
uint16_t seq;
|
|
||||||
uint32_t timeStamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RtpPacket {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtpPacket> Ptr;
|
|
||||||
uint8_t interleaved;
|
|
||||||
uint8_t PT;
|
|
||||||
bool mark;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t timeStamp;
|
|
||||||
uint16_t sequence;
|
|
||||||
uint32_t ssrc;
|
|
||||||
uint8_t payload[1560];
|
|
||||||
TrackType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RtcpCounter {
|
|
||||||
public:
|
|
||||||
uint32_t pktCnt = 0;
|
|
||||||
uint32_t octCount = 0;
|
|
||||||
uint32_t timeStamp = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
string FindField(const char* buf, const char* start, const char *end,int bufSize = 0 );
|
|
||||||
int parserSDP(const string& sdp, RtspTrack Track[2]);
|
|
||||||
|
|
||||||
|
|
||||||
struct StrCaseCompare
|
|
||||||
{
|
|
||||||
bool operator()(const string& __x, const string& __y) const
|
|
||||||
{return strcasecmp(__x.data(), __y.data()) < 0 ;}
|
|
||||||
};
|
|
||||||
typedef map<string,string,StrCaseCompare> StrCaseMap;
|
|
||||||
|
|
||||||
class Parser {
|
|
||||||
public:
|
|
||||||
Parser() {
|
|
||||||
}
|
|
||||||
virtual ~Parser() {
|
|
||||||
}
|
|
||||||
void Parse(const char *buf) {
|
|
||||||
//解析
|
|
||||||
const char *start = buf;
|
|
||||||
string line;
|
|
||||||
string field;
|
|
||||||
string value;
|
|
||||||
Clear();
|
|
||||||
while (true) {
|
|
||||||
line = FindField(start, NULL, "\r\n");
|
|
||||||
if (line.size() == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (start == buf) {
|
|
||||||
m_strMethod = FindField(line.c_str(), NULL, " ");
|
|
||||||
m_strUrl = FindField(line.c_str(), " ", " ");
|
|
||||||
m_strTail = FindField(line.c_str(), (m_strUrl + " ").c_str(), NULL);
|
|
||||||
} else {
|
|
||||||
field = FindField(line.c_str(), NULL, ": ");
|
|
||||||
value = FindField(line.c_str(), ": ", NULL);
|
|
||||||
if (field.size() != 0) {
|
|
||||||
m_mapValues[field] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
start = start + line.size() + 2;
|
|
||||||
if (strncmp(start, "\r\n", 2) == 0) { //协议解析完毕
|
|
||||||
m_strContent = FindField(start, "\r\n", NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const string& Method() const {
|
|
||||||
//rtsp方法
|
|
||||||
return m_strMethod;
|
|
||||||
}
|
|
||||||
const string& Url() const {
|
|
||||||
//rtsp url
|
|
||||||
return m_strUrl;
|
|
||||||
}
|
|
||||||
const string& Tail() const {
|
|
||||||
//RTSP/1.0
|
|
||||||
return m_strTail;
|
|
||||||
}
|
|
||||||
const string& operator[](const char *name) const {
|
|
||||||
//rtsp field
|
|
||||||
auto it = m_mapValues.find(name);
|
|
||||||
if (it == m_mapValues.end()) {
|
|
||||||
return m_strNull;
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
const string& Content() const {
|
|
||||||
return m_strContent;
|
|
||||||
}
|
|
||||||
void Clear() {
|
|
||||||
m_strMethod.clear();
|
|
||||||
m_strUrl.clear();
|
|
||||||
m_strTail.clear();
|
|
||||||
m_strContent.clear();
|
|
||||||
m_mapValues.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUrl(const string& url) {
|
|
||||||
this->m_strUrl = url;
|
|
||||||
}
|
|
||||||
void setContent(const string& content) {
|
|
||||||
this->m_strContent = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
const StrCaseMap& getValues() const {
|
|
||||||
return m_mapValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
string m_strMethod;
|
|
||||||
string m_strUrl;
|
|
||||||
string m_strTail;
|
|
||||||
string m_strContent;
|
|
||||||
string m_strNull;
|
|
||||||
StrCaseMap m_mapValues;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned forbidden_zero_bit :1;
|
|
||||||
unsigned nal_ref_idc :2;
|
|
||||||
unsigned type :5;
|
|
||||||
} NALU;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned S :1;
|
|
||||||
unsigned E :1;
|
|
||||||
unsigned R :1;
|
|
||||||
unsigned type :5;
|
|
||||||
} FU;
|
|
||||||
|
|
||||||
bool MakeNalu(char in, NALU &nal) ;
|
|
||||||
bool MakeFU(char in, FU &fu) ;
|
|
||||||
|
|
||||||
|
|
||||||
#endif //RTSP_RTSP_H_
|
|
@ -1,163 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtspMediaSource.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTSP_RTSPMEDIASOURCE_H_
|
|
||||||
#define SRC_RTSP_RTSPMEDIASOURCE_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Rtsp.h"
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Common/MediaSender.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/RingBuffer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Util/ResourcePool.h"
|
|
||||||
#include "Util/NoticeCenter.h"
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RtspMediaSource: public enable_shared_from_this<RtspMediaSource> {
|
|
||||||
public:
|
|
||||||
typedef ResourcePool<RtpPacket, 64> PoolType;
|
|
||||||
typedef std::shared_ptr<RtspMediaSource> Ptr;
|
|
||||||
typedef RingBuffer<RtpPacket::Ptr> RingType;
|
|
||||||
RtspMediaSource(const string &strApp, const string &strId) :
|
|
||||||
m_strApp(strApp),
|
|
||||||
m_strId(strId),
|
|
||||||
m_pRing(new RingBuffer<RtpPacket::Ptr>()),
|
|
||||||
m_thPool(MediaSender::sendThread()) {
|
|
||||||
}
|
|
||||||
virtual ~RtspMediaSource() {
|
|
||||||
unregist();
|
|
||||||
}
|
|
||||||
|
|
||||||
const RingType::Ptr &getRing() const {
|
|
||||||
//获取媒体源的rtp环形缓冲
|
|
||||||
return m_pRing;
|
|
||||||
}
|
|
||||||
|
|
||||||
const string& getSdp() const {
|
|
||||||
//获取该源的媒体描述信息
|
|
||||||
return m_strSdp;
|
|
||||||
}
|
|
||||||
virtual void regist() {
|
|
||||||
//注册该源,注册后rtsp服务器才能找到该源
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
if (!g_mapMediaSrc[m_strApp].erase(m_strId)) {
|
|
||||||
InfoL << "Rtsp src:" << m_strApp << " " << m_strId;
|
|
||||||
}
|
|
||||||
g_mapMediaSrc[m_strApp].emplace(m_strId, shared_from_this());
|
|
||||||
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRtspSrcRegisted,m_strApp.data(),m_strId.data());
|
|
||||||
}
|
|
||||||
virtual void unregist() {
|
|
||||||
//反注册该源
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
auto it = g_mapMediaSrc.find(m_strApp);
|
|
||||||
if (it == g_mapMediaSrc.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (it->second.erase(m_strId)) {
|
|
||||||
if(it->second.size() == 0){
|
|
||||||
g_mapMediaSrc.erase(it);
|
|
||||||
}
|
|
||||||
InfoL << "Rtsp src:" << m_strApp << " " << m_strId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static set<string> getMediaSet() {
|
|
||||||
set<string> ret;
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
for (auto &pr0 : g_mapMediaSrc) {
|
|
||||||
for (auto &pr1 : pr0.second) {
|
|
||||||
if(pr1.second.lock()){
|
|
||||||
ret.emplace(pr0.first + "/" + pr1.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static Ptr find(const string &_app, const string &_id,bool bMake = true) ;
|
|
||||||
|
|
||||||
const string& getApp() const {
|
|
||||||
//获取该源的id
|
|
||||||
return m_strApp;
|
|
||||||
}
|
|
||||||
const string& getId() const {
|
|
||||||
return m_strId;
|
|
||||||
}
|
|
||||||
virtual uint32_t getSsrc(int trackId) {
|
|
||||||
return m_mapTracks[trackId].ssrc;
|
|
||||||
}
|
|
||||||
virtual uint16_t getSeqence(int trackId) {
|
|
||||||
return m_mapTracks[trackId].seq;
|
|
||||||
}
|
|
||||||
virtual uint32_t getTimestamp(int trackId) {
|
|
||||||
return m_mapTracks[trackId].timeStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onGetSDP(const string& sdp) {
|
|
||||||
//派生类设置该媒体源媒体描述信息
|
|
||||||
this->m_strSdp = sdp;
|
|
||||||
}
|
|
||||||
virtual void onGetRTP(const RtpPacket::Ptr &rtppt, bool keyPos) {
|
|
||||||
auto &trackRef = m_mapTracks[rtppt->interleaved / 2];
|
|
||||||
trackRef.seq = rtppt->sequence;
|
|
||||||
trackRef.timeStamp = rtppt->timeStamp;
|
|
||||||
trackRef.ssrc = rtppt->ssrc;
|
|
||||||
trackRef.type = rtppt->type;
|
|
||||||
auto _outRing = m_pRing;
|
|
||||||
m_thPool.async([_outRing,rtppt,keyPos]() {
|
|
||||||
_outRing->write(rtppt,keyPos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
bool seekTo(uint32_t ui32Stamp) {
|
|
||||||
if (!m_onSeek) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return m_onSeek(ui32Stamp);
|
|
||||||
}
|
|
||||||
virtual void setOnSeek(const function<bool(uint32_t)> &cb){
|
|
||||||
m_onSeek = cb;
|
|
||||||
}
|
|
||||||
uint32_t getStamp() {
|
|
||||||
if (!m_onStamp) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_onStamp();
|
|
||||||
}
|
|
||||||
virtual void setOnStamp(const function<uint32_t()> &cb) {
|
|
||||||
m_onStamp = cb;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
function<bool(uint32_t)> m_onSeek;
|
|
||||||
function<uint32_t()> m_onStamp;
|
|
||||||
unordered_map<int, RtspTrack> m_mapTracks;
|
|
||||||
private:
|
|
||||||
string m_strSdp; //媒体描述信息
|
|
||||||
string m_strApp; //媒体app
|
|
||||||
string m_strId; //媒体id
|
|
||||||
RingType::Ptr m_pRing; //rtp环形缓冲
|
|
||||||
ThreadPool &m_thPool;
|
|
||||||
static unordered_map<string, unordered_map<string, weak_ptr<RtspMediaSource> > > g_mapMediaSrc; //静态的媒体源表
|
|
||||||
static recursive_mutex g_mtxMediaSrc; ///访问静态的媒体源表的互斥锁
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTSP_RTSPMEDIASOURCE_H_ */
|
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtspPlayer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月17日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
|
|
||||||
#define SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include "Rtsp.h"
|
|
||||||
#include "RtspSession.h"
|
|
||||||
#include "RtspMediaSource.h"
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Poller/Timer.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
#include "Network/TcpClient.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Poller;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
//实现了rtsp播放器协议部分的功能
|
|
||||||
class RtspPlayer: public PlayerBase,public TcpClient {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtspPlayer> Ptr;
|
|
||||||
//设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播)
|
|
||||||
//设置方法:player[RtspPlayer::kRtpType] = 0/1/2;
|
|
||||||
static const char kRtpType[];
|
|
||||||
|
|
||||||
RtspPlayer();
|
|
||||||
virtual ~RtspPlayer(void);
|
|
||||||
void play(const char* strUrl) override;
|
|
||||||
void pause(bool bPause) override;
|
|
||||||
void teardown() override;
|
|
||||||
float getRtpLossRate(int iTrackId) const override;
|
|
||||||
protected:
|
|
||||||
//派生类回调函数
|
|
||||||
virtual bool onCheckSDP(const string &strSdp, const RtspTrack *pTrack, int iTrackCnt) = 0;
|
|
||||||
virtual void onRecvRTP(const RtpPacket::Ptr &pRtppt, const RtspTrack &track) = 0;
|
|
||||||
float getProgressTime() const;
|
|
||||||
void seekToTime(float fTime);
|
|
||||||
private:
|
|
||||||
void _onShutdown(const SockException &ex) {
|
|
||||||
WarnL << ex.getErrCode() << " " << ex.what();
|
|
||||||
m_pPlayTimer.reset();
|
|
||||||
m_pRtpTimer.reset();
|
|
||||||
m_pBeatTimer.reset();
|
|
||||||
onShutdown(ex);
|
|
||||||
}
|
|
||||||
void _onRecvRTP(const RtpPacket::Ptr &pRtppt, const RtspTrack &track) {
|
|
||||||
m_rtpTicker.resetTime();
|
|
||||||
onRecvRTP(pRtppt,track);
|
|
||||||
}
|
|
||||||
void _onPlayResult(const SockException &ex) {
|
|
||||||
WarnL << ex.getErrCode() << " " << ex.what();
|
|
||||||
m_pPlayTimer.reset();
|
|
||||||
m_pRtpTimer.reset();
|
|
||||||
if (!ex) {
|
|
||||||
m_rtpTicker.resetTime();
|
|
||||||
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
|
||||||
m_pRtpTimer.reset( new Timer(5, [weakSelf]() {
|
|
||||||
auto strongSelf=weakSelf.lock();
|
|
||||||
if(!strongSelf) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(strongSelf->m_rtpTicker.elapsedTime()>10000) {
|
|
||||||
//recv rtp timeout!
|
|
||||||
strongSelf->_onShutdown(SockException(Err_timeout,"recv rtp timeout"));
|
|
||||||
strongSelf->teardown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
onPlayResult(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void play(const char* strUrl, const char *strUser, const char *strPwd, eRtpType eType);
|
|
||||||
void onConnect(const SockException &err) override;
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
void onErr(const SockException &ex) override;
|
|
||||||
|
|
||||||
void HandleResSETUP(const Parser &parser, unsigned int uiTrackIndex);
|
|
||||||
void HandleResDESCRIBE(const Parser &parser);
|
|
||||||
void HandleResPAUSE(const Parser &parser, bool bPause);
|
|
||||||
|
|
||||||
//发数据给服务器
|
|
||||||
inline int write(const char *strMsg, ...);
|
|
||||||
inline int onProcess(const char* strBuf);
|
|
||||||
//生成rtp包结构体
|
|
||||||
inline void splitRtp(unsigned char *pucData, unsigned int uiLen);
|
|
||||||
//发送SETUP命令
|
|
||||||
inline void sendSetup(unsigned int uiTrackIndex);
|
|
||||||
inline void sendPause(bool bPause,float fTime);
|
|
||||||
//处理一个rtp包
|
|
||||||
inline bool HandleOneRtp(int iTrackidx, unsigned char *ucData, unsigned int uiLen);
|
|
||||||
bool sendOptions();
|
|
||||||
inline void _onRecvRTP(const RtpPacket::Ptr &pRtppt, int iTrackidx);
|
|
||||||
inline int getTrackIndex(int iTrackId) const{
|
|
||||||
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
|
|
||||||
if (m_aTrackInfo[i].trackId == iTrackId) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string m_strUrl;
|
|
||||||
unsigned int m_uiTrackCnt = 0;
|
|
||||||
RtspTrack m_aTrackInfo[2];
|
|
||||||
|
|
||||||
function<void(const Parser&)> m_onHandshake;
|
|
||||||
RtspMediaSource::PoolType m_pktPool;
|
|
||||||
|
|
||||||
uint8_t *m_pucRtpBuf = nullptr;
|
|
||||||
unsigned int m_uiRtpBufLen = 0;
|
|
||||||
Socket::Ptr m_apUdpSock[2];
|
|
||||||
//rtsp info
|
|
||||||
string m_strSession;
|
|
||||||
unsigned int m_uiCseq = 1;
|
|
||||||
uint32_t m_aui32SsrcErrorCnt[2] = { 0, 0 };
|
|
||||||
string m_strAuthorization;
|
|
||||||
string m_strContentBase;
|
|
||||||
eRtpType m_eType = RTP_TCP;
|
|
||||||
/* RTP包排序所用参数 */
|
|
||||||
uint16_t m_aui16LastSeq[2] = { 0 , 0 };
|
|
||||||
uint64_t m_aui64SeqOkCnt[2] = { 0 , 0};
|
|
||||||
bool m_abSortStarted[2] = { 0 , 0};
|
|
||||||
map<uint32_t , RtpPacket::Ptr> m_amapRtpSort[2];
|
|
||||||
|
|
||||||
/* 丢包率统计需要用到的参数 */
|
|
||||||
uint16_t m_aui16FirstSeq[2] = { 0 , 0};
|
|
||||||
uint16_t m_aui16NowSeq[2] = { 0 , 0 };
|
|
||||||
uint64_t m_aui64RtpRecv[2] = { 0 , 0};
|
|
||||||
|
|
||||||
//超时功能实现
|
|
||||||
Ticker m_rtpTicker;
|
|
||||||
std::shared_ptr<Timer> m_pPlayTimer;
|
|
||||||
std::shared_ptr<Timer> m_pRtpTimer;
|
|
||||||
//心跳定时器
|
|
||||||
std::shared_ptr<Timer> m_pBeatTimer;
|
|
||||||
|
|
||||||
//播放进度控制
|
|
||||||
float m_fSeekTo = 0;
|
|
||||||
double m_adFistStamp[2] = {0,0};
|
|
||||||
double m_adNowStamp[2] = {0,0};
|
|
||||||
Ticker m_aNowStampTicker[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_ */
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtspParserTester.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月5日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTP_RTPPARSERTESTER_H_
|
|
||||||
#define SRC_RTP_RTPPARSERTESTER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "RtpParser.h"
|
|
||||||
#include "RtspPlayer.h"
|
|
||||||
#include "Poller/Timer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtspPlayerImp: public PlayerImp<RtspPlayer,RtpParser> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtspPlayerImp> Ptr;
|
|
||||||
RtspPlayerImp();
|
|
||||||
virtual ~RtspPlayerImp();
|
|
||||||
float getProgresss() const override{
|
|
||||||
if(getDuration() > 0){
|
|
||||||
return getProgressTime() / getDuration();
|
|
||||||
}
|
|
||||||
return PlayerBase::getProgresss();
|
|
||||||
|
|
||||||
};
|
|
||||||
void seekTo(float fProgress) override{
|
|
||||||
fProgress = MAX(float(0),MIN(fProgress,float(1.0)));
|
|
||||||
seekToTime(fProgress * getDuration());
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
//派生类回调函数
|
|
||||||
bool onCheckSDP(const string &sdp, const RtspTrack *track, int trackCnt) override {
|
|
||||||
try {
|
|
||||||
m_parser.reset(new RtpParser(sdp));
|
|
||||||
m_parser->setOnVideoCB(m_onGetVideoCB);
|
|
||||||
m_parser->setOnAudioCB(m_onGetAudioCB);
|
|
||||||
return true;
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
WarnL << ex.what();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void onRecvRTP(const RtpPacket::Ptr &rtppt, const RtspTrack &track) override {
|
|
||||||
m_parser->inputRtp(*rtppt);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTP_RTPPARSERTESTER_H_ */
|
|
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtspSession.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月12日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SESSION_RTSPSESSION_H_
|
|
||||||
#define SESSION_RTSPSESSION_H_
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Rtsp.h"
|
|
||||||
#include "RtpBroadCaster.h"
|
|
||||||
#include "RtspMediaSource.h"
|
|
||||||
#include "Player/PlayerBase.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Network/TcpLimitedSession.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class RtspSession;
|
|
||||||
class RtspSession: public TcpLimitedSession<MAX_TCP_SESSION> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtspSession> Ptr;
|
|
||||||
RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock);
|
|
||||||
virtual ~RtspSession();
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &pBuf) override;
|
|
||||||
void onError(const SockException &err) override;
|
|
||||||
void onManager() override;
|
|
||||||
private:
|
|
||||||
typedef bool (RtspSession::*rtspCMDHandle)();
|
|
||||||
int send(const string &strBuf) override {
|
|
||||||
return m_pSender->send(strBuf);
|
|
||||||
}
|
|
||||||
int send(const char *pcBuf, int iSize) override {
|
|
||||||
return m_pSender->send(pcBuf, iSize);
|
|
||||||
}
|
|
||||||
void shutdown() override;
|
|
||||||
bool handleReq_Options(); //处理options方法
|
|
||||||
bool handleReq_Describe(); //处理describe方法
|
|
||||||
bool handleReq_Setup(); //处理setup方法
|
|
||||||
bool handleReq_Play(); //处理play方法
|
|
||||||
bool handleReq_Pause(); //处理pause方法
|
|
||||||
bool handleReq_Teardown(); //处理teardown方法
|
|
||||||
bool handleReq_Get(); //处理Get方法
|
|
||||||
bool handleReq_Post(); //处理Post方法
|
|
||||||
bool handleReq_SET_PARAMETER(); //处理SET_PARAMETER方法
|
|
||||||
|
|
||||||
void inline send_StreamNotFound(); //rtsp资源未找到
|
|
||||||
void inline send_UnsupportedTransport(); //不支持的传输模式
|
|
||||||
void inline send_SessionNotFound(); //会话id错误
|
|
||||||
void inline send_NotAcceptable(); //rtsp同时播放数限制
|
|
||||||
inline bool findStream(); //根据rtsp url查找 MediaSource实例
|
|
||||||
|
|
||||||
inline void initSender(const std::shared_ptr<RtspSession> &pSession); //处理rtsp over http,quicktime使用的
|
|
||||||
inline void sendRtpPacket(const RtpPacket &pkt);
|
|
||||||
inline string printSSRC(uint32_t ui32Ssrc) {
|
|
||||||
char tmp[9] = { 0 };
|
|
||||||
ui32Ssrc = htonl(ui32Ssrc);
|
|
||||||
uint8_t *pSsrc = (uint8_t *) &ui32Ssrc;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
sprintf(tmp + 2 * i, "%02X", pSsrc[i]);
|
|
||||||
}
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
inline int getTrackIndexByTrackId(int iTrackId) {
|
|
||||||
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
|
|
||||||
if (iTrackId == m_aTrackInfo[i].trackId) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
inline void onRcvPeerUdpData(int iTrackIdx, const Socket::Buffer::Ptr &pBuf, const struct sockaddr &addr);
|
|
||||||
inline void tryGetPeerUdpPort();
|
|
||||||
|
|
||||||
char *m_pcBuf = nullptr;
|
|
||||||
Ticker m_ticker;
|
|
||||||
Parser m_parser; //rtsp解析类
|
|
||||||
string m_strUrl;
|
|
||||||
string m_strSdp;
|
|
||||||
string m_strSession;
|
|
||||||
bool m_bFirstPlay = true;
|
|
||||||
string m_strApp;
|
|
||||||
string m_strStream;
|
|
||||||
std::weak_ptr<RtspMediaSource> m_pMediaSrc;
|
|
||||||
static unordered_map<string, rtspCMDHandle> g_mapCmd;
|
|
||||||
|
|
||||||
//RTP缓冲
|
|
||||||
weak_ptr<RingBuffer<RtpPacket::Ptr> > m_pWeakRing;
|
|
||||||
RingBuffer<RtpPacket::Ptr>::RingReader::Ptr m_pRtpReader;
|
|
||||||
|
|
||||||
PlayerBase::eRtpType m_rtpType = PlayerBase::RTP_UDP;
|
|
||||||
bool m_bSetUped = false;
|
|
||||||
int m_iCseq = 0;
|
|
||||||
unsigned int m_uiTrackCnt = 0; //媒体track个数
|
|
||||||
RtspTrack m_aTrackInfo[2]; //媒体track信息,trackid idx 为数组下标
|
|
||||||
|
|
||||||
#ifdef RTSP_SEND_RTCP
|
|
||||||
RtcpCounter m_aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
|
|
||||||
Ticker m_aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标
|
|
||||||
inline void sendRTCP();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//RTP over UDP
|
|
||||||
bool m_abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数
|
|
||||||
weak_ptr<Socket> m_apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标
|
|
||||||
std::shared_ptr<struct sockaddr> m_apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标
|
|
||||||
bool m_bListenPeerUdpPort = false;
|
|
||||||
RtpBroadCaster::Ptr m_pBrdcaster;
|
|
||||||
|
|
||||||
//RTSP over HTTP
|
|
||||||
function<void(void)> m_onDestory;
|
|
||||||
bool m_bBase64need = false; //是否需要base64解码
|
|
||||||
Socket::Ptr m_pSender; //回复rtsp时走的tcp通道,供quicktime用
|
|
||||||
//quicktime 请求rtsp会产生两次tcp连接,
|
|
||||||
//一次发送 get 一次发送post,需要通过sessioncookie关联起来
|
|
||||||
string m_strSessionCookie;
|
|
||||||
static recursive_mutex g_mtxGetter; //对quicktime上锁保护
|
|
||||||
static recursive_mutex g_mtxPostter; //对quicktime上锁保护
|
|
||||||
static unordered_map<string, weak_ptr<RtspSession> > g_mapGetter;
|
|
||||||
static unordered_map<void *, std::shared_ptr<RtspSession> > g_mapPostter;
|
|
||||||
static string g_serverName;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Session */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SESSION_RTSPSESSION_H_ */
|
|
@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* RtspToRtmpMediaSource.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月7日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_RTSP_RTSPTORTMPMEDIASOURCE_H_
|
|
||||||
#define SRC_RTSP_RTSPTORTMPMEDIASOURCE_H_
|
|
||||||
|
|
||||||
#include "RtpParser.h"
|
|
||||||
#include "RtspMediaSource.h"
|
|
||||||
#include "Rtmp/amf.h"
|
|
||||||
#include "Rtmp/RtmpMediaSource.h"
|
|
||||||
#include "MediaFile/MediaRecorder.h"
|
|
||||||
|
|
||||||
using namespace ZL::Rtmp;
|
|
||||||
using namespace ZL::MediaFile;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
#ifdef ENABLE_RTSP2RTMP
|
|
||||||
class RtspToRtmpMediaSource: public RtspMediaSource {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RtspToRtmpMediaSource> Ptr;
|
|
||||||
RtspToRtmpMediaSource(const string &_app,const string &_id,bool bEnableFile = true);
|
|
||||||
virtual ~RtspToRtmpMediaSource();
|
|
||||||
|
|
||||||
virtual void onGetSDP(const string& strSdp) override{
|
|
||||||
try {
|
|
||||||
m_pParser.reset(new RtpParser(strSdp));
|
|
||||||
if(m_bEnableFile){
|
|
||||||
m_pRecorder.reset(new MediaRecorder(getApp(),getId(),m_pParser));
|
|
||||||
}
|
|
||||||
m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAdts, this, placeholders::_1));
|
|
||||||
m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
|
|
||||||
makeMetaData();
|
|
||||||
} catch (exception &ex) {
|
|
||||||
WarnL << ex.what();
|
|
||||||
}
|
|
||||||
RtspMediaSource::onGetSDP(strSdp);
|
|
||||||
}
|
|
||||||
virtual void onGetRTP(const RtpPacket::Ptr &pRtppkt, bool bKeyPos) override{
|
|
||||||
if (m_pParser) {
|
|
||||||
bKeyPos = m_pParser->inputRtp(*pRtppkt);
|
|
||||||
}
|
|
||||||
RtspMediaSource::onGetRTP(pRtppkt, bKeyPos);
|
|
||||||
}
|
|
||||||
virtual void regist() override ;
|
|
||||||
virtual void unregist() override;
|
|
||||||
int readerCount(){
|
|
||||||
return getRing()->readerCount() + (m_pRtmpSrc ? m_pRtmpSrc->getRing()->readerCount() : 0);
|
|
||||||
}
|
|
||||||
void setOnSeek(const function<bool(uint32_t)> &cb) override{
|
|
||||||
RtspMediaSource::setOnSeek(cb);
|
|
||||||
if(m_pRtmpSrc){
|
|
||||||
m_pRtmpSrc->setOnSeek(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setOnStamp(const function<uint32_t()> &cb) override{
|
|
||||||
RtspMediaSource::setOnStamp(cb);
|
|
||||||
if (m_pRtmpSrc) {
|
|
||||||
m_pRtmpSrc->setOnStamp(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void updateTimeStamp(uint32_t uiStamp) {
|
|
||||||
for (auto &pr : m_mapTracks) {
|
|
||||||
switch (pr.second.type) {
|
|
||||||
case TrackAudio: {
|
|
||||||
pr.second.timeStamp = uiStamp * (m_pParser->getAudioSampleRate() / 1000.0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TrackVideo: {
|
|
||||||
pr.second.timeStamp = uiStamp * 90;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
RtpParser::Ptr m_pParser;
|
|
||||||
RtmpMediaSource::Ptr m_pRtmpSrc;
|
|
||||||
RtmpPacket m_rtmpPkt;
|
|
||||||
uint8_t m_ui8AudioFlags = 0;
|
|
||||||
MediaRecorder::Ptr m_pRecorder;
|
|
||||||
bool m_bEnableFile = true;
|
|
||||||
void onGetH264(const H264Frame &frame);
|
|
||||||
void onGetAdts(const AdtsFrame &frame);
|
|
||||||
void makeVideoConfigPkt();
|
|
||||||
void makeAudioConfigPkt();
|
|
||||||
void makeMetaData();
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
typedef RtspMediaSource RtspToRtmpMediaSource;
|
|
||||||
#endif //ENABLE_RTSP2RTMP
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_RTSP_RTSPTORTMPMEDIASOURCE_H_ */
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* UDPServer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月12日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RTSP_UDPSERVER_H_
|
|
||||||
#define RTSP_UDPSERVER_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Rtsp {
|
|
||||||
|
|
||||||
class UDPServer {
|
|
||||||
public:
|
|
||||||
typedef function< bool(int, const Socket::Buffer::Ptr &, struct sockaddr *)> onRecvData;
|
|
||||||
UDPServer();
|
|
||||||
virtual ~UDPServer();
|
|
||||||
static UDPServer &Instance() {
|
|
||||||
static UDPServer *instance(new UDPServer());
|
|
||||||
return *instance;
|
|
||||||
}
|
|
||||||
static void Destory() {
|
|
||||||
delete &UDPServer::Instance();
|
|
||||||
}
|
|
||||||
Socket::Ptr getSock(const char *strLocalIp, int iTrackIndex);
|
|
||||||
void listenPeer(const char *strPeerIp, void *pSelf, const onRecvData &cb);
|
|
||||||
void stopListenPeer(const char *strPeerIp, void *pSelf);
|
|
||||||
private:
|
|
||||||
void onRcvData(int iTrackId, const Socket::Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr);
|
|
||||||
void onErr(const string &strKey,const SockException &err);
|
|
||||||
unordered_map<string, Socket::Ptr> m_mapUpdSock;
|
|
||||||
mutex m_mtxUpdSock;
|
|
||||||
|
|
||||||
unordered_map<string, unordered_map<void *, onRecvData> > m_mapDataHandler;
|
|
||||||
mutex m_mtxDataHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Rtsp */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* RTSP_UDPSERVER_H_ */
|
|
@ -1,253 +0,0 @@
|
|||||||
/*
|
|
||||||
* CMD.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月26日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_SHELL_CMD_H_
|
|
||||||
#define SRC_SHELL_CMD_H_
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include "win32/getopt.h"
|
|
||||||
#else
|
|
||||||
#include <getopt.h>
|
|
||||||
#endif //defined(_WIN32)
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Shell {
|
|
||||||
|
|
||||||
class OutStream {
|
|
||||||
public:
|
|
||||||
virtual ~OutStream() {
|
|
||||||
}
|
|
||||||
virtual void response(const string &str) =0;
|
|
||||||
virtual string &operator[](const string &) =0;
|
|
||||||
virtual int erase(const string &) =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Option {
|
|
||||||
public:
|
|
||||||
typedef function<bool(OutStream *stream, const char *arg)> OptionHandler;
|
|
||||||
enum ArgType {
|
|
||||||
ArgNone = no_argument,
|
|
||||||
ArgRequired = required_argument,
|
|
||||||
ArgOptional = optional_argument
|
|
||||||
};
|
|
||||||
Option() {
|
|
||||||
}
|
|
||||||
Option(char _shortOpt, const char *_longOpt, enum ArgType _argType,
|
|
||||||
const char *_des, const OptionHandler &_cb) {
|
|
||||||
shortOpt = _shortOpt;
|
|
||||||
longOpt = _longOpt;
|
|
||||||
argType = _argType;
|
|
||||||
des = _des;
|
|
||||||
cb = _cb;
|
|
||||||
}
|
|
||||||
virtual ~Option() {
|
|
||||||
}
|
|
||||||
bool operator()(OutStream *stream, const char *arg){
|
|
||||||
return cb ? cb(stream,arg): true;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
friend class OptionParser;
|
|
||||||
char shortOpt;
|
|
||||||
string longOpt;
|
|
||||||
enum ArgType argType;
|
|
||||||
string des;
|
|
||||||
OptionHandler cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OptionParser {
|
|
||||||
public:
|
|
||||||
typedef function< void(OutStream *stream, const unordered_multimap<char, string> &)> OptionCompleted;
|
|
||||||
OptionParser(const OptionCompleted &_cb) {
|
|
||||||
onCompleted = _cb;
|
|
||||||
helper = Option('h', "help", Option::ArgNone, "print this message", [this](OutStream *stream,const char *arg)->bool {
|
|
||||||
_StrPrinter printer;
|
|
||||||
for (auto &pr : options) {
|
|
||||||
printer<<"\t-"<<pr.first<<"\t--"<<pr.second.longOpt<<"\t"<<pr.second.des<<"\r\n";
|
|
||||||
}
|
|
||||||
auto sendStr=printer<<endl;
|
|
||||||
stream->response(sendStr);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
virtual ~OptionParser() {
|
|
||||||
}
|
|
||||||
OptionParser &operator <<(const Option &option) {
|
|
||||||
options.emplace(option.shortOpt, option);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
void operator <<(ostream&(*f)(ostream&)) {
|
|
||||||
str_shortOpt.clear();
|
|
||||||
vec_longOpt.clear();
|
|
||||||
(*this) << helper;
|
|
||||||
struct option tmp;
|
|
||||||
for (auto &pr : options) {
|
|
||||||
//long opt
|
|
||||||
tmp.name = (char *)pr.second.longOpt.data();
|
|
||||||
tmp.has_arg = pr.second.argType;
|
|
||||||
tmp.flag = NULL;
|
|
||||||
tmp.val = pr.first;
|
|
||||||
vec_longOpt.emplace_back(tmp);
|
|
||||||
//short opt
|
|
||||||
str_shortOpt.push_back(pr.first);
|
|
||||||
switch (pr.second.argType) {
|
|
||||||
case Option::ArgRequired:
|
|
||||||
str_shortOpt.append(":");
|
|
||||||
break;
|
|
||||||
case Option::ArgOptional:
|
|
||||||
str_shortOpt.append("::");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp.flag=0;
|
|
||||||
tmp.name=0;
|
|
||||||
tmp.has_arg=0;
|
|
||||||
tmp.val=0;
|
|
||||||
vec_longOpt.emplace_back(tmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
bool operator ()(OutStream *stream, int argc, char *argv[]) {
|
|
||||||
lock_guard<mutex> lck(mtx_opt);
|
|
||||||
unordered_multimap<char, string> allArg;
|
|
||||||
int opt;
|
|
||||||
optind = 0;
|
|
||||||
while ((opt = getopt_long(argc, argv, &str_shortOpt[0], &vec_longOpt[0],NULL)) != -1) {
|
|
||||||
auto it = options.find(opt);
|
|
||||||
if (it == options.end()) {
|
|
||||||
string sendStr = StrPrinter << "\tUnrecognized option. Enter \"-h\" to get help.\r\n" << endl;
|
|
||||||
stream->response(sendStr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
allArg.emplace(it->first, optarg ? optarg : "");
|
|
||||||
if (!it->second(stream, optarg)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
optarg = NULL;
|
|
||||||
}
|
|
||||||
if(!allArg.size() && options.size()){
|
|
||||||
helper(stream,"");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (onCompleted) {
|
|
||||||
onCompleted(stream, allArg);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
unordered_map<char, Option> options;
|
|
||||||
OptionCompleted onCompleted;
|
|
||||||
vector<struct option> vec_longOpt;
|
|
||||||
string str_shortOpt;
|
|
||||||
Option helper;
|
|
||||||
static mutex mtx_opt;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CMD {
|
|
||||||
public:
|
|
||||||
CMD();
|
|
||||||
virtual ~CMD();
|
|
||||||
virtual const char *description() const {
|
|
||||||
return "description";
|
|
||||||
}
|
|
||||||
bool operator ()(OutStream *stream, int argc, char *argv[]) const {
|
|
||||||
return (*parser)(stream, argc, argv);
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
mutable std::shared_ptr<OptionParser> parser;
|
|
||||||
};
|
|
||||||
template<typename C>
|
|
||||||
class CMDInstance {
|
|
||||||
public:
|
|
||||||
static CMD &Instance() {
|
|
||||||
static C instance;
|
|
||||||
return (CMD &) instance;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class CMD_help: public CMD {
|
|
||||||
public:
|
|
||||||
CMD_help();
|
|
||||||
virtual ~CMD_help() {
|
|
||||||
}
|
|
||||||
const char *description() const override {
|
|
||||||
return "打印帮助信息.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CMD_rtsp: public CMD {
|
|
||||||
public:
|
|
||||||
CMD_rtsp();
|
|
||||||
virtual ~CMD_rtsp() {
|
|
||||||
}
|
|
||||||
const char *description() const override {
|
|
||||||
return "查看rtsp服务器相关信息.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class CMD_rtmp: public CMD {
|
|
||||||
public:
|
|
||||||
CMD_rtmp();
|
|
||||||
virtual ~CMD_rtmp() {
|
|
||||||
}
|
|
||||||
const char *description() const override {
|
|
||||||
return "查看rtmp服务器相关信息.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Shell */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_SHELL_CMD_H_ */
|
|
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* ShellSession.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月26日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_SHELL_SHELLSESSION_H_
|
|
||||||
#define SRC_SHELL_SHELLSESSION_H_
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include "CMD.h"
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Network/TcpLimitedSession.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Network;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Shell {
|
|
||||||
|
|
||||||
class ShellSession: public TcpLimitedSession<MAX_TCP_SESSION>, public OutStream {
|
|
||||||
public:
|
|
||||||
ShellSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock);
|
|
||||||
virtual ~ShellSession();
|
|
||||||
void onRecv(const Socket::Buffer::Ptr &) override;
|
|
||||||
void onError(const SockException &err) override;
|
|
||||||
void onManager() override;
|
|
||||||
static void addUser(const string &userName,const string &userPwd){
|
|
||||||
g_mapUser[userName] = userPwd;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
friend class CMD_help;
|
|
||||||
inline bool onProcessLine(const string &);
|
|
||||||
inline void requestLogin();
|
|
||||||
inline void requestPasswd();
|
|
||||||
inline void sendHead();
|
|
||||||
inline bool authUser(const string &user, const string &pwd);
|
|
||||||
void response(const string &str) override{
|
|
||||||
send(str);
|
|
||||||
}
|
|
||||||
string &operator[](const string &key) override{
|
|
||||||
return m_mapConfig[key];
|
|
||||||
}
|
|
||||||
int erase(const string &key) override{
|
|
||||||
return m_mapConfig.erase(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function<bool(const string &)> m_requestCB;
|
|
||||||
string m_strRecvBuf;
|
|
||||||
Ticker m_beatTicker;
|
|
||||||
string m_strUserName;
|
|
||||||
unordered_map<string,string> m_mapConfig;
|
|
||||||
static unordered_map<string, string> g_mapUser;
|
|
||||||
static map<string, CMD&> g_mapCmd;
|
|
||||||
static string g_serverName;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Shell */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_SHELL_SHELLSESSION_H_ */
|
|
@ -1,128 +0,0 @@
|
|||||||
/* Declarations for getopt.
|
|
||||||
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2, or (at your option) any
|
|
||||||
later version.
|
|
||||||
|
|
||||||
This program 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
||||||
|
|
||||||
#ifndef _GETOPT_H
|
|
||||||
#define _GETOPT_H 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* For communication from `getopt' to the caller.
|
|
||||||
When `getopt' finds an option that takes an argument,
|
|
||||||
the argument value is returned here.
|
|
||||||
Also, when `ordering' is RETURN_IN_ORDER,
|
|
||||||
each non-option ARGV-element is returned here. */
|
|
||||||
|
|
||||||
extern char *optarg;
|
|
||||||
|
|
||||||
/* Index in ARGV of the next element to be scanned.
|
|
||||||
This is used for communication to and from the caller
|
|
||||||
and for communication between successive calls to `getopt'.
|
|
||||||
|
|
||||||
On entry to `getopt', zero means this is the first call; initialize.
|
|
||||||
|
|
||||||
When `getopt' returns EOF, this is the index of the first of the
|
|
||||||
non-option elements that the caller should itself scan.
|
|
||||||
|
|
||||||
Otherwise, `optind' communicates from one call to the next
|
|
||||||
how much of ARGV has been scanned so far. */
|
|
||||||
|
|
||||||
extern int optind;
|
|
||||||
|
|
||||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
|
||||||
for unrecognized options. */
|
|
||||||
|
|
||||||
extern int opterr;
|
|
||||||
|
|
||||||
/* Set to an option character which was unrecognized. */
|
|
||||||
|
|
||||||
extern int optopt;
|
|
||||||
|
|
||||||
/* Describe the long-named options requested by the application.
|
|
||||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
|
||||||
of `struct option' terminated by an element containing a name which is
|
|
||||||
zero.
|
|
||||||
|
|
||||||
The field `has_arg' is:
|
|
||||||
no_argument (or 0) if the option does not take an argument,
|
|
||||||
required_argument (or 1) if the option requires an argument,
|
|
||||||
optional_argument (or 2) if the option takes an optional argument.
|
|
||||||
|
|
||||||
If the field `flag' is not NULL, it points to a variable that is set
|
|
||||||
to the value given in the field `val' when the option is found, but
|
|
||||||
left unchanged if the option is not found.
|
|
||||||
|
|
||||||
To have a long-named option do something other than set an `int' to
|
|
||||||
a compiled-in constant, such as set a value from `optarg', set the
|
|
||||||
option's `flag' field to zero and its `val' field to a nonzero
|
|
||||||
value (the equivalent single-letter option character, if there is
|
|
||||||
one). For long options that have a zero `flag' field, `getopt'
|
|
||||||
returns the contents of the `val' field. */
|
|
||||||
|
|
||||||
struct option
|
|
||||||
{
|
|
||||||
#if __STDC__
|
|
||||||
const char *name;
|
|
||||||
#else
|
|
||||||
char *name;
|
|
||||||
#endif
|
|
||||||
/* has_arg can't be an enum because some compilers complain about
|
|
||||||
type mismatches in all the code that assumes it is an int. */
|
|
||||||
int has_arg;
|
|
||||||
int *flag;
|
|
||||||
int val;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
|
||||||
|
|
||||||
#define no_argument 0
|
|
||||||
#define required_argument 1
|
|
||||||
#define optional_argument 2
|
|
||||||
|
|
||||||
//#if __STDC__ || defined(PROTO)
|
|
||||||
//#if defined(__GNU_LIBRARY__)
|
|
||||||
/* Many other libraries have conflicting prototypes for getopt, with
|
|
||||||
differences in the consts, in stdlib.h. To avoid compilation
|
|
||||||
errors, only prototype getopt for the GNU C library. */
|
|
||||||
extern int getopt (int argc, char *const *argv, const char *shortopts);
|
|
||||||
//#endif /* not __GNU_LIBRARY__ */
|
|
||||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
|
||||||
const struct option *longopts, int *longind);
|
|
||||||
extern int getopt_long_only (int argc, char *const *argv,
|
|
||||||
const char *shortopts,
|
|
||||||
const struct option *longopts, int *longind);
|
|
||||||
|
|
||||||
/* Internal only. Users should not call this directly. */
|
|
||||||
/* extern int _getopt_internal (int argc, char *const *argv,
|
|
||||||
const char *shortopts,
|
|
||||||
const struct option *longopts, int *longind,
|
|
||||||
int long_only); */
|
|
||||||
//#else /* not __STDC__ */
|
|
||||||
//extern int getopt ();
|
|
||||||
//extern int getopt_long ();
|
|
||||||
//extern int getopt_long_only ();
|
|
||||||
|
|
||||||
//extern int _getopt_internal ();
|
|
||||||
//#endif /* not __STDC__ */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _GETOPT_H */
|
|
||||||
|
|
@ -1,329 +0,0 @@
|
|||||||
/* tailor.h -- target dependent definitions
|
|
||||||
* Copyright (C) 1992-1993 Jean-loup Gailly.
|
|
||||||
* This is free software; you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU General Public License, see the file COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The target dependent definitions should be defined here only.
|
|
||||||
* The target dependent functions should be defined in tailor.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* $Id: tailor.h,v 0.18 1993/06/14 19:32:20 jloup Exp $ */
|
|
||||||
|
|
||||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
|
||||||
# define MSDOS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__OS2__) && !defined(OS2)
|
|
||||||
# define OS2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
|
|
||||||
# undef MSDOS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MSDOS
|
|
||||||
# ifdef __GNUC__
|
|
||||||
/* DJGPP version 1.09+ on MS-DOS.
|
|
||||||
* The DJGPP 1.09 stat() function must be upgraded before gzip will
|
|
||||||
* fully work.
|
|
||||||
* No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
|
|
||||||
* implies DIRENT.
|
|
||||||
*/
|
|
||||||
# define near
|
|
||||||
# else
|
|
||||||
# define MAXSEG_64K
|
|
||||||
# ifdef __TURBOC__
|
|
||||||
# define NO_OFF_T
|
|
||||||
# ifdef __BORLANDC__
|
|
||||||
# define DIRENT
|
|
||||||
# else
|
|
||||||
# define NO_UTIME
|
|
||||||
# endif
|
|
||||||
# else /* MSC */
|
|
||||||
# define HAVE_SYS_UTIME_H
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# define PATH_SEP2 '\\'
|
|
||||||
# define PATH_SEP3 ':'
|
|
||||||
# define MAX_PATH_LEN 128
|
|
||||||
# define NO_MULTIPLE_DOTS
|
|
||||||
# define MAX_EXT_CHARS 3
|
|
||||||
# define Z_SUFFIX "z"
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define PROTO
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define NO_SIZE_CHECK
|
|
||||||
# define casemap(c) tolow(c) /* Force file names to lower case */
|
|
||||||
# include <io.h>
|
|
||||||
# define OS_CODE 0x00
|
|
||||||
# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
|
|
||||||
# if !defined(NO_ASM) && !defined(ASMV)
|
|
||||||
# define ASMV
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define near
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef OS2
|
|
||||||
# define PATH_SEP2 '\\'
|
|
||||||
# define PATH_SEP3 ':'
|
|
||||||
# define MAX_PATH_LEN 260
|
|
||||||
# ifdef OS2FAT
|
|
||||||
# define NO_MULTIPLE_DOTS
|
|
||||||
# define MAX_EXT_CHARS 3
|
|
||||||
# define Z_SUFFIX "z"
|
|
||||||
# define casemap(c) tolow(c)
|
|
||||||
# endif
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define PROTO
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# include <io.h>
|
|
||||||
# define OS_CODE 0x06
|
|
||||||
# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
|
|
||||||
# ifdef _MSC_VER
|
|
||||||
# define HAVE_SYS_UTIME_H
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# define MAXSEG_64K
|
|
||||||
# undef near
|
|
||||||
# define near _near
|
|
||||||
# endif
|
|
||||||
# ifdef __EMX__
|
|
||||||
# define HAVE_SYS_UTIME_H
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# define DIRENT
|
|
||||||
# define EXPAND(argc,argv) \
|
|
||||||
{_response(&argc, &argv); _wildcard(&argc, &argv);}
|
|
||||||
# endif
|
|
||||||
# ifdef __BORLANDC__
|
|
||||||
# define DIRENT
|
|
||||||
# endif
|
|
||||||
# ifdef __ZTC__
|
|
||||||
# define NO_DIR
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# include <dos.h>
|
|
||||||
# define EXPAND(argc,argv) \
|
|
||||||
{response_expand(&argc, &argv);}
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32 /* Windows NT */
|
|
||||||
# define HAVE_SYS_UTIME_H
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# define PATH_SEP2 '\\'
|
|
||||||
# define PATH_SEP3 ':'
|
|
||||||
# define MAX_PATH_LEN 260
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define PROTO
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
|
|
||||||
# include <io.h>
|
|
||||||
# include <malloc.h>
|
|
||||||
# ifdef NTFAT
|
|
||||||
# define NO_MULTIPLE_DOTS
|
|
||||||
# define MAX_EXT_CHARS 3
|
|
||||||
# define Z_SUFFIX "z"
|
|
||||||
# define casemap(c) tolow(c) /* Force file names to lower case */
|
|
||||||
# endif
|
|
||||||
# define OS_CODE 0x0b
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MSDOS
|
|
||||||
# ifdef __TURBOC__
|
|
||||||
# include <alloc.h>
|
|
||||||
# define DYN_ALLOC
|
|
||||||
/* Turbo C 2.0 does not accept static allocations of large arrays */
|
|
||||||
void * fcalloc (unsigned items, unsigned size);
|
|
||||||
void fcfree (void *ptr);
|
|
||||||
# else /* MSC */
|
|
||||||
# include <malloc.h>
|
|
||||||
# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
|
|
||||||
# define fcfree(ptr) hfree(ptr)
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifdef MAXSEG_64K
|
|
||||||
# define fcalloc(items,size) calloc((items),(size))
|
|
||||||
# else
|
|
||||||
# define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
|
|
||||||
# endif
|
|
||||||
# define fcfree(ptr) free(ptr)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(VAXC) || defined(VMS)
|
|
||||||
# define PATH_SEP ']'
|
|
||||||
# define PATH_SEP2 ':'
|
|
||||||
# define SUFFIX_SEP ';'
|
|
||||||
# define NO_MULTIPLE_DOTS
|
|
||||||
# define Z_SUFFIX "-gz"
|
|
||||||
# define RECORD_IO 1
|
|
||||||
# define casemap(c) tolow(c)
|
|
||||||
# define OS_CODE 0x02
|
|
||||||
# define OPTIONS_VAR "GZIP_OPT"
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define NO_UTIME
|
|
||||||
# define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
|
|
||||||
# include <file.h>
|
|
||||||
# define unlink delete
|
|
||||||
# ifdef VAXC
|
|
||||||
# define NO_FCNTL_H
|
|
||||||
# include <unixio.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AMIGA
|
|
||||||
# define PATH_SEP2 ':'
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define OS_CODE 0x01
|
|
||||||
# define ASMV
|
|
||||||
# ifdef __GNUC__
|
|
||||||
# define DIRENT
|
|
||||||
# define HAVE_UNISTD_H
|
|
||||||
# else /* SASC */
|
|
||||||
# define NO_STDIN_FSTAT
|
|
||||||
# define SYSDIR
|
|
||||||
# define NO_SYMLINK
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define NO_FCNTL_H
|
|
||||||
# include <fcntl.h> /* for read() and write() */
|
|
||||||
# define direct dirent
|
|
||||||
extern void _expand_args(int *argc, char ***argv);
|
|
||||||
# define EXPAND(argc,argv) _expand_args(&argc,&argv);
|
|
||||||
# undef O_BINARY /* disable useless --ascii option */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ATARI) || defined(atarist)
|
|
||||||
# ifndef STDC_HEADERS
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define HAVE_UNISTD_H
|
|
||||||
# define DIRENT
|
|
||||||
# endif
|
|
||||||
# define ASMV
|
|
||||||
# define OS_CODE 0x05
|
|
||||||
# ifdef TOSFS
|
|
||||||
# define PATH_SEP2 '\\'
|
|
||||||
# define PATH_SEP3 ':'
|
|
||||||
# define MAX_PATH_LEN 128
|
|
||||||
# define NO_MULTIPLE_DOTS
|
|
||||||
# define MAX_EXT_CHARS 3
|
|
||||||
# define Z_SUFFIX "z"
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define casemap(c) tolow(c) /* Force file names to lower case */
|
|
||||||
# define NO_SYMLINK
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MACOS
|
|
||||||
# define PATH_SEP ':'
|
|
||||||
# define DYN_ALLOC
|
|
||||||
# define PROTO
|
|
||||||
# define NO_STDIN_FSTAT
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define NO_UTIME
|
|
||||||
# define chmod(file, mode) (0)
|
|
||||||
# define OPEN(name, flags, mode) open(name, flags)
|
|
||||||
# define OS_CODE 0x07
|
|
||||||
# ifdef MPW
|
|
||||||
# define isatty(fd) ((fd) <= 2)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __50SERIES /* Prime/PRIMOS */
|
|
||||||
# define PATH_SEP '>'
|
|
||||||
# define STDC_HEADERS
|
|
||||||
# define NO_MEMORY_H
|
|
||||||
# define NO_UTIME_H
|
|
||||||
# define NO_UTIME
|
|
||||||
# define NO_CHOWN
|
|
||||||
# define NO_STDIN_FSTAT
|
|
||||||
# define NO_SIZE_CHECK
|
|
||||||
# define NO_SYMLINK
|
|
||||||
# define RECORD_IO 1
|
|
||||||
# define casemap(c) tolow(c) /* Force file names to lower case */
|
|
||||||
# define put_char(c) put_byte((c) & 0x7F)
|
|
||||||
# define get_char(c) ascii2pascii(get_byte())
|
|
||||||
# define OS_CODE 0x0F /* temporary, subject to change */
|
|
||||||
# ifdef SIGTERM
|
|
||||||
# undef SIGTERM /* We don't want a signal handler for SIGTERM */
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */
|
|
||||||
# define NOMEMCPY /* problem with overlapping copies */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TOPS20
|
|
||||||
# define OS_CODE 0x0a
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef unix
|
|
||||||
# define NO_ST_INO /* don't rely on inode numbers */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Common defaults */
|
|
||||||
|
|
||||||
#ifndef OS_CODE
|
|
||||||
# define OS_CODE 0x03 /* assume Unix */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PATH_SEP
|
|
||||||
# define PATH_SEP '/'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef casemap
|
|
||||||
# define casemap(c) (c)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPTIONS_VAR
|
|
||||||
# define OPTIONS_VAR "GZIP"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Z_SUFFIX
|
|
||||||
# define Z_SUFFIX ".gz"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MAX_EXT_CHARS
|
|
||||||
# define MAX_SUFFIX MAX_EXT_CHARS
|
|
||||||
#else
|
|
||||||
# define MAX_SUFFIX 30
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAKE_LEGAL_NAME
|
|
||||||
# ifdef NO_MULTIPLE_DOTS
|
|
||||||
# define MAKE_LEGAL_NAME(name) make_simple_name(name)
|
|
||||||
# else
|
|
||||||
# define MAKE_LEGAL_NAME(name)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIN_PART
|
|
||||||
# define MIN_PART 3
|
|
||||||
/* keep at least MIN_PART chars between dots in a file name. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EXPAND
|
|
||||||
# define EXPAND(argc,argv)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RECORD_IO
|
|
||||||
# define RECORD_IO 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SET_BINARY_MODE
|
|
||||||
# define SET_BINARY_MODE(fd)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPEN
|
|
||||||
# define OPEN(name, flags, mode) open(name, flags, mode)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef get_char
|
|
||||||
# define get_char() get_byte()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef put_char
|
|
||||||
# define put_char(c) put_byte(c)
|
|
||||||
#endif
|
|
||||||
|
|
Binary file not shown.
@ -1,246 +0,0 @@
|
|||||||
//
|
|
||||||
// Socket.h
|
|
||||||
// xzl
|
|
||||||
//
|
|
||||||
// Created by xzl on 16/4/13.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef Socket_h
|
|
||||||
#define Socket_h
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
#include <functional>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Poller/Timer.h"
|
|
||||||
#include "Network/sockutil.h"
|
|
||||||
#include "Thread/spin_mutex.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Poller;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
#if defined(MSG_NOSIGNAL)
|
|
||||||
#define FLAG_NOSIGNAL MSG_NOSIGNAL
|
|
||||||
#else
|
|
||||||
#define FLAG_NOSIGNAL 0
|
|
||||||
#endif //MSG_NOSIGNAL
|
|
||||||
|
|
||||||
#if defined(MSG_MORE)
|
|
||||||
#define FLAG_MORE MSG_MORE
|
|
||||||
#else
|
|
||||||
#define FLAG_MORE 0
|
|
||||||
#endif //MSG_MORE
|
|
||||||
|
|
||||||
#if defined(MSG_DONTWAIT)
|
|
||||||
#define FLAG_DONTWAIT MSG_DONTWAIT
|
|
||||||
#else
|
|
||||||
#define FLAG_DONTWAIT 0
|
|
||||||
#endif //MSG_DONTWAIT
|
|
||||||
|
|
||||||
#define TCP_DEFAULE_FLAGS (FLAG_NOSIGNAL | FLAG_DONTWAIT)
|
|
||||||
#define UDP_DEFAULE_FLAGS (FLAG_NOSIGNAL | FLAG_DONTWAIT)
|
|
||||||
|
|
||||||
#define MAX_SEND_PKT (256)
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#import "TargetConditionals.h"
|
|
||||||
#if TARGET_IPHONE_SIMULATOR
|
|
||||||
#define OS_IPHONE
|
|
||||||
#elif TARGET_OS_IPHONE
|
|
||||||
#define OS_IPHONE
|
|
||||||
#endif
|
|
||||||
#endif //__APPLE__
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Err_success = 0, //成功
|
|
||||||
Err_eof, //eof
|
|
||||||
Err_timeout, //超时
|
|
||||||
Err_refused,
|
|
||||||
Err_dns,
|
|
||||||
Err_other,
|
|
||||||
} ErrCode;
|
|
||||||
|
|
||||||
class SockException: public std::exception {
|
|
||||||
public:
|
|
||||||
SockException(ErrCode _errCode = Err_success, const string &_errMsg = "") {
|
|
||||||
errMsg = _errMsg;
|
|
||||||
errCode = _errCode;
|
|
||||||
}
|
|
||||||
void reset(ErrCode _errCode, const string &_errMsg) {
|
|
||||||
errMsg = _errMsg;
|
|
||||||
errCode = _errCode;
|
|
||||||
}
|
|
||||||
virtual const char* what() const noexcept {
|
|
||||||
return errMsg.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrCode getErrCode() const {
|
|
||||||
return errCode;
|
|
||||||
}
|
|
||||||
operator bool() const{
|
|
||||||
return errCode != Err_success;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
string errMsg;
|
|
||||||
ErrCode errCode;
|
|
||||||
};
|
|
||||||
class SockFD
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<SockFD> Ptr;
|
|
||||||
SockFD(int sock){
|
|
||||||
_sock = sock;
|
|
||||||
}
|
|
||||||
virtual ~SockFD(){
|
|
||||||
::shutdown(_sock, SHUT_RDWR);
|
|
||||||
#if defined (OS_IPHONE)
|
|
||||||
unsetSocketOfIOS(_sock);
|
|
||||||
#endif //OS_IPHONE
|
|
||||||
int fd = _sock;
|
|
||||||
EventPoller::Instance().delEvent(fd,[fd](bool){
|
|
||||||
close(fd);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void setConnected(){
|
|
||||||
#if defined (OS_IPHONE)
|
|
||||||
setSocketOfIOS(_sock);
|
|
||||||
#endif //OS_IPHONE
|
|
||||||
}
|
|
||||||
int rawFd() const{
|
|
||||||
return _sock;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int _sock;
|
|
||||||
|
|
||||||
#if defined (OS_IPHONE)
|
|
||||||
void *readStream=NULL;
|
|
||||||
void *writeStream=NULL;
|
|
||||||
bool setSocketOfIOS(int socket);
|
|
||||||
void unsetSocketOfIOS(int socket);
|
|
||||||
#endif //OS_IPHONE
|
|
||||||
};
|
|
||||||
|
|
||||||
class Socket: public std::enable_shared_from_this<Socket> {
|
|
||||||
public:
|
|
||||||
class Buffer {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<Buffer> Ptr;
|
|
||||||
Buffer(uint32_t size) {
|
|
||||||
_size = size;
|
|
||||||
_data = new char[size];
|
|
||||||
}
|
|
||||||
virtual ~Buffer() {
|
|
||||||
delete[] _data;
|
|
||||||
}
|
|
||||||
const char *data() const {
|
|
||||||
return _data;
|
|
||||||
}
|
|
||||||
uint32_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
friend class Socket;
|
|
||||||
char *_data;
|
|
||||||
uint32_t _size;
|
|
||||||
};
|
|
||||||
typedef std::shared_ptr<Socket> Ptr;
|
|
||||||
typedef function<void(const Buffer::Ptr &buf, struct sockaddr *addr)> onReadCB;
|
|
||||||
typedef function<void(const SockException &err)> onErrCB;
|
|
||||||
typedef function<void(Socket::Ptr &sock)> onAcceptCB;
|
|
||||||
typedef function<bool()> onFlush;
|
|
||||||
|
|
||||||
Socket();
|
|
||||||
virtual ~Socket();
|
|
||||||
int rawFD() const{
|
|
||||||
SockFD::Ptr sock;
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lck(_mtx_sockFd);
|
|
||||||
sock = _sockFd;
|
|
||||||
}
|
|
||||||
if(!sock){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return sock->rawFd();
|
|
||||||
}
|
|
||||||
void connect(const string &url, uint16_t port, onErrCB &&connectCB, int timeoutSec = 5);
|
|
||||||
bool listen(const uint16_t port, const char *localIp = "0.0.0.0", int backLog = 1024);
|
|
||||||
bool bindUdpSock(const uint16_t port, const char *localIp = "0.0.0.0");
|
|
||||||
|
|
||||||
void setOnRead(const onReadCB &cb);
|
|
||||||
void setOnErr(const onErrCB &cb);
|
|
||||||
void setOnAccept(const onAcceptCB &cb);
|
|
||||||
void setOnFlush(const onFlush &cb);
|
|
||||||
|
|
||||||
int send(const char *buf, int size = 0,int flags = TCP_DEFAULE_FLAGS);
|
|
||||||
int send(const string &buf,int flags = TCP_DEFAULE_FLAGS);
|
|
||||||
int sendTo(const char *buf, int size, struct sockaddr *peerAddr,int flags = UDP_DEFAULE_FLAGS);
|
|
||||||
int sendTo(const string &buf, struct sockaddr *peerAddr,int flags = UDP_DEFAULE_FLAGS);
|
|
||||||
bool emitErr(const SockException &err);
|
|
||||||
void enableRecv(bool enabled);
|
|
||||||
|
|
||||||
string get_local_ip();
|
|
||||||
uint16_t get_local_port();
|
|
||||||
string get_peer_ip();
|
|
||||||
uint16_t get_peer_port();
|
|
||||||
|
|
||||||
void setSendPktSize(uint32_t iPktSize){
|
|
||||||
_iMaxSendPktSize = iPktSize;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
mutable spin_mutex _mtx_sockFd;
|
|
||||||
SockFD::Ptr _sockFd;
|
|
||||||
//send buffer
|
|
||||||
recursive_mutex _mtx_sendBuf;
|
|
||||||
deque<string> _sendPktBuf;
|
|
||||||
deque<struct sockaddr> _udpSendPeer;
|
|
||||||
/////////////////////
|
|
||||||
std::shared_ptr<Timer> _conTimer;
|
|
||||||
struct sockaddr _peerAddr;
|
|
||||||
spin_mutex _mtx_read;
|
|
||||||
spin_mutex _mtx_err;
|
|
||||||
spin_mutex _mtx_accept;
|
|
||||||
spin_mutex _mtx_flush;
|
|
||||||
onReadCB _readCB;
|
|
||||||
onErrCB _errCB;
|
|
||||||
onAcceptCB _acceptCB;
|
|
||||||
onFlush _flushCB;
|
|
||||||
Ticker _flushTicker;
|
|
||||||
int _lastSendFlags = TCP_DEFAULE_FLAGS;
|
|
||||||
uint32_t _iMaxSendPktSize = MAX_SEND_PKT;
|
|
||||||
atomic_bool _enableRecv;
|
|
||||||
|
|
||||||
void closeSock();
|
|
||||||
bool setPeerSock(int fd, struct sockaddr *addr);
|
|
||||||
bool attachEvent(const SockFD::Ptr &pSock,bool isUdp = false);
|
|
||||||
|
|
||||||
int onAccept(const SockFD::Ptr &pSock,int event);
|
|
||||||
int onRead(const SockFD::Ptr &pSock,bool mayEof=true);
|
|
||||||
void onError(const SockFD::Ptr &pSock);
|
|
||||||
int realSend(const string &buf, struct sockaddr *peerAddr,int flags);
|
|
||||||
int onWrite(const SockFD::Ptr &pSock, bool bMainThread,int flags,bool isUdp);
|
|
||||||
void onConnected(const SockFD::Ptr &pSock, const onErrCB &connectCB);
|
|
||||||
void onFlushed(const SockFD::Ptr &pSock);
|
|
||||||
|
|
||||||
void startWriteEvent(const SockFD::Ptr &pSock);
|
|
||||||
void stopWriteEvent(const SockFD::Ptr &pSock);
|
|
||||||
bool sendTimeout(bool isUdp);
|
|
||||||
SockFD::Ptr makeSock(int sock){
|
|
||||||
return std::make_shared<SockFD>(sock);
|
|
||||||
}
|
|
||||||
static SockException getSockErr(const SockFD::Ptr &pSock,bool tryErrno=true);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Network
|
|
||||||
} // namespace ZL
|
|
||||||
|
|
||||||
#endif /* Socket_h */
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* TcpClient.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年2月13日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_NETWORK_TCPCLIENT_H_
|
|
||||||
#define SRC_NETWORK_TCPCLIENT_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
|
||||||
#include "Socket.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
#include "Thread/WorkThreadPool.h"
|
|
||||||
#include "Thread/spin_mutex.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
class TcpClient : public std::enable_shared_from_this<TcpClient> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<TcpClient> Ptr;
|
|
||||||
TcpClient();
|
|
||||||
virtual ~TcpClient();
|
|
||||||
protected:
|
|
||||||
void startConnect(const string &strUrl, uint16_t iPort, int iTimeOutSec = 3);
|
|
||||||
void shutdown();
|
|
||||||
virtual int send(const string &str);
|
|
||||||
virtual int send(const char *str, int len);
|
|
||||||
bool alive() {
|
|
||||||
lock_guard<spin_mutex> lck(m_mutex);
|
|
||||||
return m_pSock.operator bool();
|
|
||||||
}
|
|
||||||
string get_local_ip() {
|
|
||||||
decltype(m_pSock) sockTmp;
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lck(m_mutex);
|
|
||||||
sockTmp = m_pSock;
|
|
||||||
}
|
|
||||||
if(!sockTmp){
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return sockTmp->get_local_ip();
|
|
||||||
}
|
|
||||||
uint16_t get_local_port() {
|
|
||||||
decltype(m_pSock) sockTmp;
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lck(m_mutex);
|
|
||||||
sockTmp = m_pSock;
|
|
||||||
}
|
|
||||||
if(!sockTmp){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return sockTmp->get_local_port();
|
|
||||||
}
|
|
||||||
string get_peer_ip() {
|
|
||||||
decltype(m_pSock) sockTmp;
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lck(m_mutex);
|
|
||||||
sockTmp = m_pSock;
|
|
||||||
}
|
|
||||||
if(!sockTmp){
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return sockTmp->get_peer_ip();
|
|
||||||
}
|
|
||||||
uint16_t get_peer_port() {
|
|
||||||
decltype(m_pSock) sockTmp;
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lck(m_mutex);
|
|
||||||
sockTmp = m_pSock;
|
|
||||||
}
|
|
||||||
if(!sockTmp){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return sockTmp->get_peer_port();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t elapsedTime();
|
|
||||||
|
|
||||||
//链接成功后,客户端将绑定一个后台线程,并且onConnect/onRecv/onSend/onErr事件将在该后台线程触发
|
|
||||||
virtual void onConnect(const SockException &ex) {}
|
|
||||||
virtual void onRecv(const Socket::Buffer::Ptr &pBuf) {}
|
|
||||||
virtual void onSend() {}
|
|
||||||
virtual void onErr(const SockException &ex) {}
|
|
||||||
Socket::Ptr m_pSock;
|
|
||||||
private:
|
|
||||||
Ticker m_ticker;
|
|
||||||
spin_mutex m_mutex;
|
|
||||||
|
|
||||||
void onSockConnect(const SockException &ex);
|
|
||||||
void onSockRecv(const Socket::Buffer::Ptr &pBuf);
|
|
||||||
void onSockSend();
|
|
||||||
void onSockErr(const SockException &ex);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Network */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_NETWORK_TCPCLIENT_H_ */
|
|
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Session.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月27日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVER_LIMITEDSESSION_H_
|
|
||||||
#define SERVER_LIMITEDSESSION_H_
|
|
||||||
#include <memory>
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "TcpSession.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
template<int MaxCount>
|
|
||||||
class TcpLimitedSession: public TcpSession {
|
|
||||||
public:
|
|
||||||
TcpLimitedSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock) :
|
|
||||||
TcpSession(_th,_sock) {
|
|
||||||
lock_guard<recursive_mutex> lck(stackMutex());
|
|
||||||
static uint64_t maxSeq(0);
|
|
||||||
sessionSeq = maxSeq++;
|
|
||||||
auto &stack = getStack();
|
|
||||||
stack.emplace(this);
|
|
||||||
|
|
||||||
if(stack.size() > MaxCount){
|
|
||||||
auto it = stack.begin();
|
|
||||||
(*it)->safeShutdown();
|
|
||||||
stack.erase(it);
|
|
||||||
WarnL << "超过TCP个数限制:" << MaxCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual ~TcpLimitedSession() {
|
|
||||||
lock_guard<recursive_mutex> lck(stackMutex());
|
|
||||||
getStack().erase(this);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
uint64_t sessionSeq; //会话栈顺序
|
|
||||||
struct Comparer {
|
|
||||||
bool operator()(TcpLimitedSession *x, TcpLimitedSession *y) const {
|
|
||||||
return x->sessionSeq < y->sessionSeq;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static recursive_mutex &stackMutex(){
|
|
||||||
static recursive_mutex mtx;
|
|
||||||
return mtx;
|
|
||||||
}
|
|
||||||
//RTSP会话栈,先创建的在前面
|
|
||||||
static set<TcpLimitedSession *, Comparer> &getStack(){
|
|
||||||
static set<TcpLimitedSession *, Comparer> stack;
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Session */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SERVER_LIMITEDSESSION_H_ */
|
|
@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* TcpServer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月9日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TCPSERVER_TCPSERVER_H_
|
|
||||||
#define TCPSERVER_TCPSERVER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <exception>
|
|
||||||
#include <functional>
|
|
||||||
#include "Socket.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/uv_errno.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Poller/Timer.h"
|
|
||||||
#include "Thread/semaphore.h"
|
|
||||||
#include "Thread/WorkThreadPool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Poller;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
template<typename Session>
|
|
||||||
class TcpServer {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<TcpServer> Ptr;
|
|
||||||
TcpServer() {
|
|
||||||
socket.reset(new Socket());
|
|
||||||
sessionMap.reset(new typename decltype(sessionMap)::element_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
~TcpServer() {
|
|
||||||
TraceL << "start clean...";
|
|
||||||
timer.reset();
|
|
||||||
socket.reset();
|
|
||||||
|
|
||||||
typename decltype(sessionMap)::element_type copyMap;
|
|
||||||
sessionMap->swap(copyMap);
|
|
||||||
for (auto it = copyMap.begin(); it != copyMap.end(); ++it) {
|
|
||||||
auto session = it->second;
|
|
||||||
it->second->async_first( [session]() {
|
|
||||||
session->onError(SockException(Err_other,"Tcp server shutdown!"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
TraceL << "clean completed!";
|
|
||||||
}
|
|
||||||
void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog = 1024) {
|
|
||||||
bool success = socket->listen(port, host.c_str(), backlog);
|
|
||||||
if (!success) {
|
|
||||||
string err = (StrPrinter << "listen on " << host << ":" << port << "] failed:" << get_uv_errmsg(true)).operator <<(endl);
|
|
||||||
throw std::runtime_error(err);
|
|
||||||
}
|
|
||||||
socket->setOnAccept( bind(&TcpServer::onAcceptConnection, this, placeholders::_1));
|
|
||||||
timer.reset(new Timer(2, [this]()->bool {
|
|
||||||
this->onManagerSession();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
InfoL << "TCP Server listening on " << host << ":" << port;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Socket::Ptr socket;
|
|
||||||
std::shared_ptr<Timer> timer;
|
|
||||||
std::shared_ptr<std::unordered_map<Socket *, std::shared_ptr<Session> > > sessionMap;
|
|
||||||
|
|
||||||
void onAcceptConnection(const Socket::Ptr & sock) {
|
|
||||||
// 接收到客户端连接请求
|
|
||||||
auto session(std::make_shared<Session>(WorkThreadPool::Instance().getWorkThread(), sock));
|
|
||||||
auto sockPtr(sock.get());
|
|
||||||
auto sessionMapTmp(sessionMap);
|
|
||||||
weak_ptr<Session> weakSession(session);
|
|
||||||
sessionMapTmp->emplace(sockPtr, session);
|
|
||||||
|
|
||||||
// 会话接收数据事件
|
|
||||||
sock->setOnRead([weakSession](const Socket::Buffer::Ptr &buf, struct sockaddr *addr){
|
|
||||||
//获取会话强应用
|
|
||||||
auto strongSession=weakSession.lock();
|
|
||||||
if(!strongSession) {
|
|
||||||
//会话对象已释放
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//在会话线程中执行onRecv操作
|
|
||||||
strongSession->async([weakSession,buf]() {
|
|
||||||
auto strongSession=weakSession.lock();
|
|
||||||
if(!strongSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strongSession->onRecv(buf);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//会话接收到错误事件
|
|
||||||
sock->setOnErr([weakSession,sockPtr,sessionMapTmp](const SockException &err){
|
|
||||||
//获取会话强应用
|
|
||||||
auto strongSession=weakSession.lock();
|
|
||||||
//移除掉会话
|
|
||||||
sessionMapTmp->erase(sockPtr);
|
|
||||||
if(!strongSession) {
|
|
||||||
//会话对象已释放
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//在会话线程中执行onError操作
|
|
||||||
strongSession->async_first([strongSession,err]() {
|
|
||||||
strongSession->onError(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void onManagerSession() {
|
|
||||||
//DebugL<<EventPoller::Instance().isMainThread();
|
|
||||||
for (auto &pr : *sessionMap) {
|
|
||||||
weak_ptr<Session> weakSession = pr.second;
|
|
||||||
pr.second->async([weakSession]() {
|
|
||||||
auto strongSession=weakSession.lock();
|
|
||||||
if(!strongSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strongSession->onManager();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Network */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* TCPSERVER_TCPSERVER_H_ */
|
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Session.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月27日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVER_SESSION_H_
|
|
||||||
#define SERVER_SESSION_H_
|
|
||||||
#include <memory>
|
|
||||||
#include "Socket.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
class TcpSession: public std::enable_shared_from_this<TcpSession> {
|
|
||||||
public:
|
|
||||||
TcpSession(const std::shared_ptr<ThreadPool> &_th, const Socket::Ptr &_sock) :
|
|
||||||
sock(_sock), th(_th) {
|
|
||||||
localIp = sock->get_local_ip();
|
|
||||||
peerIp = sock->get_peer_ip();
|
|
||||||
localPort = sock->get_local_port();
|
|
||||||
peerPort = sock->get_peer_port();
|
|
||||||
}
|
|
||||||
virtual ~TcpSession() {
|
|
||||||
}
|
|
||||||
virtual void onRecv(const Socket::Buffer::Ptr &) =0;
|
|
||||||
virtual void onError(const SockException &err) =0;
|
|
||||||
virtual void onManager() =0;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void async(T &&task) {
|
|
||||||
th->async(std::forward<T>(task));
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
void async_first(T &&task) {
|
|
||||||
th->async_first(std::forward<T>(task));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const string& getLocalIp() const {
|
|
||||||
return localIp;
|
|
||||||
}
|
|
||||||
const string& getPeerIp() const {
|
|
||||||
return peerIp;
|
|
||||||
}
|
|
||||||
uint16_t getLocalPort() const {
|
|
||||||
return localPort;
|
|
||||||
}
|
|
||||||
uint16_t getPeerPort() const {
|
|
||||||
return peerPort;
|
|
||||||
}
|
|
||||||
virtual void shutdown() {
|
|
||||||
sock->emitErr(SockException(Err_other, "self shutdown"));
|
|
||||||
}
|
|
||||||
void safeShutdown(){
|
|
||||||
std::weak_ptr<TcpSession> weakSelf = shared_from_this();
|
|
||||||
async_first([weakSelf](){
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if(strongSelf){
|
|
||||||
strongSelf->shutdown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
virtual int send(const string &buf) {
|
|
||||||
return sock->send(buf);
|
|
||||||
}
|
|
||||||
virtual int send(const char *buf, int size) {
|
|
||||||
return sock->send(buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Socket::Ptr sock;
|
|
||||||
private:
|
|
||||||
std::shared_ptr<ThreadPool> th;
|
|
||||||
string localIp;
|
|
||||||
string peerIp;
|
|
||||||
uint16_t localPort;
|
|
||||||
uint16_t peerPort;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Session */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SERVER_SESSION_H_ */
|
|
@ -1,86 +0,0 @@
|
|||||||
#ifndef SOCKUTIL_H
|
|
||||||
#define SOCKUTIL_H
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#include <Iphlpapi.h>
|
|
||||||
#pragma comment (lib,"WS2_32")
|
|
||||||
#pragma comment(lib,"Iphlpapi.lib")
|
|
||||||
#else
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
#ifndef socklen_t
|
|
||||||
#define socklen_t int
|
|
||||||
#endif //!socklen_t
|
|
||||||
#ifndef SHUT_RDWR
|
|
||||||
#define SHUT_RDWR 2
|
|
||||||
#endif //!SHUT_RDWR
|
|
||||||
|
|
||||||
int ioctl(int fd, long cmd, u_long *ptr);
|
|
||||||
int close(int fd);
|
|
||||||
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Network {
|
|
||||||
|
|
||||||
class SockUtil {
|
|
||||||
public:
|
|
||||||
static int connect(const char *host, uint16_t port, bool bAsync = true);
|
|
||||||
static int listen(const uint16_t port, const char *localIp = "0.0.0.0",
|
|
||||||
int backLog = 1024);
|
|
||||||
static int bindUdpSock(const uint16_t port,
|
|
||||||
const char *localIp = "0.0.0.0");
|
|
||||||
static int setNoDelay(int sockFd, bool on = true);
|
|
||||||
static int setNoSigpipe(int sock);
|
|
||||||
static int setNoBlocked(int sock, bool noblock = true);
|
|
||||||
static int setRecvBuf(int sock, int size = 256 * 1024);
|
|
||||||
static int setSendBuf(int sock, int size = 256 * 1024);
|
|
||||||
|
|
||||||
static int setReuseable(int sockFd, bool on = true);
|
|
||||||
static int setBroadcast(int sockFd, bool on = true);
|
|
||||||
static int setKeepAlive(int sockFd, bool on = true);
|
|
||||||
|
|
||||||
//组播相关
|
|
||||||
static int setMultiTTL(int sockFd, uint8_t ttl = 64);
|
|
||||||
static int setMultiIF(int sockFd, const char *strLocalIp);
|
|
||||||
static int setMultiLOOP(int sockFd, bool bAccept = false);
|
|
||||||
static int joinMultiAddr(int sockFd, const char *strAddr, const char* strLocalIp = "0.0.0.0");
|
|
||||||
static int leaveMultiAddr(int sockFd, const char *strAddr, const char* strLocalIp = "0.0.0.0");
|
|
||||||
static int joinMultiAddrFilter(int sockFd, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
|
|
||||||
static int leaveMultiAddrFilter(int sockFd, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
|
|
||||||
|
|
||||||
static int getSockError(int sockFd);
|
|
||||||
static int setCloseWait(int sockFd, int second = 0);
|
|
||||||
|
|
||||||
static string get_local_ip(int fd);
|
|
||||||
static string get_local_ip();
|
|
||||||
static uint16_t get_local_port(int fd);
|
|
||||||
static string get_peer_ip(int fd);
|
|
||||||
static uint16_t get_peer_port(int fd);
|
|
||||||
|
|
||||||
static string get_ifr_name(const char *localIp);
|
|
||||||
static string get_ifr_mask(const char *ifrName);
|
|
||||||
static string get_ifr_brdaddr(const char *ifrName);
|
|
||||||
static bool in_same_lan(const char *myIp, const char *dsrIp);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Network
|
|
||||||
} // namespace ZL
|
|
||||||
|
|
||||||
#endif // !SOCKUTIL_H
|
|
@ -1,123 +0,0 @@
|
|||||||
//
|
|
||||||
// EventPoller.h
|
|
||||||
// xzl
|
|
||||||
//
|
|
||||||
// Created by xzl on 16/4/12.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef EventPoller_h
|
|
||||||
#define EventPoller_h
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "PipeWrap.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
#define HAS_EPOLL
|
|
||||||
#endif //__linux__
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Poller {
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Event_Read = 1 << 0, //读事件
|
|
||||||
Event_Write = 1 << 1, //写事件
|
|
||||||
Event_Error = 1 << 2, //错误事件
|
|
||||||
Event_LT = 1 << 3,//水平触发
|
|
||||||
} Poll_Event;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Sig_Exit = 0, //关闭监听
|
|
||||||
Sig_Async, //异步
|
|
||||||
} Sigal_Type;
|
|
||||||
|
|
||||||
typedef function<void(int event)> PollEventCB;
|
|
||||||
typedef function<void(bool success)> PollDelCB;
|
|
||||||
typedef function<void(void)> PollAsyncCB;
|
|
||||||
typedef PollAsyncCB PollSyncCB;
|
|
||||||
|
|
||||||
#ifndef HAS_EPOLL
|
|
||||||
typedef struct {
|
|
||||||
Poll_Event event;
|
|
||||||
PollEventCB callBack;
|
|
||||||
int attach;
|
|
||||||
void operator()(int _event) const{
|
|
||||||
callBack(_event);
|
|
||||||
}
|
|
||||||
void operator()() const{
|
|
||||||
callBack(attach);
|
|
||||||
}
|
|
||||||
} Poll_Record;
|
|
||||||
#endif //HAS_EPOLL
|
|
||||||
|
|
||||||
class EventPoller {
|
|
||||||
public:
|
|
||||||
EventPoller(bool enableSelfRun = false);
|
|
||||||
virtual ~EventPoller();
|
|
||||||
static EventPoller &Instance(bool enableSelfRun = false) {
|
|
||||||
static EventPoller *instance(new EventPoller(enableSelfRun));
|
|
||||||
return *instance;
|
|
||||||
}
|
|
||||||
static void Destory() {
|
|
||||||
delete &EventPoller::Instance();
|
|
||||||
}
|
|
||||||
int addEvent(int fd, int event, PollEventCB &&eventCb);
|
|
||||||
int delEvent(int fd, PollDelCB &&delCb = nullptr);
|
|
||||||
int modifyEvent(int fd, int event);
|
|
||||||
|
|
||||||
void async(PollAsyncCB &&asyncCb);
|
|
||||||
void sync(PollSyncCB &&syncCb);
|
|
||||||
|
|
||||||
void runLoop();
|
|
||||||
void shutdown();
|
|
||||||
bool isMainThread();
|
|
||||||
private:
|
|
||||||
void initPoll();
|
|
||||||
inline int sigalPipe(uint64_t type, uint64_t i64_size = 0, uint64_t *buf = NULL);
|
|
||||||
inline bool handlePipeEvent();
|
|
||||||
inline Sigal_Type _handlePipeEvent(uint64_t type, uint64_t i64_size, uint64_t *buf);
|
|
||||||
|
|
||||||
PipeWrap _pipe;
|
|
||||||
bool _exitLoop = false;
|
|
||||||
thread *loopThread = nullptr;
|
|
||||||
thread::id mainThreadId;
|
|
||||||
mutex mtx_event_map;
|
|
||||||
#if defined(HAS_EPOLL)
|
|
||||||
int epoll_fd = -1;
|
|
||||||
unordered_map<int, PollEventCB> event_map;
|
|
||||||
#else
|
|
||||||
unordered_map<int, Poll_Record> event_map;
|
|
||||||
#endif //HAS_EPOLL
|
|
||||||
string pipeBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ASYNC_TRACE(...) {\
|
|
||||||
/*TraceL;*/\
|
|
||||||
EventPoller::Instance().async(__VA_ARGS__);\
|
|
||||||
}
|
|
||||||
#define SYNC_TRACE(...) {\
|
|
||||||
/*TraceL;*/\
|
|
||||||
EventPoller::Instance().sync(__VA_ARGS__);\
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Poller
|
|
||||||
} // namespace ZL
|
|
||||||
#endif /* EventPoller_h */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// Pipe.h
|
|
||||||
// xzl
|
|
||||||
//
|
|
||||||
// Created by xzl on 16/4/13.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef Pipe_h
|
|
||||||
#define Pipe_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <functional>
|
|
||||||
#include "PipeWrap.h"
|
|
||||||
#include "EventPoller.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Poller {
|
|
||||||
|
|
||||||
class Pipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Pipe(function<void(int size,const char *buf)> &&onRead=nullptr);
|
|
||||||
virtual ~Pipe();
|
|
||||||
void send(const char *send,int size=0);
|
|
||||||
private:
|
|
||||||
std::shared_ptr<PipeWrap> _pipe;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Poller
|
|
||||||
} // namespace ZL
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* Pipe_h */
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef PipeWarp_h
|
|
||||||
#define PipeWarp_h
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Poller {
|
|
||||||
|
|
||||||
class PipeWrap {
|
|
||||||
public:
|
|
||||||
PipeWrap();
|
|
||||||
~PipeWrap();
|
|
||||||
int write(const void *buf, int n);
|
|
||||||
int read(void *buf, int n);
|
|
||||||
int readFD() const {
|
|
||||||
return _pipe_fd[0];
|
|
||||||
}
|
|
||||||
int writeFD() const {
|
|
||||||
return _pipe_fd[1];
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int _pipe_fd[2] = { -1,-1 };
|
|
||||||
void clearFD();
|
|
||||||
#if defined(_WIN32)
|
|
||||||
int _listenerFd = -1;
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Poller */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif // !PipeWarp_h
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* WinSelect.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年3月2日
|
|
||||||
* Author: Jzan
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_POLLER_SELECTWRAP_H_
|
|
||||||
#define SRC_POLLER_SELECTWRAP_H_
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Poller {
|
|
||||||
|
|
||||||
class FdSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FdSet();
|
|
||||||
virtual ~FdSet();
|
|
||||||
void fdZero();
|
|
||||||
void fdSet(int fd);
|
|
||||||
void fdClr(int fd);
|
|
||||||
bool isSet(int fd);
|
|
||||||
void *ptr;
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Poller */
|
|
||||||
} /* namespace ZL */
|
|
||||||
using namespace ZL::Poller;
|
|
||||||
int zl_select(int cnt,FdSet *read,FdSet *write,FdSet *err,struct timeval *tv);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SRC_POLLER_SELECTWRAP_H_ */
|
|
@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// Timer.h
|
|
||||||
// xzl
|
|
||||||
//
|
|
||||||
// Created by xzl on 16/4/13.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef Timer_h
|
|
||||||
#define Timer_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <functional>
|
|
||||||
#include "EventPoller.h"
|
|
||||||
#include "Thread/AsyncTaskThread.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Poller {
|
|
||||||
|
|
||||||
class Timer {
|
|
||||||
public:
|
|
||||||
Timer(float second,const function<bool()> &cb);
|
|
||||||
virtual ~Timer();
|
|
||||||
private:
|
|
||||||
std::shared_ptr<bool> canceled;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Poller
|
|
||||||
} // namespace ZL
|
|
||||||
#endif /* Timer_h */
|
|
@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// AsyncTaskThread.h
|
|
||||||
// xzl
|
|
||||||
//
|
|
||||||
// Created by xzl on 15/6/8.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef AsyncTaskThread_h
|
|
||||||
#define AsyncTaskThread_h
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include "Util/util.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
#define TASK_INTERVAL 50
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
typedef struct {
|
|
||||||
uint64_t type;
|
|
||||||
uint64_t timeLine;
|
|
||||||
uint64_t tickTime;
|
|
||||||
function<bool()> task;
|
|
||||||
} TaskInfo;
|
|
||||||
|
|
||||||
|
|
||||||
class AsyncTaskThread {
|
|
||||||
public:
|
|
||||||
//the timer default 30s
|
|
||||||
AsyncTaskThread(uint64_t millisecond_sleep);
|
|
||||||
~AsyncTaskThread();
|
|
||||||
void DoTaskDelay(uint64_t type, uint64_t millisecond, const function<bool()> &func);
|
|
||||||
void CancelTask(uint64_t type);
|
|
||||||
static AsyncTaskThread &Instance(uint32_t millisecond_sleep = TASK_INTERVAL) {
|
|
||||||
static AsyncTaskThread *instance(new AsyncTaskThread(millisecond_sleep));
|
|
||||||
return *instance;
|
|
||||||
}
|
|
||||||
static void Destory(){
|
|
||||||
delete &AsyncTaskThread::Instance();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
recursive_mutex _mtx;
|
|
||||||
unordered_multimap<uint64_t, std::shared_ptr<TaskInfo> > taskMap;
|
|
||||||
unordered_set<uint64_t> needCancel;
|
|
||||||
inline uint64_t getNowTime();
|
|
||||||
thread *taskThread;
|
|
||||||
void DoTask();
|
|
||||||
atomic_bool threadExit;
|
|
||||||
condition_variable_any cond;
|
|
||||||
uint64_t millisecond_sleep;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AsyncTaskHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AsyncTaskHelper(uint64_t millisecond,const function<bool()> &task){
|
|
||||||
AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast<uint64_t>(this),millisecond,task);
|
|
||||||
}
|
|
||||||
virtual ~AsyncTaskHelper(){
|
|
||||||
AsyncTaskThread::Instance().CancelTask(reinterpret_cast<uint64_t>(this));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* defined(AsyncTaskThread_h) */
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* TaskQueue.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-10-11
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TASKQUEUE_H_
|
|
||||||
#define TASKQUEUE_H_
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
|
||||||
#include <functional>
|
|
||||||
#include "spin_mutex.h"
|
|
||||||
#include "semaphore.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
//实现了一个基于函数对象的任务列队,该列队是线程安全的,任务列队任务数由信号量控制
|
|
||||||
class TaskQueue {
|
|
||||||
public:
|
|
||||||
TaskQueue() {
|
|
||||||
}
|
|
||||||
//打入任务至列队
|
|
||||||
template <typename T>
|
|
||||||
void push_task(T &&task_func) {
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lock(my_mutex);
|
|
||||||
my_queue.emplace_back(std::forward<T>(task_func));
|
|
||||||
}
|
|
||||||
sem.post();
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
void push_task_first(T &&task_func) {
|
|
||||||
{
|
|
||||||
lock_guard<spin_mutex> lock(my_mutex);
|
|
||||||
my_queue.emplace_front(std::forward<T>(task_func));
|
|
||||||
}
|
|
||||||
sem.post();
|
|
||||||
}
|
|
||||||
//清空任务列队
|
|
||||||
void push_exit(unsigned int n) {
|
|
||||||
sem.post(n);
|
|
||||||
}
|
|
||||||
//从列队获取一个任务,由执行线程执行
|
|
||||||
bool get_task(function<void(void)> &tsk) {
|
|
||||||
sem.wait();
|
|
||||||
lock_guard<spin_mutex> lock(my_mutex);
|
|
||||||
if (my_queue.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
tsk = my_queue.front();
|
|
||||||
my_queue.pop_front();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
uint64_t size() const{
|
|
||||||
lock_guard<spin_mutex> lock(my_mutex);
|
|
||||||
return my_queue.size();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
deque<function<void(void)>> my_queue;
|
|
||||||
mutable spin_mutex my_mutex;
|
|
||||||
semaphore sem;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
#endif /* TASKQUEUE_H_ */
|
|
@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* ThreadPool.h
|
|
||||||
*
|
|
||||||
* Created on: 2013-10-11
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef THREADPOOL_H_
|
|
||||||
#define THREADPOOL_H_
|
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "threadgroup.h"
|
|
||||||
#include "TaskQueue.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
class ThreadPool {
|
|
||||||
public:
|
|
||||||
enum Priority {
|
|
||||||
PRIORITY_LOWEST = 0,
|
|
||||||
PRIORITY_LOW,
|
|
||||||
PRIORITY_NORMAL,
|
|
||||||
PRIORITY_HIGH,
|
|
||||||
PRIORITY_HIGHEST
|
|
||||||
};
|
|
||||||
|
|
||||||
//num:线程池线程个数
|
|
||||||
ThreadPool(int num, Priority _priority = PRIORITY_NORMAL) :
|
|
||||||
thread_num(num), avaible(true), priority(_priority) {
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
~ThreadPool() {
|
|
||||||
wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
//把任务打入线程池并异步执行
|
|
||||||
template <typename T>
|
|
||||||
bool async(T &&task) {
|
|
||||||
if (!avaible) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (my_thread_group.is_this_thread_in()) {
|
|
||||||
task();
|
|
||||||
} else {
|
|
||||||
my_queue.push_task(std::forward<T>(task));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
bool async_first(T &&task) {
|
|
||||||
if (!avaible) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (my_thread_group.is_this_thread_in()) {
|
|
||||||
task();
|
|
||||||
} else {
|
|
||||||
my_queue.push_task_first(std::forward<T>(task));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
bool sync(T &&task){
|
|
||||||
semaphore sem;
|
|
||||||
bool flag = async([&](){
|
|
||||||
task();
|
|
||||||
sem.post();
|
|
||||||
});
|
|
||||||
if(flag){
|
|
||||||
sem.wait();
|
|
||||||
}
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
bool sync_first(T &&task) {
|
|
||||||
semaphore sem;
|
|
||||||
bool flag = async_first([&]() {
|
|
||||||
task();
|
|
||||||
sem.post();
|
|
||||||
});
|
|
||||||
if (flag) {
|
|
||||||
sem.wait();
|
|
||||||
}
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
//同步等待线程池执行完所有任务并退出
|
|
||||||
void wait() {
|
|
||||||
exit();
|
|
||||||
my_thread_group.join_all();
|
|
||||||
}
|
|
||||||
uint64_t size() const{
|
|
||||||
return my_queue.size();
|
|
||||||
}
|
|
||||||
static ThreadPool &Instance() {
|
|
||||||
//单例模式
|
|
||||||
static ThreadPool instance(thread::hardware_concurrency());
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
static bool setPriority(Priority _priority = PRIORITY_NORMAL,
|
|
||||||
thread::native_handle_type threadId = 0) {
|
|
||||||
// set priority
|
|
||||||
#if defined(_WIN32)
|
|
||||||
static int Priorities[] = { THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST };
|
|
||||||
if (_priority != PRIORITY_NORMAL && SetThreadPriority(GetCurrentThread(), Priorities[_priority]) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
static int Min = sched_get_priority_min(SCHED_OTHER);
|
|
||||||
if (Min == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
static int Max = sched_get_priority_max(SCHED_OTHER);
|
|
||||||
if (Max == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
static int Priorities[] = { Min, Min + (Max - Min) / 4, Min
|
|
||||||
+ (Max - Min) / 2, Min + (Max - Min) / 4, Max };
|
|
||||||
|
|
||||||
if (threadId == 0) {
|
|
||||||
threadId = pthread_self();
|
|
||||||
}
|
|
||||||
struct sched_param params;
|
|
||||||
params.sched_priority = Priorities[_priority];
|
|
||||||
return pthread_setschedparam(threadId, SCHED_OTHER, ¶ms) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
TaskQueue my_queue;
|
|
||||||
thread_group my_thread_group;
|
|
||||||
int thread_num;
|
|
||||||
volatile bool avaible;
|
|
||||||
Priority priority;
|
|
||||||
//发送空任务至任务列队,通知线程主动退出
|
|
||||||
void exit() {
|
|
||||||
avaible = false;
|
|
||||||
my_queue.push_exit(thread_num);
|
|
||||||
}
|
|
||||||
void start() {
|
|
||||||
if (thread_num <= 0)
|
|
||||||
return;
|
|
||||||
for (int i = 0; i < thread_num; ++i) {
|
|
||||||
my_thread_group.create_thread(bind(&ThreadPool::run, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void run() {
|
|
||||||
ThreadPool::setPriority(priority);
|
|
||||||
function<void(void)> task;
|
|
||||||
while (true) {
|
|
||||||
if (my_queue.get_task(task)) {
|
|
||||||
try {
|
|
||||||
task();
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
FatalL << ex.what();
|
|
||||||
}
|
|
||||||
task = nullptr;
|
|
||||||
} else {
|
|
||||||
//空任务,退出线程
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
#endif /* THREADPOOL_H_ */
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorkThreadPool.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月30日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_WORKTHREADPOOL_H_
|
|
||||||
#define UTIL_WORKTHREADPOOL_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
|
||||||
#include <atomic>
|
|
||||||
#include <iostream>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "ThreadPool.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
class WorkThreadPool {
|
|
||||||
public:
|
|
||||||
WorkThreadPool(int threadnum = thread::hardware_concurrency());
|
|
||||||
virtual ~WorkThreadPool();
|
|
||||||
std::shared_ptr<ThreadPool> &getWorkThread();
|
|
||||||
static WorkThreadPool &Instance() {
|
|
||||||
static WorkThreadPool *intance(new WorkThreadPool());
|
|
||||||
return *intance;
|
|
||||||
}
|
|
||||||
static void Destory(){
|
|
||||||
delete &(WorkThreadPool::Instance());
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int threadnum;
|
|
||||||
atomic<int> threadPos;
|
|
||||||
vector <std::shared_ptr<ThreadPool> > threads;
|
|
||||||
void wait();
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_WORKTHREADPOOL_H_ */
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* rwmutex.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年1月27日
|
|
||||||
* Author: 熊子良
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_RWMUTEX_H_
|
|
||||||
#define UTIL_RWMUTEX_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
class rw_mutex {
|
|
||||||
public:
|
|
||||||
rw_mutex() :
|
|
||||||
reader_cnt(0) {
|
|
||||||
}
|
|
||||||
void lock(bool write_mode = true) {
|
|
||||||
if (write_mode) {
|
|
||||||
//write thread
|
|
||||||
mtx_write.lock();
|
|
||||||
} else {
|
|
||||||
// read thread
|
|
||||||
lock_guard<mutex> lck(mtx_reader);
|
|
||||||
if (reader_cnt++ == 0) {
|
|
||||||
mtx_write.lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void unlock(bool write_mode = true) {
|
|
||||||
if (write_mode) {
|
|
||||||
//write thread
|
|
||||||
mtx_write.unlock();
|
|
||||||
} else {
|
|
||||||
// read thread
|
|
||||||
lock_guard<mutex> lck(mtx_reader);
|
|
||||||
if (--reader_cnt == 0) {
|
|
||||||
mtx_write.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual ~rw_mutex() {
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
mutex mtx_write;
|
|
||||||
mutex mtx_reader;
|
|
||||||
int reader_cnt;
|
|
||||||
};
|
|
||||||
class lock_guard_rw {
|
|
||||||
public:
|
|
||||||
lock_guard_rw(rw_mutex &_mtx, bool _write_mode = true) :
|
|
||||||
mtx(_mtx), write_mode(_write_mode) {
|
|
||||||
mtx.lock(write_mode);
|
|
||||||
}
|
|
||||||
virtual ~lock_guard_rw() {
|
|
||||||
mtx.unlock(write_mode);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
rw_mutex &mtx;
|
|
||||||
bool write_mode;
|
|
||||||
};
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_RWMUTEX_H_ */
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* semaphore.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年8月14日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SEMAPHORE_H_
|
|
||||||
#define SEMAPHORE_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 目前发现信号量在32位的系统上有问题,
|
|
||||||
* 休眠的线程无法被正常唤醒,先禁用之
|
|
||||||
#if defined(__linux__)
|
|
||||||
#include <semaphore.h>
|
|
||||||
#define HAVE_SEM
|
|
||||||
#endif //HAVE_SEM
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
#include <condition_variable>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
class semaphore {
|
|
||||||
public:
|
|
||||||
explicit semaphore(unsigned int initial = 0) {
|
|
||||||
#if defined(HAVE_SEM)
|
|
||||||
sem_init(&sem, 0, initial);
|
|
||||||
#else
|
|
||||||
count_ = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
~semaphore() {
|
|
||||||
#if defined(HAVE_SEM)
|
|
||||||
sem_destroy(&sem);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void post(unsigned int n = 1) {
|
|
||||||
#if defined(HAVE_SEM)
|
|
||||||
while (n--) {
|
|
||||||
sem_post(&sem);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
unique_lock<mutex> lock(mutex_);
|
|
||||||
count_ += n;
|
|
||||||
while (n--) {
|
|
||||||
condition_.notify_one();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
void wait() {
|
|
||||||
#if defined(HAVE_SEM)
|
|
||||||
sem_wait(&sem);
|
|
||||||
#else
|
|
||||||
unique_lock<mutex> lock(mutex_);
|
|
||||||
while (count_ == 0) {
|
|
||||||
condition_.wait(lock);
|
|
||||||
}
|
|
||||||
--count_;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
#if defined(HAVE_SEM)
|
|
||||||
sem_t sem;
|
|
||||||
#else
|
|
||||||
atomic_uint count_;
|
|
||||||
mutex mutex_;
|
|
||||||
condition_variable_any condition_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
#endif /* SEMAPHORE_H_ */
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* spinmutex.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年3月31日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_THREAD_SPIN_MUTEX_H_
|
|
||||||
#define SRC_THREAD_SPIN_MUTEX_H_
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
|
|
||||||
class spin_mutex {
|
|
||||||
std::atomic_flag flag = ATOMIC_FLAG_INIT;
|
|
||||||
public:
|
|
||||||
spin_mutex() = default;
|
|
||||||
spin_mutex(const spin_mutex&) = delete;
|
|
||||||
spin_mutex& operator= (const spin_mutex&) = delete;
|
|
||||||
void lock() {
|
|
||||||
while(flag.test_and_set(std::memory_order_acquire)) ;
|
|
||||||
}
|
|
||||||
void unlock() {
|
|
||||||
flag.clear(std::memory_order_release);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
typedef mutex spin_mutex;
|
|
||||||
#endif //__ARM_ARCH
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_THREAD_SPIN_MUTEX_H_ */
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* threadgroup.h
|
|
||||||
*
|
|
||||||
* Created on: 2014-6-23
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef THREADGROUP_H_
|
|
||||||
#define THREADGROUP_H_
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Thread {
|
|
||||||
|
|
||||||
class thread_group {
|
|
||||||
private:
|
|
||||||
thread_group(thread_group const&);
|
|
||||||
thread_group& operator=(thread_group const&);
|
|
||||||
public:
|
|
||||||
thread_group() {
|
|
||||||
}
|
|
||||||
~thread_group() {
|
|
||||||
for (auto &th : threads) {
|
|
||||||
delete th.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_this_thread_in() {
|
|
||||||
auto it = threads.find(this_thread::get_id());
|
|
||||||
return it != threads.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_thread_in(thread* thrd) {
|
|
||||||
if (thrd) {
|
|
||||||
auto it = threads.find(thrd->get_id());
|
|
||||||
return it != threads.end();
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename F>
|
|
||||||
thread* create_thread(F threadfunc) {
|
|
||||||
thread *new_thread=new thread(threadfunc);
|
|
||||||
threads[new_thread->get_id()] = new_thread;
|
|
||||||
return new_thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_thread(thread* thrd) {
|
|
||||||
if (thrd) {
|
|
||||||
if (is_thread_in(thrd)) {
|
|
||||||
throw runtime_error(
|
|
||||||
"thread_group: trying to add a duplicated thread");
|
|
||||||
}
|
|
||||||
threads[thrd->get_id()] = thrd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_thread(thread* thrd) {
|
|
||||||
auto it = threads.find(thrd->get_id());
|
|
||||||
if (it != threads.end()) {
|
|
||||||
threads.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void join_all() {
|
|
||||||
if (is_this_thread_in()) {
|
|
||||||
throw runtime_error("thread_group: trying joining itself");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto &it : threads) {
|
|
||||||
if (it.second->joinable()) {
|
|
||||||
it.second->join(); //等待线程主动退出
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t size() {
|
|
||||||
return threads.size();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
unordered_map<thread::id, thread*> threads;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Thread */
|
|
||||||
} /* namespace ZL */
|
|
||||||
#endif /* THREADGROUP_H_ */
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* File.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月22日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_UTIL_FILE_H_
|
|
||||||
#define SRC_UTIL_FILE_H_
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#pragma comment (lib,"WS2_32")
|
|
||||||
#endif // WIN32
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX 256
|
|
||||||
#endif // !PATH_MAX
|
|
||||||
|
|
||||||
struct dirent{
|
|
||||||
long d_ino; /* inode number*/
|
|
||||||
off_t d_off; /* offset to this dirent*/
|
|
||||||
unsigned short d_reclen; /* length of this d_name*/
|
|
||||||
unsigned char d_type; /* the type of d_name*/
|
|
||||||
char d_name[1]; /* file name (null-terminated)*/
|
|
||||||
};
|
|
||||||
typedef struct _dirdesc {
|
|
||||||
int dd_fd; /** file descriptor associated with directory */
|
|
||||||
long dd_loc; /** offset in current buffer */
|
|
||||||
long dd_size; /** amount of data returned by getdirentries */
|
|
||||||
char *dd_buf; /** data buffer */
|
|
||||||
int dd_len; /** size of data buffer */
|
|
||||||
long dd_seek; /** magic cookie returned by getdirentries */
|
|
||||||
HANDLE handle;
|
|
||||||
struct dirent *index;
|
|
||||||
} DIR;
|
|
||||||
# define __dirfd(dp) ((dp)->dd_fd)
|
|
||||||
|
|
||||||
int mkdir(const char *path, int mode);
|
|
||||||
DIR *opendir(const char *);
|
|
||||||
int closedir(DIR *);
|
|
||||||
struct dirent *readdir(DIR *);
|
|
||||||
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class File {
|
|
||||||
public:
|
|
||||||
// 可读普通文件
|
|
||||||
static bool isrfile(const char *path) ;
|
|
||||||
//新建文件,目录文件夹自动生成
|
|
||||||
static bool createfile_path(const char *file, unsigned int mod);
|
|
||||||
static FILE *createfile_file(const char *file,const char *mode);
|
|
||||||
//判断是否为目录
|
|
||||||
static bool is_dir(const char *path) ;
|
|
||||||
//判断是否为常规文件
|
|
||||||
static bool is_file(const char *path) ;
|
|
||||||
//判断是否是特殊目录(. or ..)
|
|
||||||
static bool is_special_dir(const char *path);
|
|
||||||
//删除目录或文件
|
|
||||||
static void delete_file(const char *path) ;
|
|
||||||
static bool rm_empty_dir(const char *path);
|
|
||||||
private:
|
|
||||||
File();
|
|
||||||
virtual ~File();
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_UTIL_FILE_H_ */
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* MD5.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月23日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_UTIL_MD5_H_
|
|
||||||
#define SRC_UTIL_MD5_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
// a small class for calculating MD5 hashes of strings or byte arrays
|
|
||||||
// it is not meant to be fast or secure
|
|
||||||
//
|
|
||||||
// usage: 1) feed it blocks of uchars with update()
|
|
||||||
// 2) finalize()
|
|
||||||
// 3) get hexdigest() string
|
|
||||||
// or
|
|
||||||
// MD5(std::string).hexdigest()
|
|
||||||
//
|
|
||||||
// assumes that char is 8 bit and int is 32 bit
|
|
||||||
class MD5
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef unsigned int size_type; // must be 32bit
|
|
||||||
|
|
||||||
MD5();
|
|
||||||
MD5(const std::string& text);
|
|
||||||
void update(const unsigned char *buf, size_type length);
|
|
||||||
void update(const char *buf, size_type length);
|
|
||||||
MD5& finalize();
|
|
||||||
std::string hexdigest() const;
|
|
||||||
friend std::ostream& operator<<(std::ostream&, MD5 md5);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
typedef uint8_t uint1; // 8bit
|
|
||||||
typedef uint32_t uint4; // 32bit
|
|
||||||
enum {blocksize = 64}; // VC6 won't eat a const static int here
|
|
||||||
|
|
||||||
void transform(const uint1 block[blocksize]);
|
|
||||||
static void decode(uint4 output[], const uint1 input[], size_type len);
|
|
||||||
static void encode(uint1 output[], const uint4 input[], size_type len);
|
|
||||||
|
|
||||||
bool finalized;
|
|
||||||
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
|
|
||||||
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
|
|
||||||
uint4 state[4]; // digest so far
|
|
||||||
uint1 digest[16]; // the result
|
|
||||||
|
|
||||||
// low level logic operations
|
|
||||||
static inline uint4 F(uint4 x, uint4 y, uint4 z);
|
|
||||||
static inline uint4 G(uint4 x, uint4 y, uint4 z);
|
|
||||||
static inline uint4 H(uint4 x, uint4 y, uint4 z);
|
|
||||||
static inline uint4 I(uint4 x, uint4 y, uint4 z);
|
|
||||||
static inline uint4 rotate_left(uint4 x, int n);
|
|
||||||
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
|
||||||
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
|
||||||
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
|
||||||
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_UTIL_MD5_H_ */
|
|
@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* NoticeCenter.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年2月17日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_UTIL_NOTICECENTER_H_
|
|
||||||
#define SRC_UTIL_NOTICECENTER_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <exception>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "function_traits.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
|
|
||||||
class NoticeCenter {
|
|
||||||
public:
|
|
||||||
class InterruptException : public std::runtime_error
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
InterruptException():std::runtime_error("InterruptException"){}
|
|
||||||
virtual ~InterruptException(){}
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~NoticeCenter(){}
|
|
||||||
static NoticeCenter &Instance(){
|
|
||||||
static NoticeCenter instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
template<typename ...ArgsType>
|
|
||||||
bool emitEvent(const char *strEvent,ArgsType &&...args){
|
|
||||||
lock_guard<recursive_mutex> lck(_mtxListener);
|
|
||||||
auto it0 = _mapListener.find(strEvent);
|
|
||||||
if (it0 == _mapListener.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for(auto &pr : it0->second){
|
|
||||||
typedef function<void(ArgsType &&...)> funType;
|
|
||||||
funType *obj = (funType *)(pr.second.get());
|
|
||||||
try{
|
|
||||||
(*obj)(std::forward<ArgsType>(args)...);
|
|
||||||
}catch(InterruptException &ex){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return it0->second.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename FUN>
|
|
||||||
void addListener(void *tag, const char *strEvent, const FUN &fun) {
|
|
||||||
typedef typename function_traits<FUN>::stl_function_type funType;
|
|
||||||
std::shared_ptr<void> pListener(new funType(fun), [](void *ptr) {
|
|
||||||
funType *obj = (funType *)ptr;
|
|
||||||
delete obj;
|
|
||||||
});
|
|
||||||
lock_guard<recursive_mutex> lck(_mtxListener);
|
|
||||||
_mapListener[strEvent][tag] = pListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void delListener(void *tag,const char *strEvent){
|
|
||||||
lock_guard<recursive_mutex> lck(_mtxListener);
|
|
||||||
auto it = _mapListener.find(strEvent);
|
|
||||||
if(it == _mapListener.end()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
it->second.erase(tag);
|
|
||||||
if(it->second.empty()){
|
|
||||||
_mapListener.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void delListener(void *tag){
|
|
||||||
lock_guard<recursive_mutex> lck(_mtxListener);
|
|
||||||
for(auto it = _mapListener.begin();it != _mapListener.end();){
|
|
||||||
it->second.erase(tag);
|
|
||||||
if(it->second.empty()){
|
|
||||||
it = _mapListener.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
NoticeCenter(){}
|
|
||||||
recursive_mutex _mtxListener;
|
|
||||||
unordered_map<string,unordered_map<void *,std::shared_ptr<void> > > _mapListener;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_UTIL_NOTICECENTER_H_ */
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* ResourcePool.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月29日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_RECYCLEPOOL_H_
|
|
||||||
#define UTIL_RECYCLEPOOL_H_
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <deque>
|
|
||||||
#include <memory>
|
|
||||||
#include <atomic>
|
|
||||||
#include <functional>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
template<typename C, int poolSize = 10>
|
|
||||||
class ResourcePool {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<C> ValuePtr;
|
|
||||||
ResourcePool() {
|
|
||||||
pool.reset(new _ResourcePool());
|
|
||||||
}
|
|
||||||
#if (!defined(__GNUC__)) || (__GNUC__ >= 5)
|
|
||||||
template<typename ...ArgTypes>
|
|
||||||
ResourcePool(ArgTypes &&...args) {
|
|
||||||
pool.reset(new _ResourcePool(std::forward<ArgTypes>(args)...));
|
|
||||||
}
|
|
||||||
#endif //(!defined(__GNUC__)) || (__GNUC__ >= 5)
|
|
||||||
void reSize(int size) {
|
|
||||||
pool->setSize(size);
|
|
||||||
}
|
|
||||||
ValuePtr obtain() {
|
|
||||||
return pool->obtain();
|
|
||||||
}
|
|
||||||
void quit(const ValuePtr &ptr) {
|
|
||||||
pool->quit(ptr);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
|
|
||||||
class _ResourcePool: public enable_shared_from_this<_ResourcePool> {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<C> ValuePtr;
|
|
||||||
_ResourcePool() {
|
|
||||||
poolsize = poolSize;
|
|
||||||
allotter = []()->C* {
|
|
||||||
return new C();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#if (!defined(__GNUC__)) || (__GNUC__ >= 5)
|
|
||||||
template<typename ...ArgTypes>
|
|
||||||
_ResourcePool(ArgTypes &&...args) {
|
|
||||||
poolsize = poolSize;
|
|
||||||
allotter = [args...]()->C* {
|
|
||||||
return new C(args...);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif //(!defined(__GNUC__)) || (__GNUC__ >= 5)
|
|
||||||
virtual ~_ResourcePool(){
|
|
||||||
std::lock_guard<mutex> lck(_mutex);
|
|
||||||
for(auto &ptr : objs){
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setSize(int size) {
|
|
||||||
poolsize = size;
|
|
||||||
}
|
|
||||||
ValuePtr obtain() {
|
|
||||||
std::lock_guard<mutex> lck(_mutex);
|
|
||||||
C *ptr = nullptr;
|
|
||||||
if (objs.size() == 0) {
|
|
||||||
ptr = allotter();
|
|
||||||
} else {
|
|
||||||
ptr = objs.front();
|
|
||||||
objs.pop_front();
|
|
||||||
}
|
|
||||||
return ValuePtr(ptr, Deleter(this->shared_from_this()));
|
|
||||||
}
|
|
||||||
void quit(const ValuePtr &ptr) {
|
|
||||||
std::lock_guard<mutex> lck(_mutex);
|
|
||||||
quitSet.emplace(ptr.get());
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
class Deleter {
|
|
||||||
public:
|
|
||||||
Deleter(const std::shared_ptr<_ResourcePool> &pool) {
|
|
||||||
weakPool = pool;
|
|
||||||
}
|
|
||||||
void operator()(C *ptr) {
|
|
||||||
auto strongPool = weakPool.lock();
|
|
||||||
if (strongPool) {
|
|
||||||
strongPool->recycle(ptr);
|
|
||||||
} else {
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
weak_ptr<_ResourcePool> weakPool;
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
void recycle(C *obj) {
|
|
||||||
std::lock_guard<mutex> lck(_mutex);
|
|
||||||
auto it = quitSet.find(obj);
|
|
||||||
if (it != quitSet.end()) {
|
|
||||||
delete obj;
|
|
||||||
quitSet.erase(it);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((int)objs.size() >= poolsize) {
|
|
||||||
delete obj;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
objs.push_back(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
deque<C*> objs;
|
|
||||||
unordered_set<C*> quitSet;
|
|
||||||
function<C*(void)> allotter;
|
|
||||||
mutex _mutex;
|
|
||||||
int poolsize;
|
|
||||||
};
|
|
||||||
std::shared_ptr<_ResourcePool> pool;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace util */
|
|
||||||
} /* namespace im */
|
|
||||||
|
|
||||||
#endif /* UTIL_RECYCLEPOOL_H_ */
|
|
@ -1,244 +0,0 @@
|
|||||||
/*
|
|
||||||
* RingBuffer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_RINGBUFFER_H_
|
|
||||||
#define UTIL_RINGBUFFER_H_
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
//实现了一个一写多读得环形缓冲的模板类
|
|
||||||
template<typename T> class RingBuffer: public enable_shared_from_this<
|
|
||||||
RingBuffer<T> > {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<RingBuffer> Ptr;
|
|
||||||
|
|
||||||
class RingReader {
|
|
||||||
public:
|
|
||||||
friend class RingBuffer;
|
|
||||||
typedef std::shared_ptr<RingReader> Ptr;
|
|
||||||
RingReader(const std::shared_ptr<RingBuffer> &_buffer,bool _useBuffer) {
|
|
||||||
buffer = _buffer;
|
|
||||||
curpos = _buffer->ringKeyPos;
|
|
||||||
useBuffer = _useBuffer;
|
|
||||||
}
|
|
||||||
virtual ~RingReader() {
|
|
||||||
auto strongBuffer = buffer.lock();
|
|
||||||
if (strongBuffer) {
|
|
||||||
strongBuffer->release(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//重新定位读取器至最新的数据位置
|
|
||||||
void reset(bool keypos = true) {
|
|
||||||
auto strongBuffer = buffer.lock();
|
|
||||||
if (strongBuffer) {
|
|
||||||
if(keypos){
|
|
||||||
curpos = strongBuffer->ringKeyPos; //定位读取器
|
|
||||||
}else{
|
|
||||||
curpos = strongBuffer->ringPos; //定位读取器
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setReadCB(const function<void(const T &)> &cb) {
|
|
||||||
lock_guard<recursive_mutex> lck(mtxCB);
|
|
||||||
readCB = cb;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
void setDetachCB(const function<void()> &cb) {
|
|
||||||
lock_guard<recursive_mutex> lck(mtxCB);
|
|
||||||
if (!cb) {
|
|
||||||
detachCB = []() {};
|
|
||||||
} else {
|
|
||||||
detachCB = cb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const T* read(){
|
|
||||||
auto strongBuffer=buffer.lock();
|
|
||||||
if(!strongBuffer){
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return read(strongBuffer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void onRead(const T &data) {
|
|
||||||
lock_guard<recursive_mutex> lck(mtxCB);
|
|
||||||
if(!readCB){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!useBuffer){
|
|
||||||
readCB(data);
|
|
||||||
}else{
|
|
||||||
const T *pkt = nullptr;
|
|
||||||
while((pkt = read())){
|
|
||||||
readCB(*pkt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void onDetach() const {
|
|
||||||
lock_guard<recursive_mutex> lck(mtxCB);
|
|
||||||
detachCB();
|
|
||||||
}
|
|
||||||
//读环形缓冲
|
|
||||||
const T *read(RingBuffer *ring) {
|
|
||||||
if (curpos == ring->ringPos) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
const T *data = &(ring->dataRing[curpos]); //返回包
|
|
||||||
curpos = ring->next(curpos); //更新位置
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function<void(const T &)> readCB ;
|
|
||||||
function<void(void)> detachCB = []() {};
|
|
||||||
weak_ptr<RingBuffer> buffer;
|
|
||||||
mutable recursive_mutex mtxCB;
|
|
||||||
int curpos;
|
|
||||||
bool useBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
friend class RingReader;
|
|
||||||
RingBuffer(int size = 0) {
|
|
||||||
if(size <= 0){
|
|
||||||
size = 32;
|
|
||||||
canReSize = true;
|
|
||||||
}
|
|
||||||
ringSize = size;
|
|
||||||
dataRing = new T[ringSize];
|
|
||||||
ringPos = 0;
|
|
||||||
ringKeyPos = 0;
|
|
||||||
}
|
|
||||||
virtual ~RingBuffer() {
|
|
||||||
decltype(readerMap) mapCopy;
|
|
||||||
{
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
mapCopy.swap(readerMap);
|
|
||||||
}
|
|
||||||
for (auto &pr : mapCopy) {
|
|
||||||
auto reader = pr.second.lock();
|
|
||||||
if(reader){
|
|
||||||
reader->onDetach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete[] dataRing;
|
|
||||||
}
|
|
||||||
#if defined(ENABLE_RING_USEBUF)
|
|
||||||
std::shared_ptr<RingReader> attach(bool useBuffer = true) {
|
|
||||||
#else //ENABLE_RING_USEBUF
|
|
||||||
std::shared_ptr<RingReader> attach(bool useBuffer = false) {
|
|
||||||
#endif //ENABLE_RING_USEBUF
|
|
||||||
|
|
||||||
std::shared_ptr<RingReader> ptr(new RingReader(this->shared_from_this(),useBuffer));
|
|
||||||
std::weak_ptr<RingReader> weakPtr = ptr;
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
readerMap.emplace(ptr.get(),weakPtr);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
//写环形缓冲,非线程安全的
|
|
||||||
void write(const T &in,bool isKey = true) {
|
|
||||||
computeBestSize(isKey);
|
|
||||||
dataRing[ringPos] = in;
|
|
||||||
if (isKey) {
|
|
||||||
ringKeyPos = ringPos; //设置读取器可以定位的点
|
|
||||||
}
|
|
||||||
ringPos = next(ringPos);
|
|
||||||
decltype(readerMap) mapCopy;
|
|
||||||
{
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
mapCopy = readerMap;
|
|
||||||
}
|
|
||||||
for (auto &pr : mapCopy) {
|
|
||||||
auto reader = pr.second.lock();
|
|
||||||
if(reader){
|
|
||||||
reader->onRead(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int readerCount(){
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
return readerMap.size();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
T *dataRing;
|
|
||||||
int ringPos;
|
|
||||||
int ringKeyPos;
|
|
||||||
int ringSize;
|
|
||||||
//计算最佳环形缓存大小的参数
|
|
||||||
int besetSize = 0;
|
|
||||||
int totalCnt = 0;
|
|
||||||
int lastKeyCnt = 0;
|
|
||||||
bool canReSize = false;
|
|
||||||
|
|
||||||
recursive_mutex mtx_reader;
|
|
||||||
unordered_map<void *,std::weak_ptr<RingReader> > readerMap;
|
|
||||||
|
|
||||||
inline int next(int pos) {
|
|
||||||
//读取器下一位置
|
|
||||||
if (pos > ringSize - 2) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return pos + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void release(RingReader *reader) {
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
readerMap.erase(reader);
|
|
||||||
}
|
|
||||||
void computeBestSize(bool isKey){
|
|
||||||
if(!canReSize || besetSize){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
totalCnt++;
|
|
||||||
if(!isKey){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//关键帧
|
|
||||||
if(lastKeyCnt){
|
|
||||||
//计算两个I帧之间的包个数
|
|
||||||
besetSize = totalCnt - lastKeyCnt;
|
|
||||||
reSize();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastKeyCnt = totalCnt;
|
|
||||||
}
|
|
||||||
void reSize(){
|
|
||||||
ringSize = besetSize;
|
|
||||||
delete [] dataRing;
|
|
||||||
dataRing = new T[ringSize];
|
|
||||||
ringPos = 0;
|
|
||||||
ringKeyPos = 0;
|
|
||||||
|
|
||||||
decltype(readerMap) mapCopy;
|
|
||||||
{
|
|
||||||
lock_guard<recursive_mutex> lck(mtx_reader);
|
|
||||||
mapCopy = readerMap;
|
|
||||||
}
|
|
||||||
for (auto &pr : mapCopy) {
|
|
||||||
auto reader = pr.second.lock();
|
|
||||||
if(reader){
|
|
||||||
reader->reset(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_RINGBUFFER_H_ */
|
|
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* SSLServer.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年1月11日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CRYPTO_SSLBOX_H_
|
|
||||||
#define CRYPTO_SSLBOX_H_
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <openssl/bio.h>
|
|
||||||
#include <openssl/ossl_typ.h>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <atomic>
|
|
||||||
#include <functional>
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#if defined(_WIN64)
|
|
||||||
|
|
||||||
//64bit
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
#pragma comment (lib,"libssl64MDd")
|
|
||||||
#pragma comment (lib,"libcrypto64MDd")
|
|
||||||
#else
|
|
||||||
#pragma comment (lib,"libssl64MD")
|
|
||||||
#pragma comment (lib,"libcrypto64MD")
|
|
||||||
#endif // defined(_DEBUG)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
//32 bit
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
#pragma comment (lib,"libssl32MDd")
|
|
||||||
#pragma comment (lib,"libcrypto32MDd")
|
|
||||||
#else
|
|
||||||
#pragma comment (lib,"libssl32MD")
|
|
||||||
#pragma comment (lib,"libcrypto32MD")
|
|
||||||
#endif // defined(_DEBUG)
|
|
||||||
|
|
||||||
#endif //defined(_WIN64)
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class SSL_Initor {
|
|
||||||
public:
|
|
||||||
friend class SSL_Box;
|
|
||||||
static SSL_Initor &Instance() {
|
|
||||||
static SSL_Initor obj;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
void loadServerPem(const char *keyAndCA_pem, const char *import_pwd = "");
|
|
||||||
void loadClientPem(const char *keyAndCA_pem, const char *import_pwd = "");
|
|
||||||
private:
|
|
||||||
static mutex *_mutexes;
|
|
||||||
SSL_CTX *ssl_server;
|
|
||||||
SSL_CTX *ssl_client;
|
|
||||||
SSL_Initor();
|
|
||||||
~SSL_Initor();
|
|
||||||
void setCtx(SSL_CTX *ctx);
|
|
||||||
void loadPem(SSL_CTX *ctx, const char *keyAndCA_pem,const char *import_pwd);
|
|
||||||
inline std::string getLastError();
|
|
||||||
}
|
|
||||||
;
|
|
||||||
class SSL_Box {
|
|
||||||
public:
|
|
||||||
SSL_Box(bool isServer = true, bool enable = true);
|
|
||||||
virtual ~SSL_Box();
|
|
||||||
|
|
||||||
//收到密文后,调用此函数解密
|
|
||||||
void onRecv(const char *data, uint32_t data_len);
|
|
||||||
//需要加密明文调用此函数
|
|
||||||
void onSend(const char *data, uint32_t data_len);
|
|
||||||
|
|
||||||
//设置解密后获取明文的回调
|
|
||||||
template<typename F>
|
|
||||||
void setOnDecData(F &&fun) {
|
|
||||||
onDec = fun;
|
|
||||||
}
|
|
||||||
|
|
||||||
//设置加密后获取密文的回调
|
|
||||||
template<typename F>
|
|
||||||
void setOnEncData(F &&fun) {
|
|
||||||
onEnc = fun;
|
|
||||||
}
|
|
||||||
void shutdown();
|
|
||||||
private:
|
|
||||||
bool isServer;
|
|
||||||
bool enable;
|
|
||||||
bool sendHandshake;
|
|
||||||
SSL *ssl;
|
|
||||||
BIO *read_bio, *write_bio;
|
|
||||||
function<void(const char *data, uint32_t len)> onDec;
|
|
||||||
function<void(const char *data, uint32_t len)> onEnc;
|
|
||||||
std::string _bufferOut;
|
|
||||||
void flush();
|
|
||||||
void flushWriteBio(char *buf, int bufsize);
|
|
||||||
void flushReadBio(char *buf, int bufsize);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* CRYPTO_SSLBOX_H_ */
|
|
@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* SqlConnection.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月29日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SQL_SQLCONNECTION_H_
|
|
||||||
#define SQL_SQLCONNECTION_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include "Util/logger.h"
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <mysql.h>
|
|
||||||
#pragma comment (lib,"libmysql")
|
|
||||||
#else
|
|
||||||
#include <mysql/mysql.h>
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class SqlConnection {
|
|
||||||
public:
|
|
||||||
SqlConnection(const string &url, unsigned short port, const string &dbname,
|
|
||||||
const string &user, const string &password,const string &character = "utf8mb4");
|
|
||||||
virtual ~SqlConnection();
|
|
||||||
|
|
||||||
template<typename ...Args>
|
|
||||||
int64_t query(int64_t &rowId, const char *fmt, Args && ...arg) {
|
|
||||||
check();
|
|
||||||
string tmp = queryString(fmt, std::forward<Args>(arg)...);
|
|
||||||
if (mysql_query(&sql, tmp.c_str())) {
|
|
||||||
WarnL << mysql_error(&sql) << ":" << tmp << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t query(int64_t &rowId,const char *str) {
|
|
||||||
check();
|
|
||||||
if (mysql_query(&sql, str)) {
|
|
||||||
WarnL << mysql_error(&sql) << ":" << str << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
template<typename ...Args>
|
|
||||||
int64_t query(int64_t &rowId,vector<vector<string>> &ret, const char *fmt,
|
|
||||||
Args && ...arg) {
|
|
||||||
check();
|
|
||||||
string tmp = queryString(fmt, std::forward<Args>(arg)...);
|
|
||||||
if (mysql_query(&sql, tmp.c_str())) {
|
|
||||||
WarnL << mysql_error(&sql) << ":" << tmp << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ret.clear();
|
|
||||||
MYSQL_RES *res = mysql_store_result(&sql);
|
|
||||||
if (!res) {
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
MYSQL_ROW row;
|
|
||||||
unsigned int column = mysql_num_fields(res);
|
|
||||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
|
||||||
ret.emplace_back();
|
|
||||||
auto &back = ret.back();
|
|
||||||
for (unsigned int i = 0; i < column; i++) {
|
|
||||||
back.emplace_back(row[i] ? row[i] : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mysql_free_result(res);
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
int64_t query(int64_t &rowId,vector<vector<string>> &ret, const char *str) {
|
|
||||||
check();
|
|
||||||
if (mysql_query(&sql, str)) {
|
|
||||||
WarnL << mysql_error(&sql) << ":" << str << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ret.clear();
|
|
||||||
MYSQL_RES *res = mysql_store_result(&sql);
|
|
||||||
if (!res) {
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
MYSQL_ROW row;
|
|
||||||
unsigned int column = mysql_num_fields(res);
|
|
||||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
|
||||||
ret.emplace_back();
|
|
||||||
auto &back = ret.back();
|
|
||||||
for (unsigned int i = 0; i < column; i++) {
|
|
||||||
back.emplace_back(row[i] ? row[i] : "" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mysql_free_result(res);
|
|
||||||
rowId=mysql_insert_id(&sql);
|
|
||||||
return mysql_affected_rows(&sql);
|
|
||||||
}
|
|
||||||
template<typename ...Args>
|
|
||||||
static string queryString(const char *fmt, Args && ...arg) {
|
|
||||||
char *ptr_out = NULL;
|
|
||||||
asprintf(&ptr_out, fmt, arg...);
|
|
||||||
string ret(ptr_out);
|
|
||||||
if (ptr_out) {
|
|
||||||
free(ptr_out);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static string queryString(const char *fmt) {
|
|
||||||
return fmt;
|
|
||||||
}
|
|
||||||
string &escape(string &str) {
|
|
||||||
char *out = new char[str.length() * 2 + 1];
|
|
||||||
mysql_real_escape_string(&sql, out, str.c_str(), str.size());
|
|
||||||
str.assign(out);
|
|
||||||
delete [] out;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MYSQL sql;
|
|
||||||
inline void check() {
|
|
||||||
if (mysql_ping(&sql) != 0) {
|
|
||||||
throw runtime_error("MYSQL连接异常!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
#endif /* SQL_SQLCONNECTION_H_ */
|
|
@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
* SqlPool.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年10月29日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SQL_SQLPOOL_H_
|
|
||||||
#define SQL_SQLPOOL_H_
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <sstream>
|
|
||||||
#include <functional>
|
|
||||||
#include "logger.h"
|
|
||||||
#include "SqlConnection.h"
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
#include "Util/ResourcePool.h"
|
|
||||||
#include "Thread/AsyncTaskThread.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
template<int poolSize = 10>
|
|
||||||
class _SqlPool {
|
|
||||||
public:
|
|
||||||
typedef ResourcePool<SqlConnection, poolSize> PoolType;
|
|
||||||
typedef vector<vector<string> > SqlRetType;
|
|
||||||
static _SqlPool &Instance() {
|
|
||||||
static _SqlPool *pool(new _SqlPool());
|
|
||||||
return *pool;
|
|
||||||
}
|
|
||||||
static void Destory(){
|
|
||||||
delete &Instance();
|
|
||||||
}
|
|
||||||
void reSize(int size) {
|
|
||||||
if (size < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
poolsize = size;
|
|
||||||
pool->reSize(size);
|
|
||||||
threadPool.reset(new ThreadPool(poolsize));
|
|
||||||
}
|
|
||||||
template<typename ...Args>
|
|
||||||
void Init(Args && ...arg) {
|
|
||||||
pool.reset(new PoolType(std::forward<Args>(arg)...));
|
|
||||||
pool->obtain();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ...Args>
|
|
||||||
int64_t query(const char *fmt, Args && ...arg) {
|
|
||||||
string sql = SqlConnection::queryString(fmt, std::forward<Args>(arg)...);
|
|
||||||
doQuery(sql);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int64_t query(const string &sql) {
|
|
||||||
doQuery(sql);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ...Args>
|
|
||||||
int64_t query(int64_t &rowID,vector<vector<string>> &ret, const char *fmt,
|
|
||||||
Args && ...arg) {
|
|
||||||
return _query(rowID,ret, fmt, std::forward<Args>(arg)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t query(int64_t &rowID,vector<vector<string>> &ret, const string &sql) {
|
|
||||||
return _query(rowID,ret, sql.c_str());
|
|
||||||
}
|
|
||||||
static const string &escape(const string &str) {
|
|
||||||
try {
|
|
||||||
//捕获创建对象异常
|
|
||||||
_SqlPool::Instance().pool->obtain()->escape(
|
|
||||||
const_cast<string &>(str));
|
|
||||||
} catch (exception &e) {
|
|
||||||
WarnL << e.what() << endl;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
_SqlPool() :
|
|
||||||
threadPool(new ThreadPool(poolSize)), asyncTaskThread(10 * 1000) {
|
|
||||||
poolsize = poolSize;
|
|
||||||
asyncTaskThread.DoTaskDelay(reinterpret_cast<uint64_t>(this), 30 * 1000,
|
|
||||||
[this]() {
|
|
||||||
flushError();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
inline void doQuery(const string &str,int tryCnt = 3) {
|
|
||||||
auto lam = [this,str,tryCnt]() {
|
|
||||||
int64_t rowID;
|
|
||||||
auto cnt = tryCnt - 1;
|
|
||||||
if(_query(rowID,str.c_str())==-2 && cnt > 0) {
|
|
||||||
lock_guard<mutex> lk(error_query_mutex);
|
|
||||||
sqlQuery query(str,cnt);
|
|
||||||
error_query.push_back(query);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
threadPool->async(lam);
|
|
||||||
}
|
|
||||||
template<typename ...Args>
|
|
||||||
inline int64_t _query(int64_t &rowID,Args &&...arg) {
|
|
||||||
typename PoolType::ValuePtr mysql;
|
|
||||||
try {
|
|
||||||
//捕获执行异常
|
|
||||||
mysql = pool->obtain();
|
|
||||||
return mysql->query(rowID,std::forward<Args>(arg)...);
|
|
||||||
} catch (exception &e) {
|
|
||||||
pool->quit(mysql);
|
|
||||||
WarnL << e.what() << endl;
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void flushError() {
|
|
||||||
decltype(error_query) query_copy;
|
|
||||||
error_query_mutex.lock();
|
|
||||||
query_copy.swap(error_query);
|
|
||||||
error_query_mutex.unlock();
|
|
||||||
if (query_copy.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto &query : query_copy) {
|
|
||||||
doQuery(query.sql_str,query.tryCnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual ~_SqlPool() {
|
|
||||||
asyncTaskThread.CancelTask(reinterpret_cast<uint64_t>(this));
|
|
||||||
flushError();
|
|
||||||
threadPool.reset();
|
|
||||||
pool.reset();
|
|
||||||
InfoL;
|
|
||||||
}
|
|
||||||
std::shared_ptr<ThreadPool> threadPool;
|
|
||||||
mutex error_query_mutex;
|
|
||||||
class sqlQuery
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
sqlQuery(const string &sql,int cnt):sql_str(sql),tryCnt(cnt){}
|
|
||||||
string sql_str;
|
|
||||||
int tryCnt = 0;
|
|
||||||
} ;
|
|
||||||
deque<sqlQuery> error_query;
|
|
||||||
|
|
||||||
std::shared_ptr<PoolType> pool;
|
|
||||||
AsyncTaskThread asyncTaskThread;
|
|
||||||
unsigned int poolsize;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
typedef _SqlPool<1> SqlPool;
|
|
||||||
|
|
||||||
class SqlStream {
|
|
||||||
public:
|
|
||||||
SqlStream(const char *_sql) :
|
|
||||||
sql(_sql) {
|
|
||||||
startPos = 0;
|
|
||||||
}
|
|
||||||
~SqlStream() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
SqlStream& operator <<(const T& data) {
|
|
||||||
auto pos = sql.find_first_of('?', startPos);
|
|
||||||
if (pos == string::npos) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
str_tmp.str("");
|
|
||||||
str_tmp << data;
|
|
||||||
string str = str_tmp.str();
|
|
||||||
startPos = pos + str.size();
|
|
||||||
sql.replace(pos, 1, str);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
const string& operator <<(std::ostream&(*f)(std::ostream&)) const {
|
|
||||||
return sql;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
stringstream str_tmp;
|
|
||||||
string sql;
|
|
||||||
string::size_type startPos;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SqlWriter {
|
|
||||||
public:
|
|
||||||
SqlWriter(const char *_sql,bool _throwAble = true) :
|
|
||||||
sqlstream(_sql),throwAble(_throwAble) {
|
|
||||||
}
|
|
||||||
~SqlWriter() {
|
|
||||||
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
SqlWriter& operator <<(const T& data) {
|
|
||||||
sqlstream << data;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator <<(std::ostream&(*f)(std::ostream&)) {
|
|
||||||
SqlPool::Instance().query(sqlstream << endl);
|
|
||||||
}
|
|
||||||
int64_t operator <<(vector<vector<string>> &ret) {
|
|
||||||
affectedRows = SqlPool::Instance().query(rowId,ret, sqlstream << endl);
|
|
||||||
if(affectedRows < 0 && throwAble){
|
|
||||||
throw std::runtime_error("operate database failed");
|
|
||||||
}
|
|
||||||
return affectedRows;
|
|
||||||
}
|
|
||||||
int64_t getRowID() const {
|
|
||||||
return rowId;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t getAffectedRows() const {
|
|
||||||
return affectedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SqlStream sqlstream;
|
|
||||||
int64_t rowId = 0;
|
|
||||||
int64_t affectedRows = -1;
|
|
||||||
bool throwAble = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace mysql */
|
|
||||||
} /* namespace im */
|
|
||||||
|
|
||||||
#endif /* SQL_SQLPOOL_H_ */
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* TimeTicker.h
|
|
||||||
*
|
|
||||||
* Created on: 2015年12月30日
|
|
||||||
* Author: root
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_TIMETICKER_H_
|
|
||||||
#define UTIL_TIMETICKER_H_
|
|
||||||
|
|
||||||
#include "logger.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class Ticker {
|
|
||||||
public:
|
|
||||||
Ticker(int64_t _minMs = 0, const char *_where = "",
|
|
||||||
LogInfoMaker && _stream = LogInfoMaker(LWarn, __FILE__, "", __LINE__),bool printLog=false) :
|
|
||||||
stream(_stream) {
|
|
||||||
if(!printLog){
|
|
||||||
stream.clear();
|
|
||||||
}
|
|
||||||
begin = getNowTime();
|
|
||||||
created = begin;
|
|
||||||
minMs = _minMs;
|
|
||||||
where = _where;
|
|
||||||
}
|
|
||||||
virtual ~Ticker() {
|
|
||||||
int64_t tm = getNowTime() - begin;
|
|
||||||
if (tm > minMs) {
|
|
||||||
stream << where << " take time:" << tm << endl;
|
|
||||||
} else {
|
|
||||||
stream.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint64_t elapsedTime() {
|
|
||||||
stream.clear();
|
|
||||||
return getNowTime() - begin;
|
|
||||||
}
|
|
||||||
uint64_t createdTime() {
|
|
||||||
stream.clear();
|
|
||||||
return getNowTime() - created;
|
|
||||||
}
|
|
||||||
void resetTime() {
|
|
||||||
stream.clear();
|
|
||||||
begin = getNowTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline static uint64_t getNowTime() {
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
||||||
}
|
|
||||||
uint64_t begin;
|
|
||||||
uint64_t created;
|
|
||||||
LogInfoMaker stream;
|
|
||||||
const char *where;
|
|
||||||
int64_t minMs;
|
|
||||||
|
|
||||||
};
|
|
||||||
class SmoothTicker {
|
|
||||||
public:
|
|
||||||
SmoothTicker(uint64_t _resetMs = 10000) {
|
|
||||||
resetMs = _resetMs;
|
|
||||||
ticker.resetTime();
|
|
||||||
}
|
|
||||||
virtual ~SmoothTicker() {
|
|
||||||
}
|
|
||||||
uint64_t elapsedTime() {
|
|
||||||
auto nowTime = ticker.elapsedTime();
|
|
||||||
if (firstTime == 0) {
|
|
||||||
firstTime = nowTime;
|
|
||||||
lastTime = nowTime;
|
|
||||||
pktCount = 0;
|
|
||||||
return nowTime;
|
|
||||||
}
|
|
||||||
uint64_t elapseTime = (nowTime - firstTime);
|
|
||||||
uint64_t retTime = lastTime + elapseTime / ++pktCount;
|
|
||||||
lastTime = retTime;
|
|
||||||
if (elapseTime > 10000) {
|
|
||||||
firstTime = 0;
|
|
||||||
}
|
|
||||||
return retTime;
|
|
||||||
}
|
|
||||||
void resetTime(){
|
|
||||||
firstTime = 0;
|
|
||||||
pktCount = 0;
|
|
||||||
lastTime = 0;
|
|
||||||
ticker.resetTime();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
uint64_t firstTime = 0;
|
|
||||||
uint64_t pktCount = 0;
|
|
||||||
uint64_t lastTime = 0;
|
|
||||||
uint64_t resetMs;
|
|
||||||
Ticker ticker;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
#define TimeTicker() Ticker(5,"",WarnL,true)
|
|
||||||
#define TimeTicker1(tm) Ticker(tm,"",WarnL,true)
|
|
||||||
#define TimeTicker2(tm,where) Ticker(tm,where,WarnL,true)
|
|
||||||
#define TimeTicker3(tm,where,log) Ticker(tm,where,log,true)
|
|
||||||
#else
|
|
||||||
#define TimeTicker()
|
|
||||||
#define TimeTicker1(tm)
|
|
||||||
#define TimeTicker2(tm,where)
|
|
||||||
#define TimeTicker3(tm,where,log)
|
|
||||||
#endif
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_TIMETICKER_H_ */
|
|
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* functiontraits.h
|
|
||||||
*
|
|
||||||
* Created on: 2017年3月15日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_UTIL_FUNCTION_TRAITS_H_
|
|
||||||
#define SRC_UTIL_FUNCTION_TRAITS_H_
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct function_traits;
|
|
||||||
|
|
||||||
//普通函数
|
|
||||||
template<typename Ret, typename... Args>
|
|
||||||
struct function_traits<Ret(Args...)>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum { arity = sizeof...(Args) };
|
|
||||||
typedef Ret function_type(Args...);
|
|
||||||
typedef Ret return_type;
|
|
||||||
using stl_function_type = std::function<function_type>;
|
|
||||||
typedef Ret(*pointer)(Args...);
|
|
||||||
|
|
||||||
template<size_t I>
|
|
||||||
struct args
|
|
||||||
{
|
|
||||||
static_assert(I < arity, "index is out of range, index must less than sizeof Args");
|
|
||||||
using type = typename std::tuple_element<I, std::tuple<Args...> >::type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//函数指针
|
|
||||||
template<typename Ret, typename... Args>
|
|
||||||
struct function_traits<Ret(*)(Args...)> : function_traits<Ret(Args...)>{};
|
|
||||||
|
|
||||||
//std::function
|
|
||||||
template <typename Ret, typename... Args>
|
|
||||||
struct function_traits<std::function<Ret(Args...)>> : function_traits<Ret(Args...)>{};
|
|
||||||
|
|
||||||
//member function
|
|
||||||
#define FUNCTION_TRAITS(...) \
|
|
||||||
template <typename ReturnType, typename ClassType, typename... Args>\
|
|
||||||
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)>{}; \
|
|
||||||
|
|
||||||
FUNCTION_TRAITS()
|
|
||||||
FUNCTION_TRAITS(const)
|
|
||||||
FUNCTION_TRAITS(volatile)
|
|
||||||
FUNCTION_TRAITS(const volatile)
|
|
||||||
|
|
||||||
//函数对象
|
|
||||||
template<typename Callable>
|
|
||||||
struct function_traits : function_traits<decltype(&Callable::operator())>{};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_UTIL_FUNCTION_TRAITS_H_ */
|
|
@ -1,400 +0,0 @@
|
|||||||
/*
|
|
||||||
* logger.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月3日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_LOGGER_H_
|
|
||||||
#define UTIL_LOGGER_H_
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <deque>
|
|
||||||
#include <map>
|
|
||||||
#include <ctime>
|
|
||||||
#include <string.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <time.h>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Thread/semaphore.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
enum LogLevel {
|
|
||||||
LTrace = 0, LDebug, LInfo, LWarn, LError, LFatal,
|
|
||||||
};
|
|
||||||
static const char *LogLevelStr[] = { "trace", "debug", "info", "warn", "error",
|
|
||||||
"fatal" };
|
|
||||||
|
|
||||||
#define CLEAR_COLOR "\033[0m"
|
|
||||||
#define UNDERLINE "\033[4m"
|
|
||||||
|
|
||||||
static const char *COLOR[6][2] = { { "\033[44;37m", "\033[34m" }, {
|
|
||||||
"\033[42;37m", "\033[32m" }, { "\033[46;37m", "\033[36m" }, {
|
|
||||||
"\033[43;37m", "\033[33m" }, { "\033[45;37m", "\033[35m" }, {
|
|
||||||
"\033[41;37m", "\033[31m" } };
|
|
||||||
|
|
||||||
class Logger;
|
|
||||||
class LogWriter;
|
|
||||||
class LogChannel;
|
|
||||||
class LogInfo;
|
|
||||||
class LogInfoMaker;
|
|
||||||
|
|
||||||
typedef std::shared_ptr<LogInfo> LogInfo_ptr;
|
|
||||||
class LogChannel {
|
|
||||||
public:
|
|
||||||
LogChannel(const string& name, LogLevel level = LDebug,
|
|
||||||
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
|
|
||||||
_name(name), _level(level), _timeFormat(timeFormat) {
|
|
||||||
}
|
|
||||||
virtual ~LogChannel() {
|
|
||||||
}
|
|
||||||
virtual void write(const LogInfo_ptr & stream)=0;
|
|
||||||
const string &name() const {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
LogLevel level() const {
|
|
||||||
return _level;
|
|
||||||
}
|
|
||||||
const string &timeFormat() const {
|
|
||||||
return _timeFormat;
|
|
||||||
}
|
|
||||||
void setLevel(LogLevel level) {
|
|
||||||
_level = level;
|
|
||||||
}
|
|
||||||
void setDateFormat(const char* format) {
|
|
||||||
_timeFormat = format;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
string _name;
|
|
||||||
LogLevel _level;
|
|
||||||
string _timeFormat;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LogWriter {
|
|
||||||
public:
|
|
||||||
LogWriter() {
|
|
||||||
}
|
|
||||||
virtual ~LogWriter() {
|
|
||||||
}
|
|
||||||
virtual void write(const LogInfo_ptr &stream) =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Logger {
|
|
||||||
public:
|
|
||||||
friend class LogWriter;
|
|
||||||
friend class AsyncLogWriter;
|
|
||||||
static Logger& Instance() {
|
|
||||||
static Logger *logger(new Logger());
|
|
||||||
return *logger;
|
|
||||||
}
|
|
||||||
static void Destory() {
|
|
||||||
delete &Logger::Instance();
|
|
||||||
}
|
|
||||||
void add(const std::shared_ptr<LogChannel> &&channel) {
|
|
||||||
channels[channel->name()] = channel;
|
|
||||||
}
|
|
||||||
void del(const string& name) {
|
|
||||||
auto it = channels.find(name);
|
|
||||||
if (it != channels.end()) {
|
|
||||||
channels.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::shared_ptr<LogChannel> get(const string& name){
|
|
||||||
auto it = channels.find(name);
|
|
||||||
if(it == channels.end()){
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWriter(const std::shared_ptr<LogWriter> &&_writer) {
|
|
||||||
if (_writer) {
|
|
||||||
this->writer = _writer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void write(const LogInfo_ptr &stream) {
|
|
||||||
if (writer) {
|
|
||||||
writer->write(stream);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto &chn : channels) {
|
|
||||||
chn.second->write(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setLevel(LogLevel level) {
|
|
||||||
for (auto &chn : channels) {
|
|
||||||
chn.second->setLevel(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
Logger() {
|
|
||||||
}
|
|
||||||
~Logger() {
|
|
||||||
}
|
|
||||||
// Non-copyable and non-movable
|
|
||||||
Logger(const Logger&); // = delete;
|
|
||||||
Logger(Logger&&); // = delete;
|
|
||||||
Logger& operator=(const Logger&); // = delete;
|
|
||||||
Logger& operator=(Logger&&); // = delete;
|
|
||||||
|
|
||||||
map<string, std::shared_ptr<LogChannel> > channels;
|
|
||||||
std::shared_ptr<LogWriter> writer;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LogInfo {
|
|
||||||
public:
|
|
||||||
friend class LogInfoMaker;
|
|
||||||
void format(ostream& ost, const char *timeFormat = "%Y-%m-%d %H:%M:%S",
|
|
||||||
bool enableColor = true) {
|
|
||||||
static string appName = exeName();
|
|
||||||
ost << appName << " "<< file << " " << line << "\r\n ";
|
|
||||||
if (enableColor) {
|
|
||||||
ost << COLOR[level][1];
|
|
||||||
}
|
|
||||||
if (timeFormat) {
|
|
||||||
ost << print(toLocal(ts), timeFormat);
|
|
||||||
}
|
|
||||||
ost << " [" << LogLevelStr[level] << "] ";
|
|
||||||
ost << function << " ";
|
|
||||||
ost << message.str();
|
|
||||||
if (enableColor) {
|
|
||||||
ost << CLEAR_COLOR;
|
|
||||||
}
|
|
||||||
ost.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
LogLevel getLevel() const {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
LogInfo(LogLevel _level, const char* _file, const char* _function,
|
|
||||||
int _line) :
|
|
||||||
level(_level), line(_line), file(_file), function(_function), ts(
|
|
||||||
::time(NULL)) {
|
|
||||||
}
|
|
||||||
std::string print(const std::tm& dt, const char* fmt) {
|
|
||||||
/*
|
|
||||||
#if defined(__WIN32__)
|
|
||||||
// BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm* "
|
|
||||||
// ref. C++11 standard: ISO/IEC 14882:2011, <20> 27.7.1,
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::put_time(const_cast<std::tm*>(&dt), fmt);
|
|
||||||
return oss.str();
|
|
||||||
|
|
||||||
#else // LINUX
|
|
||||||
*/
|
|
||||||
const size_t size = 1024;
|
|
||||||
char buffer[size];
|
|
||||||
auto success = std::strftime(buffer, size, fmt, &dt);
|
|
||||||
if (0 == success)
|
|
||||||
return string(fmt);
|
|
||||||
return buffer;
|
|
||||||
//#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tm toLocal(const std::time_t& time) {
|
|
||||||
std::tm tm_snapshot;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
localtime_s(&tm_snapshot, &time); // thread-safe?
|
|
||||||
#else
|
|
||||||
localtime_r(&time, &tm_snapshot); // POSIX
|
|
||||||
#endif //WIN32
|
|
||||||
return tm_snapshot;
|
|
||||||
}
|
|
||||||
LogLevel level;
|
|
||||||
int line;
|
|
||||||
string file;
|
|
||||||
string function;
|
|
||||||
time_t ts;
|
|
||||||
ostringstream message;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LogInfoMaker {
|
|
||||||
public:
|
|
||||||
LogInfoMaker(LogLevel level, const char* file, const char* function,
|
|
||||||
int line) :
|
|
||||||
logInfo(new LogInfo(level, file, function, line)) {
|
|
||||||
}
|
|
||||||
LogInfoMaker(LogInfoMaker &&that) {
|
|
||||||
this->logInfo = that.logInfo;
|
|
||||||
that.logInfo.reset();
|
|
||||||
}
|
|
||||||
LogInfoMaker(const LogInfoMaker &that) {
|
|
||||||
this->logInfo = that.logInfo;
|
|
||||||
(const_cast<LogInfoMaker &>(that)).logInfo.reset();
|
|
||||||
}
|
|
||||||
~LogInfoMaker() {
|
|
||||||
*this << endl;
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
LogInfoMaker& operator <<(const T& data) {
|
|
||||||
if (!logInfo) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
logInfo->message << data;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfoMaker& operator <<(const char *data) {
|
|
||||||
if (!logInfo) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
if(data){
|
|
||||||
logInfo->message << data;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogInfoMaker& operator <<(ostream&(*f)(ostream&)) {
|
|
||||||
if (!logInfo) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
logInfo->message << f;
|
|
||||||
Logger::Instance().write(logInfo);
|
|
||||||
logInfo.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
void clear() {
|
|
||||||
logInfo.reset();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
LogInfo_ptr logInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AsyncLogWriter: public LogWriter {
|
|
||||||
public:
|
|
||||||
AsyncLogWriter() :
|
|
||||||
exit_flag(false) {
|
|
||||||
_thread.reset(new thread([this]() {this->run();}));
|
|
||||||
|
|
||||||
}
|
|
||||||
virtual ~AsyncLogWriter() {
|
|
||||||
exit_flag = true;
|
|
||||||
sem.post();
|
|
||||||
_thread->join();
|
|
||||||
while (_pending.size()) {
|
|
||||||
auto &next = _pending.front();
|
|
||||||
realWrite(next);
|
|
||||||
_pending.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
virtual void write(const LogInfo_ptr &stream) {
|
|
||||||
{
|
|
||||||
lock_guard<mutex> lock(_mutex);
|
|
||||||
_pending.push_back(stream);
|
|
||||||
}
|
|
||||||
sem.post();
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
void run() {
|
|
||||||
while (!exit_flag) {
|
|
||||||
sem.wait();
|
|
||||||
{
|
|
||||||
lock_guard<mutex> lock(_mutex);
|
|
||||||
if (_pending.size()) {
|
|
||||||
auto &next = _pending.front();
|
|
||||||
realWrite(next);
|
|
||||||
_pending.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline void realWrite(const LogInfo_ptr &stream) {
|
|
||||||
for (auto &chn : Logger::Instance().channels) {
|
|
||||||
chn.second->write(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool exit_flag;
|
|
||||||
std::shared_ptr<thread> _thread;
|
|
||||||
deque<LogInfo_ptr> _pending;
|
|
||||||
semaphore sem;
|
|
||||||
mutex _mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConsoleChannel: public LogChannel {
|
|
||||||
public:
|
|
||||||
ConsoleChannel(const string& name, LogLevel level = LDebug,
|
|
||||||
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
|
|
||||||
LogChannel(name, level, timeFormat) {
|
|
||||||
}
|
|
||||||
virtual ~ConsoleChannel() {
|
|
||||||
}
|
|
||||||
void write(const LogInfo_ptr &logInfo) {
|
|
||||||
if (level() > logInfo->getLevel()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logInfo->format(std::cout, timeFormat().c_str(), true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FileChannel: public LogChannel {
|
|
||||||
public:
|
|
||||||
FileChannel(const string& name, const string& path, LogLevel level = LDebug,
|
|
||||||
const char* timeFormat = "%Y-%m-%d %H:%M:%S") :
|
|
||||||
LogChannel(name, level, timeFormat), _path(path) {
|
|
||||||
}
|
|
||||||
virtual ~FileChannel() {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
virtual void write(const std::shared_ptr<LogInfo> &stream) {
|
|
||||||
if (level() > stream->getLevel()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!_fstream.is_open()) {
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
stream->format(_fstream, timeFormat().c_str(), false);
|
|
||||||
}
|
|
||||||
void setPath(const string& path) {
|
|
||||||
_path = path;
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
const string &path() const {
|
|
||||||
return _path;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
virtual void open() {
|
|
||||||
// Ensure a path was set
|
|
||||||
if (_path.empty()) {
|
|
||||||
throw runtime_error("Log file path must be set.");
|
|
||||||
}
|
|
||||||
// Open the file stream
|
|
||||||
_fstream.close();
|
|
||||||
_fstream.open(_path.c_str(), ios::out | ios::app);
|
|
||||||
// Throw on failure
|
|
||||||
if (!_fstream.is_open()) {
|
|
||||||
throw runtime_error("Failed to open log file: " + _path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual void close() {
|
|
||||||
_fstream.close();
|
|
||||||
}
|
|
||||||
ofstream _fstream;
|
|
||||||
string _path;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TraceL LogInfoMaker(LTrace, __FILE__,__FUNCTION__, __LINE__)
|
|
||||||
#define DebugL LogInfoMaker(LDebug, __FILE__,__FUNCTION__, __LINE__)
|
|
||||||
#define InfoL LogInfoMaker(LInfo, __FILE__,__FUNCTION__, __LINE__)
|
|
||||||
#define WarnL LogInfoMaker(LWarn,__FILE__, __FUNCTION__, __LINE__)
|
|
||||||
#define ErrorL LogInfoMaker(LError,__FILE__, __FUNCTION__, __LINE__)
|
|
||||||
#define FatalL LogInfoMaker(LFatal,__FILE__, __FUNCTION__, __LINE__)
|
|
||||||
|
|
||||||
} /* namespace util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_LOGGER_H_ */
|
|
@ -1,149 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef UTIL_MINI_H
|
|
||||||
#define UTIL_MINI_H
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <exception>
|
|
||||||
#include "Util/util.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
|
|
||||||
template<typename key, typename variant>
|
|
||||||
class mINI_basic: public map<key, variant> {
|
|
||||||
// Public API : existing map<> interface plus following methods
|
|
||||||
public:
|
|
||||||
void parse(const string &text) {
|
|
||||||
// reset, split lines and parse
|
|
||||||
static auto trim = []( string line ) {
|
|
||||||
while( line.size() && ( line.back()=='\t' || line.back()==' ' ) ) line.pop_back();
|
|
||||||
while( line.size() && ( line.front()=='\t' || line.front()==' ' ) ) line.erase(0,1);
|
|
||||||
return line;
|
|
||||||
};
|
|
||||||
vector<string> lines = tokenize(text, "\r\n");
|
|
||||||
string symbol, tag;
|
|
||||||
for (auto &line : lines){
|
|
||||||
// trim blanks
|
|
||||||
line = trim(line);
|
|
||||||
// split line into tokens and parse tokens
|
|
||||||
if(line.empty() || line.front() == ';' || line.front() == '#'){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (line.size() >= 3 && line.front() == '[' && line.back() == ']') {
|
|
||||||
tag = trim(line.substr(1, line.size() - 2));
|
|
||||||
} else {
|
|
||||||
auto at = line.find_first_of('=');
|
|
||||||
symbol = trim(tag + "." + line.substr(0, at));
|
|
||||||
(*this)[symbol] = (at == string::npos ? string() : trim(line.substr(at + 1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void parseFile(const string &fileName = exePath() + ".ini") {
|
|
||||||
ifstream in(fileName, ios::in | ios::binary | ios::ate);
|
|
||||||
if (!in.good()) {
|
|
||||||
stringstream ss;
|
|
||||||
ss << "invalid ini file:" << fileName;
|
|
||||||
throw invalid_argument(ss.str());
|
|
||||||
}
|
|
||||||
long size = in.tellg();
|
|
||||||
in.seekg(0, ios::beg);
|
|
||||||
string buf;
|
|
||||||
buf.resize(size);
|
|
||||||
in.read((char *) buf.data(), size);
|
|
||||||
parse(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
string dump(const string &header = "; auto-generated by mINI class {",
|
|
||||||
const string &footer = "; } ---") const {
|
|
||||||
string output(header + (header.empty() ? "" : "\r\n")), tag;
|
|
||||||
for (auto &pr : *this) {
|
|
||||||
vector<string> kv = tokenize(pr.first, ".");
|
|
||||||
if (tag != kv[0]) {
|
|
||||||
output += "\r\n[" + (tag = kv[0]) + "]\r\n";
|
|
||||||
}
|
|
||||||
output += kv[1] + "=" + pr.second + "\r\n";
|
|
||||||
}
|
|
||||||
return output + "\r\n" + footer + (footer.empty() ? "" : "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void dumpFile(const string &fileName = exePath() + ".ini") {
|
|
||||||
ofstream out(fileName, ios::out | ios::binary | ios::trunc);
|
|
||||||
auto dmp = dump();
|
|
||||||
out.write(dmp.data(),dmp.size());
|
|
||||||
}
|
|
||||||
static mINI_basic &Instance(){
|
|
||||||
static mINI_basic instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
vector<string> tokenize(const string &self, const string &chars) const {
|
|
||||||
vector<string> tokens(1);
|
|
||||||
string map(256, '\0');
|
|
||||||
for (const unsigned char &ch : chars) {
|
|
||||||
map[ch] = '\1';
|
|
||||||
}
|
|
||||||
for (const unsigned char &ch : self) {
|
|
||||||
if (!map.at(ch)) {
|
|
||||||
tokens.back().push_back(char(ch));
|
|
||||||
} else if (tokens.back().size()) {
|
|
||||||
tokens.push_back(string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (tokens.size() && tokens.back().empty()) {
|
|
||||||
tokens.pop_back();
|
|
||||||
}
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// handy variant class as key/values
|
|
||||||
struct variant: public string {
|
|
||||||
template<typename T>
|
|
||||||
variant(const T &t) :
|
|
||||||
string(to_string(t)) {
|
|
||||||
}
|
|
||||||
template<size_t N>
|
|
||||||
variant(const char (&s)[N]) :
|
|
||||||
string(s, N) {
|
|
||||||
}
|
|
||||||
variant(const char *cstr) :
|
|
||||||
string(cstr) {
|
|
||||||
}
|
|
||||||
variant(const string &other = string()) :
|
|
||||||
string(other) {
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
operator T() const {
|
|
||||||
T t;
|
|
||||||
stringstream ss;
|
|
||||||
return ss << *this && ss >> t ? t : T();
|
|
||||||
}
|
|
||||||
template<typename T> bool operator ==(const T &t) const {
|
|
||||||
return 0 == this->compare(variant(t));
|
|
||||||
}
|
|
||||||
bool operator ==(const char *t) const {
|
|
||||||
return this->compare(t) == 0;
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
T as() const {
|
|
||||||
return (T) (*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using mINI = mINI_basic<string, variant>;
|
|
||||||
|
|
||||||
} // namespace Util
|
|
||||||
} // namespace ZL
|
|
||||||
|
|
||||||
#endif //UTIL_MINI_H
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* onceToken.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_ONCETOKEN_H_
|
|
||||||
#define UTIL_ONCETOKEN_H_
|
|
||||||
|
|
||||||
#include "functional"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class onceToken {
|
|
||||||
public:
|
|
||||||
typedef function<void(void)> task;
|
|
||||||
onceToken(const task &onConstructed, const task &_onDestructed) {
|
|
||||||
if (onConstructed) {
|
|
||||||
onConstructed();
|
|
||||||
}
|
|
||||||
onDestructed = _onDestructed;
|
|
||||||
}
|
|
||||||
virtual ~onceToken() {
|
|
||||||
if (onDestructed) {
|
|
||||||
onDestructed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
onceToken();
|
|
||||||
onceToken(const onceToken &);
|
|
||||||
onceToken(onceToken &&);
|
|
||||||
onceToken &operator =(const onceToken &);
|
|
||||||
onceToken &operator =(onceToken &&);
|
|
||||||
task onDestructed;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Util */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* UTIL_ONCETOKEN_H_ */
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* util.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月4日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_UTIL_H_
|
|
||||||
#define UTIL_UTIL_H_
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#pragma comment (lib,"WS2_32")
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
class _StrPrinter {
|
|
||||||
public:
|
|
||||||
_StrPrinter() {
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
_StrPrinter& operator <<(const T& data) {
|
|
||||||
ss << data;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
string operator <<(std::ostream&(*f)(std::ostream&)) const {
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
stringstream ss;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define StrPrinter _StrPrinter()
|
|
||||||
|
|
||||||
string makeRandStr(int sz, bool printable = true);
|
|
||||||
string hexdump(const void *buf, size_t len);
|
|
||||||
string exePath();
|
|
||||||
string exeDir();
|
|
||||||
string exeName();
|
|
||||||
void setExePath(const string &path);
|
|
||||||
|
|
||||||
#ifndef bzero
|
|
||||||
#define bzero(ptr,size) memset((ptr),0,(size));
|
|
||||||
#endif //bzero
|
|
||||||
|
|
||||||
#if defined(ANDROID)
|
|
||||||
template <typename T>
|
|
||||||
std::string to_string(T value){
|
|
||||||
std::ostringstream os ;
|
|
||||||
os << std::forward<T>(value);
|
|
||||||
return os.str() ;
|
|
||||||
}
|
|
||||||
#endif//ANDROID
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
int gettimeofday(struct timeval *tp, void *tzp);
|
|
||||||
int strcasecmp(const char *strA,const char *strB);
|
|
||||||
void usleep(int micro_seconds);
|
|
||||||
void sleep(int second);
|
|
||||||
|
|
||||||
#endif //WIN32
|
|
||||||
|
|
||||||
} // namespace Util
|
|
||||||
} // namespace ZL
|
|
||||||
|
|
||||||
#endif /* UTIL_UTIL_H_ */
|
|
@ -1,522 +0,0 @@
|
|||||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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 UV_ERRNO_H_
|
|
||||||
#define UV_ERRNO_H_
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define UV__EOF (-4095)
|
|
||||||
#define UV__UNKNOWN (-4094)
|
|
||||||
|
|
||||||
#define UV__EAI_ADDRFAMILY (-3000)
|
|
||||||
#define UV__EAI_AGAIN (-3001)
|
|
||||||
#define UV__EAI_BADFLAGS (-3002)
|
|
||||||
#define UV__EAI_CANCELED (-3003)
|
|
||||||
#define UV__EAI_FAIL (-3004)
|
|
||||||
#define UV__EAI_FAMILY (-3005)
|
|
||||||
#define UV__EAI_MEMORY (-3006)
|
|
||||||
#define UV__EAI_NODATA (-3007)
|
|
||||||
#define UV__EAI_NONAME (-3008)
|
|
||||||
#define UV__EAI_OVERFLOW (-3009)
|
|
||||||
#define UV__EAI_SERVICE (-3010)
|
|
||||||
#define UV__EAI_SOCKTYPE (-3011)
|
|
||||||
#define UV__EAI_BADHINTS (-3013)
|
|
||||||
#define UV__EAI_PROTOCOL (-3014)
|
|
||||||
|
|
||||||
/* Only map to the system errno on non-Windows platforms. It's apparently
|
|
||||||
* a fairly common practice for Windows programmers to redefine errno codes.
|
|
||||||
*/
|
|
||||||
#if defined(E2BIG) && !defined(_WIN32)
|
|
||||||
# define UV__E2BIG (-E2BIG)
|
|
||||||
#else
|
|
||||||
# define UV__E2BIG (-4093)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EACCES) && !defined(_WIN32)
|
|
||||||
# define UV__EACCES (-EACCES)
|
|
||||||
#else
|
|
||||||
# define UV__EACCES (-4092)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EADDRINUSE) && !defined(_WIN32)
|
|
||||||
# define UV__EADDRINUSE (-EADDRINUSE)
|
|
||||||
#else
|
|
||||||
# define UV__EADDRINUSE (-4091)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
|
|
||||||
# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL)
|
|
||||||
#else
|
|
||||||
# define UV__EADDRNOTAVAIL (-4090)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
|
|
||||||
# define UV__EAFNOSUPPORT (-EAFNOSUPPORT)
|
|
||||||
#else
|
|
||||||
# define UV__EAFNOSUPPORT (-4089)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EAGAIN) && !defined(_WIN32)
|
|
||||||
# define UV__EAGAIN (-EAGAIN)
|
|
||||||
#else
|
|
||||||
# define UV__EAGAIN (-4088)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EALREADY) && !defined(_WIN32)
|
|
||||||
# define UV__EALREADY (-EALREADY)
|
|
||||||
#else
|
|
||||||
# define UV__EALREADY (-4084)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EBADF) && !defined(_WIN32)
|
|
||||||
# define UV__EBADF (-EBADF)
|
|
||||||
#else
|
|
||||||
# define UV__EBADF (-4083)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EBUSY) && !defined(_WIN32)
|
|
||||||
# define UV__EBUSY (-EBUSY)
|
|
||||||
#else
|
|
||||||
# define UV__EBUSY (-4082)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ECANCELED) && !defined(_WIN32)
|
|
||||||
# define UV__ECANCELED (-ECANCELED)
|
|
||||||
#else
|
|
||||||
# define UV__ECANCELED (-4081)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ECHARSET) && !defined(_WIN32)
|
|
||||||
# define UV__ECHARSET (-ECHARSET)
|
|
||||||
#else
|
|
||||||
# define UV__ECHARSET (-4080)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ECONNABORTED) && !defined(_WIN32)
|
|
||||||
# define UV__ECONNABORTED (-ECONNABORTED)
|
|
||||||
#else
|
|
||||||
# define UV__ECONNABORTED (-4079)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ECONNREFUSED) && !defined(_WIN32)
|
|
||||||
# define UV__ECONNREFUSED (-ECONNREFUSED)
|
|
||||||
#else
|
|
||||||
# define UV__ECONNREFUSED (-4078)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ECONNRESET) && !defined(_WIN32)
|
|
||||||
# define UV__ECONNRESET (-ECONNRESET)
|
|
||||||
#else
|
|
||||||
# define UV__ECONNRESET (-4077)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EDESTADDRREQ) && !defined(_WIN32)
|
|
||||||
# define UV__EDESTADDRREQ (-EDESTADDRREQ)
|
|
||||||
#else
|
|
||||||
# define UV__EDESTADDRREQ (-4076)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EEXIST) && !defined(_WIN32)
|
|
||||||
# define UV__EEXIST (-EEXIST)
|
|
||||||
#else
|
|
||||||
# define UV__EEXIST (-4075)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EFAULT) && !defined(_WIN32)
|
|
||||||
# define UV__EFAULT (-EFAULT)
|
|
||||||
#else
|
|
||||||
# define UV__EFAULT (-4074)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EHOSTUNREACH) && !defined(_WIN32)
|
|
||||||
# define UV__EHOSTUNREACH (-EHOSTUNREACH)
|
|
||||||
#else
|
|
||||||
# define UV__EHOSTUNREACH (-4073)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EINTR) && !defined(_WIN32)
|
|
||||||
# define UV__EINTR (-EINTR)
|
|
||||||
#else
|
|
||||||
# define UV__EINTR (-4072)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EINVAL) && !defined(_WIN32)
|
|
||||||
# define UV__EINVAL (-EINVAL)
|
|
||||||
#else
|
|
||||||
# define UV__EINVAL (-4071)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EIO) && !defined(_WIN32)
|
|
||||||
# define UV__EIO (-EIO)
|
|
||||||
#else
|
|
||||||
# define UV__EIO (-4070)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EISCONN) && !defined(_WIN32)
|
|
||||||
# define UV__EISCONN (-EISCONN)
|
|
||||||
#else
|
|
||||||
# define UV__EISCONN (-4069)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EISDIR) && !defined(_WIN32)
|
|
||||||
# define UV__EISDIR (-EISDIR)
|
|
||||||
#else
|
|
||||||
# define UV__EISDIR (-4068)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ELOOP) && !defined(_WIN32)
|
|
||||||
# define UV__ELOOP (-ELOOP)
|
|
||||||
#else
|
|
||||||
# define UV__ELOOP (-4067)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EMFILE) && !defined(_WIN32)
|
|
||||||
# define UV__EMFILE (-EMFILE)
|
|
||||||
#else
|
|
||||||
# define UV__EMFILE (-4066)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EMSGSIZE) && !defined(_WIN32)
|
|
||||||
# define UV__EMSGSIZE (-EMSGSIZE)
|
|
||||||
#else
|
|
||||||
# define UV__EMSGSIZE (-4065)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENAMETOOLONG) && !defined(_WIN32)
|
|
||||||
# define UV__ENAMETOOLONG (-ENAMETOOLONG)
|
|
||||||
#else
|
|
||||||
# define UV__ENAMETOOLONG (-4064)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENETDOWN) && !defined(_WIN32)
|
|
||||||
# define UV__ENETDOWN (-ENETDOWN)
|
|
||||||
#else
|
|
||||||
# define UV__ENETDOWN (-4063)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENETUNREACH) && !defined(_WIN32)
|
|
||||||
# define UV__ENETUNREACH (-ENETUNREACH)
|
|
||||||
#else
|
|
||||||
# define UV__ENETUNREACH (-4062)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENFILE) && !defined(_WIN32)
|
|
||||||
# define UV__ENFILE (-ENFILE)
|
|
||||||
#else
|
|
||||||
# define UV__ENFILE (-4061)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOBUFS) && !defined(_WIN32)
|
|
||||||
# define UV__ENOBUFS (-ENOBUFS)
|
|
||||||
#else
|
|
||||||
# define UV__ENOBUFS (-4060)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENODEV) && !defined(_WIN32)
|
|
||||||
# define UV__ENODEV (-ENODEV)
|
|
||||||
#else
|
|
||||||
# define UV__ENODEV (-4059)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOENT) && !defined(_WIN32)
|
|
||||||
# define UV__ENOENT (-ENOENT)
|
|
||||||
#else
|
|
||||||
# define UV__ENOENT (-4058)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOMEM) && !defined(_WIN32)
|
|
||||||
# define UV__ENOMEM (-ENOMEM)
|
|
||||||
#else
|
|
||||||
# define UV__ENOMEM (-4057)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENONET) && !defined(_WIN32)
|
|
||||||
# define UV__ENONET (-ENONET)
|
|
||||||
#else
|
|
||||||
# define UV__ENONET (-4056)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOSPC) && !defined(_WIN32)
|
|
||||||
# define UV__ENOSPC (-ENOSPC)
|
|
||||||
#else
|
|
||||||
# define UV__ENOSPC (-4055)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOSYS) && !defined(_WIN32)
|
|
||||||
# define UV__ENOSYS (-ENOSYS)
|
|
||||||
#else
|
|
||||||
# define UV__ENOSYS (-4054)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOTCONN) && !defined(_WIN32)
|
|
||||||
# define UV__ENOTCONN (-ENOTCONN)
|
|
||||||
#else
|
|
||||||
# define UV__ENOTCONN (-4053)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOTDIR) && !defined(_WIN32)
|
|
||||||
# define UV__ENOTDIR (-ENOTDIR)
|
|
||||||
#else
|
|
||||||
# define UV__ENOTDIR (-4052)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOTEMPTY) && !defined(_WIN32)
|
|
||||||
# define UV__ENOTEMPTY (-ENOTEMPTY)
|
|
||||||
#else
|
|
||||||
# define UV__ENOTEMPTY (-4051)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOTSOCK) && !defined(_WIN32)
|
|
||||||
# define UV__ENOTSOCK (-ENOTSOCK)
|
|
||||||
#else
|
|
||||||
# define UV__ENOTSOCK (-4050)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOTSUP) && !defined(_WIN32)
|
|
||||||
# define UV__ENOTSUP (-ENOTSUP)
|
|
||||||
#else
|
|
||||||
# define UV__ENOTSUP (-4049)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPERM) && !defined(_WIN32)
|
|
||||||
# define UV__EPERM (-EPERM)
|
|
||||||
#else
|
|
||||||
# define UV__EPERM (-4048)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPIPE) && !defined(_WIN32)
|
|
||||||
# define UV__EPIPE (-EPIPE)
|
|
||||||
#else
|
|
||||||
# define UV__EPIPE (-4047)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPROTO) && !defined(_WIN32)
|
|
||||||
# define UV__EPROTO (-EPROTO)
|
|
||||||
#else
|
|
||||||
# define UV__EPROTO (-4046)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
|
|
||||||
# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT)
|
|
||||||
#else
|
|
||||||
# define UV__EPROTONOSUPPORT (-4045)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPROTOTYPE) && !defined(_WIN32)
|
|
||||||
# define UV__EPROTOTYPE (-EPROTOTYPE)
|
|
||||||
#else
|
|
||||||
# define UV__EPROTOTYPE (-4044)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EROFS) && !defined(_WIN32)
|
|
||||||
# define UV__EROFS (-EROFS)
|
|
||||||
#else
|
|
||||||
# define UV__EROFS (-4043)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ESHUTDOWN) && !defined(_WIN32)
|
|
||||||
# define UV__ESHUTDOWN (-ESHUTDOWN)
|
|
||||||
#else
|
|
||||||
# define UV__ESHUTDOWN (-4042)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ESPIPE) && !defined(_WIN32)
|
|
||||||
# define UV__ESPIPE (-ESPIPE)
|
|
||||||
#else
|
|
||||||
# define UV__ESPIPE (-4041)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ESRCH) && !defined(_WIN32)
|
|
||||||
# define UV__ESRCH (-ESRCH)
|
|
||||||
#else
|
|
||||||
# define UV__ESRCH (-4040)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ETIMEDOUT) && !defined(_WIN32)
|
|
||||||
# define UV__ETIMEDOUT (-ETIMEDOUT)
|
|
||||||
#else
|
|
||||||
# define UV__ETIMEDOUT (-4039)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ETXTBSY) && !defined(_WIN32)
|
|
||||||
# define UV__ETXTBSY (-ETXTBSY)
|
|
||||||
#else
|
|
||||||
# define UV__ETXTBSY (-4038)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EXDEV) && !defined(_WIN32)
|
|
||||||
# define UV__EXDEV (-EXDEV)
|
|
||||||
#else
|
|
||||||
# define UV__EXDEV (-4037)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EFBIG) && !defined(_WIN32)
|
|
||||||
# define UV__EFBIG (-EFBIG)
|
|
||||||
#else
|
|
||||||
# define UV__EFBIG (-4036)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENOPROTOOPT) && !defined(_WIN32)
|
|
||||||
# define UV__ENOPROTOOPT (-ENOPROTOOPT)
|
|
||||||
#else
|
|
||||||
# define UV__ENOPROTOOPT (-4035)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ERANGE) && !defined(_WIN32)
|
|
||||||
# define UV__ERANGE (-ERANGE)
|
|
||||||
#else
|
|
||||||
# define UV__ERANGE (-4034)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENXIO) && !defined(_WIN32)
|
|
||||||
# define UV__ENXIO (-ENXIO)
|
|
||||||
#else
|
|
||||||
# define UV__ENXIO (-4033)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EMLINK) && !defined(_WIN32)
|
|
||||||
# define UV__EMLINK (-EMLINK)
|
|
||||||
#else
|
|
||||||
# define UV__EMLINK (-4032)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is
|
|
||||||
* defined. Fortunately, its value is always 64 so it's possible albeit
|
|
||||||
* icky to hard-code it.
|
|
||||||
*/
|
|
||||||
#if defined(EHOSTDOWN) && !defined(_WIN32)
|
|
||||||
# define UV__EHOSTDOWN (-EHOSTDOWN)
|
|
||||||
#elif defined(__APPLE__) || \
|
|
||||||
defined(__DragonFly__) || \
|
|
||||||
defined(__FreeBSD__) || \
|
|
||||||
defined(__FreeBSD_kernel__) || \
|
|
||||||
defined(__NetBSD__) || \
|
|
||||||
defined(__OpenBSD__)
|
|
||||||
# define UV__EHOSTDOWN (-64)
|
|
||||||
#else
|
|
||||||
# define UV__EHOSTDOWN (-4031)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EREMOTEIO) && !defined(_WIN32)
|
|
||||||
# define UV__EREMOTEIO (-EREMOTEIO)
|
|
||||||
#else
|
|
||||||
# define UV__EREMOTEIO (-4030)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define UV_ERRNO_MAP(XX) \
|
|
||||||
XX(E2BIG, "argument list too long") \
|
|
||||||
XX(EACCES, "permission denied") \
|
|
||||||
XX(EADDRINUSE, "address already in use") \
|
|
||||||
XX(EADDRNOTAVAIL, "address not available") \
|
|
||||||
XX(EAFNOSUPPORT, "address family not supported") \
|
|
||||||
XX(EAGAIN, "resource temporarily unavailable") \
|
|
||||||
XX(EAI_ADDRFAMILY, "address family not supported") \
|
|
||||||
XX(EAI_AGAIN, "temporary failure") \
|
|
||||||
XX(EAI_BADFLAGS, "bad ai_flags value") \
|
|
||||||
XX(EAI_BADHINTS, "invalid value for hints") \
|
|
||||||
XX(EAI_CANCELED, "request canceled") \
|
|
||||||
XX(EAI_FAIL, "permanent failure") \
|
|
||||||
XX(EAI_FAMILY, "ai_family not supported") \
|
|
||||||
XX(EAI_MEMORY, "out of memory") \
|
|
||||||
XX(EAI_NODATA, "no address") \
|
|
||||||
XX(EAI_NONAME, "unknown node or service") \
|
|
||||||
XX(EAI_OVERFLOW, "argument buffer overflow") \
|
|
||||||
XX(EAI_PROTOCOL, "resolved protocol is unknown") \
|
|
||||||
XX(EAI_SERVICE, "service not available for socket type") \
|
|
||||||
XX(EAI_SOCKTYPE, "socket type not supported") \
|
|
||||||
XX(EALREADY, "connection already in progress") \
|
|
||||||
XX(EBADF, "bad file descriptor") \
|
|
||||||
XX(EBUSY, "resource busy or locked") \
|
|
||||||
XX(ECANCELED, "operation canceled") \
|
|
||||||
XX(ECHARSET, "invalid Unicode character") \
|
|
||||||
XX(ECONNABORTED, "software caused connection abort") \
|
|
||||||
XX(ECONNREFUSED, "connection refused") \
|
|
||||||
XX(ECONNRESET, "connection reset by peer") \
|
|
||||||
XX(EDESTADDRREQ, "destination address required") \
|
|
||||||
XX(EEXIST, "file already exists") \
|
|
||||||
XX(EFAULT, "bad address in system call argument") \
|
|
||||||
XX(EFBIG, "file too large") \
|
|
||||||
XX(EHOSTUNREACH, "host is unreachable") \
|
|
||||||
XX(EINTR, "interrupted system call") \
|
|
||||||
XX(EINVAL, "invalid argument") \
|
|
||||||
XX(EIO, "i/o error") \
|
|
||||||
XX(EISCONN, "socket is already connected") \
|
|
||||||
XX(EISDIR, "illegal operation on a directory") \
|
|
||||||
XX(ELOOP, "too many symbolic links encountered") \
|
|
||||||
XX(EMFILE, "too many open files") \
|
|
||||||
XX(EMSGSIZE, "message too long") \
|
|
||||||
XX(ENAMETOOLONG, "name too long") \
|
|
||||||
XX(ENETDOWN, "network is down") \
|
|
||||||
XX(ENETUNREACH, "network is unreachable") \
|
|
||||||
XX(ENFILE, "file table overflow") \
|
|
||||||
XX(ENOBUFS, "no buffer space available") \
|
|
||||||
XX(ENODEV, "no such device") \
|
|
||||||
XX(ENOENT, "no such file or directory") \
|
|
||||||
XX(ENOMEM, "not enough memory") \
|
|
||||||
XX(ENONET, "machine is not on the network") \
|
|
||||||
XX(ENOPROTOOPT, "protocol not available") \
|
|
||||||
XX(ENOSPC, "no space left on device") \
|
|
||||||
XX(ENOSYS, "function not implemented") \
|
|
||||||
XX(ENOTCONN, "socket is not connected") \
|
|
||||||
XX(ENOTDIR, "not a directory") \
|
|
||||||
XX(ENOTEMPTY, "directory not empty") \
|
|
||||||
XX(ENOTSOCK, "socket operation on non-socket") \
|
|
||||||
XX(ENOTSUP, "operation not supported on socket") \
|
|
||||||
XX(EPERM, "operation not permitted") \
|
|
||||||
XX(EPIPE, "broken pipe") \
|
|
||||||
XX(EPROTO, "protocol error") \
|
|
||||||
XX(EPROTONOSUPPORT, "protocol not supported") \
|
|
||||||
XX(EPROTOTYPE, "protocol wrong type for socket") \
|
|
||||||
XX(ERANGE, "result too large") \
|
|
||||||
XX(EROFS, "read-only file system") \
|
|
||||||
XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \
|
|
||||||
XX(ESPIPE, "invalid seek") \
|
|
||||||
XX(ESRCH, "no such process") \
|
|
||||||
XX(ETIMEDOUT, "connection timed out") \
|
|
||||||
XX(ETXTBSY, "text file is busy") \
|
|
||||||
XX(EXDEV, "cross-device link not permitted") \
|
|
||||||
XX(UNKNOWN, "unknown error") \
|
|
||||||
XX(EOF, "end of file") \
|
|
||||||
XX(ENXIO, "no such device or address") \
|
|
||||||
XX(EMLINK, "too many links") \
|
|
||||||
XX(EHOSTDOWN, "host is down") \
|
|
||||||
XX(EREMOTEIO, "remote I/O error") \
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
#define XX(code, _) UV_ ## code = UV__ ## code,
|
|
||||||
UV_ERRNO_MAP(XX)
|
|
||||||
#undef XX
|
|
||||||
UV_ERRNO_MAX = UV__EOF - 1
|
|
||||||
} uv_errno_t;
|
|
||||||
|
|
||||||
|
|
||||||
const char* uv_err_name(int err);
|
|
||||||
const char* uv_strerror(int err);
|
|
||||||
|
|
||||||
int uv_translate_posix_error(int err);
|
|
||||||
int get_uv_error(bool netErr = false);
|
|
||||||
const char* get_uv_errmsg(bool netErr = false);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* UV_ERRNO_H_ */
|
|
Binary file not shown.
@ -269,12 +269,12 @@
|
|||||||
<option name="number" value="Default" />
|
<option name="number" value="Default" />
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1513153608354</updated>
|
<updated>1513153608354</updated>
|
||||||
<workItem from="1513153610227" duration="5193000" />
|
<workItem from="1513153610227" duration="5467000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TimeTrackingManager">
|
<component name="TimeTrackingManager">
|
||||||
<option name="totallyTimeSpent" value="5193000" />
|
<option name="totallyTimeSpent" value="5467000" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<component name="ToolWindowManager">
|
||||||
<frame x="0" y="23" width="1852" height="1057" extended-state="6" />
|
<frame x="0" y="23" width="1852" height="1057" extended-state="6" />
|
||||||
|
Loading…
Reference in New Issue
Block a user