diff --git a/README.md b/README.md index 83cbe271350d4b2a633b29e4d64a13e80dd2ece6..5aacb6f1205ce5926afc3df3e563e261176a934d 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,118 @@ -# yangwebrtc +## MetaRTC(yangwebrtc) Overview -#### 介绍 -中国人自己的webrtc,可与谷歌webrtc类库互通。 +MetaRTC(yangwebrtc)是一个自主研发的支持Webrtc/Srt/Rtmp的rtc架构,包含多种视音频编解码和处理等。 +yangwebrtc为C++版本 +metaRTC为纯C版本 +https://gitee.com/metartc/metaRTC https://github.com/metartc/metaRTC -#### 软件架构 -软件架构说明 -#### 安装教程 +支持视频会议、高清录播直播、直播互动等多种视音频应用。 +可用于远程教育、远程医疗、指挥调度、安防监控、影视录播、协同办公、直播互动等多种行业应用。 +webrtc支持为自主研发,非谷歌lib,兼容webrtc协议 ,可与谷歌Lib和浏览器互通 +支持Srs sfu https://github.com/ossrs/srs/ +支持Linux/Windows操作系统,android/ios/mac版本正开发中 -1. xxxx -2. xxxx -3. xxxx +## MetaRTC(yangwebrtc)微信群 +加微信taihang82 + +### MetaRTC(yangwebrtc)功能 -#### 使用说明 + 1、视频编码 8bit:x264、x265、vaapi、nvenc等。 + 2、视频编码 10bit:x265、vaapi、nvenc等。 + 3、视频解码:ffmpeg和yangh264decoder。 + 4、VR:基于抠图实现虚拟视频的互动和录制、直播等。 + 5、8bit和10bit网络播放器:yangplayer + 6、音频:Opus、Aac、Speex、Mp3等音频编解码。 + 7、音频:AEC、AGC、ANS及声音合成等处理。 + 8、传输:webrtc、rtmp、srt,webrtc为自己实现,没使用谷歌lib库。 + 9、直播:rtmp、srt、webrtc、HLS、HTTP-FLV。 + 10、8bit录制:h264、h265的mp4和flv。 + 11、10bit录制:h265的mp4 + 12、实现了屏幕共享与控制。 + 13、实现了声音和图像多种处理。 + 14、专业摄像头的云台控制与多镜头导播切换。 -1. xxxx -2. xxxx -3. xxxx -#### 参与贡献 +### 目录简介 +#### libyangrtc2 +yangwebrtc基础类库,实现所有核心功能 +#### yangpushstream2 +webrtc推流系统demo +#### yangplayer2 +webrtc拉流播放系统demo -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +### yangwebrtc3.0规划 + 1、支持android/ios/mac等。 + 2、webrtc支持h265、av1等。 + 3、传输加密支持国密加密,修改srtp支持国密。 + 4、实现10位、16位全链路打通,从采集、编码、传输、解码、播放这些环节全部支持10/16位。 + -#### 特技 +## Getting Started + +Remark: MetaRTC(yangwebrtc)2.0 is developing and not stable. + +下载源码,推荐ubuntu或者win10 + +git clone https://gitee.com/metartc/yangwebrtc.git + +### 服务器部署 + +启动服务程序,推荐Srs4.0.146及以后版本,下载编译参考http://github.com/ossrs/srs#usage + +​ objs/srs -c conf/https.rtc.conf +或者 + objs/srs -c conf/rtc.conf + + + +### 客户端编译 +#### 编译操作教程视频 +https://www.bilibili.com/video/BV1d3411r742/ +https://gitee.com/metartc/yangwebrtc/releases/yangrtc2.032_video +#### 编译教程 +gpu编码器搭建游戏教育等在线低延迟直播 https://blog.csdn.net/m0_56595685/article/details/121575105 +搭建兼容webrtc的跨平台的云桌面 https://blog.csdn.net/m0_56595685/article/details/121410868 +搭建虚拟背景和美颜webrtc直播系统 https://blog.csdn.net/m0_56595685/article/details/121575105 +搭建视频会议 https://blog.csdn.net/m0_56595685/article/details/121304109 +搭建H264和H265的MP4录制系统 https://blog.csdn.net/m0_56595685/article/details/121720754 +搭建H265(HEVC)的webrtc应用 https://blog.csdn.net/m0_56595685/article/details/121880362 +#### 编译 +用QT(推荐5.14.2及以上版本)打开工程libyangrtc2、yangpushstream2、yangplayer2。 +QT下载地址:https://download.qt.io/archive/qt/5.14/5.14.2/ +静态库需要三个,ssl/crypto/srtp2,目录里已经有编译好的,如果有问题请再编译新的, 然后顺序编译即可。 +Remark: **windows下qt编译器为msvc,推荐vs2019** +Remark:ubuntu默认不支持opengl sudo apt-get install libgl1-mesa-dev + #### thirdparty下载链接 +https://gitee.com/yangrtc/yangwebrtc/releases/thirdparty2.0.016 +编译后的二进制文件在当前bin目录下 +#### debug目录 +linux:bin/app_debug bin/lib_debug +windows:bin/app_win_debug bin/lib_win_debug +#### release目录 +linux:bin/app_release bin/lib_release +windows:bin/app_win_release bin/lib_win_release + + **remark:程序需要一些动态库才能运行,所需动态库在lib文件夹里,lib文件夹在runtime包中 ** + **remark:如用qt调试,需将yang_config.ini和lib目录copy到debug和release目录下 ** +yang_config.ini和lib目录下载链接:https://github.com/yangrtc/yangwebrtc/releases/tag/2.0-runtime +#### windows qt debug dlls +![输入图片说明](https://images.gitee.com/uploads/images/2021/1008/160543_77ba86ff_9074428.png "屏幕截图.png") +#### windows lib dlls +![输入图片说明](https://images.gitee.com/uploads/images/2021/0918/170143_f5570da6_9074428.png "屏幕截图.png") +#### linux lib so +![输入图片说明](https://images.gitee.com/uploads/images/2021/0918/170015_05b8c102_9074428.png "屏幕截图.png") + + +### 第三方系统源码 + +https://gitee.com/metartc/yangwebrtc/releases/thirdparty2.0 + +里面不包含支持vr动态库,如需支持vr,下载opencv3 + +https://github.com/opencv/opencv/releases/tag/3.4.13 及以上版本 + +yang_config.ini配置参数http://gitee.com/metartc/yangwebrtc/wikis/yang_config_file -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/include/Yang_Config.h b/include/Yang_Config.h new file mode 100644 index 0000000000000000000000000000000000000000..b40234036e7201068290d635f63411a19f57fa2a --- /dev/null +++ b/include/Yang_Config.h @@ -0,0 +1,24 @@ +/* + * Yang_Config.h + * + * Created on: 2020年12月19日 + * Author: yang + */ + +#ifndef INCLUDE_YANG_CONFIG_H_ +#define INCLUDE_YANG_CONFIG_H_ + +#define Yang_HaveLibva 0 +#define Yang_Have10bit 0 +#define Yang_HavePicUtilFfmpeg 0 +#define Yang_HaveWebsockets 1 +#define Yang_HaveVr 0 +#define Yang_GPU_Encoding 0 +#define Yang_H265_Encoding 1 +#ifdef _WIN32 +#define Yang_Ffmpeg_UsingSo 0 +#else +#define Yang_Ffmpeg_UsingSo 1 +#endif + +#endif /* INCLUDE_YANG_CONFIG_H_ */ diff --git a/include/yangaudiodev/YangAudioCapture.h b/include/yangaudiodev/YangAudioCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..de74d81f5fc21fd64abbfaa5e41c205882949d07 --- /dev/null +++ b/include/yangaudiodev/YangAudioCapture.h @@ -0,0 +1,41 @@ +#ifndef YANGAUDIOCAPTURE_H +#define YANGAUDIOCAPTURE_H + +#include +#include +#include +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include +#include "yangutil/sys/YangThread.h" +#include "yangutil/sys/YangLog.h" +using namespace std; + +class YangAudioCapture:public YangThread +{ + public: + YangAudioCapture(); + virtual ~YangAudioCapture(); + public: + + int32_t aIndex; + int32_t m_isStart; + virtual int32_t init()=0; + virtual void setCatureStart()=0; + virtual void setCatureStop()=0; + virtual void setOutAudioBuffer(YangAudioBuffer *pbuffer)=0; + virtual void setPlayAudoBuffer(YangAudioBuffer *pbuffer)=0; + virtual void setAec(YangAecBase *paec)=0; + virtual void setInAudioBuffer(vector *pbuffer)=0; + virtual void setPreProcess(YangPreProcess *pp)=0; + + void stop(); + protected: + void run(); + YangContext *m_context; + virtual void startLoop()=0; + virtual void stopLoop()=0; + +}; + +#endif // YANGAUDIOCAPTURE_H diff --git a/include/yangaudiodev/YangAudioCaptureData.h b/include/yangaudiodev/YangAudioCaptureData.h new file mode 100644 index 0000000000000000000000000000000000000000..4bfa3818d16bfdcf8bd8ca7c961dcbb6324aba9e --- /dev/null +++ b/include/yangaudiodev/YangAudioCaptureData.h @@ -0,0 +1,33 @@ + +#ifndef YANGCAPTURE_WIN_API_YANGCAPTUREAUDIODATA_H_ +#define YANGCAPTURE_WIN_API_YANGCAPTUREAUDIODATA_H_ +#include +#include +#include +#include +#include +#include +class YangAudioCaptureData { +public: + YangAudioCaptureData(); + virtual ~YangAudioCaptureData(); + void initIn(int psample,int pchannel); + void initOut(int psample,int pchannel); + void caputure(YangFrame* audioFrame); + int getOutLength(); + YangCaptureCallback* m_cb; + +private: + uint8_t* m_cache; + int m_cacheLen; + int m_size; + int m_pos; + +private: + YangAudioResample m_res; + YangFrame m_audioFrame; + + void captureData(); +}; + +#endif /* YANGCAPTURE_WIN_API_YANGCAPTUREAUDIODATA_H_ */ diff --git a/include/yangaudiodev/YangAudioDeviceQuery.h b/include/yangaudiodev/YangAudioDeviceQuery.h new file mode 100644 index 0000000000000000000000000000000000000000..b65f49349879378a6e9b9c73961bce81161032d3 --- /dev/null +++ b/include/yangaudiodev/YangAudioDeviceQuery.h @@ -0,0 +1,28 @@ +#ifndef INCLUDE_YANGAUDIODEV_YANGAUDIODEVICEQUERY_H_ +#define INCLUDE_YANGAUDIODEV_YANGAUDIODEVICEQUERY_H_ +#include +#include + +using namespace std; +struct YangAudioDeivce{ + string name; + string deviceName; + string subName; + int32_t aIndex; + int32_t aSubIndex; + int32_t aIdx; +}; +class YangAudioDeviceQuery { +public: + YangAudioDeviceQuery(); + virtual ~YangAudioDeviceQuery(); + vector* getCaptureDeviceList(); + vector* getPlayDeviceList(); +private: + vector m_captureDeviceList; + vector m_playDeviceList; + void getDeviceList(int32_t stream,vector* plist); + +}; + +#endif /* INCLUDE_YANGAUDIODEV_YANGAUDIODEVICEQUERY_H_ */ diff --git a/include/yangaudiodev/YangAudioPlay.h b/include/yangaudiodev/YangAudioPlay.h new file mode 100644 index 0000000000000000000000000000000000000000..8bf56413e6c7407d62147f0f38f02e7e86d376a8 --- /dev/null +++ b/include/yangaudiodev/YangAudioPlay.h @@ -0,0 +1,58 @@ +#ifndef YangAudioPlay_H +#define YangAudioPlay_H +//#include "yangutil/UtilPlay.h" +#include +#include +#include +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#define YangAudioBufferMaxNum 10 + +#include +#include + +using namespace std; +//#define SIZE_AUDIO_FRAME 4096 + + + +class YangAudioPlay:public YangThread +{ + public: + YangAudioPlay(YangContext* pcontext); + virtual ~YangAudioPlay(); + public: + + int32_t aIndex; + virtual int init()=0; + void setAudioBuffers(vector *paudioList); + void setAudioBuffer(YangAudioPlayBuffer *paudioList); + void setAecBase(YangAecBase* pace); + int32_t m_aecInit=0; + int32_t m_isStart; + void stop(); + YangAudioRenderData m_audioData; + protected: + virtual void startLoop()=0; + virtual void stopLoop()=0; + + void run(); + YangContext *m_context; + YangAecBase *m_ace; + YangAudioMix mix; + int m_frames; + int m_channel; + int m_sample; + + + + + private: + + + + + }; + +#endif // YANGAUDIOCAPTURE_H diff --git a/include/yangaudiodev/YangAudioPlayerSdl.h b/include/yangaudiodev/YangAudioPlayerSdl.h new file mode 100644 index 0000000000000000000000000000000000000000..de5bf0bde92ba1fb2498b9757febac6afdfaa655 --- /dev/null +++ b/include/yangaudiodev/YangAudioPlayerSdl.h @@ -0,0 +1,67 @@ +/* + * YangAudioPlayerSdl.h + * + * Created on: 2020年9月4日 + * Author: yang + */ + +#ifndef YANGPLAYER_INCLUDE_YANGAUDIOPLAYSDL1_H_ +#define YANGPLAYER_INCLUDE_YANGAUDIOPLAYSDL1_H_ + +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#include "yangutil/sys/YangLoadLib.h" +#include + +class YangAudioPlayerSdl:public YangThread{ +public: + YangAudioPlayerSdl(YangAudioInfo *pcontext); + ~YangAudioPlayerSdl(); + void init(); + void* (*yang_SDL_memset)(SDL_OUT_BYTECAP(len) void *dst, int32_t c, size_t len); + void (*yang_SDL_MixAudio)(Uint8 * dst, const Uint8 * src, Uint32 len, int32_t volume); + void setAudioList(YangAudioPlayBuffer *pal); + int32_t m_isStart; + void stop(); + + int32_t m_frames; + int32_t m_channel; + int32_t m_sample; + static void fill_audio(void *udata, Uint8 *stream, int32_t len); +protected: + void startLoop(); + void stopLoop(); + void run(); + // uint8_t *m_buffer[YangAudioBufferMaxNum]; +private: + YangAudioInfo *m_context; + YangAudioPlayBuffer *m_in_audioBuffer; + static YangAudioPlayerSdl* m_instance; + int32_t isInit; + + void closeAudio(); + int32_t ret; + int32_t m_size; + int32_t m_loops; + + SDL_AudioSpec wanted; + void playSDL(uint8_t *p_data); + void initSDL(); + void startLoopSDL(); + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + int32_t (*yang_SDL_Init)(Uint32 flags); + void (*yang_SDL_Delay)(Uint32 ms); + + const char * (*yang_SDL_GetError)(void); + + int32_t (*yang_SDL_OpenAudio)(SDL_AudioSpec * desired, SDL_AudioSpec * obtained); + + void (*yang_SDL_PauseAudio)(int32_t pause_on); + void (*yang_SDL_CloseAudio)(void); + +}; + +#endif /* YANGPLAYER_INCLUDE_YANGAUDIOPLAYSDL_H_ */ diff --git a/include/yangaudiodev/YangAudioRenderData.h b/include/yangaudiodev/YangAudioRenderData.h new file mode 100644 index 0000000000000000000000000000000000000000..e3eef4cf9c86a8e33d5c788ea2f60306a25f04c0 --- /dev/null +++ b/include/yangaudiodev/YangAudioRenderData.h @@ -0,0 +1,68 @@ +/* + * YangAudioDataManager.h + * + * Created on: 2021年9月21日 + * Author: yang + */ + +#ifndef INCLUDE_YANGCAPTURE_YANGRENDERAUDIODATA_H_ +#define INCLUDE_YANGCAPTURE_YANGRENDERAUDIODATA_H_ +#include +#include +#include +#include +#include + +#include +using namespace std; + +class YangAudioRenderData { +public: + YangAudioRenderData(); + virtual ~YangAudioRenderData(); + +public: + vector *m_in_audioBuffers; + YangSynBuffer* m_syn; + YangPreProcess* m_preProcess; + YangAudioResample m_res; + void setAec(); + void setRenderLen(int plen); + + void initRender(int psample,int pchannel); + void initPlay(int psample,int pchannel); + uint8_t* getAudioRef(YangFrame* pframe); + uint8_t* getRenderAudioData(int len); + uint8_t* getAecAudioData(); + void setInAudioBuffer(YangSynBuffer *pal); + void setInAudioBuffers(vector *pal); + +private: + bool m_hasAec; + int m_aecBufLen; + int m_mixPos; + int m_renderLen; + uint8_t* m_aecBuf; + + + uint8_t* m_cache; + int m_cacheLen; + int m_size; + int m_pos; + + uint8_t* m_mixBuf; + + YangFrame m_audioFrame; + + YangAudioMix m_mix; + +private: + + uint8_t* getAudioData(YangFrame* frame); + + void setAudioData(YangFrame* frame); + bool hasData(); + +}; + +#endif /* INCLUDE_YANGCAPTURE_YANGRENDERAUDIODATA_H_ */ diff --git a/include/yangavutil/audio/YangAecBase.h b/include/yangavutil/audio/YangAecBase.h new file mode 100644 index 0000000000000000000000000000000000000000..15ccc35b7cd0f5e2e966ec144e55a070abd3230d --- /dev/null +++ b/include/yangavutil/audio/YangAecBase.h @@ -0,0 +1,30 @@ +/* + * YangAecBase.h + * + * Created on: 2019年11月16日 + * Author: yang + */ + +#ifndef YANGUTIL_AUDIO_YANGAECBASE_H_ +#define YANGUTIL_AUDIO_YANGAECBASE_H_ +#include "yangutil/buffer/YangAudioBuffer.h" + +class YangAecBase { +public: + YangAecBase(); + virtual ~YangAecBase(); + virtual void init(int32_t pFrameSize,int32_t sampling_rate,int32_t pchannel)=0; + virtual void echo_state_reset()=0; + virtual void echo_playback(short *play)=0; + virtual void put_echo_playback(uint8_t *play,int32_t plen)=0; + virtual void echo_capture(short *rec, short *out)=0; + virtual void preprocess_run(short* pcm)=0; + virtual void echo_cancellation(const short *rec, const short *play, short *out)=0; + virtual void setPlayBuffer(YangAudioBuffer *pab)=0; + int32_t m_channel; + int32_t m_frameSize; + int32_t m_sampleRate; + int32_t m_echoPath; +}; + +#endif /* YANGUTIL_AUDIO_YANGAECBASE_H_ */ diff --git a/include/yangavutil/audio/YangAudioFactory.h b/include/yangavutil/audio/YangAudioFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..6f7429ba6111f4a0f141c2dfb083b5ef9e67296f --- /dev/null +++ b/include/yangavutil/audio/YangAudioFactory.h @@ -0,0 +1,21 @@ +/* + * YangAudioFactory.h + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#ifndef YANGAUDIOPROC_YANGAUDIOFACTORY_H_ +#define YANGAUDIOPROC_YANGAUDIOFACTORY_H_ +#include +#include + +class YangAudioFactory { +public: + YangAudioFactory(); + virtual ~YangAudioFactory(); + YangAecBase* createAec(); + YangPreProcess* createPreProcess(); +}; + +#endif /* YANGAUDIOPROC_YANGAUDIOFACTORY_H_ */ diff --git a/include/yangavutil/audio/YangAudioMix.h b/include/yangavutil/audio/YangAudioMix.h new file mode 100644 index 0000000000000000000000000000000000000000..6996f8dbb61b71145faeb4733ebc6e6faa5de69f --- /dev/null +++ b/include/yangavutil/audio/YangAudioMix.h @@ -0,0 +1,29 @@ +/* + * YangAudioMix.h + * + * Created on: 2020年9月25日 + * Author: yang + */ + +#ifndef YANGUTIL_AUDIO_YANGAUDIOMIX_H_ +#define YANGUTIL_AUDIO_YANGAUDIOMIX_H_ +#include +#define SIZE_AUDIO_FRAME 4096 + +class YangAudioMix { +public: + YangAudioMix(); + virtual ~YangAudioMix(); + void yangMix4(uint8_t *dst, uint8_t *src, int32_t len,int32_t pvolume); + void yangMix3(uint8_t *dst, uint8_t *src, int32_t len,int32_t pvolume); + //void yangMix(uint8_t *sourseFile[SIZE_AUDIO_FRAME], int32_t number, uint8_t *objectFile); + //void yangMixs1(uint8_t *dst, uint8_t *src, int32_t len, int32_t volume); + void yangMix1(uint8_t *dst, uint8_t *src, int32_t len, int32_t volume); + void yangMix1(short *dst, short *src, int32_t len, int32_t volume); + void yangMix2(uint8_t *pin, uint8_t *pout,int32_t len,int32_t pvolume); +private: + int32_t m_yangAudioMAX; + int32_t m_yangAudioMIN ; +}; + +#endif /* YANGUTIL_AUDIO_YANGAUDIOMIX_H_ */ diff --git a/include/yangavutil/audio/YangAudioUtil.h b/include/yangavutil/audio/YangAudioUtil.h new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd00a05d62f80babaf7823294ef40eeefa2bf --- /dev/null +++ b/include/yangavutil/audio/YangAudioUtil.h @@ -0,0 +1,67 @@ +/* + * YangAudioUtil.h + * + * Created on: 2020年9月28日 + * Author: yang + */ + +#ifndef SRC_YANGUTIL_YANGAUDIOUTIL_H_ +#define SRC_YANGUTIL_YANGAUDIOUTIL_H_ +#include +#include +#include +#include +//#include +class YangAudioResample{ +public: + YangAudioResample(int ms=20); + virtual ~YangAudioResample(); + void initIn(int psample,int pchannel); + void initOut(int psample,int pchannel); + void init(int insample,int inchannel,int outsample,int outchannel,int ms); + void setIntervalTime(int ms); + int getOutBytes(); + int getInBytes(); + int getInSample(); + int getOutSample(); + int getInChannel(); + int getOutChannel(); + int resample(YangFrame* audioFrame); +private: + int m_inSample; + int m_outSample; + int m_inChannel; + int m_outChannel; + + int m_intervalTime; + + + int m_inLen; + int m_outLen; + int m_inFrames; + int m_outFrames; + bool m_sampleTrans; + bool m_channelTrans; + bool m_isTrans; + uint8_t* m_inBuf; + uint8_t* m_outBuf; + + YangResample m_res; + //YangSwResample m_res1; + + bool m_isInitTrans; + void initTrans(); + void initParam(); + +}; + + +int32_t MonoToStereo(int16_t *pData, int16_t *dData, int32_t samples_per_channel); +int32_t StereoToMono(const int16_t* src_audio,int16_t* dst_audio,int32_t samples_per_channe); +uint64_t Resample_s16(const int16_t *input, int16_t *output, int32_t inSampleRate, int32_t outSampleRate, uint64_t inputSize, + uint32_t channels); +short FloatS16ToS16(float v); +int16_t maxAbsValueW16C(const int16_t* vector, size_t length); +void ComputeLevel(const int16_t* data, size_t length); + +#endif /* SRC_YANGUTIL_YANGAUDIOUTIL_H_ */ diff --git a/include/yangavutil/audio/YangMakeWave.h b/include/yangavutil/audio/YangMakeWave.h new file mode 100644 index 0000000000000000000000000000000000000000..58168390b2f4693e2f1fe9f2491869c09818bb30 --- /dev/null +++ b/include/yangavutil/audio/YangMakeWave.h @@ -0,0 +1,38 @@ +#ifndef _YangMakeWave_H_ +#define _YangMakeWave_H_ + +#include +#include "stdio.h" + +typedef short Int16; +typedef int32_t Int32; +typedef struct { + char fileID[4]; + Int32 fileleth; + char wavTag[4]; + char FmtHdrID[4]; + Int32 FmtHdrLeth; + Int16 FormatTag; + Int16 Channels; + Int32 SamplesPerSec; + Int32 AvgBytesPerSec; + Int16 BlockAlign; + Int16 BitsPerSample; + char DataHdrID[4]; + Int32 DataHdrLeth; +} WaveHdr; +class YangMakeWave{ +public: + YangMakeWave(); + FILE *waveFile; + void init(); + void start(int32_t pisMono,char * filename); + void write(uint8_t *data,int32_t len); + void stop(); +void writeHeader(int32_t isMono,FILE *WavFile,unsigned long len); +int32_t isMp3(char* p); +//void updateLameTagFrame(lame_global_flags* gfp, FILE* fpStream); +int32_t PCMSize; +int32_t m_isMono; +}; +#endif diff --git a/include/yangavutil/audio/YangPreProcess.h b/include/yangavutil/audio/YangPreProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..e101eb1e15af86c96505652b209a3080ab74a501 --- /dev/null +++ b/include/yangavutil/audio/YangPreProcess.h @@ -0,0 +1,24 @@ +/* + * YangAudioPreProcess.h + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#ifndef YANGUTIL_AUDIO_YANGPREPROCESS_H_ +#define YANGUTIL_AUDIO_YANGPREPROCESS_H_ +#include + +class YangPreProcess { +public: + YangPreProcess(); + virtual ~YangPreProcess(); + virtual void init(int32_t pFrameSize,int32_t sampling_rate,int32_t pchannel)=0; + virtual void state_reset()=0; + virtual void preprocess_run(short* pcm)=0; + int32_t m_channel; + int32_t m_frameSize; + int32_t m_sampleRate; +}; + +#endif /* YANGUTIL_AUDIO_YANGPREPROCESS_H_ */ diff --git a/include/yangavutil/audio/YangResample.h b/include/yangavutil/audio/YangResample.h new file mode 100644 index 0000000000000000000000000000000000000000..61d62a25802eb126808e32dc8d039712f15e9cff --- /dev/null +++ b/include/yangavutil/audio/YangResample.h @@ -0,0 +1,39 @@ +/* + * YangResample.h + * + * Created on: 2020年9月10日 + * Author: yang + */ + +#ifndef YANGAUDIOPROC_YANGRESAMPLE_H_ +#define YANGAUDIOPROC_YANGRESAMPLE_H_ +#include "speex/speex_resampler.h" +#include "yangutil/sys/YangLoadLib.h" + +class YangResample { +public: + YangResample(); + virtual ~YangResample(); + void resample(const short *pin,uint32_t pinLen,short* pout,uint32_t *poutLen); + void init(int32_t pchannel,int32_t pinsample,int32_t poutsample); + int32_t m_in_sample,m_out_sample; + int32_t m_contextt; + int32_t m_channel; + SpeexResamplerState *m_state; + +private: + spx_uint32_t m_in_len; + spx_uint32_t m_out_len; + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + SpeexResamplerState *(*yang_speex_resampler_init)(spx_uint32_t nb_channels,spx_uint32_t in_rate, spx_uint32_t out_rate,int32_t quality,int32_t *err); + + int32_t (*yang_speex_resampler_process_int)(SpeexResamplerState *st,spx_uint32_t channel_index,const spx_int16_t *in, + spx_uint32_t *in_len,spx_int16_t *out,spx_uint32_t *out_len); + int32_t (*yang_speex_resampler_process_interleaved_int)(SpeexResamplerState *st, const spx_int16_t *in,spx_uint32_t *in_len, + spx_int16_t *out,spx_uint32_t *out_len); + void (*yang_speex_resampler_destroy)(SpeexResamplerState *st); +}; + +#endif /* YANGAUDIOPROC_YANGRESAMPLE_H_ */ diff --git a/include/yangavutil/audio/YangSwResample.h b/include/yangavutil/audio/YangSwResample.h new file mode 100644 index 0000000000000000000000000000000000000000..222f4520eb952431d122e8fb8d0f2638e84eb974 --- /dev/null +++ b/include/yangavutil/audio/YangSwResample.h @@ -0,0 +1,26 @@ +#ifndef YANGSWRESAMPLE_H +#define YANGSWRESAMPLE_H + +#include +#include +#include +#include +class YangSwResample +{ +public: + YangSwResample(); + ~YangSwResample(); + void resample(const uint8_t *pin,uint32_t pinLen,uint8_t* pout,uint32_t *poutLen); + int init(int32_t pchannel,int32_t pinsample,int32_t poutsample,int32_t pframesize); +private: + struct SwrContext* swr_ctx; + int32_t m_inSample; + int32_t m_outSample; + int32_t m_contextt; + int32_t m_channel; + int32_t m_frameSize; + + uint8_t** m_swrData; +}; + +#endif // YANGSWRESAMPLE_H diff --git a/include/yangavutil/video/YangBittype.h b/include/yangavutil/video/YangBittype.h new file mode 100644 index 0000000000000000000000000000000000000000..c165407b85bd07d7e19f1be443f667956533a387 --- /dev/null +++ b/include/yangavutil/video/YangBittype.h @@ -0,0 +1,259 @@ +#ifndef YANGbittype_H_ +#define YANGbittype_H_ +#include "stdint.h" +#define Yang_QP_MAX_NUM (51 + 6*6) +typedef struct YangGetBitContext { + uint8_t *buffer, *buffer_end; + int32_t index; + int32_t size_in_bits; + int32_t size_in_bits_plus8; +} YangGetBitContext; +enum YangPictureType { + Yang_PICTURE_TYPE_NONE = 0, ///< Undefined + Yang_PICTURE_TYPE_I, ///< Intra + Yang_PICTURE_TYPE_P, ///< Predicted + Yang_PICTURE_TYPE_B, ///< Bi-dir predicted + Yang_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4 + Yang_PICTURE_TYPE_SI, ///< Switching Intra + Yang_PICTURE_TYPE_SP, ///< Switching Predicted + Yang_PICTURE_TYPE_BI, ///< BI type +}; +typedef struct YangPredWeightTable { + int32_t use_weight; + int32_t use_weight_chroma; + int32_t luma_log2_weight_denom; + int32_t chroma_log2_weight_denom; + int32_t luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag + int32_t chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + // The following 2 can be changed to char but that causes a 10 CPU cycles speed loss + int32_t luma_weight[48][2][2]; + int32_t chroma_weight[48][2][2][2]; + int32_t implicit_weight[48][48][2]; +} YangPredWeightTable; +typedef struct YangNAL { + uint8_t *rbsp_buffer; + + int32_t size; + uint8_t *data; + + /** + * Size, in bits, of just the data, excluding the stop bit and any trailing + * padding. I.e. what HEVC calls SODB. + */ + int32_t size_bits; + + int32_t raw_size; + uint8_t *raw_data; + + YangGetBitContext gb; + + /** + * NAL unit type + */ + int32_t type; + + /** + * HEVC only, nuh_temporal_id_plus_1 - 1 + */ + int32_t temporal_id; + + int32_t skipped_bytes; + int32_t skipped_bytes_pos_size; + int32_t *skipped_bytes_pos; + /** + * H.264 only, nal_ref_idc + */ + int32_t ref_idc; +} YangNAL; + +typedef struct YangRBSP { + uint8_t *rbsp_buffer; + int32_t rbsp_buffer_alloc_size; + int32_t rbsp_buffer_size; +} YangRBSP; + +/* an input packet split into unescaped NAL units */ +typedef struct YangPacket { + YangNAL *nals; + YangRBSP rbsp; + int32_t nb_nals; + int32_t nals_allocated; +} YangPacket; +typedef struct YangRational{ + int32_t num; ///< Numerator + int32_t den; ///< Denominator +} YangRational; +typedef enum Yang_MMCOOpcode { + Yang_MMCO_END = 0, + Yang_MMCO_SHORT2UNUSED, + Yang_MMCO_LONG2UNUSED, + Yang_MMCO_SHORT2LONG, + Yang_MMCO_SET_MAX_LONG, + Yang_MMCO_RESET, + Yang_MMCO_LONG, +} Yang_MMCOOpcode; +typedef struct YangMMCO { + Yang_MMCOOpcode opcode; + int32_t short_pic_num; ///< pic_num without wrapping (pic_num & max_pic_num) + int32_t long_arg; ///< index, pic_num, or num long refs depending on opcode +} YangMMCO; + +enum YangColorTransferCharacteristic { + Yang_TRC_RESERVED0 = 0, + Yang_TRC_BT709 = 1, ///< also ITU-R BT1361 + Yang_TRC_UNSPECIFIED = 2, + Yang_TRC_RESERVED = 3, + Yang_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + Yang_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + Yang_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + Yang_TRC_SMPTE240M = 7, + Yang_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + Yang_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + Yang_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + Yang_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + Yang_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + Yang_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + Yang_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system + Yang_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system + Yang_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + Yang_TRC_SMPTEST2084 = Yang_TRC_SMPTE2084, + Yang_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + Yang_TRC_SMPTEST428_1 = Yang_TRC_SMPTE428, + Yang_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + Yang_TRC_NB ///< Not part of ABI +}; +enum YangColorPrimaries { + Yang_PRI_RESERVED0 = 0, + Yang_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + Yang_PRI_UNSPECIFIED = 2, + Yang_PRI_RESERVED = 3, + Yang_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + Yang_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + Yang_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + Yang_PRI_SMPTE240M = 7, ///< functionally identical to above + Yang_PRI_FILM = 8, ///< colour filters using Illuminant C + Yang_PRI_BT2020 = 9, ///< ITU-R BT2020 + Yang_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + Yang_PRI_SMPTEST428_1 = Yang_PRI_SMPTE428, + Yang_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + Yang_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + Yang_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors + Yang_PRI_NB ///< Not part of ABI +}; +enum YangColorSpace { + Yang_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) + Yang_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + Yang_SPC_UNSPECIFIED = 2, + Yang_SPC_RESERVED = 3, + Yang_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + Yang_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + Yang_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + Yang_SPC_SMPTE240M = 7, ///< functionally identical to above + Yang_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + Yang_SPC_YCOCG = Yang_SPC_YCGCO, + Yang_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + Yang_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + Yang_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + Yang_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + Yang_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + Yang_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + Yang_SPC_NB ///< Not part of ABI +}; +typedef struct Yang_SPS { + uint32_t sps_id; + int32_t profile_idc; + int32_t level_idc; + int32_t chroma_format_idc; + int32_t transform_bypass; ///< qpprime_y_zero_transform_bypass_flag + int32_t log2_max_frame_num; ///< log2_max_frame_num_minus4 + 4 + int32_t poc_type; ///< pic_order_cnt_type + int32_t log2_max_poc_lsb; ///< log2_max_pic_order_cnt_lsb_minus4 + int32_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + int32_t poc_cycle_length; ///< num_ref_frames_in_pic_order_cnt_cycle + int32_t ref_frame_count; ///< num_ref_frames + int32_t gaps_in_frame_num_allowed_flag; + int32_t mb_width; ///< pic_width_in_mbs_minus1 + 1 + ///< (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag) + int32_t mb_height; + int32_t frame_mbs_only_flag; + int32_t mb_aff; ///< mb_adaptive_frame_field_flag + int32_t direct_8x8_inference_flag; + int32_t crop; ///< frame_cropping_flag + + /* those 4 are already in luma samples */ + uint32_t crop_left; ///< frame_cropping_rect_left_offset + uint32_t crop_right; ///< frame_cropping_rect_right_offset + uint32_t crop_top; ///< frame_cropping_rect_top_offset + uint32_t crop_bottom; ///< frame_cropping_rect_bottom_offset + int32_t vui_parameters_present_flag; + YangRational sar; + int32_t video_signal_type_present_flag; + int32_t full_range; + int32_t colour_description_present_flag; + //enum YangorPrimaries + int32_t color_primaries; + //enum YangorTransferCharacteristic + int32_t color_trc; + //enum YangorSpace + int32_t colorspace; + int32_t timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + int32_t fixed_frame_rate_flag; + short offset_for_ref_frame[256]; // FIXME dyn aloc? + int32_t bitstream_restriction_flag; + int32_t num_reorder_frames; + int32_t scaling_matrix_present; + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + int32_t nal_hrd_parameters_present_flag; + int32_t vcl_hrd_parameters_present_flag; + int32_t pic_struct_present_flag; + int32_t time_offset_length; + int32_t cpb_cnt; ///< See H.264 E.1.2 + int32_t initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 + int32_t cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 + int32_t dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 + int32_t bit_depth_luma; ///< bit_depth_luma_minus8 + 8 + int32_t bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 + int32_t residual_color_transform_flag; ///< residual_colour_transform_flag + int32_t constraint_set_flags; ///< constraint_set[0-3]_flag + // uint8_t data[4096]; + // size_t data_size; +} Yang_SPS; + +/** + * Picture parameter set + */ +typedef struct Yang_PPS { + uint32_t sps_id; + int32_t cabac; ///< entropy_coding_mode_flag + int32_t pic_order_present; ///< pic_order_present_flag + int32_t slice_group_count; ///< num_slice_groups_minus1 + 1 + int32_t mb_slice_group_map_type; + uint32_t ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 + int32_t weighted_pred; ///< weighted_pred_flag + int32_t weighted_bipred_idc; + int32_t init_qp; ///< pic_init_qp_minus26 + 26 + int32_t init_qs; ///< pic_init_qs_minus26 + 26 + int32_t chroma_qp_index_offset[2]; + int32_t deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag + int32_t constrained_intra_pred; ///< constrained_intra_pred_flag + int32_t redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag + int32_t transform_8x8_mode; ///< transform_8x8_mode_flag + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + uint8_t chroma_qp_table[2][Yang_QP_MAX_NUM+1]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table + int32_t chroma_qp_diff; + //uint8_t data[4096]; + // size_t data_size; + + uint32_t dequant4_buffer[6][Yang_QP_MAX_NUM + 1][16]; + uint32_t dequant8_buffer[6][Yang_QP_MAX_NUM + 1][64]; + uint32_t(*dequant4_coeff[6])[16]; + uint32_t(*dequant8_coeff[6])[64]; +} Yang_PPS; +#endif diff --git a/include/yangavutil/video/YangBmp.h b/include/yangavutil/video/YangBmp.h new file mode 100644 index 0000000000000000000000000000000000000000..5fe13fee6b7f8d7387ae6a4f95924bafc49a87df --- /dev/null +++ b/include/yangavutil/video/YangBmp.h @@ -0,0 +1,44 @@ +#ifndef YangBmp_H_ +#define YangBmp_H_ + +#pragma pack(1) +struct Yang_BITMAPFILEHEADER { + unsigned short bfType; + uint32_t bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + uint32_t bfOffBits; + +}; + +struct Yang_BITMAPINFOHEADER +{ + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPelsPerMeter; + uint32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +}; +#pragma pack() + +class YangBmp { +public: + YangBmp(); + virtual ~YangBmp(); +public: + void create_bmpheader(int32_t p_width, int32_t p_height); + void save_bmp(char *p_filename, char *p_addr, int32_t p_len); +protected: + +private: + struct Yang_BITMAPFILEHEADER bfh; + struct Yang_BITMAPINFOHEADER bih; +}; + +#endif diff --git a/include/yangavutil/video/YangGetBits.h b/include/yangavutil/video/YangGetBits.h new file mode 100644 index 0000000000000000000000000000000000000000..58a3281a33647cd4a083e256d8d8e4ac28841db7 --- /dev/null +++ b/include/yangavutil/video/YangGetBits.h @@ -0,0 +1,753 @@ +/* + * YangGetBits.h + * + * Created on: 2019年8月17日 + * Author: yang + */ + +#ifndef YANGUTIL_VIDEO_YANGGETBITS_H_ +#define YANGUTIL_VIDEO_YANGGETBITS_H_ + +#include +#include "stdint.h" +#include "limits.h" + + +class YangGetBits { +public: + YangGetBits(); + virtual ~YangGetBits(); +}; + +//#define BITSTREAM_READER_LE +#ifndef UNCHECKED_BITSTREAM_READER +#define UNCHECKED_BITSTREAM_READER !CONFIG_YANG_BITSTREAM_READER +#endif + +#ifndef CACHED_BITSTREAM_READER +#define CACHED_BITSTREAM_READER 0 +#endif + + + +#define yang_MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define YangERRTAG(a, b, c, d) (-(int)yang_MKTAG(a, b, c, d)) +#define YangERROR_INVALIDDATA YangERRTAG( 'I','N','D','A') +#define Yang_INPUT_BUFFER_PADDING_SIZE 64 +#define YangMAX(a,b) ((a) > (b) ? (a) : (b)) +#define Yang_TYPE int16_t +inline unsigned yang_zero_extend(unsigned val, unsigned bits) { + return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits); +} +inline int32_t yang_sign_extend(int32_t val, unsigned bits) { + unsigned shift = 8 * sizeof(int) - bits; + union { + unsigned u; + int32_t s; + } v = { (unsigned) val << shift }; + return v.s >> shift; +} + +inline uint32_t yang_get_bits(YangGetBitContext *s, int32_t n); +inline void yang_skip_bits(YangGetBitContext *s, int32_t n); +inline uint32_t yang_show_bits(YangGetBitContext *s, int32_t n); + +#define Yang_RL32(x) \ + (((uint32_t)((const uint8_t*)(x))[3] << 24) | \ + (((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +# define Yang_RB32(x) \ + (((uint32_t)((const uint8_t*)(x))[0] << 24) | \ + (((const uint8_t*)(x))[1] << 16) | \ + (((const uint8_t*)(x))[2] << 8) | \ + ((const uint8_t*)(x))[3]) + +# define Yang_NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define Yang_NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) + +#if CACHED_BITSTREAM_READER +# define Yang_MIN_CACHE_BITS 64 +#elif defined LONG_BITSTREAM_READER +# define Yang_MIN_CACHE_BITS 32 +#else +# define Yang_MIN_CACHE_BITS 25 +#endif + +#if !CACHED_BITSTREAM_READER + + #define Yang_OPEN_READER_NOSIZE(name, gb) \ + uint32_t name ## _index = (gb)->index; \ + uint32_t name ## _cache; + + #if UNCHECKED_BITSTREAM_READER + #define Yang_OPEN_READER(name, gb) Yang_OPEN_READER_NOSIZE(name, gb) + + #define Yang_BITS_AVAILABLE(name, gb) 1 + #else + #define Yang_OPEN_READER(name, gb) \ + Yang_OPEN_READER_NOSIZE(name, gb); \ + uint32_t name ## _size_plus8 = (gb)->size_in_bits_plus8 + + #define Yang_BITS_AVAILABLE(name, gb) name ## _index < name ## _size_plus8 + #endif + + #define Yang_CLOSE_READER(name, gb) (gb)->index = name ## _index + + # ifdef LONG_BITSTREAM_READER + + # define Yang_UPDATE_CACHE_LE(name, gb) name ## _cache = \ + Yang_RL64((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) + + # define Yang_UPDATE_CACHE_BE(name, gb) name ## _cache = \ + Yang_RB64((gb)->buffer + (name ## _index >> 3)) >> (32 - (name ## _index & 7)) + + #else + + # define Yang_UPDATE_CACHE_LE(name, gb) name ## _cache = \ + Yang_RL32((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) + + # define Yang_UPDATE_CACHE_BE(name, gb) name ## _cache = \ + Yang_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7) + + #endif + + #ifdef BITSTREAM_READER_LE + + # define Yang_UPDATE_CACHE(name, gb) Yang_UPDATE_CACHE_LE(name, gb) + + # define Yang_Yang_SKIP_BITS(name, gb, num) name ## _cache >>= (num) + + #else + + # define Yang_UPDATE_CACHE(name, gb) Yang_UPDATE_CACHE_BE(name, gb) + + # define Yang_Yang_SKIP_BITS(name, gb, num) name ## _cache <<= (num) + + #endif + + #if UNCHECKED_BITSTREAM_READER + # define Yang_SKIP_COUNTER(name, gb, num) name ## _index += (num) + #else + # define Yang_SKIP_COUNTER(name, gb, num) \ + name ## _index = FFMIN(name ## _size_plus8, name ## _index + (num)) + #endif + + #define Yang_BITS_LEFT(name, gb) ((int)((gb)->size_in_bits - name ## _index)) + + #define Yang_SKIP_BITS(name, gb, num) \ + do { \ + Yang_Yang_SKIP_BITS(name, gb, num); \ + Yang_SKIP_COUNTER(name, gb, num); \ + } while (0) + + #define LAST_Yang_SKIP_BITS(name, gb, num) Yang_SKIP_COUNTER(name, gb, num) + + #define Yang_SHOW_UBITS_LE(name, gb, num) yang_zero_extend(name ## _cache, num) + #define Yang_SHOW_SBITS_LE(name, gb, num) yang_sign_extend(name ## _cache, num) + + #define Yang_SHOW_UBITS_BE(name, gb, num) Yang_NEG_USR32(name ## _cache, num) + #define Yang_SHOW_SBITS_BE(name, gb, num) Yang_NEG_SSR32(name ## _cache, num) + + #ifdef BITSTREAM_READER_LE + # define Yang_SHOW_UBITS(name, gb, num) Yang_SHOW_UBITS_LE(name, gb, num) + # define Yang_SHOW_SBITS(name, gb, num) Yang_SHOW_SBITS_LE(name, gb, num) + #else + # define Yang_SHOW_UBITS(name, gb, num) Yang_SHOW_UBITS_BE(name, gb, num) + # define Yang_SHOW_SBITS(name, gb, num) Yang_SHOW_SBITS_BE(name, gb, num) + #endif + + #define Yang_GET_CACHE(name, gb) ((uint32_t) name ## _cache) + +#endif + +static int32_t yang_get_bits_count(YangGetBitContext *s) { +#if CACHED_BITSTREAM_READER + return s->index - s->bits_left; +#else + return s->index; +#endif +} + +#if CACHED_BITSTREAM_READER +static void yang_refill_32(YangGetBitContext *s) +{ +#if !UNCHECKED_BITSTREAM_READER + if (s->index >> 3 >= s->buffer_end - s->buffer) + return; +#endif + +#ifdef BITSTREAM_READER_LE + s->cache = (uint64_t)Yang_RL32(s->buffer + (s->index >> 3)) << s->bits_left | s->cache; +#else + s->cache = s->cache | (uint64_t)Yang_RB32(s->buffer + (s->index >> 3)) << (32 - s->bits_left); +#endif + s->index += 32; + s->bits_left += 32; +} + +static void yang_refill_64(YangGetBitContext *s) +{ +#if !UNCHECKED_BITSTREAM_READER + if (s->index >> 3 >= s->buffer_end - s->buffer) + return; +#endif + +#ifdef BITSTREAM_READER_LE + s->cache = Yang_RL64(s->buffer + (s->index >> 3)); +#else + s->cache = Yang_RB64(s->buffer + (s->index >> 3)); +#endif + s->index += 64; + s->bits_left = 64; +} + +static uint64_t yang_get_val(YangGetBitContext *s, unsigned n, int32_t is_le) +{ + uint64_t ret; + av_assert2(n>0 && n<=63); + if (is_le) { + ret = s->cache & ((UINT64_C(1) << n) - 1); + s->cache >>= n; + } else { + ret = s->cache >> (64 - n); + s->cache <<= n; + } + s->bits_left -= n; + return ret; +} + +static unsigned yang_show_val(const YangGetBitContext *s, unsigned n) +{ +#ifdef BITSTREAM_READER_LE + return s->cache & ((UINT64_C(1) << n) - 1); +#else + return s->cache >> (64 - n); +#endif +} +#endif + +/** + * Skips the specified number of bits. + * @param n the number of bits to skip, + * For the UNCHECKED_BITSTREAM_READER this must not cause the distance + * from the start to overflow int32_t. Staying within the bitstream + padding + * is sufficient, too. + */ +static void yang_skip_bits_long(YangGetBitContext *s, int32_t n) { +#if CACHED_BITSTREAM_READER + yang_skip_bits(s, n); +#else +#if UNCHECKED_BITSTREAM_READER + s->index += n; +#else + s->index += av_clip(n, -s->index, s->size_in_bits_plus8 - s->index); +#endif +#endif +} + +#if CACHED_BITSTREAM_READER +static void yang_skip_remaining(YangGetBitContext *s, unsigned n) +{ +#ifdef BITSTREAM_READER_LE + s->cache >>= n; +#else + s->cache <<= n; +#endif + s->bits_left -= n; +} +#endif + +/** + * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). + * if MSB not set it is negative + * @param n length in bits + */ +static int32_t yang_get_xbits(YangGetBitContext *s, int32_t n) { +#if CACHED_BITSTREAM_READER + int32_t cache = yang_show_bits(s, 32); + int32_t sign = ~cache >> 31; + yang_skip_remaining(s, n); + + return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; +#else + register int32_t sign; + register int32_t cache; + Yang_OPEN_READER(re, s); + // av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE(re, s); + cache = Yang_GET_CACHE(re, s); + sign = ~cache >> 31; + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); + return (Yang_NEG_USR32(sign ^ cache, n) ^ sign) - sign; +#endif +} + +#if !CACHED_BITSTREAM_READER +static int32_t yang_get_xbits_le(YangGetBitContext *s, int32_t n) { + register int32_t sign; + register int32_t cache; + Yang_OPEN_READER(re, s); + // av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE_LE(re, s); + cache = Yang_GET_CACHE(re, s); + sign = yang_sign_extend(~cache, n) >> 31; + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); + return (yang_zero_extend(sign ^ cache, n) ^ sign) - sign; +} +#endif + +static int32_t yang_get_sbits(YangGetBitContext *s, int32_t n) { + register int32_t tmp; +#if CACHED_BITSTREAM_READER + av_assert2(n>0 && n<=25); + tmp = sign_extend(yang_get_bits(s, n), n); +#else + Yang_OPEN_READER(re, s); + //av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE(re, s); + tmp = Yang_SHOW_SBITS(re, s, n); + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); +#endif + return tmp; +} + +/** + * Read 1-25 bits. + */ +inline uint32_t yang_get_bits(YangGetBitContext *s, int32_t n) { + register int32_t tmp; +#if CACHED_BITSTREAM_READER + + av_assert2(n>0 && n<=32); + if (n > s->bits_left) { + yang_refill_32(s); + if (s->bits_left < 32) + s->bits_left = n; + } + +#ifdef BITSTREAM_READER_LE + tmp = yang_get_val(s, n, 1); +#else + tmp = yang_get_val(s, n, 0); +#endif +#else + Yang_OPEN_READER(re, s); + // av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE(re, s); + tmp = Yang_SHOW_UBITS(re, s, n); + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); +#endif + return tmp; +} + +/** + * Read 0-25 bits. + */ +inline int32_t yang_get_bitsz(YangGetBitContext *s, int32_t n) { + return n ? yang_get_bits(s, n) : 0; +} + +inline uint32_t yang_get_bits_le(YangGetBitContext *s, int32_t n) { +#if CACHED_BITSTREAM_READER + av_assert2(n>0 && n<=32); + if (n > s->bits_left) { + yang_refill_32(s); + if (s->bits_left < 32) + s->bits_left = n; + } + + return yang_get_val(s, n, 1); +#else + register int32_t tmp; + Yang_OPEN_READER(re, s); + // av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE_LE(re, s); + tmp = Yang_SHOW_UBITS_LE(re, s, n); + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); + return tmp; +#endif +} + +/** + * Show 1-25 bits. + */ +inline uint32_t yang_show_bits(YangGetBitContext *s, int32_t n) { + register int32_t tmp; +#if CACHED_BITSTREAM_READER + if (n > s->bits_left) + yang_refill_32(s); + + tmp = yang_show_val(s, n); +#else + Yang_OPEN_READER_NOSIZE(re, s); + // av_assert2(n>0 && n<=25); + Yang_UPDATE_CACHE(re, s); + tmp = Yang_SHOW_UBITS(re, s, n); +#endif + return tmp; +} + +inline void yang_skip_bits(YangGetBitContext *s, int32_t n) { +#if CACHED_BITSTREAM_READER + if (n < s->bits_left) + yang_skip_remaining(s, n); + else { + n -= s->bits_left; + s->cache = 0; + s->bits_left = 0; + + if (n >= 64) { + unsigned skip = (n / 8) * 8; + + n -= skip; + s->index += skip; + } + yang_refill_64(s); + if (n) + yang_skip_remaining(s, n); + } +#else + Yang_OPEN_READER(re, s); + LAST_Yang_SKIP_BITS(re, s, n); + Yang_CLOSE_READER(re, s); +#endif +} + +inline uint32_t yang_get_bits1(YangGetBitContext *s) { +#if CACHED_BITSTREAM_READER + if (!s->bits_left) + yang_refill_64(s); + +#ifdef BITSTREAM_READER_LE + return yang_get_val(s, 1, 1); +#else + return yang_get_val(s, 1, 0); +#endif +#else + uint32_t index = s->index; + uint8_t result = s->buffer[index >> 3]; +#ifdef BITSTREAM_READER_LE + result >>= index & 7; + result &= 1; +#else + result <<= index & 7; + result >>= 8 - 1; +#endif +#if !UNCHECKED_BITSTREAM_READER + if (s->index < s->size_in_bits_plus8) +#endif + index++; + s->index = index; + + return result; +#endif +} + +inline uint32_t yang_show_bits1(YangGetBitContext *s) { + return yang_show_bits(s, 1); +} + +inline void yang_skip_bits1(YangGetBitContext *s) { + yang_skip_bits(s, 1); +} + +/** + * Read 0-32 bits. + */ +inline uint32_t yang_get_bits_long(YangGetBitContext *s, int32_t n) { + //av_assert2(n>=0 && n<=32); + if (!n) { + return 0; +#if CACHED_BITSTREAM_READER + } + return yang_get_bits(s, n); +#else + } else if (n <= Yang_MIN_CACHE_BITS) { + return yang_get_bits(s, n); + } else { +#ifdef BITSTREAM_READER_LE + unsigned ret = yang_get_bits(s, 16); + return ret | (yang_get_bits(s, n - 16) << 16); +#else + unsigned ret = yang_get_bits(s, 16) << (n - 16); + return ret | yang_get_bits(s, n - 16); +#endif + } +#endif +} + +/** + * Read 0-64 bits. + */ +inline uint64_t yang_get_bits64(YangGetBitContext *s, int32_t n) { + if (n <= 32) { + return yang_get_bits_long(s, n); + } else { +#ifdef BITSTREAM_READER_LE + uint64_t ret = yang_get_bits_long(s, 32); + return ret | (uint64_t) yang_get_bits_long(s, n - 32) << 32; +#else + uint64_t ret = (uint64_t) yang_get_bits_long(s, n - 32) << 32; + return ret | yang_get_bits_long(s, 32); +#endif + } +} + +/** + * Read 0-32 bits as a signed integer. + */ +inline int32_t yang__get_sbits_long(YangGetBitContext *s, int32_t n) { + // sign_extend(x, 0) is undefined + if (!n) + return 0; + + return yang_sign_extend(yang_get_bits_long(s, n), n); +} + +/** + * Show 0-32 bits. + */ +inline uint32_t yang_show_bits_long(YangGetBitContext *s, int32_t n) { + if (n <= Yang_MIN_CACHE_BITS) { + return yang_show_bits(s, n); + } else { + YangGetBitContext gb = *s; + return yang_get_bits_long(&gb, n); + } +} + +inline int32_t yang_check_marker(void *logctx, YangGetBitContext *s, + const char *msg) { + int32_t bit = yang_get_bits1(s); + // if (!bit) + // av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", yang_get_bits_count(s) - 1, s->size_in_bits, msg); + + return bit; +} + +/** + * Initialize YangGetBitContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +inline int32_t yang_init_get_bits(YangGetBitContext *s, uint8_t *buffer, + int32_t bit_size) { + int32_t buffer_size; + int32_t ret = 0; + + if (bit_size >= INT_MAX - YangMAX(7, Yang_INPUT_BUFFER_PADDING_SIZE*8) + || bit_size < 0 || !buffer) { + bit_size = 0; + buffer = 0; + ret = YangERROR_INVALIDDATA; + } + + buffer_size = (bit_size + 7) >> 3; + + s->buffer = buffer; + s->size_in_bits = bit_size; + s->size_in_bits_plus8 = bit_size + 8; + s->buffer_end = buffer + buffer_size; + s->index = 0; + +#if CACHED_BITSTREAM_READER + yang_refill_64(s); +#endif + + return ret; +} + +/** + * Initialize YangGetBitContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +inline int32_t yang_init_get_bits8(YangGetBitContext *s, uint8_t *buffer, + int32_t byte_size) { + if (byte_size > INT_MAX / 8 || byte_size < 0) + byte_size = -1; + return yang_init_get_bits(s, buffer, byte_size * 8); +} + +static uint8_t *align_yang_get_bits(YangGetBitContext *s) { + int32_t n = -yang_get_bits_count(s) & 7; + if (n) + yang_skip_bits(s, n); + return s->buffer + (s->index >> 3); +} + +/** + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +#define Yang_GET_VLC(code, name, gb, table, bits, max_depth) \ + do { \ + int32_t n, nb_bits; \ + uint32_t index; \ + \ + index = Yang_SHOW_UBITS(name, gb, bits); \ + code = table[index][0]; \ + n = table[index][1]; \ + \ + if (max_depth > 1 && n < 0) { \ + LAST_Yang_SKIP_BITS(name, gb, bits); \ + Yang_UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = Yang_SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 2 && n < 0) { \ + LAST_Yang_SKIP_BITS(name, gb, nb_bits); \ + Yang_UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = Yang_SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + } \ + } \ + Yang_SKIP_BITS(name, gb, n); \ + } while (0) + +#define Yang_GET_RL_VLC(level, run, name, gb, table, bits, \ + max_depth, need_update) \ + do { \ + int32_t n, nb_bits; \ + uint32_t index; \ + \ + index = Yang_SHOW_UBITS(name, gb, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + Yang_SKIP_BITS(name, gb, bits); \ + if (need_update) { \ + Yang_UPDATE_CACHE(name, gb); \ + } \ + \ + nb_bits = -n; \ + \ + index = Yang_SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + LAST_Yang_SKIP_BITS(name, gb, nb_bits); \ + if (need_update) { \ + Yang_UPDATE_CACHE(name, gb); \ + } \ + nb_bits = -n; \ + \ + index = Yang_SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + Yang_SKIP_BITS(name, gb, n); \ + } while (0) + +/* Return the LUT element for the given bitstream configuration. */ +inline int32_t yang_set_idx(YangGetBitContext *s, int32_t code, int32_t *n, int32_t *nb_bits, +Yang_TYPE (*table)[2]) { + unsigned idx; + + *nb_bits = -*n; + idx = yang_show_bits(s, *nb_bits) + code; + *n = table[idx][1]; + + return table[idx][0]; +} + +/** + * Parse a vlc code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + * @returns the code parsed or -1 if no vlc matches + */ +inline int32_t Yang_GET_VLC2(YangGetBitContext *s, Yang_TYPE (*table)[2], int32_t bits, + int32_t max_depth) { +#if CACHED_BITSTREAM_READER + int32_t nb_bits; + unsigned idx = yang_show_bits(s, bits); + int32_t code = table[idx][0]; + int32_t n = table[idx][1]; + + if (max_depth > 1 && n < 0) { + yang_skip_remaining(s, bits); + code = yang_set_idx(s, code, &n, &nb_bits, table); + if (max_depth > 2 && n < 0) { + yang_skip_remaining(s, nb_bits); + code = yang_set_idx(s, code, &n, &nb_bits, table); + } + } + yang_skip_remaining(s, n); + + return code; +#else + int32_t code; + + Yang_OPEN_READER(re, s); + Yang_UPDATE_CACHE(re, s); + + Yang_GET_VLC(code, re, s, table, bits, max_depth); + + Yang_CLOSE_READER(re, s); + + return code; +#endif +} + +inline int32_t yang_decode012(YangGetBitContext *gb) { + int32_t n; + n = yang_get_bits1(gb); + if (n == 0) + return 0; + else + return yang_get_bits1(gb) + 1; +} + +inline int32_t yang_decode210(YangGetBitContext *gb) { + if (yang_get_bits1(gb)) + return 0; + else + return 2 - yang_get_bits1(gb); +} + +inline int32_t yang_get_bits_left(YangGetBitContext *gb) { + return gb->size_in_bits - yang_get_bits_count(gb); +} + +inline int32_t yang_skip_1stop_8data_bits(YangGetBitContext *gb) { + if (yang_get_bits_left(gb) <= 0) + return YangERROR_INVALIDDATA; + + while (yang_get_bits1(gb)) { + yang_skip_bits(gb, 8); + if (yang_get_bits_left(gb) <= 0) + return YangERROR_INVALIDDATA; + } + + return 0; +} + + +#endif /* YANGUTIL_VIDEO_YANGGETBITS_H_ */ diff --git a/include/yangavutil/video/YangGolomb.h b/include/yangavutil/video/YangGolomb.h new file mode 100644 index 0000000000000000000000000000000000000000..6292c77f5931fefd2ea7b88bd9ef47ce9814e675 --- /dev/null +++ b/include/yangavutil/video/YangGolomb.h @@ -0,0 +1,403 @@ +#ifndef YANGGolombH12345_ +#define YANGGolombH12345_ +#include +#include "stdlib.h" +#include "immintrin.h" + +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define INVALID_VLC 0x80000000 + +//#define yang_log2(x) (_bit_scan_reverse((x)|1)) +//#define ff_log2(x) (31 - __builtin_clz((x)|1)) + +const uint8_t yang_golomb_vlc_len[512]={ +19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + +const uint8_t yang_ue_golomb_vlc_code[512]={ +32,32,32,32,32,32,32,32,31,32,32,32,32,32,32,32,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const char yang_se_golomb_vlc_code[512]={ + 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 8, -8, 9, -9, 10,-10, 11,-11, 12,-12, 13,-13, 14,-14, 15,-15, + 4, 4, 4, 4, -4, -4, -4, -4, 5, 5, 5, 5, -5, -5, -5, -5, 6, 6, 6, 6, -6, -6, -6, -6, 7, 7, 7, 7, -7, -7, -7, -7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +const uint8_t yang_ue_golomb_len[256]={ + 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17, +}; + +const uint8_t yang_interleaved_golomb_vlc_len[256]={ +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +const uint8_t yang_interleaved_ue_golomb_vlc_code[256]={ + 15,16,7, 7, 17,18,8, 8, 3, 3, 3, 3, 3, 3, 3, 3, + 19,20,9, 9, 21,22,10,10,4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 23,24,11,11,25,26,12,12,5, 5, 5, 5, 5, 5, 5, 5, + 27,28,13,13,29,30,14,14,6, 6, 6, 6, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const char yang_interleaved_se_golomb_vlc_code[256]={ + 8, -8, 4, 4, 9, -9, -4, -4, 2, 2, 2, 2, 2, 2, 2, 2, + 10,-10, 5, 5, 11,-11, -5, -5, -2, -2, -2, -2, -2, -2, -2, -2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 12,-12, 6, 6, 13,-13, -6, -6, 3, 3, 3, 3, 3, 3, 3, 3, + 14,-14, 7, 7, 15,-15, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const uint8_t yang_interleaved_dirac_golomb_vlc_code[256]={ +0, 1, 0, 0, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, +4, 5, 2, 2, 6, 7, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +8, 9, 4, 4, 10,11,5, 5, 2, 2, 2, 2, 2, 2, 2, 2, +12,13,6, 6, 14,15,7, 7, 3, 3, 3, 3, 3, 3, 3, 3, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; +const uint8_t yang_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; +//#define get_ue_golomb(a) get_ue(a, __FILE__, __func__, __LINE__) +//#define get_se_golomb(a) get_se(a, __FILE__, __func__, __LINE__) +//#define get_te_golomb(a, r) get_te(a, r, __FILE__, __func__, __LINE__) +//#define get_te0_golomb(a, r) get_te(a, r, __FILE__, __func__, __LINE__) +inline int32_t yang_log2(uint32_t v) +{ + int32_t n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += yang_log2_tab[v]; + + return n; +} + +inline int32_t yang_get_ue_golomb(YangGetBitContext *gb) +{ + uint32_t buf; + +#if CACHED_BITSTREAM_READER + buf = show_bits_long(gb, 32); + + if (buf >= (1 << 27)) { + buf >>= 32 - 9; + skip_bits_long(gb, ff_golomb_vlc_len[buf]); + + return ff_ue_golomb_vlc_code[buf]; + } else { + int32_t log = 2 * av_log2(buf) - 31; + buf >>= log; + buf--; + skip_bits_long(gb, 32 - log); + + return buf; + } +#else + Yang_OPEN_READER(re, gb); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + + if (buf >= (1 << 27)) { + buf >>= 32 - 9; + LAST_Yang_SKIP_BITS(re, gb, yang_golomb_vlc_len[buf]); + Yang_CLOSE_READER(re, gb); + + return yang_ue_golomb_vlc_code[buf]; + } else { + int32_t log = 2 * yang_log2(buf) - 31; + LAST_Yang_SKIP_BITS(re, gb, 32 - log); + Yang_CLOSE_READER(re, gb); + if (log < 7) { + // av_log(NULL, AV_LOG_ERROR, "Invalid UE golomb code\n"); + return YangERROR_INVALIDDATA; + } + buf >>= log; + buf--; + + return buf; + } +#endif +} + +inline int32_t yang_get_ue_golomb_31(YangGetBitContext *gb) +{ + uint32_t buf; + Yang_OPEN_READER(re, gb); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + buf >>= 32 - 9; + LAST_Yang_SKIP_BITS(re, gb, yang_golomb_vlc_len[buf]); + Yang_CLOSE_READER(re, gb); + + + return yang_ue_golomb_vlc_code[buf]; +} + + +inline unsigned yang_get_interleaved_ue_golomb(YangGetBitContext *gb) +{ + uint32_t buf; + + + Yang_OPEN_READER(re, gb); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + + if (buf & 0xAA800000) { + buf >>= 32 - 8; + LAST_Yang_SKIP_BITS(re, gb, yang_interleaved_golomb_vlc_len[buf]); + Yang_CLOSE_READER(re, gb); + + return yang_interleaved_ue_golomb_vlc_code[buf]; + } else { + unsigned ret = 1; + + do { + buf >>= 32 - 8; + LAST_Yang_SKIP_BITS(re, gb, + FFMIN(yang_interleaved_golomb_vlc_len[buf], 8)); + + if (yang_interleaved_golomb_vlc_len[buf] != 9) { + ret <<= (yang_interleaved_golomb_vlc_len[buf] - 1) >> 1; + ret |= yang_interleaved_dirac_golomb_vlc_code[buf]; + break; + } + ret = (ret << 4) | yang_interleaved_dirac_golomb_vlc_code[buf]; + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + } while (ret<0x8000000U && Yang_BITS_AVAILABLE(re, gb)); + + Yang_CLOSE_READER(re, gb); + return ret - 1; + } + +} + + + +/** + * read unsigned truncated exp golomb code. + */ +inline int32_t yang_get_te0_golomb(YangGetBitContext *gb, int32_t range) +{ + // av_assert2(range >= 1); + + if (range == 1) + return 0; + else if (range == 2) + return yang_get_bits1(gb) ^ 1; + else + return yang_get_ue_golomb(gb); + return 0; +} + +/** + * read unsigned truncated exp golomb code. + */ +inline int32_t yang_get_te_golomb(YangGetBitContext *gb, int32_t range) +{ + // av_assert2(range >= 1); + + if (range == 2) + return yang_get_bits1(gb) ^ 1; + else + return yang_get_ue_golomb(gb); + return 0; +} +inline int32_t yang_get_se_golomb(YangGetBitContext *gb) +{ + uint32_t buf; + + + Yang_OPEN_READER(re, gb); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + + if (buf >= (1 << 27)) { + buf >>= 32 - 9; + LAST_Yang_SKIP_BITS(re, gb, yang_golomb_vlc_len[buf]); + Yang_CLOSE_READER(re, gb); + + return yang_se_golomb_vlc_code[buf]; + } else { + int32_t log = yang_log2(buf), sign; + LAST_Yang_SKIP_BITS(re, gb, 31 - log); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + + buf >>= log; + + LAST_Yang_SKIP_BITS(re, gb, 32 - log); + Yang_CLOSE_READER(re, gb); + + sign = -(buf & 1); + buf = ((buf >> 1) ^ sign) - sign; + + return buf; + } + return 0; +} +inline unsigned yang_get_ue_golomb_long(YangGetBitContext *gb) +{ + unsigned buf, log; + + buf = yang_show_bits_long(gb, 32); + log = 31 - yang_log2(buf); + yang_skip_bits_long(gb, log); + + return yang_get_bits_long(gb, log + 1) - 1; +} +inline int32_t yang_get_se_golomb_long(YangGetBitContext *gb) +{ + uint32_t buf = yang_get_ue_golomb_long(gb); + int32_t sign = (buf & 1) - 1; + return ((buf >> 1) ^ sign) + 1; +} + + +inline int32_t yang_get_interleaved_se_golomb(YangGetBitContext *gb) +{ + uint32_t buf; + Yang_OPEN_READER(re, gb); + Yang_UPDATE_CACHE(re, gb); + buf = Yang_GET_CACHE(re, gb); + + if (buf & 0xAA800000) { + buf >>= 32 - 8; + LAST_Yang_SKIP_BITS(re, gb, yang_interleaved_golomb_vlc_len[buf]); + Yang_CLOSE_READER(re, gb); + + return yang_interleaved_se_golomb_vlc_code[buf]; + } else { + int32_t log; + LAST_Yang_SKIP_BITS(re, gb, 8); + Yang_UPDATE_CACHE(re, gb); + buf |= 1 | (Yang_GET_CACHE(re, gb) >> 8); + + if ((buf & 0xAAAAAAAA) == 0) + return INVALID_VLC; + + for (log = 31; (buf & 0x80000000) == 0; log--) + buf = (buf << 2) - ((buf << log) >> (log - 1)) + (buf >> 30); + + LAST_Yang_SKIP_BITS(re, gb, 63 - 2 * log - 8); + Yang_CLOSE_READER(re, gb); + + return (signed) (((((buf << log) >> log) - 1) ^ -(buf & 0x1)) + 1) >> 1; + } + +} + + +#endif diff --git a/include/yangavutil/video/YangMeta.h b/include/yangavutil/video/YangMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..85eadb3c7e52349cb952a322b39d3fc72d7053f8 --- /dev/null +++ b/include/yangavutil/video/YangMeta.h @@ -0,0 +1,18 @@ +#ifndef INCLUDE_YANGAVUTIL_VIDEO_YANGMETA_H_ +#define INCLUDE_YANGAVUTIL_VIDEO_YANGMETA_H_ +#include +#include +#include +void yang_createH264Meta(YangVideoMeta* pvmd,YangFrame *videoFrame); +void yang_createH265Meta(YangVideoMeta* pvmd,YangFrame *videoFrame); +void yang_getConfig_Flv_H264(YangH2645Conf *p_264, uint8_t *configBuf,int32_t *p_configLen); +void yang_getConfig_Meta_H264(YangSample* sps, YangSample* pps,uint8_t *configBuf,int32_t *p_configLen); +void yang_getConfig_Flv_H265(YangH2645Conf *p_264, uint8_t *configBuf,int32_t *p_configLen); +void yang_getConfig_Meta_H265(YangSample* vps,YangSample* sps, YangSample* pps, uint8_t *configBuf,int32_t *p_configLen); + +void yang_getH265RtmpHeader(uint8_t *meta, uint8_t *src, int32_t *hLen); +void yang_getH264RtmpHeader(uint8_t *buf, uint8_t *src, int32_t *hLen); + +void yang_decodeMetaH264(uint8_t *configBuf,int32_t p_configLen,YangSample* sps,YangSample* pps); +void yang_decodeMetaH265(uint8_t *configBuf,int32_t p_configLen,YangSample* vps,YangSample* sps,YangSample* pps); +#endif /* INCLUDE_YANGAVUTIL_VIDEO_YANGMETA_H_ */ diff --git a/include/yangavutil/video/YangNalu.h b/include/yangavutil/video/YangNalu.h new file mode 100644 index 0000000000000000000000000000000000000000..a7dec7412ead2b7c15f1cd25c71d7e575a2e19aa --- /dev/null +++ b/include/yangavutil/video/YangNalu.h @@ -0,0 +1,33 @@ +#ifndef INCLUDE_YANGAVUTIL_VIDEO_YANGNALU_H_ +#define INCLUDE_YANGAVUTIL_VIDEO_YANGNALU_H_ +#include +#include +#include +struct YangH264NaluData{ + int spsppsPos; + int keyframePos; +}; +struct YangH264NaluData2{ + int spsPos; + int ppsPos; + int spsLen; + int ppsLen; + int keyframePos; +}; +int32_t yang_parseH264Nalu(YangFrame* videoFrame,YangH264NaluData* pnalu); +int32_t yang_parseH264Nalu2(YangFrame* videoFrame,YangH264NaluData2* pnalu); +int32_t yang_getH264SpsppseNalu(YangFrame* videoFrame,uint8_t* pnaludata); +int32_t yang_getH264KeyframeNalu(YangFrame* videoFrame); +bool yang_hasH264Pframe(uint8_t* p); + +int32_t yang_getH265SpsppseNalu(YangFrame* videoFrame,uint8_t* pnaludata); +int32_t yang_parseH265Nalu(YangFrame* videoFrame,YangH264NaluData* pnalu); + +/** + * Table 7-1 - NAL unit type codes, syntax element categories, and NAL unit type classes + * ISO_IEC_14496-10-AVC-2012.pdf, page 83. + */ + +std::string yang_avc_nalu2str(YangAvcNaluType nalu_type); + +#endif /* INCLUDE_YANGAVUTIL_VIDEO_YANGNALU_H_ */ diff --git a/include/yangavutil/video/YangPicConvert.h b/include/yangavutil/video/YangPicConvert.h new file mode 100644 index 0000000000000000000000000000000000000000..285e8366d4a589fed8fee2169c255ec45c16cda4 --- /dev/null +++ b/include/yangavutil/video/YangPicConvert.h @@ -0,0 +1,33 @@ +#ifndef _YangConvert_H__ +#define _YangConvert_H__ + +#include "stdint.h" + +//#include "YangResize.h" +#define u8_t uint8_t +class YangConvert{ +public: +~YangConvert(); +YangConvert(); + //YangResize *mpu; + +void zoomIn4(uint8_t *src,uint8_t *dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeigh); +void zoom4Yuy2(uint8_t *src,uint8_t *dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +//void initNv12_resize(int32_t p_srcWidth,int32_t p_srcHeight,int32_t p_dstWidth,int32_t p_dstHeight); +void resize_NV12(uint8_t *src,uint8_t *dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +void resize_Yuy2_NV12(uint8_t *src,uint8_t *dest,int32_t p_srcWidth,int32_t p_srcHeight,int32_t p_destWidth,int32_t p_destHeight); +void nv12_nearest_scale(uint8_t* src, uint8_t* dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight) ; +void YUY2toI420(int32_t inWidth, int32_t inHeight, uint8_t *pSrc, uint8_t *pDest); +void YUY2toNV12(int32_t inWidth, int32_t inHeight, uint8_t *pSrc, uint8_t *pDest); +void plusNV12(uint8_t* src,uint8_t * dest,int32_t model,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +void plusYuy2(uint8_t* src,uint8_t * dest,int32_t model,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); + +void RGB24_TO_YV12(uint8_t* yv12,uint8_t* rgb24,int32_t w,int32_t h); +void RGB24_To_I420( uint8_t *RGBbuf, uint8_t *YUV, int32_t width, int32_t height ); +void RGB24_To_NV12( uint8_t *RGBbuf, uint8_t *YUV, int32_t width, int32_t height ); +void YUY2_To_RGB24(uint8_t *YUY2buff,uint8_t *RGBbuff,unsigned long dwSize); +private: + uint8_t clip255(long v); +}; +#endif + diff --git a/include/yangavutil/video/YangPicUtilFfmpeg.h b/include/yangavutil/video/YangPicUtilFfmpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..280f13fd54c0ddc7085ca056d4c5933dbbd9bfe1 --- /dev/null +++ b/include/yangavutil/video/YangPicUtilFfmpeg.h @@ -0,0 +1,52 @@ +#ifndef YangPicUtilFfmpeg___ +#define YangPicUtilFfmpeg___ +#include "yangutil/sys/YangLoadLib.h" +#include "../../Yang_Config.h" +#if HavePicUtilFfmpeg +//extern "C" { +#include "libswscale/swscale.h" +#include "libavformat/avformat.h" +//} +class YangPicUtilFfmpeg +{ +public: + YangPicUtilFfmpeg(void); + ~YangPicUtilFfmpeg(void); + int32_t inWidth,inHeight,outWidth,outHeight; + void resize(); + void init(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight,AVPixelFormat src,AVPixelFormat dst); + void init(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void initYuy2(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void initNv12(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void init420P(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void initYuy2_Bgr24(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void initBgr24_Yuy2(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + void getAddr(uint8_t **p_in,uint8_t **p_out); + void closeAll(); + + struct SwsContext *img_convert_ctx; + AVPicture in_pic, out_pic; +private: + + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + struct SwsContext *(*yang_sws_getContext)(int32_t srcW, int32_t srcH, enum AVPixelFormat srcFormat, + int32_t dstW, int32_t dstH, enum AVPixelFormat dstFormat, + int32_t flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param); + + int32_t (*yang_sws_scale)(struct SwsContext *c, const uint8_t *const srcSlice[], + const int32_t srcStride[], int32_t srcSliceY, int32_t srcSliceH, + uint8_t *const dst[], const int32_t dstStride[]); + void (*yang_sws_freeContext)(struct SwsContext *swsContext); + + + + + int32_t (*yang_avpicture_alloc)(AVPicture *picture, enum AVPixelFormat pix_fmt, int32_t width, int32_t height); + void (*yang_avpicture_free)(AVPicture *picture); +}; +#endif +#endif + diff --git a/include/yangavutil/video/YangResize.h b/include/yangavutil/video/YangResize.h new file mode 100644 index 0000000000000000000000000000000000000000..085d35f03012d6b880d88625d3e08bfd27959800 --- /dev/null +++ b/include/yangavutil/video/YangResize.h @@ -0,0 +1,43 @@ +#ifndef YANGRESIZE_H +#define YANGRESIZE_H + + +class PicUtilBmp +{ +public: + PicUtilBmp(void); + virtual ~PicUtilBmp(void); + //uint8_t *in; + //uint8_t *out; + //int32_t inWidth,inHeight,outWidth,outHeight; + virtual void resize(); + virtual void init(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + virtual void initYuy2(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + virtual void initYuy2tonv12(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + virtual void initNv12(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + virtual void init420P(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight); + virtual void getAddr(uint8_t **p_in,uint8_t **p_out); + virtual void close(); +}; + + + +class YangResize +{ +public: + YangResize(); + virtual ~YangResize(); +public: + + //uint8_t *in; + //uint8_t *out; + PicUtilBmp *pu; + + +protected: + +private: +}; + + +#endif // YANGRESIZE_H diff --git a/include/yangavutil/video/YangVideoEncoderMeta.h b/include/yangavutil/video/YangVideoEncoderMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..d8ad4621d185c692748a3a9a5054e923ef730fca --- /dev/null +++ b/include/yangavutil/video/YangVideoEncoderMeta.h @@ -0,0 +1,20 @@ +/* + * YangVideoEncoderMeta.h + * + * Created on: 2020年11月14日 + * Author: yang + */ + +#ifndef YANGENCODER_INCLUDE_YANGVIDEOENCODERMETA_H_ +#define YANGENCODER_INCLUDE_YANGVIDEOENCODERMETA_H_ +#include +#include + +class YangVideoEncoderMeta { +public: + YangVideoEncoderMeta(); + virtual ~YangVideoEncoderMeta(); + virtual void yang_initVmd(YangVideoMeta *p_vmd, YangVideoInfo *p_config, YangVideoEncInfo *penc)=0; +}; + +#endif /* YANGENCODER_INCLUDE_YANGVIDEOENCODERMETA_H_ */ diff --git a/include/yangavutil/video/YangYuvConvert.h b/include/yangavutil/video/YangYuvConvert.h new file mode 100644 index 0000000000000000000000000000000000000000..6665994a2398ed31364a3e84b6e796f6717a1dfc --- /dev/null +++ b/include/yangavutil/video/YangYuvConvert.h @@ -0,0 +1,233 @@ +/* + * YangYuvUtil.h + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#ifndef YangYuvConvert_H_ +#define YangYuvConvert_H_ +//#include "yangutil/yangavtype.h" +#include "stdint.h" +#include "yangutil/sys/YangLoadLib.h" +#include "libyuv.h" +using namespace libyuv; + +class YangYuvConvert { +public: + YangYuvConvert(); + virtual ~YangYuvConvert(); + //void rgbtonv12(); + int32_t yuy2tonv12(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t yuy2toi420(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t yuy2toargb(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t i420tonv12(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t i420tonv21(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t bgr24toyuy2(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht); + int32_t rgb24toI420(uint8_t* src_rgb24,uint8_t *dst,int32_t width,int32_t height); + int32_t rgbatoI420(uint8_t* src_rgba,uint8_t *dst,int32_t width,int32_t height); + int32_t bgratoI420(uint8_t* src_rgba,uint8_t *dst,int32_t width,int32_t height); + //I420ToRGB24 + int32_t I420torgb24(uint8_t* src_rgb24,uint8_t *dst,int32_t width,int32_t height); + int32_t nv12torgb24(uint8_t* src_rgb24,uint8_t *dst,int32_t width,int32_t height); + int32_t nv21torgb24(uint8_t* src_rgb24,uint8_t *dst,int32_t width,int32_t height); + int32_t argbtorgb24(uint8_t* src_argb, uint8_t *dst,int32_t width,int32_t height); + int32_t rgb24toargb(uint8_t *src_rgb24, uint8_t *dst, int32_t width,int32_t height); + int32_t scaleNv12(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode=2); + int32_t scaleI420(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode=2); + int32_t scaleYuy2(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode=2); + int32_t scaleRgb(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode=2); + int32_t scaleArgb(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode=2); + + +private: + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + //I420ToNV12 + int32_t (*yang_YUY2ToNV12)(const uint8_t* src_yuy2, + int32_t src_stride_yuy2, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_uv, + int32_t dst_stride_uv, + int32_t width, + int32_t height); + int32_t (*yang_YUY2ToI420)(const uint8_t* src_yuy2, + int32_t src_stride_yuy2, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_u, + int32_t dst_stride_u, + uint8_t* dst_v, + int32_t dst_stride_v, + int32_t width, + int32_t height); + int (*yang_YUY2ToARGB)(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + int32_t (*yang_I420ToNV12)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_u, + int32_t src_stride_u, + const uint8_t* src_v, + int32_t src_stride_v, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_uv, + int32_t dst_stride_uv, + int32_t width, + int32_t height); + + int32_t (*yang_I420ToNV21)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_u, + int32_t src_stride_u, + const uint8_t* src_v, + int32_t src_stride_v, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_vu, + int32_t dst_stride_vu, + int32_t width, + int32_t height); + + int32_t (*yang_I420ToRGB24)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_u, + int32_t src_stride_u, + const uint8_t* src_v, + int32_t src_stride_v, + uint8_t* dst_rgb24, + int32_t dst_stride_rgb24, + int32_t width, + int32_t height); + int32_t (*yang_NV12ToRGB24)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_uv, + int32_t src_stride_uv, + uint8_t* dst_rgb24, + int32_t dst_stride_rgb24, + int32_t width, + int32_t height); + int32_t (*yang_NV21ToRGB24)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_vu, + int32_t src_stride_vu, + uint8_t* dst_rgb24, + int32_t dst_stride_rgb24, + int32_t width, + int32_t height); + int32_t (*yang_ARGBToRGB24)(const uint8_t* src_argb, + int32_t src_stride_argb, + uint8_t* dst_rgb24, + int32_t dst_stride_rgb24, + int32_t width, + int32_t height); + int32_t (*yang_RGB24ToARGB)(const uint8_t* src_rgb24, + int32_t src_stride_rgb24, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t width, + int32_t height); + int32_t (*yang_RAWToARGB)(const uint8_t* src_raw, + int32_t src_stride_raw, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t width, + int32_t height); + int32_t (*yang_RGB24ToI420)(const uint8_t* src_rgb24, + int32_t src_stride_rgb24, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_u, + int32_t dst_stride_u, + uint8_t* dst_v, + int32_t dst_stride_v, + int32_t width, + int32_t height); + int (*yang_RGBAToI420)(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + + int (*yang_BGRAToI420)(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + int (*yang_ARGBToI420)(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + int32_t (*yang_NV12Scale)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_uv, + int32_t src_stride_uv, + int32_t src_width, + int32_t src_height, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_uv, + int32_t dst_stride_uv, + int32_t dst_width, + int32_t dst_height, + enum FilterMode filtering); + int32_t (*yang_I420Scale)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_u, + int32_t src_stride_u, + const uint8_t* src_v, + int32_t src_stride_v, + int32_t src_width, + int32_t src_height, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_u, + int32_t dst_stride_u, + uint8_t* dst_v, + int32_t dst_stride_v, + int32_t dst_width, + int32_t dst_height, + enum FilterMode filtering); + void (*yang_ScalePlane)(const uint8_t* src, + int32_t src_stride, + int32_t src_width, + int32_t src_height, + uint8_t* dst, + int32_t dst_stride, + int32_t dst_width, + int32_t dst_height, + enum FilterMode filtering); + int32_t (*yang_ARGBScale)(const uint8_t* src_argb, + int32_t src_stride_argb, + int32_t src_width, + int32_t src_height, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t dst_width, + int32_t dst_height, + enum FilterMode filtering); +}; + +#endif /* YANGYUVUTIL_H_ */ diff --git a/include/yangavutil/video/YangYuvUtil.h b/include/yangavutil/video/YangYuvUtil.h new file mode 100644 index 0000000000000000000000000000000000000000..8c1503c597c4f391d1729e4766d18b46cc86bc55 --- /dev/null +++ b/include/yangavutil/video/YangYuvUtil.h @@ -0,0 +1,19 @@ +/* + * YangYuvUtil.h + * + * Created on: 2019年8月25日 + * Author: yang + */ + +#ifndef INCLUDE_YANGAVUTIL_VIDEO_YANGYUVUTIL_H_ +#define INCLUDE_YANGAVUTIL_VIDEO_YANGYUVUTIL_H_ +#include "stdint.h" + +void yang_plusNV12(uint8_t* src,uint8_t * dest,int32_t model,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +void yang_plusI420(uint8_t* src,uint8_t * dest,int32_t model,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +void yang_plusYuy2(uint8_t* src,uint8_t * dest,int32_t model,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight); +void yang_rgbtobgr(uint8_t *rgb,uint8_t *bgr,int32_t srcWidth,int32_t srcHeight); +void yang_zoom4(uint8_t* src,uint8_t* dst,int32_t wid,int32_t hei); + + +#endif /* INCLUDE_YANGAVUTIL_VIDEO_YANGYUVUTIL_H_ */ diff --git a/include/yangcapture/YangCaptureFactory.h b/include/yangcapture/YangCaptureFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..98274940eb299e3c3f1dac7a4871a6b0df9f51ef --- /dev/null +++ b/include/yangcapture/YangCaptureFactory.h @@ -0,0 +1,27 @@ +/* + * YangCaptureImpl.h + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#ifndef INCLUDE_YANGCAPTURE_YANGCAPTUREFACTORY_H_ +#define INCLUDE_YANGCAPTURE_YANGCAPTUREFACTORY_H_ +#include +#include +#include "YangScreenCapture.h" +//#include "../include/YangLivingVideoCapture.h" + +class YangCaptureFactory { +public: + YangCaptureFactory(); + virtual ~YangCaptureFactory(); + YangAudioCapture *createAudioCapture(YangContext *pcontext); + YangAudioCapture *createRecordAudioCapture(YangContext *pcontext); + //YangMultiVideoCapture *createVideoCapture(YangVideoInfo *pcontext); + YangMultiVideoCapture *createVideoCapture(YangVideoInfo *pcontext); + YangMultiVideoCapture *createRecordVideoCapture(YangVideoInfo *pcontext); + YangScreenCapture *createScreenCapture(YangContext *pcontext); +}; + +#endif /* INCLUDE_YANGCAPTURE_YANGCAPTUREFACTORY_H_ */ diff --git a/include/yangcapture/YangMultiVideoCapture.h b/include/yangcapture/YangMultiVideoCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..2fca6f08204210a4115615e531cd1e614f6d39bd --- /dev/null +++ b/include/yangcapture/YangMultiVideoCapture.h @@ -0,0 +1,24 @@ +#ifndef YangMultiVideoCapture_H +#define YangMultiVideoCapture_H +#include "yangutil/sys/YangThread.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangLog.h" +#include "YangVideoCapture.h" +class YangMultiVideoCapture: public YangVideoCapture { +public: + YangMultiVideoCapture(); + virtual ~YangMultiVideoCapture(); +public: + virtual void setLivingOutVideoBuffer(YangVideoBuffer *pbuf)=0; + virtual void setLivingVideoCaptureStart()=0; + virtual void setLivingVideoCaptureStop()=0; + virtual int32_t getLivingVideoCaptureState()=0; + + virtual void setFilmOutVideoBuffer(YangVideoBuffer *pbuf)=0; + virtual void setFilmVideoCaptureStart()=0; + virtual void setFilmVideoCaptureStop()=0; + virtual int32_t getFilmVideoCaptureState()=0; +}; + +#endif // YANGVIDEOCAPTURE_H diff --git a/include/yangcapture/YangScreenCapture.h b/include/yangcapture/YangScreenCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..2bf8f11e004f6c4f041e04018364caac5d9aa22b --- /dev/null +++ b/include/yangcapture/YangScreenCapture.h @@ -0,0 +1,44 @@ +/* + * YangScreenCaptureLinux.h + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#ifndef INCLUDE_YANGCAPTURE_YANGSCREENCAPTURE_H_ +#define INCLUDE_YANGCAPTURE_YANGSCREENCAPTURE_H_ + +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangThread.h" +#include "YangScreenCaptureHandleI.h" + + +class YangScreenCapture :public YangThread{ +public: + YangScreenCapture(); + virtual ~YangScreenCapture(); + + int32_t m_isStart; + +public: + virtual void setDrawmouse(bool isDraw)=0; + virtual bool getisDrawmouse()=0; + + virtual void setInterval(int32_t pinterval)=0; + virtual int32_t init()=0; + virtual void setVideoCaptureStart()=0; + virtual void setVideoCaptureStop()=0; + virtual YangVideoBuffer* getOutVideoBuffer()=0; + virtual YangVideoBuffer* getPreVideoBuffer()=0; + virtual int32_t getVideoCaptureState()=0; + void stop(); +protected: + void run(); + virtual void startLoop()=0; + virtual void stopLoop()=0; + + + +}; + +#endif /* INCLUDE_YANGCAPTURE_YANGSCREENCAPTURE_H_ */ diff --git a/include/yangcapture/YangScreenCaptureHandleI.h b/include/yangcapture/YangScreenCaptureHandleI.h new file mode 100644 index 0000000000000000000000000000000000000000..218196a882b7f20f4dac28ff3d81ae5ddb5e0972 --- /dev/null +++ b/include/yangcapture/YangScreenCaptureHandleI.h @@ -0,0 +1,12 @@ +#ifndef YangScreenCaptureI_H_ +#define YangScreenCaptureI_H_ +class YangScreenCaptureHandleI { +public: + YangScreenCaptureHandleI(){} + virtual ~YangScreenCaptureHandleI(){} + int32_t m_width=0,m_height=0; + virtual int32_t init()=0; + virtual int32_t captureFrame(uint8_t* p)=0; +}; + +#endif diff --git a/include/yangcapture/YangVideoCapture.h b/include/yangcapture/YangVideoCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..03e923b435208163ed285cabd4a866a7160040fe --- /dev/null +++ b/include/yangcapture/YangVideoCapture.h @@ -0,0 +1,36 @@ + +#ifndef INCLUDE_YANGCAPTURE_YANGVIDEOCAPTURE_H_ +#define INCLUDE_YANGCAPTURE_YANGVIDEOCAPTURE_H_ +#include +#include +#include +#include +#include +#include + + +void yang_get_camera_indexs(std::vector *pvs,std::string pcamindex); +class YangVideoCapture :public YangThread { +public: + YangVideoCapture(); + virtual ~YangVideoCapture(); +public: + int32_t cameraIndex; + virtual int32_t init()=0; + virtual void setVideoCaptureStart()=0; + virtual void setVideoCaptureStop()=0; + virtual void setOutVideoBuffer(YangVideoBuffer *pbuf)=0; + virtual void setPreVideoBuffer(YangVideoBuffer *pbuf)=0; + virtual int32_t getVideoCaptureState()=0; + virtual void initstamp()=0; + + int32_t m_isStart; + void stop(); +protected: + void run(); + virtual void startLoop()=0; + virtual void stopLoop()=0; + YangVideoInfo *m_para; +}; + +#endif /* INCLUDE_YANGCAPTURE_YANGVIDEOCAPTURE_H_ */ diff --git a/include/yangdecoder/YangAudioDecoder.h b/include/yangdecoder/YangAudioDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..800382a018bf6e4339d05fb50f72d00d0ffaebf7 --- /dev/null +++ b/include/yangdecoder/YangAudioDecoder.h @@ -0,0 +1,31 @@ +/* + * YangAudioDecoder.h + * + * Created on: 2020年9月3日 + * Author: yang + */ + +#ifndef YANGDECODER_INCLUDE_YANGAUDIODECODER_H_ +#define YANGDECODER_INCLUDE_YANGAUDIODECODER_H_ +#include +#include "yangstream/YangStreamType.h" +#include "YangDecoder.h" + + +class YangAudioDecoder{ +public: + YangAudioDecoder(); + virtual ~YangAudioDecoder(); + virtual void init()=0; + virtual int32_t decode(YangFrame* pframe,YangDecoderCallback* pcallback)=0; + int32_t m_uid; +protected: + int32_t m_isInit; + int32_t m_frameSize; + int32_t m_alen; + YangAudioParam *m_context; + uint8_t* m_dstBuffer; + int32_t m_dstLen; +}; + +#endif /* YANGDECODER_INCLUDE_YANGAUDIODECODER_H_ */ diff --git a/include/yangdecoder/YangAudioDecoderHandle.h b/include/yangdecoder/YangAudioDecoderHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..9e929d152ee993dca2e1dfed9e44e65b8aee0e7e --- /dev/null +++ b/include/yangdecoder/YangAudioDecoderHandle.h @@ -0,0 +1,62 @@ + +#ifndef __YangAudioDecoderHandle__ +#define __YangAudioDecoderHandle__ + +#include "stdint.h" +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" + +#include "yangdecoder/YangAudioDecoder.h" +using namespace std; +class YangAudioDecoderHandle:public YangThread,public YangDecoderCallback,public YangMediaConfigCallback +{ +public: + YangAudioDecoderHandle(YangContext *pcontext); + ~YangAudioDecoderHandle(void); + int32_t m_isStart; +private: + int32_t m_isInit; + +public: + + YangAudioPlayBuffer* getOutAudioBuffer(); + void setRemoteParam(YangAudioParam* para); + void init(); + void stop(); + void setInAudioBuffer(YangAudioEncoderBuffer *pbuf); + void setOutAudioBuffer(YangAudioPlayBuffer* pbuf); + void removeAudioStream(int32_t puid); + void removeAllStream(); + + void onAudioData(YangFrame* pframe); + void onVideoData(YangFrame* pframe); + void setMediaConfig(int32_t puid, YangAudioParam *audio,YangVideoParam *video); + +protected: + void run(); + void stopLoop(); + void startLoop(); + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + YangAudioPlayBuffer* m_out_audioBuffer; + YangAudioDecoder *m_decs; + int32_t m_isConvert; + YangAudioEncoderBuffer *m_in_audioBuffer; + YangContext *m_context; + YangAudioParam* m_param; + + //int32_t m_channel; + bool m_is44100; + uint8_t* m_buf; + int32_t m_size; + YangFrame m_audioFrame; + void decode(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + +}; +#endif diff --git a/include/yangdecoder/YangAudioDecoderHandles.h b/include/yangdecoder/YangAudioDecoderHandles.h new file mode 100644 index 0000000000000000000000000000000000000000..1574cf35c706254ad63c65ad46b66a1b5ab4a375 --- /dev/null +++ b/include/yangdecoder/YangAudioDecoderHandles.h @@ -0,0 +1,58 @@ + +#ifndef __YangAudioDecoderHandles__ +#define __YangAudioDecoderHandles__ + +#include "stdint.h" +#include +#include +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" + +#include "yangdecoder/YangAudioDecoder.h" +using namespace std; +class YangAudioDecoderHandles:public YangThread,public YangDecoderCallback +{ +public: + YangAudioDecoderHandles(YangContext *pcontext); + ~YangAudioDecoderHandles(void); + +private: + int32_t m_isInit; + +public: + YangAudioDecoder *getDecoder(int32_t puid); + YangAudioPlayBuffer* getAudioBuffer(int32_t puid); + int32_t getDecoderIndex(int32_t puid); + void init(); + void stop(); + void setInAudioBuffer(YangAudioEncoderBuffer *pbuf); + void setOutAudioBuffer(vector* pbuf); + void removeAudioStream(int32_t puid); + void removeAllStream(); + int32_t m_isStart; + void onAudioData(YangFrame* pframe); + void onVideoData(YangFrame* pframe); + void setRemoteParam(int32_t puid,YangAudioParam* para); + +protected: + void run(); + void stopLoop(); + void startLoop(); + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + std::map m_paramMap; + vector *m_out_audioBuffer; + vector *m_decs; + int32_t m_isConvert; + YangAudioEncoderBuffer *m_in_audioBuffer; + YangContext *m_context; + + int32_t m_frameSize,m_channel; + void decode(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + +}; +#endif diff --git a/include/yangdecoder/YangDecoder.h b/include/yangdecoder/YangDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..762904baba4eb92c3c0dca97a6380f7ad7c5cd9e --- /dev/null +++ b/include/yangdecoder/YangDecoder.h @@ -0,0 +1,14 @@ +#ifndef YANGDECODER_INCLUDE_YANGDECODER_H_ +#define YANGDECODER_INCLUDE_YANGDECODER_H_ + +class YangDecoderCallback{ +public: + YangDecoderCallback(){}; + virtual ~YangDecoderCallback(){}; + virtual void onAudioData(YangFrame* pframe)=0; + virtual void onVideoData(YangFrame* pframe)=0; +}; + + + +#endif /* YANGDECODER_INCLUDE_YANGDECODER_H_ */ diff --git a/include/yangdecoder/YangDecoderFactory.h b/include/yangdecoder/YangDecoderFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..afa4878193e075c1cbcfe421af8c1df8394c38c3 --- /dev/null +++ b/include/yangdecoder/YangDecoderFactory.h @@ -0,0 +1,26 @@ +/* + * YangDecoderFactory.h + * + * Created on: 2019年9月3日 + * Author: yang + */ + +#ifndef YANGDECODER_INCLUDE_YANGDECODERFACTORY_H_ +#define YANGDECODER_INCLUDE_YANGDECODERFACTORY_H_ +#include "yangdecoder/YangAudioDecoder.h" +#include "yangdecoder/YangVideoDecoder.h" + + +class YangDecoderFactory { +public: + YangDecoderFactory(); + virtual ~YangDecoderFactory(); + + YangAudioDecoder* createAudioDecoder(YangAudioEncDecType paet,YangAudioParam *pcontext); + YangAudioDecoder* createAudioDecoder(YangAudioParam *pcontext); + YangVideoDecoder* createVideoDecoder(YangVideoEncDecType paet,YangVideoInfo *pcontext); + YangVideoDecoder* createFfmpegVideoDecoder(YangVideoEncDecType paet,YangVideoInfo *pcontext); + YangVideoDecoder* createVideoDecoder(YangVideoInfo *pcontext); +}; + +#endif /* YANGDECODER_INCLUDE_YANGDECODERFACTORY_H_ */ diff --git a/include/yangdecoder/YangVideoDecoder.h b/include/yangdecoder/YangVideoDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..9f3ed1fc768a33319dcc495296467cf3d6c22655 --- /dev/null +++ b/include/yangdecoder/YangVideoDecoder.h @@ -0,0 +1,22 @@ +#ifndef YANGH264DECODER_H +#define YANGH264DECODER_H +#include +#include "YangDecoder.h" +class YangVideoDecoder { +public: + YangVideoDecoder(){} + virtual ~YangVideoDecoder(){} + virtual void init()=0; + virtual void parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, + int32_t *phei, int32_t *pfps)=0; + virtual int32_t decode(YangFrame* pframe,YangYuvType yuvtype,YangDecoderCallback* pcallback)=0; + int32_t m_isInit=0; + int32_t m_uid = -1; + int32_t m_state = 0; +protected: + +private: + +}; + +#endif // YANGH264DECODER_H diff --git a/include/yangdecoder/YangVideoDecoderHandle.h b/include/yangdecoder/YangVideoDecoderHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..b234c24c55eead5cec4ee92904c8b68e28a29406 --- /dev/null +++ b/include/yangdecoder/YangVideoDecoderHandle.h @@ -0,0 +1,63 @@ +#ifndef __YangVideoDecoderHandle__ +#define __YangVideoDecoderHandle__ +#include "stdint.h" + +#include + +#include "yangutil/buffer/YangVideoDecoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#include "YangVideoDecoder.h" +using namespace std; +class YangVideoDecoderHandle:public YangThread,public YangDecoderCallback +{ +public: + YangVideoDecoderHandle(YangContext *pcontext); + ~YangVideoDecoderHandle(void); + +private: + int32_t isInit; + +public: + int32_t m_isStart; + YangVideoDecoder *getDecoder(int32_t puid); + YangVideoBuffer* getOutVideoBuffer(); + //int32_t getDecoderIndex(int32_t puid); + void parseVideoHeader(uint8_t *p,int32_t pind); + void addVideoStream(uint8_t *ps,int32_t pind,int32_t pisAdd); + //void removeAllStream(); + //int32_t fx; + void init(); + void stop(); + void setInVideoBuffer(YangVideoDecoderBuffer *pbuf); + void setOutVideoBuffer(YangVideoBuffer* pbuf); + + void onAudioData(YangFrame* pframe); + void onVideoData(YangFrame* pframe); + + + + +protected: + void run(); + void stopLoop(); + void startLoop(); + + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + YangVideoDecoderBuffer *m_in_videoBuffer; + YangVideoBuffer *m_out_videoBuffer; + YangVideoDecoder *m_decs; + //vector m_removeList; + int32_t m_isConvert; + YangContext *m_context; + + //void removeStream(); + void decode(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + + +}; +#endif diff --git a/include/yangdecoder/YangVideoDecoderHandles.h b/include/yangdecoder/YangVideoDecoderHandles.h new file mode 100644 index 0000000000000000000000000000000000000000..a6fd5f66735f6d6ec0a6bc395b9dbd52e10cdcb0 --- /dev/null +++ b/include/yangdecoder/YangVideoDecoderHandles.h @@ -0,0 +1,64 @@ +#ifndef __YangVideoDecoderHandles__ +#define __YangVideoDecoderHandles__ +#include "stdint.h" + +#include + +#include "yangutil/buffer/YangVideoDecoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#include "YangVideoDecoder.h" +using namespace std; +class YangVideoDecoderHandles:public YangThread,public YangDecoderCallback +{ +public: + YangVideoDecoderHandles(YangContext *pcontext); + ~YangVideoDecoderHandles(void); + +private: + int32_t isInit; + +public: + int32_t m_isStart; + YangVideoDecoder *getDecoder(int32_t puid); + YangVideoBuffer* getVideoBuffer(int32_t puid); + int32_t getDecoderIndex(int32_t puid); + void parseVideoHeader(uint8_t *p,int32_t pind); + void addVideoStream(uint8_t *ps,int32_t pind,int32_t pisAdd); + void removeAllStream(); + //int32_t fx; + void init(); + void stop(); + void setInVideoBuffer(YangVideoDecoderBuffer *pbuf); + void setOutVideoBuffer(vector* pbuf); + + void onAudioData(YangFrame* pframe); + void onVideoData(YangFrame* pframe); + + + + +protected: + void run(); + void stopLoop(); + void startLoop(); + + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + YangVideoDecoderBuffer *m_in_videoBuffer; + vector *m_out_videoBuffer; + vector *m_decs; + vector m_removeList; + int32_t m_isConvert; + //int32_t m_roomState; + YangContext *m_context; + + void removeStream(); + void decode(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + + +}; +#endif diff --git a/include/yangencoder/YangAudioEncoder.h b/include/yangencoder/YangAudioEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..dfdfff9a0ad6aab6351955b4377ec8d65647ba5a --- /dev/null +++ b/include/yangencoder/YangAudioEncoder.h @@ -0,0 +1,27 @@ +#ifndef ___YangAudioEncoderPipe__ +#define ___YangAudioEncoderPipe__ +#include +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#include "YangEncoder.h" + +class YangAudioEncoder//:public YangThread +{ +public: + YangAudioEncoder(); + virtual ~YangAudioEncoder(void); + virtual void init(YangAudioInfo *pap)=0; + virtual int32_t encoder(YangFrame* pframe,YangEncoderCallback* pcallback)=0; + void stop(); + int32_t m_uid; + +protected: + void setAudioPara(YangAudioInfo *audioInfo); + int32_t m_isInit; + YangAudioInfo m_audioInfo; + //YangAudioFrame m_audioFrame; +}; + +#endif diff --git a/include/yangencoder/YangAudioEncoderHandle.h b/include/yangencoder/YangAudioEncoderHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..ac10698d1bafb25b81ba1f3697cf542f3e2c3b99 --- /dev/null +++ b/include/yangencoder/YangAudioEncoderHandle.h @@ -0,0 +1,53 @@ +#pragma once +#ifndef __YangAudioEncoderrHandle__ +#define __YangAudioEncoderrHandle__ +#include "stdint.h" + +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +#include "yangencoder/YangAudioEncoder.h" +using namespace std; +class YangAudioEncoderHandle:public YangThread,public YangEncoderCallback +{ +public: + YangAudioEncoderHandle(YangAudioInfo *pcontext); + ~YangAudioEncoderHandle(void); + +private: + int32_t m_isInit; + +public: + void init(); + void stop(); + void setInAudioBuffer(YangAudioBuffer *pbuf); + void setOutAudioBuffer(YangAudioEncoderBuffer *pbuf); + + void onVideoData(YangFrame* pframe); + void onAudioData(YangFrame* pframe); + int32_t m_isStart; + int32_t m_uid; + + + +protected: + void run(); + void stopLoop(); + void startLoop(); + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + + YangAudioEncoder *m_enc; + int32_t m_isConvert; + YangAudioBuffer *m_in_audioBuffer; + YangAudioEncoderBuffer *m_out_audioBuffer; + YangAudioInfo *m_context; + void Encoder(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + +}; +#endif diff --git a/include/yangencoder/YangAudioEncoderHandleCb.h b/include/yangencoder/YangAudioEncoderHandleCb.h new file mode 100644 index 0000000000000000000000000000000000000000..f2e6572e35bac611c9ad1ff53acdc504718c94ed --- /dev/null +++ b/include/yangencoder/YangAudioEncoderHandleCb.h @@ -0,0 +1,58 @@ + + +#ifndef YANGENCODER_INCLUDE_YANGAUDIOENCODERHANDLECB_H_ +#define YANGENCODER_INCLUDE_YANGAUDIOENCODERHANDLECB_H_ + +#include "stdint.h" + +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" +//#include "yangutil/YangVideoContext.h" +#include "yangencoder/YangAudioEncoder.h" +using namespace std; +class YangAudioEncoderHandleCb:public YangThread +{ +public: + YangAudioEncoderHandleCb(YangAudioInfo *pcontext); + ~YangAudioEncoderHandleCb(void); + +private: + int32_t m_isInit; + +public: + void init(); + void stop(); + void setInAudioBuffer(YangAudioBuffer *pbuf); + //void setOutAudioBuffer(YangAudioEncoderBuffer *pbuf); + void setCallback(YangEncoderCallback* pcb); + //void setRoomState(int32_t pst); + //void onVideoData(uint8_t* p,int32_t plen,int64_t timestamp,int32_t pframetype,int32_t puid); + //void onAudioData(uint8_t* p,int32_t plen,int32_t puid); + int32_t m_isStart; + int32_t m_uid; + + + +protected: + void run(); + void stopLoop(); + void startLoop(); + +void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + YangEncoderCallback* m_cb; + YangAudioEncoder *m_enc; + int32_t m_isConvert; + //int32_t m_roomState; + YangAudioBuffer *m_in_audioBuffer; + //YangAudioEncoderBuffer *m_out_audioBuffer; + YangAudioInfo *m_context; + void Encoder(int32_t isIframe,uint8_t*src,int32_t p_buflen,uint8_t *dest,int32_t *p_destLen); + +}; +#endif /* YANGENCODER_INCLUDE_YANGAUDIOENCODERHANDLECB_H_ */ diff --git a/include/yangencoder/YangAudioEncoderMeta.h b/include/yangencoder/YangAudioEncoderMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..45e7ed7d004ce8c5ad585c560d122ade80286c2a --- /dev/null +++ b/include/yangencoder/YangAudioEncoderMeta.h @@ -0,0 +1,38 @@ +/* + * YangAudioEncoderMeta.h + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#ifndef YANGENCODER_INCLUDE_YANGAUDIOENCODERMETA_H_ +#define YANGENCODER_INCLUDE_YANGAUDIOENCODERMETA_H_ +#include "faac.h" +#include "yangutil/sys/YangLoadLib.h" + +class YangAudioEncoderMeta{ +public: + YangAudioEncoderMeta(); + ~YangAudioEncoderMeta(); + void createMeta(uint8_t *pasc,int32_t *asclen); +private: + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + faacEncHandle (*yang_faacEncOpen)(unsigned long sampleRate, uint32_t numChannels, + unsigned long *inputSamples, unsigned long *maxOutputBytes); + int32_t (*yang_faacEncSetConfiguration)(faacEncHandle hEncoder,faacEncConfigurationPtr config); + int32_t (*yang_faacEncEncode)(faacEncHandle hEncoder, int32_t * inputBuffer, uint32_t samplesInput, + uint8_t *outputBuffer, uint32_t bufferSize); + int32_t (*yang_faacEncClose)(faacEncHandle hEncoder); + faacEncConfigurationPtr + (*yang_faacEncGetCurrentConfiguration)(faacEncHandle hEncoder); + + + int32_t (*yang_faacEncGetDecoderSpecificInfo)(faacEncHandle hEncoder, uint8_t **ppBuffer, + unsigned long *pSizeOfDecoderSpecificInfo); +}; + + + +#endif /* YANGENCODER_INCLUDE_YANGAUDIOENCODERMETA_H_ */ diff --git a/include/yangencoder/YangEncoder.h b/include/yangencoder/YangEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..0fad4d81c60bc44dd26790598f7f1373865edc97 --- /dev/null +++ b/include/yangencoder/YangEncoder.h @@ -0,0 +1,15 @@ +#ifndef YANGENCODER_INCLUDE_YANGENCODER_H_ +#define YANGENCODER_INCLUDE_YANGENCODER_H_ +#include +class YangEncoderCallback{ +public: + YangEncoderCallback(){}; + virtual ~YangEncoderCallback(){}; + virtual void onVideoData(YangFrame* pframe)=0; + virtual void onAudioData(YangFrame* pframe)=0; +}; + + + + +#endif /* YANGENCODER_INCLUDE_YANGENCODER_H_ */ diff --git a/include/yangencoder/YangEncoderFactory.h b/include/yangencoder/YangEncoderFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..9d7760028b655ce76ead5c3dbec149dea1c3da6d --- /dev/null +++ b/include/yangencoder/YangEncoderFactory.h @@ -0,0 +1,27 @@ +/* + * YangAudioEncoderFactory.h + * + * Created on: 2020年9月3日 + * Author: yang + */ + +#ifndef YANGENCODER_INCLUDE_YANGVIDEOENCODERFACTORY_H_ +#define YANGENCODER_INCLUDE_YANGVIDEOENCODERFACTORY_H_ +#include +#include "YangVideoEncoder.h" +#include "yangencoder/YangAudioEncoder.h" +#include + + +class YangEncoderFactory { +public: + YangEncoderFactory(); + virtual ~YangEncoderFactory(); + YangAudioEncoder* createAudioEncoder(YangAudioEncDecType paet,YangAudioInfo *pcontext); + YangAudioEncoder* createAudioEncoder(YangAudioInfo *pcontext); + YangVideoEncoder* createVideoEncoder(YangVideoEncDecType paet,YangVideoInfo *pcontext); + YangVideoEncoder* createVideoEncoder(YangVideoInfo *pcontext); + YangVideoEncoderMeta* createVideoEncoderMeta(YangVideoInfo *pcontext); +}; + +#endif /* YANGENCODER_INCLUDE_YANGVIDEOENCODERFACTORY_H_ */ diff --git a/include/yangencoder/YangGpuEncoderFactory.h b/include/yangencoder/YangGpuEncoderFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..22cc81c1365855d7d8c1c8c8c38dcfacf0d68743 --- /dev/null +++ b/include/yangencoder/YangGpuEncoderFactory.h @@ -0,0 +1,16 @@ +#ifndef YANGGPUENCODERFACTORY_H +#define YANGGPUENCODERFACTORY_H + +#include +#include +class YangGpuEncoderFactory +{ +public: + + YangGpuEncoderFactory(); + ~YangGpuEncoderFactory(); + YangVideoEncoder* createGpuEncoder(); + +}; + +#endif // YANGGPUENCODERFACTORY_H diff --git a/include/yangencoder/YangVideoEncoder.h b/include/yangencoder/YangVideoEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..4cbee3c9e9799753bd1b26f26c64bf4fdbbef688 --- /dev/null +++ b/include/yangencoder/YangVideoEncoder.h @@ -0,0 +1,30 @@ +/* + * YangH246Encoder.h + * + * Created on: 2019年10月16日 + * Author: yang + */ + +#ifndef YANGENCODER_INCLUDE_YANGVideoENCODER_H_ +#define YANGENCODER_INCLUDE_YANGVideoENCODER_H_ +#include +#include "stdint.h" +#include "YangEncoder.h" + +class YangVideoEncoder{ +public: + YangVideoEncoder(); + virtual ~YangVideoEncoder(); + virtual int32_t init(YangVideoInfo *pvp,YangVideoEncInfo *penc)=0; + virtual int32_t encode(YangFrame* pframe, YangEncoderCallback* pcallback)=0; + virtual void setVideoMetaData(YangVideoMeta *pvmd)=0; + virtual void sendKeyFrame()=0; +protected: + int32_t m_isInit; + YangVideoInfo m_videoInfo; + YangVideoEncInfo m_enc; + uint8_t* m_vbuffer; + void setVideoPara(YangVideoInfo *pap,YangVideoEncInfo *penc); +}; + +#endif /* YANGENCODER_INCLUDE_YANGENCODER_H_ */ diff --git a/include/yangencoder/YangVideoEncoderHandle.h b/include/yangencoder/YangVideoEncoderHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..483141288f078d93f4afdcb6e2351401f11d0a5c --- /dev/null +++ b/include/yangencoder/YangVideoEncoderHandle.h @@ -0,0 +1,52 @@ +#ifndef __YangVideoEncoderHandle__ +#define __YangVideoEncoderHandle__ +#include "YangVideoEncoder.h" +#include "stdint.h" + +#include + +#include "yangutil/buffer/YangVideoEncoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/sys/YangThread.h" + +using namespace std; +class YangVideoEncoderHandle:public YangThread,public YangEncoderCallback +{ +public: + YangVideoEncoderHandle(YangVideoInfo *pcontext,YangVideoEncInfo *enc); + ~YangVideoEncoderHandle(void); + +private: + int32_t m_isInit; + +public: + int32_t m_isStart; + int32_t m_uid; + void init(); + void stop(); + void setOutVideoBuffer(YangVideoEncoderBuffer * pvl); + void setInVideoBuffer(YangVideoBuffer *pvl); + + //void setRoomState(int32_t pst); + void setVideoMetaData(YangVideoMeta *pvmd); + void sendKeyframe(); + void onVideoData(YangFrame* pframe); + void onAudioData(YangFrame* pframe); +protected: + void run(); + void stopLoop(); + void startLoop(); + void saveFile(char *fileName, uint8_t *pBuffer, long BufferLen); + +private: + YangVideoBuffer *m_in_videoBuffer; + YangVideoEncoderBuffer *m_out_videoBuffer; + YangVideoMeta *m_vmd; + int32_t m_isConvert; + YangVideoInfo *m_para; + YangVideoEncInfo *m_enc; + int32_t m_sendKeyframe; + +}; +#endif diff --git a/include/yangplayer/YangPlayFactory.h b/include/yangplayer/YangPlayFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..c8db1a2cf703b70cc175abfbc7dc4054c6a46575 --- /dev/null +++ b/include/yangplayer/YangPlayFactory.h @@ -0,0 +1,24 @@ +/* + * YangPlayFactory.h + * + * Created on: 2020年9月4日 + * Author: yang + */ + +#ifndef YANGPLAYER_INCLUDE_YANGPLAYFACTORY_H_ +#define YANGPLAYER_INCLUDE_YANGPLAYFACTORY_H_ +#include +enum YangAudioPlayType{ + Yang_AP_SDL, + Yang_AP_ALSA, +}; + +class YangPlayFactory { +public: + YangPlayFactory(); + virtual ~YangPlayFactory(); + YangAudioPlay* createAudioPlay(YangAudioInfo *pcontext); + YangAudioPlay *createAudioPlay(YangAudioPlayType paet,YangAudioInfo *pcontext); +}; + +#endif /* YANGPLAYER_INCLUDE_YANGPLAYFACTORY_H_ */ diff --git a/include/yangplayer/YangPlayReceive.h b/include/yangplayer/YangPlayReceive.h new file mode 100644 index 0000000000000000000000000000000000000000..8995be0ce2e6a4e0f26a64f387af1a27b3f6294b --- /dev/null +++ b/include/yangplayer/YangPlayReceive.h @@ -0,0 +1,38 @@ +#ifndef YangPlayReceive_H +#define YangPlayReceive_H +//#include "mytype.h" +#include +#include +#include +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangVideoDecoderBuffer.h" +#include "yangutil/sys/YangThread.h" +using namespace std; +class YangPlayReceive: public YangThread, public YangReceiveCallback +{ + public: + YangPlayReceive(YangContext* pcontext); + virtual ~YangPlayReceive(); + void receiveAudio(YangFrame* audioFrame); + void receiveVideo(YangFrame* videoFrame); + int32_t init(int32_t nettype,string server,int32_t pport,string stream); + void setBuffer(YangAudioEncoderBuffer *al,YangVideoDecoderBuffer *vl); + void disConnect(); + void play(char* pserverStr,char *streamName); + YangStreamHandle *m_recv; + int32_t isReceived; //,isHandled; + int32_t isReceiveConvert; //,isHandleAllInvoke; + int32_t m_isStart; + void stop(); + protected: + void run(); + void startLoop(); + + private: + int32_t m_headLen; + YangAudioEncoderBuffer *m_out_audioBuffer; + YangVideoDecoderBuffer *m_out_videoBuffer; + YangContext* m_context; +}; + +#endif // VIDEOMEETING_H diff --git a/include/yangplayer/YangPlayerBase.h b/include/yangplayer/YangPlayerBase.h new file mode 100644 index 0000000000000000000000000000000000000000..11cd92ff9c6d0f89356994cffca0ae938e9656e6 --- /dev/null +++ b/include/yangplayer/YangPlayerBase.h @@ -0,0 +1,31 @@ +#ifndef MeetingPlayoBase_H +#define MeetingPlayoBase_H +#include +#include +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/buffer/YangVideoDecoderBuffer.h" + +using namespace std; +class YangPlayerBase +{ + public: + YangPlayerBase(); + virtual ~YangPlayerBase(); + YangPlayerDecoder *m_ydb; + YangPlayerPlay *m_ypb; + + void startAudioDecoder(YangAudioEncoderBuffer *prr); + void startVideoDecoder(YangVideoDecoderBuffer *prr); + void init(YangContext* audio); + void startAudioPlay(YangContext* paudio); + void stopAll(); + protected: + + private: + +}; + +#endif // ZBBASE_H diff --git a/include/yangplayer/YangPlayerDecoder.h b/include/yangplayer/YangPlayerDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..3de424155c18e97bf3f838b625e462ffe4800787 --- /dev/null +++ b/include/yangplayer/YangPlayerDecoder.h @@ -0,0 +1,49 @@ +/* + * YangDeocoderBase.h + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#ifndef YANGAPP_YANGDECODERAPP_H_ +#define YANGAPP_YANGDECODERAPP_H_ +#include +#include + +#include + + +#include "yangutil/sys/YangIni.h" + +using namespace std; +class YangPlayerDecoder { +public: + YangPlayerDecoder(YangContext* pcontext); + virtual ~YangPlayerDecoder(); + void initAudioDecoder(); + void initVideoDecoder(); + void setInVideoBuffer(YangVideoDecoderBuffer *pvel); + void setInAudioBuffer(YangAudioEncoderBuffer *pael); + YangVideoBuffer* getOutVideoBuffer(); + YangAudioPlayBuffer* getOutAudioBuffer(); + void startAudioDecoder(); + void startVideoDecoder(); + //YangRoomI* getYangRoomI(); + void setRoomState(int32_t pst); + //void setAddSdl(YangSdlAdd *psa); + void stopAll(); + YangVideoDecoderHandle *m_videoDec; + //YangAudioInfo m_audio;//={0}; +private: + YangContext *m_context; + //YangSynBuffer m_syn; + YangVideoBuffer* m_out_videoBuffer; + YangAudioPlayBuffer* m_out_audioBuffer; + YangAudioDecoderHandle *m_audioDec; + //YangVideoInfo m_video;//={0}; + + //void initList(); +}; + + +#endif /* YANGAPP_YANGDECODERAPP_H_ */ diff --git a/include/yangplayer/YangPlayerHandle.h b/include/yangplayer/YangPlayerHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..1a41394f50d42030af53276d6f368e37576bc06d --- /dev/null +++ b/include/yangplayer/YangPlayerHandle.h @@ -0,0 +1,25 @@ +/* + * YangPlayerHandle.h + * + * Created on: 2021年5月26日 + * Author: yang + */ + +#ifndef INCLUDE_YANGPLAYER_YANGPLAYERHANDLE_H_ +#define INCLUDE_YANGPLAYER_YANGPLAYERHANDLE_H_ +#include +#include +#include +#include +class YangPlayerHandle { +public: + YangPlayerHandle(){}; + virtual ~YangPlayerHandle(){}; + virtual YangVideoBuffer* getVideoBuffer()=0; + virtual int play(std::string url,int32_t localport)=0; + virtual int32_t playRtc(int32_t puid,std::string localIp,int32_t localPort, std::string server, int32_t pport,std::string app,std::string stream)=0; + virtual void stopPlay()=0; + static YangPlayerHandle* createPlayerHandle(YangContext* pcontext,YangSysMessageI* pmessage); +}; + +#endif /* INCLUDE_YANGPLAYER_YANGPLAYERHANDLE_H_ */ diff --git a/include/yangplayer/YangPlayerPlay.h b/include/yangplayer/YangPlayerPlay.h new file mode 100644 index 0000000000000000000000000000000000000000..b59b81e09acd3313e88d2ce1936eae1802f7d294 --- /dev/null +++ b/include/yangplayer/YangPlayerPlay.h @@ -0,0 +1,41 @@ +/* + * YangPlayBase.h + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#ifndef YANGAPP_YANGPLAYAPP_H_ +#define YANGAPP_YANGPLAYAPP_H_ +#include +#include +#include + +#include + + +#include "yangavutil/audio/YangAecBase.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" + +using namespace std; +class YangPlayerPlay { +public: + YangPlayerPlay(); + virtual ~YangPlayerPlay(); + void initAudioPlay(YangContext* paudio); + void startAudioPlay(); + void setInAudioList(YangAudioPlayBuffer *paudioList); + void stopAll(); +private: + #ifdef _WIN32 + YangWinAudioApiRender *m_audioPlay; +#else + YangAudioPlayAlsa *m_audioPlay; +#endif + int32_t vm_audio_player_start; + +}; + +#endif /* YANGAPP_YANGPLAYAPP_H_ */ diff --git a/include/yangplayer/YangWinPlayFactroy.h b/include/yangplayer/YangWinPlayFactroy.h new file mode 100644 index 0000000000000000000000000000000000000000..612046daaec0abd6d85c8483e38f5e229c24acf5 --- /dev/null +++ b/include/yangplayer/YangWinPlayFactroy.h @@ -0,0 +1,47 @@ +/* + * YangPainterFactroy.h + * + * Created on: 2020年9月17日 + * Author: yang + */ + +#ifndef YANGPLAYER_INCLUDE_YANGWINPLAYFACTROY_H_ +#define YANGPLAYER_INCLUDE_YANGWINPLAYFACTROY_H_ +#include + +class YangPainter{ +public: + YangPainter(); + virtual ~YangPainter(); + virtual void draw(void *win,YangRect *prect,YangColor *pcolor)=0; +}; +class YangWinPlay{ + public: + YangWinPlay(); + virtual ~YangWinPlay(); + virtual void init(void* pid)=0; + virtual void initBg(int32_t pwid,int32_t phei)=0; + virtual void initVideo(int32_t pwid,int32_t phei,YangYuvType sdfe)=0; + virtual void initText(char *pname,YangColor *pcolor)=0; + //virtual void initAll(char *pname,YangColor *pcolor,void* pid,int32_t pwid,int32_t phei,YangYuvType sdfe)=0; + + //virtual void reInitBg(int32_t pwid,int32_t phei)=0; + virtual void reInitVideo(int32_t pwid,int32_t phei,YangYuvType sdfe)=0; + virtual void reInitText(char *pname,YangColor *pcolor)=0; + + + virtual void renderPreview(uint8_t* pdata)=0; + virtual void render(uint8_t* pdata)=0; + virtual void render(uint8_t* pdata,int64_t ptimestamp)=0; + virtual void renderBg(YangColor *pcolor)=0; + int32_t m_width,m_height; +}; +class YangWinPlayFactroy { +public: + YangWinPlayFactroy(); + virtual ~YangWinPlayFactroy(); + YangPainter *createPainter(); + YangWinPlay *createWinPlay(); +}; + +#endif /* YANGPLAYER_INCLUDE_YANGWINPLAYFACTROY_H_ */ diff --git a/include/yangpush/YangPushCapture.h b/include/yangpush/YangPushCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..ce9a7dd5a6c5db22b0f6094b3737b4bf8ce9ec08 --- /dev/null +++ b/include/yangpush/YangPushCapture.h @@ -0,0 +1,86 @@ +#ifndef YANGAPP_YangPushCapture_H_ +#define YANGAPP_YangPushCapture_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +class YangPushCapture :public YangThread { +public: + YangPushCapture(YangContext *pcontext); + virtual ~YangPushCapture(); +public: + void startCamera(); + void startScreen(); + void stopCamera(); + void stopScreen(); + void setScreenInterval(int32_t pinterval); + void setDrawmouse(bool isDraw); + void startVideoCaptureState(); + void startScreenCaptureState(); + void stopVideoCaptureState(); + void stopScreenCaptureState(); + int32_t initVideo(); + int32_t initScreen(); + void startVideoCapture(); + void startScreenCapture(); + YangVideoBuffer * getOutVideoBuffer(); + YangVideoBuffer * getPreVideoBuffer(); + + YangVideoBuffer * getScreenOutVideoBuffer(); + YangVideoBuffer * getScreenPreVideoBuffer(); + void stopAll(); + void change(int32_t st); + + + +#if Yang_HaveVr + void addVr(); + void delVr(); +#endif +private: + YangAudioCapture *m_audioCapture; + YangMultiVideoCapture *m_videoCapture; + + YangVideoBuffer *m_out_videoBuffer; + YangVideoBuffer *m_pre_videoBuffer; + + YangVideoBuffer *m_screen_pre_videoBuffer; + YangVideoBuffer *m_screen_out_videoBuffer; + YangScreenCapture* m_screenCapture; + + YangContext *m_context; + YangAudioBuffer *m_out_audioBuffer; + +#if Yang_HaveVr + YangVideoBuffer *m_out_vr_pre_videoBuffer; +#endif +public: + void stop(); + int32_t m_isStart; +protected: + void run(); +#if Yang_HaveVr + void startLoop(); +#else + void startLoop(){}; + #endif + void stopLoop(); + void initVr(); + + int32_t m_isConvert; +public: + int32_t initAudio(YangPreProcess *pp); + void startAudioCapture(); + YangAudioBuffer* getOutAudioBuffer(); + void stopAudioCaptureState(); + void startAudioCaptureState(); + void setAec(YangAecBase *paec); + void setInAudioBuffer(vector *pbuf); +}; + +#endif /* YANGAPP_YANGCAPTUREAPP_H_ */ diff --git a/include/yangpush/YangPushCommon.h b/include/yangpush/YangPushCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..603bf2886c1a8ab6bd3b75d1d92c70dc523d522b --- /dev/null +++ b/include/yangpush/YangPushCommon.h @@ -0,0 +1,24 @@ +#ifndef INCLUDE_YANGPUSH_YANGPUSHCOMMON_H_ +#define INCLUDE_YANGPUSH_YANGPUSHCOMMON_H_ + + +#define Yang_VideoSrc_Camera 0 +#define Yang_VideoSrc_Screen 1 +#define Yang_VideoSrc_OutInterface 2 +enum YangPushMessageType { + YangM_Push_StartAudioCapture, + YangM_Push_StartVideoCapture, + YangM_Push_StartScreenCapture, + YangM_Push_StartOutCapture, + YangM_Push_Publish_Start, + YangM_Push_Publish_Stop, + YangM_Push_Record_Start, + YangM_Push_Record_Stop, + YangM_Push_SwitchToCamera, + YangM_Push_SwitchToScreen, + YangM_Sys_Setvr, + YangM_Sys_UnSetvr + +}; + +#endif /* INCLUDE_YANGPUSH_YANGPUSHCOMMON_H_ */ diff --git a/include/yangpush/YangPushFactory.h b/include/yangpush/YangPushFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..bb7a3b4ce8c51dc64031f1eae017cde32ac2acdf --- /dev/null +++ b/include/yangpush/YangPushFactory.h @@ -0,0 +1,16 @@ +#ifndef INCLUDE_YANGPUSH_YANGPUSHFACTORY_H_ +#define INCLUDE_YANGPUSH_YANGPUSHFACTORY_H_ +#include +#include +#include +class YangPushFactory { +public: + YangPushFactory(); + virtual ~YangPushFactory(); + YangPushHandle* createPushHandle(bool hasAudio,bool initVideo,int pvideotype,YangVideoInfo *screenvideo, YangVideoInfo *outvideo,YangContext* pcontext,YangSysMessageI* pmessage); + YangSysMessageHandle* createPushMessageHandle(bool hasAudio,bool initVideo,int pvideotype,YangVideoInfo *screenvideo, YangVideoInfo *outvideo,YangContext* pcontext,YangSysMessageI* pmessage,YangSysMessageHandleI* pmessagehandle); + YangVideoBuffer* getPreVideoBuffer(YangSysMessageHandle* pmessageHandle); + YangSendVideoI* getSendVideo(YangSysMessageHandle* pmessageHandle); +}; + +#endif /* INCLUDE_YANGPUSH_YANGPUSHFACTORY_H_ */ diff --git a/include/yangpush/YangPushHandle.h b/include/yangpush/YangPushHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..cab48929270a21061e62573b8875f78f57a58352 --- /dev/null +++ b/include/yangpush/YangPushHandle.h @@ -0,0 +1,32 @@ +#ifndef INCLUDE_YANGPUSH_YANGPUSHHANDLE_H_ +#define INCLUDE_YANGPUSH_YANGPUSHHANDLE_H_ +#include +#include +#include +#include +#include +#include +class YangPushHandle { +public: + YangPushHandle(); + virtual ~YangPushHandle(); + virtual int publish(std::string url,std::string localIp,int32_t localport)=0; + virtual void disconnect()=0; + virtual void recordFile(char* filename)=0; + virtual void stopRecord()=0; + virtual void init()=0; + virtual void changeSrc(int videoSrcType,bool pisinit)=0; + + virtual void setScreenVideoInfo(int videoSrcType,YangVideoInfo* pvideo)=0; + virtual void setScreenInterval(int32_t pinterval)=0; + virtual void setDrawmouse(bool isDraw)=0; + virtual YangVideoBuffer* getPreVideoBuffer()=0; + + virtual YangSendVideoI* getSendVideo()=0; + //virtual YangVideoBuffer* getScreenPreVideoBuffer()=0; + +}; + + + +#endif /* INCLUDE_YANGPUSH_YANGPUSHHANDLE_H_ */ diff --git a/include/yangpush/YangPushPublish.h b/include/yangpush/YangPushPublish.h new file mode 100644 index 0000000000000000000000000000000000000000..880e2bc7665a8784c29b6e081f5c07aedc80c51f --- /dev/null +++ b/include/yangpush/YangPushPublish.h @@ -0,0 +1,79 @@ +#ifndef YangPushPublish_H +#define YangPushPublish_H +#include +#include +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/buffer/YangVideoEncoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +class YangPushPublish: public YangSendRequestCallback { +public: + YangPushPublish(YangContext *pcontext); + virtual ~YangPushPublish(); + + void setCaptureType(int pct); + + void startCamera(); + void startScreen(); + void stopCamera(); + void stopScreen(); + void setScreenInterval(int32_t pinterval); + void setDrawmouse(bool isDraw); + void setNetBuffer(YangRtcPublish *prr); + void startPubVideo(); + void startPubAudio(); + void initAudioEncoding(); + void initVideoEncoding(); + void setVideoInfo(YangVideoInfo *pvideo); + int32_t startAudioCapture(); + int32_t startVideoCapture(); + int32_t startScreenCapture(); + + void initVideoMeeting(); + void startAudioEncoding(); + void startVideoEncoding(); + void deleteVideoEncoding(); + void startAudioCaptureState(); + void startVideoCaptureState(); + void startScreenCaptureState(); + void stopAudioCaptureState(); + void stopVideoCaptureState(); + void stopScreenCaptureState(); + YangVideoBuffer* getPreVideoBuffer(); + YangVideoBuffer* getScreenPreVideoBuffer(); + YangVideoBuffer* getScreenOutVideoBuffer(); + YangVideoBuffer* getOutPreVideoBuffer(); + YangVideoBuffer* getOutVideoBuffer(); + void stopAll(); + void setInAudioBuffer(vector *pbuf); + void change(int32_t st); +#if Yang_HaveVr + void addVr(); + void delVr(); +#endif + void sendRequest(int32_t puid, uint32_t ssrc, YangRequestType req); + void sendKeyframe(); + YangPushCapture* getPushCapture(); +protected: + +private: + YangVideoBuffer* m_outVideoBuffer; + YangVideoBuffer* m_outPreVideoBuffer; +private: + YangContext *m_context; + YangPushEncoder *m_encoder; + YangPushCapture *m_capture; + + YangVideoInfo *m_videoInfo; + int32_t isStartAudioCapture, isStartVideoCapture, isStartScreenCapture; + int32_t isStartAudioEncoder, isStartVideoEncoder; + void stopAudioState(); + void stopVideoState(); + void initCapture(); + int m_captureType; +}; + +#endif // diff --git a/include/yangpush/YangRtcPublish.h b/include/yangpush/YangRtcPublish.h new file mode 100644 index 0000000000000000000000000000000000000000..34fcd2f9ff4e9edfc6d872295794babdb3ab4a4e --- /dev/null +++ b/include/yangpush/YangRtcPublish.h @@ -0,0 +1,53 @@ + +#ifndef SRC_YANGMEETING_INCLUDE_YangRtcPublish_H_ +#define SRC_YANGMEETING_INCLUDE_YangRtcPublish_H_ +#include + +#include +#include +#include +#include +#include +using namespace std; +class YangRtcPublish: public YangThread { +public: + YangRtcPublish(YangContext *pcontext); + virtual ~YangRtcPublish(); + + int32_t init(int32_t nettype, string server,string localIp,int32_t localPort, int32_t pport, + string app,string stream); + int32_t connectServer(int32_t puid); + int32_t connectMediaServer(); + int32_t disConnectMediaServer(); + int32_t reconnectMediaServer(); + void setInVideoMetaData(YangVideoMeta *pvmd); + void setInAudioList(YangAudioEncoderBuffer *pbuf); + void setInVideoList(YangVideoEncoderBuffer *pbuf); + + int32_t stopPublishAudioData(); + int32_t stopPublishVideoData(); + + int32_t m_netState; + int32_t isPublished; + int32_t m_isStart; + void stop(); +protected: + void run(); + void handleError(int32_t perrCode); + void startLoop(); + void startLoop_h265(); + YangContext *m_context; + YangVideoMeta *m_vmd; + YangVideoEncoderBuffer *m_in_videoBuffer; + YangAudioEncoderBuffer *m_in_audioBuffer; + + int32_t m_isConvert; + int32_t m_isInit; + int32_t m_audioEncoderType; + std::vector m_pushs; +private: + int32_t m_transType; + int32_t notifyState; +}; + +#endif /* SRC_YANGMEETING_INCLUDE_YangRtcPublish_H_ */ diff --git a/include/yangpush/YangSendVideoI.h b/include/yangpush/YangSendVideoI.h new file mode 100644 index 0000000000000000000000000000000000000000..75c0662dc3cf596e377f4d46c88e976ac1bc077a --- /dev/null +++ b/include/yangpush/YangSendVideoI.h @@ -0,0 +1,15 @@ +#ifndef INCLUDE_YANGPUSH_YANGSENDVIDEOI_H_ +#define INCLUDE_YANGPUSH_YANGSENDVIDEOI_H_ +#include +class YangSendVideoI{ +public: + YangSendVideoI(){}; + virtual ~YangSendVideoI(){}; + virtual void putVideoRgba(uint8_t* data,int len,int64_t timestamp)=0; + virtual void putVideoI420(uint8_t* data,int len,int64_t timestamp)=0; +}; + + + + +#endif /* INCLUDE_YANGPUSH_YANGSENDVIDEOI_H_ */ diff --git a/include/yangrecliving/YangLivingHandle.h b/include/yangrecliving/YangLivingHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..d0036a25a3773b5a5590ba0d2dab40a7ce807744 --- /dev/null +++ b/include/yangrecliving/YangLivingHandle.h @@ -0,0 +1,26 @@ +#ifndef YANGRTMP_INCLUDE_YangRecordLivingHandle_H_ +#define YANGRTMP_INCLUDE_YangRecordLivingHandle_H_ + + +#include +#include +#include "yangutil/buffer/YangVideoBuffer.h" +class YangLivingHandle +{ +public: + YangLivingHandle(); + virtual ~YangLivingHandle(); + + virtual void init()=0; + virtual void recordFile()=0; + virtual void stopRecord()=0; + virtual void pauseRecord()=0; + virtual void resumeRecord()=0; + virtual YangVideoBuffer* getPrebuffer()=0; + + virtual void startVr(char* pbgfile)=0; + virtual void stopVr()=0; + + +}; +#endif diff --git a/include/yangrecliving/YangLivingType.h b/include/yangrecliving/YangLivingType.h new file mode 100644 index 0000000000000000000000000000000000000000..3b680205ca63e9f4bedf718173ac1cd4a205f270 --- /dev/null +++ b/include/yangrecliving/YangLivingType.h @@ -0,0 +1,48 @@ +/* + * yangrecordtype.h + * + * Created on: 2020年10月12日 + * Author: yang + */ + +#ifndef YANGRECLIVING_INCLUDE_YANGRECORDTYPE_H_ +#define YANGRECLIVING_INCLUDE_YANGRECORDTYPE_H_ +#include + +struct YangRecordParam{ + char app[20]; + char filePath[128]; + int32_t roomId; + int32_t hzhType; + int32_t isMp4; + int32_t fileTimeLen; + int32_t livingModel; + int32_t recordModel; + int32_t mode; +}; +class YangRecordContext:public YangContext{ +public: + YangRecordContext(); + ~YangRecordContext(); +public: + void initExt(void *filename); + YangRecordParam record; + //YangCameraParam camera; + int32_t createFile; + int32_t createRtmp; + + int32_t createFile3; + int32_t createRtmp3; + char filename[50]; + char filenames[50]; + char bgFilename[128]; +}; +enum YangRecodeModuleType{ + Yang_Record_Film=1, + Yang_Record_Hzh, + Yang_Record_Res, + Yang_Record_Both +}; + + +#endif /* YANGRECLIVING_INCLUDE_YANGRECORDTYPE_H_ */ diff --git a/include/yangrecliving/YangRecMessageI.h b/include/yangrecliving/YangRecMessageI.h new file mode 100644 index 0000000000000000000000000000000000000000..e27e1daa32aad61ba1b1732d39381bbf735636b3 --- /dev/null +++ b/include/yangrecliving/YangRecMessageI.h @@ -0,0 +1,35 @@ +#ifndef INCLUDE_YANGRECLIVING_YANGRECMESSAGEI_H_ +#define INCLUDE_YANGRECLIVING_YANGRECMESSAGEI_H_ +#include "yangutil/sys/YangSysMessageI.h" +enum YangRecMessageType { + YangM_Rec_Shutdown, + YangM_Rec_ConnectServer, + YangM_Rec_DisconnectServer, + YangM_Rec_ConnectServerInterrupt, + + YangM_Rec_PushMediaServerConnect, + YangM_Rec_PlayMediaServerConnect, + YangM_Rec_PushMediaServerError, + YangM_Rec_PlayMediaServerError, + + YangM_Rec_Start, + YangM_Rec_Stop, + + YangM_Rec_Setvr, + YangM_Rec_UnSetvr, + YangM_Rec_Pubaudio, + YangM_Rec_Pubvideo, + YangM_Rec_UnPubaudio, + YangM_Rec_UnPubvideo, + YangM_Rec_Film_Start, + YangM_Rec_Film_Stop, + YangM_Rec_Pg_Start, + YangM_Rec_pg_Stop, + YangM_Rec_Screen_Start, + YangM_Rec_Screen_Stop +}; + + + + +#endif /* INCLUDE_YANGRECLIVING_YANGRECMESSAGEI_H_ */ diff --git a/include/yangrecliving/YangRecordUtilFactory.h b/include/yangrecliving/YangRecordUtilFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..082a4587cdd0bd3cc7153d82b6ed26b005fb8a1a --- /dev/null +++ b/include/yangrecliving/YangRecordUtilFactory.h @@ -0,0 +1,34 @@ +/* + * YangRecordUtilFactory.h + * + * Created on: 2020年10月17日 + * Author: yang + */ + +#ifndef YANGRECLIVING_INCLUDE_YANGRECORDUTILFACTORY_H_ +#define YANGRECLIVING_INCLUDE_YANGRECORDUTILFACTORY_H_ +#include +#include "YangVrHandle.h" +#include "YangLivingHandle.h" +#include "YangScreenHandle.h" +#include "yangutil/sys/YangSysMessageHandle.h" + + +class YangRecordUtilFactory { +public: + YangRecordUtilFactory(); + virtual ~YangRecordUtilFactory(); + void createIni(const char* p_filename,YangRecordContext *pcontext); + void createIni(const char* p_filename,YangRecordParam *pcontext); + YangVrHandle* createRecordHandle(YangRecordContext *pcontext); + YangLivingHandle* createLivingHandle(YangRecordContext *pcontext); + //YangScreenHandle* createScreenHandle(YangRecordContext *pcontext); + + YangSysMessageHandle* createVrRecMessageHandle(YangRecordContext *pcontext); + YangSysMessageHandle* createRecMessageHandle(YangRecordContext *pcontext); + + YangVrHandle* getVrHandle(YangSysMessageHandle* pms); + YangLivingHandle* getLivingHandle(YangSysMessageHandle* pms); +}; + +#endif /* YANGRECLIVING_INCLUDE_YANGRECORDUTILFACTORY_H_ */ diff --git a/include/yangrecliving/YangScreenHandle.h b/include/yangrecliving/YangScreenHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..5aa5a03ffdc8d04c3b221e72ff3bef603a939b31 --- /dev/null +++ b/include/yangrecliving/YangScreenHandle.h @@ -0,0 +1,29 @@ +#ifndef INCLUDE_YANGRECLIVING_YANGSCREENHANDLE_H_ +#define INCLUDE_YANGRECLIVING_YANGSCREENHANDLE_H_ +#include +#include +#include "yangutil/buffer/YangVideoBuffer.h" +class YangScreenHandle +{ +public: + + YangScreenHandle(); + virtual ~YangScreenHandle(); + + virtual void init()=0; + virtual void recordFile()=0; + virtual void stopRecord()=0; + //virtual void pauseRecord()=0; + //virtual void resumeRecord()=0; + virtual YangVideoBuffer* getPrebuffer()=0; + + virtual void startScreen()=0; + virtual void stopScreen()=0; + //YangRecordContext *m_para; + +}; + + + + +#endif /* INCLUDE_YANGRECLIVING_YANGSCREENHANDLE_H_ */ diff --git a/include/yangrecliving/YangVrHandle.h b/include/yangrecliving/YangVrHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..5928bc692138047f63a9bba9983b8e617b56e819 --- /dev/null +++ b/include/yangrecliving/YangVrHandle.h @@ -0,0 +1,46 @@ +/* + * YangVrHandle.h + * + * Created on: 2020年10月29日 + * Author: yang + */ + +#ifndef YANGRECLIVING_SRC_YANGVRHANDLE_H_ +#define YANGRECLIVING_SRC_YANGVRHANDLE_H_ +#include +#include +#include "yangutil/buffer/YangVideoBuffer.h" + +class YangVrHandle { +public: + YangVrHandle(); + virtual ~YangVrHandle(); + virtual void setVideoCount(int32_t vcount)=0; + virtual void setRecordModule(int32_t mo)=0;; + virtual void setHzhtype(int32_t ttype)=0;; + virtual void startRecordWave(char* filename)=0;; + virtual void stopRecordWave()=0;; + virtual void initPara(YangRecordContext *pra)=0;; + virtual void initAll()=0;; + virtual void reset()=0;; + + + virtual void startRecordLiving()=0;; + virtual void stopRecordLiving()=0;; + virtual void startFilmLiving()=0;; + virtual void stopFilmLiving()=0;; + virtual void startMultiLiving()=0;; + virtual void stopMultiLiving()=0;; + + + // virtual void closeAll()=0;; + virtual void pause()=0;; + virtual void resume()=0;; + virtual void change(int32_t st)=0;; + virtual int32_t isValid(int32_t p_vtype)=0;; + virtual std::vector* getPreVideoBuffer()=0;; + + +}; + +#endif /* YANGRECLIVING_SRC_YANGVRHANDLE_H_ */ diff --git a/include/yangrecord/YangFlvWrite.h b/include/yangrecord/YangFlvWrite.h new file mode 100644 index 0000000000000000000000000000000000000000..6806dbf0476a7c86f340a1b56c72cfabd7d49b97 --- /dev/null +++ b/include/yangrecord/YangFlvWrite.h @@ -0,0 +1,96 @@ +#ifndef __YangFlvWriter__ +#define __YangFlvWriter__ +#include "stdlib.h" +#include "stdio.h" +#include +#include + +//#include "flv_types.h" +//#include "as_objects.h" + +#define FLV_CODEC_NONE -1 +#define FLV_CODEC_FLV1 2 // Sorenson H.263 +#define FLV_CODEC_FLV4 4 // On2 VP6 +#define FLV_CODEC_H264 7 // H.264 + +#define FLV_CODEC_MP3 2 // MP3 +#define FLV_CODEC_AAC 10 // AAC + + +//typedef long __int64; +typedef uint8_t BYTE; +class YangFlvWriter { +public: + + int32_t video_codec; + int32_t audio_codec; + + + double video_fps; + int32_t audio_channels; + int32_t audio_samplerate; + + // time helpers + bool is_first; + int64_t time_first_ms; // timestamp of the first packet + int32_t time_last_ms; // timestamp of the last packet + int32_t duration_ms; // calculated duration (for the onMetaData tag) + int32_t video_raw_size; // size of all video packets + int32_t video_frames; // total video frame count + int32_t file_size; + + int32_t last_tag_size; // helper for writing FLV file + long metadatapos; // byte position in the file + + + +public: + YangFlvWriter(char* fileName, YangAudioInfo *paudio,YangVideoInfo *pvideo); + virtual ~YangFlvWriter(); + void setAudioAac(); + // stream config + FILE *file; + int32_t Reset(); + + int32_t Start(); + int32_t Stop(); + void Close(); + //void ConfigAll(); + int32_t WriteVideoPacket(YangFrame* videoFrame); + int32_t WriteAudioPacket(YangFrame* audioFrame); + void WriteVideoInfo(uint8_t* buf1, int32_t buflen); + double framerate, i_bitrate, i_level_idc; + uint32_t vtime,pre_vt; + uint32_t atime,pre_at; + + //int32_t tick, tickinterval, tickinterval1; + //int32_t tick; + + double atime1; + double perSt; +private: + YangAudioInfo *m_audio; + YangVideoInfo *m_video; + BYTE prev[4]; + BYTE tag_hdr[20]; + // write the data + int32_t m_Video_Bit_Count, m_Video_Width, m_Video_Height; + + short vcount; + int32_t vtcou; + int32_t WriteMetaData(); + + static int32_t MakeAVCc(char* data, int32_t size, char *output_data, + int32_t output_size); + + char * put_amf_string(char *c, const char *str); + char * put_amf_double(char *c, double d); + //char * put_byte(char *output, uint8_t nVal); + + //int32_t WriteExtradata(GUID type); + //AM_MEDIA_TYPE *amt; + //AM_MEDIA_TYPE *vmt; + //int32_t ConfigStream(int32_t isVideo); +}; + +#endif diff --git a/include/yangrecord/YangMp4File.h b/include/yangrecord/YangMp4File.h new file mode 100644 index 0000000000000000000000000000000000000000..ab2b07eb4667bea35701fa7522a7e0b9832b28f2 --- /dev/null +++ b/include/yangrecord/YangMp4File.h @@ -0,0 +1,115 @@ +#ifndef __YangMp4File____ +#define __YangMp4File____ +#include + +#include "faac.h" +#include "yangutil/sys/YangLoadLib.h" +#include "mp4v2/mp4v2.h" + + +class YangMp4File{ + +public : + YangMp4File( char* fileName,YangVideoInfo *pvideo); + ~YangMp4File(); + MP4FileHandle m_MP4hFile ; + MP4TrackId m_mp4Audiotrack ; + MP4TrackId m_mp4Videotrack ; + uint32_t m_ntracks, m_trackno ; + uint32_t m_ndiscs , m_discno ; + const char *m_artist ; + + double m_newtick,m_oldtick,m_newalltick,m_oldalltick,m_tmptick; + int32_t m_tick,m_interval,m_interval1; + uint32_t m_total_samples; + uint32_t m_encoded_samples; + uint32_t m_delay_samples; + uint32_t m_frameSize; + int32_t m_cou; + + + + void init(uint8_t *p_spsBuf, int32_t p_spsLen); + void closeMp4(); + + int32_t WriteVideoPacket(YangFrame* videoFrame); + int32_t WriteAudioPacket(YangFrame* audioFrame); + void WriteVideoInfo(uint8_t *p_vpsBuf,int32_t p_vpsLen,uint8_t *p_spsBuf, int32_t p_spsLen,uint8_t *p_ppsBuf, int32_t p_ppsLen); + void WriteAudioInfo(uint8_t *pasc,unsigned long pasclen,uint8_t* buf1,int32_t buflen); + double m_framerate,m_bitrate, m_level_idc; +private: + YangVideoInfo *m_context; + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + const MP4Tags* (*yang_MP4TagsAlloc)( void ); + void (*yang_MP4TagsFree)( const MP4Tags* tags ); + MP4FileHandle (*yang_MP4Create)(const char* fileName,uint32_t flags); + bool (*yang_MP4TagsFetch)( const MP4Tags* tags, MP4FileHandle hFile ); + bool (*yang_MP4TagsSetSortArtist) ( const MP4Tags*, const char* ); + bool (*yang_MP4TagsStore)( const MP4Tags* tags, MP4FileHandle hFile ); + bool (*yang_MP4SetTimeScale)( MP4FileHandle hFile, uint32_t value ); + void (*yang_MP4SetVideoProfileLevel)( MP4FileHandle hFile, uint8_t value ); + void (*yang_MP4SetAudioProfileLevel)( MP4FileHandle hFile, uint8_t value ); + MP4TrackId (*yang_MP4AddAudioTrack)( MP4FileHandle hFile, uint32_t timeScale, + MP4Duration sampleDuration, uint8_t audioType ); + MP4TrackId (*yang_MP4AddH264VideoTrack)( + MP4FileHandle hFile, uint32_t timeScale,MP4Duration sampleDuration,uint16_t width,uint16_t height, uint8_t AVCProfileIndication + ,uint8_t profile_compat, uint8_t AVCLevelIndication, uint8_t sampleLenFieldSizeMinusOne ); + bool (*yang_MP4SetTrackESConfiguration)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pConfig, + uint32_t configSize ); + void (*yang_MP4AddH264SequenceParameterSet)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen ); + void (*yang_MP4AddH264PictureParameterSet)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen ); + bool (*yang_MP4WriteSample)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pBytes, + uint32_t numBytes, + MP4Duration duration, + MP4Duration renderingOffset, + bool isSyncSample); + void (*yang_MP4Close)( + MP4FileHandle hFile, + uint32_t flags); + + MP4TrackId (*yang_MP4AddH265VideoTrack)( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t isIso); + void (*yang_MP4AddH265SequenceParameterSet)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen ); + void (*yang_MP4AddH265PictureParameterSet)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen ); + void (*yang_MP4AddH265VideoParameterSet) (MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen); + uint32_t (*yang_MP4GetTrackTimeScale)( + MP4FileHandle hFile, + MP4TrackId trackId ); + bool (*yang_MP4SetTrackTimeScale)( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t value ); +}; +#endif diff --git a/include/yangrecord/YangMp4FileApp.h b/include/yangrecord/YangMp4FileApp.h new file mode 100644 index 0000000000000000000000000000000000000000..591b8143ec968901c13d4bdb99f78eb4158a9edf --- /dev/null +++ b/include/yangrecord/YangMp4FileApp.h @@ -0,0 +1,38 @@ +/* + * YangRecordHandle.h + * + * Created on: 2020年10月4日 + * Author: yang + */ + +#ifndef SRC_YANGRECORD_SRC_YangMp4FileApp_H_ +#define SRC_YANGRECORD_SRC_YangMp4FileApp_H_ +#include +#include "yangrecord/YangRecEncoder.h" +#include "yangrecord/YangRecordMp4.h" + +class YangMp4FileApp { +public: + YangMp4FileApp(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc); + virtual ~YangMp4FileApp(); + + YangRecEncoder *m_enc; + YangRecordMp4 *m_rec; + +public: + void init(); + void startRecordMp4(char *filename0,int32_t p_module,int32_t p_isMp4); + void stopRecordMp4(); + void setInAudioBuffer(YangAudioBuffer *pbuf); + void setInVideoBuffer(YangVideoBuffer *pbuf); + void setFileTimeLen(int32_t ptlen_min); + void pauseRecord(); + void resumeRecord(); +private: + YangAudioInfo *m_audio; + YangVideoInfo *m_video; + YangVideoEncInfo *m_encPara; + int32_t m_isPause; +}; + +#endif /* SRC_YANGRECORD_SRC_YANGRECORDHANDLE_H_ */ diff --git a/include/yangrecord/YangRecEncoder.h b/include/yangrecord/YangRecEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..4494afbb995e71e13033eb689e57df73a230b25f --- /dev/null +++ b/include/yangrecord/YangRecEncoder.h @@ -0,0 +1,44 @@ +/* + * YangEncoder.h + * + * Created on: 2020年10月3日 + * Author: yang + */ + +#ifndef SRC_YANGRECORD_SRC_YANGRECENCODER_H_ +#define SRC_YANGRECORD_SRC_YANGRECENCODER_H_ +#include "yangencoder/YangAudioEncoderHandle.h" +#include "yangencoder/YangVideoEncoderHandle.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/buffer/YangVideoEncoderBuffer.h" + +class YangRecEncoder { +public: + YangRecEncoder(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc); + virtual ~YangRecEncoder(); +public: + void initVideoEncoder(); + void initAudioEncoder(); + void startAudioEncoder(); + void startVideoEncoder(); + //void setAVList(YangAudioList *pal,YangVideoList *pvl); + void setInAudioBuffer(YangAudioBuffer *pal); + void setInVideoBuffer(YangVideoBuffer *pvl); + YangAudioEncoderBuffer * getOutAudioBuffer(); + YangVideoEncoderBuffer * getOutVideoBuffer(); + YangVideoMeta * getOutVideoMetaData(); + YangVideoEncoderHandle *m_ve=NULL; + YangAudioEncoderHandle *m_ae=NULL; +private: + YangAudioInfo *m_audio; + YangVideoInfo *m_video; + YangVideoEncInfo *m_enc; + YangVideoMeta *m_vmd; + YangAudioEncoderBuffer *m_out_auidoBuffer; + YangVideoEncoderBuffer *m_out_videoBuffer; + +}; + +#endif /* SRC_YANGRECORD_SRC_YANGRECENCODER_H_ */ diff --git a/include/yangrecord/YangRecord.h b/include/yangrecord/YangRecord.h new file mode 100644 index 0000000000000000000000000000000000000000..0846b1c756f77d92a60fcfc83ac9baa3c4df783b --- /dev/null +++ b/include/yangrecord/YangRecord.h @@ -0,0 +1,64 @@ +/* + * YangRecord.h + * + * Created on: 2020年10月11日 + * Author: yang + */ + +#ifndef YANGRECORD_INCLUDE_YANGRECORD_H_ +#define YANGRECORD_INCLUDE_YANGRECORD_H_ + +#include "yangutil/sys/YangTime.h" +#include "YangFlvWrite.h" + +#include "YangMp4File.h" + +struct YangMp4Para { + YangVideoMeta *vmd; + uint8_t asc[10]; + char *fileName; + int32_t ascLen; +}; +class YangRecord { +public: + YangRecord(YangAudioInfo *paudio, YangVideoInfo *pvideo, + YangVideoEncInfo *penc); + ~YangRecord(void); + + int32_t isMp4; + void initPara(YangVideoMeta *p_vmd, char *filename, int32_t p_isMp4); + void setFileTimeLen(int32_t ptlen_min); + void pauseRec(); + void resumeRec(); + void writeVideoData(YangFrame* videoFrame); + void writeAudioData(YangFrame* audioFrame); + void closeRec(); + YangMp4File *mp4; + YangFlvWriter *flv; + YangAudioInfo *m_audio; + YangVideoInfo *m_video; + YangVideoEncInfo *m_enc; + + int64_t oldalltick, alltick; + int32_t curVideoTimestamp; + long videoDestLen; + int64_t preVideotimestamp, basestamp, minusStamp; + +private: + int64_t m_prePauseTime, m_afterPauseTime; + int64_t m_pauseTime; + int64_t m_alltime1; + int32_t m_alltime; + int32_t m_fileTimeLen; + int32_t m_isCreateNewFile; + //YangTime m_time; + YangMp4Para m_mp4Para; + void createNewfile(); + void createFile(char *filename); + void initRecPara(); + int32_t m_fileId; + //YangAudioFrame m_audioFrame; + //YangVideoFrame m_videoFrame; +}; + +#endif /* YANGRECORD_INCLUDE_YANGRECORD_H_ */ diff --git a/include/yangrecord/YangRecordApp.h b/include/yangrecord/YangRecordApp.h new file mode 100644 index 0000000000000000000000000000000000000000..ec9f80599901dd7f20b2735081a30563a779eb05 --- /dev/null +++ b/include/yangrecord/YangRecordApp.h @@ -0,0 +1,33 @@ +/* + * YangRecZbHandle.h + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#ifndef YANGRECORD_INCLUDE_YANGRECORDAPP_H_ +#define YANGRECORD_INCLUDE_YANGRECORDAPP_H_ +#include +#include +#include "YangMp4FileApp.h" +#include "YangRecordCapture.h" + +class YangRecordApp { +public: + YangRecordApp(YangContext* pcontext); + virtual ~YangRecordApp(); + YangRecordCapture *m_cap; + YangMp4FileApp *m_rec; + void init(); + void recordFile(char* filename); + void stopRecord(); + void pauseRecord(); + void resumeRecord(); + +private: + YangContext* m_context; + + +}; + +#endif /* YANGRECORD_INCLUDE_YANGRECORDAPP_H_ */ diff --git a/include/yangrecord/YangRecordCapture.h b/include/yangrecord/YangRecordCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..8c04b50b27669971d738f38ca2b6680d0ce8e438 --- /dev/null +++ b/include/yangrecord/YangRecordCapture.h @@ -0,0 +1,81 @@ +/* + * YangCaptureBase.h + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#ifndef YANGAPP_YangReczbCapture_H_ +#define YANGAPP_YangReczbCapture_H_ +#include +#include +#include +#include +#include +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "yangutil/buffer/YangAudioPlayBuffer.h" +#include "yangutil/sys/YangThread.h" +using namespace std; + +class YangRecordCapture:public YangThread { +public: + YangRecordCapture(YangContext* pcontext); + virtual ~YangRecordCapture(); +public: + void startAudioCaptureState(); + void startVideoCaptureState(); + void stopAudioCaptureState(); + void stopVideoCaptureState(); + void startPauseCaptureState(); + void stopPauseCaptureState(); + void initAudio(YangPreProcess *pp); + void initVideo(); + void startAudioCapture(); + void startVideoCapture(); + void stopAudioCapture(); + void stopVideoCapture(); + void setAec(YangAecBase *paec); + void setInAudioBuffer(vector *pbuf); + + void startVr(char* pbg); + void stopVr(); + + void startScreen(); + void stopScreen(); + + YangAudioBuffer * getOutAudioBuffer(); + YangVideoBuffer * getOutVideoBuffer(); + YangVideoBuffer * getPreVideoBuffer(); + YangAudioCapture *m_audioCapture; + //YangMultiVideoCapture *m_videoCapture; + YangVideoCapture *m_videoCapture; + YangScreenCapture *m_screenCapture; + + int32_t m_isStart; + void stop(); +protected: + void run(); + void startVrLoop(); + void startScreenLoop(); + void stopLoop(); + int32_t m_isConvert; + int32_t m_isScreen; + string m_bgFileName; +private: + //YangAudioInfo *m_audio; + //YangVideoInfo *m_video; + YangContext* m_context; + YangCaptureFactory m_capture; + YangAudioBuffer *m_out_audioBuffer; + YangVideoBuffer *m_out_videoBuffer; + YangVideoBuffer *m_pre_videoBuffer; + + YangVideoBuffer *m_vr_videoBuffer; + YangVideoBuffer *m_screen_videoBuffer; + + +}; + +#endif /* YANGAPP_YANGCAPTUREAPP_H_ */ diff --git a/include/yangrecord/YangRecordMp4.h b/include/yangrecord/YangRecordMp4.h new file mode 100644 index 0000000000000000000000000000000000000000..5cc64949de93fb5e475cb2aa99d836bc11caea9a --- /dev/null +++ b/include/yangrecord/YangRecordMp4.h @@ -0,0 +1,75 @@ +#ifndef _YangRecordMp4_H +#define _YangRecordMp4_H +#include "yangutil/sys/YangThread.h" +#include "yangutil/sys/YangTime.h" +#include "yangutil/buffer/YangVideoEncoderBuffer.h" +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "YangFlvWrite.h" +#include "YangMp4File.h" +struct YangMp4FilePara{ + YangVideoMeta *vmd; + uint8_t asc[10]; + char *fileName; + int32_t ascLen; +}; +class YangRecordMp4:public YangThread +{ +public: + YangRecordMp4(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc); + ~YangRecordMp4(void); + + int32_t isMp4; + int32_t m_isStart; + void setInVideoBuffer(YangVideoEncoderBuffer *pbuf); + void setInAudioBuffer(YangAudioEncoderBuffer *pbuf); + void initPara(YangVideoMeta *p_vmd, char *filename,int32_t p_isMp4); + void setFileTimeLen(int32_t ptlen_min); + void pauseRec(); + void resumeRec(); + void stop(); +protected: + void run(); +private: + void startLoop(); + void stopLoop(); + void closeRec(); + + YangMp4File *mp4; + YangFlvWriter *flv; + YangAudioInfo *m_audio; + YangVideoInfo *m_video; + YangVideoEncInfo *m_enc; + YangAudioEncoderBuffer *m_in_audioBuffer; + YangVideoEncoderBuffer *m_in_videoBuffer; + int64_t oldalltick,alltick; + int32_t curVideoTimestamp; + long videoDestLen; + int32_t frameType; + uint8_t *srcVideoSource; + uint8_t *srcAudioSource; + //int32_t audioBufLen; + int64_t m_videoTimestamp,m_preVideotimestamp,m_startStamp,m_mp4Stamp; + // int32_t videoBufLen; + + int32_t m_isConvert; + void writeVideoData(); + void writeAudioData(); + +private: + int64_t m_prePauseTime,m_afterPauseTime; + int64_t m_pauseTime; + int64_t m_alltime1; + int32_t m_alltime; + int32_t m_fileTimeLen; + int32_t m_isCreateNewFile; + YangFrame m_videoFrame; + YangFrame m_audioFrame; + YangMp4FilePara m_mp4Para; + void createNewfile(); + void createFile(char* filename); + void initRecPara(); + int32_t m_fileId; +}; + +#endif + diff --git a/include/yangrtmp/YangInvokeBuffer.h b/include/yangrtmp/YangInvokeBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..eb8da38ecdcc8c4f45c3e9c98312ba7097696750 --- /dev/null +++ b/include/yangrtmp/YangInvokeBuffer.h @@ -0,0 +1,34 @@ +/* + * InvokeList.h + * + * Created on: 2019年9月27日 + * Author: yang + */ + +#ifndef YANGRTMP_IMPL_YANGINVOKELIST_H_ +#define YANGRTMP_IMPL_YANGINVOKELIST_H_ +#include "YangRtmpBase.h" +#include "stdint.h" + + +class YangInvokeBuffer { +public: + YangInvokeBuffer(); + virtual ~YangInvokeBuffer(); + //int32_t start; + //int32_t first; + int32_t index; + int32_t newIndex; + int32_t size; + int32_t pac_len; + void reset(); + void resetIndex(); + char *cache,*tmp,*tmp1; + int32_t a_len,m_cache_num;//,m_cache_num_cap; + void putPacket(RTMPPacket *pac); + void getPacket(RTMPPacket *pac); + + +}; + +#endif /* YANGRTMP_IMPL_YANGINVOKELIST_H_ */ diff --git a/include/yangrtmp/YangRtmpBase.h b/include/yangrtmp/YangRtmpBase.h new file mode 100644 index 0000000000000000000000000000000000000000..440570c15da0a9060ff473ab01f65462150ed953 --- /dev/null +++ b/include/yangrtmp/YangRtmpBase.h @@ -0,0 +1,382 @@ +/* + * YangLibRtmp.h + * + * Created on: 2019年9月2日 + * Author: yang + */ + +#ifndef YANGRTMP_IMPL_YANGRTMPBASE_H_ +#define YANGRTMP_IMPL_YANGRTMPBASE_H_ +#include +#include + +#include "yangutil/sys/YangAmf.h" +#include "yangutil/sys/YangLog.h" +#include +#include +using namespace std; + + +#define RTMP_LIB_VERSION 0x020300 /* 2.3 */ +#define RTMP_FEATURE_HTTP 0x01 +#define RTMP_FEATURE_ENC 0x02 +#define RTMP_FEATURE_SSL 0x04 +#define RTMP_FEATURE_MFP 0x08 /* not yet supported */ +#define RTMP_FEATURE_WRITE 0x10 /* publish, not play */ +#define RTMP_FEATURE_HTTP2 0x20 /* server-side rtmpt */ +#define RTMP_PROTOCOL_UNDEFINED -1 +#define RTMP_PROTOCOL_RTMP 0 +#define RTMP_PROTOCOL_RTMPE RTMP_FEATURE_ENC +#define RTMP_PROTOCOL_RTMPT RTMP_FEATURE_HTTP +#define RTMP_PROTOCOL_RTMPS RTMP_FEATURE_SSL +#define RTMP_PROTOCOL_RTMPTE (RTMP_FEATURE_HTTP|RTMP_FEATURE_ENC) +#define RTMP_PROTOCOL_RTMPTS (RTMP_FEATURE_HTTP|RTMP_FEATURE_SSL) +#define RTMP_PROTOCOL_RTMFP RTMP_FEATURE_MFP +#define RTMP_DEFAULT_CHUNKSIZE 128 +#define RTMP_CHANNELS 65600 +/* RTMP_PACKET_TYPE_... 0x00 */ +#define RTMP_PACKET_TYPE_CHUNK_SIZE 0x01 +/* RTMP_PACKET_TYPE_... 0x02 */ +#define RTMP_PACKET_TYPE_BYTES_READ_REPORT 0x03 +#define RTMP_PACKET_TYPE_CONTROL 0x04 +#define RTMP_PACKET_TYPE_SERVER_BW 0x05 +#define RTMP_PACKET_TYPE_CLIENT_BW 0x06 +#define RTMP_PACKET_TYPE_AUDIO 0x08 +#define RTMP_PACKET_TYPE_VIDEO 0x09 +/* RTMP_PACKET_TYPE_... 0x07 */ + +/* RTMP_PACKET_TYPE_... 0x0A */ +/* RTMP_PACKET_TYPE_... 0x0B */ +/* RTMP_PACKET_TYPE_... 0x0C */ +/* RTMP_PACKET_TYPE_... 0x0D */ +/* RTMP_PACKET_TYPE_... 0x0E */ +#define RTMP_PACKET_TYPE_FLEX_STREAM_SEND 0x0F +#define RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT 0x10 +#define RTMP_PACKET_TYPE_FLEX_MESSAGE 0x11 +#define RTMP_PACKET_TYPE_INFO 0x12 +#define RTMP_PACKET_TYPE_SHARED_OBJECT 0x13 +#define RTMP_PACKET_TYPE_INVOKE 0x14 +/* RTMP_PACKET_TYPE_... 0x15 */ +#define RTMP_PACKET_TYPE_FLASH_VIDEO 0x16 +#define RTMP_PACKET_SIZE_LARGE 0 +#define RTMP_PACKET_SIZE_MEDIUM 1 +#define RTMP_PACKET_SIZE_SMALL 2 +#define RTMP_PACKET_SIZE_MINIMUM 3 +/* needs to fit largest number of bytes recv() may return */ +#define RTMP_BUFFER_CACHE_SIZE (16*1024) +#define RTMP_MAX_HEADER_SIZE 18 +#define RTMP_MAX_BODY_SIZE 512000 +#define RTMP_SIG_SIZE 1536 +#define RTMP_LARGE_HEADER_SIZE 12 + +#define RTMPPacket_IsReady(a) ((a)->m_nBytesRead == (a)->m_nBodySize) + +#define GetSockError() errno +#define SetSockError(e) errno = e +#undef closesocket +#ifdef _WIN32 + +#else +#define closesocket(s) close(s) +#endif +#define msleep(n) yang_usleep(n*1000) +#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +//#endif + + + +#define SAVC(x) const AVal av_##x = AVC(#x) +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) +#define MAX_IGNORED_FRAMES 50 +#define HEADERBUF (128*1024) +#define OFF(x) offsetof(struct RTMP,x) + + +enum { + OPT_STR = 0, OPT_INT, OPT_BOOL, OPT_CONN +}; +struct RTMPChunk { + int32_t c_headerSize; + int32_t c_chunkSize; + char *c_chunk; + char c_header[RTMP_MAX_HEADER_SIZE]; +}; + +struct RTMPPacket { + uint8_t m_headerType; + uint8_t m_packetType; + uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */ + int32_t m_nChannel; + uint32_t m_nTimeStamp; /* timestamp */ + int32_t m_nInfoField2; /* last 4 bytes in a long header */ + uint32_t m_nBodySize; + uint32_t m_nBytesRead; + RTMPChunk *m_chunk; + char *m_body; +}; + +struct RTMPSockBuf { + int32_t sb_socket; + int32_t sb_size; /* number of unprocessed bytes in buffer */ + char *sb_start; /* pointer into sb_pBuffer of next byte to process */ + char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */ + int32_t sb_timedout; + void *sb_ssl; +}; + +struct RTMP_LNK { + AVal hostname; + AVal sockshost; + AVal curPath; + AVal curPatht; + char streamType; + AVal tcUrl; + AVal swfUrl; + AVal pageUrl; + AVal app; + AVal auth; + AVal flashVer; + AVal subscribepath; + AVal usherToken; + AVal token; + AVal pubUser; + AVal pubPasswd; + AMFObject extras; + int32_t edepth; + + int32_t seekTime; + int32_t stopTime; + +#define RTMP_LF_AUTH 0x0001 /* using auth param */ +//#define RTMP_LF_LIVE 0x0002 /* stream is live */ +#define RTMP_LF_SWFV 0x0004 /* do SWF verification */ +#define RTMP_LF_PLST 0x0008 /* send playlist before play */ +#define RTMP_LF_BUFX 0x0010 /* toggle stream on BufferEmpty msg */ +#define RTMP_LF_FTCU 0x0020 /* free tcUrl on close */ +#define RTMP_LF_FAPU 0x0040 /* free app on close */ + int32_t lFlags; + + int32_t swfAge; + + int32_t protocol; + int32_t timeout; /* connection timeout in seconds */ + + int32_t pFlags; /* unused, but kept to avoid breaking ABI */ + + unsigned short socksport; + unsigned short port; +}; +struct RTMP_READ { + char *buf; + char *bufpos; + uint32_t buflen; + uint32_t timestamp; + uint8_t dataType; + uint8_t flags; +#define RTMP_READ_HEADER 0x01 +#define RTMP_READ_RESUME 0x02 +#define RTMP_READ_NO_IGNORE 0x04 +#define RTMP_READ_GOTKF 0x08 +#define RTMP_READ_GOTFLVK 0x10 +#define RTMP_READ_SEEKING 0x20 + int8_t status; +#define RTMP_READ_COMPLETE -3 +#define RTMP_READ_ERROR -2 +#define RTMP_READ_EOF -1 +#define RTMP_READ_IGNORE 0 + + /* if bResume == TRUE */ + uint8_t initialFrameType; + uint32_t nResumeTS; + char *metaHeader; + char *initialFrame; + uint32_t nMetaHeaderSize; + uint32_t nInitialFrameSize; + uint32_t nIgnoredFrameCounter; + uint32_t nIgnoredFlvFrameCounter; +}; + +struct RTMP_METHOD { + AVal name; + int32_t num; +}; + +struct YangNetStatus{ + char code[64]; + char description[64]; + char fmsVer[64]; +}; + +struct RTMP { + int32_t m_inChunkSize; + int32_t m_outChunkSize; + int32_t m_nBWCheckCounter; + int32_t m_nBytesIn; + int32_t m_nBytesInSent; + int32_t m_nBufferMS; + int32_t m_stream_id; /* returned in _result from createStream */ + int32_t m_mediaChannel; + uint32_t m_mediaStamp; + uint32_t m_pauseStamp; + int32_t m_pausing; + int32_t m_nServerBW; + int32_t m_nClientBW; + uint8_t m_nClientBW2; + uint8_t m_bPlaying; + uint8_t m_bSendEncoding; + uint8_t m_bSendCounter; + uint8_t m_bConnected; + + int32_t m_numInvokes; + int32_t m_numCalls; + RTMP_METHOD *m_methodCalls; /* remote method calls queue */ + + int32_t m_channelsAllocatedIn; + int32_t m_channelsAllocatedOut; + RTMPPacket **m_vecChannelsIn; + RTMPPacket **m_vecChannelsOut; + int32_t *m_channelTimestamp; /* abs timestamp of last packet */ + + double m_fAudioCodecs; /* audioCodecs for the connect packet */ + double m_fVideoCodecs; /* videoCodecs for the connect packet */ + double m_fEncoding; /* AMF0 or AMF3 */ + + double m_fDuration; /* duration of stream in seconds */ + + int32_t m_isPublish; + + int32_t m_msgCounter; /* RTMPT stuff */ + int32_t m_polling; + int32_t m_resplen; + int32_t m_unackd; + AVal m_clientID; + + RTMP_READ m_read; + RTMPPacket m_write; + RTMPSockBuf m_sb; + RTMP_LNK Link; + YangNetStatus netStatus; +}; + +class YangRtmpBase { +public: + YangRtmpBase(); + virtual ~YangRtmpBase(); + //YangLog *m_log; + RTMP *r; + int32_t m_errState; + //virtual void netStatusHandler(char *code); + void setPublishState(int32_t p_pubstate); + int32_t connectServer(); + int32_t HandleStream(char *psName,YangStreamOptType isPublish,int32_t puid); + int32_t connectRtmpServer(YangStreamOptType pisPublish,char *serverIp,char *app,int32_t port); + void initRTMP(char *serverIp,char *app,int32_t port); + void initRTMP(char *serverIp,char *app,int32_t meetingId,int32_t port); + int32_t initConnect(RTMPPacket *cp); + void setBufferMS(int32_t size); + int32_t readPacket(RTMPPacket *packet); + int32_t yangReadPacket(RTMPPacket *packet,char* pszbody); + int32_t sendPacket(RTMPPacket *packet, int32_t queue); + int32_t yangSendPacket(RTMPPacket *packet, int32_t queue); + int32_t clientPacket(RTMPPacket *packet); + int32_t clientPacket_conn(RTMPPacket *packet); + void freePacket(RTMPPacket *packet); + int32_t RTMP_SetupURL( char *url); + int32_t RTMP_SetOpt(const AVal *opt, AVal *arg); + int32_t RTMP_Connect0(struct sockaddr *svc); + int32_t RTMP_Connect1(RTMPPacket *cp); + int32_t RTMP_Serve(); + int32_t RTMP_SendChunk(RTMPChunk *chunk); + int32_t RTMP_Socket(); + int32_t RTMP_ToggleStream(); + void RTMP_DeleteStream(); + void RTMP_Init(); + void RTMP_Close(); + void deleteR(); + void RTMP_Free(); + int32_t RTMP_LibVersion(void); + void RTMP_UserInterrupt(void); + int32_t RTMP_SendCtrl(short nType, uint32_t nObject, uint32_t nTime); + int32_t RTMP_SendCtrlPong(short nType, char *p,int32_t len); + int32_t RTMP_SendPause(int32_t DoPause, int32_t dTime); + int32_t RTMP_Pause(int32_t DoPause); + int32_t RTMP_SendCreateStream(); + int32_t RTMP_SendSeek(int32_t dTime); + int32_t RTMP_SendServerBW(); + int32_t RTMP_SendClientBW(); + void RTMP_DropRequest(int32_t i, int32_t freeit); + int32_t RTMP_Read(char *buf, int32_t size); + int32_t RTMP_Write(const char *buf, int32_t size); + int32_t RTMP_HashSWF(const char *url, uint32_t *size, uint8_t *hash,int32_t age); + int32_t SendFCUnpublish(); + int32_t SendDeleteStream(double dStreamId); + int32_t SendCloseStream(double dStreamId); + int32_t RTMP_ctrlC; + char pathChar[30]; + //int32_t m_streamState; + //int32_t m_isHandleStream; +protected: + void yang_handleconn(AMFObject *pob); + uint32_t RTMP_GetTime(); + void RTMP_OptUsage(); + //void RTMP_UserInterrupt(); + //void RTMPPacket_Reset(RTMPPacket *p); + int32_t RTMPSockBuf_Close(RTMPSockBuf *sb); + int32_t RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int32_t len) ; + void HandleClientBW(const RTMPPacket *packet); + void HandleServerBW(const RTMPPacket *packet); + void HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet); + int32_t HandleMetadata(char *body, uint32_t len); + int32_t DumpMetaData(AMFObject *obj); + void RTMPPacket_Dump(RTMPPacket *p); + void RTMPPacket_Reset(RTMPPacket *p); + void SocksSetup(AVal *sockshost); + int32_t RTMPPacket_Alloc(RTMPPacket *p, uint32_t nSize); + void RTMPPacket_Free(RTMPPacket *p); + int32_t RTMP_IsConnected(); + void CloseInternal(int32_t reconnect); + int32_t add_addr_info(struct sockaddr_in *service, AVal *host, int32_t port); + void handleError(int32_t perrCode); + int32_t SocksNegotiate(); + int32_t ReadN(char *buffer, int32_t n); + int32_t WriteN(const char *buffer, int32_t n); + int32_t SendConnectPacket(RTMPPacket *cp); + int32_t SendFCSubscribe(AVal *subscribepath); + int32_t SendUsherToken(AVal *usherToken); + // void CloseInternal( int32_t reconnect); + int32_t yang_ParseURL( char *url, int32_t *protocol, AVal *host, + uint32_t *port, AVal *app); + void RTMP_SetupStream(int32_t protocol, AVal *host, uint32_t port, + AVal *sockshost, AVal *playpath, AVal *tcUrl, AVal *swfUrl, + AVal *pageUrl, AVal *app, AVal *auth, AVal *swfSHA256Hash, + uint32_t swfSize, AVal *flashVer, AVal *subscribepath, AVal *usherToken, + int32_t dStart, int32_t dStop, int32_t bLiveStream, int64_t timeout); + int32_t RTMP_ParseURL(char *url, int32_t *protocol, AVal *host, uint32_t *port, + AVal *playpath, AVal *app); + int32_t RTMP_ParseURL1(char *url, int32_t *protocol, AVal *host, uint32_t *port,AVal *app); + int32_t parseAMF(AMFObject *obj, AVal *av, int32_t *depth); + int32_t yang_SetupURL(char *url,int32_t pport); + int32_t SendReleaseStream(); + int32_t SendPublish(); + int32_t SendFCPublish(); + int32_t SendPong(double txn); + int32_t SendCheckBWResult(double txn); + int32_t SendCheckBW(); + int32_t SendBytesReceived(); + int32_t HandleInvoke(const char *body, uint32_t nBodySize); + int32_t SendSecureTokenResponse(AVal *resp); + int32_t SendPlay(); + int32_t SendPlaylist(); + void HandleCtrl(const RTMPPacket *packet); + int32_t HandShake(int32_t FP9HandShake); + int32_t SHandShake(); + AVal* getPlayPath(); + //AVal getPlayPath1(); +private: + //void initAVStreams(); + int32_t RTMPSockBuf_Fill( RTMPSockBuf *sb); +private: + +}; + +#endif /* YANGRTMP_IMPL_YANGRTMPBASE_H_ */ diff --git a/include/yangrtp/YangRtp.h b/include/yangrtp/YangRtp.h new file mode 100644 index 0000000000000000000000000000000000000000..b79e5afc6d8d31091c76b7bf9bed9137094a2bc6 --- /dev/null +++ b/include/yangrtp/YangRtp.h @@ -0,0 +1,216 @@ + +#ifndef YANGWEBRTC_YANGRTCRTP_H_ +#define YANGWEBRTC_YANGRTCRTP_H_ +#include +#include +#include +#include +#include +using namespace std; + +class YangRtpPacket; +// The payload type, for performance to avoid dynamic cast. +enum YangRtspPacketPayloadType +{ + YangRtspPacketPayloadTypeRaw, + YangRtspPacketPayloadTypeFUA2, + YangRtspPacketPayloadTypeFUA, + YangRtspPacketPayloadTypeNALU, + YangRtspPacketPayloadTypeSTAP, + YangRtspPacketPayloadTypeUnknown, +}; + +enum YangRtpExtensionType +{ + kRtpExtensionNone, + kRtpExtensionTransportSequenceNumber, + kRtpExtensionAudioLevel, + kRtpExtensionNumberOfExtensions // Must be the last entity in the enum. +}; + +const std::string kAudioLevelUri = "urn:ietf:params:rtp-hdrext:ssrc-audio-level"; + +struct YangExtensionInfo +{ + YangRtpExtensionType type; + std::string uri; +}; + +// Fast parse the SSRC from RTP packet. Return 0 if invalid. +uint32_t yang_rtp_fast_parse_ssrc(char* buf, int32_t size); +uint8_t yang_rtp_fast_parse_pt(char* buf, int32_t size); +int32_t yang_rtp_fast_parse_twcc(char* buf, int32_t size, uint8_t twcc_id, uint16_t& twcc_sn); + + + +// The "distance" between two uint16 number, for example: +// distance(prev_value=3, value=5) === (int16_t)(uint16_t)((uint16_t)3-(uint16_t)5) === -2 +// distance(prev_value=3, value=65534) === (int16_t)(uint16_t)((uint16_t)3-(uint16_t)65534) === 5 +// distance(prev_value=65532, value=65534) === (int16_t)(uint16_t)((uint16_t)65532-(uint16_t)65534) === -2 +// For RTP sequence, it's only uint16 and may flip back, so 3 maybe 3+0xffff. +// @remark Note that srs_rtp_seq_distance(0, 32768)>0 is TRUE by https://mp.weixin.qq.com/s/JZTInmlB9FUWXBQw_7NYqg +// but for WebRTC jitter buffer it's FALSE and we follow it. +// @remark For srs_rtp_seq_distance(32768, 0)>0, it's FALSE definitely. +inline int16_t yang_rtp_seq_distance(const uint16_t& prev_value, const uint16_t& value) +{ + return (int16_t)(value - prev_value); +} + +// For map to compare the sequence of RTP. +struct YangSeqCompareLess { + bool operator()(const uint16_t& pre_value, const uint16_t& value) const { + return yang_rtp_seq_distance(pre_value, value) > 0; + } +}; + +bool yang_seq_is_newer(uint16_t value, uint16_t pre_value); +bool yang_seq_is_rollback(uint16_t value, uint16_t pre_value); +int32_t yang_seq_distance(uint16_t value, uint16_t pre_value); + + +// The common payload interface for RTP packet. +class IYangRtpPayloader //: public IYangCodec +{ +public: + IYangRtpPayloader(); + virtual ~IYangRtpPayloader(); +public: + virtual IYangRtpPayloader* copy() = 0; + virtual int32_t decode(YangBuffer* buf) = 0; + virtual int32_t encode(YangBuffer* buf) = 0; + virtual uint64_t nb_bytes() = 0; + virtual int32_t nb_size()=0; +}; +class YangRtpPayloader //: public IYangCodec +{ +public: + YangRtpPayloader(); + virtual ~YangRtpPayloader(); + + char* m_payload; + int32_t m_size; +public: + virtual YangRtpPayloader* copy() = 0; + virtual int32_t decode(YangBuffer* buf) = 0; + virtual int32_t encode(YangBuffer* buf) = 0; + virtual uint64_t nb_bytes() = 0; + virtual bool getStart()=0; +}; +/** +class IYangRtspPacketDecodeHandler +{ +public: + IYangRtspPacketDecodeHandler(); + virtual ~IYangRtspPacketDecodeHandler(); +public: + // We don't know the actual payload, so we depends on external handler. + virtual void on_before_decode_payload(YangRtpPacket* pkt, YangBuffer* buf, YangRtpPayloader** ppayload, YangRtspPacketPayloadType* ppt) = 0; +}; +**/ + + +class YangRtpExtensionTypes +{ +public: + static const YangRtpExtensionType kInvalidType = kRtpExtensionNone; + static const int32_t kInvalidId = 0; +public: + bool register_by_uri(int32_t id, std::string uri); + YangRtpExtensionType get_type(int32_t id) const; +public: + YangRtpExtensionTypes(); + virtual ~YangRtpExtensionTypes(); +private: + bool register_id(int32_t id, YangRtpExtensionType type, std::string uri); +private: + uint8_t m_ids[kRtpExtensionNumberOfExtensions]; +}; + +// Note that the extensions should never extends from any class, for performance. +class YangRtpExtensionTwcc// : public ISrsCodec +{ + bool m_has_twcc; + uint8_t m_id; + uint16_t m_sn; +public: + YangRtpExtensionTwcc(); + virtual ~YangRtpExtensionTwcc(); +public: + inline bool exists() { return m_has_twcc; } // SrsRtpExtensionTwcc::exists + uint8_t get_id(); + void set_id(uint8_t id); + uint16_t get_sn(); + void set_sn(uint16_t sn); +public: + // ISrsCodec + virtual int32_t decode(YangBuffer* buf); + virtual int32_t encode(YangBuffer* buf); + virtual uint64_t nb_bytes(); +}; + +// Note that the extensions should never extends from any class, for performance. +class YangRtpExtensionOneByte// : public ISrsCodec +{ + bool m_has_ext; + int32_t m_id; + uint8_t m_value; +public: + YangRtpExtensionOneByte(); + virtual ~YangRtpExtensionOneByte(); +public: + inline bool exists() { return m_has_ext; } // SrsRtpExtensionOneByte::exists + int32_t get_id() { return m_id; } + uint8_t get_value() { return m_value; } + void set_id(int32_t id); + void set_value(uint8_t value); +public: + + virtual int32_t decode(YangBuffer* buf); + virtual int32_t encode(YangBuffer* buf); + virtual uint64_t nb_bytes() { return 2; }; +}; + +struct YangRtpExtension{ + bool m_has_ext; + // by default, twcc isnot decoded. Because it is decoded by fast function(srs_rtp_fast_parse_twcc) + bool m_decode_twcc_extension; +}; +// Note that the extensions should never extends from any class, for performance. +class YangRtpExtensions// : public ISrsCodec +{ +private: + bool m_has_ext; + // by default, twcc isnot decoded. Because it is decoded by fast function(srs_rtp_fast_parse_twcc) + bool m_decode_twcc_extension; +private: + // The extension types is used to decode the packet, which is reference to + // the types in publish stream. + YangRtpExtensionTypes* m_types; +private: + YangRtpExtensionTwcc m_twcc; + YangRtpExtensionOneByte m_audio_level; +public: + YangRtpExtensions(); + virtual ~YangRtpExtensions(); +public: + void enable_twcc_decode() { m_decode_twcc_extension = true; } // SrsRtpExtensions::enable_twcc_decode + inline bool exists() { return m_has_ext; } // SrsRtpExtensions::exists + void set_types_(YangRtpExtensionTypes* types); + int32_t get_twcc_sequence_number(uint16_t& twcc_sn); + int32_t set_twcc_sequence_number(uint8_t id, uint16_t sn); + int32_t get_audio_level(uint8_t& level); + int32_t set_audio_level(int32_t id, uint8_t level); +// ISrsCodec +public: + virtual int32_t decode(YangBuffer* buf); +private: + int32_t decode_0xbede(YangBuffer* buf); +public: + virtual int32_t encode(YangBuffer* buf); + virtual uint64_t nb_bytes(); +}; + + + + +#endif /* YANGWEBRTC_YANGRTCRTP_H_ */ diff --git a/include/yangrtp/YangRtpConstant.h b/include/yangrtp/YangRtpConstant.h new file mode 100644 index 0000000000000000000000000000000000000000..d0b9979a7ebd734b1baba841bde651b5f78d95a4 --- /dev/null +++ b/include/yangrtp/YangRtpConstant.h @@ -0,0 +1,59 @@ + +#ifndef YANGWEBRTC_YANGRTCCOMM_H_ +#define YANGWEBRTC_YANGRTCCOMM_H_ +#include +#define YANG_UTIME_MILLISECONDS 1000 + +const int32_t kRtpPacketSize = 1500; + +const uint8_t kSR = 200; +const uint8_t kRR = 201; +const uint8_t kSDES = 202; +const uint8_t kBye = 203; +const uint8_t kApp = 204; + +// @see: https://tools.ietf.org/html/rfc4585#section-6.1 +const uint8_t kRtpFb = 205; +const uint8_t kPsFb = 206; +const uint8_t kXR = 207; + + +// Firefox defaults as 109, Chrome is 111. +const int32_t kAudioPayloadType = 111; +const int32_t kAudioChannel = 2; +const int32_t kAudioSamplerate = 48000; + +// Firefox defaults as 126, Chrome is 102. +const int32_t kVideoPayloadType = 102; +const int32_t kVideoSamplerate = 90000; +const int32_t kRtpMaxPayloadSize = kRtpPacketSize - 200; + +const int32_t kRtcpPacketSize = 1500; +const uint8_t kRtcpVersion = 0x2; + +// 1500 - 20(ip_header) - 8(udp_header) +const int32_t kMaxUDPDataSize = 1472; + +// @see: https://tools.ietf.org/html/rfc4585#section-6.3 +const uint8_t kPLI = 1; +const uint8_t kSLI = 2; +const uint8_t kRPSI = 3; +const uint8_t kAFB = 15; + +const int32_t kRtpHeaderFixedSize = 12; +const uint8_t kRtpMarker = 0x80; + +// H.264 nalu header type mask. + + +// @see: https://tools.ietf.org/html/rfc6184#section-5.2 +const uint8_t kStapA = 24; + +// @see: https://tools.ietf.org/html/rfc6184#section-5.2 +const uint8_t kFuA = 28; + +// @see: https://tools.ietf.org/html/rfc6184#section-5.8 +const uint8_t kStart = 0x80; // Fu-header start bit +const uint8_t kEnd = 0x40; // Fu-header end bit + +#endif /* YANGWEBRTC_YANGRTCCOMM_H_ */ diff --git a/include/yangsrt/YangSrtBase.h b/include/yangsrt/YangSrtBase.h new file mode 100644 index 0000000000000000000000000000000000000000..cda7f6aef6302111799eedb3b16c2a3314faea5a --- /dev/null +++ b/include/yangsrt/YangSrtBase.h @@ -0,0 +1,78 @@ +/* + * YangSrtBase.h + * + * Created on: 2020年8月4日 + * Author: yang + */ + +#ifndef YANGSRTBASE_H_ +#define YANGSRTBASE_H_ +#include "stdint.h" +#ifdef __WIN32 +#include +#include +#include +#endif +#include +#include "srt/srt.h" +#include "yangutil/YangErrorCode.h" +#include "yangutil/sys/YangLoadLib.h" + +#define YangSrtBase_strlen 128 +#define YangSrtUnitLen 188 +#define Yang_Srt_CacheSize 4096 + +class YangSrtBase { +public: + YangSrtBase(); + virtual ~YangSrtBase(); + int32_t init(char *pserver,int32_t pport); + int32_t publish(char* message,int32_t len); + int32_t receive(char *p,int32_t *len); + //int32_t receive2(char *p,int32_t *len); + void startLoop(); + void closeSrt(); + int32_t initConnect(char *streamId); + int32_t connectServer(); + int32_t getSrtSocketStatus(); +#ifdef _WIN32 + int32_t yang_inet_pton(int32_t af, const char * src, void * dst); +#endif + int64_t get_bitrate(); + int32_t m_errState; + int32_t m_contextt; +private: + int32_t m_port; + int32_t m_sfd; + int32_t m_eid; + char m_server[YangSrtBase_strlen]; + int64_t m_dataCount; + int64_t m_bitRate; + int64_t m_beginTm; + + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + int32_t (*yang_srt_epoll_create)(void); + int32_t (*yang_srt_epoll_remove_usock)(int32_t eid, SRTSOCKET u); + int32_t (*yang_srt_epoll_release)(int32_t eid); + int32_t (*yang_srt_close) (SRTSOCKET u); + int32_t (*yang_srt_cleanup)(void); + int32_t (*yang_srt_startup)(void); + SRT_SOCKSTATUS (*yang_srt_getsockstate)(SRTSOCKET u); + void (*yang_srt_setloglevel)(int32_t ll); + SRTSOCKET (*yang_srt_create_socket)(void); + int32_t (*yang_srt_epoll_set)(int32_t eid, int32_t flags); + int32_t (*yang_srt_epoll_add_usock)(int32_t eid, SRTSOCKET u, const int* events); + int32_t (*yang_srt_setsockopt) (SRTSOCKET u, int32_t level /*ignored*/, SRT_SOCKOPT optname, const void* optval, int32_t optlen); + int32_t (*yang_srt_setsockflag) (SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int32_t optlen); + int32_t (*yang_srt_connect ) (SRTSOCKET u, const struct sockaddr* name, int32_t namelen); + int32_t (*yang_srt_epoll_wait)(int32_t eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, + SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); + int32_t (*yang_srt_sendmsg) (SRTSOCKET u, const char* buf, int32_t len, int32_t ttl/* = -1*/, int32_t inorder/* = false*/); + int32_t (*yang_srt_recvmsg) (SRTSOCKET u, char* buf, int32_t len); + int32_t (*yang_srt_getlasterror)(int* errno_loc); + const char* (*yang_srt_getlasterror_str)(void); +}; + +#endif /* YANGSRTBASE_H_ */ diff --git a/include/yangsrt/YangTsBuffer.h b/include/yangsrt/YangTsBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..66fd43ff7b0b33e4b62c7c1a5cb412cd661c3aa6 --- /dev/null +++ b/include/yangsrt/YangTsBuffer.h @@ -0,0 +1,53 @@ +#ifndef __SIMPLE_BUFFER_H__ +#define __SIMPLE_BUFFER_H__ + +#include +#include +#include + +// only support little endian +class YangTsBuffer +{ +public: + YangTsBuffer(); + YangTsBuffer(int32_t size, char value); + virtual ~YangTsBuffer(); + +public: + void write_1byte(char val); + void write_2bytes(int16_t val); + void write_3bytes(int32_t val); + void write_4bytes(int32_t val); + void write_8bytes(int64_t val); + void writeBytes(uint8_t* bytes,int32_t size); + void append( uint8_t* bytes, int32_t size); + +public: + char read_1byte(); + int16_t read_2bytes(); + int32_t read_3bytes(); + int32_t read_4bytes(); + int64_t read_8bytes(); + void readBytes(uint8_t *p,int32_t len); + std::string read_string(int32_t len); + +public: + void skip(int32_t size); + bool require(int32_t required_size); + bool empty(); + int32_t size(); + int32_t pos(); + uint8_t *data(); + void clear(); + void set_data(int32_t pos, const uint8_t *data, int32_t len); + +public: + std::string to_string(); + +private: + uint8_t _data[188*2]; + int32_t _pos; + int32_t curPos; +}; + +#endif /* __SIMPLE_BUFFER_H__ */ diff --git a/include/yangsrt/YangTsMuxer.h b/include/yangsrt/YangTsMuxer.h new file mode 100644 index 0000000000000000000000000000000000000000..09b217df1868e0d0f6bee48f277000300631767c --- /dev/null +++ b/include/yangsrt/YangTsMuxer.h @@ -0,0 +1,118 @@ + +/* + * YangTsMux.h + * + * Created on: 2020年8月7日 + * Author: yang + */ + +#ifndef YANGTS_YANGTSMUXER_H_ +#define YANGTS_YANGTSMUXER_H_ +#include "stdint.h" +#include +#include + +#include "YangTsBuffer.h" +#include "YangTsPacket.h" +#include "YangTsPid.h" +using namespace std; + +/** +static const int32_t DEFAULT_PCR_PID = 4097; +static const int32_t DEFAULT_PMT_PID = 256; + +static const uint8_t SEQUENCE_END_CODE = 0xb7; +static const uint8_t ISO_11172_END_CODE = 0xb9; +static const uint8_t PACK_START_CODE = 0xba; +static const uint8_t SYSTEM_HEADER_START_CODE = 0xbb; +static const uint8_t PES_PROGRAM_STREAM_MAP = 0xbc; +static const uint8_t PES_PRIVATE_DATA1 = 0xbd; +static const uint8_t PADDING_STREAM = 0xbe; +static const uint8_t PES_PRIVATE_DATA2 = 0xbf; +static const uint8_t PROGRAM_STREAM_DIRECTORY = 0xff; + +static const uint8_t PES_AUDIO_ID = 0xc0; +static const uint8_t PES_VIDEO_ID = 0xe1; +static const uint8_t PES_VC1_ID = 0xfd; + +static const uint8_t DVB_SUBT_DESCID = 0x59; + +static const uint8_t STREAM_TYPE_VIDEO_MPEG1 = 0x01; +static const uint8_t STREAM_TYPE_VIDEO_MPEG2 = 0x02; +static const uint8_t STREAM_TYPE_PRIVATE_SECTION = 0x05; +static const uint8_t STREAM_TYPE_PRIVATE_DATA = 0x06; +static const uint8_t STREAM_TYPE_VIDEO_MPEG4 = 0x10; +static const uint8_t STREAM_TYPE_VIDEO_H264 = 0x1b; +static const uint8_t STREAM_TYPE_VIDEO_MVC = 0x20; +static const uint8_t STREAM_TYPE_VIDEO_H265 = 0x24; +static const uint8_t STREAM_TYPE_VIDEO_VC1 = 0xea; + +static const uint8_t STREAM_TYPE_AUDIO_MPEG1 = 0x03; +static const uint8_t STREAM_TYPE_AUDIO_MPEG2 = 0x04; +static const uint8_t STREAM_TYPE_AUDIO_AAC = 0x0f; +static const uint8_t STREAM_TYPE_AUDIO_AAC_RAW = 0x11; +static const uint8_t STREAM_TYPE_AUDIO_DTS = 0x82; // 0x8a + +static const uint8_t STREAM_TYPE_AUDIO_LPCM = 0x80; +static const uint8_t STREAM_TYPE_AUDIO_AC3 = 0x81; +static const uint8_t STREAM_TYPE_AUDIO_EAC3 = 0x84; +static const uint8_t STREAM_TYPE_AUDIO_EAC3_ATSC = 0x87; +static const uint8_t STREAM_TYPE_AUDIO_EAC3_TRUE_HD = 0x83; +static const uint8_t STREAM_TYPE_AUDIO_DTS_HD = 0x85; +static const uint8_t STREAM_TYPE_AUDIO_DTS_HD_MASTER_AUDIO = 0x86; + +static const uint8_t STREAM_TYPE_AUDIO_EAC3_SECONDARY = 0xA1; +static const uint8_t STREAM_TYPE_AUDIO_DTS_HD_SECONDARY = 0xA2; + +static const uint8_t STREAM_TYPE_AUDIO_VC9 = 0x88; +static const uint8_t STREAM_TYPE_AUDIO_OPUS = 0x89; +static const uint8_t STREAM_TYPE_SUB_PGS = 0x90; + +static const uint8_t STREAM_TYPE_SUBTITLE_DVB = 0x00; +**/ +#define pat_interval 50 +enum YangTsStream{ + TS_H264, + TS_H265, + TS_AAC, + TS_OPUS, + TS_PRIVATE + +}; +struct YangTsPes{ + uint8_t *data; + int32_t len; + int32_t pos; + uint64_t pts; + uint64_t dts; + uint64_t pcr; + uint8_t stream_type; + uint8_t stream_id; + uint16_t pid; +}; +class YangTsMuxer { +public: + YangTsMuxer(); + virtual ~YangTsMuxer(); + void create_pat(YangTsBuffer *sb, uint16_t pmt_pid, uint8_t cc); + void create_pmt(YangTsBuffer *sb,uint8_t cc); + void create_ts(YangTsPes *frame,vector *sb); + void create_pes(YangTsPes *frame,uint8_t *p,int32_t plen,int32_t frametype,int64_t timestamp,YangTsStream streamType); + void create_pcr(YangTsBuffer *sb); + void create_null(YangTsBuffer *sb); + void encode(uint8_t* p,int32_t plen,int32_t frametype,int64_t timestamp ,YangTsStream streamType,vector *sb); + void encodeWithPmt(uint8_t* p,int32_t plen,int32_t frametype,int64_t timestamp ,YangTsStream streamType,vector *sb); + //void encodePmt(vector *sb); + void encodePmtWithoutData(vector *sb); + std::map m_stream_pid_map; +private: + uint8_t get_cc(uint32_t with_pid); + bool should_create_pat(); + int32_t m_pmt_pid; + + int32_t current_index; +private: + std::map _pid_cc_map; +}; + +#endif /* YANGTS_YANGTSMUXER_H_ */ diff --git a/include/yangsrt/YangTsPacket.h b/include/yangsrt/YangTsPacket.h new file mode 100644 index 0000000000000000000000000000000000000000..14a47f302e2a040241278796c776715d7a2ed552 --- /dev/null +++ b/include/yangsrt/YangTsPacket.h @@ -0,0 +1,189 @@ +#pragma once + +#include +#include +#include +#include + +class YangTsBuffer; + +class MpegTsStream +{ +public: + static const uint8_t AAC = 0x0f; + static const uint8_t AVC = 0x1b; +}; + +class TsFrame +{ +public: + TsFrame(); + TsFrame(uint8_t st); + virtual ~TsFrame(){}; + +public: + bool empty(); + void reset(); + +public: + std::shared_ptr _data; + uint64_t pts; + uint64_t dts; + uint64_t pcr; + uint8_t stream_type; + uint8_t stream_id; + uint16_t pid; + uint16_t expected_pes_packet_length; + bool completed; +}; + +class TsHeader +{ +public: + TsHeader(); + virtual ~TsHeader(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + +public: + uint8_t sync_byte; // 8 bits + uint8_t transport_error_indicator; // 1 bit + uint8_t payload_unit_start_indicator; // 1 bit + uint8_t transport_priority; // 1 bit + uint16_t pid; // 13 bits + uint8_t transport_scrambling_control; // 2 bits + uint8_t adaptation_field_control; // 2 bits + uint8_t continuity_counter; // 4 bits +}; + +class PATHeader +{ +public: + PATHeader(); + virtual ~PATHeader(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + void print(); + +public: + uint8_t table_id; // 8 bits + uint8_t section_syntax_indicator; // 1 bit + uint8_t b0; // 1 bit + uint8_t reserved0; // 2 bits + uint16_t section_length; // 12 bits + uint16_t transport_stream_id; // 16 bits + uint8_t reserved1; // 2 bits + uint8_t version_number; // 5 bits + uint8_t current_next_indicator; // 1 bit + uint8_t section_number; // 8 bits + uint8_t last_section_number; // 8 bits +}; + +class PMTElementInfo +{ +public: + PMTElementInfo(); + PMTElementInfo(uint8_t st, uint16_t pid); + virtual ~PMTElementInfo(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + uint16_t size(); + void print(); + +public: + uint8_t stream_type; // 8 bits + uint8_t reserved0; // 3 bits + uint16_t elementary_PID; // 13 bits + uint8_t reserved1; // 4 bits + uint16_t ES_info_length; // 12 bits + std::string ES_info; +}; + +class PMTHeader +{ +public: + PMTHeader(); + virtual ~PMTHeader(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + uint16_t size(); + void print(); + +public: + uint8_t table_id; // 8 bits + uint8_t section_syntax_indicator; // 1 bit + uint8_t b0; // 1 bit + uint8_t reserved0; // 2 bits + uint16_t section_length; // 12 bits + uint16_t program_number; // 16 bits + uint8_t reserved1; // 2 bits + uint8_t version_number; // 5 bits + uint8_t current_next_indicator; // 1 bit + uint8_t section_number; // 8 bits + uint8_t last_section_number; // 8 bits + uint8_t reserved2; // 3 bits + uint16_t PCR_PID; // 13 bits + uint8_t reserved3; // 4 bits + uint16_t program_info_length; // 12 bits + std::vector> infos; +}; + +class AdaptationFieldHeader +{ +public: + AdaptationFieldHeader(); + virtual ~AdaptationFieldHeader(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + +public: + uint8_t adaptation_field_length; // 8 bits + uint8_t adaptation_field_extension_flag; // 1 bit + uint8_t transport_private_data_flag; // 1 bit + uint8_t splicing_point_flag; // 1 bit + uint8_t opcr_flag; // 1 bit + uint8_t pcr_flag; // 1 bit + uint8_t elementary_stream_priority_indicator; // 1 bit + uint8_t random_access_indicator; // 1 bit + uint8_t discontinuity_indicator; // 1 bit +}; + +class PESHeader +{ +public: + PESHeader(); + virtual ~PESHeader(); + +public: + void encode(YangTsBuffer *sb); + void decode(YangTsBuffer *sb); + +public: + uint32_t packet_start_code; // 24 bits + uint8_t stream_id; // 8 bits + uint16_t pes_packet_length; // 16 bits + uint8_t original_or_copy; // 1 bit + uint8_t copyright; // 1 bit + uint8_t data_alignment_indicator; // 1 bit + uint8_t pes_priority; // 1 bit + uint8_t pes_scrambling_control; // 2 bits + uint8_t marker_bits; // 2 bits + uint8_t pes_ext_flag; // 1 bit + uint8_t pes_crc_flag; // 1 bit + uint8_t add_copy_info_flag; // 1 bit + uint8_t dsm_trick_mode_flag; // 1 bit + uint8_t es_rate_flag; // 1 bit + uint8_t escr_flag; // 1 bit + uint8_t pts_dts_flags; // 2 bits + uint8_t header_data_length; // 8 bits +}; diff --git a/include/yangsrt/YangTsPid.h b/include/yangsrt/YangTsPid.h new file mode 100644 index 0000000000000000000000000000000000000000..fc47a3f092ed81bb4ce61e5c3b312a5b70e93dae --- /dev/null +++ b/include/yangsrt/YangTsPid.h @@ -0,0 +1,80 @@ +/* + * YangTsPid.h + * + * Created on: 2020年10月16日 + * Author: yang + */ + +#ifndef SRC_YANGSRT_INCLUDE_YANGTSPID_H_ +#define SRC_YANGSRT_INCLUDE_YANGTSPID_H_ + + +/* mpegts stream type in ts pmt +Value Description +0x00 ITU-T | ISO/IEC Reserved +0x01 ISO/IEC 11172-2 Video (mpeg video v1) +0x02 ITU-T Rec. H.262 | ISO/IEC 13818-2 Video(mpeg video v2)or ISO/IEC 11172-2 constrained parameter video stream +0x03 ISO/IEC 11172-3 Audio (MPEG 1 Audio codec Layer I, Layer II and Layer III audio specifications) +0x04 ISO/IEC 13818-3 Audio (BC Audio Codec) +0x05 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections +0x06 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data +0x07 ISO/IEC 13522 MHEG +0x08 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A DSM-CC +0x09 ITU-T Rec. H.222.1 +0x0A ISO/IEC 13818-6 type A +0x0B ISO/IEC 13818-6 type B +0x0C ISO/IEC 13818-6 type C +0x0D ISO/IEC 13818-6 type D +0x0E ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary +0x0F ISO/IEC 13818-7 Audio with ADTS transport syntax +0x10 ISO/IEC 14496-2 Visual +0x11 ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3/Amd.1 +0x12 ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets +0x13 ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496_sections +0x14 ISO/IEC 13818-6 Synchronized Download Protocol +0x15 Metadata carried in PES packets +0x16 Metadata carried in metadata_sections +0x17 Metadata carried in ISO/IEC 13818-6 Data Carousel +0x18 Metadata carried in ISO/IEC 13818-6 Object Carousel +0x19 Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol +0x1A IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP) +0x1B AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video (h.264) +0x1C ISO/IEC 14496-3 Audio, without using any additional transport syntax, such as DST, ALS and SLS +0x1D ISO/IEC 14496-17 Text +0x1E Auxiliary video stream as defined in ISO/IEC 23002-3 (AVS) +0x1F-0x7E ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved +0x7F IPMP stream 0x80-0xFF User Private +*/ +#define STREAM_TYPE_VIDEO_MPEG1 0x01 +#define STREAM_TYPE_VIDEO_MPEG2 0x02 +#define STREAM_TYPE_AUDIO_MPEG1 0x03 +#define STREAM_TYPE_AUDIO_MPEG2 0x04 +#define STREAM_TYPE_PRIVATE_SECTION 0x05 +#define STREAM_TYPE_PRIVATE_DATA 0x06 +#define STREAM_TYPE_AUDIO_AAC 0x0f +#define STREAM_TYPE_AUDIO_AAC_LATM 0x11 + +#define STREAM_TYPE_VIDEO_MPEG4 0x10 +#define STREAM_TYPE_METADATA 0x15 +#define STREAM_TYPE_VIDEO_H264 0x1b +#define STREAM_TYPE_VIDEO_HEVC 0x24 +#define STREAM_TYPE_VIDEO_CAVS 0x42 +#define STREAM_TYPE_VIDEO_VC1 0xea +#define STREAM_TYPE_VIDEO_DIRAC 0xd1 + +#define STREAM_TYPE_AUDIO_AC3 0x81 +#define STREAM_TYPE_AUDIO_DTS 0x82 +#define STREAM_TYPE_AUDIO_TRUEHD 0x83 +#define STREAM_TYPE_AUDIO_EAC3 0x87 + +#define STREAM_TYPE_AUDIO_OPUS 0x12 +#define PES_AUDIO_ID 0xc0 +#define PES_VIDEO_ID 0xe0 +//#define PES_VIDEO_ID 0xe1 +#define Yang_H264_PID 225 +#define Yang_H265_PID 226 +#define Yang_AAC_PID 192 +#define Yang_OPUS_PID 193 +#define Yang_PRIVATE_PID 200 + +#endif /* SRC_YANGSRT_INCLUDE_YANGTSPID_H_ */ diff --git a/include/yangsrt/YangTsdemux.h b/include/yangsrt/YangTsdemux.h new file mode 100644 index 0000000000000000000000000000000000000000..970546110a2b282d31bc522702ad2b69ea832995 --- /dev/null +++ b/include/yangsrt/YangTsdemux.h @@ -0,0 +1,188 @@ +/* + * YangTsdemux.h + * + * Created on: 2020年8月15日 + * Author: yang + */ + +#ifndef YANGSRT_INCLUDE_YANGTSDEMUX_H_ +#define YANGSRT_INCLUDE_YANGTSDEMUX_H_ +#include +#include +#include +#include +#include +#include "srt_data.hpp" +#include "yangutil/YangErrorCode.h" +#include "YangTsPid.h" + + +class ts_media_data_callback_I { +public: + virtual void on_data_callback(SRT_DATA_MSG_PTR data_ptr, uint32_t media_type, uint64_t dts, uint64_t pts) = 0; +}; + +typedef std::shared_ptr TS_DATA_CALLBACK_PTR; + +class adaptation_field { +public: + adaptation_field(){}; + ~adaptation_field(){}; + +public: + uint8_t _adaptation_field_length; + + uint8_t _discontinuity_indicator:1; + uint8_t _random_access_indicator:1; + uint8_t _elementary_stream_priority_indicator:1; + uint8_t _PCR_flag:1; + uint8_t _OPCR_flag:1; + uint8_t _splicing_point_flag:1; + uint8_t _transport_private_data_flag:1; + uint8_t _adaptation_field_extension_flag:1; + + //if(PCR_flag == '1') + unsigned long _program_clock_reference_base;//33 bits + unsigned short _program_clock_reference_extension;//9bits + //if (OPCR_flag == '1') + unsigned long _original_program_clock_reference_base;//33 bits + unsigned short _original_program_clock_reference_extension;//9bits + //if (splicing_point_flag == '1') + uint8_t _splice_countdown; + //if (transport_private_data_flag == '1') + uint8_t _transport_private_data_length; + uint8_t _private_data_byte[256]; + //if (adaptation_field_extension_flag == '1') + uint8_t _adaptation_field_extension_length; + uint8_t _ltw_flag; + uint8_t _piecewise_rate_flag; + uint8_t _seamless_splice_flag; + uint8_t _reserved0; + //if (ltw_flag == '1') + unsigned short _ltw_valid_flag:1; + unsigned short _ltw_offset:15; + //if (piecewise_rate_flag == '1') + uint32_t _piecewise_rate;//22bits + //if (seamless_splice_flag == '1') + uint8_t _splice_type;//4bits + uint8_t _DTS_next_AU1;//3bits + uint8_t _marker_bit1;//1bit + unsigned short _DTS_next_AU2;//15bit + uint8_t _marker_bit2;//1bit + unsigned short _DTS_next_AU3;//15bit +}; + +class ts_header { +public: + ts_header(){} + ~ts_header(){} + +public: + uint8_t _sync_byte; + + unsigned short _transport_error_indicator:1; + unsigned short _payload_unit_start_indicator:1; + unsigned short _transport_priority:1; + unsigned short _PID:13; + + uint8_t _transport_scrambling_control:2; + uint8_t _adaptation_field_control:2; + uint8_t _continuity_counter:4; + + adaptation_field _adaptation_field_info; +}; + +typedef struct { + unsigned short _program_number; + unsigned short _pid; + unsigned short _network_id; +} PID_INFO; + +class pat_info { +public: + pat_info(){}; + ~pat_info(){}; + +public: + uint8_t _table_id; + + unsigned short _section_syntax_indicator:1; + unsigned short _reserved0:1; + unsigned short _reserved1:2; + unsigned short _section_length:12; + + unsigned short _transport_stream_id; + + uint8_t _reserved3:2; + uint8_t _version_number:5; + uint8_t _current_next_indicator:1; + + uint8_t _section_number; + uint8_t _last_section_number; + std::vector _pid_vec; +}; + +typedef struct { + uint8_t _stream_type; + unsigned short _reserved1:3; + unsigned short _elementary_PID:13; + unsigned short _reserved:4; + unsigned short _ES_info_length; + uint8_t _dscr[4096]; + uint32_t _crc_32; +} STREAM_PID_INFO; + +class pmt_info { +public: + pmt_info(){}; + ~pmt_info(){}; +public: + uint8_t _table_id; + unsigned short _section_syntax_indicator:1; + unsigned short _reserved1:1; + unsigned short _reserved2:2; + unsigned short _section_length:12; + unsigned short _program_number:16; + uint8_t _reserved:2; + uint8_t _version_number:5; + uint8_t _current_next_indicator:5; + uint8_t _section_number; + uint8_t _last_section_number; + unsigned short _reserved3:3; + unsigned short _PCR_PID:13; + unsigned short _reserved4:4; + unsigned short _program_info_length:12; + uint8_t _dscr[4096]; + + std::unordered_map _pid2steamtype; + std::vector _stream_pid_vec; +}; + +class YangTsdemux { +public: + YangTsdemux(); + virtual ~YangTsdemux(); + int32_t decode(SRT_DATA_MSG_PTR data_ptr, ts_media_data_callback_I* callback); + + private: + int32_t decode_unit(uint8_t* data_p,ts_media_data_callback_I* callback); + bool is_pmt(unsigned short pmt_id); + int32_t pes_parse(uint8_t* p, size_t npos, uint8_t** ret_pp, size_t& ret_size, + uint64_t& dts, uint64_t& pts,int32_t *pesLen); + void insert_into_databuf(uint8_t* data_p, size_t data_size, unsigned short pid); + void on_callback(ts_media_data_callback_I* callback, unsigned short pid, uint64_t dts, uint64_t pts); + + private: + std::string _key_path;//only for srt + + pat_info _pat; + pmt_info _pmt; + std::map> _data_buffer_map; + //std::vector _data_buffer_vec; + size_t _data_total; + unsigned short _last_pid; + uint64_t _last_dts; + uint64_t _last_pts; +}; +typedef std::shared_ptr TS_DEMUX_PTR; +#endif /* YANGSRT_INCLUDE_YANGTSDEMUX_H_ */ diff --git a/include/yangsrt/common.h b/include/yangsrt/common.h new file mode 100644 index 0000000000000000000000000000000000000000..ba072373002230da619d37d22b34b120a507f1bf --- /dev/null +++ b/include/yangsrt/common.h @@ -0,0 +1,27 @@ +#ifndef MPEGTS_COMMON_H +#define MPEGTS_COMMON_H + +#include +#include "yangutil/YangErrorCode.h" +class MpegTsAdaptationFieldType +{ +public: + // Reserved for future use by ISO/IEC + static const uint8_t reserved = 0x00; + // No adaptation_field, payload only + static const uint8_t payload_only = 0x01; + // Adaptation_field only, no payload + static const uint8_t adaption_only = 0x02; + // Adaptation_field followed by payload + static const uint8_t payload_adaption_both = 0x03; +}; + +class YangTsBuffer; + +extern void write_pcr(YangTsBuffer *sb, uint64_t pcr); +extern void write_pts(YangTsBuffer *sb, uint32_t fb, uint64_t pts); + +extern uint64_t read_pts(YangTsBuffer *sb); +extern uint64_t read_pcr(YangTsBuffer *sb); + +#endif //MPEGTS_COMMON_H diff --git a/include/yangsrt/crc.h b/include/yangsrt/crc.h new file mode 100644 index 0000000000000000000000000000000000000000..8aed334ec14b778e9852fc82ad61de948b7145a5 --- /dev/null +++ b/include/yangsrt/crc.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +static const uint32_t crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +extern uint32_t crc32(const uint8_t *data, int32_t len); + diff --git a/include/yangsrt/srt_data.hpp b/include/yangsrt/srt_data.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4a6717bf6dbccaae95d245b2e2b2d4d8892006e5 --- /dev/null +++ b/include/yangsrt/srt_data.hpp @@ -0,0 +1,31 @@ + +#ifndef SRT_DATA_H +#define SRT_DATA_H +#include +#include + +#define SRT_MSG_DATA_TYPE 0x01 +#define SRT_MSG_CLOSE_TYPE 0x02 + +class SRT_DATA_MSG { +public: + SRT_DATA_MSG(); + SRT_DATA_MSG(uint32_t len); + SRT_DATA_MSG(uint8_t* data_p, uint32_t len); + ~SRT_DATA_MSG(); + + uint32_t msg_type(); + uint32_t data_len(); + uint8_t* get_data(); + // std::string get_path(); + +private: + uint32_t _msg_type; + uint32_t _len; + uint8_t* _data_p; + // std::string _key_path; +}; + +typedef std::shared_ptr SRT_DATA_MSG_PTR; + +#endif diff --git a/include/yangstream/YangAudioStreamCapture.h b/include/yangstream/YangAudioStreamCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..c1d93c9ae9931f91d26f32d79c9c4b870c18a05b --- /dev/null +++ b/include/yangstream/YangAudioStreamCapture.h @@ -0,0 +1,41 @@ + +#ifndef YANGSTREAM_INCLUDE_YANGAUDIOSTREAMDATA_H_ +#define YANGSTREAM_INCLUDE_YANGAUDIOSTREAMDATA_H_ +#include +#include +class YangAudioStreamCapture{ +public: + YangAudioStreamCapture(); + virtual ~YangAudioStreamCapture(); + void setAudioData(YangFrame* audioFrame); + void setAudioMetaData(uint8_t* p,int32_t plen); + void setFrametype(int32_t frametype); + void init(int32_t transType,int32_t sample,int32_t channel,YangAudioEncDecType audioType); + uint8_t* getAudioData(); + int64_t getRtmpTimestamp(); + int64_t getTsTimestamp(); +public: + int64_t getTimestamp(); + int32_t getAudioLen(); + int32_t getFrametype(); + YangAudioEncDecType getAudioType(); + +private: + uint8_t* m_audioBufs; + uint8_t* m_audioBuffer; + int32_t m_audioHeaderLen; + uint8_t* m_src; + int32_t m_srcLen; + int32_t m_audioLen; + + int64_t atime ; + int64_t m_unitAudioTime; + double atime1; + double perSt ; + + int32_t m_transType; + int32_t m_frametype; + YangAudioEncDecType m_audioType; +}; + +#endif /* YANGSTREAM_INCLUDE_YANGAUDIOSTREAMDATA_H_ */ diff --git a/include/yangstream/YangStreamCapture.h b/include/yangstream/YangStreamCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..52490084b58725030a4d45e687239c4eb50f636e --- /dev/null +++ b/include/yangstream/YangStreamCapture.h @@ -0,0 +1,45 @@ +/* + * YangStreamCapture.h + * + * Created on: 2021年10月2日 + * Author: yang + */ + +#ifndef INCLUDE_YANGSTREAM_YANGSTREAMCAPTURE_H_ +#define INCLUDE_YANGSTREAM_YANGSTREAMCAPTURE_H_ +#include "YangAudioStreamCapture.h" +#include "YangVideoStreamCapture.h" +class YangStreamCapture { +public: + YangStreamCapture(); + virtual ~YangStreamCapture(); +public: + uint8_t* getVideoData(); + int32_t getVideoLen(); + int32_t getVideoFrametype(); + int64_t getVideoTimestamp(); + + + uint8_t* getAudioData(); + int32_t getAudioLen(); + int64_t getAudioTimestamp(); + YangAudioEncDecType getAudioType(); + + + void initVideo(int32_t transtype); + void setVideoData(YangFrame* videoFrame,YangVideoEncDecType videoType=Yang_VED_264); + void setVideoMeta(uint8_t* p,int32_t plen,YangVideoEncDecType videoType=Yang_VED_264); + void setMetaTimestamp(int64_t timestamp); + void setVideoFrametype(int32_t frametype); + + + void setAudioData(YangFrame* audioFrame); + void setAudioMetaData(uint8_t* p,int32_t plen); + void setAudioFrametype(int32_t frametype); + void initAudio(int32_t transType,int32_t sample,int32_t channel,YangAudioEncDecType audioType); +public: + YangAudioStreamCapture m_audio; + YangVideoStreamCapture m_video; +}; + +#endif /* INCLUDE_YANGSTREAM_YANGSTREAMCAPTURE_H_ */ diff --git a/include/yangstream/YangStreamFactory.h b/include/yangstream/YangStreamFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..151620b91d2890bf624935b88578809f17cfe856 --- /dev/null +++ b/include/yangstream/YangStreamFactory.h @@ -0,0 +1,18 @@ + +#ifndef YANGSTREAM_INCLUDE_YANGSTREAMFACTORY_H_ +#define YANGSTREAM_INCLUDE_YANGSTREAMFACTORY_H_ +#include +//#include "YangPlay.h" +//#include "YangPush.h" +class YangStreamFactory { +public: + YangStreamFactory(); + virtual ~YangStreamFactory(); + YangStreamHandle *createStreamHandle(int32_t transType,int32_t puid,YangContext* pcontext); + //YangPlay* createPlayRtmp(int32_t puid); + //YangPlay* createPlaySrt(int32_t puid); + //YangPush* createPushRtmp(int32_t puid); + //YangPush* createPushSrt(int32_t puid); +}; + +#endif /* YANGSTREAM_INCLUDE_YANGSTREAMFACTORY_H_ */ diff --git a/include/yangstream/YangStreamHandle.h b/include/yangstream/YangStreamHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..a775389ae87ec83e504fca9bd2b89b5e1f6cc856 --- /dev/null +++ b/include/yangstream/YangStreamHandle.h @@ -0,0 +1,43 @@ + +#ifndef YANGSTREAM_INCLUDE_YANGSTREAMBASE_H_ +#define YANGSTREAM_INCLUDE_YANGSTREAMBASE_H_ +#include +#include +#include + +#include "YangStreamType.h" + + +class YangStreamHandle { +public: + YangStreamHandle(int32_t puid,YangContext* pcontext); + virtual ~YangStreamHandle(); + void init(YangStreamConfig* pconf); + int32_t connectServer(); + int32_t disConnectServer(); + virtual int32_t reconnect()=0; + virtual int32_t receiveData(int32_t *plen)=0; + virtual int32_t publishVideoData(YangStreamCapture* videoFrame)=0; + virtual int32_t publishAudioData(YangStreamCapture* audioFrame)=0; + virtual int32_t getConnectState()=0; + virtual int32_t isconnected()=0; + //virtual void setLocalMediaParam(YangAudioInfo* localAudioConf,YangVideoInfo* localVideoConf,YangRtcInfo* rtcInfo)=0; + //virtual void setRemoteMediaParamCallback(YangMediaConfigCallback* remoteCb)=0; + //virtual void setSendRequestCallback(YangSendRequestCallback *cb)=0; + + void setReceiveCallback(YangReceiveCallback *pdata); + int32_t m_streamInit; + int32_t m_uid; + int32_t m_audioStream; + int32_t m_videoStream; + +protected: + virtual int32_t connectMediaServer()=0; + virtual int32_t disConnectMediaServer()=0; + YangStreamConfig m_conf; + YangReceiveCallback *m_data; + int32_t m_netState; + YangContext* m_context; +}; + +#endif /* YANGSTREAM_INCLUDE_YANGSTREAMBASE_H_ */ diff --git a/include/yangstream/YangStreamManager.h b/include/yangstream/YangStreamManager.h new file mode 100644 index 0000000000000000000000000000000000000000..f1ba246ca5528bc6679d7b46c2de8ac522d42f7f --- /dev/null +++ b/include/yangstream/YangStreamManager.h @@ -0,0 +1,46 @@ +#ifndef INCLUDE_YANGSTREAM_YANGSTREAMMANAGER1_H_ +#define INCLUDE_YANGSTREAM_YANGSTREAMMANAGER1_H_ +#include +#include +#include +#include + +class YangStreamManager { +public: + YangStreamManager(); + virtual ~YangStreamManager(); + +public: + std::vector* m_playBuffers; + YangSynBuffer* m_playBuffer; + int getIndex(int puid); + YangSynBuffer* getSynBuffer(int puid); +public: + void setMediaConfig(int32_t puid,YangAudioParam* audio,YangVideoParam* video); + void sendRequest(int32_t puid,uint32_t ssrc,YangRequestType req); + void sendRequest(int32_t puid,YangRtcMessageType msg); + void setRtcMessageNotify(int puid,YangRtcMessageNotify* rtcmsg); + void setSendRequestCallback(YangSendRequestCallback* pli); + void setDecoderMediaConfigCallback(YangMediaConfigCallback* dec); + void setRenderMediaConfigCallback(YangMediaConfigCallback* render); + + + int32_t getAudioClock(); + int32_t getVideoClock(); +private: + YangSendRequestCallback* m_sendPli; + YangMediaConfigCallback* m_mediaConfig_dec; + YangMediaConfigCallback* m_mediaConfig_render; + + + int32_t m_videoClock; + int32_t m_audioClock; +private: + YangRtcMessageNotify* m_rtcMsg; + map *m_rtcMsgMap; + + + +}; + +#endif /* INCLUDE_YANGSTREAM_YANGSTREAMMANAGER_H_ */ diff --git a/include/yangstream/YangStreamType.h b/include/yangstream/YangStreamType.h new file mode 100644 index 0000000000000000000000000000000000000000..84263dabf4303e4590a79099e6ca3691703abf68 --- /dev/null +++ b/include/yangstream/YangStreamType.h @@ -0,0 +1,69 @@ +#ifndef YangStreamType_YangStreamType_H_ +#define YangStreamType_YangStreamType_H_ + +#include +#include + +enum YangStreamOptType { + Yang_Stream_Play, Yang_Stream_Publish, Yang_Stream_Both +}; + +enum YangRequestType { + Yang_Req_Sendkeyframe, Yang_Req_Connected, Yang_Req_Disconnected +}; + +enum YangRtcMessageType{ + YangRTC_Decoder_Input +}; + +struct SrsSdpResponseType { + std::string retcode; + std::string serverIp; + std::string sdp; + std::string sessionid; +}; + +struct YangStreamConfig { + std::string serverIp; + std::string localIp; + std::string app; + std::string stream; + std::string url; + int32_t localPort; + int32_t serverPort; + int32_t uid; + YangStreamOptType streamOptType; +}; + +class YangRtcMessageNotify{ +public: + YangRtcMessageNotify(){}; + virtual ~YangRtcMessageNotify(){}; + virtual int notify(int puid,YangRtcMessageType mess)=0; +}; + +class YangMediaConfigCallback { +public: + YangMediaConfigCallback() {}; + virtual ~YangMediaConfigCallback() {}; + virtual void setMediaConfig(int32_t puid, YangAudioParam *audio, + YangVideoParam *video)=0; +}; + +class YangSendRequestCallback { +public: + YangSendRequestCallback() {}; + virtual ~YangSendRequestCallback() {}; + virtual void sendRequest(int32_t puid, uint32_t ssrc, + YangRequestType req)=0; +}; + +class YangReceiveCallback { +public: + YangReceiveCallback() { }; + virtual ~YangReceiveCallback() {}; + virtual void receiveAudio(YangFrame *audioFrame)=0; + virtual void receiveVideo(YangFrame *videoFrame)=0; +}; + +#endif diff --git a/include/yangstream/YangSynBuffer.h b/include/yangstream/YangSynBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..84a974eff54ea0f967cee49b72e4d3efe4dc9ebd --- /dev/null +++ b/include/yangstream/YangSynBuffer.h @@ -0,0 +1,102 @@ +#ifndef YANGPLAYER_INCLUDE_YANGAVSYN_H_ +#define YANGPLAYER_INCLUDE_YANGAVSYN_H_ +#include +#include +#include +#include +#include +#include + + +enum YangSynType{ + YANG_SYNC_AUDIO_MASTER, /* default choice */ + YANG_SYNC_VIDEO_MASTER, + YANG_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */ +}; +#define Yang_Max_Audio_Intervaltime 25 +#define Yang_Max_Video_Intervaltime 35 +#define Yang_Video_Base_Update_Interval 600000//10*60*1000 //10m +#define Yang_Audio_Base_Update_Interval 5000//10*60*1000 //10m +#define Yang_Video_Cache_time 35 +#define Yang_Audio_Cache_time 5 +class YangSynBuffer //:public YangSynBufferI +{ +public: + YangSynBuffer(); + virtual ~YangSynBuffer(); + int32_t m_uid; + int32_t m_width; + int32_t m_height; + void setTranstype(int transtype); + void setAudioClock(int paudioclock); + void setVideoClock(int pvideoclock); + void setVideoCacheTime(int pctime); + + void resetVideoClock(); + void resetAudioClock(); + +public: + uint8_t* getVideoRef(YangFrame* pframe); + uint8_t* getAudioRef(YangFrame* audioFrame); + int32_t getAudioSize(); + int32_t getVideoSize(); + + //void setAudioBuffers(vector *paudioList); + void setInAudioBuffer(YangAudioPlayBuffer *paudioList); + void setInVideoBuffer(YangVideoBuffer *pbuf); + + + void initClock(); + void setClock(); + + int playAudioFrame(int64_t pts); + int playVideoFrame(YangFrame* frame); + double compute_target_delay(double delay); + void video_refresh(int32_t pisaudio, double *remaining_time); + int32_t m_maxAudioMinus; + int32_t m_maxVideoMinus; +private: + bool m_isFirstVideo; + bool m_isFirstAudio; + int32_t m_video_time_state; + void updateBaseTimestamp(int64_t pts); + void updateVideoBaseTimestamp(int64_t pts); + void updateAudioBaseTimestamp(int64_t pts); +private: + + YangSynType m_synType; + int32_t m_paused; + int64_t m_baseClock; + + int64_t m_audio_startClock; + int32_t m_audioClock; + int64_t m_audioBase; + int64_t m_audioTime; + int32_t m_audioMinus; + int32_t m_audioDelay; + int32_t m_lostAudioCount; + int32_t m_audioNegativeCount; + int32_t m_audioTimeoutCount; + + // int32_t m_keyFrameCount; + int64_t m_videoBase; + int32_t m_videoClock; + int64_t m_videoTime; + int32_t m_videoMinus; + int32_t m_videoNegativeCount; + int32_t m_videoTimeoutCount; + int32_t m_videoCacheTime; + int64_t m_video_startClock; + + int64_t m_pre_audioTime; + int64_t m_pre_videoTime; + + int m_transtype; + + +private: + YangVideoBuffer *m_videoBuffer; + YangAudioPlayBuffer* m_audioBuffer; +}; + +#endif /* YANGPLAYER_INCLUDE_YANGAVSYN_H_ */ diff --git a/include/yangstream/YangVideoStreamCapture.h b/include/yangstream/YangVideoStreamCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..0e1b3d716de3ad1a927ae5a0dbc07084cc6b88a9 --- /dev/null +++ b/include/yangstream/YangVideoStreamCapture.h @@ -0,0 +1,59 @@ +#ifndef YANGSTREAM_INCLUDE_YANGVIDEOSTREAMDATA_H_ +#define YANGSTREAM_INCLUDE_YANGVIDEOSTREAMDATA_H_ +#include +#include "stdint.h" +struct YangSpsppsConf{ + uint8_t* sps; + uint8_t* pps; + int32_t spsLen; + int32_t ppsLen; +}; +class YangVideoStreamCapture { +public: + YangVideoStreamCapture(); + virtual ~YangVideoStreamCapture(); + + void init(int32_t transtype); + void setVideoData(YangFrame* videoFrame,YangVideoEncDecType videoType=Yang_VED_264); + void setVideoMeta(uint8_t* p,int32_t plen,YangVideoEncDecType videoType=Yang_VED_264); + void setFrametype(int32_t frametype); + void setMetaTimestamp(int64_t timestamp); + int64_t getRtmpTimestamp(); + int64_t getTsTimestamp(); + int64_t getMetaTimestamp(); + + +public: + //uint8_t* getVideoMeta(); + //int32_t getVideoMetaLen(); + uint8_t* getVideoData(); + YangSpsppsConf* getSpsppsConf(); + + int32_t getFrametype(); + int32_t getVideoLen(); + int64_t getTimestamp(); +protected: + + void initEncType(YangVideoEncDecType videoType,int32_t frametype); + void initSpspps(uint8_t *p); +private: + uint8_t* m_videoBufs; + uint8_t* m_videoBuffer; + //uint8_t* m_videoMeta; + YangSpsppsConf *m_spsppsConf; + int32_t m_frametype; + int32_t m_videoLen; + uint8_t* m_src; + + int32_t m_transType; + int64_t videoTimestamp , baseTimestamp; + int64_t curVideotimestamp ; + int32_t preTimestamp ; + + int64_t m_metaTime; + + + +}; + +#endif /* YANGSTREAM_INCLUDE_YANGVIDEOSTREAMDATA_H_ */ diff --git a/include/yangtrace/YangCameraControl.h b/include/yangtrace/YangCameraControl.h new file mode 100644 index 0000000000000000000000000000000000000000..fbc458425bebf78e192ffa3b17253b35b0126c9d --- /dev/null +++ b/include/yangtrace/YangCameraControl.h @@ -0,0 +1,39 @@ +#ifndef YangCameraControl_H +#define YangCameraControl_H +#include +#include +#include + +using namespace std; + +class YangCameraControl +{ +public: + YangCameraControl(void); + ~YangCameraControl(void); + + void init(const char *teacherip,uint32_t teacherport,const char *studentip,uint32_t studentport); //分别 初始化老师和学生定位摄像机的ip + void Up(std::string type,const char *speed); + void Down(string type,const char *speed); + void Left(string type,const char *speed); + void Right(string type,const char *speed); + void Home(string type); //原点 + void Tele(string type); //近焦 长焦镜头 + void Wide(string type); //远焦 广角镜头 + void tiltStop(string type); + void zoomStop(string type); + + void StopAuto(); + void StartAuto(); + +private: + + void sendmsg(string type,char *visca,int32_t len); + + YangTraceUdp m_studentudp; //学生手动 + YangTraceUdp m_teacherudp; //老师手动 + + int32_t m_isManual; +}; + +#endif diff --git a/include/yangtrace/YangTraceHandle.h b/include/yangtrace/YangTraceHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..5b40b4e3457cf66dd78f908e7abf9226d8238e52 --- /dev/null +++ b/include/yangtrace/YangTraceHandle.h @@ -0,0 +1,63 @@ +#ifndef YangTraceHandle_H +#define YangTraceHandle_H +#include +#include +#include +#include +#include +#define Yang_Trace_WhiteBoardStart "08090802" +#define Yang_Trace_Teacher "08090801" +#define Yang_Trace_Student "08090803" +#define Command_Trace_Start "Auto|END" +#define Command_Trace_Stop "Manual|END" +#define Command_Mouse_Move "MouseMove|END" +#define Command_Mouse_Stop "MouseStop|END" +#define Command_Teacher_Close "08090801" //jin jing +#define Command_Whiteboard_Start "08090802" +#define Command_Student_Close "08090803" //jin jing +#define Command_Whiteboard_Stop "08090804" +#define Command_Student_Down "08090805" //zuo xia +#define Command_Teacher_Move "08090806" +#define Command_Student_Multi_Up "08090807" +#define Command_Teacher_Disappear "08090808" +#define Command_Teacher_Full "08090809" +#define Command_Teacher_Move_Full "08090810" + +enum YangTraceType{ + Yang_Trace_Start, + Yang_Trace_Stop, + Yang_Trace_Teacher_Move, + Yang_Trace_Teacher_Pause, + Yang_Trace_Teacher_Full, + Yang_Trace_Teacher_Disappear, + Yang_Trace_Student_Single_Up, + Yang_Trace_Student_Single_Down, + Yang_Trace_Student_Multi_Up, + Yang_Trace_Student_Multi_Down, + Yang_Trace_Whiteboard_Start, + Yang_Trace_Whiteboard_Stop +}; +class YangTraceHandle +{ +public: + YangTraceHandle(); + virtual ~YangTraceHandle(); + YangCameraControl *m_camCtl; + void init(const char *ip,const int32_t port); + void startTrace(); + void stopTrace(); + void proc(const char* command); + void procCommand(YangTraceType evt); + void manualCyc(string str); +private: + void change(const char *s); + int32_t m_isStartTrace; + YangTraceUdp m_udp; + + int32_t m_whiteBoStat; + int32_t m_studentStat; + + std::string m_ip; +}; + +#endif // AUTOTRACEI_H diff --git a/include/yangtrace/YangTraceIni.h b/include/yangtrace/YangTraceIni.h new file mode 100644 index 0000000000000000000000000000000000000000..bb7e19085cadc268a8c8395e5b047621ac2cfdc9 --- /dev/null +++ b/include/yangtrace/YangTraceIni.h @@ -0,0 +1,19 @@ + +#ifndef INCLUDE_YANGTRACE_YANGTRACEINI_H_ +#define INCLUDE_YANGTRACE_YANGTRACEINI_H_ +#include +struct YangTraceIni{ + std::string traceIp; + std::string luboIp; + std::string studentIp; + std::string teacherIp; + int32_t studentPort; + int32_t teacherPort; + int32_t localPort; + int32_t luboPort; + +}; + + + +#endif /* INCLUDE_YANGTRACE_YANGTRACEINI_H_ */ diff --git a/include/yangtrace/YangTraceServer.h b/include/yangtrace/YangTraceServer.h new file mode 100644 index 0000000000000000000000000000000000000000..13f18bc3a6e3013918cc2929f4c09ec53d1ba954 --- /dev/null +++ b/include/yangtrace/YangTraceServer.h @@ -0,0 +1,30 @@ + +#ifndef TRACE_YangTraceServer_H_ +#define TRACE_YangTraceServer_H_ + +#include +#include "YangCameraControl.h" +#include "YangTraceHandle.h" +#include "yangutil/sys/YangThread.h" +#include "YangTraceIni.h" +class YangTraceServer:public YangThread +{ +public: + YangTraceServer(YangTraceIni* pcontext); + virtual ~YangTraceServer(void); + + void init(); + void startLoop(); + + int32_t m_isStart; + int32_t m_isConvert; + void stop(); + void run(); +private: + YangTraceHandle *m_trace; + YangCameraControl m_camCtl; + YangTraceIni* m_context; + +}; + +#endif diff --git a/include/yangtrace/YangTraceUdp.h b/include/yangtrace/YangTraceUdp.h new file mode 100644 index 0000000000000000000000000000000000000000..1bf7aecc5037e4540747ad3c5b3f19f83cf210ec --- /dev/null +++ b/include/yangtrace/YangTraceUdp.h @@ -0,0 +1,27 @@ +#ifndef TRACE_YangTraceUdp_H_ +#define TRACE_YangTraceUdp_H_ +#ifdef _WIN32 +//#include +#include + +//#define SOCKADDR_IN +#else +#include +#include +#include +#endif +#include +class YangTraceUdp +{ +public: + YangTraceUdp(void); + ~YangTraceUdp(void); + void init(const char *ip,int32_t port); + int32_t sendUdp(const char* data,int32_t len); + void setSockSrv(const char *ip,int32_t port); +private: + int32_t sockSrv; + struct sockaddr_in m_addrClient; +}; + +#endif diff --git a/include/yangutil/YangErrorCode.h b/include/yangutil/YangErrorCode.h new file mode 100644 index 0000000000000000000000000000000000000000..922ca4627472eebe9ba84c60caf3e6a2a544fc71 --- /dev/null +++ b/include/yangutil/YangErrorCode.h @@ -0,0 +1,116 @@ +/* + * YangErrorCode.h + * + * Created on: 2019年3月4日 + * Author: yang + */ + +#ifndef INCLUDE_YANGUTIL_YANGERRORCODE_H_ +#define INCLUDE_YANGUTIL_YANGERRORCODE_H_ + +#define Yang_Ok 0 +#define Yang_LeaveRoom 1 + + +#define ERROR_SYS_NoAudioDevice 110 +#define ERROR_SYS_NoVideoDevice 111 +#define ERROR_SYS_NoAudioCaptureDevice 112 +#define ERROR_SYS_NoAudioPlayDevice 113 +#define ERROR_SYS_AudioCapture 114 +#define ERROR_SYS_AudioRender 115 + +#define ERROR_SYS_Linux_VideoDeveceOpenFailure 120 +#define ERROR_SYS_Linux_NoVideoDriver 122 +#define ERROR_SYS_Linux_NoVideoCatpureInterface 124 + +#define ERROR_SYS_Win_VideoDeveceOpenFailure 150 +#define ERROR_SYS_Win_NoVideoDriver 151 +#define ERROR_SYS_Win_NoVideoCatpureInterface 152 + +#define ERROR_SYS_Linux_ScreenDeviceOpenFailure 163 +#define ERROR_SYS_Linux_ScreenCaptureFailure 164 +#define ERROR_SYS_Win_ScreenCaptureFailure 165 + + +#define ERROR_SOCKET 201 +#define ERROR_SOCKET_Timeout 202 +#define ERROR_SOCKET_Close 203 +#define ERROR_SOCKET_Close_Wr 204 +#define ERROR_SOCKET_Negotiation 205 +#define ERROR_CONNECT_Handshaked 206 +#define ERROR_CONNECT_Fail 207 +#define ERROR_REQUEST_Close 208 +#define ERROR_SERVER_Reject 209 +#define ERROR_SERVER_Logout 210 +#define ERROR_SERVER_ConnectFailure 211 + +#define ERROR_SSL 300 + + + + +#define ERROR_RTMP_ConnectFailure 2100 +#define ERROR_RTMP_PubFailure 2101 +#define ERROR_RTMP_UnPubFailure 2102 +#define ERROR_RTMP_PlayFailure 2103 +#define ERROR_RTMP_UnPlayFailure 2104 +#define ERROR_RTMP_SendCommandFailure 2105 +#define ERROR_RTMP_UserInfosResult 2106 + +#define Yang_SRTS_SocketBase 3000 +#define ERROR_SRT_NotInit 3001 +#define Yang_SRTS_CONNECTING 3004 +#define Yang_SRTS_BROKEN 3006 +#define Yang_SRTS_CLOSING 3007 +#define Yang_SRTS_CLOSED 3008 +#define Yang_SRTS_NONEXIST 3009 +#define Yang_SRTS_NONSRTSERVER 3010 +#define ERROR_SRT_PushFailure 3100 +#define ERROR_SRT_PullFailure 3101 +#define ERROR_SRT_StreamIdSetFailure 3102 +#define ERROR_SRT_EpollCreateFailure 3103 +#define ERROR_SRT_EpollSetFailure 3104 +#define ERROR_SRT_EpollSelectFailure 3105 +#define ERROR_SRT_SocketConnectCreate 3201 +#define ERROR_SRT_SocketConnect 3202 +#define ERROR_SRT_WriteSocket 3210 +#define ERROR_SRT_ReadSocket 3211 + +#define ERROR_RTC_PORT 5000 +#define ERROR_RTP_PACKET_CREATE 5001 +#define ERROR_OpenSslCreateSSL 5002 +#define ERROR_OpenSslBIOReset 5003 +#define ERROR_OpenSslBIOWrite 5004 +#define ERROR_OpenSslBIONew 5005 +#define ERROR_RTC_RTP 5006 +#define ERROR_RTC_RTCP 5007 +#define ERROR_RTC_STUN 5008 +#define ERROR_RTC_DTLS 5009 +#define ERROR_RTC_UDP 5010 +#define ERROR_RTC_RTP_MUXER 5011 +#define ERROR_RTC_SDP_DECODE 5012 +#define ERROR_RTC_SRTP_INIT 5013 +#define ERROR_RTC_SRTP_PROTECT 5014 +#define ERROR_RTC_SRTP_UNPROTECT 5015 +#define ERROR_RTC_RTCP_CHECK 5016 +#define ERROR_RTC_SOURCE_CHECK 5017 +#define ERROR_RTC_SDP_EXCHANGE 5018 +#define ERROR_RTC_API_BODY 5019 +#define ERROR_RTC_SOURCE_BUSY 5020 +#define ERROR_RTC_DISABLED 5021 +#define ERROR_RTC_NO_SESSION 5022 +#define ERROR_RTC_INVALID_PARAMS 5023 +#define ERROR_RTC_DUMMY_BRIDGER 5024 +#define ERROR_RTC_STREM_STARTED 5025 +#define ERROR_RTC_TRACK_CODEC 5026 +#define ERROR_RTC_NO_PLAYER 5027 +#define ERROR_RTC_NO_PUBLISHER 5028 +#define ERROR_RTC_DUPLICATED_SSRC 5029 +#define ERROR_RTC_NO_TRACK 5030 +#define ERROR_RTC_RTCP_EMPTY_RR 5031 + +//char* yang_getErrorStr(int32_t errcode); + + + +#endif /* INCLUDE_YANGUTIL_YANGERRORCODE_H_ */ diff --git a/include/yangutil/YangSynBufferI.h b/include/yangutil/YangSynBufferI.h new file mode 100644 index 0000000000000000000000000000000000000000..7e2058fd32502cfeca18c1bb24231cd191d15036 --- /dev/null +++ b/include/yangutil/YangSynBufferI.h @@ -0,0 +1,15 @@ + +#ifndef INCLUDE_YANGUTIL_YANGAVSYNI_H_ +#define INCLUDE_YANGUTIL_YANGAVSYNI_H_ + +class YangSynBufferI{ +public: + YangSynBufferI(){}; + virtual ~YangSynBufferI(){}; + virtual int32_t playAudioFrame(int64_t pts)=0; + virtual int32_t playVideoFrame(int64_t pts)=0; +}; + + + +#endif /* INCLUDE_YANGUTIL_YANGAVSYNI_H_ */ diff --git a/include/yangutil/buffer/YangAudioBuffer.h b/include/yangutil/buffer/YangAudioBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..fac3ea345d123964164a59bd716aea153b30c140 --- /dev/null +++ b/include/yangutil/buffer/YangAudioBuffer.h @@ -0,0 +1,21 @@ +#ifndef ___YangAudioBuffer__ +#define ___YangAudioBuffer__ +#include + +#include +class YangAudioBuffer:public YangMediaBuffer +{ +public: + YangAudioBuffer(int32_t pcacheNum); + ~YangAudioBuffer(void); + void putAudio(YangFrame* pframe); + int32_t getAudio(YangFrame* pframe); + uint8_t *getAudioRef(YangFrame* pframe); + void reset(); + +private: + + int32_t m_bufLen; + +}; +#endif diff --git a/include/yangutil/buffer/YangAudioEncoderBuffer.h b/include/yangutil/buffer/YangAudioEncoderBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..a309605d9008de26a2bf15164f1f39a036fef7c4 --- /dev/null +++ b/include/yangutil/buffer/YangAudioEncoderBuffer.h @@ -0,0 +1,22 @@ +#ifndef YangAudioEncoderBuffer_H +#define YangAudioEncoderBuffer_H + +#include + +class YangAudioEncoderBuffer: public YangMediaBuffer { +public: + YangAudioEncoderBuffer(int32_t paudioCacheNum); + ~YangAudioEncoderBuffer(void); + void reset(); + + void putAudio(YangFrame* audioFrame); + void getAudio(YangFrame* audioFrame); + uint8_t* getAudioRef(YangFrame* pframe); + void putPlayAudio(YangFrame* pframe); + void getPlayAudio(YangFrame* audioFrame); + +private: + +}; + +#endif diff --git a/include/yangutil/buffer/YangAudioPlayBuffer.h b/include/yangutil/buffer/YangAudioPlayBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..17ae523537858061629c4a57791c087a81bf5b11 --- /dev/null +++ b/include/yangutil/buffer/YangAudioPlayBuffer.h @@ -0,0 +1,24 @@ +#ifndef ___YangAudioPlayBuffer1__ +#define ___YangAudioPlayBuffer1__ + +#include + + +class YangAudioPlayBuffer:public YangMediaBuffer{ + +public: + YangAudioPlayBuffer(); + ~YangAudioPlayBuffer(void); + + void putAudio(YangFrame* pframe); + void getAudio(YangFrame* pframe); + uint8_t *getAudios(YangFrame* pframe); + int32_t getFrameTimestamp(int64_t *timestamp); + int64_t getNextTimestamp(); + //int32_t playFrame(); + void reset(); +private: + int32_t m_bufLen; + +}; +#endif diff --git a/include/yangutil/buffer/YangBuffer.h b/include/yangutil/buffer/YangBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..57ad2f1ccc5b076a2606416fdfa7791ed7d915a3 --- /dev/null +++ b/include/yangutil/buffer/YangBuffer.h @@ -0,0 +1,110 @@ + +#ifndef YangBuffer_YANGRTCUTIL_H_ +#define YangBuffer_YANGRTCUTIL_H_ +#include +#include +#include +#include +using namespace std; +class YangBuffer +{ +private: + // current position at bytes. + char* p; + // the bytes data for buffer to read or write. + char* bytes; + // the total number of bytes. + int32_t nb_bytes; +public: + // Create buffer with data b and size nn. + // @remark User must free the data b. + YangBuffer(); + YangBuffer(char* b, int32_t nn); + ~YangBuffer(); +public: + // Copy the object, keep position of buffer. + YangBuffer* copy(); + void init(char* b, int32_t nn); + // Get the data and head of buffer. + // current-bytes = head() = data() + pos() + char* data(); + char* head(); + // Get the total size of buffer. + // left-bytes = size() - pos() + int32_t size(); + void set_size(int32_t v); + // Get the current buffer position. + int32_t pos(); + // Left bytes in buffer, total size() minus the current pos(). + int32_t left(); + // Whether buffer is empty. + bool empty(); + // Whether buffer is able to supply required size of bytes. + // @remark User should check buffer by require then do read/write. + // @remark Assert the required_size is not negative. + bool require(int32_t required_size); +public: + // Skip some size. + // @param size can be any value. positive to forward; negative to backward. + // @remark to skip(pos()) to reset buffer. + // @remark assert initialized, the data() not NULL. + void skip(int32_t size); +public: + // Read 1bytes char from buffer. + char read_1bytes(); + // Read 2bytes int32_t from buffer. + int16_t read_2bytes(); + int16_t read_le2bytes(); + // Read 3bytes int32_t from buffer. + int32_t read_3bytes(); + int32_t read_le3bytes(); + // Read 4bytes int32_t from buffer. + int32_t read_4bytes(); + int32_t read_le4bytes(); + // Read 8bytes int32_t from buffer. + int64_t read_8bytes(); + int64_t read_le8bytes(); + // Read string from buffer, length specifies by param len. + std::string read_string(int32_t len); + // Read bytes from buffer, length specifies by param len. + void read_bytes(char* data, int32_t size); +public: + // Write 1bytes char to buffer. + void write_1bytes(char value); + // Write 2bytes int32_t to buffer. + void write_2bytes(int16_t value); + void write_le2bytes(int16_t value); + // Write 4bytes int32_t to buffer. + void write_4bytes(int32_t value); + void write_le4bytes(int32_t value); + // Write 3bytes int32_t to buffer. + void write_3bytes(int32_t value); + void write_le3bytes(int32_t value); + // Write 8bytes int32_t to buffer. + void write_8bytes(int64_t value); + void write_le8bytes(int64_t value); + // Write string to buffer + void write_string(std::string value); + // Write bytes to buffer + void write_bytes(char* data, int32_t size); +}; + +/** + * the bit buffer, base on SrsBuffer, + * for exmaple, the h.264 avc buffer is bit buffer. + */ +class YangBitBuffer +{ +private: + char cb; + uint8_t cb_left; + YangBuffer* stream; +public: + YangBitBuffer(YangBuffer* b); + ~YangBitBuffer(); +public: + bool empty(); + char read_bit(); +}; + +#endif diff --git a/include/yangutil/buffer/YangMediaBuffer.h b/include/yangutil/buffer/YangMediaBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..a4c807567b31229961031ae3503a23b620df76e8 --- /dev/null +++ b/include/yangutil/buffer/YangMediaBuffer.h @@ -0,0 +1,50 @@ +/* + * YangBaseAllocator.h + * + * Created on: 2020年8月8日 + * Author: yang + */ + +#ifndef YANGUTIL_BUFFER_YANGBUFFER_H_ +#define YANGUTIL_BUFFER_YANGBUFFER_H_ +#include +#include +#include +#define yang_reindex(p) if(p!=NULL) p->resetIndex(); +#define Yang_MediaBuffer_Maxsize 2000 +class YangMediaBuffer { +public: + YangMediaBuffer(); + virtual ~YangMediaBuffer(); +public: + int32_t m_mediaType; + int32_t m_uid; + int32_t m_putSize; + int32_t m_getSize; + void resetIndex(); + int32_t size(); +protected: + int32_t m_putIndex; + int32_t m_getIndex; + int32_t m_cache_num; + + int32_t m_nextIndex; + int32_t m_ret; + void setSize(int32_t padd); + + YangFrame** m_frames; + YangBufferManager* m_bufferManager; +protected: + void initFrames(int pnum,int unitsize); + + void putFrame(YangFrame* pframe); + void getFrame(YangFrame* pframe); + YangFrame* getCurFrameRef(); + int64_t getNextFrameTimestamp(); + uint8_t* getFrameRef(YangFrame* pframe); +private: + void checkSize(); + //pthread_mutex_t m_lock; +}; + +#endif /* YANGUTIL_BUFFER_YANGBUFFER_H_ */ diff --git a/include/yangutil/buffer/YangVideoBuffer.h b/include/yangutil/buffer/YangVideoBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..5762fb1ad5a2006a83e08c5fd57fd9ba587c08fc --- /dev/null +++ b/include/yangutil/buffer/YangVideoBuffer.h @@ -0,0 +1,44 @@ +#ifndef __YangVideoBuffer__ +#define __YangVideoBuffer__ +#include +#include + + +#define yang_get_videoBuffer(x) new YangVideoBuffer(x->width,x->height,x->videoCaptureFormat==YangYuy2?16:12,x->bitDepth==8?1:2) +class YangVideoBuffer:public YangMediaBuffer +{ +public: + YangVideoBuffer(int32_t pBitDepthLen); + + YangVideoBuffer(int32_t pwid,int32_t phei,YangYuvType ptype,int32_t pBitDepthLen); + ~YangVideoBuffer(void); + void initTemp(); + void init(int32_t pwid,int32_t phei,YangYuvType ptype); + + + void reset(); + //YangAvsynI* m_syn; + + int32_t isPreview=0; + int32_t m_width; + int32_t m_height; + int32_t m_length; + int32_t m_frames; + int32_t m_bitDepthLen; + void putVideo(YangFrame* pframe); + + void getVideo(YangFrame* pframe); + uint8_t * getVideoRef(YangFrame* pframe); + int64_t getTimestamp(int64_t *timestamp); + int64_t getNextTimestamp(); + YangFrame* getCurVideoFrame(); + //int32_t playFrame(); +protected: + + +private: + int32_t m_headerLen; + + +}; +#endif diff --git a/include/yangutil/buffer/YangVideoDecoderBuffer.h b/include/yangutil/buffer/YangVideoDecoderBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..4baceca1976431e25e00419b904955a56c2b3d55 --- /dev/null +++ b/include/yangutil/buffer/YangVideoDecoderBuffer.h @@ -0,0 +1,18 @@ +#ifndef __YangVideoDecoderBuffer__ +#define __YangVideoDecoderBuffer__ +#include +#include +#include +class YangVideoDecoderBuffer:public YangMediaBuffer +{ +public: + YangVideoDecoderBuffer(int num=8); + ~YangVideoDecoderBuffer(void); + + void putEVideo(YangFrame* pframe); + void getEVideo(YangFrame* pframe); +private: + + +}; +#endif diff --git a/include/yangutil/buffer/YangVideoEncoderBuffer.h b/include/yangutil/buffer/YangVideoEncoderBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..27eb0056c5af8ce9b9775e1b71ae79f071393cb4 --- /dev/null +++ b/include/yangutil/buffer/YangVideoEncoderBuffer.h @@ -0,0 +1,19 @@ +#ifndef __YangVideoEncoderBuffer__ +#define __YangVideoEncoderBuffer__ +#include +#include + +class YangVideoEncoderBuffer:public YangMediaBuffer +{ +public: + YangVideoEncoderBuffer(int32_t pcachenum); + ~YangVideoEncoderBuffer(void); + + + void getEVideo(YangFrame* pframe); + uint8_t * getEVideoRef(YangFrame* frame); + void putEVideo(YangFrame* pframe); +private: + +}; +#endif diff --git a/include/yangutil/sys/YangAmf.h b/include/yangutil/sys/YangAmf.h new file mode 100644 index 0000000000000000000000000000000000000000..ff1377c317b88d54fbd65778904aa11ed102d5e2 --- /dev/null +++ b/include/yangutil/sys/YangAmf.h @@ -0,0 +1,140 @@ +#ifndef __YangAMF_H__ +#define __YangAMF_H__ +#include +#include +#include +#include +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + + + + enum AMFDataType + { AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT, + AMF_MOVIECLIP, /* reserved, not used */ + AMF_NULL, AMF_UNDEFINED, AMF_REFERENCE, AMF_ECMA_ARRAY, AMF_OBJECT_END,//9 + AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED, + AMF_RECORDSET, /* reserved, not used */ + AMF_XML_DOC, AMF_TYPED_OBJECT, + AMF_AVMPLUS, /* switch to AMF3 */ + AMF_INVALID = 0xff + } ; + + enum AMF3DataType + { AMF3_UNDEFINED = 0, AMF3_NULL, AMF3_FALSE, AMF3_TRUE, + AMF3_INTEGER, AMF3_DOUBLE, AMF3_STRING, AMF3_XML_DOC, AMF3_DATE, + AMF3_ARRAY, AMF3_OBJECT, AMF3_XML, AMF3_BYTE_ARRAY + } ; + + struct AVal + { + char *av_val; + int32_t av_len; + }; +#define AVC(str) {(char*)str,sizeof(str)-1} +#define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len)) + + struct AMFObjectProperty; + + typedef struct AMFObject + { + int32_t o_num; + struct AMFObjectProperty *o_props; + } AMFObject; + + typedef struct AMFObjectProperty + { + AVal p_name; + AMFDataType p_type; + union + { + double p_number; + AVal p_aval; + AMFObject p_object; + } p_vu; + int16_t p_UTCoffset; + } AMFObjectProperty; + + + + + + char *AMF_EncodeString(char *output, char *outend, const AVal * str); + char *AMF_EncodeNumber(char *output, char *outend, double dVal); + char *AMF_EncodeInt16(char *output, char *outend, short nVal); + char *AMF_EncodeInt24(char *output, char *outend, int32_t nVal); + char *AMF_EncodeInt32(char *output, char *outend, int32_t nVal); + char *AMF_EncodeBoolean(char *output, char *outend, int32_t bVal); + + /* Shortcuts for AMFProp_Encode */ + char *AMF_EncodeNamedString(char *output, char *outend, const AVal * name, const AVal * value); + char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal * name, double dVal); + char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal * name, int32_t bVal); + + unsigned short AMF_DecodeInt16(const char *data); + uint32_t AMF_DecodeInt24(const char *data); + uint32_t AMF_DecodeInt32(const char *data); + void AMF_DecodeString(const char *data, AVal * str); + void AMF_DecodeLongString(const char *data, AVal * str); + int32_t AMF_DecodeBoolean(const char *data); + double AMF_DecodeNumber(const char *data); + + char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd); + char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd); + char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd); + + int32_t AMF_Decode(AMFObject * obj, const char *pBuffer, int32_t nSize, + int32_t bDecodeName); + int32_t AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int32_t nSize, + int32_t nArrayLen, int32_t bDecodeName); + int32_t AMF3_Decode(AMFObject * obj, const char *pBuffer, int32_t nSize, + int32_t bDecodeName); + void AMF_Dump(AMFObject * obj); + void AMF_Dump1(AMFObject * obj); + void AMF_Reset(AMFObject * obj); + + void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop); + int32_t AMF_CountProp(AMFObject * obj); + AMFObjectProperty *AMF_GetProp(AMFObject * obj, const AVal * name, + int32_t nIndex); + + AMFDataType AMFProp_GetType(AMFObjectProperty * prop); + void AMFProp_SetNumber(AMFObjectProperty * prop, double dval); + void AMFProp_SetBoolean(AMFObjectProperty * prop, int32_t bflag); + void AMFProp_SetString(AMFObjectProperty * prop, AVal * str); + void AMFProp_SetObject(AMFObjectProperty * prop, AMFObject * obj); + + void AMFProp_GetName(AMFObjectProperty * prop, AVal * name); + void AMFProp_SetName(AMFObjectProperty * prop, AVal * name); + double AMFProp_GetNumber(AMFObjectProperty * prop); + int32_t AMFProp_GetBoolean(AMFObjectProperty * prop); + void AMFProp_GetString(AMFObjectProperty * prop, AVal * str); + void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj); + + int32_t AMFProp_IsValid(AMFObjectProperty * prop); + + char *AMFProp_Encode(AMFObjectProperty * prop, char *pBuffer, char *pBufEnd); + int32_t AMF3Prop_Decode(AMFObjectProperty * prop, const char *pBuffer, + int32_t nSize, int32_t bDecodeName); + int32_t AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer, + int32_t nSize, int32_t bDecodeName); + + void AMFProp_Dump(AMFObjectProperty * prop); + void AMFProp_Dump1(AMFObjectProperty * prop); + void AMFProp_Reset(AMFObjectProperty * prop); + + typedef struct AMF3ClassDef + { + AVal cd_name; + char cd_externalizable; + char cd_dynamic; + int32_t cd_num; + AVal *cd_props; + } AMF3ClassDef; + + void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop); + AVal *AMF3CD_GetProp(AMF3ClassDef * cd, int32_t idx); + +#endif /* __AMF_H__ */ diff --git a/include/yangutil/sys/YangBits.h b/include/yangutil/sys/YangBits.h new file mode 100644 index 0000000000000000000000000000000000000000..2d2701031039715cd19171da80e88bffd4be2cc3 --- /dev/null +++ b/include/yangutil/sys/YangBits.h @@ -0,0 +1,108 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGBITS_H_ +#define INCLUDE_YANGUTIL_SYS_YANGBITS_H_ +#include +#ifdef _WIN32 +static __inline uint16_t +uint16_identity (uint16_t __x) +{ + return __x; +} +#define __bswap_constant_16(x) \ + ((__uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) + +static __inline uint32_t +__uint32_identity (uint32_t __x) +{ + return __x; +} + +static __inline uint64_t +__uint64_identity (uint64_t __x) +{ + return __x; +} +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + + static __inline uint64_t +__bswap_64 (uint64_t __bsx) +{ +//#if __GNUC_PREREQ (4, 3) + return __builtin_bswap64 (__bsx); +//#else + //return __bswap_constant_64 (__bsx); +//#endif +} +/* Swap bytes in 32-bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \ + | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +#define __bswap_constant_16(x) \ + ((__uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) +static __inline uint16_t +__bswap_16 (uint16_t __bsx) +{ +//#if __GNUC_PREREQ (4, 8) + return __builtin_bswap16 (__bsx); +//#else + // return __bswap_constant_16 (__bsx); +//#endif +} +#define __bswap_32(x) ((unsigned int)__builtin_bswap32(x)) +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \ + | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +//static inline uint32_t __bswap_32(uint32_t x) +//{ + // x = ((x << 8) &0xFF00FF00) | ((x >> 8) &0x00FF00FF); + // return (x >> 16) | (x << 16); +//} +#endif +// Convert srs_utime_t as ms. +#define srsu2ms(us) ((us) / YANG_UTIME_MILLISECONDS) +#define srsu2msi(us) int((us) / YANG_UTIME_MILLISECONDS) +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define htobe16(x) __bswap_16 (x) +# define htole16(x) __uint16_identity (x) +# define be16toh(x) __bswap_16 (x) +# define le16toh(x) __uint16_identity (x) + +# define htobe32(x) __bswap_32 (x) +# define htole32(x) __uint32_identity (x) +# define be32toh(x) __bswap_32 (x) +# define le32toh(x) __uint32_identity (x) + +# define htobe64(x) __bswap_64 (x) +# define htole64(x) __uint64_identity (x) +# define be64toh(x) __bswap_64 (x) +# define le64toh(x) __uint64_identity (x) + +# else +# define htobe16(x) __uint16_identity (x) +# define htole16(x) __bswap_16 (x) +# define be16toh(x) __uint16_identity (x) +# define le16toh(x) __bswap_16 (x) + +# define htobe32(x) __uint32_identity (x) +# define htole32(x) __bswap_32 (x) +# define be32toh(x) __uint32_identity (x) +# define le32toh(x) __bswap_32 (x) + +# define htobe64(x) __uint64_identity (x) +# define htole64(x) __bswap_64 (x) +# define be64toh(x) __uint64_identity (x) +# define le64toh(x) __bswap_64 (x) +# endif + + + +#endif /* INCLUDE_YANGUTIL_SYS_YANGBITS_H_ */ diff --git a/include/yangutil/sys/YangCertificate.h b/include/yangutil/sys/YangCertificate.h new file mode 100644 index 0000000000000000000000000000000000000000..91a5c896736b792ca797a8173e50a0cd88ee1e7f --- /dev/null +++ b/include/yangutil/sys/YangCertificate.h @@ -0,0 +1,17 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGCERTIFICATE_H_ +#define INCLUDE_YANGUTIL_SYS_YANGCERTIFICATE_H_ +#include +#include +class YangCertificate{ +public: + YangCertificate(){}; + virtual ~YangCertificate(){}; + virtual int32_t init()=0; + virtual std::string get_fingerprint()=0; + // whether is ecdsa + virtual bool is_ecdsa()=0; +}; + + + +#endif /* INCLUDE_YANGUTIL_SYS_YANGCERTIFICATE_H_ */ diff --git a/include/yangutil/sys/YangEndian.h b/include/yangutil/sys/YangEndian.h new file mode 100644 index 0000000000000000000000000000000000000000..b1c1d1fbd449f98d27e59903025f6681b7b3bd8e --- /dev/null +++ b/include/yangutil/sys/YangEndian.h @@ -0,0 +1,23 @@ +/* + * YangCommon.h + * + * Created on: 2019年7月20日 + * Author: yang + */ + +#ifndef YANGUTIL_VIDEO_YANGEndian_H_ +#define YANGUTIL_VIDEO_YANGEndian_H_ +#include + + +char* yang_put_amf_string(char *c, const char *str); +char* yang_put_amf_double(char *c, double d); +char* yang_put_byte(char *output, uint8_t nVal); +char* yang_put_be16(char *output, unsigned short nVal); +char* yang_put_be24(char *output, uint32_t nVal); +char* yang_put_be32(char *output, uint32_t nVal); +char* yang_put_be64(char *output, unsigned long nVal); + +uint32_t yang_get_be32(uint8_t *output); +uint16_t yang_get_be16(uint8_t *output); +#endif /* YANGUTIL_VIDEO_YANGCOMMON_H_ */ diff --git a/include/yangutil/sys/YangFile.h b/include/yangutil/sys/YangFile.h new file mode 100644 index 0000000000000000000000000000000000000000..f0ca8bb97536b0ffc924cb83ad374235920df509 --- /dev/null +++ b/include/yangutil/sys/YangFile.h @@ -0,0 +1,19 @@ + +#ifndef INCLUDE_YANGUTIL_SYS_YANGFILE_H_ +#define INCLUDE_YANGUTIL_SYS_YANGFILE_H_ +#include +int32_t yang_getCurpath(char* path); +int32_t yang_getLibpath(char* path); +int32_t yang_getCaFile(char* pem,char* key); + +class YangFile { +public: + YangFile(); + virtual ~YangFile(); + int32_t hasPath(const char* path); + int32_t createPath(const char* path); + int32_t getCurpath(char* path); + +}; + +#endif /* INCLUDE_YANGUTIL_SYS_YANGFILE_H_ */ diff --git a/include/yangutil/sys/YangHttp.h b/include/yangutil/sys/YangHttp.h new file mode 100644 index 0000000000000000000000000000000000000000..c009365919bf013ddc629bc429e137a85f029f52 --- /dev/null +++ b/include/yangutil/sys/YangHttp.h @@ -0,0 +1,29 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGHTTP_H_ +#define INCLUDE_YANGUTIL_SYS_YANGHTTP_H_ +#include +#include +#include + +class YangHttp { +public: + YangHttp(); + virtual ~YangHttp(); + static size_t WriteFunction(void* input, size_t uSize, size_t uCount, void* avg); + int32_t queryPost(char* purl, std::string psdp,std::string &outsdp); + int32_t querySslPost(char* purl, std::string psdp,std::string &outsdp); + + private: + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + CURLcode (*yang_curl_global_init)(long flags); + CURL* (*yang_curl_easy_init)(void); + CURLcode (*yang_curl_easy_setopt)(CURL *curl, CURLoption option, ...); + struct curl_slist* (*yang_curl_slist_append)(struct curl_slist *, + const char *); + CURLcode (*yang_curl_easy_perform)(CURL *curl); + void (*yang_curl_easy_cleanup)(CURL *curl); + void (*yang_curl_global_cleanup)(void); +}; + +#endif /* INCLUDE_YANGUTIL_SYS_YANGHTTP_H_ */ diff --git a/include/yangutil/sys/YangIni.h b/include/yangutil/sys/YangIni.h new file mode 100644 index 0000000000000000000000000000000000000000..0651c0e12b4ccdd8b35aef2082dac6a32738ed79 --- /dev/null +++ b/include/yangutil/sys/YangIni.h @@ -0,0 +1,28 @@ +#ifndef __YYangIni__ +#define __YYangIni__ +#include + +class YangIni { +public: + YangIni(); + ~YangIni(); +public: + void init(const char *p_filename); + int32_t IniReadValue(const char *section, const char *key, char *val); + int32_t readStringValue(const char *section, const char *key, char *val, + const char *p_defaultStr); + int32_t readIntValue(const char *section, const char *key, int32_t p_defaultInt); + void initVideo(YangVideoInfo *video); + void initAudio(YangAudioInfo *audio); + void initSys(YangSysInfo *sys); + void initEnc(YangVideoEncInfo *enc); + void initRtc(YangRtcInfo *rtc); + +protected: + +private: + char *m_file; + int32_t readStringValue1(const char *section, const char *key, char *val); + +}; +#endif diff --git a/include/yangutil/sys/YangJson.h b/include/yangutil/sys/YangJson.h new file mode 100644 index 0000000000000000000000000000000000000000..f21bcc63119e0379d393296c61d3c324b71c6cf4 --- /dev/null +++ b/include/yangutil/sys/YangJson.h @@ -0,0 +1,15 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGJSON_H_ +#define INCLUDE_YANGUTIL_SYS_YANGJSON_H_ +#include +#include +#include +using namespace std; +struct YangJsonData{ + string key; + string value; +}; + +void yang_gen_jsonstr(vector &jsons,string &outstr); + + +#endif /* INCLUDE_YANGUTIL_SYS_YANGJSON_H_ */ diff --git a/include/yangutil/sys/YangLoadLib.h b/include/yangutil/sys/YangLoadLib.h new file mode 100644 index 0000000000000000000000000000000000000000..28197861048b7dccf8f7d612b35a1675ad03a6cf --- /dev/null +++ b/include/yangutil/sys/YangLoadLib.h @@ -0,0 +1,33 @@ +/* + * YangLoadSo.h + * + * Created on: 2020-09-20 + * Author: yang + */ + +#ifndef YANGUTIL_SYS_YANGLOADLIB_H_ +#define YANGUTIL_SYS_YANGLOADLIB_H_ +#include +#ifdef _WIN32 +#include +#endif +class YangLoadLib{ +public: + YangLoadLib(); + ~YangLoadLib(); + +void *loadObject(const char *sofile); +void *loadSysObject(const char *sofile); +void *loadFunction(const char *name); +void unloadObject(); + +#ifdef _WIN32 +HMODULE m_handle; +char *dlerror(); +#else +void *m_handle; +#endif + +}; + +#endif /* YANGUTIL_SYS_YANGLOADLIB_H_ */ diff --git a/include/yangutil/sys/YangLog.h b/include/yangutil/sys/YangLog.h new file mode 100644 index 0000000000000000000000000000000000000000..1d5b4d9a64666a4cef7893b44ae93c293efc9b11 --- /dev/null +++ b/include/yangutil/sys/YangLog.h @@ -0,0 +1,54 @@ +#ifndef __YangLOG_H__ +#define __YangLOG_H__ +#include +#include +#include +#include + + +#include "yangutil/YangErrorCode.h" +#include +#define YANG_LOG_FATAL 0 +#define YANG_LOG_ERROR 1 +#define YANG_LOG_WARNING 2 +#define YANG_LOG_INFO 3 +#define YANG_LOG_DEBUG 4 +#define YANG_LOG_TRACE 5 + +class YangCLog { +public: + YangCLog(); + virtual ~YangCLog(); + //int32_t neednl; + +public: + static void log(int32_t level, const char *format, ...); + static void logf(int32_t level, const char *format, ...); + static void setLogLevel(int32_t plevel); + static void setLogFile(int32_t isSetLogFile); + static void closeLogFile(); + + static int32_t m_hasLogFile; +private: + static int32_t logLevel; + + +}; + +int32_t yang_error_wrap(int32_t errcode, const char *fmt, ...); +#define yang_fatal( fmt, ...) YangCLog::log(0,fmt, ##__VA_ARGS__) +#define yang_error( fmt, ...) YangCLog::log(1,fmt, ##__VA_ARGS__) +#define yang_warn( fmt, ...) YangCLog::log(2,fmt, ##__VA_ARGS__) +#define yang_info( fmt, ...) YangCLog::log(3,fmt, ##__VA_ARGS__) +#define yang_debug( fmt, ...) YangCLog::log(4,fmt, ##__VA_ARGS__) + + +#define yang_debug2( fmt, ...) YangCLog::logf(4,fmt, ##__VA_ARGS__) +#define yang_info2( fmt, ...) YangCLog::logf(3,fmt, ##__VA_ARGS__) +#define yang_trace( fmt, ...) YangCLog::logf(5,fmt, ##__VA_ARGS__) + +#define yang_setLogLevle(x) YangCLog::setLogLevel(x) +#define yang_setLogFile(x) YangCLog::setLogFile(x) + +#define yang_closeLogFile YangCLog::closeLogFile +#endif diff --git a/include/yangutil/sys/YangSRtp.h b/include/yangutil/sys/YangSRtp.h new file mode 100644 index 0000000000000000000000000000000000000000..6f290bbc856a32ef82898254c028879a768ea1c3 --- /dev/null +++ b/include/yangutil/sys/YangSRtp.h @@ -0,0 +1,20 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGSRTP_H_ +#define INCLUDE_YANGUTIL_SYS_YANGSRTP_H_ +#include +class YangSRtp +{ +public: + YangSRtp(); + virtual ~YangSRtp(); +public: + int32_t init(char* recv_key,int precvkeylen, char* send_key,int psendkeylen); +public: + int32_t enc_rtp(void* packet, int* nb_cipher); + int32_t enc_rtcp(void* packet, int* nb_cipher); + int32_t dec_rtp(void* packet, int* nb_plaintext); + int32_t dec_rtcp(void* packet, int* nb_plaintext); +private: + srtp_t m_recvCtx; + srtp_t m_sendCtx; +}; +#endif /* INCLUDE_YANGUTIL_SYS_YANGSRTP_H_ */ diff --git a/include/yangutil/sys/YangSocket.h b/include/yangutil/sys/YangSocket.h new file mode 100644 index 0000000000000000000000000000000000000000..3c4c3c51e8cee32162a0a9c688eedb30efefe283 --- /dev/null +++ b/include/yangutil/sys/YangSocket.h @@ -0,0 +1,8 @@ + +#ifndef YANGSOCKETUTIL_H_ +#define YANGSOCKETUTIL_H_ +#include + +std::string yang_getLocalInfo(void); +void yang_getIp( std::string domain, std::string& ip); +#endif /* YANGSOCKETUTIL_H_ */ diff --git a/include/yangutil/sys/YangSsl.h b/include/yangutil/sys/YangSsl.h new file mode 100644 index 0000000000000000000000000000000000000000..11e1fb78efe38353452c3da7cfee1b088678b39a --- /dev/null +++ b/include/yangutil/sys/YangSsl.h @@ -0,0 +1,47 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGSSL_H_ +#define INCLUDE_YANGUTIL_SYS_YANGSSL_H_ + +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif +#include "YangCertificate.h" +int32_t hmac_encode(const std::string& algo, const char* key, const int& key_length, + const char* input, const int32_t input_length, char* output, unsigned int& output_length); +std::string encode_hmac(char* hamc_buf, const int32_t hmac_buf_len); +std::string encode_fingerprint(uint32_t crc32); +class YangCertificateImpl:public YangCertificate +{ + +public: + YangCertificateImpl(); + virtual ~YangCertificateImpl(); +private: + std::string fingerprint; + bool ecdsa_mode; + X509* dtls_cert; + EVP_PKEY* dtls_pkey; + EC_KEY* eckey; + +public: + // Initialize DTLS certificate. + int32_t init(); + + // dtls_cert + X509* get_cert(); + // public key + EVP_PKEY* get_public_key(); + // ECDSA key + EC_KEY* get_ecdsa_key(); + // certificate fingerprint + std::string get_fingerprint(); + // whether is ecdsa + bool is_ecdsa(); +public: + +}; +#endif /* INCLUDE_YANGUTIL_SYS_YANGSSL_H_ */ diff --git a/include/yangutil/sys/YangSsrc.h b/include/yangutil/sys/YangSsrc.h new file mode 100644 index 0000000000000000000000000000000000000000..149d22559689e8f688c3b7cd6daca9f7c4388411 --- /dev/null +++ b/include/yangutil/sys/YangSsrc.h @@ -0,0 +1,26 @@ +#ifndef YANGWEBRTC_YANGRTCUTIL_H_ +#define YANGWEBRTC_YANGRTCUTIL_H_ +#include +#include +#include +#include + +using namespace std; + +class YangRtcSSRCGenerator +{ +private: + static YangRtcSSRCGenerator* _instance; +private: + uint32_t ssrc_num; +private: + YangRtcSSRCGenerator(); + virtual ~YangRtcSSRCGenerator(); +public: + static YangRtcSSRCGenerator* instance(); + uint32_t generate_ssrc(); +}; + +uint32_t yang_crc32_ieee(const void* buf, int32_t size, uint32_t previous); + +#endif /* YANGWEBRTC_YANGRTCUTIL_H_ */ diff --git a/include/yangutil/sys/YangString.h b/include/yangutil/sys/YangString.h new file mode 100644 index 0000000000000000000000000000000000000000..c7590d86350b3762e89f8413591fdc001662b810 --- /dev/null +++ b/include/yangutil/sys/YangString.h @@ -0,0 +1,17 @@ + +#ifndef INCLUDE_YANGUTIL_SYS_YANGSTRING_H_ +#define INCLUDE_YANGUTIL_SYS_YANGSTRING_H_ +#include +#include +#include +using namespace std; +long yang_random(); +vector yang_split(string s, char ch); +vector yang_split_first(string s, char ch); +std::vector yang_splits(const std::string& str, const std::string& delim); +std::string yang_int2str(int64_t value); +std::string yang_random_str(int32_t len); +void yang_replace(std::string& strBig, const std::string& strsrc, const std::string& strdst); +void skip_first_spaces(std::string& str); + +#endif /* INCLUDE_YANGUTIL_SYS_YANGSTRING_H_ */ diff --git a/include/yangutil/sys/YangSysMessageHandle.h b/include/yangutil/sys/YangSysMessageHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..858b7f6ca70e78418b6919ba26b833f77d81ea82 --- /dev/null +++ b/include/yangutil/sys/YangSysMessageHandle.h @@ -0,0 +1,39 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGSYSMESSAGEHANDLE_H_ +#define INCLUDE_YANGUTIL_SYS_YANGSYSMESSAGEHANDLE_H_ +#include +#include +#include + + +using namespace std; + +class YangSysMessageHandle :public YangThread{ +public: + YangSysMessageHandle(); + virtual ~YangSysMessageHandle(); + virtual void handleMessage(YangSysMessage* mss)=0; + virtual void initAll()=0; + virtual void deleteAll()=0; + void putMessage(YangSysMessageI *handle,int32_t pst, int32_t puid, int32_t handleState,void* user=NULL); + // void putMessage(YangSysMessageI *handle,int32_t pst, int32_t puid, int32_t handleState,void* user); + static YangSysMessageHandle* m_instance; + int32_t m_isStart; + int32_t m_loop; + void stop(); +protected: + void run(); + void startLoop(); + void stopLoop(); + +private: + + vector m_sysMessages; + pthread_mutex_t m_lock; + pthread_cond_t m_cond_mess; + + int32_t m_waitState; + YangSysMessageHandleI* m_receive; + +}; + +#endif /* INCLUDE_YANGUTIL_SYS_YANGSYSMESSAGEHANDLE_H_ */ diff --git a/include/yangutil/sys/YangSysMessageI.h b/include/yangutil/sys/YangSysMessageI.h new file mode 100644 index 0000000000000000000000000000000000000000..fb8a3d633566091c62e1ebdc2323c8167cc55e80 --- /dev/null +++ b/include/yangutil/sys/YangSysMessageI.h @@ -0,0 +1,29 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGMESSAGEI_H_ +#define INCLUDE_YANGUTIL_SYS_YANGMESSAGEI_H_ +#include +#include + +class YangSysMessageI { +public: + YangSysMessageI(){}; + virtual ~YangSysMessageI(){}; + virtual void success()=0; + virtual void failure(int32_t errcode)=0; +}; +struct YangSysMessage { + int32_t uid; + int32_t messageId; + int32_t handleState; + YangSysMessageI *handle; + void* user; +}; +class YangSysMessageHandleI { +public: + YangSysMessageHandleI() {}; + virtual ~YangSysMessageHandleI() {}; + virtual void receiveSysMessage(YangSysMessage *psm, int32_t phandleRet)=0; +}; +void yang_post_message(int32_t st, int32_t uid,YangSysMessageI *mhandle,void* user=NULL); +//void yang_post_userMessage(int32_t st, int32_t uid,YangSysMessageI *mhandle,void* user); +void yang_post_state_message(int32_t st, int32_t uid, int32_t handleState,YangSysMessageI *mhandle); +#endif /* INCLUDE_YANGUTIL_SYS_YANGMESSAGEI_H_ */ diff --git a/include/yangutil/sys/YangThread.h b/include/yangutil/sys/YangThread.h new file mode 100644 index 0000000000000000000000000000000000000000..5376ef0def565fe1fa898d91c27950fb35be9653 --- /dev/null +++ b/include/yangutil/sys/YangThread.h @@ -0,0 +1,31 @@ +#ifndef YangThread_H__ +#define YangThread_H__ +#include +#include +#include + +#define yang_stop_thread(x) if(x){while(x->m_isStart) yang_usleep(1000);} +#define yang_stop(x) if(x&&x->m_isStart){x->stop();} +class YangThread { +public: + YangThread(); + virtual ~YangThread(); + + int32_t start(); + void* join(); + int32_t detach(); + int32_t equals(YangThread *t); + void exitThread(void *value_ptr); + int32_t cancel(); + pthread_t getThread(); + virtual void stop()=0; +protected: + virtual void run() = 0; + +private: + static void* go(void *obj); + pthread_t m_thread; + +}; + +#endif diff --git a/include/yangutil/sys/YangTime.h b/include/yangutil/sys/YangTime.h new file mode 100644 index 0000000000000000000000000000000000000000..6aa1c1d1c0372ce875f3ef2655f834e5dbd45acc --- /dev/null +++ b/include/yangutil/sys/YangTime.h @@ -0,0 +1,74 @@ +#ifndef YANG_TIME_H__ +#define YANG_TIME_H__ +#ifndef _MSC_VER +#include +#endif +#include +#include +#include +using namespace std; +#define yang_get_system_time YangSystime::get_system_micro_time +#define yang_update_system_time YangSystime::get_system_micro_time + +int64_t yang_get_milli_time();//haomiao +int64_t yang_get_micro_time();//weimiao +#ifdef _MSC_VER +#include +int gettimeofday(struct timeval *tp, void *tzp); +int64_t yang_get_milli_tick();//haomiao +int64_t yang_get_micro_tick();//weimiao +#else +#define yang_get_milli_tick yang_get_milli_time +#define yang_get_micro_tick yang_get_micro_time +#endif + + + +int64_t yang_get_nano_tick();//namiao +class YangSystime{ +public: + YangSystime(); + ~YangSystime(); + + static int64_t system_time_us_cache; + static int64_t system_time_startup_time; + static void update_system_time(); + static int64_t get_system_milli_time(); + static int64_t get_system_micro_time(); +#ifdef _MSC_VER + static LARGE_INTEGER large_interger; + static int64_t dff; +#endif +}; + +class YangNtp +{ +public: + YangNtp(); + virtual ~YangNtp(); +public: + uint64_t m_system_ms; + uint64_t m_ntp; + uint32_t m_ntp_second; + uint32_t m_ntp_fractions; +public: + static YangNtp from_time_ms(uint64_t ms); + static YangNtp to_time_ms(uint64_t ntp); +public: + static uint64_t kMagicNtpFractionalUnit; +}; + +class YangWallClock +{ +public: + YangWallClock(); + virtual ~YangWallClock(); +public: + /** + * Current time in get_system_milli_time. + */ + virtual int64_t now(); +}; + + +#endif diff --git a/include/yangutil/sys/YangTimer.h b/include/yangutil/sys/YangTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..6faef46cebb85b2370cd32c2f18c122c30cd3d05 --- /dev/null +++ b/include/yangutil/sys/YangTimer.h @@ -0,0 +1,75 @@ +#ifndef SRC_YANGUTIL_SRC_YANGTIMER_H_ +#define SRC_YANGUTIL_SRC_YANGTIMER_H_ +#include +#include + + +#define Yang_Using_Phtread 1 + + +#if !Yang_Using_Phtread +#ifdef _WIN32 +#include +#endif +#endif + +//#include +class YangTimerTask { +public: + YangTimerTask() {}; + virtual ~YangTimerTask() {}; + virtual void doTask(int32_t taskId)=0; +}; + + +class YangTimer: public YangThread { +public: + YangTimer(); + virtual ~YangTimer(); + int32_t m_isStart; + int32_t m_loop; + int32_t m_waitState; + int32_t m_waitTime; + + void setTask(YangTimerTask *ptask); + void setTimelen(int32_t ptimelen);//hao miao + + + void setTaskId(int32_t ptaskId); + void stop(); + +#if !Yang_Using_Phtread +#ifdef _WIN32 + static void CALLBACK TimeEvent(PVOID lpParam, BOOLEAN TimerOrWaitFired); +#endif +#endif + +protected: + void run(); + void startLoop(); + void stopLoop(); +private: + YangTimerTask *m_task; + int32_t m_taskId; + // std::condition_variable_any m_threadCon; + // std::mutex m_ThreadLock; + + +#if Yang_Using_Phtread + pthread_mutex_t m_lock; + pthread_cond_t m_cond_mess; +#else +#ifdef _WIN32 + void startWindowsEventTime(int pwaitTime,DWORD_PTR duser); + HANDLE m_hTimerQueue; + HANDLE m_hTimerQueueTimer; + HANDLE m_winEvent; +#else + int m_timerfd; + int m_efd; +#endif +#endif + +}; + +#endif /* SRC_YANGUTIL_SRC_YANGTIMER_H_ */ diff --git a/include/yangutil/sys/YangUrl.h b/include/yangutil/sys/YangUrl.h new file mode 100644 index 0000000000000000000000000000000000000000..aee99322292db8ca9e745290a39832db40de6ee3 --- /dev/null +++ b/include/yangutil/sys/YangUrl.h @@ -0,0 +1,21 @@ +#ifndef INCLUDE_YANGUTIL_SYS_YANGURL_H_ +#define INCLUDE_YANGUTIL_SYS_YANGURL_H_ +#include +#include + +#define Yang_Websocket_Ws 0 +#define Yang_Websocket_Wss 1 +#define Yang_Websocket_Http 2 +#define Yang_Websocket_Https 3 +struct YangUrlData{ + int32_t netType; + int32_t port; + std::string server; + std::string app; + std::string stream; +}; +//webrtc://host[:port]/app/stream +int32_t yang_srs_url_parse(char* purl,YangUrlData* data); +//http://host:port/path ws://host:port/path wss://host:port/path +int32_t yang_ws_url_parse(char* purl,YangUrlData* data); +#endif /* INCLUDE_YANGUTIL_SYS_YANGURL_H_ */ diff --git a/include/yangutil/sys/YangWebsocket.h b/include/yangutil/sys/YangWebsocket.h new file mode 100644 index 0000000000000000000000000000000000000000..d3e9e52da536c86c6da98feef3504573ec70dd12 --- /dev/null +++ b/include/yangutil/sys/YangWebsocket.h @@ -0,0 +1,46 @@ +#ifndef YANGRTP_YANGWEBSOCKET_H_ +#define YANGRTP_YANGWEBSOCKET_H_ +#include +#include +#include + +struct YangWebsocketData{ + uint8_t payload[1024]; + int nb; +}; +class YangWebsocketCallback{ +public: + YangWebsocketCallback(){}; + virtual ~YangWebsocketCallback(){}; + virtual int receive(YangWebsocketData* data)=0; +}; + + +class YangWebsocket :public YangThread{ +public: + YangWebsocket(); + virtual ~YangWebsocket(); + + virtual int connectServer(std::string url)=0; + virtual int disconnectServer()=0; + virtual int sendData(uint8_t* p,int nb)=0; + + int m_isStart; + void stop(); + + void setReceiveCallback(YangWebsocketCallback* pcallback); + YangWebsocketCallback* getReceiveCallback(); + static YangWebsocket* getWebsocket(); + +protected: + void run(); + virtual void startLoop()=0; + virtual void stopLoop()=0; + + YangUrlData m_urlData; + YangWebsocketCallback* m_receiveCallback; + + +}; + +#endif /* YANGRTP_YANGWEBSOCKET_H_ */ diff --git a/include/yangutil/sys/YangWindowsMouse.h b/include/yangutil/sys/YangWindowsMouse.h new file mode 100644 index 0000000000000000000000000000000000000000..9b89379c92f0ef7afe02625c2c4e28f534e44250 --- /dev/null +++ b/include/yangutil/sys/YangWindowsMouse.h @@ -0,0 +1,55 @@ +#ifndef INCLUDE_YANGUTIL_YangWindowsMouse_ +#define INCLUDE_YANGUTIL_YangWindowsMouse_ +#ifdef _WIN32 +#include +#endif +#include +#include +using namespace std; +struct YangScreenKeyEvent{ + uint8_t key; + int x; + int y; + int wheel; + string direction; + string event; +}; + +class YangWindowsMouse +{ +public: + YangWindowsMouse(); + ~YangWindowsMouse(); + +public: + void moveTo(int x, int y); + void relativeMove(int cx, int cy); + void setPos(); + void restorePos(); + + void lockMouse(); + void unlockMouse(); + + void leftBClick(); + void leftbDClick(); + void leftBDown(); + void leftBUp(); + + void middleBClick(); + void middleBDbClick(); + void middleBDown(); + void middleBUp(); + void middleBRoll(int px,int py,int ch); + + + void rightBClick(); + void rightBDbClick(); + void rightBDown(); + void rightBUp(); +private: + #ifdef _WIN32 + POINT p; +#endif + +}; +#endif diff --git a/include/yangutil/yang_unistd.h b/include/yangutil/yang_unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..8c5ed3ec0443d83aef9233152bf5631e4fc3c64f --- /dev/null +++ b/include/yangutil/yang_unistd.h @@ -0,0 +1,19 @@ +#ifndef INCLUDE_YANGUTIL_YANG_UNISTD_H_ +#define INCLUDE_YANGUTIL_YANG_UNISTD_H_ + +#ifdef _MSC_VER +#include +#define yang_usleep(x) Sleep(x>1000?x/1000:1) +//void yang_usleep(int ns){ + // Sleep(ns>1000?ns/1000:1); +//} +#define yang_sleep(x) Sleep(1000*x) +#else + + +#include +#define yang_usleep usleep +#define yang_sleep sleep +#endif + +#endif /* INCLUDE_YANGUTIL_YANG_UNISTD_H_ */ diff --git a/include/yangutil/yangavinfotype.h b/include/yangutil/yangavinfotype.h new file mode 100644 index 0000000000000000000000000000000000000000..67621a6b5e668886c784c32341ef657172fe477f --- /dev/null +++ b/include/yangutil/yangavinfotype.h @@ -0,0 +1,140 @@ +/* + * yangtype.h + * + * Created on: 2020年10月14日 + * Author: yang + */ + +#ifndef YANGUTIL_YANGAVINFOTYPE_H_ +#define YANGUTIL_YANGAVINFOTYPE_H_ +#include +#include +#include +#include + +/** + struct YangEncoderParam { + int32_t width; + int32_t height; + int32_t fps; + int32_t bitrate; + int32_t keyint_max; + int32_t level_idc; + int32_t profile; + }; + **/ +struct YangAudioInfo { + int32_t sample; + int32_t frameSize; + int32_t bitrate; + int32_t channel; + + int32_t usingMono; + int32_t hasAec; + int32_t echoPath; + + int32_t aecBufferFrames; + int32_t audioCacheSize; + int32_t audioCacheNum; + int32_t audioPlayCacheNum; + + int32_t hasAudioHeader; + int32_t audioEncoderType; + int audioDecoderType; + int32_t audioPlayType; + + int32_t aIndex; + int32_t aSubIndex; +}; + +struct YangVideoInfo { + int32_t width; //= 800 + int32_t height; //= 600 + int32_t outWidth; + int32_t outHeight; + int32_t rate; // 512 + int32_t frame; //25 + //int32_t bitcount; // 16 + int32_t bitDepth; + + int32_t videoCacheNum; + int32_t evideoCacheNum; + int32_t videoPlayCacheNum; + + YangYuvType videoCaptureFormat; + YangYuvType videoEncoderFormat; + YangYuvType videoDecoderFormat; + + int32_t videoEncoderType; + int32_t videoDecoderType; + int32_t videoEncHwType; + int32_t videoDecHwType; + int32_t vIndex; +}; +struct YangVideoEncInfo { + int32_t preset; + int32_t level_idc; + int32_t profile; + int32_t keyint_max; + int32_t enc_threads; + int32_t gop; + bool createMeta; + + +}; +struct YangSysInfo { + int32_t isMultCamera; + int32_t transType; + int32_t usingDataServer; + int32_t rtmpPort; + int32_t srtPort; + int32_t rtcPort; + int32_t rtcLocalPort; + int32_t httpPort; + int32_t dataPort; + int32_t hasLogFile; + int32_t logLevel; + int32_t cameraCount; + + char cameraIndexs[50]; + char rtmpServerIP[20]; + char srtServerIP[20]; + char rtcServerIP[20]; + char httpServerIP[20]; + char dataServerIP[20]; +}; + +struct YangRtcInfo { + int32_t sendTwcc; + int32_t mixAvqueue; + int32_t audioQueueCount; + int32_t videoQueueCount; + +}; + +class YangContext { +public: + YangContext(); + virtual ~YangContext(); + void init(char *filename); + void init(); + YangCertificate* getCertificate(); + virtual void initExt(void *filename); + virtual void initExt(); +public: + YangAudioInfo audio; + YangVideoInfo video; + YangVideoEncInfo enc; + YangSysInfo sys; + YangRtcInfo rtc; +#if Yang_HaveVr + char bgFilename[256]; +#endif + + YangStreamManager streams; +private: + YangCertificate* m_certificate; + +}; +//void yang_init_context(YangContext* context,char* filename); +#endif /* YANGUTIL_YANGTYPE_H_ */ diff --git a/include/yangutil/yangavtype.h b/include/yangutil/yangavtype.h new file mode 100644 index 0000000000000000000000000000000000000000..5fc00458a1fd657162a472a9c6f54dd4a114d3a2 --- /dev/null +++ b/include/yangutil/yangavtype.h @@ -0,0 +1,234 @@ +#ifndef INCLUDE_YANGUTIL_YANGAVTYPE_H_ +#define INCLUDE_YANGUTIL_YANGAVTYPE_H_ +#include +#include +#define YANG_Frametype_Spspps 9 +#define YANG_Frametype_I 1 +#define YANG_Frametype_P 0 + +#define kNalTypeMask 0x1F +enum YangYuvType{ + YangYuy2, + YangI420, + YangNv12, + YangYv12, + YangRgb, + YangArgb, + YangBgra, + YangP010, + YangP016 +}; + +/** + * the level for avc/h.264. + * @see Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 207. + */ +enum YangAvcLevel +{ + YangAvcLevelReserved = 0, + + YangAvcLevel_1 = 10, + YangAvcLevel_11 = 11, + YangAvcLevel_12 = 12, + YangAvcLevel_13 = 13, + YangAvcLevel_2 = 20, + YangAvcLevel_21 = 21, + YangAvcLevel_22 = 22, + YangAvcLevel_3 = 30, + YangAvcLevel_31 = 31, + YangAvcLevel_32 = 32, + YangAvcLevel_4 = 40, + YangAvcLevel_41 = 41, + YangAvcLevel_5 = 50, + YangAvcLevel_51 = 51, +}; + +/** + * Table 7-6 – Name association to slice_type + * ISO_IEC_14496-10-AVC-2012.pdf, page 105. + */ +enum YangAvcSliceType +{ + YangAvcSliceTypeP = 0, + YangAvcSliceTypeB = 1, + YangAvcSliceTypeI = 2, + YangAvcSliceTypeSP = 3, + YangAvcSliceTypeSI = 4, + YangAvcSliceTypeP1 = 5, + YangAvcSliceTypeB1 = 6, + YangAvcSliceTypeI1 = 7, + YangAvcSliceTypeSP1 = 8, + YangAvcSliceTypeSI1 = 9, +}; + + +enum YangAvcNaluType +{ + // Unspecified + YangAvcNaluTypeReserved = 0, + YangAvcNaluTypeForbidden = 0, + + // Coded slice of a non-IDR picture slice_layer_without_partitioning_rbsp( ) + YangAvcNaluTypeNonIDR = 1, + // Coded slice data partition A slice_data_partition_a_layer_rbsp( ) + YangAvcNaluTypeDataPartitionA = 2, + // Coded slice data partition B slice_data_partition_b_layer_rbsp( ) + YangAvcNaluTypeDataPartitionB = 3, + // Coded slice data partition C slice_data_partition_c_layer_rbsp( ) + YangAvcNaluTypeDataPartitionC = 4, + // Coded slice of an IDR picture slice_layer_without_partitioning_rbsp( ) + YangAvcNaluTypeIDR = 5, + // Supplemental enhancement information (SEI) sei_rbsp( ) + YangAvcNaluTypeSEI = 6, + // Sequence parameter set seq_parameter_set_rbsp( ) + YangAvcNaluTypeSPS = 7, + // Picture parameter set pic_parameter_set_rbsp( ) + YangAvcNaluTypePPS = 8, + // Access unit delimiter access_unit_delimiter_rbsp( ) + YangAvcNaluTypeAccessUnitDelimiter = 9, + // End of sequence end_of_seq_rbsp( ) + YangAvcNaluTypeEOSequence = 10, + // End of stream end_of_stream_rbsp( ) + YangAvcNaluTypeEOStream = 11, + // Filler data filler_data_rbsp( ) + YangAvcNaluTypeFilterData = 12, + // Sequence parameter set extension seq_parameter_set_extension_rbsp( ) + YangAvcNaluTypeSPSExt = 13, + // Prefix NAL unit prefix_nal_unit_rbsp( ) + YangAvcNaluTypePrefixNALU = 14, + // Subset sequence parameter set subset_seq_parameter_set_rbsp( ) + YangAvcNaluTypeSubsetSPS = 15, + // Coded slice of an auxiliary coded picture without partitioning slice_layer_without_partitioning_rbsp( ) + YangAvcNaluTypeLayerWithoutPartition = 19, + // Coded slice extension slice_layer_extension_rbsp( ) + YangAvcNaluTypeCodedSliceExt = 20, +}; + +enum YangAvcProfile +{ + YangAvcProfileReserved = 0, + + // @see ffmpeg, libavcodec/avcodec.h:2713 + YangAvcProfileBaseline = 66, + // FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag + // FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) + YangAvcProfileConstrainedBaseline = 578, + YangAvcProfileMain = 77, + YangAvcProfileExtended = 88, + YangAvcProfileHigh = 100, + YangAvcProfileHigh10 = 110, + YangAvcProfileHigh10Intra = 2158, + YangAvcProfileHigh422 = 122, + YangAvcProfileHigh422Intra = 2170, + YangAvcProfileHigh444 = 144, + YangAvcProfileHigh444Predictive = 244, + YangAvcProfileHigh444Intra = 2192, +}; +struct YangRect{ + short x; + short y; + short w; + short h; +}; +struct YangColor{ + uint8_t r; + uint8_t g; + uint8_t b; +}; +struct YangH2645Conf { + int32_t vpsLen; + int32_t spsLen; + int32_t ppsLen; + uint8_t vps[128]; + uint8_t sps[128]; + uint8_t pps[64]; +}; +struct YangRtmpMeta { + uint8_t buffer[128]; + int32_t bufLen; +}; +struct YangVideoMeta { + int32_t isInit; + YangH2645Conf mp4Meta; + //YangRtmpMeta flvMeta; + YangRtmpMeta livingMeta; +}; + +enum YangAudioEncDecType{ + Yang_AED_AAC, + Yang_AED_MP3, + Yang_AED_SPEEX, + Yang_AED_OPUS +}; +enum YangVideoEncDecType{ + Yang_VED_264, + Yang_VED_265, + Yang_VED_vp9 +}; +enum YangVideoHwType{ + Yang_Hw_Soft, + YangV_Hw_Intel, + YangV_Hw_Nvdia, + YangV_Hw_Android +}; +struct YangAudioParam{ + YangAudioEncDecType encode; + int32_t sample; + int32_t channel; + int32_t audioClock; +}; + +struct YangVideoParam{ + YangVideoEncDecType encode; + int32_t videoClock; + +}; +struct YangFrame{ + int32_t mediaType; + int32_t uid; + int32_t frametype; + int32_t nb; + int64_t timestamp; + uint8_t* payload; +}; + +void yang_frame_copy( YangFrame* src,YangFrame* dst); +void yang_frame_copy_buffer( YangFrame* src,YangFrame* dst); +void yang_frame_copy_nobuffer(YangFrame* src,YangFrame* dst); +//void yang_frame_init(YangFrame* frame); + +struct YangMessage{ + int32_t mediaType; + int32_t nb; + int64_t timestamp; + + char* payload; + YangMessage(){ + mediaType=0; + nb=0; + timestamp=0; + payload=NULL; + } + +}; +struct YangSample{ + int32_t nb; + char* bytes; +}; +YangSample* yang_sample_copy(YangSample* src); + +class YangBufferManager{ +public: + YangBufferManager(); + YangBufferManager(int32_t num,int32_t bufsize); + virtual ~YangBufferManager(); + void init(int32_t num,int32_t bufsize); + uint8_t* getBuffer(); +private: + uint8_t* m_cache; + int32_t m_curindex; + int32_t m_unitsize; + int32_t m_size; +}; + +#endif /* INCLUDE_YANGUTIL_YANGAVTYPE_H_ */ diff --git a/include/yangutil/yangavtype_h265.h b/include/yangutil/yangavtype_h265.h new file mode 100644 index 0000000000000000000000000000000000000000..2db5c2028281c91953282d5ea8cfbfd03164a440 --- /dev/null +++ b/include/yangutil/yangavtype_h265.h @@ -0,0 +1,70 @@ + +#ifndef INCLUDE_YANGUTIL_YANGAVTYPE_H265_H_ +#define INCLUDE_YANGUTIL_YANGAVTYPE_H265_H_ + +enum YangHevcNaluType +{ + YANG_NAL_UNIT_CODED_SLICE_TRAIL_N = 0, + YANG_NAL_UNIT_CODED_SLICE_TRAIL_R, //1 + YANG_NAL_UNIT_CODED_SLICE_TSA_N, //2 + YANG_NAL_UNIT_CODED_SLICE_TLA, //3 + YANG_NAL_UNIT_CODED_SLICE_STSA_N, //4 + YANG_NAL_UNIT_CODED_SLICE_STSA_R, //5 + YANG_NAL_UNIT_CODED_SLICE_RADL_N, //6 + YANG_NAL_UNIT_CODED_SLICE_DLP, //7 + YANG_NAL_UNIT_CODED_SLICE_RASL_N, //8 + YANG_NAL_UNIT_CODED_SLICE_TFD, //9 + YANG_NAL_UNIT_RESERVED_10, + YANG_NAL_UNIT_RESERVED_11, + YANG_NAL_UNIT_RESERVED_12, + YANG_NAL_UNIT_RESERVED_13, + YANG_NAL_UNIT_RESERVED_14, + YANG_NAL_UNIT_RESERVED_15, + YANG_NAL_UNIT_CODED_SLICE_BLA, //16 + YANG_NAL_UNIT_CODED_SLICE_BLANT, //17 + YANG_NAL_UNIT_CODED_SLICE_BLA_N_LP, //18 + YANG_NAL_UNIT_CODED_SLICE_IDR, //19 + YANG_NAL_UNIT_CODED_SLICE_IDR_N_LP, //20 + YANG_NAL_UNIT_CODED_SLICE_CRA, //21 + YANG_NAL_UNIT_VPS=32, //32 + YANG_NAL_UNIT_SPS, // 33 + YANG_NAL_UNIT_PPS, //34 + YANG_NAL_UNIT_ACCESS_UNIT_DELIMITER, //35 + YANG_NAL_UNIT_EOS, //36 + YANG_NAL_UNIT_EOB, //37 + YANG_NAL_UNIT_FILLER_DATA, //38 + YANG_NAL_UNIT_SEI , //39Prefix SEI + YANG_NAL_UNIT_SEI_SUFFIX, //40Suffix SEI + YANG_NAL_UNIT_RESERVED_41, + YANG_NAL_UNIT_RESERVED_42, + YANG_NAL_UNIT_RESERVED_43, + YANG_NAL_UNIT_RESERVED_44, + YANG_NAL_UNIT_RESERVED_45, + YANG_NAL_UNIT_RESERVED_46, + YANG_NAL_UNIT_RESERVED_47, + YANG_NAL_UNIT_UNSPECIFIED_48, + YANG_NAL_UNIT_UNSPECIFIED_49, + YANG_NAL_UNIT_UNSPECIFIED_50, + YANG_NAL_UNIT_UNSPECIFIED_51, + YANG_NAL_UNIT_UNSPECIFIED_52, + YANG_NAL_UNIT_UNSPECIFIED_53, + YANG_NAL_UNIT_UNSPECIFIED_54, + YANG_NAL_UNIT_UNSPECIFIED_55, + YANG_NAL_UNIT_UNSPECIFIED_56, + YANG_NAL_UNIT_UNSPECIFIED_57, + YANG_NAL_UNIT_UNSPECIFIED_58, + YANG_NAL_UNIT_UNSPECIFIED_59, + YANG_NAL_UNIT_UNSPECIFIED_60, + YANG_NAL_UNIT_UNSPECIFIED_61, + YANG_NAL_UNIT_UNSPECIFIED_62, + YANG_NAL_UNIT_UNSPECIFIED_63, + YANG_NAL_UNIT_INVALID, +}; + +//for nalu data first byte +#define YANG_HEVC_NALU_TYPE(code) (YangHevcNaluType)((code & 0x7E)>>1) +#define H265_kFuA 49 +#define H265_kStapA 48 + + +#endif /* INCLUDE_YANGUTIL_YANGAVTYPE_H265_H_ */ diff --git a/include/yangutil/yangtype.h b/include/yangutil/yangtype.h new file mode 100644 index 0000000000000000000000000000000000000000..d13b61696b8f9d2bcddd7965431836e23429d2cc --- /dev/null +++ b/include/yangutil/yangtype.h @@ -0,0 +1,52 @@ +#ifndef INCLUDE_YANGUTIL_YANGTYPE_H_ +#define INCLUDE_YANGUTIL_YANGTYPE_H_ +#include +#include +#include +#include "YangErrorCode.h" +#include "../Yang_Config.h" + + +#define yang_delete(a) {if( (a)) {delete (a); (a) = NULL;}} +#define yang_deleteA(a) {if( (a)) {delete[] (a); (a) = NULL;}} +#define yang_free(a) {if( (a)) {free((a)); (a) = NULL;}} +#define yang_min(a, b) (((a) < (b))? (a) : (b)) +#define yang_max(a, b) (((a) < (b))? (b) : (a)) + +#define Yang_Rtmp 0 +#define Yang_Srt 1 +#define Yang_Webrtc 2 + +#define YANG_VIDEO_ENCODE_BUFFER_LEN 1024 * 1024 + +#define YangAutoFree(className, instance) \ +impl_YangAutoFree _auto_free_##instance(&instance, false) +#define YangAutoFreeA(className, instance) \ +impl_YangAutoFree _auto_free_array_##instance(&instance, true) +template +class impl_YangAutoFree +{ +private: + T** ptr; + bool is_array; +public: + impl_YangAutoFree(T** p, bool array) { + ptr = p; + is_array = array; + } + + virtual ~impl_YangAutoFree() { + if (ptr == NULL || *ptr == NULL) { + return; + } + + if (is_array) { + delete[] *ptr; + } else { + delete *ptr; + } + + *ptr = NULL; + } +}; +#endif /* INCLUDE_YANGUTIL_YANGTYPE_H_ */ diff --git a/include/yangwebrtc/YangRtcHandle.h b/include/yangwebrtc/YangRtcHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..48ea99847aed67a592b102fcd42b3ea35d2bbfb6 --- /dev/null +++ b/include/yangwebrtc/YangRtcHandle.h @@ -0,0 +1,28 @@ + +#ifndef INCLUDE_YANGWEBRTC_YANGRTCHANDLE_H_ +#define INCLUDE_YANGWEBRTC_YANGRTCHANDLE_H_ +#include +#include + + +class YangRtcHandle +{ +public: + YangRtcHandle(); + virtual ~YangRtcHandle(); + virtual void init(YangStreamConfig* pconf)=0; + + virtual int32_t connectRtcServer()=0; + virtual int32_t disconnectServer()=0; + virtual int32_t getState()=0; + virtual int32_t publishVideo(YangStreamCapture* videoFrame)=0; + virtual int32_t publishAudio(YangStreamCapture* audioFrame)=0; + void setReceiveCallback(YangReceiveCallback* cbk); + static YangRtcHandle* createRtcHandle(YangContext* pcontext); +protected: + YangReceiveCallback* m_recvcb; + YangStreamConfig *m_conf; +}; + + +#endif /* INCLUDE_YANGWEBRTC_YANGRTCHANDLE_H_ */ diff --git a/include/yangwebrtc/YangSrsSdp.h b/include/yangwebrtc/YangSrsSdp.h new file mode 100644 index 0000000000000000000000000000000000000000..b6bee5af263edc66757e580319f175c8f160e16d --- /dev/null +++ b/include/yangwebrtc/YangSrsSdp.h @@ -0,0 +1,18 @@ +#ifndef YANGRTP_Httpurl_H_ +#define YANGRTP_Httpurl_H_ +#include +#include +using namespace std; +class YangSrsSdp +{ +public: + YangSrsSdp(); + ~YangSrsSdp(); + + int32_t querySrs(char* purl, string psdp); + SrsSdpResponseType m_srs; + YangHttp m_http; + +}; + +#endif diff --git a/libyangrtc2/src/yangaudiodev/YangAudioCapture.cpp b/libyangrtc2/src/yangaudiodev/YangAudioCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fe559b5c9e51f767a9a8cf67f0fffdae1c56b32 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioCapture.cpp @@ -0,0 +1,39 @@ +#include "stdlib.h" +#include +#include +#include "yangutil/sys/YangLog.h" +#include "memory.h" +#include "malloc.h" + + + +YangAudioCapture::YangAudioCapture() +{ + + aIndex=0; + m_isStart=0; + m_context=NULL; + //m_resample=NULL; + +} + +YangAudioCapture::~YangAudioCapture() +{ + + m_context=NULL; + + +} + + +void YangAudioCapture::run(){ + m_isStart=1; + startLoop(); + m_isStart=0; +} +void YangAudioCapture::stop(){ + stopLoop(); + //m_isStart=0; +} + + diff --git a/libyangrtc2/src/yangaudiodev/YangAudioCaptureData.cpp b/libyangrtc2/src/yangaudiodev/YangAudioCaptureData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a3dc08e4555872496cf3052bc5c11d32bcf3b82 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioCaptureData.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +YangAudioCaptureData::YangAudioCaptureData() { + m_cacheLen = 1024 * 4 * 4; + m_cache = new uint8_t[m_cacheLen]; + m_size = 0; + m_pos = 0; + m_cb = NULL; + m_res.init(48000, 2, 48000, 2, 20); + memset(&m_audioFrame,0,sizeof(YangFrame)); +} + +YangAudioCaptureData::~YangAudioCaptureData() { + yang_deleteA(m_cache); + m_cb = NULL; +} + +void YangAudioCaptureData::initIn(int psample, int pchannel) { + m_res.initIn(psample, pchannel); + +} + +void YangAudioCaptureData::initOut(int psample, int pchannel) { + m_res.initOut(psample, pchannel); +} + +void YangAudioCaptureData::caputure(YangFrame *audioFrame) { + if(m_size + audioFrame->nb > m_cacheLen) return; + if ((m_pos + m_size + audioFrame->nb) >= m_cacheLen) { + memmove(m_cache, m_cache + m_pos, m_size); + m_pos = 0; + } + + if (audioFrame->payload && audioFrame->nb > 0) { + + memcpy(m_cache + m_pos + m_size, audioFrame->payload, audioFrame->nb); + m_size += audioFrame->nb; + } + + while(m_size >= m_res.getInBytes()) { + if (m_pos + m_res.getInBytes() >= m_cacheLen) { + memmove(m_cache, m_cache + m_pos, m_size); + m_pos = 0; + } + captureData(); + + m_pos += m_res.getInBytes(); + m_size -= m_res.getInBytes(); + } + +} + +int YangAudioCaptureData::getOutLength(){ + return m_res.getOutBytes(); +} + +void YangAudioCaptureData::captureData() { + m_audioFrame.payload=m_cache + m_pos; + m_audioFrame.nb=m_res.getInBytes(); + m_res.resample(&m_audioFrame); + + if (m_cb) + m_cb->caputureAudioData(&m_audioFrame); + +} + diff --git a/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.cpp b/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17274fb1d1312dc9fb491169ca7c2674073c4aed --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.cpp @@ -0,0 +1,121 @@ +#include +#include "yangutil/yang_unistd.h" + + +YangAudioCaptureHandle::YangAudioCaptureHandle(YangContext *pcontext) +{ + + isBuf=0; + m_audioList=NULL; + m_aec=NULL; + m_aecPlayBuffer=NULL; + pcm=new short[4096/2]; + hasPlayData=1; + isFirst=1; + m_aecBufferFrames=pcontext->audio.aecBufferFrames; + memset(&m_audioFrame,0,sizeof(YangFrame)); + +} +YangAudioCaptureHandle::~YangAudioCaptureHandle(void) +{ + m_aec=NULL; + m_aecPlayBuffer=NULL; + m_audioList=NULL; + yang_deleteA(pcm); +} + + + +void YangAudioCaptureHandle::startRecordWave(char* filename){ + //wavRecord.start(1,filename); + //isRecordAudio=1; +} +void YangAudioCaptureHandle::stopRecordWave(){ + //isRecordAudio=0; + //wavRecord.stop(); + +} + +void YangAudioCaptureHandle::setOutAudioBuffer(YangAudioBuffer *pbuf) +{ + m_audioList=pbuf; +} + +//int32_t tcou=0; + void YangAudioCaptureHandle::putBuffer(uint8_t *pBuffer,int32_t plen) + { + if(!isBuf) return; + if(m_aec) { + if(hasPlayData) { + m_aec->echo_capture((short*)pBuffer,pcm); + m_aec->preprocess_run(pcm); + } + if(m_aecPlayBuffer&&m_aecPlayBuffer->size()>m_aecBufferFrames){ + uint8_t* tmp=m_aecPlayBuffer->getAudioRef(&m_audioFrame); + if(tmp) + m_aec->echo_playback((short*)tmp); + //printf("%d,",m_aecPlayBuffer->size()); + if(isFirst){ + if(m_audioList) m_audioList->resetIndex(); + isFirst=0; + } + hasPlayData=1; + //m_aec->echo_cancellation((short*)pBuffer,(short*)m_aecPlayBuffer->getAudio(),pcm); + //speex_echo_cancellation() + }else + hasPlayData=0; + + + if(hasPlayData){ + if(m_audioList) { + m_audioFrame.payload=(uint8_t *)pcm; + m_audioFrame.nb=plen; + m_audioList->putAudio(&m_audioFrame); + } + }else{ + if(m_audioList) { + m_audioFrame.payload=pBuffer; + m_audioFrame.nb=plen; + m_audioList->putAudio(&m_audioFrame); + } + } + }else{ + //printf("2,"); + if(m_audioList) { + m_audioFrame.payload=pBuffer; + m_audioFrame.nb=plen; + m_audioList->putAudio(&m_audioFrame); + } + } + //aeaac->encoder(pBuffer,BufferLen); + + } + void YangAudioCaptureHandle::putEchoPlay(short* pbuf,int32_t plen){ + if(!isBuf) return; + if(m_aec) m_aec->echo_playback(pbuf); + } + void YangAudioCaptureHandle::putEchoBuffer( uint8_t *pBuffer,int32_t plen){ + if(!isBuf) return; + if(m_aec) { + m_aec->echo_capture((short*)pBuffer,pcm); + m_aec->preprocess_run(pcm); + + if(m_audioList){ + m_audioFrame.payload=pBuffer; + m_audioFrame.nb=plen; + m_audioList->putAudio(&m_audioFrame); + } + } + + } + void YangAudioCaptureHandle::putBuffer1( uint8_t *pBuffer,int32_t plen){ + + if(!isBuf) return; + if(m_audioList) { + m_audioFrame.payload=pBuffer; + m_audioFrame.nb=plen; + m_audioList->putAudio(&m_audioFrame); + } + + } + diff --git a/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.h b/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..631c6c33cc23416aace4a38270a256ef57d5e048 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioCaptureHandle.h @@ -0,0 +1,35 @@ +#ifndef ___YangAudioCaptureHandle__ +#define ___YangAudioCaptureHandle__ +//#ifdef _WIN32 +#include + +#include +#include + +class YangAudioCaptureHandle { +public: + YangAudioCaptureHandle(YangContext *pcontext); + virtual ~YangAudioCaptureHandle(void); + YangAecBase *m_aec; + +public: + void putBuffer(uint8_t *pBuffer,int32_t plen); + void putBuffer1(uint8_t *pBuffer,int32_t plen); + void putEchoBuffer(uint8_t *pBuffer,int32_t plen); + void putEchoPlay(short *pbuf,int32_t plen); + void startRecordWave(char *filename); + void stopRecordWave(); + void setOutAudioBuffer(YangAudioBuffer *plist); + YangAudioBuffer *m_aecPlayBuffer; + int32_t isBuf; +private: + + int32_t hasPlayData; + int32_t m_aecBufferFrames; + int32_t isFirst; + short *pcm; + YangFrame m_audioFrame; + YangAudioBuffer *m_audioList; +}; +//#endif +#endif diff --git a/libyangrtc2/src/yangaudiodev/YangAudioPlay.cpp b/libyangrtc2/src/yangaudiodev/YangAudioPlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a10ee2fd14f08d6106c2062ba2e90759d6cd9ba --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioPlay.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +YangAudioPlay::YangAudioPlay(YangContext* pcontext) { //m_rc=0; + + m_context = pcontext; + m_ace = NULL; + aIndex = 0; + m_frames = 0; + m_channel = pcontext->audio.channel; + m_isStart = 0; + + m_sample = pcontext->audio.sample; + m_isStart=0; + m_audioData.setInAudioBuffer(pcontext->streams.m_playBuffer); + m_audioData.setInAudioBuffers(pcontext->streams.m_playBuffers); + m_audioData.initPlay(pcontext->audio.sample,pcontext->audio.channel); +} + +YangAudioPlay::~YangAudioPlay() { + m_context = NULL; + m_ace = NULL; +} +void YangAudioPlay::run() { + m_isStart=1; + startLoop(); + m_isStart=0; +} +void YangAudioPlay::stop() { + stopLoop(); +} +void YangAudioPlay::setAudioBuffers(vector *pal) { + // if(m_audioData.m_in_audioBuffers) m_audioData.m_in_audioBuffers->setInAudioBuffers(pal); + //m_in_audioBuffer = pal; +} +void YangAudioPlay::setAudioBuffer(YangAudioPlayBuffer* pal) { + //m_buf=pal; + //if(m_audioData.m_syn) m_audioData.m_syn->setInAudioBuffer(pal); + //m_in_audioBuffer = pal; +} +void YangAudioPlay::setAecBase(YangAecBase *pace) { + if (pace != NULL) + m_aecInit = 1; + m_ace = pace; +} + diff --git a/libyangrtc2/src/yangaudiodev/YangAudioRenderData.cpp b/libyangrtc2/src/yangaudiodev/YangAudioRenderData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20baab7de97532d50686499156f18a27ea59a8b7 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangAudioRenderData.cpp @@ -0,0 +1,181 @@ +/* + * YangAudioDataManager.cpp + * + * Created on: 2021年9月21日 + * Author: yang + */ + +#include +#include +#include +using namespace std; +#define Yang_Mix_BUF_Len 4096 +YangAudioRenderData::YangAudioRenderData() { + m_cacheLen = 1024 * 4 * 10; + m_cache = new uint8_t[m_cacheLen]; + m_size = 0; + m_pos = 0; + + m_aecBufLen = 0; + m_renderLen=0; + + m_syn = NULL; + m_in_audioBuffers=NULL; + + m_hasAec=false; + m_aecBuf=NULL; + m_mixBuf=NULL; + // m_syn=NULL; + m_preProcess=NULL; + m_mixPos=0; + m_res.init(48000, 2, 48000, 2, 20); +} + +YangAudioRenderData::~YangAudioRenderData() { + yang_deleteA(m_cache); + yang_deleteA(m_mixBuf); + m_syn = NULL; + m_in_audioBuffers=NULL; + + m_preProcess=NULL; + +} + +void YangAudioRenderData::setInAudioBuffer(YangSynBuffer *pal) { + m_syn = pal; +} + +void YangAudioRenderData::initRender(int psample, int pchannel) { + m_res.initOut(psample, pchannel); +} + +void YangAudioRenderData::initPlay(int psample, int pchannel) { + m_res.initIn(psample, pchannel); +} + + + +void YangAudioRenderData::setAec(){ + + if(m_aecBuf==NULL) m_aecBuf=new uint8_t[Yang_Mix_BUF_Len]; + m_hasAec=true; +} +void YangAudioRenderData::setInAudioBuffers(std::vector *pal) { + if(m_in_audioBuffers) return; + m_in_audioBuffers = pal; + if(m_mixBuf==NULL){ + m_mixBuf=new uint8_t[960*8]; + } +} +bool YangAudioRenderData::hasData() { + if (!m_in_audioBuffers) + return 0; + for (int32_t i = 0; i < (int) m_in_audioBuffers->size(); i++) { + + if (m_in_audioBuffers->at(i)->getAudioSize() > 0) + return true; + } + + return false; +} + + +uint8_t* YangAudioRenderData::getAudioRef(YangFrame* pframe){ + if(m_syn) { + + return m_syn->getAudioRef(pframe); + } + if(m_in_audioBuffers&&hasData()){ + uint8_t *tmp = NULL; + for (size_t i = 0; i < m_in_audioBuffers->size(); i++) { + if (m_in_audioBuffers->at(i) && m_in_audioBuffers->at(i)->getAudioSize() > 0) { + //YangFrame* frame=m_in_audioBuffer->at(i)->getAudios(); + + tmp = m_in_audioBuffers->at(i)->getAudioRef(pframe); + if (tmp) { + // if (m_preProcess) m_preProcess->preprocess_run((short*) tmp); + if (i == 0) { + memcpy(m_mixBuf, tmp, pframe->nb); + } else { + m_mix.yangMix1((short*)m_mixBuf, (short*)tmp, pframe->nb, 128); + } + } + tmp = NULL; + + // if (m_in_audioBuffer->at(i)->size() > m_audioPlayCacheNum) m_in_audioBuffer->at(i)->resetIndex(); + } + } + return m_mixBuf; + } + return NULL; +} + +uint8_t* YangAudioRenderData::getAecAudioData(){ + if(m_renderLen=Yang_Mix_BUF_Len) { + memmove(m_aecBuf,m_aecBuf+m_mixPos,m_aecBufLen); + m_mixPos=0; + } + + uint8_t* p=m_aecBuf+m_mixPos; + m_aecBufLen-=m_res.getInBytes(); + m_mixPos+=m_res.getInBytes(); + m_renderLen=0; + return p; +} +void YangAudioRenderData::setRenderLen(int plen){ + m_renderLen+=(m_res.getInBytes()*plen)/m_res.getOutBytes(); +} +uint8_t* YangAudioRenderData::getAudioData(YangFrame* frame){ + + + uint8_t* tmp=getAudioRef(frame); + + if(m_hasAec&&tmp){ + if((m_mixPos+m_aecBufLen+m_res.getInBytes())>=Yang_Mix_BUF_Len) { + memmove(m_aecBuf,m_aecBuf+m_mixPos,m_aecBufLen); + m_mixPos=0; + } + + memcpy(m_aecBuf+m_mixPos+m_aecBufLen,tmp,m_res.getInBytes()); + m_aecBufLen+=m_res.getInBytes(); + } + + return tmp; +} + +void YangAudioRenderData::setAudioData(YangFrame* frame){ + uint8_t *buf =getAudioData(frame); + frame->payload=buf; + m_res.resample(frame); +} + +uint8_t* YangAudioRenderData::getRenderAudioData(int len) { + if ((m_pos + m_size + len) >= m_cacheLen) { + memmove(m_cache, m_cache + m_pos, m_size); + m_pos = 0; + } + + m_audioFrame.payload=NULL; + m_audioFrame.nb=0; + + if((m_size+(len<<1))0) { + if ((m_pos + m_size + m_audioFrame.nb) >= m_cacheLen) { + memmove(m_cache, m_cache + m_pos, m_size); + m_pos = 0; + } + memcpy(m_cache + m_pos + m_size, m_audioFrame.payload, m_audioFrame.nb); + m_size += m_audioFrame.nb; + } + + if (len > m_size) return NULL; + uint8_t *p = m_cache + m_pos; + m_pos += len; + m_size -= len; + return p; + +} + diff --git a/libyangrtc2/src/yangaudiodev/YangCaptureCallback.h b/libyangrtc2/src/yangaudiodev/YangCaptureCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..48fe3678eca381e67ab82ba6eb2d71a6861d3f7d --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/YangCaptureCallback.h @@ -0,0 +1,15 @@ + +#ifndef YANGCAPTURE_WIN_API_YANGCAPTURECALLBACK_H_ +#define YANGCAPTURE_WIN_API_YANGCAPTURECALLBACK_H_ +#include +class YangCaptureCallback{ +public: + YangCaptureCallback(){}; + virtual ~YangCaptureCallback(){}; + virtual void caputureAudioData(YangFrame* audioFrame)=0; +}; + + + + +#endif /* YANGCAPTURE_WIN_API_YANGCAPTURECALLBACK_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.cpp b/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2a75b345e26ab6a34da5d6eb7fe81ac6cdca437 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.cpp @@ -0,0 +1,580 @@ +#include +#ifndef _WIN32 +#include +#include +YangAlsaDeviceHandle::YangAlsaDeviceHandle(YangContext *pcontext) { + m_context = pcontext; + m_ahandle = new YangAudioCaptureHandle(pcontext); + m_audioPlayCacheNum = m_context->audio.audioPlayCacheNum; + aIndex = 0; + m_ret = 0; + m_size = 0; + m_loops = 0; + //m_in_audioBuffer = NULL; + m_buffer = NULL; + m_isInit = 0; + m_dev = NULL; + + m_frames = 1024; + m_channel = pcontext->audio.channel; + m_sample = pcontext->audio.sample; + m_preProcess = NULL; + m_audioData.initPlay(m_sample,m_channel); + m_audioData.initRender(m_sample,m_channel); + m_audioData.setInAudioBuffers(pcontext->streams.m_playBuffers); + //m_resample=NULL; +} +YangAlsaDeviceHandle::~YangAlsaDeviceHandle() { +// m_in_audioBuffer = NULL; + if (m_loops) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + alsa_device_close(); + m_preProcess = NULL; + yang_delete(m_buffer); + yang_delete(m_ahandle); +} +void YangAlsaDeviceHandle::setCatureStart() { + m_ahandle->isBuf = 1; +} +void YangAlsaDeviceHandle::setCatureStop() { + m_ahandle->isBuf = 0; +} +void YangAlsaDeviceHandle::setOutAudioBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangAlsaDeviceHandle::setPlayAudoBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->m_aecPlayBuffer = pbuffer; +} +void YangAlsaDeviceHandle::setAec(YangAecBase *paec) { + m_ahandle->m_aec = paec; +} +void YangAlsaDeviceHandle::setPreProcess(YangPreProcess *pp) { + m_preProcess = pp; + m_audioData.m_preProcess=pp; +} +int32_t YangAlsaDeviceHandle::alsa_device_open(char *device_name, + uint32_t rate, int32_t channels, int32_t period) { + int32_t dir; + int32_t err; + snd_pcm_hw_params_t *hw_params; + snd_pcm_sw_params_t *sw_params; + snd_pcm_uframes_t period_size = period; + snd_pcm_uframes_t buffer_size = 2 * period; + static snd_output_t *jcd_out; + m_dev = (YangAlsaDevice*) malloc( + (unsigned long) sizeof(YangAlsaDevice)); + if (!m_dev) + return ERROR_SYS_NoAudioDevice; + m_dev->device_name = (char*) malloc(1 + strlen(device_name)); + if (!m_dev->device_name) { + free(m_dev); + return ERROR_SYS_NoAudioDevice; + } + strcpy(m_dev->device_name, device_name); + m_dev->channels = channels; + m_dev->period = period; + err = snd_output_stdio_attach(&jcd_out, stdout, 0); + + if ((err = snd_pcm_open(&m_dev->capture_handle, m_dev->device_name, + SND_PCM_STREAM_CAPTURE, 0)) < 0) { + + yang_error("cannot open audio device %s (%s)", m_dev->device_name, + snd_strerror(err)); + catpureDeviceState = 0; + //_exit(1); + } + if (catpureDeviceState) { + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + + yang_error("cannot allocate hardware parameter structure (%s)", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_dev->capture_handle, hw_params)) + < 0) { + + yang_error("cannot initialize hardware parameter structure (%s)", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_dev->capture_handle, + hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + + yang_error("cannot set access type (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_dev->capture_handle, + hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { + + yang_error("cannot set sample format (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_rate_near(m_dev->capture_handle, + hw_params, &rate, 0)) < 0) { + + yang_error("cannot set sample rate (%s)", snd_strerror(err)); + _exit(1); + } + /* yang_error( "rate = %d", rate);*/ + + if ((err = snd_pcm_hw_params_set_channels(m_dev->capture_handle, + hw_params, channels)) < 0) { + + yang_error("cannot set channel count (%s)", snd_strerror(err)); + _exit(1); + } + + period_size = period; + dir = 0; + if ((err = snd_pcm_hw_params_set_period_size_near(m_dev->capture_handle, + hw_params, &period_size, &dir)) < 0) { + + yang_error("cannot set period size (%s)", snd_strerror(err)); + _exit(1); + } + +// if ((err = snd_pcm_hw_params_set_periods(m_dev->capture_handle, hw_params,2, 0)) < 0) { +// yang_error( "cannot set number of periods (%s)",snd_strerror(err)); +// _exit(1); +// } + + buffer_size = period_size * 2; + dir = 0; + if ((err = snd_pcm_hw_params_set_buffer_size_near(m_dev->capture_handle, + hw_params, &buffer_size)) < 0) { + + yang_error("cannot set buffer time (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params(m_dev->capture_handle, hw_params)) < 0) { + + yang_error("cannot set capture parameters (%s)", snd_strerror(err)); + _exit(1); + } + /*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/ + snd_pcm_hw_params_free(hw_params); + + if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) { + + yang_error("cannot allocate software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_current(m_dev->capture_handle, sw_params)) + < 0) { + + yang_error("cannot initialize software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_set_avail_min(m_dev->capture_handle, + sw_params, period)) < 0) { + + yang_error("cannot set minimum available count (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params(m_dev->capture_handle, sw_params)) < 0) { + + yang_error("cannot set software parameters (%s)", + snd_strerror(err)); + _exit(1); + } + } + + + + if ((err = snd_pcm_open(&m_dev->playback_handle, m_dev->device_name, + SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + + yang_error("cannot open audio device %s (%s)", m_dev->device_name, snd_strerror(err)); + playDeviceState=0; + } + if(playDeviceState){ + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + + yang_error("cannot allocate hardware parameter structure (%s)", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_dev->playback_handle, hw_params)) < 0) { + + yang_error("cannot initialize hardware parameter structure (%s)", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_dev->playback_handle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + + yang_error("cannot set access type (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_dev->playback_handle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) { + + yang_error("cannot set sample format (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_rate_near(m_dev->playback_handle, + hw_params, &rate, 0)) < 0) { + + yang_error("cannot set sample rate (%s)", snd_strerror(err)); + _exit(1); + } + /* yang_error( "rate = %d", rate);*/ + + if ((err = snd_pcm_hw_params_set_channels(m_dev->playback_handle, hw_params, + channels)) < 0) { + + yang_error("cannot set channel count (%s)", snd_strerror(err)); + _exit(1); + } + + period_size = period; + dir = 0; + if ((err = snd_pcm_hw_params_set_period_size_near(m_dev->playback_handle, + hw_params, &period_size, &dir)) < 0) { + + yang_error("cannot set period size (%s)", snd_strerror(err)); + _exit(1); + } +// if ((err = snd_pcm_hw_params_set_periods(m_dev->playback_handle, hw_params, 2, 0)) < 0) { +// yang_error( "cannot set number of periods (%s)", snd_strerror(err)); +// _exit(1); +// } + buffer_size = period_size * 2; + dir = 0; + if ((err = snd_pcm_hw_params_set_buffer_size_near(m_dev->playback_handle, + hw_params, &buffer_size)) < 0) { + + yang_error("cannot set buffer time (%s)", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params(m_dev->playback_handle, hw_params)) < 0) { + + yang_error("cannot set playback parameters (%s)", snd_strerror(err)); + _exit(1); + } + + /*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/ + snd_pcm_hw_params_free(hw_params); + + if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) { + + yang_error("cannot allocate software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_current(m_dev->playback_handle, sw_params)) + < 0) { + + yang_error("cannot initialize software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_set_avail_min(m_dev->playback_handle, + sw_params, period)) < 0) { + + yang_error("cannot set minimum available count (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_set_start_threshold(m_dev->playback_handle, + sw_params, period)) < 0) { + + yang_error("cannot set start mode (%s)", snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params(m_dev->playback_handle, sw_params)) < 0) { + + yang_error("cannot set software parameters (%s)", snd_strerror(err)); + _exit(1); + } + + snd_pcm_link(m_dev->capture_handle, m_dev->playback_handle); + if ((err = snd_pcm_prepare(m_dev->capture_handle)) < 0) { + + yang_error("cannot prepare audio interface for use (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_prepare(m_dev->playback_handle)) < 0) { + + yang_error("cannot prepare audio interface for use (%s)", + snd_strerror(err)); + _exit(1); + } + } + + if(catpureDeviceState){ + m_dev->readN = snd_pcm_poll_descriptors_count(m_dev->capture_handle); + m_dev->read_fd = (pollfd*) malloc(m_dev->readN * sizeof(*m_dev->read_fd)); + if (snd_pcm_poll_descriptors(m_dev->capture_handle, m_dev->read_fd, + m_dev->readN) != m_dev->readN) { + + yang_error("cannot obtain capture file descriptors (%s)", + snd_strerror(err)); + _exit(1); + } + } + if(playDeviceState){ + m_dev->writeN = snd_pcm_poll_descriptors_count(m_dev->playback_handle); + m_dev->write_fd = (pollfd*) malloc(m_dev->writeN * sizeof(*m_dev->read_fd)); + if (snd_pcm_poll_descriptors(m_dev->playback_handle, m_dev->write_fd, + m_dev->writeN) != m_dev->writeN) { + + yang_error("cannot obtain playback file descriptors (%s)", + snd_strerror(err)); + _exit(1); + } + } + + + if(!catpureDeviceState&&!playDeviceState){ + return ERROR_SYS_NoAudioDevice; + }else if(!catpureDeviceState){ + return ERROR_SYS_NoAudioCaptureDevice; + }else if(!playDeviceState){ + return ERROR_SYS_NoAudioPlayDevice; + } + + + return Yang_Ok; +} + +void YangAlsaDeviceHandle::alsa_device_close() { + if (m_dev) { + snd_pcm_close(m_dev->capture_handle); + snd_pcm_close(m_dev->playback_handle); + free(m_dev->device_name); + free(m_dev); + m_dev = NULL; + } +} + +int32_t YangAlsaDeviceHandle::alsa_device_read(short *pcm, int32_t len) { + + if ((m_ret = snd_pcm_readi(m_dev->capture_handle, pcm, len)) != len) { + if (m_ret < 0) { + if (m_ret == -EPIPE) { + + yang_error("An overrun has occured, reseting capture"); + } else { + + yang_error("read from audio interface failed (%s)", + snd_strerror(m_ret)); + //m_ret = snd_pcm_recover(m_dev->capture_handle, m_ret, 0); + } + if ((m_ret = snd_pcm_prepare(m_dev->capture_handle)) < 0) { + + yang_error("cannot prepare audio interface for use (%s)", + snd_strerror(m_ret)); + } + if ((m_ret = snd_pcm_start(m_dev->capture_handle)) < 0) { + + yang_error("cannot prepare audio interface for use (%s)", + snd_strerror(m_ret)); + } + + } else { + + yang_error( + "Couldn't read as many samples as I wanted (%d instead of %d)", + m_ret, len); + } + return 1; + } + return Yang_Ok; +} + +int32_t YangAlsaDeviceHandle::alsa_device_write(const short *pcm, int32_t len) { + + if ((m_ret = snd_pcm_writei(m_dev->playback_handle, pcm, len)) != len) { + if (m_ret < 0) { + if (m_ret == -EPIPE) { + // yang_usleep(1000); + yang_error("An underrun has occured, reseting playback, len=%d",len); + } else { + yang_error("write to audio interface failed (%s)", + snd_strerror(m_ret)); + } + if ((m_ret = snd_pcm_prepare(m_dev->playback_handle)) < 0) { + yang_error("cannot prepare audio interface for use (%s)", + snd_strerror(m_ret)); + } + } else { + yang_error( + "Couldn't write as many samples as I wanted (%d instead of %d)", + m_ret, len); + } + + return 1; + } + return Yang_Ok; +} + +int32_t YangAlsaDeviceHandle::alsa_device_capture_ready(struct pollfd *pfds, + uint32_t nfds) { + unsigned short revents = 0; + + if ((m_ret = snd_pcm_poll_descriptors_revents(m_dev->capture_handle, pfds, + m_dev->readN, &revents)) < 0) { + + yang_error("error in alsa_device_capture_ready: %s", + snd_strerror(m_ret)); + return pfds[0].revents & POLLIN; + } + + return revents & POLLIN; +} + +int32_t YangAlsaDeviceHandle::alsa_device_playback_ready(struct pollfd *pfds, + uint32_t nfds) { + unsigned short revents = 0; + //int32_t err; + if ((m_ret = snd_pcm_poll_descriptors_revents(m_dev->playback_handle, + pfds + m_dev->readN, m_dev->writeN, &revents)) < 0) { + yang_error("error in alsa_device_playback_ready: %s", + snd_strerror(m_ret)); + return pfds[1].revents & POLLOUT; + } + //cerr << (revents & POLLERR) << endl; + return revents & POLLOUT; +} + +int32_t YangAlsaDeviceHandle::alsa_device_nfds() { + return m_dev->writeN + m_dev->readN; +} + +void YangAlsaDeviceHandle::alsa_device_getfds(struct pollfd *pfds, + uint32_t nfds) { + int32_t i; + //assert(nfds >= m_dev->writeN + m_dev->readN); + for (i = 0; i < m_dev->readN; i++) + pfds[i] = m_dev->read_fd[i]; + for (i = 0; i < m_dev->writeN; i++) + pfds[i + m_dev->readN] = m_dev->write_fd[i]; +} +void YangAlsaDeviceHandle::setInAudioBuffer(vector *pal) { + //m_in_audioBuffer = pal; +} +void YangAlsaDeviceHandle::stopLoop() { + m_loops = 0; +} + +void YangAlsaDeviceHandle::run() { + startLoop(); +} + + + +int32_t YangAlsaDeviceHandle::init() { + if (m_isInit) + return Yang_Ok; + if (m_context->audio.usingMono) { + m_channel = 1; + m_sample = 16000; + } + + m_frames=m_sample*m_channel/50; + if (m_preProcess) { + m_preProcess->init(m_frames, m_sample, m_channel); + } + + int32_t ret = alsa_device_open((char*)"default", m_sample, m_channel, m_frames); + + m_size = m_frames * 2 * m_channel; // 2 bytes/sample, 2 channels + m_buffer = (uint8_t*) malloc(m_size); + m_isInit = 1; + return ret; +} + +void YangAlsaDeviceHandle::startLoop() { + + m_loops = 1; + int32_t nfds = alsa_device_nfds(); + + + pollfd *pfds = (pollfd*) malloc(sizeof(*pfds) * nfds); + alsa_device_getfds(pfds, nfds); + int32_t audiolen = m_frames * m_channel * 2; + + short* pcm_short=new short[audiolen/2]; + + uint8_t *pcm_write = (uint8_t*)pcm_short;//new uint8_t[audiolen]; + uint8_t *tmp = NULL; + + int32_t readStart = 0; + YangFrame frame; + memset(&frame,0,sizeof(YangFrame)); + while (m_loops) { + + poll(pfds, nfds, -1); + if (playDeviceState&&alsa_device_playback_ready(pfds, nfds)) { + + tmp=m_audioData.getRenderAudioData(audiolen); + if(tmp){ + memcpy(pcm_write, tmp, audiolen); + if (!readStart) readStart = 1; + }else{ + memset(pcm_write, 0, audiolen); + } + /** + if (m_in_audioBuffer && hasData()) { + for (size_t i = 0; i < m_in_audioBuffer->size(); i++) { + if (m_in_audioBuffer->at(i) + && m_in_audioBuffer->at(i)->size() > 0) { + tmp = m_in_audioBuffer->at(i)->getAudios(&frame); + if (tmp) { + if (m_preProcess) + m_preProcess->preprocess_run((short*) tmp); + if (i == 0) { + memcpy(pcm_write, tmp, audiolen); + } else { + m_mix.yangMix1(pcm_write, tmp, audiolen, 128); + } + } + tmp = NULL; + + if (m_in_audioBuffer->at(i)->size() + > m_audioPlayCacheNum) + m_in_audioBuffer->at(i)->resetIndex(); + } + } + if (!readStart) readStart = 1; + }**/ + + alsa_device_write( pcm_short, m_frames); + if (readStart) + m_ahandle->putEchoPlay(pcm_short,audiolen); + } + if (catpureDeviceState&&alsa_device_capture_ready(pfds, nfds)) { + alsa_device_read((short*) m_buffer, m_frames); + if (readStart) + m_ahandle->putEchoBuffer(m_buffer,audiolen); + else + m_ahandle->putBuffer1(m_buffer,audiolen); + + } + } + free(pfds); + pfds = NULL; + yang_deleteA(pcm_short); + pcm_write=NULL; + +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.h b/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..254824e831a1d84efdf05569382e54eadcbd93ee --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAlsaDeviceHandle.h @@ -0,0 +1,80 @@ + +#ifndef Yang_ALSA_DEVICE_H1 +#define Yang_ALSA_DEVICE_H1 + +#ifndef _WIN32 +#include +#include +//#include +#include +//#include +#include +#include +#include +struct YangAlsaDevice { + char *device_name; + int32_t channels; + int32_t period; + snd_pcm_t *capture_handle; + snd_pcm_t *playback_handle; + int32_t readN, writeN; + struct pollfd *read_fd, *write_fd; +}; + +class YangAlsaDeviceHandle: public YangAudioCapture { +public: + YangAlsaDeviceHandle(YangContext *pcontext); + ~YangAlsaDeviceHandle(); + int32_t alsa_device_open(char *device_name, uint32_t rate, + int32_t channels, int32_t period); +public: + YangAudioCaptureHandle *m_ahandle; + int32_t init(); + void setInAudioBuffer(vector *pal); + void setPreProcess(YangPreProcess *pp); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setAec(YangAecBase *paec); + +protected: + void run(); + + void startLoop(); + + void stopLoop(); + YangAudioRenderData m_audioData; +private: + //YangResample *m_resample; + //vector *m_in_audioBuffer; + uint8_t *m_buffer; + int32_t m_isInit; + int32_t m_ret; + YangAudioMix m_mix; + YangPreProcess *m_preProcess; + //int32_t hasData(); + + void alsa_device_close(); + int32_t alsa_device_read(short *pcm, int32_t len); + int32_t alsa_device_write(const short *pcm, int32_t len); + int32_t alsa_device_capture_ready(struct pollfd *pfds, uint32_t nfds); + int32_t alsa_device_playback_ready(struct pollfd *pfds, uint32_t nfds); + //void alsa_device_start(); + int32_t alsa_device_nfds(); + void alsa_device_getfds(struct pollfd *pfds, uint32_t nfds); + +private: + YangAlsaDevice *m_dev; + int32_t playDeviceState=1; + int32_t catpureDeviceState = 1; + int32_t m_size; + int32_t m_loops; + int32_t m_channel; + uint32_t m_sample; + snd_pcm_uframes_t m_frames; + int32_t m_audioPlayCacheNum; +}; + +#endif +#endif diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.cpp b/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb0719da82cf684657629e81ab59d4ea54a178fa --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.cpp @@ -0,0 +1,361 @@ +/* + * YangAlsaHandle.cpp + * + * Created on: 2019年9月25日 + * Author: yang + */ + +#include +#ifndef _WIN32 + + +#include "stdlib.h" +#include +#include "memory.h" +#include "malloc.h" +YangAlsaHandle::YangAlsaHandle(YangContext *pcontext) //:YangAudioCapture(pcontext) + { + + m_context = pcontext; + m_ahandle = new YangAudioCaptureHandle(pcontext); + m_writeInit = 0, m_writeRet = 0; + m_readInit = 0; + aIndex = 0; + m_size = 0; + m_loops = 0; + m_readHandle = NULL; + m_writeHandle = NULL; + m_in_audioBuffer = NULL; + m_buffer = NULL; + m_frames = 1024; + m_channel = 2; + m_sample = 44100; +} + +YangAlsaHandle::~YangAlsaHandle() { + + + yang_delete(m_buffer); + yang_delete(m_ahandle); +} +void YangAlsaHandle::setCatureStart(){ + m_ahandle->isBuf=1; +} +void YangAlsaHandle::setCatureStop(){ + m_ahandle->isBuf=0; +} +void YangAlsaHandle::setOutAudioBuffer(YangAudioBuffer *pbuffer){ + m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangAlsaHandle::setPlayAudoBuffer(YangAudioBuffer *pbuffer){ + m_ahandle->m_aecPlayBuffer=pbuffer; +} +void YangAlsaHandle::setAec(YangAecBase *paec){ + m_ahandle->m_aec=paec; +} +void YangAlsaHandle::setPreProcess(YangPreProcess *pp) { + //m_preProcess = pp; +} + +int32_t YangAlsaHandle::init() { + if (m_context->audio.usingMono) { + m_frames = 320; + m_channel = 1; + m_sample = 16000; + } else { + m_frames = 1024; + } + initRead(); + initWrite(); + return Yang_Ok; +} + +void YangAlsaHandle::setInAudioBuffer(vector *pal) { + m_in_audioBuffer = pal; +} +void YangAlsaHandle::initWrite() { + if (m_writeInit == 1) + return; + + uint32_t val = 0; + int32_t dir = 0; + snd_pcm_hw_params_t *hw_params; + int32_t err = 0; + if ((err = snd_pcm_open(&m_writeHandle, "default", SND_PCM_STREAM_PLAYBACK, + 0)) < 0) { + + yang_error( "unable to open pcm device: %s\n", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + yang_error("cannot allocate hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_writeHandle, hw_params)) < 0) { + + yang_error( + "cannot initialize hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_writeHandle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + + yang_error( "cannot set access type (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_writeHandle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) { + + yang_error( "cannot set sample format (%s)\n", + snd_strerror(err)); + _exit(1); + } + + val = m_sample; + if ((err = snd_pcm_hw_params_set_rate_near(m_writeHandle, hw_params, &val, + 0)) < 0) { + + yang_error( "cannot set sample rate (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_channels(m_writeHandle, hw_params, + m_channel)) < 0) { + + yang_error( "cannot set channel count (%s)\n", + snd_strerror(err)); + _exit(1); + } + + //m_frames = m_frames; + if ((err = snd_pcm_hw_params_set_period_size_near(m_writeHandle, hw_params, + &m_frames, &dir)) < 0) { + + yang_error( "cannot set period size (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params(m_writeHandle, hw_params)) < 0) { + + yang_error( "cannot set write parameters (%s)\n", + snd_strerror(err)); + _exit(1); + } + + snd_pcm_hw_params_free(hw_params); + hw_params=NULL; + m_size = m_frames * 2 * m_channel; // 2 bytes/sample, 2 channels +//mw1.start("/home/yang/bmp/out1.wav"); + m_writeInit = 1; + +} +void YangAlsaHandle::initRead() { + if (m_readInit == 1) + return; + int32_t dir = 0; + snd_pcm_hw_params_t *hw_params; + int32_t err = 0; + if ((err = snd_pcm_open(&m_readHandle, "default", SND_PCM_STREAM_CAPTURE, 0)) + < 0) { + + yang_error( "unable to open pcm device: %s\n", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + + yang_error( + "cannot allocate hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_readHandle, hw_params)) < 0) { + + yang_error( + "cannot initialize hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_readHandle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + + yang_error( "cannot set access type (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_readHandle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) { + + yang_error( "cannot set sample format (%s)\n", + snd_strerror(err)); + _exit(1); + } + + // val=t_sample;//44100; + if ((err = snd_pcm_hw_params_set_rate_near(m_readHandle, hw_params, + &m_sample, 0)) < 0) { + + yang_error( "cannot set sample rate (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_channels(m_readHandle, hw_params, + m_channel)) < 0) { + + yang_error( "cannot set channel count (%s)\n", + snd_strerror(err)); + _exit(1); + } + + // m_frames=1024; + if ((err = snd_pcm_hw_params_set_period_size_near(m_readHandle, hw_params, + &m_frames, &dir)) < 0) { + + yang_error( "cannot set period size (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params(m_readHandle, hw_params)) < 0) { + + yang_error( "cannot set read parameters (%s)\n", + snd_strerror(err)); + _exit(1); + } + //int32_t dir=0; + // snd_pcm_uframes_t t1=0,t2=0; + //snd_pcm_hw_params_get_period_size(hw_params, &t1, &dir); + //snd_pcm_hw_params_get_buffer_size(hw_params, &t2); + + snd_pcm_hw_params_free(hw_params); + hw_params=NULL; + m_size = m_frames * 2 * m_channel; // 2 bytes/sample, 2 channels + m_buffer = (uint8_t*) malloc(m_size); + m_readInit = 1; +} +//CMyMakeWave mw1; +void YangAlsaHandle::startLoop() { + // loops = 5000000 / val; + m_loops = 1; + int32_t status = 0; + // mw1.start("/home/yang/bmp/ttt.wav"); + int32_t audiolen = m_frames * m_channel * 2; + + if ((status = snd_pcm_prepare(m_readHandle)) < 0) { + + yang_error( + "cannot prepare audio interface for use (%s)\n", + snd_strerror(status)); + _exit(1); + } + uint8_t *pcm = new uint8_t[audiolen]; + uint8_t *tmp = NULL; + int32_t readLen = 0; + + YangFrame frame; + memset(&frame,0,sizeof(YangFrame)); + while (m_loops == 1) { + readLen = 0; + if (hasData() > 0) { + + memset(pcm, 0, audiolen); + for (size_t i = 0; i < m_in_audioBuffer->size(); i++) { + tmp = m_in_audioBuffer->at(i)->getAudios(&frame); + if (tmp) + m_mix.yangMix1(pcm, tmp, audiolen, 128); + } + status = snd_pcm_writei(m_writeHandle, pcm, m_frames); + m_ahandle->putEchoPlay((short*) pcm,audiolen); + readLen = audiolen; + if (status < 0) { + if (status == -EPIPE) { + // EPIPE means overrun + + yang_usleep(1000); + snd_pcm_prepare(m_writeHandle); + continue; + //snd_pcm_prepare(m_handle); + } + status = snd_pcm_recover(m_writeHandle, status, 0); + if (status < 0) { + + yang_error( + "ALSA write failed (unrecoverable): %s\n", + snd_strerror(status)); + } + + } + + } + if ((status = snd_pcm_readi(m_readHandle, m_buffer, m_frames)) + != m_frames) { + + yang_error( + "read from audio interface failed (%s)\n", + snd_strerror(status)); + } + if (status == -EAGAIN) { + snd_pcm_wait(m_readHandle, 2 * m_channel); + status = 0; + } else if (status < 0) { + status = snd_pcm_recover(m_readHandle, status, 0); + if (status < 0) { + + yang_error( "ALSA read failed (unrecoverable): %s\n", + snd_strerror(status)); + } + continue; + } + if (readLen > 0) + m_ahandle->putEchoBuffer(m_buffer,audiolen); + else + m_ahandle->putBuffer1(m_buffer,audiolen); + + // rc = write(1, m_buffer, m_size); + //zm_ahandle->putBuffer(m_buffer); + //mw1.write(m_buffer,4096); + + } + //mw1.stop(); + printf("\n********************AudioCapture stop.......\n"); + snd_pcm_drain(m_readHandle); + snd_pcm_close(m_readHandle); + snd_pcm_drain(m_writeHandle); + snd_pcm_close(m_writeHandle); + free(m_buffer); + m_readHandle = NULL; + m_writeHandle = NULL; + //m_params=NULL; + m_buffer = NULL; +} + +void YangAlsaHandle::stopLoop() { + m_loops = 0; +} + +void YangAlsaHandle::run() { + startLoop(); +} + +int32_t YangAlsaHandle::hasData() { + if(!m_in_audioBuffer) return 0; + for (int32_t i = 0; i < (int) m_in_audioBuffer->size(); i++) { + if (m_in_audioBuffer->at(i)->size() > 0) + return 1; + } + return 0; +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.h b/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..3f7bdc47d74a4e2ad34e733970dd94605d8bbab4 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAlsaHandle.h @@ -0,0 +1,66 @@ +/* + * YangAlsaHandle.h + * + * Created on: 2019年9月25日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YANGALSAHANDLE_H_ +#define YANGCAPTURE_SRC_YANGALSAHANDLE_H_ + + +#ifndef _WIN32 +#include +#include "yangavutil/audio/YangAudioMix.h" +#include "yangavutil/audio/YangPreProcess.h" +#include "yangutil/sys/YangThread.h" +#include +#include +#include + + +class YangAlsaHandle: public YangAudioCapture { +public: + YangAlsaHandle(YangContext *pcontext); + virtual ~YangAlsaHandle(); +public: + + int32_t aIndex; + YangAudioCaptureHandle *m_ahandle; + void initRead(); + void initWrite(); + //void stop(); + void setPreProcess(YangPreProcess *pp); + int32_t init(); + void setInAudioBuffer(vector *pal); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setAec(YangAecBase *paec); + //Int32 audio_setparams(Alsa_Env *pEnv); +protected: + void run(); + void startLoop(); + void stopLoop(); +private: + //YangContext *m_context; + int32_t m_readInit; + int32_t m_writeInit, m_writeRet; + vector *m_in_audioBuffer; + + int32_t m_size; + int32_t m_loops; + int32_t m_channel; + uint32_t m_sample; + snd_pcm_uframes_t m_frames; + uint8_t *m_buffer; + snd_pcm_t *m_readHandle; + snd_pcm_t *m_writeHandle; + //YangLog *m_log; + YangAudioMix m_mix; + int32_t hasData(); + //snd_pcm_hw_params_t *m_params; +}; +#endif +#endif /* YANGCAPTURE_SRC_YANGALSAHANDLE_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.cpp b/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ebd8a294948de139afdfa2dec724b85b29ca00b --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.cpp @@ -0,0 +1,231 @@ + +/* + * YangAudioCaptureImplImpl.cpp + * + * Created on: 2019年8月30日 + * Author: yang + */ +#ifndef _WIN32 +#include +#include +#include +#include "stdlib.h" +#include +#include "memory.h" +#include "malloc.h" + +YangAudioCaptureImpl::YangAudioCaptureImpl(YangContext *pcontext) //:YangAudioCapture(pcontext) + { + + m_context = pcontext; + m_ahandle = new YangAudioCaptureHandle(pcontext); + aIndex = 0; + m_size = 0; + m_loops = 0; + m_handle = NULL; + m_buffer = NULL; + + m_channel = pcontext->audio.channel; + m_sample = pcontext->audio.sample; + if(pcontext->audio.audioEncoderType==Yang_AED_AAC){ + m_frames = 1024; + }else{ + m_frames=m_sample/50; + } + + + onlySupportSingle = 0; + +} + +YangAudioCaptureImpl::~YangAudioCaptureImpl() { + if (m_loops) { + stop(); + while (m_isStart) { + yang_usleep(500); + } + } + if (m_handle) { + //snd_pcm_drain(m_handle); + snd_pcm_close(m_handle); + m_handle = NULL; + } + //m_context = NULL; + //m_log = NULL; + yang_delete(m_buffer); + yang_delete(m_ahandle); +} +void YangAudioCaptureImpl::setCatureStart() { + m_ahandle->isBuf = 1; +} +void YangAudioCaptureImpl::setCatureStop() { + m_ahandle->isBuf = 0; +} +void YangAudioCaptureImpl::setOutAudioBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangAudioCaptureImpl::setPlayAudoBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->m_aecPlayBuffer = pbuffer; +} +void YangAudioCaptureImpl::setAec(YangAecBase *paec) { + m_ahandle->m_aec = paec; +} +void YangAudioCaptureImpl::setInAudioBuffer(vector *pal) { + +} +void YangAudioCaptureImpl::setPreProcess(YangPreProcess *pp) { + +} + + +int32_t YangAudioCaptureImpl::init() { + int32_t dir = 0; + snd_pcm_hw_params_t *hw_params; + int32_t err = 0; + char device_name[64] = { 0 }; + if (m_context->audio.aIndex > -1) + sprintf(device_name, "hw:%d,%d", m_context->audio.aIndex, m_context->audio.aSubIndex); + //printf("\nindex==%d,audioHw===%s", m_para->aIndex, device_name); + if ((err = snd_pcm_open(&m_handle, + m_context->audio.aIndex == -1 ? "default" : device_name, + SND_PCM_STREAM_CAPTURE, 0)) < 0) { + + yang_error("unable to open pcm device: %s\n", snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + + yang_error("cannot allocate hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_handle, hw_params)) < 0) { + + yang_error("cannot initialize hardware parameter structure (%s)\n", + snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_handle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + + yang_error("cannot set access type (%s)\n", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_handle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) { + + yang_error("cannot set sample format (%s)\n", snd_strerror(err)); + _exit(1); + } + + // val=t_sample;//44100; + if ((err = snd_pcm_hw_params_set_rate_near(m_handle, hw_params, &m_sample, + 0)) < 0) { + + yang_error("cannot set sample rate (%s)\n", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params_set_channels(m_handle, hw_params, m_channel)) + < 0) { + yang_error("cannot set double channel (%s)\n", snd_strerror(err)); + err = snd_pcm_hw_params_set_channels(m_handle, hw_params, 1); + if (err < 0) { + yang_error("cannot set single channel (%s)\n", snd_strerror(err)); + _exit(1); + } + onlySupportSingle = 1; + //_exit(1); + } + + if ((err = snd_pcm_hw_params_set_period_size_near(m_handle, hw_params, + &m_frames, &dir)) < 0) { + + yang_error("cannot set period size (%s)\n", snd_strerror(err)); + _exit(1); + } + + if ((err = snd_pcm_hw_params(m_handle, hw_params)) < 0) { + + yang_error("cannot set parameters (%s)\n", snd_strerror(err)); + _exit(1); + } + //int32_t dir=0; + // snd_pcm_uframes_t t1=0,t2=0; + //snd_pcm_hw_params_get_period_size(hw_params, &t1, &dir); + //snd_pcm_hw_params_get_buffer_size(hw_params, &t2); + + snd_pcm_hw_params_free(hw_params); + m_size = m_frames * 2 * m_channel; // 2 bytes/sample, 2 channels + m_buffer = (uint8_t*) malloc(m_size); + return Yang_Ok; +} + +void YangAudioCaptureImpl::startLoop() { + // loops = 5000000 / val; + m_loops = 1; + unsigned long status = 0; +// YangMakeWave mw1; +// mw1.start(0,"/home/yang/bmp/rec1.wav"); + + uint8_t *tmp = NULL; + if (onlySupportSingle) { + tmp = new uint8_t[m_frames * 2 * 2]; + } + if ((status = snd_pcm_prepare(m_handle)) < 0) { + + yang_error("cannot prepare audio interface for use (%s)\n", + snd_strerror(status)); + _exit(1); + } + int32_t audiolen = m_frames * m_channel * 2; + while (m_loops == 1) { + if ((status = snd_pcm_readi(m_handle, m_buffer, m_frames)) + != m_frames) { + + yang_error("read from audio interface failed (%s)\n", + snd_strerror(status)); + // exit (1); + } + if (status == -EAGAIN) { + //snd_pcm_wait(m_handle, 2 * m_channel); + yang_error("An overrun has occured: %s\n", snd_strerror(status)); + status = 0; + } else if (status < 0) { + status = snd_pcm_recover(m_handle, status, 0); + if (status < 0) { + yang_error("ALSA read failed (unrecoverable): %s\n", + snd_strerror(status)); + //return; + } + continue; + } + + if (onlySupportSingle) { + MonoToStereo((int16_t*) m_buffer, (int16_t*) tmp, m_frames); + m_ahandle->putBuffer1(tmp,audiolen); + } else { + m_ahandle->putBuffer1(m_buffer,audiolen); + } + //mw1.write(m_buffer,4096); + + } + //mw1.stop(); + + //snd_pcm_drain(m_handle); + + snd_pcm_close(m_handle); + yang_deleteA(tmp); + free(m_buffer); + m_handle = NULL; + m_buffer = NULL; + +} + +void YangAudioCaptureImpl::stopLoop() { + m_loops = 0; +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.h b/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..aa2f3ca3d84eb9be9b2de3624adedc595cec0487 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAudioCaptureImpl.h @@ -0,0 +1,53 @@ +/* + * YangAudioCaptureImpl.h + * + * Created on: 2019年8月30日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YANGAUDIOCAPTUREIMPL_H_ +#define YANGCAPTURE_SRC_YANGAUDIOCAPTUREIMPL_H_ +#include +#include +#include "yangavutil/audio/YangPreProcess.h" +#ifndef _WIN32 +#include +#include +using namespace std; +//#define REQ_BUF_NUM 4 //申请的缓冲区个数,最多5个,缓冲区太少可能会导致图像有间断 + +class YangAudioCaptureImpl: public YangAudioCapture { +public: + YangAudioCaptureImpl(YangContext *pcontext); + ~YangAudioCaptureImpl(); +public: + YangAudioCaptureHandle *m_ahandle; + int32_t init(); + void setPreProcess(YangPreProcess *pp); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setInAudioBuffer(vector *pal); + void setAec(YangAecBase *paec); + + +protected: + void startLoop(); + void stopLoop(); + //int32_t single2Double(short *pData, short* dData,int32_t nSize); + +private: + //YangContext *m_context; + int32_t m_size; + int32_t m_loops; + int32_t m_channel; + uint32_t m_sample; + snd_pcm_uframes_t m_frames; + uint8_t *m_buffer; + snd_pcm_t *m_handle; + int32_t onlySupportSingle; + +}; +#endif +#endif /* YANGCAPTURE_SRC_YANGAUDIOCAPTUREIMPL_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.cpp b/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bab6ae2534a9c9a198531397ac7be54dd2892cda --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.cpp @@ -0,0 +1,228 @@ +/* + * YangAudioPlayAlsa.cpp + * + * Created on: 2020年9月4日 + * Author: yang + */ + +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +YangAudioPlayAlsa::YangAudioPlayAlsa(YangContext *pcontext):YangAudioPlay(pcontext){ + m_handle = NULL; + m_loops = 0; + ret = 0; + m_frames = 0; + m_isStart = 0; + m_contextt = 0; +} + +YangAudioPlayAlsa::~YangAudioPlayAlsa() { + + closeAudio(); +} + +int YangAudioPlayAlsa::init() { + if (m_contextt == 1) + return Yang_Ok; + + m_frames = m_context->audio.sample / 50; + + uint32_t val = 0; + int32_t dir = 0; + snd_pcm_hw_params_t *hw_params; + snd_pcm_sw_params_t *sw_params; + int32_t err = 0; + if ((err = snd_pcm_open(&m_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) + < 0) { + fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(err)); + exit(1); + } + if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { + fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n", + snd_strerror(err)); + exit(1); + } + + if ((err = snd_pcm_hw_params_any(m_handle, hw_params)) < 0) { + fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n", + snd_strerror(err)); + exit(1); + } + + if ((err = snd_pcm_hw_params_set_access(m_handle, hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + fprintf(stderr, "cannot set access type (%s)\n", snd_strerror(err)); + exit(1); + } + + if ((err = snd_pcm_hw_params_set_format(m_handle, hw_params, + SND_PCM_FORMAT_S16_LE)) < 0) { + fprintf(stderr, "cannot set sample format (%s)\n", snd_strerror(err)); + exit(1); + } + + val = m_sample; + if ((err = snd_pcm_hw_params_set_rate_near(m_handle, hw_params, &val, 0)) + < 0) { + fprintf(stderr, "cannot set sample rate (%s)\n", snd_strerror(err)); + exit(1); + } + + if ((err = snd_pcm_hw_params_set_channels(m_handle, hw_params, m_channel)) + < 0) { + fprintf(stderr, "cannot set channel count (%s)\n", snd_strerror(err)); + exit(1); + } + + //m_frames = m_frames; + if ((err = snd_pcm_hw_params_set_period_size_near(m_handle, hw_params, + &m_frames, &dir)) < 0) { + fprintf(stderr, "cannot set period size (%s)\n", snd_strerror(err)); + exit(1); + } + snd_pcm_uframes_t buffer_size = m_frames * 2; + dir = 0; + if ((err = snd_pcm_hw_params_set_buffer_size_near(m_handle, + hw_params, &buffer_size)) < 0) { + + yang_error("cannot set buffer time (%s)", snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_hw_params(m_handle, hw_params)) < 0) { + fprintf(stderr, "cannot set parameters (%s)\n", snd_strerror(err)); + exit(1); + } + + snd_pcm_hw_params_free(hw_params); + //m_size = m_frames * 2 * m_channel; // 2 bytes/sample, 2 channels + if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) { + + yang_error("cannot allocate software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_current(m_handle, sw_params)) + < 0) { + + yang_error("cannot initialize software parameters structure (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_set_avail_min(m_handle, + sw_params, m_frames)) < 0) { + + yang_error("cannot set minimum available count (%s)", + snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params_set_start_threshold(m_handle, + sw_params, m_frames)) < 0) { + + yang_error("cannot set start mode (%s)", snd_strerror(err)); + _exit(1); + } + if ((err = snd_pcm_sw_params(m_handle, sw_params)) < 0) { + + yang_error("cannot set software parameters (%s)", snd_strerror(err)); + _exit(1); + } + m_audioData.initRender(m_sample,m_channel); + m_contextt = 1; + return Yang_Ok; + +} + +void YangAudioPlayAlsa::closeAudio() { + + if (m_handle) { + //snd_pcm_drain(m_handle); + snd_pcm_close(m_handle); + m_handle = NULL; + } + +} + +void YangAudioPlayAlsa::stopLoop() { + m_loops = 0; +} + +void YangAudioPlayAlsa::startLoop() { + + m_loops = 1; + unsigned long status = 0; + uint8_t *pcm = new uint8_t[4096*2]; + memset(pcm,0,4096*2); + YangAutoFreeA(uint8_t,pcm); + uint8_t *tmp = NULL; + if ((status = snd_pcm_prepare(m_handle)) < 0) { + fprintf(stderr, "cannot prepare audio interface for use (%s)\n", + snd_strerror(status)); + exit(1); + } + YangFrame frame; + memset(&frame,0,sizeof(YangFrame)); + int err = 0; + struct pollfd *ufds; + int count = snd_pcm_poll_descriptors_count(m_handle); + ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * count); + if ((err = snd_pcm_poll_descriptors(m_handle, ufds, count)) < 0) { + yang_error("Unable to obtain poll descriptors for playback: %s\n", + snd_strerror(err)); + return; + } + int32_t audiolen = m_frames * m_channel * 2; + while (m_loops == 1) { + unsigned short revents = 0; + status=0; + //int32_t err; + err = snd_pcm_poll_descriptors_revents(m_handle, ufds, count, &revents); + if (err < 0) { + yang_error("error in alsa_device_playback_ready: %s",snd_strerror(err)); + return; + } + if (revents & POLLOUT) { + frame.nb=0; + frame.payload=NULL; + tmp =m_audioData.getRenderAudioData(audiolen); + + if (tmp){ + status = snd_pcm_writei(m_handle, tmp, m_frames); + }else{ + status = snd_pcm_writei(m_handle, pcm, m_frames); + } + + if (status !=m_frames) { + if (status == -EPIPE) { + // EPIPE means overrun + yang_warn("underrun occurred"); + yang_usleep(1000); + snd_pcm_prepare(m_handle); + continue; + //snd_pcm_prepare(m_handle); + } + status = snd_pcm_recover(m_handle, status, 0); + if (status < 0) { + yang_error("ALSA write failed (unrecoverable): %s", snd_strerror(status)); + } + + } + }//endif + + } + + //snd_pcm_drain(m_handle); + snd_pcm_close(m_handle); + tmp = NULL; + + if(ufds) free(ufds); + m_handle = NULL; + +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.h b/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.h new file mode 100644 index 0000000000000000000000000000000000000000..eb0336030d708df2cb472ba9b409363c10787140 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/linux/YangAudioPlayAlsa.h @@ -0,0 +1,45 @@ +/* + * YangAudioPlayAlsa.h + * + * Created on: 2020年9月4日 + * Author: yang + */ + +#ifndef YANGPLAYER_SRC_YANGAUDIOPLAYALSA_H_ +#define YANGPLAYER_SRC_YANGAUDIOPLAYALSA_H_ + +#ifndef _WIN32 +#include + + +#include + +class YangAudioPlayAlsa:public YangAudioPlay{ +public: + YangAudioPlayAlsa(YangContext *pcontext); + ~YangAudioPlayAlsa(); + + int init(); + + + +protected: + void startLoop(); + void stopLoop(); + +private: + int32_t m_loops; + +private: + + int32_t m_contextt; + snd_pcm_t *m_handle; + snd_pcm_uframes_t m_frames; + + + void closeAudio(); + int32_t ret; + +}; +#endif +#endif /* YANGPLAYER_SRC_YANGAUDIOPLAYALSA_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/win/YangAudioApiCapture.h b/libyangrtc2/src/yangaudiodev/win/YangAudioApiCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..52bbf8c42626faa2f7b4dd69d52a2011c56b61b6 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangAudioApiCapture.h @@ -0,0 +1,29 @@ + +/* + * YangAudioApiCapture.h + * + * Created on: 2021年9月20日 + * Author: yang + */ +#ifndef SRC_YANGCAPTURE_WIN_API_YANGAUDIOAPICAPTURE_H_ +#define SRC_YANGCAPTURE_WIN_API_YANGAUDIOAPICAPTURE_H_ +#include +#include +#include + +class YangAudioApiCapture:public YangThread{ +public: + YangAudioApiCapture(){m_isStart=0;}; + virtual ~YangAudioApiCapture(){}; + virtual void setCaptureCallback(YangCaptureCallback* cb)=0; + virtual int initCapture()=0; + virtual int startCpature()=0; + virtual int stopCapture()=0; + virtual void captureThread()=0; + virtual int getAudioOutLength()=0; + int m_isStart; +}; + + + +#endif /* SRC_YANGCAPTURE_WIN_API_YANGAUDIOAPICAPTURE_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.cpp b/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79fa3b4450c32c4e73f892dcc96a73f7c7b78e61 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.cpp @@ -0,0 +1,69 @@ +#include "yangutil/yang_unistd.h" +#ifdef _WIN32 +#include +#include "YangRecAudioCaptureHandle.h" + +YangRecAudioCaptureHandle::YangRecAudioCaptureHandle(YangContext *pcontext):YangAudioCaptureHandle(pcontext) +{ + readStart=0; + + if (pcontext->audio.usingMono) { + m_len=320*2; + } else { + m_len = 1024*4; + } + if(pcontext->audio.sample==48000) m_len=960*6; + m_buf=new uint8_t[m_len]; + //m_preProcess=NULL; + m_aec=NULL; + +} +YangRecAudioCaptureHandle::~YangRecAudioCaptureHandle(void) +{ + + if(m_buf) delete[] m_buf; + m_buf=NULL; +} + + + STDMETHODIMP_(ULONG) YangRecAudioCaptureHandle::AddRef() { return 1; } + STDMETHODIMP_(ULONG) YangRecAudioCaptureHandle::Release() { return 2; } + + STDMETHODIMP YangRecAudioCaptureHandle::QueryInterface(REFIID riid, void **ppvObject) + { + // printf("*********************************\n"); + if (NULL == ppvObject) return E_POINTER; + if (riid == __uuidof(IUnknown)) + { + *ppvObject = static_cast(this); + return S_OK; + } + if (riid == IID_ISampleGrabber) + { + *ppvObject = static_cast(this); + return S_OK; + } + return E_NOTIMPL; + } + + STDMETHODIMP YangRecAudioCaptureHandle::SampleCB(double Time, IMediaSample *pSample) + { + //printf(".len=%d..\n",pSample->GetSize()); + //list->putAudio( + //printf("") + return E_NOTIMPL; + } + + STDMETHODIMP YangRecAudioCaptureHandle::BufferCB(double Time, BYTE *pBuffer, long BufferLen) + { + //printf() + //printf("a%d,",BufferLen); + memset(m_buf,0,m_len); + putBuffer1(pBuffer,BufferLen); + + + return E_NOTIMPL; + } +//int32_t tcou=0; + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.h b/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..24db4bd41103b0398c48b461dc2f29db4f44935d --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangRecAudioCaptureHandle.h @@ -0,0 +1,29 @@ +#ifndef ___YangRecAudioCaptureHandlee__ +#define ___YangRecAudioCaptureHandlee__ +#ifdef _WIN32 +#include "qedit.h" + +#include "yangavutil/audio/YangMakeWave.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include "../YangAudioCaptureHandle.h" + + +class YangRecAudioCaptureHandle: public ISampleGrabberCB,public YangAudioCaptureHandle +{ +public: + YangRecAudioCaptureHandle(YangContext *pcontext); + virtual ~YangRecAudioCaptureHandle(void); + int32_t readStart; + + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); + STDMETHODIMP SampleCB(double Time, IMediaSample *pSample); + STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen); +private: + uint8_t *m_buf; + int32_t m_len; + +}; +#endif +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..540bf86e1e7c8d41fc19a19789fba833ec284a25 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.cpp @@ -0,0 +1,180 @@ +#include +#ifdef _WIN32 +#include + +#include +#include +#include +#include +#define SAFE_RELEASE(x) if(x){x->Release();x=NULL;} + +#define Yang_Release(x) if(x){x->Release();x=NULL;} +#define EXIT_ON_ERROR(hres) \ + do { \ + if (FAILED(hres)) \ + goto Exit; \ + } while (0) + + +YangWinAudioApi::YangWinAudioApi() +{ + m_enum=NULL; + CoInitialize(NULL); //初始化COM库 + CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, + __uuidof(IMMDeviceEnumerator), + reinterpret_cast(&m_enum)); + +} +YangWinAudioApi::~YangWinAudioApi() +{ + Yang_Release(m_enum); + +} + +int YangWinAudioApi::getListDevice(IMMDeviceEnumerator* penum,EDataFlow dir,int index,IMMDevice** ppDevice) { + HRESULT hr(S_OK); + IMMDeviceCollection* pCollection = NULL; + + hr = penum->EnumAudioEndpoints( + dir, + DEVICE_STATE_ACTIVE, // only active endpoints are OK + &pCollection); + if (FAILED(hr)) { + + SAFE_RELEASE(pCollection); + return 1; + } + + hr = pCollection->Item(index, ppDevice); + if (FAILED(hr)) { + + SAFE_RELEASE(pCollection); + return 1; + } + + return 0; +} +int YangWinAudioApi::getDeviceListCount(IMMDeviceCollection* pcollection,EDataFlow dir){ + HRESULT hr = S_OK; + UINT count = 0; + + hr = pcollection->GetCount(&count); + + + return static_cast(count); +} +int YangWinAudioApi::getDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer,int bufferLen) { + + + static const WCHAR szDefault[] = L""; + + HRESULT hr = E_FAIL; + LPWSTR pwszID = NULL; + + assert(pszBuffer != NULL); + assert(bufferLen > 0); + + if (pDevice != NULL) { + hr = pDevice->GetId(&pwszID); + } + + if (hr == S_OK) { + // Found the device ID. + wcsncpy_s(pszBuffer, bufferLen, pwszID, _TRUNCATE); + } else { + // Failed to find the device ID. + wcsncpy_s(pszBuffer, bufferLen, szDefault, _TRUNCATE); + } + + CoTaskMemFree(pwszID); + return 0; +} +int YangWinAudioApi::getDefaultDeviceID( IMMDeviceEnumerator* _ptrEnumerator,EDataFlow dir,ERole role,LPWSTR szBuffer,int bufferLen) { + + + HRESULT hr = S_OK; + IMMDevice* pDevice = NULL; + + hr = _ptrEnumerator->GetDefaultAudioEndpoint(dir, role, &pDevice); + + if (FAILED(hr)) { + + SAFE_RELEASE(pDevice); + return 1; + } + + int32_t res = getDeviceID(pDevice, szBuffer, bufferLen); + SAFE_RELEASE(pDevice); + return res; +} + +int YangWinAudioApi::getDefaultDeviceIndex(IMMDeviceEnumerator* penum,EDataFlow dir, ERole role,int* index) { + HRESULT hr = S_OK; + + + WCHAR szDefaultDeviceID[MAX_PATH] = {0}; + WCHAR szDeviceID[MAX_PATH] = {0}; + + const size_t kDeviceIDLength = sizeof(szDeviceID) / sizeof(szDeviceID[0]); + assert(kDeviceIDLength == + sizeof(szDefaultDeviceID) / sizeof(szDefaultDeviceID[0])); + + if (getDefaultDeviceID(penum,dir, role, szDefaultDeviceID, kDeviceIDLength)) { + yang_error ( "getDefaultDeviceI r failed hr==%ld",hr); + return 1; + } + + IMMDeviceCollection* collection; + hr = penum->EnumAudioEndpoints(dir, DEVICE_STATE_ACTIVE, + &collection); + + if (!collection) { + yang_error ( "Device collection not valid"); + return 1; + } + + UINT count = 0; + hr = collection->GetCount(&count); + if (FAILED(hr)) { + yang_error("..........collection GetCount failed================hr==%ld",hr); + return 1; + } + + *index = -1; + for (UINT i = 0; i < count; i++) { + memset(szDeviceID, 0, sizeof(szDeviceID)); + + IMMDevice* device; + { + IMMDevice* ptrDevice = NULL; + hr = collection->Item(i, &ptrDevice); + if (FAILED(hr) || ptrDevice == NULL) { + yang_error("..........collection Item failed==================hr==%ld",hr); + return 1; + } + device = ptrDevice; + SAFE_RELEASE(ptrDevice); + } + + if (getDeviceID(device, szDeviceID, kDeviceIDLength)) { + yang_error("..........getDeviceID failed====================hr==%ld",hr); + return 1; + } + + if (wcsncmp(szDefaultDeviceID, szDeviceID, kDeviceIDLength) == 0) { + // Found a match. + *index = i; + break; + } + } + + if (*index == -1) { + yang_error( "Unable to find collection index for default device=hr==%ld",hr); + return 1; + } + SAFE_RELEASE(collection); + + + return 0; +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.h new file mode 100644 index 0000000000000000000000000000000000000000..27b259da3b0f7730d1b2e22997db717df7684159 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApi.h @@ -0,0 +1,25 @@ +#ifndef YangWinAudioApi_H +#define YangWinAudioApi_H +#ifdef _WIN32 +#include "windows.h" +#include + +#include + +class YangWinAudioApi +{ +public: + YangWinAudioApi(); +virtual ~YangWinAudioApi(); +protected: + HRESULT enumEndpointDevicesAll(IMMDeviceEnumerator* penum,EDataFlow dataFlow); + int getDefaultDeviceID( IMMDeviceEnumerator* penum,EDataFlow dir,ERole role,LPWSTR szBuffer,int bufferLen); + int getDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer,int bufferLen); + int getDefaultDeviceIndex(IMMDeviceEnumerator* penum,EDataFlow dir, ERole role, int* index); + int getDeviceListCount(IMMDeviceCollection* pcollection,EDataFlow dir); + int getListDevice(IMMDeviceEnumerator* penum,EDataFlow dir,int index,IMMDevice** ppDevice); +protected: + IMMDeviceEnumerator* m_enum; +}; +#endif +#endif // YangWinAudioApi_H diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef5aa38871707b0ecea1a5f2225dabf81a2433e7 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.cpp @@ -0,0 +1,360 @@ +#include +#include +#include +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment (lib,"wmcodecdspuuid.lib") +#pragma comment (lib,"dmoguids.lib") +#pragma comment (lib,"msdmo.lib") +#define Yang_Release(x) if(x){x->Release();x=NULL;} + +class MediaBufferImpl final : public IMediaBuffer { +public: + explicit MediaBufferImpl(BYTE* p,DWORD maxLength) + : _data(p), + _length(0), + _maxLength(maxLength), + _refCount(0) { + + + } + void init(BYTE* p){ + _data=p; + _length=0; + } + // IMediaBuffer methods. + STDMETHOD(GetBufferAndLength(BYTE** ppBuffer, DWORD* pcbLength)) { + // if (!ppBuffer || !pcbLength) { + // return E_POINTER; + // } + + if(ppBuffer) *ppBuffer = _data; + if(pcbLength) *pcbLength = _length; + + return S_OK; + } + + STDMETHOD(GetMaxLength(DWORD* pcbMaxLength)) { + if (!pcbMaxLength) { + return E_POINTER; + } + + *pcbMaxLength = _maxLength; + return S_OK; + } + + STDMETHOD(SetLength(DWORD cbLength)) { + if (cbLength > _maxLength) { + return E_INVALIDARG; + } + + _length = cbLength; + return S_OK; + } + + // IUnknown methods. + STDMETHOD_(ULONG, AddRef()) { return InterlockedIncrement(&_refCount); } + + STDMETHOD(QueryInterface(REFIID riid, void** ppv)) { + if (!ppv) { + return E_POINTER; + } else if (riid != IID_IMediaBuffer && riid != IID_IUnknown) { + return E_NOINTERFACE; + } + + *ppv = static_cast(this); + AddRef(); + return S_OK; + } + + STDMETHOD_(ULONG, Release()) { + LONG refCount = InterlockedDecrement(&_refCount); + if (refCount == 0) { + delete this; + } + + return refCount; + } + +private: + ~MediaBufferImpl() {_data=NULL; } + + BYTE* _data; + DWORD _length; + const DWORD _maxLength; + LONG _refCount; +}; +YangWinAudioApiAec::YangWinAudioApiAec() { + m_isStart=0; + m_loops=0; + //m_cb=NULL; + m_dmo=NULL; + // m_mediaBuffer=NULL; + m_micIndex=0; + m_ps=NULL; + m_dataBuf=new BYTE[640]; + CoCreateInstance(CLSID_CWMAudioAEC, NULL, CLSCTX_INPROC_SERVER, + IID_IMediaObject, reinterpret_cast(&m_dmo)); + if(m_dmo) m_dmo->QueryInterface(IID_IPropertyStore, reinterpret_cast(&m_ps)); + m_dwStatus=0; + memset(&m_audioFrame,0,sizeof(YangFrame)); + m_audioData.initIn(16000, 1); + m_audioData.initOut(16000, 1); +} + +YangWinAudioApiAec::~YangWinAudioApiAec() { + + Yang_Release(m_ps); + + Yang_Release(m_dmo); + delete[] m_dataBuf; + +} +void YangWinAudioApiAec::setCaptureCallback(YangCaptureCallback* cb){ + m_audioData.m_cb=cb; + +} +int YangWinAudioApiAec::initCapture() { + getDefaultDeviceIndex(m_enum,eCapture,eConsole,&m_micIndex); + int ret=initRecordingDMO(); + + if(ret) return yang_error_wrap(ret,"int recording dmo fail.."); + + return Yang_Ok; + +} + + +void YangWinAudioApiAec::captureThread(){ + run(); +} + int YangWinAudioApiAec::startCpature(){ + return Yang_Ok; + } + int YangWinAudioApiAec::stopCapture(){ + return Yang_Ok; + } + void YangWinAudioApiAec::stop(){ + stopLoop(); + } + + void YangWinAudioApiAec::stopLoop() { + m_loops = 0; + + + } + + void YangWinAudioApiAec::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; + } + + + + + int YangWinAudioApiAec::setVtI4Property(IPropertyStore* ptrPS,REFPROPERTYKEY key,LONG value) { + PROPVARIANT pv; + PropVariantInit(&pv); + pv.vt = VT_I4; + pv.lVal = value; + HRESULT hr = ptrPS->SetValue(key, pv); + PropVariantClear(&pv); + if (FAILED(hr)) { + // _TraceCOMError(hr); + return yang_error_wrap(1,"setVtI4Property error.....key="); + + } + return 0; + } + int YangWinAudioApiAec::setBoolProperty(IPropertyStore* ptrPS, REFPROPERTYKEY key,VARIANT_BOOL value) { + PROPVARIANT pv; + PropVariantInit(&pv); + pv.vt = VT_BOOL; + pv.boolVal = value; + HRESULT hr = ptrPS->SetValue(key, pv); + PropVariantClear(&pv); + if (FAILED(hr)) { + return yang_error_wrap(1,"setVtI4Property error.....key="); + } + return 0; + } + + int YangWinAudioApiAec::setDMOProperties() { + HRESULT hr = S_OK; + if(m_dmo == NULL) return 1; + + + + + if (FAILED(hr) || m_ps == NULL) { + return yang_error_wrap(hr,"get IID_IPropertyStore COM failed!......."); + } + // Set the AEC system mode. + // SINGLE_CHANNEL_AEC - AEC processing only. + if (setVtI4Property(m_ps, MFPKEY_WMAAECMA_SYSTEM_MODE, SINGLE_CHANNEL_AEC)) { + yang_error("set SINGLE_CHANNEL_AEC COM failed!......."); + return 1; + } + + // Set the AEC source mode. + // VARIANT_TRUE - Source mode (we poll the AEC for captured data). + if (setBoolProperty(m_ps, MFPKEY_WMAAECMA_DMO_SOURCE_MODE, VARIANT_TRUE)) { + yang_error("set MFPKEY_WMAAECMA_DMO_SOURCE_MODE COM failed!......."); + return 1; + } + + // Enable the feature mode. + // This lets us override all the default processing settings below. + if (setBoolProperty(m_ps, MFPKEY_WMAAECMA_FEATURE_MODE, VARIANT_TRUE) ) { + yang_error("set MFPKEY_WMAAECMA_FEATURE_MODE COM failed!......."); + return 1; + } + + // Disable analog AGC (default enabled). + if (setBoolProperty(m_ps, MFPKEY_WMAAECMA_MIC_GAIN_BOUNDER, VARIANT_FALSE) ) { + yang_error("set MFPKEY_WMAAECMA_MIC_GAIN_BOUNDER COM failed!......."); + return 1; + } + + // Disable noise suppression (default enabled). + // 0 - Disabled, 1 - Enabled + if (setVtI4Property(m_ps, MFPKEY_WMAAECMA_FEATR_NS, 0)) { + yang_error("set MFPKEY_WMAAECMA_FEATR_NS COM failed!......."); + return 1; + } + + // search for the device index. + int inDevIndex = m_micIndex; + + int outDevIndex =0; + this->getDefaultDeviceIndex(m_enum,eRender,eConsole,&outDevIndex);//0; + + DWORD devIndex = static_cast(outDevIndex << 16) + + static_cast(0x0000ffff & inDevIndex); + // yang_error( "Capture device index: " << inDevIndex << ", render device index: " << outDevIndex; + if (setVtI4Property(m_ps, MFPKEY_WMAAECMA_DEVICE_INDEXES, devIndex)) { + + yang_error("set MFPKEY_WMAAECMA_FEATR_NS COM failed!......."); + return 1; + } + + return 0; + } + + int YangWinAudioApiAec::initRecordingDMO() { + + + if(m_dmo == NULL) return 1; + + if (setDMOProperties()) { + yang_error("..........setDMOProperties failed===================="); + return 1; + } + + DMO_MEDIA_TYPE mt = {}; + HRESULT hr = MoInitMediaType(&mt, sizeof(WAVEFORMATEX)); + if (FAILED(hr)) { + MoFreeMediaType(&mt); + yang_error("..........MoInitMediaType failed===================="); + return 1; + } + + mt.majortype = MEDIATYPE_Audio; + mt.subtype = MEDIASUBTYPE_PCM; + mt.formattype = FORMAT_WaveFormatEx; + + WAVEFORMATEX* ptrWav = reinterpret_cast(mt.pbFormat); + ptrWav->wFormatTag = WAVE_FORMAT_PCM; + ptrWav->nChannels = 1; + ptrWav->nSamplesPerSec = 16000; + ptrWav->nAvgBytesPerSec = 32000; + ptrWav->nBlockAlign = 2; + ptrWav->wBitsPerSample = 16; + ptrWav->cbSize = 0; + + // Set the VoE format equal to the AEC output format. + + + // Set the DMO output format parameters. + hr = m_dmo->SetOutputType(0, &mt, 0); + MoFreeMediaType(&mt); + if (FAILED(hr)) { + yang_error("..........SetOutputType failed===================="); + return 1; + } + + hr = m_dmo->AllocateStreamingResources(); + if (FAILED(hr)) { + return 1; + } + return 0; + } + + + void YangWinAudioApiAec::startLoop(){ + DWORD taskIndex(0); + HANDLE hMmTask = AvSetMmThreadCharacteristicsA("Pro Audio", &taskIndex); + if (hMmTask) { + if (FALSE == AvSetMmThreadPriority(hMmTask, AVRT_PRIORITY_CRITICAL)) { + yang_warn( "failed to boost wincaecapture-thread using MMCSS"); + } + yang_trace("wincaecapture thread is now registered with MMCSS (taskIndex=%d)", + taskIndex ); + } else { + yang_error( "failed to enable MMCSS on wincaecapture thread (err=%lu", GetLastError() ); + + } + m_loops = 1; + uint8_t* tmp=new uint8_t[1024*4]; + YangAutoFreeA(uint8_t,tmp); + + MediaBufferImpl* m_mediaBuffer = new MediaBufferImpl(tmp,4096); + DMO_OUTPUT_DATA_BUFFER OutputBufferStruct; + OutputBufferStruct.pBuffer = m_mediaBuffer; + OutputBufferStruct.pBuffer->AddRef(); + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + unsigned long bufLen=0; + while(m_loops){ + yang_usleep(1000*10); + m_mediaBuffer->SetLength(0); + bufLen=0; + do{ + OutputBufferStruct.dwStatus = 0; + HRESULT hr = m_dmo->ProcessOutput(0, 1, &OutputBufferStruct, &m_dwStatus); + + if (hr == S_FALSE) { + bufLen=0; + } else { + hr = m_mediaBuffer->GetBufferAndLength(NULL, &bufLen); + + } + + } while (OutputBufferStruct.dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE); + // yang_trace("a%d,",bufLen); + if(bufLen>0){ + audioFrame.payload=tmp; + audioFrame.nb=bufLen; + m_audioData.caputure(&audioFrame); + + } + + + } + Yang_Release(m_mediaBuffer); + } + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.h new file mode 100644 index 0000000000000000000000000000000000000000..cd8fbf57712e60a187783dd4bc24052394547bf8 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiAec.h @@ -0,0 +1,59 @@ + +/* + * YangWinAudioApiAec.h + * + * Created on: 2021年9月20日 + * Author: yang + */ +#ifndef YANGCAPTURE_WIN_API_YANGWINAUDIOAPIAEC_H_ +#define YANGCAPTURE_WIN_API_YANGWINAUDIOAPIAEC_H_ +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#include +#include + +class YangWinAudioApiAec:public YangAudioApiCapture,public YangWinAudioApi { +public: + YangWinAudioApiAec(); + virtual ~YangWinAudioApiAec(); + void setCaptureCallback(YangCaptureCallback* cb); + int initCapture(); + int startCpature(); + int stopCapture(); + void captureThread(); + int getAudioOutLength(){return 640;} + + + int initRecordingDMO(); + int setDMOProperties(); + int getRenderIndex(); + // int getBuffer(uint8_t* p,unsigned long* pbufLen); + YangAudioCaptureData m_audioData; + + void stop(); +protected: + void run(); + void startLoop(); + void stopLoop(); + int setBoolProperty(IPropertyStore* ptrPS, REFPROPERTYKEY key,VARIANT_BOOL value); + int setVtI4Property(IPropertyStore* ptrPS,REFPROPERTYKEY key,LONG value); + int m_loops; + //YangCaptureCallback* m_cb; +private: + IMediaObject* m_dmo; + + + DWORD m_dwStatus; + + int m_micIndex; + BYTE* m_dataBuf; + IPropertyStore* m_ps; + // YangRecData m_recData; + YangFrame m_audioFrame; +}; +#endif +#endif /* YANGCAPTURE_WIN_API_YANGWINAUDIOAPIAEC_H_ */ diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5b18e36515122cc3859e90c9e4324ba722e0c54 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.cpp @@ -0,0 +1,369 @@ +#include +#ifdef _WIN32 +#include +#include +#include +#include + +#define Yang_Release(x) if(x){x->Release();x=NULL;} + +const float MAX_MICROPHONE_VOLUME = 255.0f; +const float MIN_MICROPHONE_VOLUME = 0.0f; +YangWinAudioApiCapture::YangWinAudioApiCapture(YangContext *pcontext) { + m_inputDeviceIndex = 0; + m_isStart = 0; + m_loops = 0; + m_bufferLength = 0; + m_blockSize = 480; + m_frameSize=4; + m_captureCollection = NULL; + m_deviceIn = NULL; + m_clientIn = NULL; + m_captureClient = NULL; + m_captureVolume = NULL; + m_samplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + m_audioData.initOut(pcontext->audio.sample, pcontext->audio.channel); + + m_channlList[0] = 2; // stereo is prio 1 + m_channlList[1] = 1; // mono is prio 2 + m_channlList[2] = 4; // quad is prio 3 + + m_blank = new uint8_t[960 * 8]; + memset(m_blank, 0, 960 * 8); +} +YangWinAudioApiCapture::~YangWinAudioApiCapture() { + yang_stop(this); + yang_stop_thread(this); + if (NULL != m_samplesReadyEvent) { + CloseHandle(m_samplesReadyEvent); + m_samplesReadyEvent = NULL; + } + Yang_Release(m_captureCollection); + Yang_Release(m_deviceIn); + Yang_Release(m_clientIn); + Yang_Release(m_captureClient); + Yang_Release(m_captureVolume); + yang_deleteA(m_blank); +} + +void YangWinAudioApiCapture::setCaptureCallback(YangCaptureCallback *cb) { + m_audioData.m_cb = cb; +} + +int YangWinAudioApiCapture::setMicrophoneVolume(int volume) { + + if (volume < static_cast(MIN_MICROPHONE_VOLUME) + || volume > static_cast(MAX_MICROPHONE_VOLUME)) { + return 1; + } + + HRESULT hr = S_OK; + // scale input volume to valid range (0.0 to 1.0) + const float fLevel = static_cast(volume) / MAX_MICROPHONE_VOLUME; + + // m_lock.lock(); + m_captureVolume->SetMasterVolumeLevelScalar(fLevel, NULL); +// m_lock.unlock(); + if (FAILED(hr)) + return 1; + + return 0; + +} +int YangWinAudioApiCapture::getMicrophoneVolume(int &volume) { + + HRESULT hr = S_OK; + float fLevel(0.0f); + volume = 0; + // m_lock.lock(); + hr = m_captureVolume->GetMasterVolumeLevelScalar(&fLevel); + // m_lock.unlock(); + if (FAILED(hr)) + return 1; + + // scale input volume range [0.0,1.0] to valid output range + volume = static_cast(fLevel * MAX_MICROPHONE_VOLUME); + + return 0; + +} + +int YangWinAudioApiCapture::setMicrophoneMute(bool enable) { + + if (m_deviceIn == NULL) { + return 1; + } + + HRESULT hr = S_OK; + IAudioEndpointVolume *pVolume = NULL; + + // Set the microphone system mute state. + hr = m_deviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, + reinterpret_cast(&pVolume)); + if (FAILED(hr)) + return 1; + + const BOOL mute(enable); + hr = pVolume->SetMute(mute, NULL); + if (FAILED(hr)) + return 1; + + Yang_Release(pVolume); + return 0; + +} + +int YangWinAudioApiCapture::initMicrophone() { + //eCommunications eConsole + int ret = getListDevice(m_enum, eCapture, m_inputDeviceIndex, &m_deviceIn); + if (ret != 0 || (m_deviceIn == NULL)) { + Yang_Release(m_deviceIn); + return yang_error_wrap(ERROR_SYS_AudioCapture, "get capture devicein fail..."); + } + + Yang_Release(m_captureVolume); + ret = m_deviceIn->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, + reinterpret_cast(&m_captureVolume)); + if (ret != 0 || m_captureVolume == NULL) { + Yang_Release(m_captureVolume); + return 1; + } + + return 0; + // if(m_deviceIn==NULL) getDefaultDevice(eCapture,eCommunications,&m_deviceIn); +} +int YangWinAudioApiCapture::initCapture() { + getDefaultDeviceIndex(m_enum, eCapture, eConsole, &m_inputDeviceIndex); + + if (initMicrophone()) { + return yang_error_wrap(ERROR_SYS_AudioCapture, "init microphone fail..."); + } + if (m_deviceIn == NULL) { + yang_error("..............initCapture failed"); + return 1; + } + + HRESULT hr = S_OK; + WAVEFORMATEX *pWfxIn = NULL; + WAVEFORMATEXTENSIBLE Wfx = WAVEFORMATEXTENSIBLE(); + WAVEFORMATEX *pWfxClosestMatch = NULL; + + // Create COM object with IAudioClient interface. + Yang_Release(m_clientIn); + hr = m_deviceIn->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, + (void**) &m_clientIn); + // qDebug()<<"m_clientIn....."<GetMixFormat(&pWfxIn); + if (SUCCEEDED(hr)) { + + } + + // Set wave format + Wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + Wfx.Format.wBitsPerSample = 16; + Wfx.Format.cbSize = 22; + Wfx.dwChannelMask = 0; + Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample; + Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + const int freqs[6] = { 48000, 44100, 16000, 96000, 32000, 8000 }; + hr = S_FALSE; + + // Iterate over frequencies and channels, in order of priority + for (unsigned int freq = 0; freq < sizeof(freqs) / sizeof(freqs[0]); + freq++) { + for (unsigned int chan = 0; + chan < sizeof(m_channlList) / sizeof(m_channlList[0]); chan++) { + Wfx.Format.nChannels = m_channlList[chan]; + Wfx.Format.nSamplesPerSec = freqs[freq]; + Wfx.Format.nBlockAlign = Wfx.Format.nChannels + * Wfx.Format.wBitsPerSample / 8; + Wfx.Format.nAvgBytesPerSec = Wfx.Format.nSamplesPerSec + * Wfx.Format.nBlockAlign; + // If the method succeeds and the audio endpoint device supports the + // specified stream format, it returns S_OK. If the method succeeds and + // provides a closest match to the specified format, it returns S_FALSE. + hr = m_clientIn->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, + (WAVEFORMATEX*) &Wfx, &pWfxClosestMatch); + if (hr == S_OK) { + break; + } else { + if (pWfxClosestMatch) { + CoTaskMemFree(pWfxClosestMatch); + pWfxClosestMatch = NULL; + } else { + yang_error(" is not supported. No closest match."); + } + } + } + if (hr == S_OK) + break; + } + + if (hr == S_OK) { + m_frameSize= Wfx.Format.nBlockAlign; + m_blockSize = Wfx.Format.nSamplesPerSec / 100; + + m_audioData.initIn(Wfx.Format.nSamplesPerSec, Wfx.Format.nChannels); + yang_trace("\ncapture: sample==%d,channle==%d,nBlockAlign==%d,blockSize==%d\n",Wfx.Format.nSamplesPerSec,Wfx.Format.nChannels,m_frameSize,m_blockSize); + } + + + // Create a capturing stream. + hr = m_clientIn->Initialize(AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications + AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by + // the client will be event driven + AUDCLNT_STREAMFLAGS_NOPERSIST,// volume and mute settings for an + // audio session will not persist + // across system restarts + 0,// required for event-driven shared mode + 0, // periodicity + (WAVEFORMATEX*) &Wfx, // selected wave format + NULL); + + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioCapture," capture audioclient Initialize fail..."); + + + hr = m_clientIn->GetBufferSize(&m_bufferLength); +// yang_trace("\ncapture bufferLength==%d..............", m_bufferLength); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioCapture, " capture audioclient GetBufferSize fail..."); + hr = m_clientIn->SetEventHandle(m_samplesReadyEvent); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioCapture, " capture audioclient SetEventHandle fail..."); + // Get an IAudioCaptureClient interface. + Yang_Release(m_captureClient); + hr = m_clientIn->GetService(__uuidof(IAudioCaptureClient), + (void**) &m_captureClient); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioCapture, " captureclient Initialize fail..."); + + CoTaskMemFree(pWfxIn); + CoTaskMemFree(pWfxClosestMatch); + + return 0; + +} +int YangWinAudioApiCapture::startCpature() { + + if (m_clientIn) { + HRESULT hr = m_clientIn->Start(); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioCapture, "capure clientin start fail..."); + return Yang_Ok; + } + return yang_error_wrap(ERROR_SYS_AudioCapture, "capure clientin is null"); + +} +int YangWinAudioApiCapture::stopCapture() { + if (m_clientIn) { + m_clientIn->Stop(); + } + return Yang_Ok; +} +int YangWinAudioApiCapture::captureFrame(YangFrame *audioFrame) { + audioFrame->nb = 0; + UINT32 packetLength=0; + BYTE *pData = 0; + UINT32 framesAvailable = 0; + DWORD flags = 0; + UINT64 recTime = 0; + UINT64 recPos = 0; + HRESULT hr =m_captureClient->GetNextPacketSize(&packetLength); + while(packetLength!=0){ + hr = m_captureClient->GetBuffer(&pData, // packet which is ready to be read by used + &framesAvailable, // #frames in the captured packet (can be zero) + &flags, // support flags (check) + &recPos, // device position of first audio frame in data packet + &recTime); // value of performance counter at the time of recording + if (SUCCEEDED(hr)) { + if (AUDCLNT_S_BUFFER_EMPTY == hr) { + // Buffer was empty => start waiting for a new capture notification + // event + return 1; + } + + if (flags & AUDCLNT_BUFFERFLAGS_SILENT) { + pData = NULL; + } + + if (pData) { + audioFrame->payload = pData; + audioFrame->nb = framesAvailable * m_frameSize; + + } else { + audioFrame->payload = m_blank; + audioFrame->nb = framesAvailable * m_frameSize; + } + m_audioData.caputure(audioFrame); + + hr = m_captureClient->ReleaseBuffer(framesAvailable); + } + m_captureClient->GetNextPacketSize(&packetLength); + } + + return 0; +} +int YangWinAudioApiCapture::getAudioOutLength(){ + return m_audioData.getOutLength(); +} +void YangWinAudioApiCapture::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangWinAudioApiCapture::stop() { + stopLoop(); +} +void YangWinAudioApiCapture::stopLoop() { + m_loops = 0; + stopCapture(); +} + +void YangWinAudioApiCapture::startLoop() { + DWORD taskIndex(0); + HANDLE hMmTask = AvSetMmThreadCharacteristicsA("Pro Audio", &taskIndex); + // ERROR_INVALID_TASK_INDEX + if (hMmTask) { + if (FALSE == AvSetMmThreadPriority(hMmTask, AVRT_PRIORITY_CRITICAL)) { + yang_warn( "failed to boost wincapture-thread using MMCSS"); + } + yang_trace("wincapture thread is now registered with MMCSS (taskIndex=%d)", + taskIndex ); + } else { + yang_error( "failed to enable MMCSS on wincapture thread (err=%lu", GetLastError() ); + + } + m_loops = 1; + HRESULT hr = m_clientIn->GetBufferSize(&m_bufferLength); + if (FAILED(hr)) yang_error( "capure clientin getbufferSize fail..."); + yang_trace("\ncapture bufferLength==%d..............", m_bufferLength); + if (startCpature()) { + yang_error("start capture fail"); + return; + } + + HANDLE waitArray[1] = { m_samplesReadyEvent }; + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + while (m_loops == 1) { + DWORD waitResult = WaitForMultipleObjects(1, waitArray, FALSE, 500); + if (waitResult == (WAIT_OBJECT_0 + 0)) { + audioFrame.payload = NULL; + audioFrame.nb = 0; + captureFrame(&audioFrame); + } + + } + +} +void YangWinAudioApiCapture::captureThread() { + run(); +} + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..2c1540caf5e0e3d38ff922198e7c51810988ea50 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiCapture.h @@ -0,0 +1,60 @@ +#ifndef YangWinAudioApiCapture_H1 +#define YangWinAudioApiCapture_H1 + +#ifdef _WIN32 +#include +#include + +#include +#include +#include +#include + +class YangWinAudioApiCapture:public YangAudioApiCapture,public YangWinAudioApi +{ +public: + YangWinAudioApiCapture(YangContext* pcontext); + virtual ~YangWinAudioApiCapture(); + void setCaptureCallback(YangCaptureCallback *cb); + void captureThread(); + int initCapture(); + int startCpature(); + int stopCapture(); + int getAudioOutLength(); + int getMicrophoneVolume(int& volume); + int setMicrophoneVolume(int volume); + int setMicrophoneMute(bool enable); + + + + IMMDeviceCollection* m_captureCollection; + IMMDevice* m_deviceIn; + IAudioClient* m_clientIn; + + IAudioCaptureClient* m_captureClient; + IAudioEndpointVolume* m_captureVolume; + + int m_inputDeviceIndex; + int captureFrame(YangFrame* paudioFrame); + + void stop(); +protected: + virtual void startLoop(); + void stopLoop(); + void run(); + int m_loops; +private: + int initMicrophone(); + UINT32 m_bufferLength; + int m_blockSize; + int m_frameSize; + + uint16_t m_channlList[3]; + YangAudioCaptureData m_audioData; + HANDLE m_samplesReadyEvent; + uint8_t* m_blank; + + +}; +#endif +#endif // YangWinAudioApiCapture_H diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e1e5acbdfd047f712ada5842b43af5dc1a43f9e --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.cpp @@ -0,0 +1,134 @@ +#include +#ifdef _WIN32 +#include +#include +#include +#include + +YangWinAudioApiDevice::YangWinAudioApiDevice(YangContext *pcontext,bool isRecord, + bool usingBuiltinAec) { + m_usingBuiltinAec = usingBuiltinAec; + m_isStart = 0; + m_isInit = 0; + m_loops = 0; + m_player=NULL; + m_context=pcontext; +#ifdef _MSC_VER + if (m_usingBuiltinAec&&!isRecord) + m_capture = new YangWinAudioApiAec(); + else{ +#endif + m_capture = new YangWinAudioApiCapture(pcontext); +#ifdef _MSC_VER + } +#else + m_usingBuiltinAec=false; +#endif + m_outLen=640; + m_ahandle = new YangAudioCaptureHandle(pcontext); + if(!isRecord) m_player = new YangWinAudioApiRender(pcontext); + +} + +YangWinAudioApiDevice::~YangWinAudioApiDevice() { + + + yang_stop(m_player); + yang_stop(m_capture); + yang_stop_thread(m_player); + yang_stop_thread(m_capture); + yang_delete(m_ahandle); + yang_delete(m_player); + yang_delete(m_capture); + + +} + +void YangWinAudioApiDevice::setCatureStart() { + if(m_ahandle) m_ahandle->isBuf = 1; +} +void YangWinAudioApiDevice::setCatureStop() { + if(m_ahandle) m_ahandle->isBuf = 0; +} +void YangWinAudioApiDevice::setOutAudioBuffer(YangAudioBuffer *pbuffer) { + if(m_ahandle) m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangWinAudioApiDevice::setPlayAudoBuffer(YangAudioBuffer *pbuffer) { + //m_player->m_audioData.setAudioList(pbuffer); + if(m_ahandle) m_ahandle->m_aecPlayBuffer = pbuffer; +} +void YangWinAudioApiDevice::setAec(YangAecBase *paec) { + if(!m_usingBuiltinAec){ + if(m_ahandle&&m_player){ + m_ahandle->m_aec = paec; + m_player->setAec(paec); + } + + } + +} +void YangWinAudioApiDevice::setPreProcess(YangPreProcess *pp) { +if(!m_usingBuiltinAec&&m_player) m_player->m_audioData.m_preProcess = pp; + +} + +void YangWinAudioApiDevice::setInAudioBuffer( + vector *pal) { + //if(m_player&&m_player->m_audioData.m_syn) m_player->m_audioData.m_syn->setInAudioBuffer(pal); + +} +void YangWinAudioApiDevice::caputureAudioData(YangFrame *audioFrame) { + //printf("%d-%d,",m_usingBuiltinAec,m_player->m_hasRenderEcho); +#ifdef _MSC_VER + if (m_usingBuiltinAec){ + if(m_ahandle) m_ahandle->putBuffer1(audioFrame->payload, m_outLen); + }else { +#endif + if (m_player&&m_player->m_hasRenderEcho){ + if(m_ahandle) m_ahandle->putEchoBuffer(audioFrame->payload, m_outLen); //aec filter render data + }else{ + if(m_ahandle) m_ahandle->putBuffer1(audioFrame->payload, m_outLen); + } +#ifdef _MSC_VER + } +#endif +} + +void YangWinAudioApiDevice::stopLoop() { + m_loops = 0; + if(m_capture) m_capture->stop(); +} + + + +int YangWinAudioApiDevice::init() { + if (m_isInit) return Yang_Ok; + + if(m_capture) { + m_capture->initCapture(); + m_capture->setCaptureCallback(this); + m_outLen=m_capture->getAudioOutLength(); + } + if(m_player) m_player->init(); + m_isInit = 1; + return Yang_Ok; +} +void YangWinAudioApiDevice::startLoop() { + + + + m_loops = 1; + if (m_player) m_player->start(); + if(m_capture){ + m_capture->captureThread(); + } + if (m_player) + m_player->stop(); + if (m_capture){ + m_capture->stop(); + } + + +} + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.h new file mode 100644 index 0000000000000000000000000000000000000000..ac55aa8a421de4f7e695fc9f6034ff1e5e5d43b4 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiDevice.h @@ -0,0 +1,51 @@ +#ifndef SRC_YANGCAPTURE_SRC_WIN_YANGWINAUDIOAPI_H_ +#define SRC_YANGCAPTURE_SRC_WIN_YANGWINAUDIOAPI_H_ + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include + +#include "YangWinAudioCaptureHandle.h" +#include +#include +#include + + + +class YangWinAudioApiDevice: public YangAudioCapture,public YangCaptureCallback { +public: + YangWinAudioApiDevice(YangContext *pcontext,bool isRecord,bool usingBuiltinAec=false); + ~YangWinAudioApiDevice(); + int init(); + void setInAudioBuffer(std::vector *pal); + void setPreProcess(YangPreProcess *pp); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setAec(YangAecBase *paec); + void caputureAudioData(YangFrame* audioFrame); + YangAudioCaptureHandle *m_ahandle; + +protected: + void startLoop(); + void stopLoop(); + +private: + int m_loops; + int m_isInit; + int m_outLen; + + +private: + bool m_usingBuiltinAec; + YangAudioApiCapture *m_capture; + YangWinAudioApiRender* m_player; +}; + +#endif /* SRC_YANGCAPTURE_SRC_WIN_YANGWINAUDIOAPI_H_ */ +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.cpp new file mode 100644 index 0000000000000000000000000000000000000000..634e7b78cee6f61c95aadd213f421de4c6d264a3 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.cpp @@ -0,0 +1,509 @@ +#include +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define Yang_Release(x) if(x){x->Release();x=NULL;} +#define ROUND(x) ((x) >= 0 ? (int)((x) + 0.5) : (int)((x)-0.5)) + + +#define CONTINUE_ON_ERROR(x) if(x!=S_OK){continue;} + +const float MAX_SPEAKER_VOLUME = 255.0f; +const float MIN_SPEAKER_VOLUME = 0.0f; + +YangWinAudioApiRender::YangWinAudioApiRender(YangContext *pcontext):YangAudioPlay(pcontext) { + m_outputDeviceIndex = 0; + m_renderCollection = NULL; + m_deviceOut = NULL; + m_clientOut = NULL; + m_renderClient = NULL; + m_renderSimpleVolume = NULL; + m_dataBufP = NULL; + m_contextt = 0; + + m_resTmp=NULL; + m_resBuf=NULL; + m_aec=NULL; + + m_bufferLength = 0; + keepPlaying = false; + flags = 0; + padding = 0; + framesAvailable = 0; + m_audioPlayCacheNum = pcontext->audio.audioPlayCacheNum; + m_audioData.initPlay(pcontext->audio.sample, pcontext->audio.channel); + m_sample=pcontext->audio.sample; + + m_size = (pcontext->audio.sample / 50) * pcontext->audio.channel * 2; + + + m_loops=0; + m_isStart=0; + m_samplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + m_bufLen=0; + m_hasRenderEcho=0; + m_blockSize=4; + memset(&m_audioFrame,0,sizeof(YangFrame)); + +} +YangWinAudioApiRender::~YangWinAudioApiRender() { + if (NULL != m_samplesReadyEvent) { + CloseHandle(m_samplesReadyEvent); + m_samplesReadyEvent = NULL; + } + Yang_Release(m_renderCollection); + Yang_Release(m_deviceOut); + Yang_Release(m_clientOut); + Yang_Release(m_renderClient); + Yang_Release(m_renderSimpleVolume); + yang_deleteA(m_resTmp); + yang_deleteA(m_resBuf); + m_aec=NULL; +} + +//void YangWinAudioApiRender::setAudioList(YangAudioPlayBuffer *pal) { + // if(m_audioData.m_syn) m_audioData.m_syn->setAudioList(pal) ; +//} + +void YangWinAudioApiRender::setAec(YangAecBase *paec){ + + m_aec=paec; + m_audioData.setAec(); +} +int YangWinAudioApiRender::setSpeakerVolume(int volume) { + if (m_deviceOut == NULL) { + return 1; + } + if (volume < (int) MIN_SPEAKER_VOLUME + || volume > (int) MAX_SPEAKER_VOLUME) { + return 1; + } + + HRESULT hr = S_OK; + + // scale input volume to valid range (0.0 to 1.0) + const float fLevel = (float) volume / MAX_SPEAKER_VOLUME; + // m_lock.lock(); + hr = m_renderSimpleVolume->SetMasterVolume(fLevel, NULL); + // m_lock.unlock(); + if (FAILED(hr)) + return 1; + return 0; + +} +int YangWinAudioApiRender::getSpeakerVolume(int &volume) { + if (m_deviceOut == NULL) { + return 1; + } + + HRESULT hr = S_OK; + float fLevel(0.0f); + + //m_lock.lock(); + hr = m_renderSimpleVolume->GetMasterVolume(&fLevel); + // m_lock.unlock(); + if (FAILED(hr)) + return 1; + + // scale input volume range [0.0,1.0] to valid output range + volume = static_cast(fLevel * MAX_SPEAKER_VOLUME); + + return 0; + +} +int YangWinAudioApiRender::getSpeakerMute(bool &enabled) { + + if (m_deviceOut == NULL) { + return 1; + } + + HRESULT hr = S_OK; + IAudioEndpointVolume *pVolume = NULL; + + // Query the speaker system mute state. + hr = m_deviceOut->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, + reinterpret_cast(&pVolume)); + if (FAILED(hr)) + return 1; + + BOOL mute; + hr = pVolume->GetMute(&mute); + if (FAILED(hr)) + return 1; + + enabled = (mute == TRUE) ? true : false; + + Yang_Release(pVolume); + + return 0; + +} +int YangWinAudioApiRender::setSpeakerMute(bool enable) { + if (m_deviceOut == NULL) { + return 1; + } + + HRESULT hr = S_OK; + IAudioEndpointVolume *pVolume = NULL; + + // Set the speaker system mute state. + hr = m_deviceOut->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, + reinterpret_cast(&pVolume)); + if (FAILED(hr)) + return 1; + + const BOOL mute(enable); + hr = pVolume->SetMute(mute, NULL); + if (FAILED(hr)) + return 1; + + Yang_Release(pVolume); + + return 0; + +} +int YangWinAudioApiRender::initSpeaker(int pind) { + // int nDevices = playoutDeviceCount(); + // if(pind>=nDevices) return 1; + // getListDevice(m_enum, eRender, pind, &m_deviceOut); + IAudioSessionManager *pManager = NULL; + int ret = m_deviceOut->Activate(__uuidof(IAudioSessionManager), CLSCTX_ALL, + NULL, (void**) &pManager); + if (ret != 0 || pManager == NULL) { + Yang_Release(pManager); + return 1; + } + Yang_Release(m_renderSimpleVolume); + ret = pManager->GetSimpleAudioVolume(NULL, FALSE, &m_renderSimpleVolume); + if (ret != 0 || m_renderSimpleVolume == NULL) { + Yang_Release(pManager); + Yang_Release(m_renderSimpleVolume); + return 1; + } + Yang_Release(pManager); + return 0; +} + +int YangWinAudioApiRender::initPlay(int pind) { + if (m_deviceOut == NULL) { + yang_error("1_Init play failed device is null"); + return 1; + } + + // Initialize the speaker (devices might have been added or removed) + if (initSpeaker(pind)) { + yang_error("InitSpeaker() failed"); + } + + // Ensure that the updated rendering endpoint device is valid + if (m_deviceOut == NULL) { + yang_error("2_Init play failed device is null"); + return 1; + } + + HRESULT hr = S_OK; + WAVEFORMATEX *pWfxOut = NULL; + WAVEFORMATEX Wfx = WAVEFORMATEX(); + WAVEFORMATEX *pWfxClosestMatch = NULL; + + // Create COM object with IAudioClient interface. + Yang_Release(m_clientOut); + hr = m_deviceOut->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, + (void**) &m_clientOut); + if (FAILED(hr)) return yang_error_wrap(ERROR_SYS_AudioRender,"create IAudioClient fail ..."); + + + hr = m_clientOut->GetMixFormat(&pWfxOut); + // Set wave format + Wfx.wFormatTag = WAVE_FORMAT_PCM; + Wfx.wBitsPerSample = 16; + Wfx.cbSize = 0; + const int freqs[] = { 48000, 44100, 16000, 96000, 32000, 8000 }; + hr = S_FALSE; + int _playChannelsPrioList[2]; + _playChannelsPrioList[0] = 2; // stereo is prio 1 + _playChannelsPrioList[1] = 1; // mono is prio 2 + // Iterate over frequencies and channels, in order of priority + for (unsigned int freq = 0; freq < sizeof(freqs) / sizeof(freqs[0]); + freq++) { + for (unsigned int chan = 0; + chan + < sizeof(_playChannelsPrioList) + / sizeof(_playChannelsPrioList[0]); chan++) { + Wfx.nChannels = _playChannelsPrioList[chan]; + Wfx.nSamplesPerSec = freqs[freq]; + Wfx.nBlockAlign = Wfx.nChannels * Wfx.wBitsPerSample / 8; + Wfx.nAvgBytesPerSec = Wfx.nSamplesPerSec * Wfx.nBlockAlign; + // If the method succeeds and the audio endpoint device supports the + // specified stream format, it returns S_OK. If the method succeeds and + // provides a closest match to the specified format, it returns S_FALSE. + hr = m_clientOut->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &Wfx, + &pWfxClosestMatch); + if (hr == S_OK) { + break; + } else { + if (pWfxClosestMatch) { + + CoTaskMemFree(pWfxClosestMatch); + pWfxClosestMatch = NULL; + } + } + } + if (hr == S_OK) + break; + } + + // TODO(andrew): what happens in the event of failure in the above loop? + // Is _ptrClientOut->Initialize expected to fail? + // Same in InitRecording(). + if (hr == S_OK) { + // Block size is the number of samples each channel in 10ms. + m_blockSize=Wfx.nSamplesPerSec / 100; + } + yang_trace("\nrender: sample==%d,channle==%d,nBlockAlign==%d,blockSize==%d",Wfx.nSamplesPerSec,Wfx.nChannels,Wfx.nBlockAlign,m_blockSize); + m_audioData.initRender(Wfx.nSamplesPerSec, Wfx.nChannels); + REFERENCE_TIME hnsBufferDuration = 0;//20 * 10000; // ask for minimum buffer size (default) + if (Wfx.nSamplesPerSec == 44100) { + hnsBufferDuration = 30 * 10000; + } + hr = m_clientOut->Initialize(AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // processing of the audio buffer by + // the client will be event driven + hnsBufferDuration, // requested buffer capacity as a time value (in + // 100-nanosecond units) + 0,// periodicity + &Wfx, // selected wave format + NULL); // session GUID + + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioRender,"AudioClient Initialize param fail ..."); + + // Get the actual size of the shared (endpoint buffer). + // Typical value is 960 audio frames <=> 20ms @ 48kHz sample rate. + + hr = m_clientOut->GetBufferSize(&m_bufferLength); + yang_trace("\nbufersize==================%d",m_bufferLength); + if (SUCCEEDED(hr)) { + + } + + // Set the event handle that the system signals when an audio buffer is ready + // to be processed by the client. + hr = m_clientOut->SetEventHandle(m_samplesReadyEvent); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioRender,"SetEventHandle fail ..."); + // EXIT_ON_ERROR(hr); + + // Get an IAudioRenderClient interface. + Yang_Release(m_renderClient); + hr = m_clientOut->GetService(__uuidof(IAudioRenderClient), + (void**) &m_renderClient); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioRender,"create AudioRenderClient fail ..."); + + CoTaskMemFree(pWfxOut); + CoTaskMemFree(pWfxClosestMatch); + + + return 0; + +} + +int YangWinAudioApiRender::startRender() { + uint32_t err=Yang_Ok; + if (m_clientOut) { + err=m_clientOut->Start(); + if(err != S_OK ) { + return yang_error_wrap(err,"client start fail.."); + } + return Yang_Ok; + } + yang_error("client is null"); + return 1; +} +int YangWinAudioApiRender::stopRender() { + if (m_clientOut) { + m_clientOut->Stop(); + return 0; + } + + return 1; +} +int YangWinAudioApiRender::init() { + + if (m_contextt) + return 0; + //getDefaultDeviceIndex(m_enum, eRender, eConsole, &m_outputDeviceIndex); + m_enum->GetDefaultAudioEndpoint(eRender, eConsole, &m_deviceOut); + // getListDevice(m_enum,eRender, m_outputDeviceIndex,&m_deviceOut); + + int err=Yang_Ok; + err=initPlay(m_outputDeviceIndex); + if(err) { + return yang_error_wrap(err,"init render fail......."); + } + + m_contextt = 1; + return 0; +} + +int YangWinAudioApiRender::render_10ms(){ + HRESULT hr = m_clientOut->GetCurrentPadding(&padding); + if (FAILED(hr)) return yang_error_wrap(ERROR_SYS_AudioRender,"outClient GetCurrentPadding fail......."); + m_dataBufP=NULL; + framesAvailable = m_bufferLength - padding; + + if(framesAvailable0) { + const uint32_t n10ms = (framesAvailable /m_blockSize); + + for (uint32_t n = 0; n < n10ms; n++) { + // render buffer. + hr = m_renderClient->GetBuffer(m_blockSize, &m_dataBufP); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioRender,"renderClient getBuffer fail......."); + + if(m_dataBufP) { + uint8_t* tmp=m_audioData.getRenderAudioData(m_blockSize<<2); + if(tmp){ + memcpy(m_dataBufP,tmp,m_blockSize<<2); + + }else{ + + memset(m_dataBufP,0,m_blockSize<<2); + } + } + + DWORD dwFlags(0); + hr = m_renderClient->ReleaseBuffer(m_blockSize, dwFlags); + if (FAILED(hr)) return yang_error_wrap(ERROR_SYS_AudioRender,"renderClient getBuffer fail......."); + + + } + + + } + return Yang_Ok; +} + + +int YangWinAudioApiRender::render_aec_10ms(){ + HRESULT hr = m_clientOut->GetCurrentPadding(&padding); + if (FAILED(hr)) return yang_error_wrap(ERROR_SYS_AudioRender,"outClient GetCurrentPadding fail......."); + m_dataBufP=NULL; + framesAvailable = m_bufferLength - padding; + if(framesAvailable0) { + const uint32_t n10ms = (framesAvailable /m_blockSize); + for (uint32_t n = 0; n < n10ms; n++) { + // render buffer. + hr = m_renderClient->GetBuffer(m_blockSize, &m_dataBufP); + if (FAILED(hr)) + return yang_error_wrap(ERROR_SYS_AudioRender,"renderClient getBuffer fail......."); + + if(m_dataBufP) { + uint8_t* tmp=m_audioData.getRenderAudioData(m_blockSize<<2); + if(tmp){ + memcpy(m_dataBufP,tmp,m_blockSize<<2); + m_audioData.setRenderLen(m_blockSize<<2); + }else + memset(m_dataBufP,0,m_blockSize<<2); + } + + DWORD dwFlags(0); + hr = m_renderClient->ReleaseBuffer(m_blockSize, dwFlags); + uint8_t* aectmp=m_audioData.getAecAudioData(); + if(aectmp){ + if(m_aec) m_aec->echo_playback((short*)aectmp); + if(!m_hasRenderEcho) m_hasRenderEcho=1; + + } + if (FAILED(hr)) return yang_error_wrap(ERROR_SYS_AudioRender,"renderClient getBuffer fail......."); + + + } + + + + } + return Yang_Ok; + +} + +/** +void YangWinAudioApiRender::run() { + m_isStart=1; + startLoop(); + m_isStart=0; +} +void YangWinAudioApiRender::stop() { + stopLoop(); + +}**/ +void YangWinAudioApiRender::stopLoop() { + stopRender(); + m_loops = 0; +} + + void YangWinAudioApiRender::startLoop() { + + DWORD taskIndex(0); + HANDLE hMmTask = AvSetMmThreadCharacteristicsA("Pro Audio", &taskIndex); + if (hMmTask) { + if (FALSE == AvSetMmThreadPriority(hMmTask, AVRT_PRIORITY_CRITICAL)) { + yang_warn( "failed to boost play-thread using MMCSS"); + } + yang_trace("render thread is now registered with MMCSS (taskIndex=%d)", + taskIndex ); + } else { + yang_error( "failed to enable MMCSS on render thread (err=%lu", GetLastError() ); + + } + + + m_loops = 1; + UINT32 bufferLength = 0; + HRESULT hr = m_clientOut->GetBufferSize(&bufferLength); + if (FAILED(hr)) + yang_error("renderClient getBuffersize fail......."); + BYTE* pData = NULL; + hr = m_renderClient->GetBuffer(bufferLength, &pData); + if (FAILED(hr)) + yang_error("renderClient getBuffer fail......."); + + hr = m_renderClient->ReleaseBuffer(bufferLength, AUDCLNT_BUFFERFLAGS_SILENT); + if(startRender()){ + yang_error("start render fail"); + return; + } + + HANDLE waitArray[1] = {m_samplesReadyEvent}; + while (m_loops == 1) { + DWORD waitResult = WaitForMultipleObjects(1, waitArray, FALSE, 500); + if(waitResult==(WAIT_OBJECT_0 + 0)){ + if(m_aec) + render_aec_10ms(); + else + render_10ms(); + + } + + + } + +} + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.h new file mode 100644 index 0000000000000000000000000000000000000000..d254624737e82694cae8a24e001f996f7f597e70 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioApiRender.h @@ -0,0 +1,99 @@ + +#ifndef YangWinAudioApiRender_H +#define YangWinAudioApiRender_H +#ifdef _WIN32 +#include +#include +//#include +#include +#include +#include +#include +#include +#include + +class YangWinAudioApiRender:public YangWinAudioApi,public YangAudioPlay +{ +public: + YangWinAudioApiRender(YangContext *pcontext); +virtual ~YangWinAudioApiRender(); +public: + int initRender(); + void setAec(YangAecBase *paec); + //void setAudioList(YangAudioPlayBuffer *pal); + int playThread(); + int startRender(); + int stopRender(); + int render_10ms(); + int render_aec_10ms(); + + int m_contextt; + // int m_isStart; + //YangRenderAudioData m_audioData; + + int init(); + int m_hasRenderEcho; + int32_t m_loops; + // void stop(); +protected: + + YangFrame m_audioFrame; +private: + + int32_t m_audioPlayCacheNum; + // int32_t m_sample; + int32_t m_size; + YangResample m_res; + + uint8_t* m_resBuf; + uint8_t* m_resTmp; + + + int32_t m_bufLen; + uint32_t m_blockSize; + + // uint8_t* m_aecBuf; + // int32_t m_aecBufLen; + + +protected: + virtual void startLoop(); + void stopLoop(); + // void run(); + + YangAecBase *m_aec; + HANDLE m_samplesReadyEvent; +private: + + IMMDeviceCollection* m_renderCollection; + IMMDevice* m_deviceOut; + IAudioClient* m_clientOut; + IAudioRenderClient* m_renderClient; + ISimpleAudioVolume* m_renderSimpleVolume; + + + UINT32 m_bufferLength; + + int getSpeakerVolume(int& volume); + int setSpeakerVolume(int volume); + int getSpeakerMute(bool& enabled); + int setSpeakerMute(bool enable); + + int initSpeaker(int pind); + int initPlay(int pind); + int setFormat(WAVEFORMATEX *pwfx); + + + int m_outputDeviceIndex; + + // YangPlayData m_playData; + + BYTE* m_dataBufP ; + DWORD flags ; + UINT32 padding; + uint32_t framesAvailable; + bool keepPlaying; + +}; +#endif +#endif // YangWinAudioApiRender_H diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa92717e143ffe5f0884c03cc9306d40abe9fbbb --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.cpp @@ -0,0 +1,260 @@ +#include +#ifdef _WIN32 +#include +#include +#include +#include + +using namespace std; +#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } +YangWinAudioCapture::YangWinAudioCapture(YangContext *pcontext){ // @suppress("Class members should be properly initialized") + m_context = pcontext; + m_ahandle = new YangWinAudioCaptureHandle(pcontext); + + //m_writeInit = 0, m_writeRet = 0; + //m_readInit = 0; + aIndex = 0; + m_ret = 0; + m_size = 0; + m_loops = 0; + + m_isInit = 0; + + m_frames = 1024; + m_channel = 2; + m_sample = 44100; + m_pg = NULL; + m_pb = NULL; + m_pm = NULL; + m_grabber = NULL; + m_grabberF = NULL; + m_event = NULL; + m_nullRender = NULL; + m_audioSrc = NULL; + m_moniker = NULL; + m_mt = NULL; + aIndex = 1; + if (m_context->audio.usingMono) { + m_frames = 320; + m_channel = 1; + m_sample = 16000; + } else { + m_frames = 1024; + } + +} +YangWinAudioCapture::~YangWinAudioCapture() { + + if (m_loops) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + //a delete pMoniker1,pGrabber,pGrabberF,pEvent; + if(m_ahandle){ + SAFE_RELEASE(m_grabber); + SAFE_RELEASE(m_grabberF); + + SAFE_RELEASE(m_event); + SAFE_RELEASE(m_pm); + SAFE_RELEASE(m_pg); + SAFE_RELEASE(m_pb); + SAFE_RELEASE(m_audioSrc); + // SAFE_RELEASE(pMoniker1); + yang_delete(m_ahandle); + } +} +void YangWinAudioCapture::setCatureStart() { + m_ahandle->isBuf = 1; +} +void YangWinAudioCapture::setCatureStop() { + m_ahandle->isBuf = 0; +} +void YangWinAudioCapture::setOutAudioBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangWinAudioCapture::setPlayAudoBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->m_aecPlayBuffer = pbuffer; +} +void YangWinAudioCapture::setAec(YangAecBase *paec) { + m_ahandle->setAec(paec); +} +void YangWinAudioCapture::setPreProcess(YangPreProcess *pp) { + m_ahandle->m_preProcess = pp; + if (pp) { + pp->init(m_frames, m_sample, m_channel); + } +} + +void YangWinAudioCapture::setInAudioBuffer(vector *pal) { + m_ahandle->setInAudioBuffer(pal); +} +void YangWinAudioCapture::stopLoop() { + m_loops = 0; + if(m_pm!=NULL) m_pm->Stop(); +} + +HRESULT YangWinAudioCapture::GetUnconnectPin(IBaseFilter *pFilter, + PIN_DIRECTION dir, IPin **ppPin) { + *ppPin = 0; + IEnumPins *pEnum = 0; + IPin *pPin = 0; + HRESULT hr = pFilter->EnumPins(&pEnum); + if (FAILED(hr)) { + return hr; + } + while (pEnum->Next(1, &pPin, NULL) == S_OK) { + PIN_DIRECTION thisPinDir; + pPin->QueryDirection(&thisPinDir); + if (thisPinDir == dir) { + IPin *pTemp = 0; + hr = pPin->ConnectedTo(&pTemp); + if (SUCCEEDED(hr)) { + pTemp->Release(); + } else { + pEnum->Release(); + *ppPin = pPin; + return S_OK; + } + } + pPin->Release(); + } + pEnum->Release(); + return E_FAIL; +} + +IPin* YangWinAudioCapture::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir) { + IEnumPins *pEnumPins; + IPin *pOutpin; + PIN_DIRECTION pDir; + pFilter->EnumPins(&pEnumPins); + while (pEnumPins->Next(1, &pOutpin, NULL) == S_OK) { + pOutpin->QueryDirection(&pDir); + + if (pDir == dir) { + return pOutpin; + } + } + return 0; +} +void YangWinAudioCapture::setPara() { +// printf("set pararm is starting...\n"); + int32_t nBytesPerSample = 2; + IAMStreamConfig *config = NULL; + HRESULT hr = m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, + m_audioSrc, IID_IAMStreamConfig, (void**) &config); + AM_MEDIA_TYPE *pmt = { 0 }; + hr = config->GetFormat(&pmt); + if (SUCCEEDED(hr)) { + + WAVEFORMATEX *pWF = (WAVEFORMATEX*) pmt->pbFormat; + pmt->subtype = MEDIASUBTYPE_PCM; + + pWF->nChannels = (WORD) m_channel; //m_sample;//2; + pWF->nSamplesPerSec = m_sample; //44100; + pWF->nAvgBytesPerSec = nBytesPerSample * m_channel * m_sample;//4 * 44100; + pWF->wBitsPerSample = nBytesPerSample * 8; + pWF->nBlockAlign = nBytesPerSample * m_channel; //4; + hr = config->SetFormat(pmt); + SAFE_RELEASE(config); + + IAMBufferNegotiation *pNeg = NULL; + hr = m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, + m_audioSrc, IID_IAMBufferNegotiation, (void**) &pNeg); + ALLOCATOR_PROPERTIES prop = { 0 }; + prop.cbBuffer = m_frames * nBytesPerSample * m_channel; + prop.cBuffers = 6; + prop.cbAlign = nBytesPerSample * m_channel; + hr = pNeg->SuggestAllocatorProperties(&prop); + SAFE_RELEASE(pNeg); +//DeleteMediaType(pmt); + } else { + printf("set parar is fail!..........\n"); + } + +} +int32_t YangWinAudioCapture::init() { + if (m_isInit) + return Yang_Ok; + + CoInitialize(NULL); + + ULONG cFetched; + ICreateDevEnum *devEnum = NULL; + CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + IID_PPV_ARGS(&devEnum)); + IEnumMoniker *classEnum = NULL; + devEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, + &classEnum, 0); + int32_t aco = 0; + while (classEnum->Next(1, &m_moniker, &cFetched) == S_OK) { + aco++; + if (aco != aIndex) + continue; + m_moniker->BindToObject(0, 0, IID_IBaseFilter, (void**) &m_audioSrc); + m_moniker->Release(); + break; + } + classEnum->Release(); + devEnum->Release(); + if (m_audioSrc == NULL) + return 1; + CoCreateInstance(CLSID_CaptureGraphBuilder2, 0, CLSCTX_INPROC_SERVER, + IID_ICaptureGraphBuilder2, (void**) &m_pb); + CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + IID_IGraphBuilder, (void**) &m_pg); + + m_pb->SetFiltergraph(m_pg); + m_pg->QueryInterface(IID_IMediaControl, (void**) &m_pm); + m_pg->AddFilter(m_audioSrc, L"Audio"); + + CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, + 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + //sample*********************************** + HRESULT hr = CoCreateInstance(CLSID_SampleGrabber, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_grabberF)); + hr = m_pg->AddFilter(m_grabberF, L"Sample Grabber"); + hr = m_grabberF->QueryInterface(IID_ISampleGrabber, (void**) &m_grabber); + //printf("pgrabber is %s",NUM_FRAMES_TO_GRAB); + hr = m_pg->QueryInterface(IID_IMediaEventEx, (void**) &m_event); + + m_nullRender = NULL; + CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, + 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC, + IID_IBaseFilter, (void**) &m_nullRender); + setPara(); + + IPin *pAudioOut = FindPin(m_audioSrc, PINDIR_OUTPUT); + IPin *pGrabin = FindPin(m_grabberF, PINDIR_INPUT); + IPin *pGrabout = FindPin(m_grabberF, PINDIR_OUTPUT); + IPin *pNullIn = FindPin(m_nullRender, PINDIR_INPUT); + hr = m_pg->Connect(pAudioOut, pGrabin); + hr = m_pg->Connect(pGrabout, pNullIn); + + //cs->list=list; + if (m_mt == NULL) m_mt = new AM_MEDIA_TYPE(); + hr = m_grabber->GetConnectedMediaType(m_mt); + //WAVEFORMATEX *wfx = (WAVEFORMATEX*) m_mt->pbFormat; + //printf("ahz=%d,channel=%d,bit=%d\n", wfx->nSamplesPerSec, wfx->nChannels,wfx->wBitsPerSample); + hr = m_grabber->SetMediaType(m_mt); + hr = m_grabber->SetBufferSamples(TRUE); + hr = m_grabber->SetOneShot(FALSE); + m_grabber->SetCallback(m_ahandle, 1); + m_isInit = 1; + return Yang_Ok; +} + +void YangWinAudioCapture::startLoop() { + m_loops = 1; + if (m_pm != NULL) { + m_pm->Run(); + long eventCode; + if(m_ahandle) m_ahandle->startRender(); + m_event->WaitForCompletion(INFINITE, &eventCode); + if(m_ahandle) m_ahandle->stopRender(); + } + //yang_deleteA(pcm_read); +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..3d907c97b6fd2133d2669cac5add6db3a0e5d8e1 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCapture.h @@ -0,0 +1,74 @@ + +#ifndef Yang_YangWinAudioCapture_H1 +#define Yang_YangWinAudioCapture_H1 + +#ifdef _WIN32 +#include "amstream.h" +#include +#include "qedit.h" +#include "yangavutil/audio/YangAudioMix.h" +#include "yangavutil/audio/YangPreProcess.h" +#include +#include + +#include "yangavutil/audio/YangAecBase.h" +class YangWinAudioCapture: public YangAudioCapture { +public: + YangWinAudioCapture(YangContext *pcontext); + ~YangWinAudioCapture(); + +public: + YangWinAudioCaptureHandle *m_ahandle; + + int32_t init(); + void setInAudioBuffer(vector *pal); + void setPreProcess(YangPreProcess *pp); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setAec(YangAecBase *paec); + +protected: + //void run(); + + void startLoop(); + + void stopLoop(); +private: + + int32_t m_isInit; + int32_t m_ret; + void setPara(); + void getBaseFilter(const GUID gi,IBaseFilter *ib,int32_t ind); + HRESULT GetUnconnectPin(IBaseFilter * pFilter,PIN_DIRECTION dir,IPin **ppPin); + IPin * FindPin(IBaseFilter * pFilter,PIN_DIRECTION dir); + IPin * FindPin1(IBaseFilter * pFilter,PIN_DIRECTION dir); + HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum); + +private: + //YangAlsaDevice *m_dev; + int32_t m_size; + int32_t m_loops; + int32_t m_channel; + uint32_t m_sample; + int32_t m_frames; + + AM_MEDIA_TYPE *m_mt; + IMediaControl *m_pm; + IGraphBuilder *m_pg; + ICaptureGraphBuilder2 *m_pb; + + IBaseFilter *m_audioSrc; + IBaseFilter *m_nullRender; + + IMoniker *m_moniker; + ISampleGrabber *m_grabber; + IBaseFilter *m_grabberF; + IMediaEventEx *m_event; +}; +//#ifdef __cplusplus +//} +//#endif +#endif +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d98c19a303c2fc4b7137345dc12fb0111448990 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.cpp @@ -0,0 +1,115 @@ + +#include "yangutil/yang_unistd.h" +#ifdef _WIN32 +#include +#include "YangWinAudioCaptureHandle.h" +#include +YangWinAudioCaptureHandle::YangWinAudioCaptureHandle(YangContext *pcontext):YangAudioCaptureHandle(pcontext) +{ + readStart=0; +#if UsingRenderApi + m_player = new YangWinAudioApiRender(pcontext); + if (m_player) m_player->init(); + m_isStartRender=0; +#else + m_player=new YangAudioPlaySdl(pcontext); + if(m_player) m_player->init(); +#endif + if (pcontext->audio.usingMono) { + m_len=320*2; + } else { + m_len = 1024*4; + } + m_buf=new uint8_t[m_len]; + m_preProcess=NULL; + m_aec=NULL; + + m_size=m_len; + + m_asyn=1;//pcontext->audioPlayType; + // m_asynStart=0; + +} +YangWinAudioCaptureHandle::~YangWinAudioCaptureHandle(void) +{ +#if UsingRenderApi + if(m_asyn){ + if(m_player&&m_player->m_isStart){ + yang_stop(m_player); + yang_stop_thread(m_player); + } + }else{ + if(m_isStartRender&&m_player) m_player->stopRender(); + } +#endif + m_preProcess = NULL; + if(m_player) delete m_player; + m_player=NULL; + if(m_buf) delete[] m_buf; + m_buf=NULL; + +} + + +STDMETHODIMP_(ULONG) YangWinAudioCaptureHandle::AddRef() { return 1; } +STDMETHODIMP_(ULONG) YangWinAudioCaptureHandle::Release() { return 2; } + +STDMETHODIMP YangWinAudioCaptureHandle::QueryInterface(REFIID riid, void **ppvObject) +{ + + if (NULL == ppvObject) return E_POINTER; + if (riid == __uuidof(IUnknown)) + { + *ppvObject = static_cast(this); + return S_OK; + } + if (riid == IID_ISampleGrabber) + { + *ppvObject = static_cast(this); + return S_OK; + } + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE YangWinAudioCaptureHandle::SampleCB(double Time, IMediaSample *pSample) +{ + + return E_NOTIMPL; +} +void YangWinAudioCaptureHandle::setInAudioBuffer(vector *pal) { + //if(m_player&&m_player->m_audioData.m_syn) m_player->m_audioData.m_syn->setInAudioBuffer(pal); +} + +void YangWinAudioCaptureHandle::startRender(){ +#if UsingRenderApi + if(m_asyn&&m_player) m_player->start(); +#endif +} +void YangWinAudioCaptureHandle::stopRender(){ +#if UsingRenderApi + if(m_asyn){ + yang_stop(m_player); + yang_stop_thread(m_player); + } +#endif +} +void YangWinAudioCaptureHandle::setAec(YangAecBase *aec){ + this->m_aec=aec; + if(m_player) m_player->setAec(aec); +} +HRESULT STDMETHODCALLTYPE YangWinAudioCaptureHandle::BufferCB(double Time, BYTE *pBuffer, LONG BufferLen) +{ + if (!readStart) { + readStart=m_player->m_hasRenderEcho; + } + if (readStart) + putEchoBuffer(pBuffer,BufferLen); + else + putBuffer1(pBuffer,BufferLen); + + + return E_NOTIMPL; +} + + +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..2124a3ca571f06797a6960220b98596fc48c5452 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioCaptureHandle.h @@ -0,0 +1,59 @@ +#ifndef ___YangWinAudioCaptureHandlee__ +#define ___YangWinAudioCaptureHandlee__ +#ifdef _WIN32 +#include "qedit.h" +#include "yangavutil/audio/YangMakeWave.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include +#include "../YangAudioCaptureHandle.h" +#define UsingRenderApi 1 + +#if UsingRenderApi +#include "YangWinAudioApiRender.h" +#else +#include "YangAudioPlaySdl.h" +#endif + + +class YangWinAudioCaptureHandle: public ISampleGrabberCB,public YangAudioCaptureHandle +{ +public: + YangWinAudioCaptureHandle(YangContext *pcontext); + virtual ~YangWinAudioCaptureHandle(void); + int32_t readStart; + + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); + HRESULT STDMETHODCALLTYPE SampleCB(double Time, IMediaSample *pSample); + HRESULT STDMETHODCALLTYPE BufferCB(double Time, BYTE *pBuffer, LONG BufferLen); + +public: + YangPreProcess *m_preProcess; + void setInAudioBuffer(vector *pal); + void setAec(YangAecBase *aec); + void startRender(); + void stopRender(); + + +private: + uint8_t *m_buf; + int32_t m_len; + + int32_t m_size; + int m_asyn; + // int m_asynStart; + + + +#if UsingRenderApi + YangWinAudioApiRender* m_player; + int m_isStartRender; +#else + YangAudioPlaySdl *m_player; +#endif + + +}; +#endif +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinAudioDevice.h b/libyangrtc2/src/yangaudiodev/win/YangWinAudioDevice.h new file mode 100644 index 0000000000000000000000000000000000000000..07b01c7fc973d912cd0f05a8b1869c8c97742227 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinAudioDevice.h @@ -0,0 +1,110 @@ +#ifndef YANGWINAUDIODEVICE_H +#define YANGWINAUDIODEVICE_H +#ifdef _WIN32 +#include +#include +#include +#include +#include +const float MAX_SPEAKER_VOLUME = 255.0f; +const float MIN_SPEAKER_VOLUME = 0.0f; +const float MAX_MICROPHONE_VOLUME = 255.0f; +const float MIN_MICROPHONE_VOLUME = 0.0f; +class YangWinAudioDevice +{ +public: + YangWinAudioDevice(); + virtual ~YangWinAudioDevice(); + void init(); + void startBuiltInAec(); + int32_t getDeviceListCount(EDataFlow dir); + int32_t playoutDeviceCount(); + int32_t enumEndpointDevicesAll(EDataFlow dataFlow); + int32_t getDeviceID(IMMDevice* pDevice,LPWSTR pszBuffer, int32_t bufferLen); + int32_t getDefaultDeviceID(EDataFlow dir, ERole role,LPWSTR szBuffer,int32_t bufferLen); + int32_t getDefaultDevice(EDataFlow dir,ERole role,IMMDevice** ppDevice); + int32_t getDefaultDeviceIndex(EDataFlow dir,ERole role,int* index); + + int32_t initCapture(); + int32_t initMicrophone(int32_t pind); + int32_t initSpeaker(int32_t pind); + int32_t initPlay(); + int32_t getListDevice(EDataFlow dir,int32_t index,IMMDevice** ppDevice); + + int32_t getMicrophoneVolume(int& volume); + int32_t setMicrophoneVolume(int32_t volume); + int32_t setMicrophoneMute(bool enable); + + int32_t getSpeakerVolume(int& volume); + int32_t setSpeakerVolume(int32_t volume); + int32_t getSpeakerMute(bool& enabled); + int32_t setSpeakerMute(bool enable); + + void captureThread(); + int32_t playThread(); +private: + IMMDeviceEnumerator* m_enum; + IMMDeviceCollection* m_renderCollection; + IMMDeviceCollection* m_captureCollection; + IMMDevice* m_deviceOut; + IMMDevice* m_deviceIn; + + IMediaObject* m_dmo; + + IAudioClient* m_clientOut; + IAudioClient* m_clientIn; + IAudioRenderClient* m_renderClient; + IAudioCaptureClient* m_captureClient; + IAudioEndpointVolume* m_captureVolume; + ISimpleAudioVolume* m_renderSimpleVolume; + + boolean _builtInAecEnabled; +double _perfCounterFactor; +uint32_t _sndCardPlayDelay; +int32_t _inputDeviceIndex=0,_outputDeviceIndex=0; +UINT64 _writtenSamples; +UINT64 _readSamples; + + UINT _playAudioFrameSize; +uint32_t _playSampleRate; +uint32_t _devicePlaySampleRate; +uint32_t _playBlockSize; +uint32_t _devicePlayBlockSize; +uint32_t _playChannels; + +UINT _recAudioFrameSize; +uint32_t _recSampleRate; +uint32_t _recBlockSize; +uint32_t _recChannels; + std::mutex m_lock; +private: + int32_t initRecordingDMO(); + int32_t setDMOProperties(); + int32_t setBoolProperty(IPropertyStore* ptrPS, REFPROPERTYKEY key,VARIANT_BOOL value); + int32_t setVtI4Property(IPropertyStore* ptrPS, REFPROPERTYKEY key,LONG value); + + HANDLE _hRenderSamplesReadyEvent; + HANDLE _hPlayThread; + HANDLE _hRenderStartedEvent; + HANDLE _hShutdownRenderEvent; + + HANDLE _hCaptureSamplesReadyEvent; + HANDLE _hRecThread; + HANDLE _hCaptureStartedEvent; + HANDLE _hShutdownCaptureEvent; + +LARGE_INTEGER _perfCounterFreq; + uint16_t _recChannelsPrioList[3]; + uint16_t _playChannelsPrioList[2]; + + bool _initialized; + bool _recording; + bool _playing; + bool _recIsInitialized; + bool _playIsInitialized; + bool _speakerIsInitialized; + bool _microphoneIsInitialized; + +}; +#endif +#endif // YANGWINAUDIODEVICE_H diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.cpp b/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66c604acf5991c317cde92a07860c31b24d67ac8 --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.cpp @@ -0,0 +1,253 @@ +#include +#ifdef _WIN32 +#include +#include +#include +#include +//#pragma comment(lib, "strmiids") +using namespace std; + +#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } +YangWinRecordAudioCapture::YangWinRecordAudioCapture(YangContext *pcontext) { + m_context = pcontext; + m_ahandle = new YangRecAudioCaptureHandle(pcontext); + + aIndex = 0; + m_ret = 0; + m_size = 0; + m_loops = 0; + + m_isInit = 0; + + m_frames=960; + m_channel = pcontext->audio.channel; + m_sample = pcontext->audio.sample; + + m_pg = NULL; + m_pb = NULL; + m_pm = NULL; + m_grabber = NULL; + m_grabberF = NULL; + m_event = NULL; + m_nullRender = NULL; + m_audioSrc = NULL; + m_moniker = NULL; + m_mt = NULL; + aIndex = 1; + + if(m_sample==44100) m_frames = 1024; + + if(m_sample==48000) m_frames=960; + +} +YangWinRecordAudioCapture::~YangWinRecordAudioCapture() { + + if (m_loops) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + + if(m_ahandle){ + SAFE_RELEASE(m_grabber); + SAFE_RELEASE(m_grabberF); + + SAFE_RELEASE(m_event); + SAFE_RELEASE(m_pm); + SAFE_RELEASE(m_pg); + SAFE_RELEASE(m_pb); + SAFE_RELEASE(m_audioSrc); + + yang_delete(m_ahandle); + } +} +void YangWinRecordAudioCapture::setCatureStart() { + m_ahandle->isBuf = 1; +} +void YangWinRecordAudioCapture::setCatureStop() { + m_ahandle->isBuf = 0; +} +void YangWinRecordAudioCapture::setOutAudioBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->setOutAudioBuffer(pbuffer); +} +void YangWinRecordAudioCapture::setPlayAudoBuffer(YangAudioBuffer *pbuffer) { + m_ahandle->m_aecPlayBuffer = pbuffer; +} +void YangWinRecordAudioCapture::setAec(YangAecBase *paec) { + m_ahandle->m_aec = paec; +} +void YangWinRecordAudioCapture::setPreProcess(YangPreProcess *pp) { + +} + +void YangWinRecordAudioCapture::setInAudioBuffer(vector *pal) { + +} +void YangWinRecordAudioCapture::stopLoop() { + m_loops = 0; + if(m_pm!=NULL) m_pm->Stop(); +} + + + +HRESULT YangWinRecordAudioCapture::GetUnconnectPin(IBaseFilter *pFilter, + PIN_DIRECTION dir, IPin **ppPin) { + *ppPin = 0; + IEnumPins *pEnum = 0; + IPin *pPin = 0; + HRESULT hr = pFilter->EnumPins(&pEnum); + if (FAILED(hr)) { + return hr; + } + while (pEnum->Next(1, &pPin, NULL) == S_OK) { + PIN_DIRECTION thisPinDir; + pPin->QueryDirection(&thisPinDir); + if (thisPinDir == dir) { + IPin *pTemp = 0; + hr = pPin->ConnectedTo(&pTemp); + if (SUCCEEDED(hr)) { + pTemp->Release(); + } else { + pEnum->Release(); + *ppPin = pPin; + return S_OK; + } + } + pPin->Release(); + } + pEnum->Release(); + return E_FAIL; +} + +IPin* YangWinRecordAudioCapture::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir) { + IEnumPins *pEnumPins; + IPin *pOutpin; + PIN_DIRECTION pDir; + pFilter->EnumPins(&pEnumPins); + while (pEnumPins->Next(1, &pOutpin, NULL) == S_OK) { + pOutpin->QueryDirection(&pDir); + + if (pDir == dir) { + return pOutpin; + } + } + return 0; +} +void YangWinRecordAudioCapture::setPara() { +// printf("set pararm is starting...\n"); + int32_t nBytesPerSample = 2; + IAMStreamConfig *config = NULL; + HRESULT hr = m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, + m_audioSrc, IID_IAMStreamConfig, (void**) &config); + AM_MEDIA_TYPE *pmt = { 0 }; + hr = config->GetFormat(&pmt); + if (SUCCEEDED(hr)) { + + WAVEFORMATEX *pWF = (WAVEFORMATEX*) pmt->pbFormat; + pmt->subtype = MEDIASUBTYPE_PCM; + + pWF->nChannels = (WORD) m_channel; //m_sample;//2; + pWF->nSamplesPerSec = m_sample; //44100; + pWF->nAvgBytesPerSec = nBytesPerSample * m_channel * m_sample;//4 * 44100; + pWF->wBitsPerSample = nBytesPerSample * 8; + pWF->nBlockAlign = nBytesPerSample * m_channel; //4; + hr = config->SetFormat(pmt); + SAFE_RELEASE(config); + + IAMBufferNegotiation *pNeg = NULL; + hr = m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, + m_audioSrc, IID_IAMBufferNegotiation, (void**) &pNeg); + ALLOCATOR_PROPERTIES prop = { 0 }; + prop.cbBuffer = m_frames * nBytesPerSample * m_channel; + prop.cBuffers = 6; + prop.cbAlign = nBytesPerSample * m_channel; + hr = pNeg->SuggestAllocatorProperties(&prop); + SAFE_RELEASE(pNeg); +//DeleteMediaType(pmt); + } else { + printf("set parar is fail!..........\n"); + } + +} +int32_t YangWinRecordAudioCapture::init() { + if (m_isInit) + return Yang_Ok; + + CoInitialize(NULL); + + ULONG cFetched; + ICreateDevEnum *devEnum = NULL; + CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + IID_PPV_ARGS(&devEnum)); + IEnumMoniker *classEnum = NULL; + devEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, + &classEnum, 0); + int32_t aco = 0; + while (classEnum->Next(1, &m_moniker, &cFetched) == S_OK) { + aco++; + if (aco != aIndex) + continue; + m_moniker->BindToObject(0, 0, IID_IBaseFilter, (void**) &m_audioSrc); + m_moniker->Release(); + break; + } + classEnum->Release(); + devEnum->Release(); + if (m_audioSrc == NULL) + return 1; + CoCreateInstance(CLSID_CaptureGraphBuilder2, 0, CLSCTX_INPROC_SERVER, + IID_ICaptureGraphBuilder2, (void**) &m_pb); + CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + IID_IGraphBuilder, (void**) &m_pg); + + m_pb->SetFiltergraph(m_pg); + m_pg->QueryInterface(IID_IMediaControl, (void**) &m_pm); + m_pg->AddFilter(m_audioSrc, L"Audio"); + + CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, + 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + + HRESULT hr = CoCreateInstance(CLSID_SampleGrabber, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_grabberF)); + hr = m_pg->AddFilter(m_grabberF, L"Sample Grabber"); + hr = m_grabberF->QueryInterface(IID_ISampleGrabber, (void**) &m_grabber); + + hr = m_pg->QueryInterface(IID_IMediaEventEx, (void**) &m_event); + + m_nullRender = NULL; + CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, + 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC, + IID_IBaseFilter, (void**) &m_nullRender); + setPara(); + + IPin *pAudioOut = FindPin(m_audioSrc, PINDIR_OUTPUT); + IPin *pGrabin = FindPin(m_grabberF, PINDIR_INPUT); + IPin *pGrabout = FindPin(m_grabberF, PINDIR_OUTPUT); + IPin *pNullIn = FindPin(m_nullRender, PINDIR_INPUT); + hr = m_pg->Connect(pAudioOut, pGrabin); + hr = m_pg->Connect(pGrabout, pNullIn); + + + if (m_mt == NULL) m_mt = new AM_MEDIA_TYPE(); + hr = m_grabber->GetConnectedMediaType(m_mt); + + hr = m_grabber->SetMediaType(m_mt); + hr = m_grabber->SetBufferSamples(TRUE); + hr = m_grabber->SetOneShot(FALSE); + m_grabber->SetCallback(m_ahandle, 1); + m_isInit = 1; + return Yang_Ok; +} + +void YangWinRecordAudioCapture::startLoop() { + m_loops = 1; + if (m_pm != NULL) { + m_pm->Run(); + long eventCode; + m_event->WaitForCompletion(INFINITE, &eventCode); + } + +} +#endif diff --git a/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.h b/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..7dcc4a602e6dfabdeedeed1aec0375df3e99b77a --- /dev/null +++ b/libyangrtc2/src/yangaudiodev/win/YangWinRecordAudioCapture.h @@ -0,0 +1,74 @@ + +#ifndef Yang_YangWinRecordAudioCapture_H1 +#define Yang_YangWinRecordAudioCapture_H1 + +#ifdef _WIN32 +#include "amstream.h" +#include +#include "qedit.h" +#include "yangavutil/audio/YangAudioMix.h" +#include "yangavutil/audio/YangPreProcess.h" +#include +#include + +#include "yangavutil/audio/YangAecBase.h" +class YangWinRecordAudioCapture: public YangAudioCapture { +public: + YangWinRecordAudioCapture(YangContext *pcontext); + ~YangWinRecordAudioCapture(); + +public: + YangRecAudioCaptureHandle *m_ahandle; + + int32_t init(); + void setInAudioBuffer(vector *pal); + void setPreProcess(YangPreProcess *pp); + void setCatureStart(); + void setCatureStop(); + void setOutAudioBuffer(YangAudioBuffer *pbuffer); + void setPlayAudoBuffer(YangAudioBuffer *pbuffer); + void setAec(YangAecBase *paec); + +protected: + //void run(); + + void startLoop(); + + void stopLoop(); +private: + + int32_t m_isInit; + int32_t m_ret; + void setPara(); + void getBaseFilter(const GUID gi,IBaseFilter *ib,int32_t ind); + HRESULT GetUnconnectPin(IBaseFilter * pFilter,PIN_DIRECTION dir,IPin **ppPin); + IPin * FindPin(IBaseFilter * pFilter,PIN_DIRECTION dir); + IPin * FindPin1(IBaseFilter * pFilter,PIN_DIRECTION dir); + HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum); + +private: + //YangAlsaDevice *m_dev; + int32_t m_size; + int32_t m_loops; + int32_t m_channel; + uint32_t m_sample; + int32_t m_frames; + + AM_MEDIA_TYPE *m_mt; + IMediaControl *m_pm; + IGraphBuilder *m_pg; + ICaptureGraphBuilder2 *m_pb; + + IBaseFilter *m_audioSrc; + IBaseFilter *m_nullRender; + + IMoniker *m_moniker; + ISampleGrabber *m_grabber; + IBaseFilter *m_grabberF; + IMediaEventEx *m_event; +}; +//#ifdef __cplusplus +//} +//#endif +#endif +#endif diff --git a/libyangrtc2/src/yangavutil/YangAecBase.cpp b/libyangrtc2/src/yangavutil/YangAecBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2ae1dc786208deedf951c605f5857e235a38607 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAecBase.cpp @@ -0,0 +1,21 @@ +/* + * YangAecBase.cpp + * + * Created on: 2019年11月16日 + * Author: yang + */ + +#include + +YangAecBase::YangAecBase() { + m_channel=2; + m_frameSize=1024; + m_sampleRate=44100; + m_echoPath=20; +} + +YangAecBase::~YangAecBase() { + +} + + diff --git a/libyangrtc2/src/yangavutil/YangAecSpeex.cpp b/libyangrtc2/src/yangavutil/YangAecSpeex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd1e9a81b1b0862a892abdf8e9fdb97abbeff7b8 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAecSpeex.cpp @@ -0,0 +1,155 @@ +/* + * YangAceSpeex.cpp + * + * Created on: 2020年9月8日 + * Author: yang + */ + +#include "YangAecSpeex.h" + +#include "stdio.h" +#ifndef NULL +#define NULL ((void *)0) +#endif + + +void YangAecSpeex::loadLib(){ + //yang_opus_encoder_create=(OpusEncoder *(*)(opus_int32_t Fs, int32_t channels, int32_t application, int32_t *error))m_lib.loadFunction(""); + yang_speex_preprocess_state_init=(SpeexPreprocessState *(*)(int32_t frame_size, int32_t sampling_rate))m_lib.loadFunction("speex_preprocess_state_init");; + yang_speex_preprocess_ctl=(int32_t (*)(SpeexPreprocessState *st, int32_t request, void *ptr))m_lib.loadFunction("speex_preprocess_ctl");; + yang_speex_preprocess_state_destroy=(void (*)(SpeexPreprocessState *st))m_lib.loadFunction("speex_preprocess_state_destroy");; + yang_speex_preprocess_run=(int32_t (*)(SpeexPreprocessState *st, spx_int16_t *x))m_lib.loadFunction("speex_preprocess_run"); + + yang_speex_echo_state_init_mc=(SpeexEchoState *(*)(int32_t frame_size, int32_t filter_length, int32_t nb_mic, int32_t nb_speakers))m_lib.loadFunction("speex_echo_state_init_mc"); + yang_speex_echo_ctl=(int32_t (*)(SpeexEchoState *st, int32_t request, void *ptr))m_lib.loadFunction("speex_echo_ctl"); + yang_speex_echo_state_reset=(void (*)(SpeexEchoState *st))m_lib.loadFunction("speex_echo_state_reset"); + yang_speex_echo_playback=(void (*)(SpeexEchoState *st, const spx_int16_t *play))m_lib.loadFunction("speex_echo_playback"); + yang_speex_echo_capture=(void (*)(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out))m_lib.loadFunction("speex_echo_capture"); + yang_speex_echo_cancellation=(void (*)(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out))m_lib.loadFunction("speex_echo_cancellation"); + yang_speex_echo_state_destroy=(void (*)(SpeexEchoState *st))m_lib.loadFunction("speex_echo_state_destroy"); +} + +void YangAecSpeex::unloadLib(){ + yang_speex_preprocess_state_init=NULL; + yang_speex_preprocess_ctl=NULL; + yang_speex_preprocess_state_destroy=NULL; + yang_speex_preprocess_run=NULL; + + yang_speex_echo_state_init_mc=NULL; + yang_speex_echo_ctl=NULL; + yang_speex_echo_state_reset=NULL; + yang_speex_echo_playback=NULL; + yang_speex_echo_capture=NULL; + yang_speex_echo_cancellation=NULL; + yang_speex_echo_state_destroy=NULL; +} +YangAecSpeex::YangAecSpeex() { + memset(&m_audioFrame,0,sizeof(YangFrame)); + m_bHasInit = false; + m_state = NULL; + m_preprocState = NULL; + m_audioBuffer = NULL; + unloadLib(); + //m_nFrameSize = 0; + //m_nFilterLen = 0; + //m_nSampleRate = 0; +} + +YangAecSpeex::~YangAecSpeex() { + closeAec(); + m_audioBuffer = NULL; + unloadLib(); + m_lib.unloadObject(); +} +void YangAecSpeex::setPlayBuffer(YangAudioBuffer *pab) { + m_audioBuffer = pab; +} +void YangAecSpeex::init(int32_t pFrameSize, int32_t sampleRate, int32_t pchannel) { + if (m_bHasInit) + return; + m_lib.loadObject("libspeexdsp"); + loadLib(); + resetAec(); + m_frameSize = pFrameSize; + m_sampleRate = sampleRate; + m_channel = pchannel; + int32_t frame_size = m_frameSize;//(m_frameSizeInMS * m_sampleRate * 1.0) / 1000; + int32_t filter_length = m_frameSize * m_echoPath;//20;//30;//m_echoPath;//(m_frameSizeInMS * m_sampleRate * 1.0) / 1000; + //m_nFrameSize = frame_size; + //m_nFilterLen = filter_length; + //m_nSampleRate = sampleRate; + //通常是m_nFrameSize 80 160 320 + //m_pState = speex_echo_state_init(m_nFrameSize, 10*m_nFrameSize); + if(!m_state) m_state = yang_speex_echo_state_init_mc(frame_size, filter_length, m_channel,m_channel); + //m_pState = aec->speex_echo_state_init_mc(m_nFrameSize, m_nFilterLen, 2, 2); + //frame_size *= 2; // length read each time + + if(!m_preprocState) m_preprocState = yang_speex_preprocess_state_init(frame_size, m_sampleRate); + + yang_speex_echo_ctl(m_state, SPEEX_ECHO_SET_SAMPLING_RATE, &m_sampleRate); + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_ECHO_STATE, + m_state); + int32_t i = 1; + //speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_VAD, &i); + int32_t noiseSuppress = -25; + i = 1; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DENOISE, &i); + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &noiseSuppress); + i=0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_AGC, &i); + i=sampleRate; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i); + i=0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB, &i); + float f=.0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f); + f=.0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); + + + //printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>> init Aec frameSize=%d,filterLen=%d,sample=%d channel==%d",frame_size,filter_length,m_sampleRate,m_channel); + //m_pfNoise = new float[m_nFrameSize + 1]; + m_bHasInit = true; +} + +void YangAecSpeex::closeAec() { + if(m_state) yang_speex_echo_state_destroy(m_state); + if(m_preprocState) yang_speex_preprocess_state_destroy(m_preprocState); + m_state = 0; + m_preprocState = 0; + +} +void YangAecSpeex::resetAec() { + closeAec(); + + m_bHasInit = false; +} +void YangAecSpeex::echo_state_reset() { + if(m_state) yang_speex_echo_state_reset(m_state); +} +void YangAecSpeex::echo_playback(short *play) { + //printf(","); + if(m_state) yang_speex_echo_playback(m_state, play); +} +void YangAecSpeex::echo_cancellation(const short *rec, const short *play, + short *out) { + if(m_state) yang_speex_echo_cancellation(m_state, rec, play, out); +} + +void YangAecSpeex::put_echo_playback(uint8_t *play,int32_t plen) { + //printf(","); + if (m_audioBuffer){ + m_audioFrame.payload=play; + m_audioFrame.nb=plen; + m_audioBuffer->putAudio(&m_audioFrame); + } + + //speex_echo_playback(m_state,play); +} +void YangAecSpeex::echo_capture(short *rec, short *out) { + if(m_state) yang_speex_echo_capture(m_state, rec, out); +} +void YangAecSpeex::preprocess_run(short *pcm) { + //speex_echo_cancellation(echo_state, ref_buf, echo_buf, e_buf); + if(m_preprocState) yang_speex_preprocess_run(m_preprocState, pcm); +} diff --git a/libyangrtc2/src/yangavutil/YangAecSpeex.h b/libyangrtc2/src/yangavutil/YangAecSpeex.h new file mode 100644 index 0000000000000000000000000000000000000000..30442a3cf2fd816b379eb08c9baff65161b3e514 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAecSpeex.h @@ -0,0 +1,57 @@ +/* + * YangAceSpeex.h + * + * Created on: 2020年9月8日 + * Author: yang + */ + +#ifndef YANGAUDIOPROC_YANGAECSPEEX_H_ +#define YANGAUDIOPROC_YANGAECSPEEX_H_ +#include + +#include "speex/speex_echo.h" +#include "speex/speex_preprocess.h" +#include "yangutil/sys/YangLoadLib.h" + + +class YangAecSpeex: public YangAecBase { +public: + YangAecSpeex(); + virtual ~YangAecSpeex(); + void init(int32_t pFrameSizeInMS,int32_t sampling_rate,int32_t pchannel); + void echo_state_reset(); + void echo_playback(short *play); + void put_echo_playback(uint8_t *play,int32_t plen); + void echo_capture(short *rec, short *out); + void preprocess_run(short* pcm); + void setPlayBuffer(YangAudioBuffer *pab); + void echo_cancellation(const short *rec, const short *play, short *out); + void closeAec(); + void resetAec(); +private: + bool m_bHasInit; + SpeexEchoState* m_state; + SpeexPreprocessState* m_preprocState; + YangAudioBuffer *m_audioBuffer; + YangFrame m_audioFrame; + //int32_t m_nFrameSize; + //int32_t m_nFilterLen; + //int32_t m_nSampleRate; + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + SpeexPreprocessState *(*yang_speex_preprocess_state_init)(int32_t frame_size, int32_t sampling_rate); + int32_t (*yang_speex_preprocess_ctl)(SpeexPreprocessState *st, int32_t request, void *ptr); + void (*yang_speex_preprocess_state_destroy)(SpeexPreprocessState *st); + int32_t (*yang_speex_preprocess_run)(SpeexPreprocessState *st, spx_int16_t *x); + + SpeexEchoState *(*yang_speex_echo_state_init_mc)(int32_t frame_size, int32_t filter_length, int32_t nb_mic, int32_t nb_speakers); + int32_t (*yang_speex_echo_ctl)(SpeexEchoState *st, int32_t request, void *ptr); + void (*yang_speex_echo_state_reset)(SpeexEchoState *st); + void (*yang_speex_echo_playback)(SpeexEchoState *st, const spx_int16_t *play); + void (*yang_speex_echo_capture)(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); + void (*yang_speex_echo_cancellation)(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); + void (*yang_speex_echo_state_destroy)(SpeexEchoState *st); +}; + +#endif /* YANGAUDIOPROC_YANGAECSPEEX_H_ */ diff --git a/libyangrtc2/src/yangavutil/YangAudioFactory.cpp b/libyangrtc2/src/yangavutil/YangAudioFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc1321f1ab055b0da2858f45b8eccc5670a8e894 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAudioFactory.cpp @@ -0,0 +1,27 @@ +/* + * YangAudioFactory.cpp + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#include + +#include "YangAecSpeex.h" +#include "YangPreProcessSpeex.h" + +YangAudioFactory::YangAudioFactory() { + // TODO Auto-generated constructor stub + +} + +YangAudioFactory::~YangAudioFactory() { + // TODO Auto-generated destructor stub +} + +YangAecBase* YangAudioFactory::createAec(){ + return new YangAecSpeex(); +} +YangPreProcess* YangAudioFactory::createPreProcess(){ + return new YangPreProcessSpeex(); +} diff --git a/libyangrtc2/src/yangavutil/YangAudioMix.cpp b/libyangrtc2/src/yangavutil/YangAudioMix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25057cd73171d68f66d4a5e43b5042066effb753 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAudioMix.cpp @@ -0,0 +1,149 @@ +/* + * YangAudioMix.cpp + * + * Created on: 2020年9月25日 + * Author: yang + */ + +#include +#include +#include +#include +#include +#include +using namespace std; + +YangAudioMix::YangAudioMix() { + m_yangAudioMAX = ((1 << (16 - 1)) - 1); + m_yangAudioMIN = -(1 << (16 - 1)); +} + +YangAudioMix::~YangAudioMix() { + +} +#define Yang_MIX_MAXVOLUME 128 +#define ADJUST_VOLUME(s, v) (s = (s*v)/Yang_MIX_MAXVOLUME) + +void YangAudioMix::yangMix4(uint8_t *dst, uint8_t *src, int32_t len,int32_t pvolume) { + short src1, src2; + int32_t output; + + len /= 2; + while (len--) { + src1 = ((src[1]) << 8 | src[0]); + // ADJUST_VOLUME(src1, pvolume); + src2 = ((dst[1]) << 8 | dst[0]); + src += 2; + if( src1 < 0 && src2 < 0) + output = src1+src2 - (src1 * src2 / -(pow(2,16-1)-1)); + else + output = src1+src2 - (src1 * src2 / (pow(2,16-1)-1)); + if (output > m_yangAudioMAX) { + //printf("a,"); + output = m_yangAudioMAX; + } else if (output < m_yangAudioMIN) { + //printf("i,"); + output = m_yangAudioMIN; + } + dst[0] = output & 0xFF; + output >>= 8; + dst[1] = output & 0xFF; + dst += 2; + } +} +void YangAudioMix::yangMix3(uint8_t *dst, uint8_t *src, int32_t len,int32_t pvolume) { + short src1, src2; + int32_t output; + + len /= 2; + while (len--) { + src1 = ((src[1]) << 8 | src[0]); + // ADJUST_VOLUME(src1, pvolume); + src2 = ((dst[1]) << 8 | dst[0]); + src += 2; + output = (src1+src2)/2;//FloatS16ToS16(src1 + src2); + if (output > m_yangAudioMAX) { + //printf("a,"); + output = m_yangAudioMAX; + } else if (output < m_yangAudioMIN) { + //printf("i,"); + output = m_yangAudioMIN; + } + dst[0] = output & 0xFF; + output >>= 8; + dst[1] = output & 0xFF; + dst += 2; + } +} +void YangAudioMix::yangMix1(uint8_t *dst, uint8_t *src, int32_t len1,int32_t pvolume) { + short src1, src2; + int32_t output; + + int32_t len = len1/2; + while (len--) { + src1 = ((src[1]) << 8 | src[0]); + // ADJUST_VOLUME(src1, pvolume); + src2 = ((dst[1]) << 8 | dst[0]); + src += 2; + output = src1 + src2; + if (output > m_yangAudioMAX) { + //printf("a,"); + output = m_yangAudioMAX; + } else if (output < m_yangAudioMIN) { + //printf("i,"); + output = m_yangAudioMIN; + } + dst[0] = output & 0xFF; + output >>= 8; + dst[1] = output & 0xFF; + dst += 2; + } +} +void YangAudioMix::yangMix1(short *dst, short *src, int32_t len1, int32_t volume){ + short src1, src2; + int32_t output; + + int32_t len = len1/2; + for(int32_t i=0;i m_yangAudioMAX) { + //printf("a,"); + output = m_yangAudioMAX; + } else if (output < m_yangAudioMIN) { + //printf("i,"); + output = m_yangAudioMIN; + } + dst[i]=output; + } +} +void YangAudioMix::yangMix2(uint8_t *dst, uint8_t *src,int32_t len,int32_t pvolume) { + double f = 1; + short src1, src2; + int32_t output; + + len /= 2; + while (len--) { + src1 = ((src[1]) << 8 | src[0]); + // ADJUST_VOLUME(src1, volume); + src2 = ((dst[1]) << 8 | dst[0]); + src += 2; + output = (src1 + src2)*f; + if (output > m_yangAudioMAX) { + output = m_yangAudioMAX; + f = (double) m_yangAudioMAX / (double) (output); + } else if (output < m_yangAudioMIN) { + output = m_yangAudioMIN; + f = (double) m_yangAudioMIN / (double) (output); + } + if (f < 1) { + f += ((double) 1 - f) / (double) 32; + } + dst[0] = output & 0xFF; + output >>= 8; + dst[1] = output & 0xFF; + dst += 2; + } +} + diff --git a/libyangrtc2/src/yangavutil/YangAudioUtil.cpp b/libyangrtc2/src/yangavutil/YangAudioUtil.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53976fb2ec5773e24700ef836e9a65decf4a5539 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangAudioUtil.cpp @@ -0,0 +1,277 @@ +/* + * YangAudioUtil.cpp + * + * Created on: 2020年9月28日 + * Author: yang + */ +#include +#include +#include +#include +#include + +YangAudioResample::YangAudioResample(int ms) { + m_intervalTime = ms; + m_inSample = 48000; + m_outSample = 48000; + m_inChannel = 2; + m_outChannel = 2; + m_inBuf = NULL; + m_outBuf = NULL; + m_sampleTrans = false; + m_channelTrans = false; + m_isInitTrans = false; + m_isTrans = true; + initParam(); +} +YangAudioResample::~YangAudioResample() { + yang_deleteA(m_inBuf); + yang_deleteA(m_outBuf); +} +void YangAudioResample::initIn(int psample, int pchannel) { + m_inSample = psample; + m_inChannel = pchannel; + m_sampleTrans = (m_inSample == m_outSample ? false : true); + m_channelTrans = (m_inChannel == m_outChannel ? false : true); + m_inFrames = m_inSample * m_intervalTime / 1000; + m_inLen = m_inFrames * 2 * m_inChannel; + m_isTrans = (m_sampleTrans || m_channelTrans) ? true : false; +} +void YangAudioResample::initOut(int psample, int pchannel) { + m_outSample = psample; + m_outChannel = pchannel; + m_sampleTrans = (m_inSample == m_outSample ? false : true); + m_channelTrans = (m_inChannel == m_outChannel ? false : true); + + m_outFrames = m_outSample * m_intervalTime / 1000; + m_outLen = m_outFrames * 2 * m_outChannel; + m_isTrans = (m_sampleTrans || m_channelTrans) ? true : false; +} +void YangAudioResample::init(int insample, int inchannel, int outsample, + int outchannel, int ms) { + m_inSample = insample; + m_inChannel = inchannel; + m_outSample = outsample; + m_outChannel = outchannel; + m_intervalTime = ms; + initParam(); +} +void YangAudioResample::initTrans() { + yang_trace("\n...insample==%d,inchannel==%d,out sample==%d,outchannel==%d....\n",m_inSample,m_inChannel,m_outSample,m_outChannel); + yang_trace("\n...m_isTrans==%d,m_channelTrans==%d,out m_sampleTrans==%d....\n",m_isTrans,m_channelTrans,m_sampleTrans); + if(!m_isTrans) return; + if(m_channelTrans){ + if (m_inBuf == NULL) m_inBuf = new uint8_t[m_inFrames<<2]; + } + if(m_sampleTrans){ + if (m_outBuf == NULL) m_outBuf = new uint8_t[m_outFrames<<2]; + //m_res1.init(m_outChannel, m_inSample, m_outSample,m_outFrames); + m_res.init(m_outChannel, m_inSample, m_outSample); + + } + +} +void YangAudioResample::setIntervalTime(int ms) { + m_intervalTime = ms; +} + +void YangAudioResample::initParam() { + m_inFrames = m_inSample * m_intervalTime / 1000; + m_outFrames = m_outSample * m_intervalTime / 1000; + m_inLen = m_inFrames * 2 * m_inChannel; + m_outLen = m_outFrames * 2 * m_outChannel; + m_isTrans = (m_sampleTrans || m_channelTrans) ? true : false; +} + +int YangAudioResample::resample(YangFrame *audioFrame) { + if (!m_isTrans||!audioFrame||!audioFrame->payload) return Yang_Ok; + + if (!m_isInitTrans){ + initTrans(); + m_isInitTrans = true; + } + uint8_t *buf = audioFrame->payload; + uint8_t *buf_in=buf; + if (m_channelTrans) { + if (m_inChannel == 1) + MonoToStereo((short*) buf, (short*) m_inBuf, m_inFrames); + else + StereoToMono((short*) buf, (short*) m_inBuf, m_inFrames); + + + buf_in=m_inBuf; + } + if (m_sampleTrans) { + uint32_t outlen = 6400; + m_res.resample((short*) (buf_in), m_inFrames,(short*) m_outBuf, &outlen); + // m_res1.resample( (m_channelTrans ? m_inBuf : buf), m_inFrames, m_outBuf, &outlen); + // yang_trace("out_%d,",outlen); + audioFrame->payload = m_outBuf; + } else { + audioFrame->payload = m_inBuf; + } + + audioFrame->nb = m_outLen; + buf_in=NULL; + buf=NULL; + return Yang_Ok; +} +int YangAudioResample::getOutBytes() { + return m_outLen; +} + +int YangAudioResample::getInBytes() { + return m_inLen; +} +int YangAudioResample::getInSample() { + return m_inSample; +} +int YangAudioResample::getOutSample() { + return m_outSample; +} + +int YangAudioResample::getInChannel() { + return m_inChannel; +} +int YangAudioResample::getOutChannel() { + return m_outChannel; +} + +int32_t MonoToStereo(int16_t *pData, int16_t *dData, + int32_t samples_per_channel) { + + /**for (int32_t i = 0; i < nSize; i++) { + if (i % 2 == 0) { + dData[i] = pData[i / 2]; + } else { + dData[i] = pData[i - 1]; + } + }**/ + + for (int32_t i = 0; i < samples_per_channel; i++) { + dData[2 * i] = pData[i]; + dData[2 * i + 1] = pData[i]; + } + return samples_per_channel * 2; +} + +int32_t StereoToMono(const int16_t *src_audio, int16_t *dst_audio, + int32_t samples_per_channel) { + for (int i = 0; i < samples_per_channel; i++) { + dst_audio[i] = (static_cast(src_audio[2 * i]) + + src_audio[2 * i + 1]) >> 1; + } + return Yang_Ok; +} + +short FloatS16ToS16(float v) { + + v = yang_min(v, 32767.f); + v = yang_max(v, -32768.f); +#ifdef _WIN32 + return static_cast(v + copysign(0.5f, v)); +#else + return static_cast(v + std::copysign(0.5f, v)); + #endif +} + +uint64_t Resample_s16(const int16_t *input, int16_t *output, + int32_t inSampleRate, int32_t outSampleRate, uint64_t inputSize, + uint32_t channels) { + if (input == NULL) + return 0; + uint64_t outputSize = inputSize * outSampleRate / inSampleRate; + if (output == NULL) + return outputSize; + double stepDist = ((double) inSampleRate / (double) outSampleRate); + const uint64_t fixedFraction = (1LL << 32); + const double normFixed = (1.0 / (1LL << 32)); + uint64_t step = ((uint64_t) (stepDist * fixedFraction + 0.5)); + uint64_t curOffset = 0; + for (uint32_t i = 0; i < outputSize; i += 1) { + for (uint32_t c = 0; c < channels; c += 1) { + *output++ = (int16_t) (input[c] + + (input[c + channels] - input[c]) + * ((double) (curOffset >> 32) + + ((curOffset & (fixedFraction - 1)) + * normFixed))); + } + curOffset += step; + input += (curOffset >> 32) * channels; + curOffset &= (fixedFraction - 1); + } + return outputSize; +} + +#define VOLUMEMAX 32767 +int32_t SimpleCalculate_DB(short *pcmData, int32_t sample) { + signed short ret = 0; + if (sample > 0) { + int32_t sum = 0; + signed short *pos = (signed short*) pcmData; + for (int32_t i = 0; i < sample; i++) { + sum += abs(*pos); + pos++; + } + ret = sum * 500.0 / (sample * VOLUMEMAX); + if (ret >= 100) { + ret = 100; + } + } + return ret; +} + +static const float kMaxSquaredLevel = 32768 * 32768; +constexpr float kMinLevel = 30.f; + +float Process(const int16_t *data, size_t length) { + float sum_square_ = 0; + size_t sample_count_ = 0; + for (size_t i = 0; i < length; ++i) { + sum_square_ += data[i] * data[i]; + } + sample_count_ += length; + float rms = sum_square_ / (sample_count_ * kMaxSquaredLevel); + //20log_10(x^0.5) = 10log_10(x) + rms = 10 * log10(rms); + if (rms < -kMinLevel) + rms = -kMinLevel; + rms = -rms; + return static_cast(rms + 0.5); +} + +//计算分贝 +int16_t maxAbsValueW16C(const int16_t *vector, size_t length) { + size_t i = 0; + int32_t absolute = 0, maximum = 0; + for (i = 0; i < length; i++) { + absolute = abs((int) vector[i]); + if (absolute > maximum) { + maximum = absolute; + } + } + if (maximum > 32767) { + maximum = 32767; + } + return (int16_t) maximum; +} +const char permutation[33] = { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; +void ComputeLevel(const int16_t *data, size_t length) { + int16_t _absMax = 0; + int16_t _count = 0; + char _currentLevel = 0; + int16_t absValue(0); + absValue = maxAbsValueW16C(data, length); + if (absValue > _absMax) + _absMax = absValue; + if (_count++ == 10) { + _count = 0; + int32_t position = _absMax / 1000; + if ((position == 0) && (_absMax > 250)) { + position = 1; + } + _currentLevel = permutation[position]; + _absMax >>= 2; + } +} diff --git a/libyangrtc2/src/yangavutil/YangConvert.cpp b/libyangrtc2/src/yangavutil/YangConvert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23b142979ccd85d7d04fd189a6759029e628f36e --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangConvert.cpp @@ -0,0 +1,613 @@ +#include +#include +#include +#include "yangavutil/video/YangPicConvert.h" + + + struct RGB24{ + uint8_t b; + uint8_t g; + uint8_t r; +} ; +#define MY(a,b,c) (( a* 0.2989 + b* 0.5866 + c* 0.1145)) +#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c* 0.5000 + 128)) +#define MV(a,b,c) (( a* 0.5000 + b*(-0.4184) + c*(-0.0816) + 128)) + +#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c))) +#define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c))) +#define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c))) + + +YangConvert::YangConvert(){ + //mpu=NULL; + +} +YangConvert::~YangConvert(){ + //mpu=NULL; + +} + + +void YangConvert::zoomIn4(uint8_t *src,uint8_t *dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight){ + uint8_t *srcTmp=src+srcWidth*srcHeight; + uint8_t *dstTmp=dest+destWidth*destHeight; + for(int32_t i=0;i>2)*f; + td=(i*p_destWidth+j)>>2; + *(dest_uv+td)=*(src_uv+ts); + *(dest_uv+td+1)=*(src_uv+ts+1); + } + } + }**/ + + for(int32_t i=0;i> 16; + src_y_slice = src + srcy * sw; + + if((y & 1) == 0) + { + dst_uv_yScanline = dst_uv + (y / 2) * dw; + src_uv_yScanline = src_uv + (srcy / 2) * sw; + } + + for(x = 0; x < (dw & ~7); ++x) + { + srcx = (x * xrIntFloat_16) >> 16; + dst_y_slice[x] = src_y_slice[srcx]; + + if((y & 1) == 0) //y is even + { + if((x & 1) == 0) //x is even + { + src_index = (srcx / 2) * 2; + + sp = dst_uv_yScanline + x; + dp = src_uv_yScanline + src_index; + *sp = *dp; + ++sp; + ++dp; + *sp = *dp; + } + } + } + dst_y_slice += dw; + } +} + +void YangConvert::resize_Yuy2_NV12(uint8_t *src,uint8_t *dest,int32_t p_srcWidth,int32_t p_srcHeight,int32_t p_destWidth,int32_t p_destHeight){ + uint8_t *dest_uv=dest+p_destWidth*p_destHeight; + //uint8_t *src_uv=src+p_srcWidth*p_srcHeight; + int32_t temp=0; + float f=p_srcWidth/p_destWidth; + for(int32_t i=0;i>>>>>>>>>>>>>>>>>>>",start3); + int32_t start4=(srcHeight-destHeight+1)*srcWidth-destWidth; + int32_t start41=(srcHeight/2-destHeight/2)*srcWidth+(srcWidth-destWidth); + uint8_t *temp,*srcTmp,*dstTmp; + if(model==4){ + temp=src+start4; + srcTmp=src+srcLen+start41; + }else if(model==3){ + temp=src+start3; + srcTmp=src+srcLen+start31; + } + else if(model==2){ + temp=src+start2; + srcTmp=src+srcLen+srcWidth-destWidth; + } + else if(model==1){ + temp=src; + srcTmp=src+srcLen; + } + dstTmp=dest+destLen; + for(int32_t i=0;i>>>>>>>>>>>>>>>>>>>",start3); + int32_t start4=(srcHeight-destHeight+1)*srcWidth*2-destWidth*2; + //int32_t start41=(srcHeight/2-destHeight/2)*srcWidth+(srcWidth-destWidth); + uint8_t *temp,*srcTmp,*dstTmp; + if(model==4){ + temp=src+start4; + //srcTmp=src+srcLen+start41; + }else if(model==3){ + temp=src+start3; + srcTmp=src+srcLen+start31; + } + else if(model==2){ + temp=src+start2; + srcTmp=src+srcLen+srcWidth-destWidth; + } + else if(model==1){ + temp=src; + srcTmp=src+srcLen; + } + dstTmp=dest+destLen; + for(int32_t i=0;ir + 0.504129 * pRGB->g + 0.097906 * pRGB->b + 16; + vau = -0.148223 * pRGB->r - 0.290993 * pRGB->g + 0.439216 * pRGB->b + 128; + vav = 0.439216 * pRGB->r - 0.367788 * pRGB->g - 0.071427 * pRGB->b + 128; + + + *y = vay < 0 ? 0 : (vay > 255 ? 255: vay); // 如果Y小于0置换成0,如果Y大于255就置换成255 + *v = vav < 0 ? 0 : (vav > 255 ? 255: vav); // 如果V小于0置换成0,如果V大于255就置换成255 + *u = vau < 0 ? 0 : (vau > 255 ? 255: vau); // 如果U小于0置换成0,如果U大于255就置换成255 + + y++; // 移动到下一位! + v++; + u++; + pRGB++; + } + } + + u = yv12 + iBufLen; // 记录成品YV12的U的位置 + + v = u + (iBufLen >> 2); // 记录成品YV12的V的位置 + + for(i = 0; i < h; i+=2) // 由于 V 和 U 只记录隔行的,所以 += 2; + { + cv = vv + i * w; // 取得第i 行的v; + nv = vv + (i + 1) * w; // 取得第i + 1 行的v + + cu = uu + i * w; // 取得第i 行的u; + nu = uu + (i + 1) * w; // 取得第i + 1 行的u + + + for(j = 0; j < w; j+=2) // 由于 一躺循环 我们访问 两个 uu 或 vv 所以 += 2; + { + v01 = *(cv + j); // 取得第i 行的第j 个v的具体的值 + v02 = *(cv + j + 1); // 取得第i 行的第j + 1 个v的具体的值 + v11 = *(nv + j); // 取得第i + 1 行的第j 个v的具体的值 + v12 = *(nv + j + 1); // 取得第i + 1 行的第j + 1 个v的具体的值 + + *v = (v01 + v02 + v11 + v12) / 4; // 取v01,v02,v11,v12的平均值给v + + + u01 = *(cu + j); // 取得第i 行的第j 个u的具体的值 + u02 = *(cu + j + 1); // 取得第i 行的第j + 1 个u的具体的值 + u11 = *(nu + j); // 取得第i + 1 行的第j 个u的具体的值 + u12 = *(nu + j + 1); // 取得第i + 1 行的第j + 1 个u的具体的值 + + *u = (u01 + u02 + u11 + u12) / 4; // 取u01,u02,u11,u12的平均值给u + + v++; // 移动到下一位! + u++; + + } + } + + delete [] vv; + delete [] uu; + + } +**/ +void YangConvert::RGB24_TO_YV12(uint8_t* yv12,uint8_t* rgb24,int32_t w,int32_t h) +{ + int32_t iBufLen = w * h; + int32_t i,j,vay,vau,vav; + uint8_t* cv; // 当前坐标的v(current v); + uint8_t* nv; // 在cv下一行的对应位置的 v; + uint8_t* cu; // 当前坐标的u(current u); + uint8_t* nu; // 在cu下一行的对应位置的 u; + uint8_t v01,v02,v11,v12,u01,u02,u11,u12; // 需要整合的相邻的4个象素 如下 + + uint8_t* vv = new uint8_t[iBufLen]; // 每个RGB单位对应的V! + uint8_t* uu = new uint8_t[iBufLen]; // 每个RGB单位对应的U! + + // 按标准算法从RGB24计算出所有YUV + + RGB24 * pRGB = (RGB24*)rgb24; + uint8_t* y = yv12; // 这里直接用 yuv 缓冲。。省了copy了。 + uint8_t* v = vv; + uint8_t* u = uu; + + for(i = 0; i < h; i++) + { + for(j = 0; j < w; j++) + { + + vay = 0.256788 * pRGB->r + 0.504129 * pRGB->g + 0.097906 * pRGB->b + 16; + vau = -0.148223 * pRGB->r - 0.290993 * pRGB->g + 0.439216 * pRGB->b + 128; + vav = 0.439216 * pRGB->r - 0.367788 * pRGB->g - 0.071427 * pRGB->b + 128; + + + *y = vay < 0 ? 0 : (vay > 255 ? 255: vay); // 如果Y小于0置换成0,如果Y大于255就置换成255 + *v = vav < 0 ? 0 : (vav > 255 ? 255: vav); // 如果V小于0置换成0,如果V大于255就置换成255 + *u = vau < 0 ? 0 : (vau > 255 ? 255: vau); // 如果U小于0置换成0,如果U大于255就置换成255 + + y++; // 移动到下一位! + v++; + u++; + pRGB++; + } + } + + u = yv12 + iBufLen; // 记录成品YV12的U的位置 + + v = u + (iBufLen >> 2); // 记录成品YV12的V的位置 + + for(i = 0; i < h; i+=2) // 由于 V 和 U 只记录隔行的,所以 += 2; + { + cv = vv + i * w; // 取得第i 行的v; + nv = vv + (i + 1) * w; // 取得第i + 1 行的v + + cu = uu + i * w; // 取得第i 行的u; + nu = uu + (i + 1) * w; // 取得第i + 1 行的u + + + for(j = 0; j < w; j+=2) // 由于 一躺循环 我们访问 两个 uu 或 vv 所以 += 2; + { + v01 = *(cv + j); // 取得第i 行的第j 个v的具体的值 + v02 = *(cv + j + 1); // 取得第i 行的第j + 1 个v的具体的值 + v11 = *(nv + j); // 取得第i + 1 行的第j 个v的具体的值 + v12 = *(nv + j + 1); // 取得第i + 1 行的第j + 1 个v的具体的值 + + *v = (v01 + v02 + v11 + v12) / 4; // 取v01,v02,v11,v12的平均值给v + + + u01 = *(cu + j); // 取得第i 行的第j 个u的具体的值 + u02 = *(cu + j + 1); // 取得第i 行的第j + 1 个u的具体的值 + u11 = *(nu + j); // 取得第i + 1 行的第j 个u的具体的值 + u12 = *(nu + j + 1); // 取得第i + 1 行的第j + 1 个u的具体的值 + + *u = (u01 + u02 + u11 + u12) / 4; // 取u01,u02,u11,u12的平均值给u + + v++; // 移动到下一位! + u++; + + } + } + + delete [] vv; + delete [] uu; + + } + +void YangConvert::RGB24_To_I420( uint8_t *RGB, uint8_t *YUV, int32_t width, int32_t height ) +{ + int32_t i,x,y,j; + uint8_t *Y = NULL; + uint8_t *U = NULL; + uint8_t *V = NULL; + Y = YUV; + U = YUV + width*height; + V = U + ((width*height)>>2); + + for(y=0; y < height; y++) + for(x=0; x < width; x++) + { + j = y*width + x; + i = j*3; + Y[j] = (uint8_t)(DY(RGB[i], RGB[i+1], RGB[i+2])); + + if(x%2 == 1 && y%2 == 1) + { + j = (width>>1) * (y>>1) + (x>>1); + //ÉÏÃæiÈÔÓÐЧ + U[j] = (uint8_t) + ((DU(RGB[i ], RGB[i+1], RGB[i+2]) + + DU(RGB[i-3], RGB[i-2], RGB[i-1]) + + DU(RGB[i -width*3], RGB[i+1-width*3], RGB[i+2-width*3]) + + DU(RGB[i-3-width*3], RGB[i-2-width*3], RGB[i-1-width*3]))/4); + + V[j] = (uint8_t) + ((DV(RGB[i ], RGB[i+1], RGB[i+2]) + + DV(RGB[i-3], RGB[i-2], RGB[i-1]) + + DV(RGB[i -width*3], RGB[i+1-width*3], RGB[i+2-width*3]) + + DV(RGB[i-3-width*3], RGB[i-2-width*3], RGB[i-1-width*3]))/4); + } + + } + Y = NULL; + U = NULL; + V = NULL; + // if(RGB) free(RGB); +} +uint8_t YangConvert::clip255(long v) +{ + if(v < 0) v=0; + else if( v > 255) v=255; + return (uint8_t )v; +} +void YangConvert::YUY2_To_RGB24(uint8_t *YUY2buff,uint8_t *RGBbuff,unsigned long dwSize) +{ + // + //lC = lY - 16 + //lD = btU - 128 + //lE = btV - 128 + //btR = clip(( 298 * lC + 409 * lE + 128) >> 8) + //btG = clip(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8) + //btB = clip(( 298 * lC + 516 * lD + 128) >> 8) + uint8_t *orgRGBbuff = RGBbuff; + for( unsigned long count = 0; count < dwSize; count += 4 ) + { + //Y0 U0 Y1 V0 + uint8_t btY0 = *YUY2buff; + uint8_t btU = *(++YUY2buff); + uint8_t btY1 = *(++YUY2buff); + uint8_t btV = *(++YUY2buff); + ++YUY2buff; + + long lY,lC,lD,lE; + uint8_t btR,btG,btB; + + lY = btY0; + lC = lY - 16; + lD = btU - 128; + lE = btV - 128; + btR = clip255(( 298 * lC + 409 * lE + 128) >> 8); + btG = clip255(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8); + btB = clip255(( 298 * lC + 516 * lD + 128) >> 8); + + *(RGBbuff) = btB; + *(++RGBbuff) = btG; + *(++RGBbuff) = btR; + + lY = btY1; + lC = lY-16; + lD = btU-128; + lE = btV-128; + btR = clip255(( 298 * lC + 409 * lE + 128) >> 8); + btG = clip255(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8); + btB = clip255(( 298 * lC + 516 * lD + 128) >> 8); + *(++RGBbuff) = btB; + *(++RGBbuff) = btG; + *(++RGBbuff) = btR; + ++RGBbuff; + } +} diff --git a/libyangrtc2/src/yangavutil/YangImageConvert.cpp b/libyangrtc2/src/yangavutil/YangImageConvert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..515d17e64b98ab92bde6bc45db09be1a2d3dab5b --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangImageConvert.cpp @@ -0,0 +1,431 @@ +/* + * YangImageConvert.cpp + * + * Created on: 2020年10月25日 + * Author: yang + */ + +#include + + +#include +#ifndef _WIN32 +#include + +#include +#include +#define MY(a,b,c) (( a* 0.2989 + b* 0.5866 + c* 0.1145)) +#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c* 0.5000 + 128)) +#define MV(a,b,c) (( a* 0.5000 + b*(-0.4184) + c*(-0.0816) + 128)) + +#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c))) +#define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c))) +#define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c))) +#define uint8_t uint8_t +YangImageConvert::YangImageConvert() { + // TODO Auto-generated constructor stub + +} + +YangImageConvert::~YangImageConvert() { + // TODO Auto-generated destructor stub +} + + +void YangImageConvert::RGB24_TO_YV12(uint8_t* yv12,uint8_t* rgb24,int32_t w,int32_t h) +{ + int32_t iBufLen = w * h; + int32_t i,j,vay,vau,vav; + uint8_t* cv; // 当前坐标的v(current v); + uint8_t* nv; // 在cv下一行的对应位置的 v; + uint8_t* cu; // 当前坐标的u(current u); + uint8_t* nu; // 在cu下一行的对应位置的 u; + uint8_t v01,v02,v11,v12,u01,u02,u11,u12; // 需要整合的相邻的4个象素 如下 + + uint8_t* vv = new uint8_t[iBufLen]; // 每个RGB单位对应的V! + uint8_t* uu = new uint8_t[iBufLen]; // 每个RGB单位对应的U! + + // 按标准算法从RGB24计算出所有YUV + + RGB24 * pRGB = (RGB24*)rgb24; + uint8_t* y = yv12; // 这里直接用 yuv 缓冲。。省了copy了。 + uint8_t* v = vv; + uint8_t* u = uu; + + for(i = 0; i < h; i++) + { + for(j = 0; j < w; j++) + { + + //Y = 0.299R + 0.587G + 0.114B + //U = -0.147R - 0.289G + 0.436B + //V = 0.615R - 0.515G - 0.100B + + // 这个算法颜色不正啊。。 + //vay = pRGB->r * 0.299 + pRGB->g * 0.587 + pRGB->b * 0.114; // 根据公式计算出Y + //vav = pRGB->r * 0.615 + pRGB->g * -0.515 + pRGB->b * -0.100; // 根据公式计算出V + //vau = pRGB->r * -0.147 + pRGB->g * -0.289 + pRGB->b * 0.436; // 根据公式计算出U + + + //Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) + 16 + //U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128 + //V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128 + + + // 好象这个算法颜色正,而且是MSDN中列出的算法 + vay = 0.256788 * pRGB->r + 0.504129 * pRGB->g + 0.097906 * pRGB->b + 16; + vau = -0.148223 * pRGB->r - 0.290993 * pRGB->g + 0.439216 * pRGB->b + 128; + vav = 0.439216 * pRGB->r - 0.367788 * pRGB->g - 0.071427 * pRGB->b + 128; + + + *y = vay < 0 ? 0 : (vay > 255 ? 255: vay); // 如果Y小于0置换成0,如果Y大于255就置换成255 + *v = vav < 0 ? 0 : (vav > 255 ? 255: vav); // 如果V小于0置换成0,如果V大于255就置换成255 + *u = vau < 0 ? 0 : (vau > 255 ? 255: vau); // 如果U小于0置换成0,如果U大于255就置换成255 + + y++; // 移动到下一位! + v++; + u++; + pRGB++; + } + } + + u = yv12 + iBufLen; // 记录成品YV12的U的位置 + + v = u + (iBufLen >> 2); // 记录成品YV12的V的位置 + + for(i = 0; i < h; i+=2) // 由于 V 和 U 只记录隔行的,所以 += 2; + { + cv = vv + i * w; // 取得第i 行的v; + nv = vv + (i + 1) * w; // 取得第i + 1 行的v + + cu = uu + i * w; // 取得第i 行的u; + nu = uu + (i + 1) * w; // 取得第i + 1 行的u + + + for(j = 0; j < w; j+=2) // 由于 一躺循环 我们访问 两个 uu 或 vv 所以 += 2; + { + v01 = *(cv + j); // 取得第i 行的第j 个v的具体的值 + v02 = *(cv + j + 1); // 取得第i 行的第j + 1 个v的具体的值 + v11 = *(nv + j); // 取得第i + 1 行的第j 个v的具体的值 + v12 = *(nv + j + 1); // 取得第i + 1 行的第j + 1 个v的具体的值 + + *v = (v01 + v02 + v11 + v12) / 4; // 取v01,v02,v11,v12的平均值给v + + + u01 = *(cu + j); // 取得第i 行的第j 个u的具体的值 + u02 = *(cu + j + 1); // 取得第i 行的第j + 1 个u的具体的值 + u11 = *(nu + j); // 取得第i + 1 行的第j 个u的具体的值 + u12 = *(nu + j + 1); // 取得第i + 1 行的第j + 1 个u的具体的值 + + *u = (u01 + u02 + u11 + u12) / 4; // 取u01,u02,u11,u12的平均值给u + + v++; // 移动到下一位! + u++; + + } + } + + delete [] vv; + delete [] uu; + + } + +void YangImageConvert::RGB24_To_I420( uint8_t *RGBbuf, uint8_t *YUV, int32_t width, int32_t height ) +{ + + int32_t i,x,y,j; + uint8_t *Y = NULL; + uint8_t *U = NULL; + uint8_t *V = NULL; + + uint8_t *RGB = NULL; + + int32_t imgSize = width*height; + + RGB = (uint8_t*)malloc(imgSize*3); + + memcpy(RGB, RGBbuf, width*height*3); +// for(i=HEIGHT-1,j=0; i>=0; i--,j++)//µ÷Õû˳Ðò +// { +// memcpy(RGB+j*WIDTH*3,RGB+WIDTH*HEIGHT*3+i*WIDTH*3,WIDTH*3); +// } + + /************************************************************************/ + // ÊäÈëµÄRGBbufÈôΪBGRÐòÁУ¬Ôò×¢Ê͸öΠ+ //˳Ðòµ÷Õû +// uint8_t temp; +// for(i=0; (unsigned int)i < WIDTH*HEIGHT*3; i+=3) +// { +// temp = RGB[i]; +// RGB[i] = RGB[i+2]; +// RGB[i+2] = temp; +// } + /************************************************************************/ + + + Y = YUV; + U = YUV + width*height; + V = U + ((width*height)>>2); + + for(y=0; y < height; y++) + for(x=0; x < width; x++) + { + j = y*width + x; + i = j*3; + Y[j] = (uint8_t)(DY(RGB[i], RGB[i+1], RGB[i+2])); + + if(x%2 == 1 && y%2 == 1) + { + j = (width>>1) * (y>>1) + (x>>1); + //ÉÏÃæiÈÔÓÐЧ + U[j] = (uint8_t) + ((DU(RGB[i ], RGB[i+1], RGB[i+2]) + + DU(RGB[i-3], RGB[i-2], RGB[i-1]) + + DU(RGB[i -width*3], RGB[i+1-width*3], RGB[i+2-width*3]) + + DU(RGB[i-3-width*3], RGB[i-2-width*3], RGB[i-1-width*3]))/4); + + V[j] = (uint8_t) + ((DV(RGB[i ], RGB[i+1], RGB[i+2]) + + DV(RGB[i-3], RGB[i-2], RGB[i-1]) + + DV(RGB[i -width*3], RGB[i+1-width*3], RGB[i+2-width*3]) + + DV(RGB[i-3-width*3], RGB[i-2-width*3], RGB[i-1-width*3]))/4); + } + + } + + if(RGB) free(RGB); +} +uint8_t YangImageConvert::clip255(long v) +{ + if(v < 0) v=0; + else if( v > 255) v=255; + return (uint8_t )v; +} +void YangImageConvert::YUY2_To_RGB24(uint8_t *YUY2buff,uint8_t *RGBbuff,unsigned long dwSize) +{ + // + //lC = lY - 16 + //lD = btU - 128 + //lE = btV - 128 + //btR = clip(( 298 * lC + 409 * lE + 128) >> 8) + //btG = clip(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8) + //btB = clip(( 298 * lC + 516 * lD + 128) >> 8) + uint8_t *orgRGBbuff = RGBbuff; + for( unsigned long count = 0; count < dwSize; count += 4 ) + { + //Y0 U0 Y1 V0 + uint8_t btY0 = *YUY2buff; + uint8_t btU = *(++YUY2buff); + uint8_t btY1 = *(++YUY2buff); + uint8_t btV = *(++YUY2buff); + ++YUY2buff; + + long lY,lC,lD,lE; + uint8_t btR,btG,btB; + + lY = btY0; + lC = lY - 16; + lD = btU - 128; + lE = btV - 128; + btR = clip255(( 298 * lC + 409 * lE + 128) >> 8); + btG = clip255(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8); + btB = clip255(( 298 * lC + 516 * lD + 128) >> 8); + + *(RGBbuff) = btB; + *(++RGBbuff) = btG; + *(++RGBbuff) = btR; + + lY = btY1; + lC = lY-16; + lD = btU-128; + lE = btV-128; + btR = clip255(( 298 * lC + 409 * lE + 128) >> 8); + btG = clip255(( 298 * lC - 100 * lD - 208 * lE + 128) >> 8); + btB = clip255(( 298 * lC + 516 * lD + 128) >> 8); + *(++RGBbuff) = btB; + *(++RGBbuff) = btG; + *(++RGBbuff) = btR; + ++RGBbuff; + } +} + +void YangImageConvert::plusYuy2(uint8_t* src,uint8_t * dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight,int32_t model){ + + int32_t i=0; + int32_t j=0; + int32_t sh=srcHeight-destHeight; + int32_t sw=srcWidth-destWidth; + int32_t start=0; + uint8_t* temp; + if(model==4){ + start=(srcHeight-destHeight+1)*srcWidth*2-destWidth*2; + temp=src+start; + for(i=0;i + + struct RGB24{ + uint8_t b; + uint8_t g; + uint8_t r; +} ; +class YangImageConvert { +public: + YangImageConvert(); + virtual ~YangImageConvert(); + void RGB24_TO_YV12(uint8_t* yv12,uint8_t* rgb24,int32_t w,int32_t h); + void RGB24_To_I420( uint8_t *RGBbuf, uint8_t *YUV, int32_t width, int32_t height ); + void YUY2_To_RGB24(uint8_t *YUY2buff,uint8_t *RGBbuff,unsigned long dwSize); + int32_t YUVBlending(void* pBGYUV, void* pFGYUV, int32_t width, int32_t height, bool alphaBG, bool alphaFG) ; + void plusAuthor(uint8_t* src,uint8_t * dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight,int32_t model); + void plusYuy2(uint8_t* src,uint8_t * dest,int32_t srcWidth,int32_t srcHeight,int32_t destWidth,int32_t destHeight,int32_t model); +private: + uint8_t clip255(long v); +}; + +#endif /* YANGAVUTIL_SRC_YANGIMAGECONVERT_H_ */ diff --git a/libyangrtc2/src/yangavutil/YangMakeWave.cpp b/libyangrtc2/src/yangavutil/YangMakeWave.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d9f253d9cb5fc97e6176ab601476ec8dc858039 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangMakeWave.cpp @@ -0,0 +1,84 @@ +#include +YangMakeWave::YangMakeWave(){ + waveFile=NULL; + PCMSize=0; + m_isMono=0; +} +/** +int32_t YangMakeWave::isMp3(char *p){ + //char p[20]; + //printf("a==%c,%c,%c",p[0],p[2],p[22]); + if(p[0]=='M'&&p[2]=='P'&&p[22]=='3') { + printf("****************mp3"); + return 1 + ;} + return 0; +}**/ +void YangMakeWave::write(uint8_t * data,int32_t len){ +fwrite(data,1,len,waveFile); +fflush(waveFile); +PCMSize+=len; + +} +void YangMakeWave::start(int32_t pisMono,char * filename){ + m_isMono=pisMono; + waveFile=fopen(filename,"wb"); + writeHeader(m_isMono,waveFile,0); + PCMSize=0; +} +void YangMakeWave::stop(){ + writeHeader(m_isMono,waveFile,PCMSize); + fclose(waveFile); + waveFile=NULL; +} +void YangMakeWave::writeHeader(int32_t isMono,FILE *WavFile,unsigned long len){ + + WaveHdr WaveHeader; + + WaveHeader.fileID[0] = 'R'; + WaveHeader.fileID[1] = 'I'; + WaveHeader.fileID[2] = 'F'; + WaveHeader.fileID[3] = 'F'; + WaveHeader.fileleth = 0; + WaveHeader.wavTag[0] = 'W'; + WaveHeader.wavTag[1] = 'A'; + WaveHeader.wavTag[2] = 'V'; + WaveHeader.wavTag[3] = 'E'; + + WaveHeader.FmtHdrID[0] = 'f'; + WaveHeader.FmtHdrID[1] = 'm'; + WaveHeader.FmtHdrID[2] = 't'; + WaveHeader.FmtHdrID[3] = ' '; + + WaveHeader.FmtHdrLeth = 0; + +// ChunkHdr FmtHdr = {"fmt ",}; + WaveHeader.DataHdrID[0] = 'd'; + WaveHeader.DataHdrID[1] = 'a'; + WaveHeader.DataHdrID[2] = 't'; + WaveHeader.DataHdrID[3] = 'a'; + WaveHeader.DataHdrLeth = 0; + rewind(WavFile); + + WaveHeader.fileleth = len + 32; + WaveHeader.FmtHdrLeth = 16; + WaveHeader.BitsPerSample = 16; + WaveHeader.Channels = 2; + WaveHeader.FormatTag = 0x0001; + if(isMono){ + WaveHeader.SamplesPerSec = 16000; + WaveHeader.AvgBytesPerSec = 2*16000; + }else{ + WaveHeader.SamplesPerSec = 44100; + WaveHeader.AvgBytesPerSec = 4*44100; + } + + WaveHeader.BlockAlign = 4; + + WaveHeader.DataHdrLeth = len; + + fwrite(&WaveHeader,sizeof(WaveHdr),1,WavFile); + fflush( WavFile ); + +} + diff --git a/libyangrtc2/src/yangavutil/YangMeta.cpp b/libyangrtc2/src/yangavutil/YangMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c79e12d3cb2e3729b99407af63fa3ace961d758 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangMeta.cpp @@ -0,0 +1,360 @@ +#include +#include +#include +#include +void yang_createH264Meta(YangVideoMeta* pvmd,YangFrame *videoFrame){ + memset(pvmd,0,sizeof(YangVideoMeta)); + uint32_t spsLen=yang_get_be32(videoFrame->payload); + uint32_t ppslen=yang_get_be32(videoFrame->payload+spsLen+4); + pvmd->mp4Meta.spsLen=spsLen; + pvmd->mp4Meta.ppsLen=ppslen; + memcpy(pvmd->mp4Meta.sps,videoFrame->payload+4,spsLen); + memcpy(pvmd->mp4Meta.pps,videoFrame->payload+4+spsLen+4,ppslen); + +} +void yang_createH265Meta(YangVideoMeta* pvmd,YangFrame *videoFrame){ + memset(pvmd,0,sizeof(YangVideoMeta)); + uint32_t spsLen=yang_get_be32(videoFrame->payload); + uint32_t ppslen=yang_get_be32(videoFrame->payload+spsLen+4); + pvmd->mp4Meta.spsLen=spsLen; + pvmd->mp4Meta.ppsLen=ppslen; + memcpy(pvmd->mp4Meta.sps,videoFrame->payload+4,spsLen); + memcpy(pvmd->mp4Meta.pps,videoFrame->payload+4+spsLen+4,ppslen); + +} + + +void yang_getConfig_Flv_H264(YangH2645Conf *p_264, uint8_t *configBuf, + int32_t *p_configLen) { + + configBuf[0] = 0x17; + configBuf[1] = 0x00; + configBuf[2] = 0x00; + configBuf[3] = 0x00; + configBuf[4] = 0x00; + configBuf[5] = 0x01; + configBuf[6] = p_264->sps[1];//0x42; + configBuf[7] = p_264->sps[2];//0xC0; + configBuf[8] = p_264->sps[3];//0x29; //0x29; //AVCLevelIndication1f + configBuf[9] = 0xff; //03;//ff;//0x03; AVCLevelIndication + configBuf[10] = 0xe1; //01;//e1;//01;numOfSequenceParameterSets + uint8_t * szTmp = configBuf + 11; + + + *szTmp++=0x00; + *szTmp++=p_264->spsLen; + + memcpy(szTmp, p_264->sps, p_264->spsLen); + szTmp += p_264->spsLen; + *szTmp = 0x01; + szTmp += 1; + *szTmp++=0x00; + *szTmp++=p_264->ppsLen; + memcpy(szTmp, p_264->pps, p_264->ppsLen); + + szTmp += p_264->ppsLen; + *p_configLen = szTmp - configBuf; + szTmp = NULL; +} +/* + * uint8_t *p = videoFrame->payload; + *p++ = 0x17; + *p++ = 0x0; // avc_type: sequence header + *p++ = 0x0; // composition time + *p++ = 0x0; + *p++ = 0x0; + *p++ = 0x01; // version + *p++ = sps[1]; + *p++ = sps[2]; + *p++ = sps[3]; + *p++ = 0xff; + *p++ = 0xe1; + yang_put_be16((char*) p, (uint16_t) spsLen); + p += 2; + memcpy(p, sps, spsLen); + p += spsLen; + yang_put_be16((char*) p, (uint16_t) ppsLen); + p += 2; + memcpy(p, pps, ppsLen); + p += ppsLen; + * + * */ +void yang_getConfig_Meta_H264(YangSample* psps, YangSample* ppps,uint8_t *configBuf,int32_t *p_configLen){ + //type_codec1 + avc_type + composition time + fix header + count of sps + len of sps + sps + count of pps + len of pps + pps + // int32_t nb_payload = 1 + 1 + 3 + 5 + 1 + 2 + sps->size + 1 + 2 + pps->size; + int32_t spsLen=psps->nb; + int32_t ppsLen=psps->nb; + uint8_t* sps=(uint8_t*)psps->bytes; + uint8_t* pps=(uint8_t*)ppps->bytes; + configBuf[0] = 0x17; + configBuf[1] = 0x00; + configBuf[2] = 0x00; + configBuf[3] = 0x00; + configBuf[4] = 0x00; + configBuf[5] = 0x01; + configBuf[6] = sps[1];//0x42; + configBuf[7] = sps[2];//0xC0; + configBuf[8] = sps[3];//0x29; //0x29; //AVCLevelIndication1f + configBuf[9] = 0xff; //03;//ff;//0x03; AVCLevelIndication + configBuf[10] = 0xe1; //01;//e1;//01;numOfSequenceParameterSets + uint8_t * szTmp = configBuf + 11; + + yang_put_be16((char*) szTmp, (uint16_t) spsLen); + szTmp+=2; + //*szTmp++=0x00; + // *szTmp++=spsLen; + + memcpy(szTmp, sps, spsLen); + szTmp += spsLen; + *szTmp = 0x01; + szTmp += 1; + + yang_put_be16((char*) szTmp, (uint16_t) ppsLen); + szTmp+=2; + // *szTmp++=0x00; + // *szTmp++=ppsLen; + memcpy(szTmp, pps, ppsLen); + + szTmp += ppsLen; + *p_configLen = szTmp - configBuf; + szTmp = NULL; +} +void yang_getConfig_Flv_H265(YangH2645Conf *p_264, uint8_t *configBuf, int32_t *p_configLen) { + int32_t i = 0; + configBuf[i++] = 0x1C; + configBuf[i++] = 0x00; + + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; +//configurationVersion + configBuf[i++] = 0x00; + + + configBuf[i++] = p_264->sps[1]; +//general_profile_compatibility_flags 32 bit + configBuf[i++] = p_264->sps[2]; + configBuf[i++] = p_264->sps[3]; + configBuf[i++] = p_264->sps[4]; + configBuf[i++] = p_264->sps[5]; + +// 48 bit NUll nothing deal in rtmp + configBuf[i++] = p_264->sps[6]; + configBuf[i++] = p_264->sps[7]; + configBuf[i++] = p_264->sps[8]; + configBuf[i++] = p_264->sps[9]; + configBuf[i++] = p_264->sps[10]; + configBuf[i++] = p_264->sps[11]; + +//general_level_idc + configBuf[i++] = p_264->sps[12]; + +//configBuf[i++] = p_264->sps[13]; +//configBuf[i++] = p_264->sps[14]; + +//configBuf[i++] = 0x00; +//configBuf[i++] = 0x00; +//configBuf[i++] = 0x00; +//configBuf[i++] = 0x00; +// 48 bit NUll nothing deal in rtmp + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + +//bit(16) avgFrameRate; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + +//bit(2) constantFrameRate; +// bit(3) numTemporalLayers; +///bit(1) temporalIdNested; + configBuf[i++] = 0x00; + configBuf[i++] = 0x03; + +//yang_trace("HEVCDecoderConfigurationRecord data = %s\n", configBuf); + configBuf[i++] = 0x20; //vps 32 + configBuf[i++] = 0x0; + configBuf[i++] = 0x01; + configBuf[i++] = (p_264->vpsLen >> 8) & 0xff; + configBuf[i++] = (p_264->vpsLen) & 0xff; + memcpy(&configBuf[i], p_264->vps, p_264->vpsLen); + i += p_264->vpsLen; + + configBuf[i++] = 0x21; //sps 33 + configBuf[i++] = (1 >> 8) & 0xff; + configBuf[i++] = 1 & 0xff; + configBuf[i++] = (p_264->spsLen >> 8) & 0xff; + configBuf[i++] = (p_264->spsLen) & 0xff; + memcpy(&configBuf[i], p_264->sps, p_264->spsLen); + i += p_264->spsLen; + + configBuf[i++] = 0x22; //sps 33 + configBuf[i++] = (1 >> 8) & 0xff; + configBuf[i++] = 1 & 0xff; + configBuf[i++] = (p_264->ppsLen >> 8) & 0xff; + configBuf[i++] = (p_264->ppsLen) & 0xff; + memcpy(&configBuf[i], p_264->pps, p_264->ppsLen); + i += p_264->ppsLen; + *p_configLen = i; + +} +void yang_getConfig_Meta_H265(YangSample* pvps,YangSample* psps, YangSample* ppps, uint8_t *configBuf,int32_t *p_configLen){ + int32_t i = 0; + int32_t vpsLen=pvps->nb; + int32_t spsLen=psps->nb; + int32_t ppsLen=ppps->nb; + uint8_t* vps=(uint8_t*)pvps->bytes; + uint8_t* sps=(uint8_t*)psps->bytes; + uint8_t* pps=(uint8_t*)ppps->bytes; + configBuf[i++] = 0x1C; + configBuf[i++] = 0x00; + + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + //configurationVersion + configBuf[i++] = 0x00; + + + configBuf[i++] = sps[1]; + //general_profile_compatibility_flags 32 bit + configBuf[i++] = sps[2]; + configBuf[i++] = sps[3]; + configBuf[i++] = sps[4]; + configBuf[i++] = sps[5]; + + // 48 bit NUll nothing deal in rtmp + configBuf[i++] = sps[6]; + configBuf[i++] = sps[7]; + configBuf[i++] = sps[8]; + configBuf[i++] = sps[9]; + configBuf[i++] = sps[10]; + configBuf[i++] = sps[11]; + + //general_level_idc + configBuf[i++] = sps[12]; + + //configBuf[i++] = sps[13]; + //configBuf[i++] = sps[14]; + + //configBuf[i++] = 0x00; + //configBuf[i++] = 0x00; + //configBuf[i++] = 0x00; + //configBuf[i++] = 0x00; + // 48 bit NUll nothing deal in rtmp + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + + //bit(16) avgFrameRate; + configBuf[i++] = 0x00; + configBuf[i++] = 0x00; + + //bit(2) constantFrameRate; + // bit(3) numTemporalLayers; + ///bit(1) temporalIdNested; + configBuf[i++] = 0x00; + configBuf[i++] = 0x03; + + //yang_trace("HEVCDecoderConfigurationRecord data = %s\n", configBuf); + configBuf[i++] = 0x20; //vps 32 + configBuf[i++] = 0x0; + configBuf[i++] = 0x01; + configBuf[i++] = (vpsLen >> 8) & 0xff; + configBuf[i++] = (vpsLen) & 0xff; + ///yang_put_be16((char*) configBuf, (uint16_t) vpsLen); + //i+=2; + memcpy(&configBuf[i], vps, vpsLen); + i += vpsLen; + + configBuf[i++] = 0x21; //sps 33 + configBuf[i++] = (1 >> 8) & 0xff; + configBuf[i++] = 1 & 0xff; + configBuf[i++] = (spsLen >> 8) & 0xff; + configBuf[i++] = (spsLen) & 0xff; + //yang_put_be16((char*) configBuf, (uint16_t) spsLen); + //i+=2; + memcpy(&configBuf[i], sps, spsLen); + i += spsLen; + + configBuf[i++] = 0x22; //sps 33 + configBuf[i++] = (1 >> 8) & 0xff; + configBuf[i++] = 1 & 0xff; + configBuf[i++] = (ppsLen >> 8) & 0xff; + configBuf[i++] = (ppsLen) & 0xff; + //yang_put_be16((char*) configBuf[i], (uint16_t) ppsLen); + //i+=2; + memcpy(&configBuf[i], pps, ppsLen); + i += ppsLen; + *p_configLen = i; +} + + +void yang_getH265RtmpHeader(uint8_t *meta, uint8_t *src, int32_t *hLen) { + uint8_t s[4]; + s[0]=0x00; + s[1]=0x00; + s[2]=0x00; + s[3]=0x01; + + int32_t pos=0; + int32_t vpsLen=*(meta+32); + int32_t vpsPos=33; + + int32_t spsLen=*(meta+32+vpsLen+5); + int32_t spsPos=32+vpsLen+5+1; + + int32_t ppsLen=*(meta+32+vpsLen+5+spsLen+5); + int32_t ppsPos=32+vpsLen+5+spsLen+5+1; + + //printf("\n***************vpsLen=%d,spsLen=%d,ppsLen=%d\n",vpsLen,spsLen,ppsLen); + memcpy(src,s,4); + memcpy(src+4,meta+vpsPos,vpsLen); + pos+=4+vpsLen; + memcpy(src+pos,s,4); + pos+=4; + memcpy(src+pos,meta+spsPos,spsLen); + pos+=spsLen; + memcpy(src+pos,s,4); + pos+=4; + memcpy(src+pos,meta+ppsPos,ppsLen); + pos+=ppsLen; + *hLen=pos; + +} + +void yang_getH264RtmpHeader(uint8_t *buf, uint8_t *src, int32_t *hLen) { + int32_t spsLen = *(buf + 12) + 1; + uint8_t *spsStart = buf + 13; + int32_t ppsLen = *(spsStart + spsLen + 1) + 1; + uint8_t *ppsStart = buf + 13 + spsLen + 2; + *(src + 3) = 0x01; + memcpy(src + 4, spsStart, spsLen); + *(src + 4 + spsLen + 3) = 0x01; + memcpy(src + 4 + spsLen + 4, ppsStart, ppsLen); + *hLen = 8 + spsLen + ppsLen; +} + +void yang_decodeMetaH264(uint8_t *buf,int32_t p_configLen,YangSample* sps,YangSample* pps){ + sps->nb= *(buf + 12) + 1; + sps->bytes = (char*)buf + 13; + pps->nb = *(sps->bytes + sps->nb + 1) + 1; + pps->bytes= (char*)buf + 13 + sps->nb + 2; +} +void yang_decodeMetaH265(uint8_t *meta,int32_t p_configLen,YangSample* vps,YangSample* sps,YangSample* pps){ + vps->nb=*(meta+32); + vps->bytes=(char*)meta+33; + int32_t vpsLen=vps->nb; + sps->nb=*(meta+32+vpsLen+5); + int32_t spsLen=sps->nb; + sps->bytes=(char*)meta+32+vpsLen+5+1; + + pps->nb=*(meta+32+vpsLen+5+spsLen+5); + pps->bytes=(char*)meta+32+vpsLen+5+spsLen+5+1; +} diff --git a/libyangrtc2/src/yangavutil/YangNalu.cpp b/libyangrtc2/src/yangavutil/YangNalu.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f577a7b09f1a4c1e458da4689b7f6705b78c3185 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangNalu.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +int32_t yang_getH264KeyframeNalu(YangFrame *videoFrame) { + uint8_t *tmp = NULL; //videoFrame->payload; + int len = videoFrame->nb; + uint32_t naluLen = 0; + int pos = 0; + int32_t err = 1; + while (pos < len) { + tmp = videoFrame->payload + pos; + if ((*(tmp + 4) & kNalTypeMask) == YangAvcNaluTypeIDR) { + videoFrame->payload = tmp; + videoFrame->nb = len - pos; + err = Yang_Ok; + break; + } + naluLen = yang_get_be32(tmp); + if (naluLen > len) { + break; + } + pos += naluLen + 4; + } + return err; +} + +bool yang_hasH264Pframe(uint8_t *p) { + if ((*(p + 4) & kNalTypeMask) == YangAvcNaluTypeNonIDR) + return true; + return false; +} + + + +int32_t yang_parseH264Nalu(YangFrame *videoFrame, YangH264NaluData *pnalu) { + uint8_t *tmp = NULL; //videoFrame->payload; + uint32_t len = videoFrame->nb; + uint32_t naluLen = 0; + int32_t pos = 0; + int32_t err = 1; + pnalu->spsppsPos = -1; + pnalu->keyframePos = -1; + while (pos < len) { + tmp = videoFrame->payload + pos; + if ((*(tmp + 4) & kNalTypeMask) == YangAvcNaluTypeIDR) { + pnalu->keyframePos = pos; + break; + } + if ((*(tmp + 4) & kNalTypeMask) == YangAvcNaluTypeSPS) { + pnalu->spsppsPos = pos; + } + naluLen = yang_get_be32(tmp); + if (naluLen > len) { + break; + } + pos += naluLen + 4; + } + return err; +} + + +int32_t yang_getNalupos(uint8_t* data,int plen){ + uint8_t* p=NULL; + int len=plen-4; + for(int i=0;ipayload; + uint32_t len = videoFrame->nb; + uint32_t naluLen = 0; + int32_t pos = 0; + int32_t err = 1; + int32_t tmpPos=0; + int32_t tmpLen=len; + pnalu->spsPos = -1; + pnalu->ppsPos = -1; + pnalu->keyframePos = -1; + pnalu->spsLen=0; + pnalu->ppsLen=0; + int32_t preType=-1; + while (pos < len) { + + tmp = videoFrame->payload + pos; + tmpPos=yang_getNalupos(tmp,tmpLen); + if(tmpPos==-1) return 1; + + if(preType==0){ + pnalu->spsLen=tmpPos-4; + preType=-1; + } + if(preType==1){ + pnalu->ppsLen=tmpPos-4; + preType=-1; + } + tmp+=tmpPos; + + if ((*tmp & kNalTypeMask) == YangAvcNaluTypeIDR) { + pnalu->keyframePos =tmp-videoFrame->payload; + preType=2; + return Yang_Ok; + } + if ((*tmp & kNalTypeMask) == YangAvcNaluTypeSPS) { + pnalu->spsPos = tmp-videoFrame->payload; + preType=0; + } + if ((*tmp & kNalTypeMask) == YangAvcNaluTypePPS) { + pnalu->ppsPos = tmp-videoFrame->payload; + preType=1; + } + tmpLen-=tmpPos; + pos+=tmpPos; + + + + } + return err; +} +int32_t yang_getH264SpsppseNalu(YangFrame *videoFrame, uint8_t *pnaludata) { + if (!videoFrame || !pnaludata || !videoFrame->payload) + return yang_error_wrap(1, "getSpsppseNalu is null"); + int32_t spsLen = yang_get_be32(pnaludata); + int32_t ppsLen = yang_get_be32(pnaludata + 4 + spsLen); + if (spsLen > videoFrame->nb || ppsLen > videoFrame->nb) + return 1; + uint8_t *sps = pnaludata + 4; + uint8_t *pps = pnaludata + 4 + spsLen + 4; + + YangSample sps_sample,pps_sample; + sps_sample.bytes=(char*)sps; + sps_sample.nb=spsLen; + + pps_sample.bytes=(char*)pps; + pps_sample.nb=ppsLen; + + yang_getConfig_Meta_H264(&sps_sample,&pps_sample,videoFrame->payload,&videoFrame->nb); + + return Yang_Ok; +} + + + + +int32_t yang_parseH265Nalu(YangFrame *videoFrame, YangH264NaluData *pnalu) { + uint8_t *tmp = NULL; //videoFrame->payload; + uint32_t len = videoFrame->nb; + uint32_t naluLen = 0; + int32_t pos = 0; + int32_t err = 1; + pnalu->spsppsPos = -1; + pnalu->keyframePos = -1; + int32_t v=0; + while (pos < len) { + tmp = videoFrame->payload + pos; + v=YANG_HEVC_NALU_TYPE(*(tmp + 4)); + if (v >= YANG_NAL_UNIT_CODED_SLICE_BLA&&v<= YANG_NAL_UNIT_CODED_SLICE_CRA) { + pnalu->keyframePos = pos; + break; + } + if (v== YANG_NAL_UNIT_VPS) { + pnalu->spsppsPos = pos; + } + naluLen = yang_get_be32(tmp); + if (naluLen > len) { + break; + } + pos += naluLen + 4; + } + return err; +} +int32_t yang_getH265SpsppseNalu(YangFrame *videoFrame, uint8_t *pnaludata) { + if (!videoFrame || !pnaludata || !videoFrame->payload) + return yang_error_wrap(1, "getSpsppseNalu is null"); + YangSample vps_sample,sps_sample,pps_sample; + int32_t vpsLen = yang_get_be32(pnaludata); + int32_t spsLen = yang_get_be32(pnaludata+ 4 + vpsLen); + int32_t ppsLen = yang_get_be32(pnaludata + 4 + vpsLen+4+spsLen); + if (spsLen > videoFrame->nb || ppsLen > videoFrame->nb) + return 1; + uint8_t *vps = pnaludata + 4; + uint8_t *sps = pnaludata + 4 + vpsLen + 4; + uint8_t *pps=pnaludata + 4 + vpsLen + 4+spsLen+4; + + vps_sample.bytes=(char*)vps; + vps_sample.nb=vpsLen; + + sps_sample.bytes=(char*)sps; + sps_sample.nb=spsLen; + + pps_sample.bytes=(char*)pps; + pps_sample.nb=ppsLen; + + yang_getConfig_Meta_H265(&vps_sample,&sps_sample,&pps_sample,videoFrame->payload,&videoFrame->nb); + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangavutil/YangPicUtilFfmpeg.cpp b/libyangrtc2/src/yangavutil/YangPicUtilFfmpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37fa1f895a9cb2e70415cb11e7b8bbc254448cd3 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangPicUtilFfmpeg.cpp @@ -0,0 +1,108 @@ +#include "yangavutil/video/YangPicUtilFfmpeg.h" +#if HavePicUtilFfmpeg + +void YangPicUtilFfmpeg::loadLib(){ + //yang_opus_encoder_create=(OpusEncoder *(*)(opus_int32_t Fs, int32_t channels, int32_t application, int32_t *error))m_lib.loadFunction(""); +yang_sws_getContext =(struct SwsContext *(*)(int32_t srcW, int32_t srcH, enum AVPixelFormat srcFormat, + int32_t dstW, int32_t dstH, enum AVPixelFormat dstFormat, + int32_t flags, SwsFilter *srcFilter, + SwsFilter *dstFilter, const double *param))m_lib.loadFunction("sws_getContext"); + +yang_sws_scale =(int32_t (*)(struct SwsContext *c, const uint8_t *const srcSlice[], + const int32_t srcStride[], int32_t srcSliceY, int32_t srcSliceH, + uint8_t *const dst[], const int32_t dstStride[]))m_lib.loadFunction("sws_scale"); +yang_sws_freeContext =(void (*)(struct SwsContext *swsContext))m_lib.loadFunction("sws_freeContext"); + + + + +yang_avpicture_alloc =(int32_t (*)(AVPicture *picture, enum AVPixelFormat pix_fmt, int32_t width, int32_t height))m_lib1.loadFunction("avpicture_alloc"); +yang_avpicture_free =(void (*)(AVPicture *picture))m_lib1.loadFunction("avpicture_free"); + + +} + +void YangPicUtilFfmpeg::unloadLib(){ + yang_sws_getContext=NULL; + yang_sws_scale=NULL; + yang_sws_freeContext=NULL; + yang_avpicture_alloc=NULL; + yang_avpicture_free=NULL; + +} +YangPicUtilFfmpeg::YangPicUtilFfmpeg(void) +{ + inWidth=0,inHeight=0,outWidth=0,outHeight=0; + img_convert_ctx=NULL; + unloadLib(); + + //in=in_pic.data[0]; + //out=out_pic.data[0]; +} + + +YangPicUtilFfmpeg::~YangPicUtilFfmpeg(void) +{ + closeAll(); + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); + // m_lib2.unloadObject(); +} +void YangPicUtilFfmpeg::closeAll() +{ + if(img_convert_ctx!=NULL) yang_sws_freeContext(img_convert_ctx); + yang_avpicture_free(&out_pic); + yang_avpicture_free(&in_pic); +} + + + +void YangPicUtilFfmpeg::getAddr(uint8_t **p_in,uint8_t **p_out){ + *p_in=in_pic.data[0]; + *p_out=out_pic.data[0]; +} +void YangPicUtilFfmpeg::init420P(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight) +{ + init(pinWidth,pinHeight,poutWidth,poutHeight,AV_PIX_FMT_YUV420P,AV_PIX_FMT_YUV420P); +} +void YangPicUtilFfmpeg::initYuy2(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight) +{ + init(pinWidth,pinHeight,poutWidth,poutHeight,AV_PIX_FMT_YUYV422,AV_PIX_FMT_YUYV422); +} +void YangPicUtilFfmpeg::initNv12(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight) +{ + init(pinWidth,pinHeight,poutWidth,poutHeight,AV_PIX_FMT_NV12,AV_PIX_FMT_NV12); +} +void YangPicUtilFfmpeg::initYuy2_Bgr24(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight) +{ + init(pinWidth,pinHeight,poutWidth,poutHeight,AV_PIX_FMT_YUYV422,AV_PIX_FMT_BGR24); +} + +void YangPicUtilFfmpeg::init(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight,AVPixelFormat src,AVPixelFormat dst){ + m_lib.loadObject("libswscale"); + m_lib1.loadObject("libavcodec"); + //m_lib2.loadObject("libopencv_imgcodecs"); + loadLib(); + inWidth=pinWidth; + inHeight=pinHeight; + outWidth=poutWidth; + outHeight=poutHeight; + img_convert_ctx = yang_sws_getContext(inWidth, inHeight, + src, outWidth, outHeight, dst,SWS_FAST_BILINEAR,//SWS_POINT,//SWS_GAUSS, + NULL, NULL, NULL); + + yang_avpicture_alloc(&in_pic, src, inWidth, inHeight); + yang_avpicture_alloc(&out_pic, dst, outWidth, outHeight); +} +void YangPicUtilFfmpeg::initBgr24_Yuy2(int32_t pinWidth,int32_t pinHeight,int32_t poutWidth,int32_t poutHeight){ + init(pinWidth,pinHeight,poutWidth,poutHeight,AV_PIX_FMT_BGR24,AV_PIX_FMT_YUYV422); + //sws_scale +} + +void YangPicUtilFfmpeg::resize() +{ + yang_sws_scale(img_convert_ctx, in_pic.data, in_pic.linesize, 0, inHeight, out_pic.data, out_pic.linesize); + +} +#endif diff --git a/libyangrtc2/src/yangavutil/YangPreProcess.cpp b/libyangrtc2/src/yangavutil/YangPreProcess.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8aaa0c469babb53215d2b0adb5cecd0f563505c8 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangPreProcess.cpp @@ -0,0 +1,20 @@ +/* + * YangAudioPreProcess.cpp + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#include + + +YangPreProcess::YangPreProcess() { + m_channel=2; + m_frameSize=1024; + m_sampleRate=44100; +} + +YangPreProcess::~YangPreProcess() { + // TODO Auto-generated destructor stub +} + diff --git a/libyangrtc2/src/yangavutil/YangPreProcessSpeex.cpp b/libyangrtc2/src/yangavutil/YangPreProcessSpeex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf512c1e73a20eb5bcd26fba4d9eac95556b4dff --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangPreProcessSpeex.cpp @@ -0,0 +1,87 @@ +/* + * YangPreProcessSpeex.cpp + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#include "YangPreProcessSpeex.h" + +void YangPreProcessSpeex::loadLib(){ + + yang_speex_preprocess_state_init=(SpeexPreprocessState *(*)(int32_t frame_size, int32_t sampling_rate))m_lib.loadFunction("speex_preprocess_state_init");; + yang_speex_preprocess_ctl=(int32_t (*)(SpeexPreprocessState *st, int32_t request, void *ptr))m_lib.loadFunction("speex_preprocess_ctl");; + yang_speex_preprocess_state_destroy=(void (*)(SpeexPreprocessState *st))m_lib.loadFunction("speex_preprocess_state_destroy");; + yang_speex_preprocess_run=(int32_t (*)(SpeexPreprocessState *st, spx_int16_t *x))m_lib.loadFunction("speex_preprocess_run");; +} + +void YangPreProcessSpeex::unloadLib(){ + yang_speex_preprocess_state_init=0; + yang_speex_preprocess_ctl=0; + yang_speex_preprocess_state_destroy=0; + yang_speex_preprocess_run=0; +} +YangPreProcessSpeex::YangPreProcessSpeex() { + m_bHasInit = false; + m_preprocState = 0; + unloadLib(); +} + +YangPreProcessSpeex::~YangPreProcessSpeex() { + closePre(); + unloadLib(); + m_lib.unloadObject(); +} + +void YangPreProcessSpeex::init(int32_t pFrameSize, int32_t sampleRate, int32_t pchannel) { + if (m_bHasInit) + return; + m_lib.loadObject("libspeexdsp"); + loadLib(); + //resetAec(); + m_frameSize = pFrameSize; + m_sampleRate = sampleRate; + m_channel = pchannel; + int32_t frame_size = m_frameSize; //(m_frameSizeInMS * m_sampleRate * 1.0) / 1000; + m_preprocState = yang_speex_preprocess_state_init(frame_size, m_sampleRate); + + //speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_ECHO_STATE,m_state); +// int32_t i = 1; + //speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_VAD, &i); + int32_t noiseSuppress = -25; + int32_t i = 1; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DENOISE, &i); + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, + &noiseSuppress); + i = 0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_AGC, &i); + i = sampleRate; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i); + i = 0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB, &i); + float f = .0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, + &f); + f = .0; + yang_speex_preprocess_ctl(m_preprocState, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, + &f); + + m_bHasInit = true; +} + +void YangPreProcessSpeex::closePre() { +// speex_echo_state_destroy(m_state); + if(m_preprocState) yang_speex_preprocess_state_destroy(m_preprocState); + //m_state = 0; + m_preprocState = 0; + +} + +void YangPreProcessSpeex::preprocess_run(short *pcm) { + //speex_echo_cancellation(echo_state, ref_buf, echo_buf, e_buf); + if(m_preprocState) yang_speex_preprocess_run(m_preprocState, pcm); +} + +void YangPreProcessSpeex::state_reset() { + //speex_preprocess_state_reset(m_preprocState); +} diff --git a/libyangrtc2/src/yangavutil/YangPreProcessSpeex.h b/libyangrtc2/src/yangavutil/YangPreProcessSpeex.h new file mode 100644 index 0000000000000000000000000000000000000000..35d82d69e790cc32805337da97c1dc6f0eca38b6 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangPreProcessSpeex.h @@ -0,0 +1,34 @@ +/* + * YangPreProcessSpeex.h + * + * Created on: 2020年9月29日 + * Author: yang + */ + +#ifndef YANGAUDIOPROC_YANGPREPROCESSSPEEX_H_ +#define YANGAUDIOPROC_YANGPREPROCESSSPEEX_H_ +#include +#include "speex/speex_preprocess.h" +#include "yangutil/sys/YangLoadLib.h" + +class YangPreProcessSpeex: public YangPreProcess { +public: + YangPreProcessSpeex(); + virtual ~YangPreProcessSpeex(); + void init(int32_t pFrameSize,int32_t sampling_rate,int32_t pchannel); + void state_reset(); + void preprocess_run(short* pcm); + void closePre(); +private: + bool m_bHasInit; + SpeexPreprocessState* m_preprocState; + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + SpeexPreprocessState *(*yang_speex_preprocess_state_init)(int32_t frame_size, int32_t sampling_rate); + int32_t (*yang_speex_preprocess_ctl)(SpeexPreprocessState *st, int32_t request, void *ptr); + void (*yang_speex_preprocess_state_destroy)(SpeexPreprocessState *st); + int32_t (*yang_speex_preprocess_run)(SpeexPreprocessState *st, spx_int16_t *x); +}; + +#endif /* YANGAUDIOPROC_YANGPREPROCESSSPEEX_H_ */ diff --git a/libyangrtc2/src/yangavutil/YangResample.cpp b/libyangrtc2/src/yangavutil/YangResample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0336e25df8d95d886fdcd9f20e449a8da75b5f7c --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangResample.cpp @@ -0,0 +1,71 @@ +/* + * YangResample.cpp + * + * Created on: 2020年9月10日 + * Author: yang + */ + +#include + + +void YangResample::loadLib(){ + + yang_speex_resampler_init=(SpeexResamplerState *(*)(spx_uint32_t nb_channels,spx_uint32_t in_rate, + spx_uint32_t out_rate,int32_t quality,int32_t *err))m_lib.loadFunction("speex_resampler_init"); + yang_speex_resampler_process_int=(int32_t (*)(SpeexResamplerState *st,spx_uint32_t channel_index,const spx_int16_t *in, + spx_uint32_t *in_len,spx_int16_t *out,spx_uint32_t *out_len))m_lib.loadFunction("speex_resampler_process_int"); + yang_speex_resampler_process_interleaved_int=(int32_t (*)(SpeexResamplerState *st, const spx_int16_t *in,spx_uint32_t *in_len, + spx_int16_t *out,spx_uint32_t *out_len))m_lib.loadFunction("speex_resampler_process_interleaved_int"); + yang_speex_resampler_destroy=(void (*)(SpeexResamplerState *st))m_lib.loadFunction("speex_resampler_destroy"); +} + +void YangResample::unloadLib(){ + yang_speex_resampler_init=0; + yang_speex_resampler_process_int=0; + yang_speex_resampler_process_interleaved_int=0; + yang_speex_resampler_destroy=0; +} +YangResample::YangResample() { + // TODO Auto-generated constructor stub + m_contextt=0; + m_state=0; + m_channel=2; + m_in_sample=44100; + m_out_sample=44100; + m_in_len=0; + m_out_len=0; + unloadLib(); +} + +YangResample::~YangResample() { + if(m_state) yang_speex_resampler_destroy(m_state); + m_state=0; + unloadLib(); + m_lib.unloadObject(); +} + +void YangResample::init(int32_t pchannel,int32_t pinsample,int32_t poutsample){ + if(m_contextt) return; + m_lib.loadObject("libspeexdsp"); + loadLib(); + m_channel=pchannel; + m_in_sample=pinsample; + m_out_sample=poutsample; + if(!m_state) m_state = yang_speex_resampler_init(m_channel, m_in_sample, m_out_sample, 10, 0); + // speex_resampler_set_rate(m_state, 96000, 44100); + //speex_resampler_skip_zeros(m_state); + + + m_contextt=1; +} + +void YangResample::resample(const short *pin,uint32_t pinLen, short* pout,uint32_t* poutLen){ + m_in_len=pinLen; + //m_out_len=poutLen; + // speex_resampler_process_interleaved_int + if(m_channel==1){ + if(m_state) yang_speex_resampler_process_int(m_state, 0, pin, &m_in_len, pout, poutLen); + }else{ + if(m_state) yang_speex_resampler_process_interleaved_int(m_state, pin, &m_in_len, pout, poutLen); + } +} diff --git a/libyangrtc2/src/yangavutil/YangSwResample.cpp b/libyangrtc2/src/yangavutil/YangSwResample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04cb38367253b3d1009946f73f61b30dab0bae15 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangSwResample.cpp @@ -0,0 +1,64 @@ +#include +#include +YangSwResample::YangSwResample() +{ + swr_ctx = NULL; + m_swrData=NULL; + m_channel=2; + m_inSample=48000; + m_outSample=44100; + m_frameSize=441; + m_contextt=0; + +} +YangSwResample::~YangSwResample() +{ + if (swr_ctx) { + swr_free(&swr_ctx); + } + if (m_swrData) { + av_freep(&m_swrData[0]); + free(m_swrData); + m_swrData = NULL; + } + + +} +int YangSwResample::init(int32_t pchannel,int32_t pinsample,int32_t poutsample,int32_t pframeSize){ + if(m_contextt) return Yang_Ok; + m_inSample=pinsample; + m_outSample=poutsample; + m_channel=pchannel; + m_frameSize=pframeSize; + + swr_ctx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, m_inSample, + AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, m_outSample, 0, NULL); + if (!swr_ctx) { + return yang_error_wrap(1, "YangSwResample fail to swr_alloc\n"); + + } + int error; + char err_buf[AV_ERROR_MAX_STRING_SIZE] = {0}; + if ((error = swr_init(swr_ctx)) < 0) { + return yang_error_wrap(1,"open swr(%d:%s)", error, av_make_error_string(err_buf, AV_ERROR_MAX_STRING_SIZE, error)); + } + + if (!(m_swrData = (uint8_t **)calloc(m_channel, sizeof(*m_swrData)))) { + return yang_error_wrap(1, "alloc swr buffer"); + } + + if ((error = av_samples_alloc(m_swrData, NULL, m_channel, m_frameSize, AV_SAMPLE_FMT_S16, 0)) < 0) { + return yang_error_wrap(1, "alloc swr buffer(%d:%s)", error, + av_make_error_string(err_buf, AV_ERROR_MAX_STRING_SIZE, error)); + } + m_contextt=1; + return Yang_Ok; + +} + +void YangSwResample::resample(const uint8_t *pin,uint32_t pinLen,uint8_t* pout,uint32_t *poutLen){ + int frame_size = swr_convert(swr_ctx, m_swrData, m_frameSize, &pin, pinLen); + *poutLen=frame_size; + memcpy(pout,*m_swrData,frame_size<<2); + +} diff --git a/libyangrtc2/src/yangavutil/YangVideoEncoderMeta.cpp b/libyangrtc2/src/yangavutil/YangVideoEncoderMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75a7413d97a3df08adc017bf3a855122fa2dfb1f --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangVideoEncoderMeta.cpp @@ -0,0 +1,22 @@ +/* + * YangVideoEncoderMeta.cpp + * + * Created on: 2020年08月14日 + * Author: yang + */ +#include +#include +#include +#include +#include + + +YangVideoEncoderMeta::YangVideoEncoderMeta() { + + +} + +YangVideoEncoderMeta::~YangVideoEncoderMeta() { + +} + diff --git a/libyangrtc2/src/yangavutil/YangYuvConvert.cpp b/libyangrtc2/src/yangavutil/YangYuvConvert.cpp new file mode 100644 index 0000000000000000000000000000000000000000..980ec00e6adff09107cfbda26eac34e02f07336f --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangYuvConvert.cpp @@ -0,0 +1,292 @@ +/* + * YangYuvUtil.cpp + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#include +#include "yangavutil/video/YangYuvConvert.h" + + + + +void YangYuvConvert::loadLib() { + + yang_YUY2ToNV12 = (int32_t (*)(const uint8_t *src_yuy2, int32_t src_stride_yuy2, + uint8_t *dst_y, int32_t dst_stride_y, uint8_t *dst_uv, + int32_t dst_stride_uv, int32_t width, int32_t height)) m_lib.loadFunction( + "YUY2ToNV12"); + yang_YUY2ToI420 =(int32_t (*)(const uint8_t *src_yuy2, int32_t src_stride_yuy2, + uint8_t *dst_y, int32_t dst_stride_y, uint8_t *dst_u, + int32_t dst_stride_u, uint8_t *dst_v, int32_t dst_stride_v, + int32_t width, int32_t height)) m_lib.loadFunction("YUY2ToI420"); + + yang_YUY2ToARGB=(int (*)(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height)) m_lib.loadFunction("YUY2ToARGB"); + yang_I420ToNV12=(int32_t (*)(const uint8_t* src_y, int32_t src_stride_y, const uint8_t* src_u, + int32_t src_stride_u,const uint8_t* src_v,int32_t src_stride_v, uint8_t* dst_y, + int32_t dst_stride_y, uint8_t* dst_uv, int32_t dst_stride_uv, int32_t width, int32_t height)) m_lib.loadFunction("I420ToNV12"); + + yang_I420ToNV21=(int32_t (*)(const uint8_t* src_y, + int32_t src_stride_y, + const uint8_t* src_u, + int32_t src_stride_u, + const uint8_t* src_v, + int32_t src_stride_v, + uint8_t* dst_y, + int32_t dst_stride_y, + uint8_t* dst_vu, + int32_t dst_stride_vu, + int32_t width, + int32_t height)) m_lib.loadFunction("I420ToNV21"); + + yang_I420ToRGB24 = (int32_t (*)(const uint8_t *src_y, int32_t src_stride_y, + const uint8_t *src_u, int32_t src_stride_u, const uint8_t *src_v, + int32_t src_stride_v, uint8_t *dst_rgb24, int32_t dst_stride_rgb24, + int32_t width, int32_t height)) m_lib.loadFunction("I420ToRGB24"); + yang_NV12ToRGB24 = (int32_t (*)(const uint8_t *src_y, int32_t src_stride_y, + const uint8_t *src_uv, int32_t src_stride_uv, uint8_t *dst_rgb24, + int32_t dst_stride_rgb24, int32_t width, int32_t height)) m_lib.loadFunction( + "NV12ToRGB24"); + yang_NV21ToRGB24 = (int32_t (*)(const uint8_t *src_y, int32_t src_stride_y, + const uint8_t *src_vu, int32_t src_stride_vu, uint8_t *dst_rgb24, + int32_t dst_stride_rgb24, int32_t width, int32_t height)) m_lib.loadFunction( + "NV21ToRGB24"); + yang_ARGBToRGB24 = + (int32_t (*)(const uint8_t *src_argb, int32_t src_stride_argb, + uint8_t *dst_rgb24, int32_t dst_stride_rgb24, int32_t width, + int32_t height)) m_lib.loadFunction("ARGBToRGB24"); + yang_RGB24ToI420 = + (int32_t (*)(const uint8_t *src_rgb24, int32_t src_stride_rgb24, + uint8_t *dst_y, int32_t dst_stride_y, uint8_t *dst_u, + int32_t dst_stride_u, uint8_t *dst_v, int32_t dst_stride_v, + int32_t width, int32_t height)) m_lib.loadFunction("RGB24ToI420"); + + yang_RGBAToI420=(int (*)(const uint8_t* src_rgba, + int src_stride_rgba, uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_u, int dst_stride_u, uint8_t* dst_v, + int dst_stride_v, int width, int height)) m_lib.loadFunction("RGBAToI420"); + yang_BGRAToI420=(int (*)(const uint8_t* src_bgra, int src_stride_bgra, + uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u, int dst_stride_u, + uint8_t* dst_v, int dst_stride_v,int width, int height)) m_lib.loadFunction("BGRAToI420"); + yang_ARGBToI420=(int (*)(const uint8_t* src_argb, int src_stride_argb, + uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,int dst_stride_u, + uint8_t* dst_v, int dst_stride_v, int width,int height)) m_lib.loadFunction("ARGBToI420"); + yang_RGB24ToARGB=(int32_t (*)(const uint8_t* src_rgb24, + int32_t src_stride_rgb24, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t width, + int32_t height)) m_lib.loadFunction("RGB24ToARGB"); + yang_RAWToARGB=(int32_t (*)(const uint8_t* src_raw, + int32_t src_stride_raw, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t width, + int32_t height)) m_lib.loadFunction("RAWToARGB"); + yang_NV12Scale = (int32_t (*)(const uint8_t *src_y, int32_t src_stride_y, + const uint8_t *src_uv, int32_t src_stride_uv, int32_t src_width, + int32_t src_height, uint8_t *dst_y, int32_t dst_stride_y, uint8_t *dst_uv, + int32_t dst_stride_uv, int32_t dst_width, int32_t dst_height, + enum FilterMode filtering)) m_lib.loadFunction("NV12Scale"); + yang_I420Scale = (int32_t (*)(const uint8_t *src_y, int32_t src_stride_y, + const uint8_t *src_u, int32_t src_stride_u, const uint8_t *src_v, + int32_t src_stride_v, int32_t src_width, int32_t src_height, uint8_t *dst_y, + int32_t dst_stride_y, uint8_t *dst_u, int32_t dst_stride_u, uint8_t *dst_v, + int32_t dst_stride_v, int32_t dst_width, int32_t dst_height, + enum FilterMode filtering)) m_lib.loadFunction("I420Scale"); + yang_ScalePlane = + (void (*)(const uint8_t *src, int32_t src_stride, int32_t src_width, + int32_t src_height, uint8_t *dst, int32_t dst_stride, int32_t dst_width, + int32_t dst_height, enum FilterMode filtering)) m_lib.loadFunction( + "ScalePlane"); + yang_ARGBScale=(int32_t (*)(const uint8_t* src_argb, + int32_t src_stride_argb, + int32_t src_width, + int32_t src_height, + uint8_t* dst_argb, + int32_t dst_stride_argb, + int32_t dst_width, + int32_t dst_height, + enum FilterMode filtering)) m_lib.loadFunction( + "ARGBScale"); +} + +void YangYuvConvert::unloadLib() { //srt_cleanup + yang_YUY2ToNV12 = NULL; + yang_YUY2ToI420 = NULL; + yang_YUY2ToARGB = NULL; + yang_I420ToNV12 = NULL; + yang_I420ToNV21 = NULL; + yang_I420ToRGB24 = NULL; + yang_NV12ToRGB24 = NULL; + yang_NV21ToRGB24 = NULL; + yang_ARGBToRGB24 = NULL; + yang_RGB24ToARGB=NULL; + yang_RAWToARGB=NULL; + yang_RGB24ToI420 = NULL; + yang_BGRAToI420=NULL; + yang_ARGBToI420=NULL; + yang_NV12Scale = NULL; + yang_I420Scale = NULL; + yang_ScalePlane = NULL; + yang_RGBAToI420=NULL; + yang_ARGBScale=NULL; + +} +YangYuvConvert::YangYuvConvert() { + + m_lib.loadObject("libyuv"); + loadLib(); +} + +YangYuvConvert::~YangYuvConvert() { + unloadLib(); + m_lib.unloadObject(); +} + +int32_t YangYuvConvert::yuy2tonv12(uint8_t *src, uint8_t *dst, int32_t width, int32_t height) { + return yang_YUY2ToNV12((const uint8_t*) src, width << 1, dst, width, + dst + (width * height), width, width, height); + //return ret; +} +int32_t YangYuvConvert::yuy2toi420(uint8_t *src, uint8_t *dst, int32_t width, int32_t height) { + + return yang_YUY2ToI420((const uint8_t*) src, width << 1, dst, width, + dst + (width * height), (width >> 1), + dst + (width * height) + (int) (width * height / 4), (width >> 1), + width, height); + +} +int32_t YangYuvConvert::yuy2toargb(uint8_t *src, uint8_t *dst, int32_t width, int32_t height) { + return yang_YUY2ToARGB((const uint8_t*) src, width << 1, + dst,width * 4, + width, height); + + //return ret; +} +int32_t YangYuvConvert::i420tonv12(uint8_t* src,uint8_t *dst,int32_t width,int32_t height){ + return yang_I420ToNV12((const uint8_t*) src, width, + (const uint8_t*) (src + (width * height)), (width >> 1), + (const uint8_t*) (src + (width * height)+ (int) (width * height / 4)), (width >> 1), + dst, width ,dst+width*height,width, + width, height); +} +int32_t YangYuvConvert::i420tonv21(uint8_t* src,uint8_t *dst,int32_t width,int32_t height){ + return yang_I420ToNV21((const uint8_t*) src, width, + (const uint8_t*) (src + (width * height)), (width >> 1), + (const uint8_t*) (src + (width * height)+ (int) (width * height / 4)), (width >> 1), + dst, width ,dst+width*height,width, + width, height); +} +//int32_t YangYuvUtil::bgr2yuy2(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeiht){ +// return 0; +//} + +int32_t YangYuvConvert::I420torgb24(uint8_t *src, uint8_t *dst, int32_t width, + int32_t height) { + return yang_I420ToRGB24((const uint8_t*) src, width, + (const uint8_t*) (src + (width * height)), (width >> 1), + (const uint8_t*) (src + (width * height) + + (int) (width * height / 4)), (width >> 1), dst, width * 3, + width, height); +} +int32_t YangYuvConvert::nv12torgb24(uint8_t *src, uint8_t *dst, int32_t width, + int32_t height) { + return yang_NV12ToRGB24((const uint8_t*) src, width, + (const uint8_t*) (src + (width * height)), width, dst, + width * 3, width, height); +} +int32_t YangYuvConvert::nv21torgb24(uint8_t *src, uint8_t *dst, int32_t width, + int32_t height) { + return yang_NV21ToRGB24((const uint8_t*) src, width, + (const uint8_t*) (src + (width * height)), width, dst, + width * 3, width, height); +} +int32_t YangYuvConvert::argbtorgb24(uint8_t *src, uint8_t *dst, int32_t width, + int32_t height) { + return yang_ARGBToRGB24((const uint8_t*) src, width * 4, dst, + width * 3, width, height); +} +int32_t YangYuvConvert::rgb24toargb(uint8_t *src, uint8_t *dst, int32_t width, + int32_t height) { + + return yang_RGB24ToARGB((const uint8_t*) src, width * 3, dst, + width * 4, width, height); +} +int32_t YangYuvConvert::rgb24toI420(uint8_t *src_rgb24, uint8_t *dst, int32_t width, + int32_t height) { + return yang_RGB24ToI420((const uint8_t*) src_rgb24, width * 3, dst, + width, dst + (width * height), (width >> 1), + dst + (width * height) + (int) (width * height / 4), (width >> 1), + width, height); +} + +int32_t YangYuvConvert::rgbatoI420(uint8_t* src_rgba,uint8_t *dst,int32_t width,int32_t height) { + return yang_RGBAToI420((const uint8_t*) src_rgba, width * 4, dst, + width, dst + (width * height), (width >> 1), + dst + (width * height) + (int) (width * height / 4), (width >> 1), + width, height); +} +int32_t YangYuvConvert::bgratoI420(uint8_t* src_bgra,uint8_t *dst,int32_t width,int32_t height) { + //return yang_BGRAToI420((const uint8_t*) src_bgra, width * 4, dst, + return yang_ARGBToI420((const uint8_t*) src_bgra, width * 4, dst, + width, dst + (width * height), (width >> 1), + dst + (width * height) + (int) (width * height / 4), (width >> 1), + width, height); +} +int32_t YangYuvConvert::scaleNv12(uint8_t *src, uint8_t *dst, int32_t srcWidth, + int32_t srcHeight, int32_t dstWidth, int32_t dstHeight, int32_t mode) { + return yang_NV12Scale((const uint8_t*) src, srcWidth, + (const uint8_t*) src + srcWidth * srcHeight, srcWidth, srcWidth, + srcHeight, dst, dstWidth, dst + dstWidth * dstHeight, dstWidth, + dstWidth, dstHeight, (libyuv::FilterMode) mode); +} +int32_t YangYuvConvert::scaleI420(uint8_t *src, uint8_t *dst, int32_t srcWidth, + int32_t srcHeight, int32_t dstWidth, int32_t dstHeight, int32_t mode) { + int32_t srcLen=srcWidth*srcHeight; + int32_t dstLen=dstWidth*dstHeight; + return yang_I420Scale((const uint8_t*) src, srcWidth, + (const uint8_t*) (src + srcLen), srcWidth/2, + (const uint8_t*) (src + srcLen*5/4),srcWidth/2, + srcWidth, srcHeight, + dst, dstWidth, + dst + dstLen, dstWidth/2, + dst + dstLen*5/4, dstWidth/2, + dstWidth, dstHeight, (libyuv::FilterMode) mode); +} + +int32_t YangYuvConvert::scaleYuy2(uint8_t *src, uint8_t *dst, int32_t srcWidth, + int32_t srcHeight, int32_t dstWidth, int32_t dstHeight, int32_t mode) { + yang_ScalePlane((const uint8_t*) src, srcWidth << 1, srcWidth, srcHeight, + dst, dstWidth << 1, dstWidth, dstHeight, (libyuv::FilterMode) mode); + return 0; +} + +int32_t YangYuvConvert::scaleArgb(uint8_t* src,uint8_t *dst,int32_t srcWidth,int32_t srcHeight,int32_t dstWidth,int32_t dstHeight,int32_t mode){ + +return yang_ARGBScale((const uint8_t*)src,srcWidth*4, +srcWidth,srcHeight, +dst,dstWidth*4, +dstWidth,dstHeight, +(libyuv::FilterMode)mode +); +} + +/** + int32_t scaleRgb(uint8_t* src,int32_t srcWidth,int32_t srcHeiht,uint8_t *dst,int32_t dstWidth,int32_t dstHeight,int32_t mode=2){ + libyuv::Scale() + return yang_ScaleR((const uint8_t*)src,srcWidth<<1, + srcWidth,srcHeight, + dst,dstWidth<<1, + dstWidth,dstHeight, + (libyuv::FilterMode)mode + ); + } +**/ + diff --git a/libyangrtc2/src/yangavutil/YangYuvUtil.cpp b/libyangrtc2/src/yangavutil/YangYuvUtil.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39bd0937c68e51c0e5fca563d29fc5ec7bb00623 --- /dev/null +++ b/libyangrtc2/src/yangavutil/YangYuvUtil.cpp @@ -0,0 +1,218 @@ +/* + * YangYuvUtil.cpp + * + * Created on: 2019年8月25日 + * Author: yang + */ + +#include "yangavutil/video/YangYuvUtil.h" +#include "stdio.h" +#include "memory.h" + + +void yang_plusNV12(uint8_t *src, uint8_t *dest, int32_t model, int32_t srcWidth, + int32_t srcHeight, int32_t destWidth, int32_t destHeight) { + int32_t srcLen = srcWidth * srcHeight, destLen = destWidth * destHeight; + uint8_t *temp, *srcTmp, *dstTmp; + if (model == 4) { + int32_t start4 = (srcHeight - destHeight + 1) * srcWidth - destWidth; + int32_t start41 = (srcHeight / 2 - destHeight / 2) * srcWidth + + (srcWidth - destWidth); + temp = src + start4; + srcTmp = src + srcLen + start41; + } else if (model == 3) { + int32_t start3 = srcWidth * (srcHeight - destHeight); + int32_t start31 = (srcHeight / 2 - destHeight / 2) * srcWidth; + temp = src + start3; + srcTmp = src + srcLen + start31; + } else if (model == 2) { + int32_t start2 = srcWidth - destWidth; + temp = src + start2; + srcTmp = src + srcLen + srcWidth - destWidth; + } else if (model == 1) { + temp = src; + srcTmp = src + srcLen; + } + dstTmp = dest + destLen; + for (int32_t i = 0; i < destHeight; i += 2) { + memcpy(temp + srcWidth * i, dest + i * destWidth, destWidth); + memcpy(temp + srcWidth * (i + 1), dest + (i + 1) * destWidth, + destWidth); + memcpy(srcTmp + i * srcWidth / 2, dstTmp + i * destWidth / 2, + destWidth); + } + temp=NULL; + srcTmp=NULL; + dstTmp=NULL; +} + +void yang_plusYuy2(uint8_t *src, uint8_t *dest, int32_t model, int32_t srcWidth, + int32_t srcHeight, int32_t destWidth, int32_t destHeight) { + //int32_t srcLen = srcWidth * srcHeight, destLen = destWidth * destHeight; + uint8_t *temp;//, *srcTmp, *dstTmp; + if (model == 4) { + int32_t start4 = (srcHeight - destHeight + 1) * srcWidth * 2 - destWidth * 2; + temp = src + start4; + //srcTmp=src+srcLen+start41; + } else if (model == 3) { + int32_t start3 = srcWidth * (srcHeight - destHeight); + //int32_t start31 = (srcHeight / 2 - destHeight / 2) * srcWidth; + temp = src + start3; + // srcTmp = src + srcLen + start31; + } else if (model == 2) { + int32_t start2 = srcWidth - destWidth; + temp = src + start2; + // srcTmp = src + srcLen + srcWidth - destWidth; + } else if (model == 1) { + temp = src; + // srcTmp = src + srcLen; + } + //dstTmp = dest + destLen; + for (int32_t i = 0; i < destHeight; i += 1) { + memcpy(temp + srcWidth * i * 2, dest + i * destWidth * 2, + destWidth * 2); + //memcpy(temp+srcWidth*(i+1),dest+(i+1)*destWidth,destWidth); + //memcpy(srcTmp+i*srcWidth/2,dstTmp+i*destWidth/2,destWidth); + } + temp=NULL; + //srcTmp=NULL; + + //dstTmp=NULL; + +} + +void yang_zoom4(uint8_t* src,uint8_t* dest,int32_t srcWidth,int32_t hei){ + + int32_t srcLen=srcWidth*hei; + int32_t destWidth=srcWidth/4; + int32_t destHeight=hei/4; + int32_t dstLen=destWidth*destHeight; + uint8_t* srcU=src+srcLen; + uint8_t* srcV=src+srcLen*5/4; + uint8_t* dstU=dest+dstLen; + uint8_t* dstV=dest+dstLen*5/4; + /** + for(int32_t i=0;i +#endif +#include +#include "yangutil/sys/YangLog.h" +YangAudioDeviceQuery::YangAudioDeviceQuery() { + + +} + +YangAudioDeviceQuery::~YangAudioDeviceQuery() { + +} + + +vector* YangAudioDeviceQuery::getCaptureDeviceList(){ + #ifndef _WIN32 + getDeviceList((int)SND_PCM_STREAM_CAPTURE,&m_captureDeviceList); + #endif + return &m_captureDeviceList; +} +vector* YangAudioDeviceQuery::getPlayDeviceList(){ + #ifndef _WIN32 + getDeviceList((int)SND_PCM_STREAM_PLAYBACK,&m_playDeviceList); + #endif + return &m_playDeviceList; +} +#ifndef _WIN32 +void YangAudioDeviceQuery::getDeviceList(int32_t pstream,vector* plist) { + snd_pcm_stream_t stream=(snd_pcm_stream_t)pstream; + snd_ctl_t *handle; + int32_t card, err, dev, idx; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + card = -1; + int32_t aindex=0; + while (1) { + if (snd_card_next(&card) < 0 || card < 0) { + yang_error("no soundcards found..."); + return; + } + + //printf("**** List of %s Hardware Devices ****\n",snd_pcm_stream_name(stream)); + char name[32]; + sprintf(name, "hw:%d", card); + if ((err = snd_ctl_open(&handle, name, 0)) < 0) { + yang_error("control open (%i): %s", card, snd_strerror(err)); + return; + } + if ((err = snd_ctl_card_info(handle, info)) < 0) { + yang_error("control hardware info (%i): %s", card, + snd_strerror(err)); + snd_ctl_close(handle); + return; + } + + dev = -1; + while (1) { + uint32_t count; + if (snd_ctl_pcm_next_device(handle, &dev) < 0) + yang_error("\nsnd_ctl_pcm_next_device"); + if (dev < 0) + break; + snd_pcm_info_set_device(pcminfo, dev); + snd_pcm_info_set_subdevice(pcminfo, 0); + snd_pcm_info_set_stream(pcminfo, stream); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { + if (err != -ENOENT) + yang_error("\ncontrol digital audio info (%i): %s", card, + snd_strerror(err)); + continue; + } + //printf("card %i: %s [%s], device %i: %s [%s]\n", card, + // snd_ctl_card_info_get_id(info), + // snd_ctl_card_info_get_name(info), dev, + // snd_pcm_info_get_id(pcminfo), + // snd_pcm_info_get_name(pcminfo)); + count = snd_pcm_info_get_subdevices_count(pcminfo); + //printf(" Subdevices: %i/%i\n",snd_pcm_info_get_subdevices_avail(pcminfo), count); + for (idx = 0; idx < (int) count; idx++) { + snd_pcm_info_set_subdevice(pcminfo, idx); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { + yang_error("control digital audio playback info (%i): %s", + card, snd_strerror(err)); + } else { + plist->push_back(YangAudioDeivce()); + char sn[64]={0}; + sprintf(sn,"%s [%s]",snd_ctl_card_info_get_id(info),snd_ctl_card_info_get_name(info)); + plist->back().name=string(sn); + char sn1[64]={0}; + sprintf(sn1,"%s [%s]",snd_pcm_info_get_id(pcminfo),snd_pcm_info_get_name(pcminfo)); + plist->back().deviceName=string(sn1); + plist->back().subName=string(snd_pcm_info_get_subdevice_name(pcminfo)); + plist->back().aIndex=aindex; + plist->back().aSubIndex=dev; + plist->back().aIdx=idx; + //printf(" Subdevice #%i: %s\n", idx,snd_pcm_info_get_subdevice_name(pcminfo)); + } + } + } + snd_ctl_close(handle); + aindex++; + } + +} +#endif diff --git a/libyangrtc2/src/yangcapture/YangCaptureFactory.cpp b/libyangrtc2/src/yangcapture/YangCaptureFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13d99c7c6d76c0e1164147238bec2c8c95652e08 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangCaptureFactory.cpp @@ -0,0 +1,68 @@ +/* + * YangCaptureImpl.cpp + * + * Created on: 2019年8月30日 + * Author: yang + */ + +#include "yangcapture/YangCaptureFactory.h" +#ifndef _WIN32 +#include +#include +#include +#include "YangVideoCaptureImpl.h" + +#else +#include +#include +#include +#include "win/YangWinVideoCapture.h" +#endif +#include "YangScreenCaptureImpl.h" + +YangCaptureFactory::YangCaptureFactory() { + + +} + +YangCaptureFactory::~YangCaptureFactory() { + +} + +YangAudioCapture *YangCaptureFactory::createAudioCapture(YangContext *pcontext){ +#ifndef _WIN32 + return new YangAlsaDeviceHandle(pcontext);//new YangAlsaHandle(pcontext);//YangAudioCaptureImpl(pcontext); +#else + // return new YangWinAudioCapture(pcontext); + return new YangWinAudioApiDevice(pcontext,0,true); +#endif + +} +YangAudioCapture *YangCaptureFactory::createRecordAudioCapture(YangContext *pcontext){ +#ifndef _WIN32 + return new YangAudioCaptureImpl(pcontext);//new YangAlsaHandle(pcontext);//YangAudioCaptureImpl(pcontext); +#else + return new YangWinRecordAudioCapture(pcontext); + //return new YangWinAudioApiDevice(pcontext,1); +#endif +} + + +YangMultiVideoCapture *YangCaptureFactory::createVideoCapture(YangVideoInfo *pcontext){ +#ifndef _WIN32 + return new YangVideoCaptureImpl(pcontext); +#else + return new YangWinVideoCapture(pcontext); +#endif +} +YangMultiVideoCapture *YangCaptureFactory::createRecordVideoCapture(YangVideoInfo *pcontext){ +#ifndef _WIN32 + return new YangVideoCaptureImpl(pcontext); +#else + return new YangWinVideoCapture(pcontext); +#endif +} + +YangScreenCapture *YangCaptureFactory::createScreenCapture(YangContext *pcontext){ + return new YangScreenCaptureImpl(pcontext); +} diff --git a/libyangrtc2/src/yangcapture/YangDXGIManager.cpp b/libyangrtc2/src/yangcapture/YangDXGIManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d6c990366e2d28d8e022161a74230eed8294f9e --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangDXGIManager.cpp @@ -0,0 +1,729 @@ +#ifdef _MSC_VER + +#include "YangDXGIManager.h" +#include +#include +#ifdef _MSC_VER +#pragma comment (lib,"D3D11.lib") +#pragma comment (lib,"dxgi.lib") +#pragma comment (lib,"gdiplus.lib") +#endif +using namespace Gdiplus; + +YangDXGIPointerInfo::YangDXGIPointerInfo(BYTE* pPointerShape, UINT uiPointerShapeBufSize, DXGI_OUTDUPL_FRAME_INFO fi, DXGI_OUTDUPL_POINTER_SHAPE_INFO psi) + : m_pPointerShape(pPointerShape), + m_uiPointerShapeBufSize(uiPointerShapeBufSize), + m_FI(fi), + m_PSI(psi) +{ + +} + +YangDXGIPointerInfo::~YangDXGIPointerInfo() +{ + if(m_pPointerShape) + { + delete [] m_pPointerShape; + } +} + +BYTE* YangDXGIPointerInfo::GetBuffer() +{ + return m_pPointerShape; +} + +UINT YangDXGIPointerInfo::GetBufferSize() +{ + return m_uiPointerShapeBufSize; +} + +DXGI_OUTDUPL_FRAME_INFO& YangDXGIPointerInfo::GetFrameInfo() +{ + return m_FI; +} + +DXGI_OUTDUPL_POINTER_SHAPE_INFO& YangDXGIPointerInfo::GetShapeInfo() +{ + return m_PSI; +} + +YangDXGIOutputDuplication::YangDXGIOutputDuplication(IDXGIAdapter1* pAdapter, + ID3D11Device* pD3DDevice, + ID3D11DeviceContext* pD3DDeviceContext, + IDXGIOutput1* pDXGIOutput1, + IDXGIOutputDuplication* pDXGIOutputDuplication) + : m_Adapter(pAdapter), + m_D3DDevice(pD3DDevice), + m_D3DDeviceContext(pD3DDeviceContext), + m_DXGIOutput1(pDXGIOutput1), + m_DXGIOutputDuplication(pDXGIOutputDuplication) +{ +} + +HRESULT YangDXGIOutputDuplication::GetDesc(DXGI_OUTPUT_DESC& desc) +{ + m_DXGIOutput1->GetDesc(&desc); + return S_OK; +} + +HRESULT YangDXGIOutputDuplication::AcquireNextFrame(IDXGISurface1** pDXGISurface, YangDXGIPointerInfo*& pDXGIPointer) +{ + DXGI_OUTDUPL_FRAME_INFO fi; + CComPtr spDXGIResource; + HRESULT hr = m_DXGIOutputDuplication->AcquireNextFrame(33, &fi, &spDXGIResource); + if(FAILED(hr)) + { + // yang_error("m_DXGIOutputDuplication->AcquireNextFrame failed with hr=0x%08x", hr); + return hr; + } + + CComQIPtr spTextureResource = spDXGIResource; + + D3D11_TEXTURE2D_DESC desc; + spTextureResource->GetDesc(&desc); + + D3D11_TEXTURE2D_DESC texDesc; + ZeroMemory( &texDesc, sizeof(texDesc) ); + texDesc.Width = desc.Width; + texDesc.Height = desc.Height; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0; + texDesc.Usage = D3D11_USAGE_STAGING; + texDesc.Format = desc.Format; + texDesc.BindFlags = 0; + texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + texDesc.MiscFlags = 0; + + CComPtr spD3D11Texture2D = NULL; + hr = m_D3DDevice->CreateTexture2D(&texDesc, NULL, &spD3D11Texture2D); + if(FAILED(hr)) + return hr; + + m_D3DDeviceContext->CopyResource(spD3D11Texture2D, spTextureResource); + + CComQIPtr spDXGISurface = spD3D11Texture2D; + + *pDXGISurface = spDXGISurface.Detach(); + + // Updating mouse pointer, if visible + if(fi.PointerPosition.Visible) + { + BYTE* pPointerShape = new BYTE[fi.PointerShapeBufferSize]; + + DXGI_OUTDUPL_POINTER_SHAPE_INFO psi = {}; + UINT uiPointerShapeBufSize = fi.PointerShapeBufferSize; + hr = m_DXGIOutputDuplication->GetFramePointerShape(uiPointerShapeBufSize, pPointerShape, &uiPointerShapeBufSize, &psi); + if(hr == DXGI_ERROR_MORE_DATA) + { + pPointerShape = new BYTE[uiPointerShapeBufSize]; + + hr = m_DXGIOutputDuplication->GetFramePointerShape(uiPointerShapeBufSize, pPointerShape, &uiPointerShapeBufSize, &psi); + } + + if(hr == S_OK) + { + // yang_trace("\nPointerPosition Visible=%d x=%d y=%d w=%d h=%d type=%d\n", fi.PointerPosition.Visible, fi.PointerPosition.Position.x, fi.PointerPosition.Position.y, psi.Width, psi.Height, psi.Type); + + if((psi.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME || + psi.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR || + psi.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR) && + psi.Width <= 128 && psi.Height <= 128) + { + // Here we can obtain pointer shape + if(pDXGIPointer) + { + delete pDXGIPointer; + } + + pDXGIPointer = new YangDXGIPointerInfo(pPointerShape, uiPointerShapeBufSize, fi, psi); + + pPointerShape = NULL; + } + + DXGI_OUTPUT_DESC outDesc; + GetDesc(outDesc); + + if(pDXGIPointer) + { + pDXGIPointer->GetFrameInfo().PointerPosition.Position.x = outDesc.DesktopCoordinates.left + fi.PointerPosition.Position.x; + pDXGIPointer->GetFrameInfo().PointerPosition.Position.y = outDesc.DesktopCoordinates.top + fi.PointerPosition.Position.y; + } + } + + if(pPointerShape) + { + yang_deleteA(pPointerShape); + } + } + + return hr; +} + +HRESULT YangDXGIOutputDuplication::ReleaseFrame() +{ + m_DXGIOutputDuplication->ReleaseFrame(); + return S_OK; +} + +bool YangDXGIOutputDuplication::IsPrimary() +{ + DXGI_OUTPUT_DESC outdesc; + m_DXGIOutput1->GetDesc(&outdesc); + + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(outdesc.Monitor, &mi); + if(mi.dwFlags & MONITORINFOF_PRIMARY) + { + return true; + } + return false; +} + +YangDXGIManager::YangDXGIManager() +{ + m_CaptureSource = CSUndefined; + SetRect(&m_rcCurrentOutput, 0, 0, 0, 0); + m_pBuf = NULL; + m_pDXGIPointer = NULL; + m_bInitialized = false; + m_isDrawmouse=false; +} + +YangDXGIManager::~YangDXGIManager() +{ + GdiplusShutdown(m_gdiplusToken); + + if(m_pBuf) + { + delete [] m_pBuf; + m_pBuf = NULL; + } + + if(m_pDXGIPointer) + { + delete m_pDXGIPointer; + m_pDXGIPointer = NULL; + } +} + +HRESULT YangDXGIManager::SetCaptureSource(YangCaptureSource cs) +{ + m_CaptureSource = cs; + return S_OK; +} + +YangCaptureSource YangDXGIManager::GetCaptureSource() +{ + return m_CaptureSource; +} + +HRESULT YangDXGIManager::Init() +{ + if(m_bInitialized) + return S_OK; + + GdiplusStartupInput gdiplusStartupInput; + GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); + + HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&m_spDXGIFactory1) ); + if( FAILED(hr) ) + { + yang_error("Failed to CreateDXGIFactory1 hr=%08x", hr); + return hr; + } + + // Getting all adapters + vector> vAdapters; + + CComPtr spAdapter; + for(int i=0; m_spDXGIFactory1->EnumAdapters1(i, &spAdapter) != DXGI_ERROR_NOT_FOUND; i++) + { + vAdapters.push_back(spAdapter); + spAdapter.Release(); + } + + // Iterating over all adapters to get all outputs + for(vector>::iterator AdapterIter = vAdapters.begin(); + AdapterIter != vAdapters.end(); + AdapterIter++) + { + vector> vOutputs; + + CComPtr spDXGIOutput; + for(int i=0; (*AdapterIter)->EnumOutputs(i, &spDXGIOutput) != DXGI_ERROR_NOT_FOUND; i++) + { + DXGI_OUTPUT_DESC outputDesc; + spDXGIOutput->GetDesc(&outputDesc); + + /** yang_trace("\nDisplay output found. DeviceName=%ls AttachedToDesktop=%d Rotation=%d DesktopCoordinates={(%d,%d),(%d,%d)}", + outputDesc.DeviceName, + outputDesc.AttachedToDesktop, + outputDesc.Rotation, + outputDesc.DesktopCoordinates.left, + outputDesc.DesktopCoordinates.top, + outputDesc.DesktopCoordinates.right, + outputDesc.DesktopCoordinates.bottom); + **/ + if(outputDesc.AttachedToDesktop) + { + vOutputs.push_back(spDXGIOutput); + } + + spDXGIOutput.Release(); + } + + if(vOutputs.size() == 0) + continue; + + // Creating device for each adapter that has the output + CComPtr spD3D11Device; + CComPtr spD3D11DeviceContext; + D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_9_1; + hr = D3D11CreateDevice((*AdapterIter), D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &spD3D11Device, &fl, &spD3D11DeviceContext); + if( FAILED(hr) ) + { + yang_error("Failed to create D3D11CreateDevice hr=%08x", hr); + return hr; + } + + for(std::vector>::iterator OutputIter = vOutputs.begin(); + OutputIter != vOutputs.end(); + OutputIter++) + { + CComQIPtr spDXGIOutput1 = *OutputIter; + if (!spDXGIOutput1) + { + yang_error("spDXGIOutput1 is NULL"); + continue; + } + + CComQIPtr spDXGIDevice = spD3D11Device; + if (!spDXGIDevice) + { + yang_error("spDXGIDevice is NULL"); + continue; + } + + CComPtr spDXGIOutputDuplication; + hr = spDXGIOutput1->DuplicateOutput(spDXGIDevice, &spDXGIOutputDuplication); + if (FAILED(hr)) + { + yang_error("Failed to duplicate output hr=%08x", hr); + continue; + } + + m_vOutputs.push_back( + YangDXGIOutputDuplication((*AdapterIter), + spD3D11Device, + spD3D11DeviceContext, + spDXGIOutput1, + spDXGIOutputDuplication)); + } + } + + hr = m_spWICFactory.CoCreateInstance(CLSID_WICImagingFactory); + if( FAILED(hr) ) + { + yang_error("Failed to create WICImagingFactory hr=%08x", hr); + return hr; + } + + m_bInitialized = true; + + return S_OK; +} + +HRESULT YangDXGIManager::GetOutputRect(RECT& rc) +{ + // Nulling rc just in case... + SetRect(&rc, 0, 0, 0, 0); + + HRESULT hr = Init(); + if(hr != S_OK) + return hr; + + vector vOutputs = GetOutputDuplication(); + + RECT rcShare; + SetRect(&rcShare, 0, 0, 0, 0); + + for(vector::iterator iter = vOutputs.begin(); + iter != vOutputs.end(); + iter++) + { + YangDXGIOutputDuplication& out = *iter; + + DXGI_OUTPUT_DESC outDesc; + out.GetDesc(outDesc); + RECT rcOutCoords = outDesc.DesktopCoordinates; + + UnionRect(&rcShare, &rcShare, &rcOutCoords); + } + + CopyRect(&rc, &rcShare); + + return S_OK; +} + +HRESULT YangDXGIManager::GetOutputBits(BYTE* pBits, RECT& rcDest) +{ + HRESULT hr = S_OK; + + DWORD dwDestWidth = rcDest.right - rcDest.left; + DWORD dwDestHeight = rcDest.bottom - rcDest.top; + + RECT rcOutput; + hr = GetOutputRect(rcOutput); + if( FAILED(hr) ) + return hr; + + DWORD dwOutputWidth = rcOutput.right - rcOutput.left; + DWORD dwOutputHeight = rcOutput.bottom - rcOutput.top; + + BYTE* pBuf = NULL; + if(rcOutput.right > (LONG)dwDestWidth || rcOutput.bottom > (LONG)dwDestHeight) + { + // Output is larger than pBits dimensions + if(!m_pBuf || !EqualRect(&m_rcCurrentOutput, &rcOutput)) + { + DWORD dwBufSize = dwOutputWidth*dwOutputHeight*4; + + if(m_pBuf) + { + delete [] m_pBuf; + m_pBuf = NULL; + } + + m_pBuf = new BYTE[dwBufSize]; + + CopyRect(&m_rcCurrentOutput, &rcOutput); + } + + pBuf = m_pBuf; + } + else + { + // Output is smaller than pBits dimensions + pBuf = pBits; + dwOutputWidth = dwDestWidth; + dwOutputHeight = dwDestHeight; + } + + vector vOutputs = GetOutputDuplication(); + + for(vector::iterator iter = vOutputs.begin(); + iter != vOutputs.end(); + iter++) + { + YangDXGIOutputDuplication& out = *iter; + + DXGI_OUTPUT_DESC outDesc; + out.GetDesc(outDesc); + RECT rcOutCoords = outDesc.DesktopCoordinates; + + CComPtr spDXGISurface1; + hr = out.AcquireNextFrame(&spDXGISurface1, m_pDXGIPointer); + if( FAILED(hr) ) + break; + + DXGI_MAPPED_RECT map; + spDXGISurface1->Map(&map, DXGI_MAP_READ); + + RECT rcDesktop = outDesc.DesktopCoordinates; + DWORD dwWidth = rcDesktop.right - rcDesktop.left; + DWORD dwHeight = rcDesktop.bottom - rcDesktop.top; + + OffsetRect(&rcDesktop, -rcOutput.left, -rcOutput.top); + + DWORD dwMapPitchPixels = map.Pitch/4; + + switch(outDesc.Rotation) + { + case DXGI_MODE_ROTATION_IDENTITY: + { + // Just copying + DWORD dwStripe = dwWidth*4; + for(unsigned int i=0; iUnmap(); + + out.ReleaseFrame(); + } + + if(FAILED(hr)) + return hr; + + // Now pBits have the desktop. Let's paint mouse pointer! + if(m_isDrawmouse){ + if(pBuf != pBits) + { + DrawMousePointer(pBuf, rcOutput, rcOutput); + } + else + { + DrawMousePointer(pBuf, rcOutput, rcDest); + } + } + // We have the pBuf filled with current desktop/monitor image. + if(pBuf != pBits) + { + // pBuf contains the image that should be resized + CComPtr spBitmap = NULL; + hr = m_spWICFactory->CreateBitmapFromMemory(dwOutputWidth, dwOutputHeight, GUID_WICPixelFormat32bppBGRA, dwOutputWidth*4, dwOutputWidth*dwOutputHeight*4, (BYTE*)pBuf, &spBitmap); + if( FAILED(hr) ) + return hr; + + CComPtr spBitmapScaler = NULL; + hr = m_spWICFactory->CreateBitmapScaler(&spBitmapScaler); + if( FAILED(hr) ) + return hr; + + dwOutputWidth = rcOutput.right - rcOutput.left; + dwOutputHeight = rcOutput.bottom - rcOutput.top; + + double aspect = (double)dwOutputWidth/(double)dwOutputHeight; + + DWORD scaledWidth = dwDestWidth; + DWORD scaledHeight = dwDestHeight; + + if(aspect > 1) + { + scaledWidth = dwDestWidth; + scaledHeight = (DWORD)(dwDestWidth/aspect); + } + else + { + scaledWidth = (DWORD)(aspect*dwDestHeight); + scaledHeight = dwDestHeight; + } + yang_trace("\nscaledWidth==%ld,scaledHeight=%ld",scaledWidth,scaledHeight); + spBitmapScaler->Initialize( + spBitmap, scaledWidth, scaledHeight, WICBitmapInterpolationModeNearestNeighbor); + + spBitmapScaler->CopyPixels(NULL, scaledWidth*4, dwDestWidth*dwDestHeight*4, pBits); + } + return hr; +} + +void YangDXGIManager::DrawMousePointer(BYTE* pDesktopBits, RECT rcDesktop, RECT rcDest) +{ + if(!m_pDXGIPointer) + return; + +// DWORD dwDesktopWidth = rcDesktop.right - rcDesktop.left; +// DWORD dwDesktopHeight = rcDesktop.bottom - rcDesktop.top; + + DWORD dwDestWidth = rcDest.right - rcDest.left; + DWORD dwDestHeight = rcDest.bottom - rcDest.top; + + int PtrX = m_pDXGIPointer->GetFrameInfo().PointerPosition.Position.x - rcDesktop.left; + int PtrY = m_pDXGIPointer->GetFrameInfo().PointerPosition.Position.y - rcDesktop.top; + switch(m_pDXGIPointer->GetShapeInfo().Type) + { + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: + { + Bitmap bmpBitmap(dwDestWidth, dwDestHeight, dwDestWidth*4, PixelFormat32bppARGB, pDesktopBits); + Graphics* graphics=Graphics::FromImage(&bmpBitmap); + Bitmap bmpPointer(m_pDXGIPointer->GetShapeInfo().Width, m_pDXGIPointer->GetShapeInfo().Height, m_pDXGIPointer->GetShapeInfo().Width*4, PixelFormat32bppARGB, m_pDXGIPointer->GetBuffer()); + + graphics->DrawImage(&bmpPointer, PtrX, PtrY); + yang_delete(graphics); + } + break; + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME: + case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR: + { + RECT rcPointer; + + if(m_pDXGIPointer->GetShapeInfo().Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME) + { + SetRect(&rcPointer, PtrX, PtrY, PtrX + m_pDXGIPointer->GetShapeInfo().Width, PtrY + m_pDXGIPointer->GetShapeInfo().Height/2); + } + else + { + SetRect(&rcPointer, PtrX, PtrY, PtrX + m_pDXGIPointer->GetShapeInfo().Width, PtrY + m_pDXGIPointer->GetShapeInfo().Height); + } + + RECT rcDesktopPointer; + IntersectRect(&rcDesktopPointer, &rcPointer, &rcDesktop); + + CopyRect(&rcPointer, &rcDesktopPointer); + OffsetRect(&rcPointer, -PtrX, -PtrY); + + BYTE* pShapeBuffer = m_pDXGIPointer->GetBuffer(); + UINT* pDesktopBits32 = (UINT*)pDesktopBits; + + if(m_pDXGIPointer->GetShapeInfo().Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME) + { + for(int j = rcPointer.top, jDP = rcDesktopPointer.top; + j> (i % 8); + BYTE AndMask = pShapeBuffer[i/8 + (m_pDXGIPointer->GetShapeInfo().Pitch)*j] & Mask; + BYTE XorMask = pShapeBuffer[i/8 + (m_pDXGIPointer->GetShapeInfo().Pitch)*(j + m_pDXGIPointer->GetShapeInfo().Height / 2)] & Mask; + + UINT AndMask32 = (AndMask) ? 0xFFFFFFFF : 0xFF000000; + UINT XorMask32 = (XorMask) ? 0x00FFFFFF : 0x00000000; + + pDesktopBits32[jDP*dwDestWidth + iDP] = (pDesktopBits32[jDP*dwDestWidth + iDP] & AndMask32) ^ XorMask32; + } + } + } + else + { + UINT* pShapeBuffer32 = (UINT*)pShapeBuffer; + for(int j = rcPointer.top, jDP = rcDesktopPointer.top; + jGetShapeInfo().Pitch/4)*j]; + if (MaskVal) + { + // Mask was 0xFF + pDesktopBits32[jDP*dwDestWidth + iDP] = (pDesktopBits32[jDP*dwDestWidth + iDP] ^ pShapeBuffer32[i + (m_pDXGIPointer->GetShapeInfo().Pitch/4)*j]) | 0xFF000000; + } + else + { + // Mask was 0x00 - replacing pixel + pDesktopBits32[jDP*dwDestWidth + iDP] = pShapeBuffer32[i + (m_pDXGIPointer->GetShapeInfo().Pitch/4)*j]; + } + } + } + } + } + break; + } +} + +vector YangDXGIManager::GetOutputDuplication() +{ + vector outputs; + switch(m_CaptureSource) + { + case CSMonitor1: + { + // Return the one with IsPrimary + for(vector::iterator iter = m_vOutputs.begin(); + iter != m_vOutputs.end(); + iter++) + { + YangDXGIOutputDuplication& out = *iter; + if(out.IsPrimary()) + { + outputs.push_back(out); + break; + } + } + } + break; + + case CSMonitor2: + { + // Return the first with !IsPrimary + for(vector::iterator iter = m_vOutputs.begin(); + iter != m_vOutputs.end(); + iter++) + { + YangDXGIOutputDuplication& out = *iter; + if(!out.IsPrimary()) + { + outputs.push_back(out); + break; + } + } + } + break; + + case CSDesktop: + { + // Return all outputs + for(vector::iterator iter = m_vOutputs.begin(); + iter != m_vOutputs.end(); + iter++) + { + YangDXGIOutputDuplication& out = *iter; + outputs.push_back(out); + } + } + break; + } + return outputs; +} + +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + int *Count = (int*)dwData; + (*Count)++; + return TRUE; +} + +int YangDXGIManager::GetMonitorCount() +{ + int Count = 0; + if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count)) + return Count; + return -1; +} +#endif diff --git a/libyangrtc2/src/yangcapture/YangDXGIManager.h b/libyangrtc2/src/yangcapture/YangDXGIManager.h new file mode 100644 index 0000000000000000000000000000000000000000..7152dbdc90c50828c3fd3236972dc60d630234d8 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangDXGIManager.h @@ -0,0 +1,92 @@ +#ifdef _MSC_VER + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class YangDXGIPointerInfo; + +enum YangCaptureSource +{ + CSUndefined, + CSMonitor1, + CSMonitor2, + CSDesktop +}; + +class YangDXGIPointerInfo +{ +public: + YangDXGIPointerInfo(BYTE* pPointerShape, UINT uiPointerShapeBufSize, DXGI_OUTDUPL_FRAME_INFO fi, DXGI_OUTDUPL_POINTER_SHAPE_INFO psi); + ~YangDXGIPointerInfo(); + BYTE* GetBuffer(); + UINT GetBufferSize(); + DXGI_OUTDUPL_FRAME_INFO& GetFrameInfo(); + DXGI_OUTDUPL_POINTER_SHAPE_INFO& GetShapeInfo(); + +private: + BYTE* m_pPointerShape; + UINT m_uiPointerShapeBufSize; + DXGI_OUTDUPL_POINTER_SHAPE_INFO m_PSI; + DXGI_OUTDUPL_FRAME_INFO m_FI; +}; + +class YangDXGIOutputDuplication +{ +public: + YangDXGIOutputDuplication(IDXGIAdapter1* pAdapter, + ID3D11Device* pD3DDevice, + ID3D11DeviceContext* pD3DDeviceContext, + IDXGIOutput1* pDXGIOutput1, + IDXGIOutputDuplication* pDXGIOutputDuplication); + + HRESULT GetDesc(DXGI_OUTPUT_DESC& desc); + HRESULT AcquireNextFrame(IDXGISurface1** pD3D11Texture2D, YangDXGIPointerInfo*& pDXGIPointer); + HRESULT ReleaseFrame(); + + bool IsPrimary(); + + +private: + CComPtr m_Adapter; + CComPtr m_D3DDevice; + CComPtr m_D3DDeviceContext; + CComPtr m_DXGIOutput1; + CComPtr m_DXGIOutputDuplication; +}; + +class YangDXGIManager +{ +public: + YangDXGIManager(); + ~YangDXGIManager(); + HRESULT SetCaptureSource(YangCaptureSource type); + YangCaptureSource GetCaptureSource(); + + HRESULT GetOutputRect(RECT& rc); + HRESULT GetOutputBits(BYTE* pBits, RECT& rcDest); + bool m_isDrawmouse; +private: + HRESULT Init(); + int GetMonitorCount(); + vector GetOutputDuplication(); + void DrawMousePointer(BYTE* pDesktopBits, RECT rcDesktop, RECT rcDest); +private: + CComPtr m_spDXGIFactory1; + vector m_vOutputs; + bool m_bInitialized; + YangCaptureSource m_CaptureSource; + RECT m_rcCurrentOutput; + BYTE* m_pBuf; + + CComPtr m_spWICFactory; + ULONG_PTR m_gdiplusToken; + YangDXGIPointerInfo* m_pDXGIPointer; +}; +#endif diff --git a/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.cpp b/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48bfc2c13934ab13da9fdebd54c3213d099c3b5b --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.cpp @@ -0,0 +1,229 @@ +/* + * YangScreenCapture.cpp + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#include "YangScreenCaptureImpl.h" +#include +#include +#include "yangutil/sys/YangTime.h" +#include "yangutil/sys/YangLog.h" +#include +#include + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +int32_t YangScreenCaptureImpl::init(){ + + struct fb_var_screeninfo fb_var_info; + struct fb_fix_screeninfo fb_fix_info; + + + + // 打开framebuffer设备 + m_fd = open("/dev/fb0", O_RDONLY); + if(m_fd < 0) + { + yang_error("can not open dev\n"); + return ERROR_SYS_Linux_ScreenDeviceOpenFailure; + } + + // 获取LCD的可变参数 + ioctl(m_fd, FBIOGET_VSCREENINFO, &fb_var_info); + // 一个像素多少位 + printf("bits_per_pixel: %d\n", fb_var_info.bits_per_pixel); + // 一个像素多少位 + printf("bits_per_pixel: %d\n", fb_var_info.bits_per_pixel); + // x分辨率 + printf("xres: %d\n", fb_var_info.xres); + // y分辨率 + printf("yres: %d\n", fb_var_info.yres); + // r分量长度(bit) + printf("red_length: %d\n", fb_var_info.red.length); + // g分量长度(bit) + printf("green_length: %d\n", fb_var_info.green.length); + // b分量长度(bit) + printf("blue_length: %d\n", fb_var_info.blue.length); + // t(透明度)分量长度(bit) + printf("transp_length: %d\n", fb_var_info.transp.length); + // r分量偏移 + printf("red_offset: %d\n", fb_var_info.red.offset); + // g分量偏移 + printf("green_offset: %d\n", fb_var_info.green.offset); + // b分量偏移 + printf("blue_offset: %d\n", fb_var_info.blue.offset); + // t分量偏移 + printf("transp_offset: %d\n", fb_var_info.transp.offset); + + // 获取LCD的固定参数 + ioctl(m_fd, FBIOGET_FSCREENINFO, &fb_fix_info); + // 一帧大小 + printf("smem_len: %d\n", fb_fix_info.smem_len); + // 一行大小 + printf("line_length: %d\n", fb_fix_info.line_length); + // 一帧大小 + m_bufLen = (fb_var_info.xres * fb_var_info.yres * fb_var_info.bits_per_pixel / 8); + m_width=fb_var_info.xres; + m_height=fb_var_info.yres; + m_rgb = (uint8_t *)malloc(m_bufLen); + //if(trgb == NULL) exit(0); + m_rgb = (uint8_t *)malloc(fb_var_info.xres * fb_var_info.yres * 3); + //if(m_rgb == NULL) + //{ + // goto here; + //} + + return Yang_Ok; +} +#else +#include "YangDXGIManager.h" + +int32_t YangScreenCaptureImpl::init() { + + if (m_out_videoBuffer == NULL) + m_out_videoBuffer = new YangVideoBuffer( + m_context->video.bitDepth == 8 ? 1 : 2); + if (m_pre_videoBuffer == NULL) + m_pre_videoBuffer = new YangVideoBuffer( + m_context->video.bitDepth == 8 ? 1 : 2); + return Yang_Ok; +} + +#endif +YangScreenCaptureImpl::YangScreenCaptureImpl(YangContext *pcontext) { + m_context = pcontext; + m_width = 0; + m_height = 0; + m_rgb = NULL; + m_bufLen = 0; + m_fd = 0; + m_out_videoBuffer = nullptr; + m_pre_videoBuffer = nullptr; + isCapture = 0; + m_loop = 0; + m_state = 0; + m_interval=40; + m_isDrawmouse=false; +} + +YangScreenCaptureImpl::~YangScreenCaptureImpl() { + if(m_isStart){ + stop(); + yang_stop_thread(this); + } + m_context = NULL; + yang_delete(m_pre_videoBuffer); + yang_delete(m_out_videoBuffer); +} + +void YangScreenCaptureImpl::setVideoCaptureStart() { + m_state = 1; +} +void YangScreenCaptureImpl::setVideoCaptureStop() { + m_state = 0; +} +int32_t YangScreenCaptureImpl::getVideoCaptureState(){ + return m_state; +} +YangVideoBuffer* YangScreenCaptureImpl::getPreVideoBuffer() { + return m_pre_videoBuffer; +} +YangVideoBuffer* YangScreenCaptureImpl::getOutVideoBuffer() { + return m_out_videoBuffer; +} +void YangScreenCaptureImpl::putBuffer(YangFrame *videoFrame) { + m_out_videoBuffer->putVideo(videoFrame); +} + +void YangScreenCaptureImpl::setDrawmouse(bool isDraw) { + m_isDrawmouse=isDraw; + +} + +bool YangScreenCaptureImpl::getisDrawmouse() { + return m_isDrawmouse; +} + +void YangScreenCaptureImpl::stopLoop() { + m_loop = 0; +} +void YangScreenCaptureImpl::startLoop() { +#ifdef _MSC_VER + CoInitialize(NULL); + YangDXGIManager g_DXGIManager; + g_DXGIManager.SetCaptureSource(CSDesktop); + + RECT rcDim; + g_DXGIManager.GetOutputRect(rcDim); + + int dwWidth = rcDim.right - rcDim.left; + int dwHeight = rcDim.bottom - rcDim.top; + if (m_out_videoBuffer == NULL) + m_out_videoBuffer = new YangVideoBuffer( + m_context->video.bitDepth == 8 ? 1 : 2); + if (m_pre_videoBuffer == NULL) + m_pre_videoBuffer = new YangVideoBuffer( + m_context->video.bitDepth == 8 ? 1 : 2); + m_out_videoBuffer->init(dwWidth, dwHeight, m_context->video.videoEncoderFormat); + m_pre_videoBuffer->init(dwWidth, dwHeight, m_context->video.videoEncoderFormat); + yang_trace("dwWidth=%d dwHeight=%d\n", dwWidth, dwHeight); + + DWORD dwBufSize = dwWidth * dwHeight * 4; + int yuvLen=dwWidth * dwHeight * 3 / 2; + YangYuvConvert yuv; + uint8_t *pBuf = new uint8_t[dwBufSize]; + uint8_t *dst = new uint8_t[yuvLen]; + YangFrame frame; + memset(&frame,0,sizeof(YangFrame)); + int64_t startTime = 0; + frame.payload = dst; + frame.nb = dwWidth * dwHeight * 3 / 2; + if(m_context->video.videoEncoderFormat==YangArgb) { + frame.nb = dwWidth * dwHeight * 4; + frame.payload=pBuf; + } + HRESULT hr = 0; + m_loop = 1; + while (m_loop) { + yang_usleep(m_interval*1000); + g_DXGIManager.m_isDrawmouse=m_isDrawmouse; + hr = g_DXGIManager.GetOutputBits(pBuf, rcDim); + if (FAILED(hr)) { + if(hr==DXGI_ERROR_WAIT_TIMEOUT){ + //yang_error("GetOutputBits failed because DXGI_ERROR_WAIT_TIMEOUT\n"); + }else + yang_error("GetOutputBits failed with hr=0x%08x\n", hr); + + } else { + if (startTime == 0) + startTime = yang_get_system_time(); + + if(m_context->video.videoEncoderFormat==YangI420) yuv.bgratoI420(pBuf, dst, dwWidth, dwHeight); + //yuv.rgbatoI420(pBuf, dst, dwWidth, dwHeight); + + frame.timestamp = yang_get_system_time() - startTime; + m_pre_videoBuffer->putVideo(&frame); + if (m_state){ + //yang_trace("%d,",frame.nb); + m_out_videoBuffer->putVideo(&frame); + } + + } + + } + yang_deleteA(pBuf); + yang_deleteA(dst); + CoUninitialize(); +#endif +} + +void YangScreenCaptureImpl::setInterval(int32_t pinterval) { + m_interval=pinterval; +} diff --git a/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.h b/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..aa5567d07042dab2e70ccfe5af19db3d34d023d9 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangScreenCaptureImpl.h @@ -0,0 +1,45 @@ +/* + * YangScreenCapture.h + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YANGSCREENCAPTUREIMPL_H_ +#define YANGCAPTURE_SRC_YANGSCREENCAPTUREIMPL_H_ +#include +#include "yangutil/buffer/YangVideoBuffer.h" +#include + +class YangScreenCaptureImpl:public YangScreenCapture { +public: + YangScreenCaptureImpl(YangContext* pcontext); + virtual ~YangScreenCaptureImpl(); + int32_t m_width,m_height; + int32_t init(); + void setInterval(int32_t pinterval); + void setDrawmouse(bool isDraw); + bool getisDrawmouse(); + YangVideoBuffer * getOutVideoBuffer(); + YangVideoBuffer * getPreVideoBuffer(); + void setVideoCaptureStart(); + void setVideoCaptureStop(); + int32_t getVideoCaptureState(); + YangVideoBuffer* getScreenBuffer(); + uint8_t *m_rgb; + int32_t m_bufLen,isCapture; + int32_t m_fd; + void putBuffer(YangFrame* videoFrame); + void startLoop(); + void stopLoop(); +private: + YangVideoBuffer *m_out_videoBuffer; + YangVideoBuffer *m_pre_videoBuffer; + YangContext* m_context; + int m_loop; + int m_state; + int32_t m_interval; + bool m_isDrawmouse; +}; + +#endif /* YANGCAPTURE_SRC_YANGSCREENCAPTUREIMPL_H_ */ diff --git a/libyangrtc2/src/yangcapture/YangScreenShare.cpp b/libyangrtc2/src/yangcapture/YangScreenShare.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c99511af0b6cd91d4403e9bf55b979be3005c6c --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangScreenShare.cpp @@ -0,0 +1,93 @@ +/* + * YangScreenShareLinux.cpp + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#include "YangScreenShare.h" +#include "yangutil/yang_unistd.h" +#include "yangavutil/video/YangYuvConvert.h" + +YangScreenCapture::YangScreenCapture(){ + m_isStart=0; +} +YangScreenCapture::~YangScreenCapture(){ + + } + +void YangScreenCapture::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangScreenCapture::stop() { + stopLoop(); + +} +YangScreenShare::YangScreenShare() { + //m_capture=new YangScreenShareImpl(); + //m_vhandle=new YangVideoCaptureHandle(); + m_isloop=0; + m_out_videoBuffer=NULL; + m_capture=NULL; + m_isCapture=0; + m_interval=0; +} + +YangScreenShare::~YangScreenShare() { + m_capture=NULL; + m_out_videoBuffer=NULL; +} +void YangScreenShare::setOutVideoBuffer(YangVideoBuffer *pbuf){ + m_out_videoBuffer=pbuf; +} +void YangScreenShare::setScreenHandle(YangScreenCaptureHandleI *handle){ + m_capture=handle; +} +void YangScreenShare::setInterval(int32_t pinterval){ + m_interval=1000*pinterval; +} +void YangScreenShare::setVideoCaptureStart() { + m_isCapture = 1; +} +void YangScreenShare::setVideoCaptureStop() { + m_isCapture = 0; +} +int32_t YangScreenShare::getVideoCaptureState() { + return m_isCapture; +} + +void YangScreenShare::initstamp() { + //m_vhandle->initstamp(); +} +void YangScreenShare::stopLoop() { + m_isloop = 0; +} +int32_t YangScreenShare::init() { + return m_capture->init(); +} +void YangScreenShare::startLoop() { + m_isloop = 1; + /** + //m_vhandle->m_start_time = 0; + int32_t width=m_capture->m_width; + int32_t height=m_capture->m_height; + uint8_t buf[width*height*4]; + uint8_t yuv[width*height*3/2]; + int32_t yuvLen=width*height*3/2; + YangYuvConvert con; + int64_t timestamp=0; + YangFrame videoFrame; +memset(&m_audioFrame,0,sizeof(YangFrame)); + while (m_isloop) { + m_capture->captureFrame(buf); + con.rgb24toI420(buf,yuv,width,height); + videoFrame.payload=yuv; + videoFrame.nb=yuvLen; + videoFrame.timestamp=timestamp; + m_out_videoBuffer->putVideo(&videoFrame); + yang_usleep(3000); + }**/ +} + diff --git a/libyangrtc2/src/yangcapture/YangScreenShare.h b/libyangrtc2/src/yangcapture/YangScreenShare.h new file mode 100644 index 0000000000000000000000000000000000000000..764ed2959fc4484d200266379702eaeda5ec5670 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangScreenShare.h @@ -0,0 +1,42 @@ +/* + * YangScreenShare.h + * + * Created on: 2021年3月31日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YANGSCREENSHARE_H_ +#define YANGCAPTURE_SRC_YANGSCREENSHARE_H_ +#include "yangcapture/YangScreenCapture.h" +class YangScreenShare :public YangScreenCapture{ +public: + YangScreenShare(); + virtual ~YangScreenShare(); + + +public: + void setScreenHandle(YangScreenCaptureHandleI *handle); + void setInterval(int32_t pinterval); + int32_t init(); + void setVideoCaptureStart(); + void setVideoCaptureStop(); + void setOutVideoBuffer(YangVideoBuffer *pbuf); + int32_t getVideoCaptureState(); + void initstamp(); + void stopLoop(); +private: + int32_t m_isloop; + int32_t m_isCapture; + int32_t m_interval; + YangScreenCaptureHandleI *m_capture; + YangVideoBuffer *m_out_videoBuffer; + + +protected: + void startLoop(); +}; + + + + +#endif /* YANGCAPTURE_SRC_YANGSCREENSHARE_H_ */ diff --git a/libyangrtc2/src/yangcapture/YangVideoCapture.cpp b/libyangrtc2/src/yangcapture/YangVideoCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c557c898cab38a6bdcadcdefab151e6df687b63f --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoCapture.cpp @@ -0,0 +1,29 @@ + +#include +#include +YangVideoCapture::YangVideoCapture() { + cameraIndex=0; + m_isStart=0; + m_para=NULL; +} + +YangVideoCapture::~YangVideoCapture() { + m_para=NULL; +} + +void YangVideoCapture::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangVideoCapture::stop() { + stopLoop(); + +} + +void yang_get_camera_indexs(std::vector *pvs,std::string pcamindex){ + vector res=yang_split(pcamindex,','); + for(size_t i=0;ipush_back(atoi(res[i].c_str())); + } +} diff --git a/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.cpp b/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a07e8cdc24021d5ff9ce20ddf7a44d3c5a8ca15 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.cpp @@ -0,0 +1,95 @@ +#include "YangVideoCaptureHandle.h" + +#include "time.h" +#include "stdlib.h" +#include "stdio.h" + + +YangVideoCaptureHandle::YangVideoCaptureHandle(YangVideoInfo *pcontext) { + memset(&m_videoFrame,0,sizeof(YangFrame)); + curstamp = 0; + basesatmp = 0; + m_isCapture = 0; + m_isLivingCaptrue=0; + m_isFilm=0; + vtick=0; + + m_start_time = 0; + m_out_videoBuffer = NULL; + m_pre_videoBuffer=NULL; + m_living_out_videoBuffer=NULL; + m_film_out_videoBuffer=NULL; + m_width=pcontext->width; + m_height=pcontext->height; + m_buf=NULL; + m_bufLen=m_width*m_height*3/2; + + m_encoderVideoFormat=pcontext->videoEncoderFormat; + +} +YangVideoCaptureHandle::~YangVideoCaptureHandle(void) { + m_out_videoBuffer=NULL; + m_pre_videoBuffer=NULL; + m_living_out_videoBuffer=NULL; + m_film_out_videoBuffer=NULL; + if(m_buf) delete[] m_buf; + m_buf=NULL; + +} +void YangVideoCaptureHandle::setCaptureFormat(int32_t pformat){ + if(pformat==YangYuy2&&!m_buf) m_buf=new uint8_t[m_bufLen]; +} +void YangVideoCaptureHandle::setVideoBuffer(YangVideoBuffer *pbuf){ + m_out_videoBuffer=pbuf; +} +void YangVideoCaptureHandle::setPreVideoBuffer(YangVideoBuffer *pbuf){ + m_pre_videoBuffer=pbuf; +} +void YangVideoCaptureHandle::setLivingVideoBuffer(YangVideoBuffer *pbuf){ + m_living_out_videoBuffer=pbuf; +} +void YangVideoCaptureHandle::setFilmVideoBuffer(YangVideoBuffer *pbuf){ + m_film_out_videoBuffer=pbuf; +} +void YangVideoCaptureHandle::initstamp() { + basesatmp = curstamp; //-m_adjust_time*10000; +} + +void YangVideoCaptureHandle::putBuffer(int64_t pstamtime, uint8_t *pBuffer, int32_t BufferLen) { + + curstamp = pstamtime; + if(basesatmp==0) basesatmp=pstamtime; + vtick = pstamtime - basesatmp; + + m_videoFrame.timestamp=vtick; + if(m_buf){ + if(m_encoderVideoFormat==YangI420) m_yuv.yuy2toi420(pBuffer,m_buf,m_width,m_height); + if(m_encoderVideoFormat==YangNv12) m_yuv.yuy2tonv12(pBuffer,m_buf,m_width,m_height); + if(m_encoderVideoFormat==YangArgb) m_yuv.yuy2toargb(pBuffer,m_buf,m_width,m_height); + m_videoFrame.payload=m_buf; + m_videoFrame.nb=m_bufLen; + putBuffers(); + + }else{ + m_videoFrame.payload=pBuffer; + m_videoFrame.nb=BufferLen; + putBuffers(); + + } + //return; +} + +void YangVideoCaptureHandle::putBuffers() { + + if(m_pre_videoBuffer) m_pre_videoBuffer->putVideo(&m_videoFrame); + if(m_isFilm&&m_film_out_videoBuffer) m_film_out_videoBuffer->putVideo(&m_videoFrame); + if (m_isCapture&&m_out_videoBuffer) { + m_out_videoBuffer->putVideo(&m_videoFrame); + + } + if (m_isLivingCaptrue&&m_living_out_videoBuffer){ + m_living_out_videoBuffer->putVideo(&m_videoFrame); + } + + +} diff --git a/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.h b/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..d24832cf9d5859f7f20583caea2a3ca5b302c26c --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoCaptureHandle.h @@ -0,0 +1,42 @@ +#ifndef __YangLivingVideoCaptureHandle__ +#define __YangLivingVideoCaptureHandle__ +#include +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +class YangVideoCaptureHandle +{ +public: + YangVideoCaptureHandle(YangVideoInfo *pcontext); + virtual ~YangVideoCaptureHandle(void); + void reset(YangVideoInfo* p_config); + + void putBuffer(int64_t startTime, uint8_t *pBuffer, int32_t BufferLen); + void putBuffers(); + void saveFile(char* fileName,double Time, uint8_t *pBuffer, int32_t BufferLen); + void initstamp(); + void startLoop(); + long m_start_time; + int32_t m_isCapture; + int32_t m_isLivingCaptrue; + int32_t m_isFilm; + void setVideoBuffer(YangVideoBuffer *pbuf); + void setLivingVideoBuffer(YangVideoBuffer *pbuf); + void setFilmVideoBuffer(YangVideoBuffer *pbuf); + void setPreVideoBuffer(YangVideoBuffer *plist); + void setCaptureFormat(int32_t pformat); +private: + + YangVideoBuffer *m_out_videoBuffer,*m_pre_videoBuffer,*m_living_out_videoBuffer,*m_film_out_videoBuffer; + YangFrame m_videoFrame; + YangYuvConvert m_yuv; + uint8_t *m_buf; + int32_t m_width,m_height,m_bufLen; + int64_t vtick; + int64_t curstamp,basesatmp; + int m_encoderVideoFormat; + + + +}; + +#endif diff --git a/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.cpp b/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79c526624824d1788a456a09f1c2343f91b844ee --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.cpp @@ -0,0 +1,458 @@ +/* + * YangVideoCaptureImpl.cpp + * + * Created on: 2019年8月30日 + * Author: yang + */ + +#include "YangVideoCaptureImpl.h" +YangMultiVideoCapture::YangMultiVideoCapture() { + + +} +YangMultiVideoCapture::~YangMultiVideoCapture() { + +} + + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +YangVideoCaptureImpl::YangVideoCaptureImpl(YangVideoInfo *pcontext) { + + m_para = pcontext; + + m_vhandle = new YangVideoCaptureHandle(pcontext); + cameraIndex = pcontext->vIndex; + m_width = m_para->width; + m_height = m_para->height; + m_vd_id = 0; + + memset(&m_buf, 0, sizeof(m_buf)); + m_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + m_buf.memory = V4L2_MEMORY_MMAP; + m_isloop = 0; + m_isFirstFrame = 0; + m_buffer_count = 0; + m_timestatmp = 0; + m_hasYuy2 = 0, m_hasI420 = 0, m_hasNv12 = 0, m_hasYv12 = 0, m_hasP010 = 0,m_hasP016=0; +} + +YangVideoCaptureImpl::~YangVideoCaptureImpl() { + if (m_isloop) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + //m_log=NULL; + //m_context=NULL; + stop_capturing(); + uninit_camer_device(); + close_camer_device(); + delete m_vhandle; + m_vhandle = NULL; +} +void YangVideoCaptureImpl::setVideoCaptureStart() { + m_vhandle->m_isCapture = 1; +} +void YangVideoCaptureImpl::setVideoCaptureStop() { + m_vhandle->m_isCapture = 0; +} +int32_t YangVideoCaptureImpl::getVideoCaptureState() { + return m_vhandle->m_isCapture; +} +int32_t YangVideoCaptureImpl::getLivingVideoCaptureState() { + return m_vhandle->m_isLivingCaptrue; +} +int32_t YangVideoCaptureImpl::getFilmVideoCaptureState() { + return m_vhandle->m_isFilm; +} + +void YangVideoCaptureImpl::setLivingVideoCaptureStart() { + m_vhandle->m_isLivingCaptrue = 1; +} +void YangVideoCaptureImpl::setLivingVideoCaptureStop() { + m_vhandle->m_isLivingCaptrue = 0; +} + +void YangVideoCaptureImpl::setFilmVideoCaptureStart() { + m_vhandle->m_isFilm = 1; +} +void YangVideoCaptureImpl::setFilmVideoCaptureStop() { + m_vhandle->m_isFilm = 0; +} + +void YangVideoCaptureImpl::setOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setVideoBuffer(pbuf); +} +void YangVideoCaptureImpl::setLivingOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setLivingVideoBuffer(pbuf); +} +void YangVideoCaptureImpl::setFilmOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setFilmVideoBuffer(pbuf); +} +void YangVideoCaptureImpl::setPreVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setPreVideoBuffer(pbuf); +} +void YangVideoCaptureImpl::initstamp() { + m_vhandle->initstamp(); +} +int32_t YangVideoCaptureImpl::enum_camera_frmival(int32_t fd, struct v4l2_frmsizeenum *framesize) { + struct v4l2_frmivalenum frmival; + memset(&frmival, 0, sizeof(frmival)); + frmival.pixel_format = framesize->pixel_format; + frmival.width = framesize->discrete.width; + frmival.height = framesize->discrete.height; + //frmival.type = V4L2_FRMIVAL_TYPE_DISCRETE; + frmival.index = 0; + //yang_trace("the frame intervals enum"); + + while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) == 0) { + //输出分数,即帧间隔 + if(frmival.width==m_para->width) { + yang_trace("%d.frameinterval:%u/%u\n ", frmival.index, + frmival.discrete.numerator, frmival.discrete.denominator); + } + frmival.index++; + } + //yang_trace(".........................................\n"); + return 0; +} + +void YangVideoCaptureImpl::setReselution(__u32 format,int32_t val){ + if (format == V4L2_PIX_FMT_YUYV) + m_hasYuy2 = val; + if (format == V4L2_PIX_FMT_YUV420) + m_hasI420 = val; + if (format == V4L2_PIX_FMT_NV12) + m_hasNv12 = val; + if (format == V4L2_PIX_FMT_YVU420) + m_hasYv12 = val; +} +void YangVideoCaptureImpl::setReselutionPara(__u32 pformat){ + //struct v4l2_capability cap; + struct v4l2_fmtdesc fmt; + int32_t vet=0; + while ((vet = ioctl(m_vd_id, VIDIOC_ENUM_FMT, &fmt)) != -1) { + fmt.index++; + if(fmt.pixelformat==pformat){ + struct v4l2_frmsizeenum frmsize; + frmsize.pixel_format = fmt.pixelformat; + frmsize.index = 0; + while (!ioctl(m_vd_id, VIDIOC_ENUM_FRAMESIZES, &frmsize)) { + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + m_para->width=frmsize.discrete.width; + m_para->height=frmsize.discrete.height; + m_width=frmsize.discrete.width; + m_height=frmsize.discrete.height; + } + enum_camera_frmival(m_vd_id, &frmsize); + frmsize.index++; + } + } + } + +} +int32_t YangVideoCaptureImpl::setPara() { + struct v4l2_capability cap; + struct v4l2_fmtdesc fmt; + memset(&fmt, 0, sizeof(struct v4l2_fmtdesc)); + fmt.index = 0; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int32_t vet = 0; + + + if (ioctl(m_vd_id, VIDIOC_QUERYCAP, &cap) != 0) { + yang_error("\n VIDIOC_QUERYCAP error!"); + return ERROR_SYS_Linux_NoVideoDriver; + } + yang_trace("\ndriver name %s card = %s cap = %0x\n", cap.driver, cap.card, + cap.capabilities); + + while ((vet = ioctl(m_vd_id, VIDIOC_ENUM_FMT, &fmt)) != -1) { + fmt.index++; + setReselution(fmt.pixelformat,1); + //if(fmt.==m_para->width) + yang_trace("\n{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n", + fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF, + (fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF, + fmt.description); + struct v4l2_frmsizeenum frmsize; + frmsize.pixel_format = fmt.pixelformat; + frmsize.index = 0; + while (!ioctl(m_vd_id, VIDIOC_ENUM_FRAMESIZES, &frmsize)) { + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + if(m_para->width==(int)frmsize.discrete.width&&m_para->height==(int)frmsize.discrete.height){ + yang_trace("DISCRETE: line-%d %d: {%d*%d}\n", __LINE__, + frmsize.index, frmsize.discrete.width,frmsize.discrete.height); + setReselution(fmt.pixelformat,2); + } + + } + + else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + yang_trace("\nSTEPWISE: line: %d %d: {%d*%d}\n", __LINE__, + frmsize.index, frmsize.stepwise.max_width, + frmsize.stepwise.max_height); + } + + enum_camera_frmival(m_vd_id, &frmsize); + frmsize.index++; + } + } + + return Yang_Ok; +} +std::string getVideoFormat(uint32_t pformat ){ + std::string res=""; + if(pformat==V4L2_PIX_FMT_YUV420) res="I420"; + if(pformat==V4L2_PIX_FMT_NV12) res="Nv12"; + if(pformat==V4L2_PIX_FMT_YVU420) res="Yv12"; + if(pformat==V4L2_PIX_FMT_YUYV) res="Yuy2"; + return res; +} +int32_t YangVideoCaptureImpl::init() { + char devStr[30]; + memset(devStr, 0, 30); + sprintf(devStr, "/dev/video%d", cameraIndex); + //if ((m_vd_id = open(devStr, O_RDWR|O_NONBLOCK)) == -1) { + if ((m_vd_id = open(devStr, O_RDWR)) == -1) { + yang_error("open video device Error!"); + return ERROR_SYS_Linux_VideoDeveceOpenFailure; + } + + int32_t ret = Yang_Ok; + ret = setPara(); + if (ret) return ret; + uint32_t format = V4L2_PIX_FMT_YUYV; + if(m_hasYuy2>1||m_hasI420>1||m_hasNv12>1||m_hasYv12>1){ + if(m_hasI420>1) { + format = V4L2_PIX_FMT_YUV420; + m_para->videoCaptureFormat=YangI420; + }else if(m_hasNv12>1){ + format = V4L2_PIX_FMT_NV12; + m_para->videoCaptureFormat=YangNv12; + }else if(m_hasYv12>1){ + format = V4L2_PIX_FMT_YVU420; + m_para->videoCaptureFormat=YangYv12; + }else if(m_hasYuy2>1){ + format = V4L2_PIX_FMT_YUYV; + m_para->videoCaptureFormat=YangYuy2; + } + #if Yang10bit + if(m_para->videoCaptureFormat==YangP010) format=V4L2_PIX_FMT_P010; + if(m_para->videoCaptureFormat==YangP016) format=V4L2_PIX_FMT_P016; + #endif + + }else if(m_hasYuy2||m_hasI420||m_hasNv12||m_hasYv12){ + if(m_hasI420) { + format = V4L2_PIX_FMT_YUV420; + m_para->videoCaptureFormat=YangI420; + }else if(m_hasNv12){ + format = V4L2_PIX_FMT_NV12; + m_para->videoCaptureFormat=YangNv12; + }else if(m_hasYv12){ + format = V4L2_PIX_FMT_YVU420; + m_para->videoCaptureFormat=YangYv12; + }else if(m_hasYuy2){ + format = V4L2_PIX_FMT_YUYV; + m_para->videoCaptureFormat=YangYuy2; + } + setReselutionPara(format); + }else{ + return ERROR_SYS_Linux_NoVideoCatpureInterface; + } + + struct v4l2_format v4_format; + v4_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4_format.fmt.pix.width = m_width; + v4_format.fmt.pix.height = m_height; + v4_format.fmt.pix.pixelformat = format; //V4L2_PIX_FMT_YUYV; //V4L2_PIX_FMT_YUYV; + v4_format.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if ((ioctl(m_vd_id, VIDIOC_S_FMT, &v4_format)) != 0) { + yang_error("\n set fmt error!"); + + } + if(m_vhandle) m_vhandle->setCaptureFormat(m_para->videoCaptureFormat); + + + + + struct v4l2_streamparm Stream_Parm; + memset(&Stream_Parm, 0, sizeof(struct v4l2_streamparm)); + Stream_Parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + Stream_Parm.parm.capture.timeperframe.denominator =m_para->frame;; + Stream_Parm.parm.capture.timeperframe.numerator = 1; + + if( ioctl(m_vd_id, VIDIOC_S_PARM, &Stream_Parm)){ + yang_error("\n..........................set video frame error!"); + } + + printf("\n..................index==%d......set.format============%s\n",cameraIndex,getVideoFormat(format).c_str()); + printf("\n ...................index==%d,set framerate===%d",cameraIndex,m_para->frame); + // setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + // setfps.parm.capture.timeperframe.numerator = 10; + // setfps.parm.capture.timeperframe.denominator = 10; + struct v4l2_requestbuffers tV4L2_reqbuf; + uint32_t i = 0; + memset(&tV4L2_reqbuf, 0, sizeof(struct v4l2_requestbuffers)); + tV4L2_reqbuf.count = REQ_BUF_NUM; + tV4L2_reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + tV4L2_reqbuf.memory = V4L2_MEMORY_MMAP; + + if (ioctl(m_vd_id, VIDIOC_REQBUFS, &tV4L2_reqbuf)) { + + } + m_buffer_count = tV4L2_reqbuf.count; + + if (m_user_buffer == NULL) { + yang_error("calloc Error"); + exit(1); + } + for (i = 0; i < tV4L2_reqbuf.count; i++) { + struct v4l2_buffer tV4L2buf; + memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer)); + tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + tV4L2buf.memory = V4L2_MEMORY_MMAP; + tV4L2buf.index = i; + if (ioctl(m_vd_id, VIDIOC_QUERYBUF, &tV4L2buf)) + printf("search!"); + //m_buf_length=tV4L2buf.length; + m_user_buffer[i].length = tV4L2buf.length; + m_user_buffer[i].start = (uint8_t*) mmap( NULL, tV4L2buf.length, + PROT_READ | PROT_WRITE, MAP_SHARED, m_vd_id, tV4L2buf.m.offset); + if (MAP_FAILED == m_user_buffer[i].start) { + yang_error(" error! mmap"); + exit(1); + } + } + return Yang_Ok; +} + +long YangVideoCaptureImpl::m_difftime(struct timeval *p_start, + struct timeval *p_end) { + return (p_end->tv_sec - p_start->tv_sec) * 1000000 + + (p_end->tv_usec - p_start->tv_usec); +} + +int32_t YangVideoCaptureImpl::read_buffer() { + + if (ioctl(m_vd_id, VIDIOC_DQBUF, &m_buf) != 0) { + yang_error("VIDIOC_DQBUF"); + exit(1); + } + if (m_isFirstFrame) { + m_timestatmp = m_difftime(&m_startTime, &m_buf.timestamp); + } else { + m_isFirstFrame = 1; + m_startTime.tv_sec = m_buf.timestamp.tv_sec; + m_startTime.tv_usec = m_buf.timestamp.tv_usec; + m_timestatmp = 0; + } + + if (m_vhandle) + m_vhandle->putBuffer(m_timestatmp, m_user_buffer[m_buf.index].start, + m_user_buffer[m_buf.index].length); + + // printf("\n%ld",m_timestatmp); + if (ioctl(m_vd_id, VIDIOC_QBUF, &m_buf) != 0) { + yang_error("VIDIOC_QBUF"); + exit(1); + } + + return Yang_Ok; +} +void YangVideoCaptureImpl::stopLoop() { + m_isloop = 0; +} + +void YangVideoCaptureImpl::stop_capturing() { + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == ioctl(m_vd_id, VIDIOC_STREAMOFF, &type)) { + yang_error("Fail to ioctl 'VIDIOC_STREAMOFF'"); + exit(EXIT_FAILURE); + } + +} +void YangVideoCaptureImpl::uninit_camer_device() { + int32_t i = 0; + + for (i = 0; i < m_buffer_count; i++) { + if (-1 == munmap(m_user_buffer[i].start, m_user_buffer[i].length)) { + exit(EXIT_FAILURE); + } + } + + //free(user_buffer); + +} +void YangVideoCaptureImpl::close_camer_device() { + if (-1 == close(m_vd_id)) { + yang_error("Fail to close fd"); + exit(EXIT_FAILURE); + } + +} + +void YangVideoCaptureImpl::startLoop() { + for (int32_t i = 0; i < m_buffer_count; i++) { + struct v4l2_buffer tV4L2buf; + memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer)); + tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + tV4L2buf.memory = V4L2_MEMORY_MMAP; + tV4L2buf.index = i; + if (ioctl(m_vd_id, VIDIOC_QBUF, &tV4L2buf)) { + yang_error("VIDIOC_QBUF"); + } + } + + enum v4l2_buf_type v4l2type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(m_vd_id, VIDIOC_STREAMON, &v4l2type)) { + yang_error("VIDIOC_STREAMON"); + } + + fd_set fds; + struct timeval tv; + int32_t r; + FD_ZERO(&fds); + FD_SET(m_vd_id, &fds); + m_isloop = 1; + m_vhandle->m_start_time = 0; + + while (m_isloop) { + tv.tv_sec = 2; + tv.tv_usec = 0; + r = select(m_vd_id + 1, &fds, NULL, NULL, &tv); + if (-1 == r) { + if (EINTR == errno) + continue; + yang_error("video capture Fail to select"); + exit(EXIT_FAILURE); + } + if (0 == r) { + yang_error("video capture select Timeout\n"); + exit(EXIT_FAILURE); + } + read_buffer(); + } + +} +#endif diff --git a/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.h b/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..0e5cf5e2da1d7659e11a8841b7de218492853a02 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoCaptureImpl.h @@ -0,0 +1,74 @@ +/* + * YangVideoCaptureImpl.h + * + * Created on: 2019年8月30日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YANGVIDEOCAPTUREIMPL_H_ +#define YANGCAPTURE_SRC_YANGVIDEOCAPTUREIMPL_H_ +#include "yangcapture/YangMultiVideoCapture.h" + +#ifndef _WIN32 +#include "linux/videodev2.h" + +#include "YangVideoCaptureHandle.h" +#define REQ_BUF_NUM 4 //申请的缓冲区个数,最多5个,缓冲区太少可能会导致图像有间断 +typedef struct buffer_type_r buffer_type; +struct buffer_type_r { + uint8_t *start; + int32_t length; +}; + +class YangVideoCaptureImpl: public YangMultiVideoCapture { +public: + YangVideoCaptureImpl(YangVideoInfo *pcontext); + ~YangVideoCaptureImpl(); + YangVideoCaptureHandle *m_vhandle; + int32_t init(); + void setVideoCaptureStart(); + void setVideoCaptureStop(); + void setOutVideoBuffer(YangVideoBuffer *pbuf); + void setPreVideoBuffer(YangVideoBuffer *pbuf); + int32_t getVideoCaptureState(); + void initstamp(); + void stopLoop(); + + int32_t getLivingVideoCaptureState(); + int32_t getFilmVideoCaptureState(); + + void setLivingOutVideoBuffer(YangVideoBuffer *pbuf); + void setLivingVideoCaptureStart(); + void setLivingVideoCaptureStop(); + + void setFilmOutVideoBuffer(YangVideoBuffer *pbuf); + void setFilmVideoCaptureStart(); + void setFilmVideoCaptureStop(); +protected: + void startLoop(); + long m_difftime(struct timeval *p_start, struct timeval *p_end); +private: + int32_t setPara(); + void setReselution(__u32 format, int32_t val); + void setReselutionPara(__u32 pformat); + void process_image(char *p_addr, int32_t p_length); + int32_t read_buffer(); + void stop_capturing(); + void uninit_camer_device(); + void close_camer_device(); + int32_t enum_camera_frmival(int32_t fd, struct v4l2_frmsizeenum *framesize); + + int32_t m_hasYuy2, m_hasI420, m_hasNv12, m_hasYv12, m_hasP010, m_hasP016; + int32_t m_width, m_height; + int32_t m_vd_id; + struct v4l2_buffer m_buf; + buffer_type m_user_buffer[REQ_BUF_NUM]; + int32_t m_buffer_count; + int32_t m_isloop; + int32_t m_isFirstFrame; + struct timeval m_startTime; + long m_timestatmp; + +}; +#endif +#endif /* YANGCAPTURE_SRC_YANGVIDEOCAPTUREIMPL_H_ */ diff --git a/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.cpp b/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c27654a6f272ff77fc235ff9f43bb6ae0381f89 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.cpp @@ -0,0 +1,101 @@ +#include +#ifndef _WIN32 +#include "linux/videodev2.h" +#include +#include +#include + +#endif +#include "yangutil/sys/YangLog.h" + +YangVideoDeviceQuery::YangVideoDeviceQuery() { + +} + +YangVideoDeviceQuery::~YangVideoDeviceQuery() { + +} + +struct YangVideoDevice{ + string name; + int32_t vindex; +}; +#ifndef _WIN32 +int32_t YangVideoDeviceQuery::getVideoDeviceList() { + vector* pv; + struct v4l2_capability cap; + struct v4l2_fmtdesc fmt; + memset(&fmt, 0, sizeof(struct v4l2_fmtdesc)); + fmt.index = 0; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int32_t vet = 0; + int32_t m_vd_id=0; + //v4l2_device dd; + if (ioctl(m_vd_id, VIDIOC_QUERYCAP, &cap) != 0) { + yang_error("\n VIDIOC_QUERYCAP error!"); + return ERROR_SYS_Linux_NoVideoDriver; + } + yang_trace("\ndriver name %s card = %s cap = %0x\n", cap.driver, cap.card, + cap.capabilities); + + while ((vet = ioctl(m_vd_id, VIDIOC_ENUM_FMT, &fmt)) != -1) { + pv->push_back(YangVideoDevice()); + pv->back().name=string((char*)fmt.description); + pv->back().vindex=fmt.index; + fmt.index++; + + //if(fmt.==m_para->width) + yang_trace("\n{ pixelformat = ''%c%c%c%c'', description = ''%s'' }\n", + fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF, + (fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF, + fmt.description); + struct v4l2_frmsizeenum frmsize; + frmsize.pixel_format = fmt.pixelformat; + frmsize.index = 0; + while (!ioctl(m_vd_id, VIDIOC_ENUM_FRAMESIZES, &frmsize)) { + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + //if (m_para->width == (int) frmsize.discrete.width&& m_para->height == (int) frmsize.discrete.height) { + yang_trace("DISCRETE: line-%d %d: {%d*%d}\n", __LINE__, + frmsize.index, frmsize.discrete.width, + frmsize.discrete.height); + // setReselution(fmt.pixelformat, 2); + //} + + } + + else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + yang_trace("\nSTEPWISE: line: %d %d: {%d*%d}\n", __LINE__, + frmsize.index, frmsize.stepwise.max_width, + frmsize.stepwise.max_height); + } + + enum_camera_frmival(m_vd_id, &frmsize); + frmsize.index++; + } + } + return 1; +} + +int32_t YangVideoDeviceQuery::enum_camera_frmival(int32_t fd, struct v4l2_frmsizeenum *framesize) { + struct v4l2_frmivalenum frmival; + memset(&frmival, 0, sizeof(frmival)); + frmival.pixel_format = framesize->pixel_format; + frmival.width = framesize->discrete.width; + frmival.height = framesize->discrete.height; + //frmival.type = V4L2_FRMIVAL_TYPE_DISCRETE; + frmival.index = 0; + //yang_trace("the frame intervals enum"); + + while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) == 0) { + //输出分数,即帧间隔 + //if(frmival.width==m_para->width) { + yang_trace("%d.frameinterval:%u/%u\n ", frmival.index, + frmival.discrete.numerator, frmival.discrete.denominator); + //} + frmival.index++; + } + //yang_trace(".........................................\n"); + return 0; +} + +#endif diff --git a/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.h b/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.h new file mode 100644 index 0000000000000000000000000000000000000000..0abe06ef4cec805538193550a9aa9e98f6754350 --- /dev/null +++ b/libyangrtc2/src/yangcapture/YangVideoDeviceQuery.h @@ -0,0 +1,15 @@ +#ifndef YANGCAPTURE_SRC_YANGVIDEODEVICEQUERY_H_ +#define YANGCAPTURE_SRC_YANGVIDEODEVICEQUERY_H_ +#include +#include +#include +using namespace std; +class YangVideoDeviceQuery { +public: + YangVideoDeviceQuery(); + virtual ~YangVideoDeviceQuery(); + int32_t getVideoDeviceList(); + int32_t enum_camera_frmival(int32_t fd, struct v4l2_frmsizeenum *framesize); +}; + +#endif /* YANGCAPTURE_SRC_YANGVIDEODEVICEQUERY_H_ */ diff --git a/libyangrtc2/src/yangcapture/win/YangVideoSrc.cpp b/libyangrtc2/src/yangcapture/win/YangVideoSrc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..695bb5df9f9ab44007a101b03c7bd0888501066f --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangVideoSrc.cpp @@ -0,0 +1,412 @@ +// +// +#ifdef __WIN321__ +#include "YangVideoSrc.h" +#include +#include +#include +#include +#define CheckPointer(p,ret) {if((p)==0) return (ret);} + #define ValidateReadWritePtr(p,cb) \ + {ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)} +//DEFINE_GUID(MEDIASUBTYPE_I420, 0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); +DEFINE_GUID(CLSID_YangVideoSrcFilter, 0xa5532f97, 0x46a2, 0x48ad, 0xab, 0x23, + 0xfd, 0x96, 0xb7, 0xbd, 0x86, 0xa3); +YangVideoSrc::YangVideoSrc() +{ + m_clsid=CLSID_YangVideoSrcFilter; + m_pName=new char[64]; + m_iPins=1; + m_stream=new CSourceStream(); +} +YangVideoSrc::~YangVideoSrc(){ + delete[] m_pName; + m_pName=0; +} + +HRESULT STDMETHODCALLTYPE YangVideoSrc::EnumPins(IEnumPins **ppEnum){ + CheckPointer(ppEnum,E_POINTER); + // ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *)); + + /* Create a new ref counted enumerator */ + + *ppEnum = new CEnumPins(this, NULL); + + return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR; +} +#define VFW_E_NOT_FOUND ((HRESULT)0x80040216L) + HRESULT STDMETHODCALLTYPE YangVideoSrc::FindPin(LPCWSTR Id, IPin **ppPin){ + CheckPointer(ppPin,E_POINTER); + *ppPin = m_stream; + m_stream->AddRef(); + return S_OK; + //return VFW_E_NOT_FOUND; + } + + HRESULT STDMETHODCALLTYPE YangVideoSrc::QueryFilterInfo(FILTER_INFO *pInfo){ + CheckPointer(pInfo,E_POINTER); + // ValidateReadWritePtr(pInfo,sizeof(FILTER_INFO)); + + if (m_pName) { + memcpy(pInfo->achName, m_pName,strlen(m_pName)); + } else { + pInfo->achName[0] = L'\0'; + } + pInfo->pGraph = m_pGraph; + if (m_pGraph) + m_pGraph->AddRef(); + return NOERROR; + } + + HRESULT STDMETHODCALLTYPE YangVideoSrc::JoinFilterGraph(IFilterGraph *pGraph, + LPCWSTR pName){ + + m_pGraph = pGraph; + if (m_pGraph) { + HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEventSink, + (void**) &m_pSink); + m_pSink->Release(); // we do NOT keep a reference on it. + } else { + // if graph pointer is null, then we should + // also release the IMediaEventSink on the same object - we don't + // refcount it, so just set it to null + m_pSink = NULL; + } + + + if (m_pName) { + delete[] m_pName; + m_pName = NULL; + } + + if (pName) { + DWORD nameLen = lstrlenW(pName)+1; + m_pName = new WCHAR[nameLen]; + if (m_pName) { + CopyMemory(m_pName, pName, nameLen*sizeof(WCHAR)); + } + } + + + return NOERROR; + + } + STDMETHODIMP + YangVideoSrc::GetClassID(CLSID *pClsID) + { + CheckPointer(pClsID,E_POINTER); + // ValidateReadWritePtr(pClsID,sizeof(CLSID)); + *pClsID = m_clsid; + return NOERROR; + } + + HRESULT STDMETHODCALLTYPE YangVideoSrc::QueryVendorInfo(LPWSTR *pVendorInfo){ + UNREFERENCED_PARAMETER(pVendorInfo); + return E_NOTIMPL; + } + + /* This is called after a media type has been proposed + + Try to complete the connection by agreeing the allocator + */ + HRESULT + CSourceStream::CompleteConnect(IPin *pReceivePin) + { + UNREFERENCED_PARAMETER(pReceivePin); + return DecideAllocator(m_pInputPin, &m_pAllocator); + } + + HRESULT + CSourceStream::CheckConnect(IPin * pPin) + { + /* Check that pin directions DONT match */ + + PIN_DIRECTION pd; + pPin->QueryDirection(&pd); + + // ASSERT((pd == PINDIR_OUTPUT) || (pd == PINDIR_INPUT)); + // ASSERT((m_dir == PINDIR_OUTPUT) || (m_dir == PINDIR_INPUT)); + + // we should allow for non-input and non-output connections? + if (pd == m_dir) { + return VFW_E_INVALID_DIRECTION; + } + return NOERROR; + } + /* This method is called when the output pin is about to try and connect to + an input pin. It is at this point32_t that you should try and grab any extra + interfaces that you need, in this case IMemInputPin. Because this is + only called if we are not currently connected we do NOT need to call + BreakConnect. This also makes it easier to derive classes from us as + BreakConnect is only called when we actually have to break a connection + (or a partly made connection) and not when we are checking a connection */ + + /* Overriden from CBasePin */ + + HRESULT + CSourceStream::CheckConnect(IPin * pPin) + { + HRESULT hr = CBasePin::CheckConnect(pPin); + if (FAILED(hr)) { + return hr; + } + + // get an input pin and an allocator interface + hr = pPin->QueryInterface(IID_IMemInputPin, (void **) &m_pInputPin); + if (FAILED(hr)) { + return hr; + } + return NOERROR; + } + + + /* Overriden from CBasePin */ + + HRESULT + CSourceStream::BreakConnect() + { + /* Release any allocator we hold */ + + if (m_pAllocator) { + // Always decommit the allocator because a downstream filter may or + // may not decommit the connection's allocator. A memory leak could + // occur if the allocator is not decommited when a connection is broken. + HRESULT hr = m_pAllocator->Decommit(); + if( FAILED( hr ) ) { + return hr; + } + + m_pAllocator->Release(); + m_pAllocator = NULL; + } + + /* Release any input pin interface we hold */ + + if (m_pInputPin) { + m_pInputPin->Release(); + m_pInputPin = NULL; + } + return NOERROR; + } + + + /* This is called when the input pin didn't give us a valid allocator */ + + HRESULT + CSourceStream::InitAllocator(IMemAllocator **ppAlloc) + { + return CreateMemoryAllocator(ppAlloc); + } + + + /* Decide on an allocator, override this if you want to use your own allocator + Override DecideBufferSize to call SetProperties. If the input pin fails + the GetAllocator call then this will construct a CMemAllocator and call + DecideBufferSize on that, and if that fails then we are completely hosed. + If the you succeed the DecideBufferSize call, we will notify the input + pin of the selected allocator. NOTE this is called during Connect() which + therefore looks after grabbing and locking the object's critical section */ + + // We query the input pin for its requested properties and pass this to + // DecideBufferSize to allow it to fulfill requests that it is happy + // with (eg most people don't care about alignment and are thus happy to + // use the downstream pin's alignment request). + + HRESULT + CSourceStream::DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc) + { + HRESULT hr = NOERROR; + *ppAlloc = NULL; + + // get downstream prop request + // the derived class may modify this in DecideBufferSize, but + // we assume that he will consistently modify it the same way, + // so we only get it once + ALLOCATOR_PROPERTIES prop; + ZeroMemory(&prop, sizeof(prop)); + + // whatever he returns, we assume prop is either all zeros + // or he has filled it out. + pPin->GetAllocatorRequirements(&prop); + + // if he doesn't care about alignment, then set it to 1 + if (prop.cbAlign == 0) { + prop.cbAlign = 1; + } + + /* Try the allocator provided by the input pin */ + + hr = pPin->GetAllocator(ppAlloc); + if (SUCCEEDED(hr)) { + + hr = DecideBufferSize(*ppAlloc, &prop); + if (SUCCEEDED(hr)) { + hr = pPin->NotifyAllocator(*ppAlloc, FALSE); + if (SUCCEEDED(hr)) { + return NOERROR; + } + } + } + + /* If the GetAllocator failed we may not have an interface */ + + if (*ppAlloc) { + (*ppAlloc)->Release(); + *ppAlloc = NULL; + } + + /* Try the output pin's allocator by the same method */ + + hr = InitAllocator(ppAlloc); + if (SUCCEEDED(hr)) { + + // note - the properties passed here are in the same + // structure as above and may have been modified by + // the previous call to DecideBufferSize + hr = DecideBufferSize(*ppAlloc, &prop); + if (SUCCEEDED(hr)) { + hr = pPin->NotifyAllocator(*ppAlloc, FALSE); + if (SUCCEEDED(hr)) { + return NOERROR; + } + } + } + + /* Likewise we may not have an interface to release */ + + if (*ppAlloc) { + (*ppAlloc)->Release(); + *ppAlloc = NULL; + } + return hr; + } + + + /* This returns an empty sample buffer from the allocator WARNING the same + dangers and restrictions apply here as described below for Deliver() */ + + HRESULT + CSourceStream::GetDeliveryBuffer(IMediaSample ** ppSample, + REFERENCE_TIME * pStartTime, + REFERENCE_TIME * pEndTime, + DWORD dwFlags) + { + if (m_pAllocator != NULL) { + return m_pAllocator->GetBuffer(ppSample,pStartTime,pEndTime,dwFlags); + } else { + return E_NOINTERFACE; + } + } + + + + + HRESULT + CSourceStream::Deliver(IMediaSample * pSample) + { + if (m_pInputPin == NULL) { + return VFW_E_NOT_CONNECTED; + } + + + return m_pInputPin->Receive(pSample); + } + + + // called from elsewhere in our filter to pass EOS downstream to + // our connected input pin + HRESULT + CSourceStream::DeliverEndOfStream(void) + { + // remember this is on IPin not IMemInputPin + if (m_Connected == NULL) { + return VFW_E_NOT_CONNECTED; + } + return m_Connected->EndOfStream(); + } + + + /* Commit the allocator's memory, this is called through IMediaFilter + which is responsible for locking the object before calling us */ + + HRESULT + CSourceStream::Active(void) + { + if (m_pAllocator == NULL) { + return VFW_E_NO_ALLOCATOR; + } + return m_pAllocator->Commit(); + } + + + /* Free up or unprepare allocator's memory, this is called through + IMediaFilter which is responsible for locking the object first */ + + HRESULT + CSourceStream::Inactive(void) + { + m_bRunTimeError = FALSE; + if (m_pAllocator == NULL) { + return VFW_E_NO_ALLOCATOR; + } + return m_pAllocator->Decommit(); + } + + // we have a default handling of EndOfStream which is to return + // an error, since this should be called on input pins only + STDMETHODIMP + CSourceStream::EndOfStream(void) + { + return E_UNEXPECTED; + } + + + // BeginFlush should be called on input pins only + STDMETHODIMP + CSourceStream::BeginFlush(void) + { + return E_UNEXPECTED; + } + + // EndFlush should be called on input pins only + STDMETHODIMP + CSourceStream::EndFlush(void) + { + return E_UNEXPECTED; + } + + // call BeginFlush on the connected input pin + HRESULT + CSourceStream::DeliverBeginFlush(void) + { + // remember this is on IPin not IMemInputPin + if (m_Connected == NULL) { + return VFW_E_NOT_CONNECTED; + } + return m_Connected->BeginFlush(); + } + + // call EndFlush on the connected input pin + HRESULT + CSourceStream::DeliverEndFlush(void) + { + // remember this is on IPin not IMemInputPin + if (m_Connected == NULL) { + return VFW_E_NOT_CONNECTED; + } + return m_Connected->EndFlush(); + } + // deliver NewSegment to connected pin + HRESULT + CSourceStream::DeliverNewSegment( + REFERENCE_TIME tStart, + REFERENCE_TIME tStop, + double dRate) + { + if (m_Connected == NULL) { + return VFW_E_NOT_CONNECTED; + } + return m_Connected->NewSegment(tStart, tStop, dRate); + } + +#endif diff --git a/libyangrtc2/src/yangcapture/win/YangVideoSrc.h b/libyangrtc2/src/yangcapture/win/YangVideoSrc.h new file mode 100644 index 0000000000000000000000000000000000000000..71dc6676f45081e14318bbd920dd462cb10c7737 --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangVideoSrc.h @@ -0,0 +1,219 @@ +#ifndef Yang_YangVideoSrc_H1 +#define Yang_YangVideoSrc_H1 +#ifdef __WIN321__ +#include +#include "amstream.h" +#include +#include "qedit.h" + +#include +#include +#include + +class CSourceStream; + +class YangVideoSrc: public IBaseFilter { +public: + + YangVideoSrc(); + virtual ~YangVideoSrc(); +//ibasefilter + HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum); + + HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin); + + HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo); + + HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, + LPCWSTR pName); + + HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo); +// + STDMETHODIMP GetClassID(CLSID *pClsID); + + + +protected: + CLSID m_clsid; + IFilterGraph *m_pGraph; + IMediaEventSink *m_pSink; + LONG m_PinVersion; + int32_t m_iPins; // The number of pins on this filter. Updated by CSourceStream + CSourceStream *m_stream; + char *m_pName; +}; + +// +// CSourceStream +// +// Use this class to manage a stream of data that comes from a +// pin. +// Uses a worker thread to put data on the pin. +class CSourceStream: public IPin,public IUnknown { +public: + + CSourceStream(); + virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too. + +protected: + + YangVideoSrc *m_pFilter; // The parent of this stream + + // * + // * Data Source + // * + // * The following three functions: FillBuffer, OnThreadCreate/Destroy, are + // * called from within the ThreadProc. They are used in the creation of + // * the media samples this pin will provide + // * + + // Override this to provide the worker thread a means + // of processing a buffer + virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE; + + // Called as the thread is created/destroyed - use to perform + // jobs such as start/stop streaming mode + // If OnThreadCreate returns an error the thread will exit. + virtual HRESULT OnThreadCreate(void) { + return NOERROR; + } + ; + virtual HRESULT OnThreadDestroy(void) { + return NOERROR; + } + ; + virtual HRESULT OnThreadStartPlay(void) { + return NOERROR; + } + ; + + // * + // * Worker Thread + // * + + HRESULT Active(void); // Starts up the worker thread + HRESULT Inactive(void); // Exits the worker thread. + + + IMemAllocator *m_pAllocator; + IMemInputPin *m_pInputPin; + IPin *m_Connected; // Pin we have connected to + PIN_DIRECTION m_dir; + bool m_bRunTimeError; // Run time error generated + bool m_bCanReconnectWhenActive; // OK to reconnect when active + bool m_bTryMyTypesFirst; // When connecting enumerate + +public: + // thread commands + enum Command { + CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT + }; + HRESULT Init(void) { + return CallWorker(CMD_INIT); + } + HRESULT Exit(void) { + return CallWorker(CMD_EXIT); + } + HRESULT Run(void) { + return CallWorker(CMD_RUN); + } + HRESULT Pause(void) { + return CallWorker(CMD_PAUSE); + } + HRESULT Stop(void) { + return CallWorker(CMD_STOP); + } + + + + HRESULT STDMETHODCALLTYPE Connect( + IPin *pReceivePin, + const AM_MEDIA_TYPE *pmt) ; + + HRESULT STDMETHODCALLTYPE ReceiveConnection( + IPin *pConnector, + const AM_MEDIA_TYPE *pmt) ; + + HRESULT STDMETHODCALLTYPE Disconnect( + ) ; + + HRESULT STDMETHODCALLTYPE ConnectedTo( + IPin **pPin) ; + + HRESULT STDMETHODCALLTYPE ConnectionMediaType( + AM_MEDIA_TYPE *pmt) ; + + HRESULT STDMETHODCALLTYPE Querypcontextnfo( + PIN_INFO *pInfo); + + HRESULT STDMETHODCALLTYPE QueryDirection( + PIN_DIRECTION *pPinDir) ; + + HRESULT STDMETHODCALLTYPE QueryId( + LPWSTR *Id) ; + + HRESULT STDMETHODCALLTYPE QueryAccept( + const AM_MEDIA_TYPE *pmt) ; + + HRESULT STDMETHODCALLTYPE EnumMediaTypes( + IEnumMediaTypes **ppEnum) ; + + HRESULT STDMETHODCALLTYPE QueryInternalConnections( + IPin **apPin, + ULONG *nPin) ; + + HRESULT STDMETHODCALLTYPE EndOfStream( + ) ; + + HRESULT STDMETHODCALLTYPE BeginFlush( + ); + + HRESULT STDMETHODCALLTYPE EndFlush( + ) ; + + HRESULT STDMETHODCALLTYPE NewSegment( + REFERENCE_TIME tStart, + REFERENCE_TIME tStop, + double dRate); + + HRESULT InitAllocator(IMemAllocator **ppAlloc); + HRESULT CheckConnect(IPin *pPin); + HRESULT BreakConnect(); + + HRESULT CompleteConnect(IPin *pReceivePin); + HRESULT DeliverEndOfStream(void); + + +protected: + Command GetRequest(void) { + return (Command) CAMThread::GetRequest(); + } + BOOL CheckRequest(Command *pCom) { + return CAMThread::CheckRequest((DWORD*) pCom); + } + + // override these if you want to add thread commands + virtual DWORD ThreadProc(void); // the thread function + + virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running + + // * + // * AM_MEDIA_TYPE support + // * + + // If you support more than one media type then override these 2 functions + virtual HRESULT CheckMediaType(const CMediaType *pMediaType); + virtual HRESULT GetMediaType(int32_t iPosition, CMediaType *pMediaType); // List pos. 0-n + + // If you support only one type then override this fn. + // This will only be called by the default implementations + // of CheckMediaType and GetMediaType(int, CMediaType*) + // You must override this fn. or the above 2! + virtual HRESULT GetMediaType(CMediaType *pMediaType) { + return E_UNEXPECTED; + } + + STDMETHODIMP QueryId(LPWSTR *Id); +}; +#endif +#endif diff --git a/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.cpp b/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e34fc0a1badbc4d3adb81aa71d18a918057a6279 --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.cpp @@ -0,0 +1,424 @@ +/* + * YangLivingVideoCaptureWinImpl.cpp + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#include "YangWinVideoCapture.h" + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include + +#include "yangutil/sys/YangLog.h" +#define yang_release(x) { if (x) x->Release(); x = NULL; } +//HRESULT WINAPI CopyMediaType( AM_MEDIA_TYPE *pmtTarget, + // const AM_MEDIA_TYPE *pmtSource +//); + + +#include + +HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource) +{ + + *pmtTarget = *pmtSource; + if (pmtSource->cbFormat != 0) { + // ASSERT(pmtSource->pbFormat != NULL); + pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat); + if (pmtTarget->pbFormat == NULL) { + pmtTarget->cbFormat = 0; + return E_OUTOFMEMORY; + } else { + CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat, + pmtTarget->cbFormat); + } + } + if (pmtTarget->pUnk != NULL) { + pmtTarget->pUnk->AddRef(); + } + + return S_OK; +} + +YangWinVideoCapture::YangWinVideoCapture(YangVideoInfo *pcontext) { + m_para = pcontext; + + m_vhandle = new YangWinVideoCaptureHandle(pcontext); + cameraIndex = pcontext->vIndex; + m_width = m_para->width; + m_height = m_para->height; + m_vd_id = 0; + + m_isloop = 0; + m_isFirstFrame = 0; + m_buffer_count = 0; + m_timestatmp = 0; + m_pg = NULL; + m_pb = NULL; + m_pm = NULL; + m_videoSrc = NULL; + m_grabberF=NULL; + m_grabber=NULL; + m_event = NULL; + //m_moniker = NULL; + m_nullRender=NULL; + m_t_time=0; + //m_gid=MEDIASUBTYPE_I420; + //videoRender1 = NULL; + + //vcs=new VideoSampleCapture(&config); + + cameraIndex = 1; + hasVideo = 1; + m_preframe = 12; + //m_fx=conf->fx; + m_isOpAddMinus = 0; + memset(&m_yuy2,0,sizeof(m_yuy2)); + memset(&m_i420,0,sizeof(m_i420)); + memset(&m_nv12,0,sizeof(m_nv12)); + memset(&m_yv12,0,sizeof(m_yv12)); + memset(&m_p010,0,sizeof(m_p010)); + memset(&m_p016,0,sizeof(m_p016)); + m_yuy2.yuvType = YangYuy2; + m_i420.yuvType = YangI420; + m_nv12.yuvType = YangNv12; + m_yv12.yuvType = YangYv12; + m_p010.yuvType=YangP010; + m_p016.yuvType=YangP016; + + +} + +YangWinVideoCapture::~YangWinVideoCapture() { + if (m_isloop) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + yang_release(m_grabber); + yang_release(m_grabberF); + + yang_release( m_event); + yang_release( m_pm); + yang_release( m_pg); + yang_release( m_pb); + yang_release( m_videoSrc); + delete m_vhandle; + m_vhandle = NULL; + + +} + +int32_t YangWinVideoCapture::getVideoCaptureState() { + return m_vhandle->m_isCapture; +} +int32_t YangWinVideoCapture::getLivingVideoCaptureState() { + return m_vhandle->m_isLivingCaptrue; +} +int32_t YangWinVideoCapture::getFilmVideoCaptureState() { + return m_vhandle->m_isFilm; +} + +void YangWinVideoCapture::setVideoCaptureStart() { + m_vhandle->m_isCapture = 1; +} +void YangWinVideoCapture::setVideoCaptureStop() { + m_vhandle->m_isCapture = 0; +} +void YangWinVideoCapture::setLivingVideoCaptureStart() { + m_vhandle->m_isLivingCaptrue = 1; +} +void YangWinVideoCapture::setLivingVideoCaptureStop() { + m_vhandle->m_isLivingCaptrue = 0; +} + +void YangWinVideoCapture::setFilmVideoCaptureStart() { + m_vhandle->m_isFilm = 1; +} +void YangWinVideoCapture::setFilmVideoCaptureStop() { + m_vhandle->m_isFilm = 0; +} + +void YangWinVideoCapture::setOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setVideoBuffer(pbuf); +} +void YangWinVideoCapture::setLivingOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setLivingVideoBuffer(pbuf); +} +void YangWinVideoCapture::setFilmOutVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setFilmVideoBuffer(pbuf); +} +void YangWinVideoCapture::setPreVideoBuffer(YangVideoBuffer *pbuf) { + m_vhandle->setPreVideoBuffer(pbuf); +} +void YangWinVideoCapture::initstamp() { + m_vhandle->initstamp(); +} +int32_t YangWinVideoCapture::init() { + CoInitialize(NULL); + + ICreateDevEnum *devEnum = NULL; + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&devEnum)); + + //if (SUCCEEDED(hr)) { + // printf("suncess!"); + //} else { + // printf("fail"); + //} + IEnumMoniker *classEnum = NULL; + + ULONG cFetched; + IMoniker *moniker=NULL; + int32_t cco = 0; + devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &classEnum,0); + while (classEnum->Next(1, &moniker, &cFetched) == S_OK) { + cco++; + if (cco != cameraIndex) + continue; + moniker->BindToObject(0, 0, IID_IBaseFilter, (void**) &m_videoSrc); + yang_release(moniker); + break; + } + yang_release(classEnum); + yang_release(devEnum); + + if (m_videoSrc == NULL) + return ERROR_SYS_Win_VideoDeveceOpenFailure; + + CoCreateInstance(CLSID_CaptureGraphBuilder2, 0, CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2, (void**) &m_pb); + CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**) &m_pg); + m_pb->SetFiltergraph(m_pg); + m_pg->QueryInterface(IID_IMediaControl, (void**) &m_pm); + m_pg->AddFilter(m_videoSrc, L"mp4"); + CLSID CLSID_NullRenderer1 = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + CLSID CLSID_SampleGrabber1 = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + hr=CoCreateInstance(CLSID_SampleGrabber1, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&m_grabberF)); + hr = m_pg->AddFilter(m_grabberF, L"Sample Grabber"); + + hr = m_grabberF->QueryInterface(IID_ISampleGrabber,(void **)&m_grabber); + hr=m_pg->QueryInterface(IID_IMediaEventEx,(void **)&m_event); + + m_nullRender=NULL; + hr=CoCreateInstance(CLSID_NullRenderer1, NULL, CLSCTX_INPROC, IID_IBaseFilter,(void **)&m_nullRender); + + setRevolutionPara(); + + //m_yuy2, m_i420 , m_nv12, m_yv12 + if(m_i420.state>1||m_nv12.state>1||m_yv12.state>1||m_yuy2.state>1){ + if(m_i420.state>1) { + m_para->videoCaptureFormat=YangI420; + }else if(m_nv12.state>1){ + m_para->videoCaptureFormat=YangNv12; + }else if(m_yv12.state>1){ + m_para->videoCaptureFormat=YangYv12; + }else if(m_yuy2.state>1){ + m_para->videoCaptureFormat=YangYuy2; + } + #if Yang10bit + if(m_para->videoCaptureFormat==YangP010) format=V4L2_PIX_FMT_P010; + if(m_para->videoCaptureFormat==YangP016) format=V4L2_PIX_FMT_P016; + #endif + + }else if(m_i420.state||m_nv12.state||m_yv12.state||m_yuy2.state){ + if(m_i420.state) { + setWH(&m_i420); + }else if(m_nv12.state){ + setWH(&m_nv12); + }else if(m_yv12.state){ + setWH(&m_yv12); + }else if(m_yuy2.state){ + setWH(&m_yuy2); + } + //setReselution(format); + }else{ + return ERROR_SYS_Win_NoVideoDriver; + } + + setRevolution(); + // if(1) return 0; + if(m_vhandle) m_vhandle->setCaptureFormat(m_para->videoCaptureFormat); + return Yang_Ok; +} + +IPin* YangWinVideoCapture::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir) { + IEnumPins *pEnumPins; + IPin *pOutpin; + PIN_DIRECTION pDir; + pFilter->EnumPins(&pEnumPins); + while (pEnumPins->Next(1, &pOutpin, NULL) == S_OK) { + pOutpin->QueryDirection(&pDir); + + if (pDir == dir) { + yang_release(pEnumPins); + return pOutpin; + } + } + return 0; +} +REFGUID YangWinVideoCapture::getUID(){ + YangYuvType format=(YangYuvType)m_para->videoCaptureFormat; + if(format==YangYuy2) return MEDIASUBTYPE_YUY2; + if(format==YangI420) return MEDIASUBTYPE_I420; + if(format==YangNv12) return MEDIASUBTYPE_NV12; + if(format==YangYv12) return MEDIASUBTYPE_YV12; + return MEDIASUBTYPE_I420; + +} +void YangWinVideoCapture::setRevolutionPara() { + IAMStreamConfig *config1 = 0; + m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_videoSrc, + IID_IAMStreamConfig, (void**) &config1); + int32_t iCount = 0, iSize = 0; + HRESULT hr = config1->GetNumberOfCapabilities(&iCount, &iSize); + + + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + for (int32_t iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + + hr = config1->GetStreamCaps(iFormat, &pmtConfig, (BYTE*) &scc); + VIDEOINFOHEADER* pvih1=(VIDEOINFOHEADER*)pmtConfig->pbFormat; + + if(IsEqualGUID(pmtConfig->subtype, MEDIASUBTYPE_I420)){ + if(!m_i420.state) m_i420.state=1; + if(pvih1->bmiHeader.biWidth==m_para->width&&pvih1->bmiHeader.biHeight==m_para->height) m_i420.state=2; + m_i420.width=pvih1->bmiHeader.biWidth; + m_i420.height=pvih1->bmiHeader.biHeight; + }else if(IsEqualGUID(pmtConfig->subtype, MEDIASUBTYPE_NV12)){ + if(!m_nv12.state) m_nv12.state=1; + if(pvih1->bmiHeader.biWidth==m_para->width&&pvih1->bmiHeader.biHeight==m_para->height) m_nv12.state=2; + m_nv12.width=pvih1->bmiHeader.biWidth; + m_nv12.height=pvih1->bmiHeader.biHeight; + }else if(IsEqualGUID(pmtConfig->subtype, MEDIASUBTYPE_YV12)){ + if(!m_yv12.state) m_yv12.state=1; + if(pvih1->bmiHeader.biWidth==m_para->width&&pvih1->bmiHeader.biHeight==m_para->height) m_yv12.state=2; + m_yv12.width=pvih1->bmiHeader.biWidth; + m_yv12.height=pvih1->bmiHeader.biHeight; + }else if(IsEqualGUID(pmtConfig->subtype, MEDIASUBTYPE_YUY2)){ + if(!m_yuy2.state) m_yuy2.state=1; + if(pvih1->bmiHeader.biWidth==m_para->width&&pvih1->bmiHeader.biHeight==m_para->height) m_yuy2.state=2; + m_yuy2.width=pvih1->bmiHeader.biWidth; + m_yuy2.height=pvih1->bmiHeader.biHeight; + } + pvih1=NULL; + } + } +} +void YangWinVideoCapture::setRevolution() { + IAMStreamConfig *config1 = 0; + + m_pb->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_videoSrc,IID_IAMStreamConfig, (void**) &config1); + int32_t iCount = 0, iSize = 0; + HRESULT hr = config1->GetNumberOfCapabilities(&iCount, &iSize); +//printf("***********start setRevolution*******************\n"); +// Check the size to make sure we pass in the correct structure. + YangYuvType format=(YangYuvType)m_para->videoCaptureFormat; + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + // Use the video capabilities structure. + + for (int32_t iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + AM_MEDIA_TYPE amt; + hr = config1->GetStreamCaps(iFormat, &pmtConfig, (BYTE*) &scc); + VIDEOINFOHEADER* pvih1=(VIDEOINFOHEADER*)pmtConfig->pbFormat; + + if (IsEqualGUID(pmtConfig->subtype,getUID())&&pvih1->bmiHeader.biWidth==m_para->width&&pvih1->bmiHeader.biHeight==m_para->height) { + + CopyMediaType(&amt, pmtConfig); + VIDEOINFOHEADER *pvih = (VIDEOINFOHEADER*) amt.pbFormat; + BITMAPINFOHEADER bmi = pvih->bmiHeader; + pvih->bmiHeader.biWidth = m_para->width; + pvih->bmiHeader.biHeight = m_para->height; + pvih->bmiHeader.biBitCount = format==YangYuy2?16:12;//config.Video_Bit_Count; + pvih->bmiHeader.biSizeImage = pvih->bmiHeader.biWidth + * pvih->bmiHeader.biHeight + * pvih->bmiHeader.biBitCount / 8; + yang_info("\nset %d Camera Revolution Sucess!width=%d,height=%d..\n",cameraIndex,m_para->width,m_para->height); + config1->SetFormat(&amt); + pvih = NULL; + //break; + return; + + + } + pvih1=NULL; + } + // + } + //} + //printf("\nCamera %d Error Error!.yuy2 or Nv12 not exists............\n",cameraIndex); + //ExitProcess(0); + +} + + +void YangWinVideoCapture::stopLoop() { + m_isloop = 0; + if(m_pm!=NULL) m_pm->Stop(); +} +void YangWinVideoCapture::setWH(YangVideoCaptureType *pct){ + m_width=pct->width; + m_height=pct->height; + m_para->width=pct->width; + m_para->height=pct->height; + m_para->videoCaptureFormat=pct->yuvType; +} +void YangWinVideoCapture::startLoop() { + if (m_videoSrc == NULL) + return; +/** + DWORD taskIndex(0); + HANDLE hMmTask = AvSetMmThreadCharacteristicsA("Capture", &taskIndex); + if (hMmTask) { + if (FALSE == AvSetMmThreadPriority(hMmTask, AVRT_PRIORITY_CRITICAL)) { + yang_warn( "failed to boost videoCapture-thread using MMCSS"); + } + yang_trace("videoCapture thread is now registered with MMCSS (taskIndex=%d)", + taskIndex ); + } else { + yang_error( "failed to enable MMCSS on videoCapture thread (err=%lu", GetLastError() ); + + } +**/ + IPin *pVideoOut = FindPin(m_videoSrc, PINDIR_OUTPUT); + IPin *pGrabin = FindPin(m_grabberF, PINDIR_INPUT); + IPin *pGrabout = FindPin(m_grabberF, PINDIR_OUTPUT); + IPin *pNullIn = FindPin(m_nullRender, PINDIR_INPUT); + HRESULT hr = m_pg->Connect(pVideoOut, pGrabin); + hr = m_pg->Connect(pGrabout, pNullIn); + yang_release(pVideoOut); + yang_release(pGrabin); + yang_release(pGrabout); + yang_release(pNullIn); + hr = m_grabber->SetBufferSamples(TRUE); + hr = m_grabber->SetOneShot(FALSE); + m_grabber->SetCallback(m_vhandle, 1); + m_pm->Run(); + long eventCode; + m_event->WaitForCompletion(INFINITE, &eventCode); +} +#endif diff --git a/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.h b/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.h new file mode 100644 index 0000000000000000000000000000000000000000..00c7dcedbabca548fbb8178727dddec8a488cdfb --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangWinVideoCapture.h @@ -0,0 +1,93 @@ +/* + * YangLivingVideoCaptureWinImpl.h + * + * Created on: 2020年8月30日 + * Author: yang + */ + +#ifndef YANGCAPTURE_SRC_YangLivingVideoCaptureWinImpl_H_ +#define YANGCAPTURE_SRC_YangLivingVideoCaptureWinImpl_H_ + +#ifdef _WIN32 + +#include +#include +#include "amstream.h" +#include +#include "qedit.h" + +#include +#include +#include +#include "YangWinVideoCaptureHandle.h" + +struct YangVideoCaptureType{ + YangYuvType yuvType; + int32_t state; + int32_t width; + int32_t height; +}; +class YangWinVideoCapture: public YangMultiVideoCapture { +public: + YangWinVideoCapture(YangVideoInfo *pcontext); + virtual ~YangWinVideoCapture(); + YangWinVideoCaptureHandle *m_vhandle; + int32_t init(); + void setVideoCaptureStart(); + void setVideoCaptureStop(); + int32_t getVideoCaptureState(); + int32_t getLivingVideoCaptureState(); + int32_t getFilmVideoCaptureState(); + + void setLivingOutVideoBuffer(YangVideoBuffer *pbuf); + void setLivingVideoCaptureStart(); + void setLivingVideoCaptureStop(); + + void setFilmOutVideoBuffer(YangVideoBuffer *pbuf); + void setFilmVideoCaptureStart(); + void setFilmVideoCaptureStop(); + + void setOutVideoBuffer(YangVideoBuffer *pbuf); + void setPreVideoBuffer(YangVideoBuffer *pbuf); + + void initstamp(); + void stopLoop(); + +protected: + void startLoop(); + //long m_difftime(struct timeval *p_start, struct timeval *p_end); + + void setRevolutionPara(); + void setRevolution(); + IPin* FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir); + IPin* GetOutPin(IBaseFilter *pFilter, PIN_DIRECTION pin_dir, int32_t nPin); + IPin* GetInPin(IBaseFilter *pFilter, PIN_DIRECTION pin_dir, int32_t nPin); + + IMediaControl *m_pm; + IGraphBuilder *m_pg; + ICaptureGraphBuilder2 *m_pb; + IBaseFilter *m_videoSrc, *m_grabberF; + ISampleGrabber *m_grabber; + IBaseFilter *m_nullRender; + //IMoniker *m_moniker; + IMediaEventEx *m_event; +private: + void setWH(YangVideoCaptureType *pct); + REFGUID getUID(); + + YangVideoCaptureType m_yuy2, m_i420 , m_nv12, m_yv12, m_p010,m_p016; + int32_t m_width, m_height; + int32_t m_vd_id; + int32_t cameraIndex; + int32_t hasVideo; + int32_t m_preframe, m_isOpAddMinus; + ULONG m_t_time; + int32_t m_buffer_count; + int32_t m_isloop; + int32_t m_isFirstFrame; + //struct timeval m_startTime; + long m_timestatmp; + +}; +#endif +#endif /* YANGCAPTURE_SRC_YangLivingVideoCaptureWinImpl_H_ */ diff --git a/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.cpp b/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdb125f6731da6cf42dd1edf87db1fa1fc01ce56 --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.cpp @@ -0,0 +1,53 @@ +#include "YangWinVideoCaptureHandle.h" +#ifdef _WIN32 + +#include "time.h" +#include "stdlib.h" +#include "stdio.h" +#include +//using namespace std; + +YangWinVideoCaptureHandle::YangWinVideoCaptureHandle(YangVideoInfo *pcontext):YangVideoCaptureHandle(pcontext) +{ + +} +YangWinVideoCaptureHandle:: ~YangWinVideoCaptureHandle(void){ + +} +STDMETHODIMP_(ULONG) YangWinVideoCaptureHandle::AddRef() { + return 1; +} +STDMETHODIMP_(ULONG) YangWinVideoCaptureHandle::Release() { + return 2; +} + +STDMETHODIMP YangWinVideoCaptureHandle::QueryInterface(REFIID riid, + void **ppvObject) { + // printf("*********************************\n"); + if (NULL == ppvObject) + return E_POINTER; + if (riid == __uuidof(IUnknown)) { + *ppvObject = static_cast(this); + return S_OK; + } + if (riid == IID_ISampleGrabber) { + *ppvObject = static_cast(this); + return S_OK; + } + return E_NOTIMPL; +} + +STDMETHODIMP YangWinVideoCaptureHandle::SampleCB(double Time, + IMediaSample *pSample) { + + return E_NOTIMPL; +} + +STDMETHODIMP YangWinVideoCaptureHandle::BufferCB(double Time, BYTE *pBuffer, + long BufferLen) { + + putBuffer(Time*1000000, pBuffer, BufferLen); + return E_NOTIMPL; +} + +#endif diff --git a/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.h b/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..cd5bfe94e9d1de9e79853d5be7c61e6d7d3ae1fe --- /dev/null +++ b/libyangrtc2/src/yangcapture/win/YangWinVideoCaptureHandle.h @@ -0,0 +1,24 @@ +#ifndef __YangWinVideoCaptureHandle__ +#define __YangWinVideoCaptureHandle__ +#ifdef _WIN32 +#include "qedit.h" +//#include +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangIni.h" +#include "../YangVideoCaptureHandle.h" +class YangWinVideoCaptureHandle: public ISampleGrabberCB, + public YangVideoCaptureHandle { +public: + YangWinVideoCaptureHandle(YangVideoInfo *pcontext); + virtual ~YangWinVideoCaptureHandle(void); + + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); + STDMETHODIMP SampleCB(double Time, IMediaSample *pSample); + STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen); +private: + +}; +#endif +#endif diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoder.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c93d370042965d9cdd1c7989a7c13836affaf5dd --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoder.cpp @@ -0,0 +1,25 @@ +/* + * YangAudioDecoder.cpp + * + * Created on: 2020年9月3日 + * Author: yang + */ + +#include "yangdecoder/YangAudioDecoder.h" +#include +YangAudioDecoder::YangAudioDecoder() { + m_context = NULL; + m_isInit = 0; + m_frameSize = 0; + m_uid=-1; + m_alen=0; + m_dstBuffer=new uint8_t[4096]; + m_dstLen=0; +} + +YangAudioDecoder::~YangAudioDecoder() { + m_context = NULL; + if(m_dstBuffer) delete[] m_dstBuffer; + m_dstBuffer=NULL; +} + diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ded6f5c4709161fe62c57ec617622bc58b0440ff --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.cpp @@ -0,0 +1,117 @@ +#include +#include "YangAudioDecoderAac.h" + +#include "yangutil/yang_unistd.h" +#include "string.h" +#include "memory.h" + +//#define yang_deleteA(a) {if( (a) != NULL ) {delete[] (a); (a) = NULL;}} +void YangAudioDecoderAac::loadLib(){ + //const SpeexMode * (*yang_speex_lib_get_mode) (int32_t mode); + + + yang_NeAACDecOpen=( NeAACDecHandle (*)(void))m_lib.loadFunction("NeAACDecOpen"); + yang_NeAACDecGetCurrentConfiguration=( NeAACDecConfigurationPtr (*)(NeAACDecHandle hDecoder))m_lib.loadFunction("NeAACDecGetCurrentConfiguration"); + yang_NeAACDecSetConfiguration=( uint8_t (*)(NeAACDecHandle hDecoder, + NeAACDecConfigurationPtr config))m_lib.loadFunction("NeAACDecSetConfiguration"); + yang_NeAACDecInit=( long (*)(NeAACDecHandle hDecoder, + uint8_t *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + uint8_t *channels))m_lib.loadFunction("NeAACDecInit"); + yang_NeAACDecDecode=( void* (*)(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + uint8_t *buffer, + unsigned long buffer_size))m_lib.loadFunction("NeAACDecDecode"); + yang_NeAACDecClose=( void (*)(NeAACDecHandle hDecoder))m_lib.loadFunction("NeAACDecClose"); + +} + + +void YangAudioDecoderAac::unloadLib(){ + yang_NeAACDecOpen=NULL; + yang_NeAACDecGetCurrentConfiguration=NULL; + yang_NeAACDecSetConfiguration=NULL; + yang_NeAACDecInit=NULL; + yang_NeAACDecDecode=NULL; + yang_NeAACDecClose=NULL; + + +} +YangAudioDecoderAac::YangAudioDecoderAac(YangAudioParam *pcontext) { + m_context=pcontext; + m_samplerate = 44100; + m_channel = 2; + m_bufLen = 4096; + isFirst = 1; + isConvert = 0; + m_handle = NULL; + m_buffer = new uint8_t[4096]; + temp = NULL; + unloadLib(); +} + +YangAudioDecoderAac::~YangAudioDecoderAac() { + + closeAacdec(); + temp = NULL; + m_handle = NULL; + yang_deleteA(m_buffer); + unloadLib(); + m_lib.unloadObject(); +} + +void YangAudioDecoderAac::init() { + //yap->init(); + if(m_isInit) return; + m_lib.loadObject("libfaad"); + loadLib(); + if (m_handle == NULL) + m_handle = yang_NeAACDecOpen(); + if (!m_handle) { + printf("NeAACDecOpen failed\n"); + // goto error; + } + NeAACDecConfigurationPtr conf = yang_NeAACDecGetCurrentConfiguration(m_handle); + if (!conf) { + printf("NeAACDecGetCurrentConfiguration failed\n"); + // goto error; + } + conf->defObjectType = LC; + conf->defSampleRate = 44100; + + conf->outputFormat = FAAD_FMT_16BIT; + conf->dontUpSampleImplicitSBR = 1; + + yang_NeAACDecSetConfiguration(m_handle, conf); + m_alen=4096; + m_isInit=1; +} + + +int32_t YangAudioDecoderAac::decode(YangFrame* pframe,YangDecoderCallback* pcallback){ + if (isFirst&&m_handle) { + long res = yang_NeAACDecInit(m_handle, m_buffer, m_bufLen, &m_samplerate,&m_channel); + isFirst = 0; + } + + if(m_handle) temp = (uint8_t *) yang_NeAACDecDecode(m_handle, &m_info, pframe->payload, pframe->nb); + + if (temp&&pcallback){ + pframe->payload=temp; + pframe->nb=4096; + pcallback->onAudioData(pframe); + } + return Yang_Ok; + +} + +void YangAudioDecoderAac::closeAacdec() { + if (m_handle) { + yang_NeAACDecClose(m_handle); + } + m_handle = NULL; + // yap->close(); + +} + diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.h b/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.h new file mode 100644 index 0000000000000000000000000000000000000000..945d2312c7b84b1d97e512effda55237e02b9cd3 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderAac.h @@ -0,0 +1,59 @@ +#ifndef AACDECODER_H +#define AACDECODER_H +#include +#include +#include + +#include "faad.h" +#include + +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/sys/YangLoadLib.h" +#include "yangdecoder/YangAudioDecoder.h" +using namespace std; +class YangAudioDecoderAac :public YangAudioDecoder +{ +public: + YangAudioDecoderAac(YangAudioParam *pcontext); + ~YangAudioDecoderAac(); + void init(); + int32_t decode(YangFrame* pframe,YangDecoderCallback* pcallback); + + +protected: + +private: + + void closeAacdec(); + int32_t isConvert; + uint8_t *temp; + NeAACDecHandle m_handle; + + int32_t isFirst; + NeAACDecFrameInfo m_info; + unsigned long m_samplerate; + uint8_t m_channel; + unsigned long m_bufLen; + uint8_t *m_buffer; + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + NeAACDecHandle (*yang_NeAACDecOpen)(void); + NeAACDecConfigurationPtr (*yang_NeAACDecGetCurrentConfiguration)(NeAACDecHandle hDecoder); + uint8_t (*yang_NeAACDecSetConfiguration)(NeAACDecHandle hDecoder, + NeAACDecConfigurationPtr config); + long (*yang_NeAACDecInit)(NeAACDecHandle hDecoder, + uint8_t *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + uint8_t *channels); + void* (*yang_NeAACDecDecode)(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + uint8_t *buffer, + unsigned long buffer_size); + void (*yang_NeAACDecClose)(NeAACDecHandle hDecoder); + + +}; + +#endif // AACDECODER_H diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderHandle.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoderHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..efd67f090db12190269885c8cf68599c54f60252 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderHandle.cpp @@ -0,0 +1,168 @@ +#include "malloc.h" +#include +#include +#include +#include +#include "stdlib.h" + +#include "yangdecoder/YangDecoderFactory.h" + +YangAudioDecoderHandle::YangAudioDecoderHandle(YangContext *pcontext) { + m_context=pcontext; + m_context->streams.setDecoderMediaConfigCallback(this); + m_isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_audioBuffer = NULL; + m_decs = NULL; + m_out_audioBuffer = NULL; + m_buf=NULL; + m_size=0; + m_is44100=false; + m_param = new YangAudioParam(); + m_param->encode = (YangAudioEncDecType) pcontext->audio.audioDecoderType; + m_param->sample = pcontext->audio.sample; + m_param->channel = pcontext->audio.channel; + + m_is44100=(m_param->sample==44100); + memset(&m_audioFrame,0,sizeof(YangFrame)); +} + + +YangAudioDecoderHandle::~YangAudioDecoderHandle(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_context = NULL; + m_in_audioBuffer = NULL; + m_out_audioBuffer = NULL; + + if (m_decs) { + + delete m_decs; + m_decs = NULL; + + } + yang_deleteA(m_buf); + +} + +void YangAudioDecoderHandle::stop() { + stopLoop(); +} + +void YangAudioDecoderHandle::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +YangAudioPlayBuffer* YangAudioDecoderHandle::getOutAudioBuffer() { + + return m_out_audioBuffer; +} + +void YangAudioDecoderHandle::init() { + m_isInit = 1; +} +void YangAudioDecoderHandle::setRemoteParam(YangAudioParam *para) { + m_param->encode = para->encode; + m_param->sample = para->sample; + m_param->channel = para->channel; + m_is44100=(m_param->sample==44100); + +} + +void YangAudioDecoderHandle::setMediaConfig(int32_t puid, YangAudioParam *para, + YangVideoParam *video) { + m_param->encode = para->encode; + m_param->sample = para->sample; + m_param->channel = para->channel; + m_is44100=(m_param->sample==44100); + +} +void YangAudioDecoderHandle::setInAudioBuffer(YangAudioEncoderBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} +void YangAudioDecoderHandle::setOutAudioBuffer(YangAudioPlayBuffer *pbuf) { + m_out_audioBuffer = pbuf; + if(m_context&&m_context->streams.m_playBuffer) m_context->streams.m_playBuffer->setInAudioBuffer(pbuf); +} + +void YangAudioDecoderHandle::onAudioData(YangFrame *pframe) { + + if (m_out_audioBuffer){ + if(m_is44100){ + if(m_buf==NULL) { + m_buf=new uint8_t[1024*10]; + m_size=0; + + } + memcpy(m_buf,pframe->payload,pframe->nb); + m_size+=pframe->nb; + int indexs=0; + int len=882<<2; + while(m_size>=len){ + pframe->payload=m_buf+indexs; + pframe->nb=len; + m_out_audioBuffer->putAudio(pframe); + indexs+=len; + m_size-=len; + } + if(indexs>0&&m_size>0) memmove(m_buf,m_buf+indexs,m_size); + }else{ + + m_out_audioBuffer->putAudio(pframe); + } + } + +} +void YangAudioDecoderHandle::onVideoData(YangFrame *pframe) { + +} +void YangAudioDecoderHandle::startLoop() { + m_isConvert = 1; + uint8_t srcAudioSource[600]; + int32_t audioCacheSize = m_context->audio.audioPlayCacheNum; + YangDecoderFactory ydf; + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + while (m_isConvert == 1) { + if (!m_in_audioBuffer) { + yang_usleep(1000); + continue; + } + if (m_in_audioBuffer->size() == 0) { + yang_usleep(200); + continue; + } + audioFrame.payload = srcAudioSource; + m_in_audioBuffer->getPlayAudio(&audioFrame); + + if (!m_decs) { + m_decs = ydf.createAudioDecoder(m_param); + + m_decs->m_uid = audioFrame.uid; + m_decs->init(); + } + + if (m_decs){ + if(m_decs->decode(&audioFrame, this)){ + yang_error("decode audio fail.."); + } + } + + if (m_in_audioBuffer && m_in_audioBuffer->size() > audioCacheSize) + m_in_audioBuffer->resetIndex(); + + } //end + +} + +void YangAudioDecoderHandle::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderHandles.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoderHandles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e4b4fbc76a2f64f2996f3cb196ee56a66df83fc --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderHandles.cpp @@ -0,0 +1,248 @@ +#include "malloc.h" +#include +#include +#include +#include +#include "stdlib.h" + +#include "yangdecoder/YangDecoderFactory.h" + +YangAudioDecoderHandles::YangAudioDecoderHandles(YangContext *pcontext) { + m_isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_audioBuffer = NULL; + m_decs = new vector(); + m_out_audioBuffer = NULL; + m_context = pcontext; + m_frameSize=1024; + m_channel=2; +} + + +YangAudioDecoderHandles::~YangAudioDecoderHandles(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_context = NULL; + m_in_audioBuffer = NULL; + + size_t i = 0; + if (m_out_audioBuffer && m_out_audioBuffer->size() > 0) { + for (i = 0; i < m_out_audioBuffer->size(); i++) {yang_delete( m_out_audioBuffer->at(i)); } + + m_out_audioBuffer->clear(); + + } + m_out_audioBuffer = NULL; + if (m_decs) { + for (i = 0; i < m_decs->size(); i++) {yang_delete( m_decs->at(i)); } + + m_decs->clear(); + delete m_decs; + m_decs = NULL; + + } + + for(std::map::iterator it = m_paramMap.begin(); it != m_paramMap.end(); ++it) { + yang_delete(it->second); + } + m_paramMap.clear(); + +} +void YangAudioDecoderHandles::stop() { + stopLoop(); +} + +void YangAudioDecoderHandles::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +void YangAudioDecoderHandles::setRemoteParam(int32_t puid,YangAudioParam* para){ + + map::iterator iter; + iter=m_paramMap.find(puid); + YangAudioParam* t_param=NULL; + if(iter == m_paramMap.end()){ + t_param=new YangAudioParam(); + m_paramMap[puid]=t_param; + }else{ + t_param=iter->second; + } + t_param->encode=para->encode; + t_param->sample=para->sample; + t_param->channel=para->channel; + +} + +int32_t YangAudioDecoderHandles::getDecoderIndex(int32_t puid) { + for (int32_t i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) + return i; + } + return -1; +} +void YangAudioDecoderHandles::removeAllStream() { + int32_t i = 0; + if (m_decs && m_decs->size() > 0) { + for (i = 0; i < (int) m_decs->size(); i++) { + delete m_decs->at(i); + m_decs->at(i) = NULL; + } + m_decs->clear(); + } + if (m_out_audioBuffer && m_out_audioBuffer->size() > 0) { + for (i = 0; i < (int) m_out_audioBuffer->size(); i++) { + delete m_out_audioBuffer->at(i); + m_out_audioBuffer->at(i) = NULL; + } + m_out_audioBuffer->clear(); + } + + for (map::iterator it = m_paramMap.begin(); it != m_paramMap.end();it++) { + yang_delete(it->second); + } + m_paramMap.clear(); +} +void YangAudioDecoderHandles::removeAudioStream(int32_t puid) { + int32_t i = 0; + if (m_decs && m_decs->size() > 0) { + for (i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) { + delete m_decs->at(i); + m_decs->at(i) = NULL; + m_decs->erase(m_decs->begin() + i); + break; + } + + } + } + if (m_out_audioBuffer && m_out_audioBuffer->size() > 0) { + for (i = 0; i < (int) m_out_audioBuffer->size(); i++) { + if (m_out_audioBuffer->at(i)->m_uid == puid) { + delete m_out_audioBuffer->at(i); + m_out_audioBuffer->at(i) = NULL; + m_out_audioBuffer->erase(m_out_audioBuffer->begin() + i); + return; + } + } + + } + map::iterator it = m_paramMap.find(puid); + if(it!=m_paramMap.end()){ + yang_delete(it->second); + } + m_paramMap.erase(puid); + // m_paramMap.clear(); + +} + +YangAudioDecoder* YangAudioDecoderHandles::getDecoder(int32_t puid) { + for (int32_t i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) + return m_decs->at(i); + } + return NULL; +} + +YangAudioPlayBuffer* YangAudioDecoderHandles::getAudioBuffer(int32_t puid) { + for (int32_t i = 0; i < (int) m_out_audioBuffer->size(); i++) { + if (m_out_audioBuffer->at(i)->m_uid == puid) + return m_out_audioBuffer->at(i); + } + return NULL; +} + +void YangAudioDecoderHandles::init() { + m_isInit = 1; +} + +void YangAudioDecoderHandles::setInAudioBuffer(YangAudioEncoderBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} +void YangAudioDecoderHandles::setOutAudioBuffer(vector *pbuf) { + m_out_audioBuffer = pbuf; +} +void YangAudioDecoderHandles::onAudioData(YangFrame* pframe){ + YangAudioPlayBuffer *t_vb = getAudioBuffer(pframe->uid); + if (!t_vb) { + m_out_audioBuffer->push_back(new YangAudioPlayBuffer()); + m_out_audioBuffer->back()->m_uid = pframe->uid; + t_vb = m_out_audioBuffer->back(); + int ind=0; + if(m_context&&(ind=m_context->streams.getIndex(pframe->uid))>-1){ + m_context->streams.m_playBuffers->at(ind)->setInAudioBuffer(t_vb); + m_context->streams.m_playBuffers->at(ind)->setAudioClock(m_context->streams.getAudioClock()); + } + } + if (t_vb) { + t_vb->putAudio(pframe); + } + t_vb=NULL; +} +void YangAudioDecoderHandles::onVideoData(YangFrame* pframe){ + +} + +void YangAudioDecoderHandles::startLoop() { + m_isConvert = 1; + uint8_t srcAudioSource[600]; + int32_t audioCacheSize = m_context->audio.audioPlayCacheNum; + YangAudioDecoder *t_decoder = NULL; + YangDecoderFactory ydf; + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + while (m_isConvert == 1) { + if (!m_in_audioBuffer) { + yang_usleep(1000); + continue; + } + if (m_in_audioBuffer->size() == 0) { + yang_usleep(200); + continue; + } + audioFrame.payload=srcAudioSource; + m_in_audioBuffer->getPlayAudio(&audioFrame); + t_decoder = getDecoder(audioFrame.uid); + + if (!t_decoder) { + map::iterator iter; + iter=m_paramMap.find(audioFrame.uid); + if(iter != m_paramMap.end()){ + m_decs->push_back(ydf.createAudioDecoder(iter->second)); + }else{ + YangAudioParam* param=new YangAudioParam(); + m_paramMap[audioFrame.uid]=param; + param->encode=(YangAudioEncDecType)m_context->audio.audioDecoderType; + param->sample=m_context->audio.sample; + param->channel=m_context->audio.channel; + m_decs->push_back(ydf.createAudioDecoder(param)); + } + + t_decoder = m_decs->back(); + t_decoder->m_uid = audioFrame.uid; + t_decoder->init(); + } + + if (t_decoder){ + if(t_decoder->decode(&audioFrame,this)){ + yang_error("decode audio fail..uid==%d",audioFrame.uid); + } + } + + if (m_in_audioBuffer && m_in_audioBuffer->size() > audioCacheSize) + m_in_audioBuffer->resetIndex(); + t_decoder = NULL; + } //end + +} + +void YangAudioDecoderHandles::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc2273fce9b57ee412e1b77cfe67d47fe62eb6f3 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.cpp @@ -0,0 +1,100 @@ +/* + * YangAudioDecoderOpus.cpp + * + * Created on: 2019年9月29日 + * Author: yang + */ +#include "YangAudioDecoderOpus.h" + +#include "yangutil/yang_unistd.h" +#include "string.h" +#include "memory.h" +#include +#include + +void YangAudioDecoderOpus::loadLib(){ + yang_opus_decoder_create=(OpusDecoder *(*)( opus_int32 Fs, int32_t channels, int32_t *error))m_lib.loadFunction("opus_decoder_create"); + yang_opus_decoder_init=(int32_t (*)(OpusDecoder *st,opus_int32 Fs, int32_t channels ))m_lib.loadFunction("opus_decoder_init") ; + yang_opus_decode=(int32_t (*)(OpusDecoder *st,const uint8_t *data, opus_int32 len,opus_int16 *pcm, + int32_t frame_size, int32_t decode_fec))m_lib.loadFunction("opus_decode"); + yang_opus_decoder_ctl=( int32_t (*)(OpusDecoder *st, int32_t request, ...))m_lib.loadFunction("opus_decoder_ctl"); + yang_opus_decoder_destroy=( void (*)(OpusDecoder *st))m_lib.loadFunction("opus_decoder_destroy"); + yang_opus_strerror=(const char *(*)(int32_t error))m_lib.loadFunction("opus_strerror"); +} + +void YangAudioDecoderOpus::unloadLib(){ + yang_opus_decoder_create=NULL; + yang_opus_decoder_init=NULL; + yang_opus_decode=NULL; + yang_opus_decoder_ctl=NULL; + yang_opus_decoder_destroy=NULL; + yang_opus_strerror=NULL; +} + +YangAudioDecoderOpus::YangAudioDecoderOpus(YangAudioParam *pcontext) { + m_context=pcontext; + isConvert = 0; + m_frameSize=1024; + ret=0; + m_out=NULL; + m_output=NULL; + m_decoder=NULL; + m_sample=pcontext->sample; + m_channel = pcontext->channel; + m_isMono= (m_channel==1); + m_frameSize=m_sample/50; + unloadLib(); +} + +YangAudioDecoderOpus::~YangAudioDecoderOpus() { + yang_deleteA(m_out); + yang_delete(m_output); + closedec(); + unloadLib(); + m_lib.unloadObject(); +} + +#define MAX_FRAME_SIZE 8192 +void YangAudioDecoderOpus::init() { + if(m_isInit) return; + m_lib.loadObject("libopus"); + loadLib(); + + int32_t err=0; + m_decoder=yang_opus_decoder_create(m_sample, m_channel, &err); + if (err<0) + { + fprintf(stderr, "failed to create an decoder: %s\n", yang_opus_strerror(err)); + _exit(0); + // return EXIT_FAILURE; + } + m_out=new short[MAX_FRAME_SIZE*m_channel]; + m_output=new uint8_t[m_frameSize*m_channel*2]; + m_alen=m_frameSize*m_channel*2; + m_isInit=1; + +} + +int32_t YangAudioDecoderOpus::decode(YangFrame* pframe,YangDecoderCallback* pcallback){ +if(!m_decoder) return 1; + ret=yang_opus_decode(m_decoder, pframe->payload, pframe->nb, m_out, MAX_FRAME_SIZE, 0); + + if(ret==m_frameSize&&pcallback){ + + for(int32_t i=0;i>8)&0xFF; + } + pframe->payload=m_output; + pframe->nb=ret*2*m_channel; + pcallback->onAudioData(pframe); + return Yang_Ok; + } + return 1; +} + +void YangAudioDecoderOpus::closedec() { + if(m_decoder) yang_opus_decoder_destroy(m_decoder); + m_decoder=NULL; + +} diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.h b/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.h new file mode 100644 index 0000000000000000000000000000000000000000..6aacc710f34dfb4dfc5f1fd3ec2d309121d33e77 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderOpus.h @@ -0,0 +1,46 @@ +/* + * YangAudioDecoderOpus.h + * + * Created on: 2019年9月29日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGAUDIODECODEROPUS_H_ +#define YANGDECODER_SRC_YANGAUDIODECODEROPUS_H_ +#include +#include "opus/opus.h" +#include "yangdecoder/YangAudioDecoder.h" + +class YangAudioDecoderOpus:public YangAudioDecoder { +public: + YangAudioDecoderOpus(YangAudioParam *pcontext); + virtual ~YangAudioDecoderOpus(); + void init(); + int32_t decode(YangFrame* pframe,YangDecoderCallback* pcallback); + private: + + void closedec(); + int32_t isConvert; + OpusDecoder *m_decoder; + + + int32_t m_isMono; + int32_t ret; + int32_t m_sample; + int32_t m_channel; + short *m_out; + uint8_t *m_output; + + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + OpusDecoder *(*yang_opus_decoder_create)( opus_int32 Fs, int32_t channels, int32_t *error); + int32_t (*yang_opus_decoder_init)(OpusDecoder *st,opus_int32 Fs, int32_t channels ) ; + int32_t (*yang_opus_decode)(OpusDecoder *st,const uint8_t *data, opus_int32 len,opus_int16 *pcm, + int32_t frame_size, int32_t decode_fec); + int32_t (*yang_opus_decoder_ctl)(OpusDecoder *st, int32_t request, ...); + void (*yang_opus_decoder_destroy)(OpusDecoder *st); + const char *(*yang_opus_strerror)(int32_t error); +}; + +#endif /* YANGDECODER_SRC_YANGAUDIODECODEROPUS_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.cpp b/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5dfb6f5fd34190f08317ff0ceefc561326cfba7 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.cpp @@ -0,0 +1,176 @@ +/* + * YangAudioDecoderSpeex.cpp + * + * Created on: 2019年9月8日 + * Author: yang + */ + +#include "YangAudioDecoderSpeex.h" + +#include "yangutil/yang_unistd.h" +#include "string.h" +#include "memory.h" + +void YangAudioDecoderSpeex::loadLib(){ + yang_speex_lib_get_mode=(const SpeexMode * (*) (int32_t mode))m_lib.loadFunction("speex_lib_get_mode"); + yang_speex_decoder_ctl=(int32_t (*)(void *state, int32_t request, void *ptr))m_lib.loadFunction("speex_decoder_ctl"); + yang_speex_decoder_init=(void* (*)(const SpeexMode *mode))m_lib.loadFunction("speex_decoder_init"); + yang_speex_bits_init=(void (*)(SpeexBits *bits))m_lib.loadFunction("speex_bits_init"); + yang_speex_bits_reset=(void (*)(SpeexBits *bits))m_lib.loadFunction("speex_bits_reset"); + yang_speex_bits_read_from=(int32_t (*)(SpeexBits *bits, const char *bytes, int32_t len))m_lib.loadFunction("speex_bits_read_from"); + yang_speex_decode_int=(int32_t (*)(void *state, SpeexBits *bits, spx_int16_t *out))m_lib.loadFunction("speex_decode_int"); + yang_speex_decoder_destroy=(void (*)(void *state))m_lib.loadFunction("speex_decoder_destroy"); + yang_speex_bits_destroy=(void (*)(SpeexBits *bits))m_lib.loadFunction("speex_bits_destroy"); +} + +void YangAudioDecoderSpeex::unloadLib(){ + yang_speex_lib_get_mode=NULL; + yang_speex_decoder_init=NULL; + yang_speex_bits_init=NULL; + yang_speex_bits_reset=NULL; + yang_speex_bits_read_from=NULL; + yang_speex_decode_int=NULL; + yang_speex_decoder_destroy=NULL; + yang_speex_bits_destroy=NULL; +} + +YangAudioDecoderSpeex::YangAudioDecoderSpeex(YangAudioParam *pcontext) { + m_context=pcontext; + //m_samplerate = 44100; + m_channel = 1; + //m_bufLen = 4096; + //m_tlen = 0; + //isFirst = 1; + //m_index = 0; + isConvert = 0; + m_frameSize=320; + //m_handle = NULL; + //m_buffer = new uint8_t[4096]; + //audioList = NULL; + // conf=NULL; + //temp = NULL; + //m_mode=speex_wb_mode; + ///memset(srcAudioSource, 0, sizeof(srcAudioSource)); + + //printf("\n*************************YangAudioDecoderSpeex Speex is starting.....\n"); + + m_quality=8; + m_state=NULL; + ret=0; + m_out=0; + m_bits=NULL; + unloadLib(); + +} + +YangAudioDecoderSpeex::~YangAudioDecoderSpeex() { + yang_deleteA(m_out); + //yang_delete(m_bits); + closedec(); + unloadLib(); + m_lib.unloadObject(); + //temp = NULL; + //m_handle = NULL; + //yang_deleteA(m_buffer); +} +void YangAudioDecoderSpeex::initSpeexPara(){ + //if(m_mode==speex_nb_mode){ + // m_quality=6; + // m_frameSize=160; + //} + //if(m_mode==speex_wb_mode){ + //m_quality=8; + //m_frameSize=320; + // } +// if(m_mode==speex_uwb_mode){ + // m_quality=10; + //m_frameSize=640; + // } +} +void YangAudioDecoderSpeex::init() { + //yap->init(); + if(m_isInit) return; + m_lib.loadObject("libspeex"); + loadLib(); + m_bits=new SpeexBits(); + m_state = yang_speex_decoder_init(yang_speex_lib_get_mode(SPEEX_MODEID_WB));//speex_wb_mode &speex_nb_mode); + initSpeexPara(); + m_quality=10; + yang_speex_decoder_ctl(m_state, SPEEX_SET_QUALITY, &m_quality); + // int32_t tmp=1; + m_frameSize=320; + // speex_decoder_ctl(m_state, SPEEX_SET_ENH, &tmp); + yang_speex_bits_init(m_bits); + // callback.callback_id = SPEEX_INBAND_CHAR; + // callback.func = speex_std_char_handler; + // callback.data = stderr; + // speex_decoder_ctl(m_state, SPEEX_SET_HANDLER, &callback); + // tmp=1; + // speex_decoder_ctl(m_state, SPEEX_GET_LOOKAHEAD, &tmp); + + + // speex_decoder_ctl(m_state, SPEEX_GET_FRAME_SIZE, &m_frameSize); + // m_output=new float[m_frameSize]; + m_out=new short[m_frameSize]; + m_alen=640; + m_isInit=1; + +} + +//void YangAudioDecoderSpeex::decode(uint8_t *pout,uint8_t *pData, int32_t *outLen, unsigned long nLen, int32_t puid) { +int32_t YangAudioDecoderSpeex::decode(YangFrame* pframe,YangDecoderCallback* pcallback){ + //printf("m%d,",m_state); +if(!m_state) return 1; + yang_speex_bits_read_from(m_bits, (const char*)pframe->payload, pframe->nb); + ret=yang_speex_decode_int(m_state, m_bits, m_out); + + if(!ret&&pcallback){ + pframe->payload=(uint8_t*)m_out; + pframe->nb=640; + pcallback->onAudioData(pframe); + return Yang_Ok; + } + return 1; +} + +void YangAudioDecoderSpeex::closedec() { + if(m_state) yang_speex_decoder_destroy(m_state); + m_state=NULL; + if(m_bits) yang_speex_bits_destroy(m_bits); + m_bits=NULL; +} +/** +int32_t YangAudioDecoderSpeex::getIndex(int32_t puid){ + for(int32_t i=0;isize();i++){ + if(m_out_audioBuffer->at(i)->m_uid==puid){ + return i; + } + } + + return -1; +} +void YangAudioDecoderSpeex::startLoop() { + int32_t audioBufLen = 0; + isConvert = 1; + int32_t t_uid = 0; + //int32_t t_size=0; + //m_out_audioBuffer->push_back(new YangAudioPlayBuffer(4096)); + //printf("\n*************************decode Speex is starting.....\n"); + int32_t audioCacheSize=m_context->audioPlayCacheNum; + while (isConvert == 1) { + + if (m_in_audioBuffer->size() == 0) { + yang_usleep(200); + continue; + } + + m_in_audioBuffer->getPlayAudio(srcAudioSource, &audioBufLen, &t_uid); + decode(srcAudioSource, audioBufLen, t_uid); + if(m_in_audioBuffer->size()>audioCacheSize) m_in_audioBuffer->resetIndex(); + } //end + +} +void YangAudioDecoderSpeex::stopLoop(){ + isConvert=0; +} +**/ diff --git a/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.h b/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.h new file mode 100644 index 0000000000000000000000000000000000000000..b26ecd8dc23e78cae63ed628f32149afa229311f --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangAudioDecoderSpeex.h @@ -0,0 +1,51 @@ +/* + * YangAudioDecoderSpeex.h + * + * Created on: 2019年9月8日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGAUDIODECODERSPEEX_H_ +#define YANGDECODER_SRC_YANGAUDIODECODERSPEEX_H_ +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include + +#include "yangutil/sys/YangLoadLib.h" +#include "yangdecoder/YangAudioDecoder.h" + + +class YangAudioDecoderSpeex :public YangAudioDecoder{ +public: + YangAudioDecoderSpeex(YangAudioParam *pcontext); + virtual ~YangAudioDecoderSpeex(); + void init(); + int32_t decode(YangFrame* pframe,YangDecoderCallback* pcallback); +private: + void closedec(); + int32_t isConvert; + SpeexBits *m_bits; + //SpeexMode m_mode; + //SpeexCallback callback; + YangLoadLib m_lib; + void initSpeexPara(); + int32_t m_quality; + int32_t ret; + void* m_state; + + int32_t m_channel; + short *m_out;//[m_frameSize]; + + void loadLib(); + void unloadLib(); + const SpeexMode * (*yang_speex_lib_get_mode) (int32_t mode); + void *(*yang_speex_decoder_init)(const SpeexMode *mode); + void (*yang_speex_bits_init)(SpeexBits *bits); + void (*yang_speex_bits_reset)(SpeexBits *bits); + int32_t (*yang_speex_bits_read_from)(SpeexBits *bits, const char *bytes, int32_t len); + int32_t (*yang_speex_decode_int)(void *state, SpeexBits *bits, spx_int16_t *out); + void (*yang_speex_decoder_destroy)(void *state); + void (*yang_speex_bits_destroy)(SpeexBits *bits); + int32_t (*yang_speex_decoder_ctl)(void *state, int32_t request, void *ptr); +}; + +#endif /* YANGDECODER_SRC_YANGAUDIODECODERSPEEX_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangDecoderFactory.cpp b/libyangrtc2/src/yangdecoder/YangDecoderFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cf0af464cb3079fe9a2043c9eb1d14a05519475 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangDecoderFactory.cpp @@ -0,0 +1,66 @@ +/* + * YangDecoderFactory.cpp + * + * Created on: 2019年9月3日 + * Author: yang + */ + +#include "yangdecoder/YangDecoderFactory.h" + +#include "YangAudioDecoderAac.h" +//#include "YangAudioDecoderMp3.h" +#include "YangAudioDecoderOpus.h" +#include "YangAudioDecoderSpeex.h" +#include "YangVideoDecoderIntel.h" +#include "YangH2645VideoDecoderFfmpeg.h" +#include "YangH264DecoderSoft.h" +#include "YangH264DecoderSoftFactory.h" +YangDecoderFactory::YangDecoderFactory() { + + +} + +YangDecoderFactory::~YangDecoderFactory() { + +} + +YangAudioDecoder *YangDecoderFactory::createAudioDecoder(YangAudioEncDecType paet,YangAudioParam *pcontext){ + //if(paet==Yang_AED_MP3) return new YangAudioDecoderMp3(pcontext); + if(paet==Yang_AED_SPEEX) return new YangAudioDecoderSpeex(pcontext); + if(paet==Yang_AED_OPUS) return new YangAudioDecoderOpus(pcontext); + return new YangAudioDecoderAac(pcontext); +} + +YangAudioDecoder *YangDecoderFactory::createAudioDecoder(YangAudioParam *pcontext){ + + + return createAudioDecoder(pcontext->encode,pcontext); +} + +YangVideoDecoder* YangDecoderFactory::createFfmpegVideoDecoder(YangVideoEncDecType paet,YangVideoInfo *pcontext){ + return new YangH2645VideoDecoderFfmpeg(pcontext,paet); +} +YangVideoDecoder* YangDecoderFactory::createVideoDecoder(YangVideoEncDecType paet,YangVideoInfo *pcontext){ + if (paet == Yang_VED_264) { + if(pcontext->videoDecHwType==0){ + //return new YangH264DecoderSoft(); + return new YangH2645VideoDecoderFfmpeg(pcontext,paet); + }else + return new YangH2645VideoDecoderFfmpeg(pcontext,paet); + } + if (paet == Yang_VED_265) return new YangH2645VideoDecoderFfmpeg(pcontext,paet); + //de264=new YangVideoDecoderIntel(); + // if(p_decType==Type_Nvdia) de264= new YangH264DecoderNv(); +#if YangLibva + return new YangVideoDecoderIntel(); +#else + return NULL; +#endif +} + YangVideoDecoder* YangDecoderFactory::createVideoDecoder(YangVideoInfo *pcontext){ + YangVideoEncDecType maet=Yang_VED_264; + if(pcontext->videoDecoderType==Yang_VED_265) maet=Yang_VED_265; + //if(pcontext->videoDecoderType==1) maet=Type_Dec_Ffmpeg; + //if(pcontext->audioDecoderType==2) maet=Yang_AE_SPEEX; + return createVideoDecoder(maet,pcontext); + } diff --git a/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.cpp b/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baaa49384f06afc9724d7647b60f66ee55def8ff --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.cpp @@ -0,0 +1,462 @@ +/* + * YangH2645VideoDecoderFfmpeg.cpp + * + * Created on: 2019年9月20日 + * Author: yang + */ + +#include "YangH2645VideoDecoderFfmpeg.h" +#include +#include +#include "stdlib.h" +#if Yang_Ffmpeg_UsingSo +void YangH2645VideoDecoderFfmpeg::loadLib() { + + yang_av_frame_alloc = (AVFrame* (*)(void)) m_lib1.loadFunction( + "av_frame_alloc"); + yang_av_buffer_unref = (void (*)(AVBufferRef **buf)) m_lib1.loadFunction( + "av_buffer_unref"); + yang_av_hwframe_ctx_init = (int32_t (*)(AVBufferRef *ref)) m_lib1.loadFunction( + "av_hwframe_ctx_init"); + yang_av_image_get_buffer_size = (int32_t (*)(enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_get_buffer_size"); + yang_av_hwdevice_ctx_create = (int32_t (*)(AVBufferRef **device_ctx, + enum AVHWDeviceType type, const char *device, AVDictionary *opts, + int32_t flags)) m_lib1.loadFunction("av_hwdevice_ctx_create"); + yang_av_hwframe_transfer_data = (int32_t (*)(AVFrame *dst, const AVFrame *src, + int32_t flags)) m_lib1.loadFunction("av_hwframe_transfer_data"); + yang_av_free = (void (*)(void *ptr)) m_lib1.loadFunction("av_free"); + yang_av_frame_free = (void (*)(AVFrame **frame)) m_lib1.loadFunction( + "av_frame_free"); + yang_av_buffer_ref = + (AVBufferRef* (*)(AVBufferRef *buf)) m_lib1.loadFunction( + "av_buffer_ref"); + yang_av_image_fill_arrays = (int32_t (*)(uint8_t *dst_data[4], + int32_t dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_fill_arrays"); + yang_av_hwframe_ctx_alloc = + (AVBufferRef* (*)(AVBufferRef *device_ctx)) m_lib1.loadFunction( + "av_hwframe_ctx_alloc"); + yang_av_malloc = (void* (*)(size_t size)) m_lib1.loadFunction("av_malloc"); + + yang_avcodec_open2 = (int32_t (*)(AVCodecContext *avctx, const AVCodec *codec, + AVDictionary **options)) m_lib.loadFunction("avcodec_open2"); + yang_av_init_packet = (void (*)(AVPacket *pkt)) m_lib.loadFunction( + "av_init_packet"); + yang_av_hwframe_get_buffer = (int32_t (*)(AVBufferRef *hwframe_ctx, + AVFrame *frame, int32_t flags)) m_lib.loadFunction( + "av_hwframe_get_buffer"); + yang_avcodec_find_decoder = + (AVCodec* (*)(enum AVCodecID id)) m_lib.loadFunction( + "avcodec_find_decoder"); + yang_avcodec_find_decoder_by_name=(AVCodec *(*)(const char *name)) m_lib.loadFunction( + "avcodec_find_decoder_by_name"); + yang_avcodec_alloc_context3 = + (AVCodecContext* (*)(const AVCodec *codec)) m_lib.loadFunction( + "avcodec_alloc_context3"); + yang_avcodec_send_packet = (int32_t (*)(AVCodecContext *avctx, + const AVPacket *avpkt)) m_lib.loadFunction("avcodec_send_packet"); + yang_avcodec_receive_frame = + (int32_t (*)(AVCodecContext *avctx, AVFrame *frame)) m_lib.loadFunction( + "avcodec_receive_frame"); + yang_avcodec_flush_buffers=(void (*)(AVCodecContext *avctx)) m_lib.loadFunction( + "avcodec_flush_buffers"); + yang_avcodec_close = (int32_t (*)(AVCodecContext *avctx)) m_lib.loadFunction( + "avcodec_close"); +} +void YangH2645VideoDecoderFfmpeg::unloadLib() { + yang_avcodec_find_decoder_by_name=NULL; + yang_av_free = NULL; + yang_av_hwframe_ctx_alloc = NULL; + yang_av_hwframe_ctx_init = NULL; + yang_av_buffer_ref = NULL; + yang_av_malloc = NULL; + yang_av_hwdevice_ctx_create = NULL; + yang_avcodec_open2 = NULL; + yang_av_frame_alloc = NULL; + yang_av_image_get_buffer_size = NULL; + yang_av_image_fill_arrays = NULL; + yang_av_init_packet = NULL; + yang_av_hwframe_get_buffer = NULL; + yang_avcodec_find_decoder = NULL; + yang_avcodec_alloc_context3 = NULL; + yang_avcodec_send_packet = NULL; + yang_avcodec_receive_frame = NULL; + yang_av_hwframe_transfer_data = NULL; + yang_avcodec_flush_buffers=NULL; + yang_av_frame_free = NULL; + yang_avcodec_close = NULL; +} +#endif +enum AVPixelFormat get_hw_format1(AVCodecContext *ctx, + const enum AVPixelFormat *pix_fmts) { + if(YangH2645VideoDecoderFfmpeg::g_hwType==YangV_Hw_Intel) return AV_PIX_FMT_VAAPI; + if(YangH2645VideoDecoderFfmpeg::g_hwType==YangV_Hw_Nvdia) return AV_PIX_FMT_CUDA; + if(YangH2645VideoDecoderFfmpeg::g_hwType==YangV_Hw_Android) return AV_PIX_FMT_MEDIACODEC; + //return AV_PIX_FMT_VAAPI; + return AV_PIX_FMT_VAAPI; + +} + +int32_t YangH2645VideoDecoderFfmpeg::set_hwframe_ctx(AVPixelFormat ctxformat,AVPixelFormat swformat,YangVideoInfo *yvp,AVCodecContext *ctx, + AVBufferRef *hw_device_ctx, int32_t pwid, int32_t phei) { + AVBufferRef *hw_frames_ref; + AVHWFramesContext *frames_ctx = NULL; + int32_t err = 0; + + if (!(hw_frames_ref = yang_av_hwframe_ctx_alloc(hw_device_ctx))) { + printf("Failed to create hw frame context.\n"); + return -1; + } + frames_ctx = (AVHWFramesContext*) (hw_frames_ref->data); + frames_ctx->format = ctxformat; + frames_ctx->sw_format = swformat; + + frames_ctx->width = pwid; + frames_ctx->height = phei; + //frames_ctx->initial_pool_size = 20; + if ((err = yang_av_hwframe_ctx_init(hw_frames_ref)) < 0) { + printf("Failed to initialize VAAPI frame context.Error code: %d\n", + ret); + yang_av_buffer_unref(&hw_frames_ref); + return err; + } + ctx->hw_frames_ctx = yang_av_buffer_ref(hw_frames_ref); + ctx->hw_device_ctx = yang_av_buffer_ref(hw_device_ctx); + // ctx->hwaccel_flags=1; + if (!ctx->hw_frames_ctx) + err = AVERROR(ENOMEM); + + yang_av_buffer_unref(&hw_frames_ref); + return err; +} + +YangH2645VideoDecoderFfmpeg::YangH2645VideoDecoderFfmpeg(YangVideoInfo *pcontext,YangVideoEncDecType pencdectype) { + m_encDecType= pencdectype; + m_context=pcontext; + usingHw = 0; //pcontext->usingHwDec==2?1:0; + if(pcontext->videoDecHwType>0) usingHw=1; + + m_buffer=NULL; + m_bufLen=0; + + g_hwType=(YangVideoHwType)pcontext->videoDecHwType; + m_bitDepth=pcontext->bitDepth; + + m_width = 0; + m_height = 0; + m_frame = NULL; + yLen = 0; + uLen = 0; + allLen = 0; + buffer = NULL; + ret = 0; + m_codec = NULL; + + hw_device_ctx = NULL; + frame_mem_gpu = NULL; +#if Yang_Ffmpeg_UsingSo + unloadLib(); +#endif + +} +YangH2645VideoDecoderFfmpeg::~YangH2645VideoDecoderFfmpeg() { + m_context=NULL; + if(m_buffer) delete[] m_buffer; + m_buffer=NULL; + decode_close(); +#if Yang_Ffmpeg_UsingSo + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); +#endif + +} +YangVideoHwType YangH2645VideoDecoderFfmpeg::g_hwType=YangV_Hw_Intel; +void YangH2645VideoDecoderFfmpeg::parseHeader(uint8_t *p,int32_t pLen,int32_t *pwid,int32_t *phei,int32_t *pfps){ + + AVCodec *t_codec = yang_avcodec_find_decoder(AV_CODEC_ID_H265); + AVCodecContext* t_codecCtx = yang_avcodec_alloc_context3(t_codec); + t_codecCtx->extradata = (uint8_t*) yang_av_malloc(pLen + AV_INPUT_BUFFER_PADDING_SIZE); + t_codecCtx->extradata_size = pLen; + memcpy(t_codecCtx->extradata, p, pLen); + int32_t ret = yang_avcodec_open2(t_codecCtx, t_codec, NULL); + if (ret < 0) + printf("\navcodec_open2 failure................\n"); + + *pwid=t_codecCtx->width; + *phei=t_codecCtx->height; + *pfps=t_codecCtx->time_base.den;///t_codecCtx->time_base.num; + + yang_av_free(t_codecCtx->extradata); + t_codecCtx->extradata=NULL; + t_codecCtx->extradata_size = 0; + yang_avcodec_close(t_codecCtx); + yang_av_free(t_codecCtx); + t_codecCtx=NULL; + t_codec=NULL; +} +void YangH2645VideoDecoderFfmpeg::parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, + int32_t *phei, int32_t *pfps) { + + uint8_t headers[128]; + memset(headers, 0, 128); + int32_t headerLen = 0; + if(m_encDecType==Yang_VED_264){ + yang_getH264RtmpHeader(p, headers, &headerLen); + YangH264Header h264header; + h264header.parseRtmpHeader(p); + *pwid = h264header.width; + *phei = h264header.height; + *pfps = h264header.fps; + }else if(m_encDecType==Yang_VED_265) { + yang_getH265RtmpHeader(p, headers, &headerLen); + parseHeader(headers,headerLen,pwid,phei,pfps); + + } + m_width = *pwid; + m_height= *phei ; + + if(!m_buffer) m_buffer=new uint8_t[m_width*m_height*3/2]; + + int32_t bitLen=(m_bitDepth==8?1:2); + + yLen = m_width * m_height*bitLen; + uLen = yLen / 4; + allLen = yLen * 3 / 2; + + + m_codecCtx->extradata = (uint8_t*) yang_av_malloc(headerLen + AV_INPUT_BUFFER_PADDING_SIZE); + m_codecCtx->extradata_size = headerLen; + memcpy(m_codecCtx->extradata, headers, headerLen); + + m_codecCtx->width = m_width; + m_codecCtx->height = m_height; + + if (usingHw) { + AVPixelFormat ctxformat,swformat; + if(m_context->videoDecHwType==YangV_Hw_Intel) ctxformat = AV_PIX_FMT_VAAPI; + if(m_context->videoDecHwType==YangV_Hw_Nvdia) ctxformat = AV_PIX_FMT_CUDA; + if(m_context->videoDecHwType==YangV_Hw_Android) ctxformat = AV_PIX_FMT_MEDIACODEC; + if(m_context->bitDepth==8) swformat = AV_PIX_FMT_NV12; + if(m_context->bitDepth==10) swformat = AV_PIX_FMT_P010; + if(m_context->bitDepth==16) swformat = AV_PIX_FMT_P016; + if ((ret = set_hwframe_ctx(ctxformat,swformat,m_context,m_codecCtx, hw_device_ctx, m_width, m_height)) + < 0) { + printf("Failed to set hwframe context.\n"); + //goto close; + } + m_codecCtx->get_format = get_hw_format1; + } + + ret = yang_avcodec_open2(m_codecCtx, m_codec, NULL); + if (ret < 0) + printf("\navcodec_open2 failure................\n"); + AVPixelFormat fmt=AV_PIX_FMT_YUV420P; + if(m_bitDepth==8){ + if(usingHw) fmt=AV_PIX_FMT_NV12; + }else if(m_bitDepth==10){ + fmt=AV_PIX_FMT_P010; + }else if(m_bitDepth==16){ + fmt=AV_PIX_FMT_P016; + } + m_frame = yang_av_frame_alloc(); + + int32_t numBytes = yang_av_image_get_buffer_size(fmt, m_width,m_height, 1); + + buffer = (uint8_t*) yang_av_malloc(numBytes * sizeof(uint8_t)); + + + if (usingHw) { + yang_av_image_fill_arrays(m_frame->data, m_frame->linesize, buffer, + fmt, m_width, m_height, 1); + yang_av_init_packet(&packet); + frame_mem_gpu = yang_av_frame_alloc(); + frame_mem_gpu->format = m_codecCtx->pix_fmt; + frame_mem_gpu->width = m_codecCtx->width; + frame_mem_gpu->height = m_codecCtx->height; + ret = yang_av_hwframe_get_buffer(m_codecCtx->hw_frames_ctx,frame_mem_gpu, 0); + if (ret < 0) + printf("\nERROR:av_hwframe_get_buffer failure!\n"); + } else { + yang_av_image_fill_arrays(m_frame->data, m_frame->linesize, buffer, + fmt, m_width, m_height, 1); + yang_av_init_packet(&packet); + } + + m_isInit = 1; +} + +void YangH2645VideoDecoderFfmpeg::init() { + //AVCodecID codec_id = AV_CODEC_ID_H264; + // av_register_all(); + // avcodec_register_all(); + // avcodec_register(AV_CODEC_ID_H264); +#if Yang_Ffmpeg_UsingSo + m_lib.loadObject("libavcodec"); + m_lib1.loadObject("libavutil"); + loadLib(); +#endif + + if(usingHw){ + if(m_encDecType==Yang_VED_264){ + if(m_context->videoDecHwType==YangV_Hw_Intel) m_codec = yang_avcodec_find_decoder_by_name("h264_vaapi");//avcodec_find_encoder(AV_CODEC_ID_H264); + if(m_context->videoDecHwType==YangV_Hw_Nvdia) m_codec = yang_avcodec_find_decoder_by_name("h264_nvdec");//h264_cuvid + if(m_context->videoDecHwType==YangV_Hw_Android) m_codec = yang_avcodec_find_decoder_by_name("h264_mediacodec"); + }else if(m_encDecType==Yang_VED_265){ + if(m_context->videoDecHwType==YangV_Hw_Intel) m_codec = yang_avcodec_find_decoder_by_name("hevc_vaapi"); + if(m_context->videoDecHwType==YangV_Hw_Nvdia) m_codec = yang_avcodec_find_decoder_by_name("hevc_nvdec"); + if(m_context->videoDecHwType==YangV_Hw_Android) m_codec = yang_avcodec_find_decoder_by_name("hevc_mediacodec"); + } + }else{ + if(m_encDecType==Yang_VED_264){ + m_codec = yang_avcodec_find_decoder(AV_CODEC_ID_H264); + }else if(m_encDecType==Yang_VED_265){ + m_codec = yang_avcodec_find_decoder(AV_CODEC_ID_H265); + } + } + m_codecCtx = yang_avcodec_alloc_context3(m_codec); +} + +int32_t YangH2645VideoDecoderFfmpeg::decode(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback){ + if (usingHw) + return decode_2(videoFrame,yuvtype,pcallback); + else + return decode_1(videoFrame,yuvtype,pcallback); + +} +int32_t YangH2645VideoDecoderFfmpeg::decode_1(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback) { + packet.data = videoFrame->payload; + packet.size = videoFrame->nb; + + ret = yang_avcodec_send_packet(m_codecCtx, &packet); + if (ret != 0) { + m_bufLen= 0; + if(ret==AVERROR(EAGAIN)) { + yang_error("avcodec_send_packet EAGAIN error:input is not accepted in the current state"); + return 2; + } + if(ret==AVERROR_EOF){ + yang_error("avcodec_send_packet AVERROR_EOF error: the decoder has been flushed, and no new packets can be sent to it "); + return 2; + } + if(ret==AVERROR_INVALIDDATA){ + yang_error("avcodec_send_packet AVERROR_INVALIDDATA"); + yang_trace("\n%d:",videoFrame->nb); + for(int i=0;i<100;i++) yang_trace("%02x,",videoFrame->payload[i]); + return 2; + } + yang_error("avcodec_send_packet err(%d)",ret); + yang_trace("\n"); + for(int i=0;i<100;i++) yang_trace("%02x,",videoFrame->payload[i]); + return 2; + } + //avcodec_receive_frame + while(ret==0){ + ret = yang_avcodec_receive_frame(m_codecCtx, m_frame); + + if (ret != 0) { + m_bufLen = 0; + if(ret==AVERROR_EOF){ + yang_avcodec_flush_buffers(m_codecCtx); + return ret; + } + if(ret==AVERROR(EAGAIN)) { + // yang_error("avcodec_receive_packet err EAGAIN"); + return ret; + } + + yang_error("avcodec_receive_packet err(%d)",ret); + return 1; + } + + for (int i = 0; i < m_height; i++) { + memcpy(m_buffer + i * m_width, m_frame->data[0] + i * m_frame->linesize[0], m_width); + } + for (int i = 0; i < m_height / 2; i++) { + memcpy(m_buffer + yLen+i * m_width / 2,m_frame->data[1] + i * m_frame->linesize[1], m_width / 2); + } + for (int i = 0; i < m_height / 2; i++) { + memcpy(m_buffer + yLen+ uLen+ i * m_width / 2, m_frame->data[2] + i * m_frame->linesize[2], m_width / 2); + } + m_bufLen= allLen; + videoFrame->payload=m_buffer; + videoFrame->nb=m_bufLen; + if(pcallback) pcallback->onVideoData(videoFrame); + } + return Yang_Ok; +} +int32_t YangH2645VideoDecoderFfmpeg::decode_2(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback) { + packet.data = videoFrame->payload; + packet.size = videoFrame->nb; + ret = yang_avcodec_send_packet(m_codecCtx, &packet); + if (ret != 0) { + m_bufLen= 0; + return 2; + } + while(ret==0){ + ret = yang_avcodec_receive_frame(m_codecCtx, frame_mem_gpu); + + if (ret != 0) { + m_bufLen = 0; + if(ret==AVERROR_EOF){ + yang_avcodec_flush_buffers(m_codecCtx); + return ret; + } + if(ret==AVERROR(EAGAIN)) { + // yang_error("avcodec_receive_packet err EAGAIN"); + return ret; + } + + yang_error("avcodec_receive_packet err(%d)",ret); + return 1; + } + yang_av_hwframe_transfer_data(m_frame, frame_mem_gpu, 0); + //memcpy(m_buffer, m_frame->data[0], yLen); + // if(yuvtype==YangYv12){ + // memcpy(m_buffer + yLen, m_frame->data[1], uLen); + // memcpy(m_buffer + yLen + uLen, m_frame->data[1]+uLen, uLen); + // }else if(yuvtype==YangI420){ + // memcpy(m_buffer + yLen, m_frame->data[1]+uLen, uLen); + // memcpy(m_buffer + yLen + uLen, m_frame->data[1], uLen); + // } + //memcpy(m_buffer + yLen, m_frame->data[1], uLen * 2); + for (int i = 0; i < m_height; i++) { + memcpy(m_buffer + i * m_width, m_frame->data[0] + i * m_frame->linesize[0], m_width); + } + for (int i = 0; i < m_height / 2; i++) { + memcpy(m_buffer + yLen+i * m_width / 2,m_frame->data[1] + i * m_frame->linesize[1], m_width / 2); + } + for (int i = 0; i < m_height / 2; i++) { + memcpy(m_buffer + yLen+ uLen+ i * m_width / 2, m_frame->data[2] + i * m_frame->linesize[2], m_width / 2); + } + m_bufLen = allLen; + videoFrame->payload=m_buffer; + videoFrame->nb=m_bufLen; + if(pcallback) pcallback->onVideoData(videoFrame); + } + return Yang_Ok; +} +void YangH2645VideoDecoderFfmpeg::decode_close() { + if (usingHw) { + yang_av_buffer_unref(&hw_device_ctx); + yang_av_frame_free(&frame_mem_gpu); + } + + yang_av_frame_free(&m_frame); + m_frame = NULL; + if (m_codecCtx) { + yang_avcodec_close(m_codecCtx); + yang_av_free(m_codecCtx); + } + + m_codecCtx = NULL; + if (buffer) + yang_av_free(buffer); + buffer = NULL; + +} + + diff --git a/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.h b/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..cac8a0a16c84ef3d334160d846783c85fd6d1a78 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH2645VideoDecoderFfmpeg.h @@ -0,0 +1,125 @@ +/* + * YangH2645VideoDecoderFfmpeg.h + * + * Created on: 2019年9月20日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGH2645VIDEODECODERFFMPEG_H_ +#define YANGDECODER_SRC_YANGH2645VIDEODECODERFFMPEG_H_ +#include +#include +#include "yangdecoder/YangVideoDecoder.h" +#include "yangutil/sys/YangLoadLib.h" +#include "YangH264Header.h" +extern "C" { +#include "libavcodec/avcodec.h" +//#include "libavformat/avformat.h" +#include "libavutil/avutil.h" +#include "libavutil/imgutils.h" +} + + +class YangH2645VideoDecoderFfmpeg: public YangVideoDecoder { +public: + YangH2645VideoDecoderFfmpeg(YangVideoInfo *pcontext, + YangVideoEncDecType pencdectype); + virtual ~YangH2645VideoDecoderFfmpeg(); + void parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, int32_t *phei, int32_t *pfps); + void init(); + int32_t decode(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback); + //int32_t decode( int32_t isIframe, uint8_t *pData, int32_t nSize, uint8_t *dest, int32_t *pnFrameReturned); + void decode_close(); + static YangVideoHwType g_hwType; +protected: + uint8_t* m_buffer; + int32_t m_bufLen; +private: + YangVideoEncDecType m_encDecType; + YangVideoInfo *m_context; + int32_t m_bitDepth; + int32_t ret; + AVCodec *m_codec; + AVCodecContext *m_codecCtx = NULL; + AVPacket packet; + AVFrame *m_frame; + int32_t m_width, m_height; + int32_t yLen; + int32_t uLen; + int32_t allLen; + uint8_t *buffer = NULL; + int32_t usingHw; + AVBufferRef *hw_device_ctx; + AVFrame *frame_mem_gpu; + + int32_t decode_1(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback); + int32_t decode_2(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback); + int32_t set_hwframe_ctx(AVPixelFormat ctxformat, AVPixelFormat swformat, + YangVideoInfo *yvp, AVCodecContext *ctx, + AVBufferRef *hw_device_ctx, int32_t pwid, int32_t phei); + + void parseHeader(uint8_t *p, int32_t pLen, int32_t *pwid, int32_t *phei, int32_t *pfps); + +#if Yang_Ffmpeg_UsingSo + YangLoadLib m_lib, m_lib1; + void loadLib(); + void unloadLib(); + AVBufferRef* (*yang_av_hwframe_ctx_alloc)(AVBufferRef *device_ctx); + int32_t (*yang_av_hwframe_ctx_init)(AVBufferRef *ref); + AVBufferRef* (*yang_av_buffer_ref)(AVBufferRef *buf); + void* (*yang_av_malloc)(size_t size); + int32_t (*yang_av_hwdevice_ctx_create)(AVBufferRef **device_ctx, + enum AVHWDeviceType type, const char *device, AVDictionary *opts, + int32_t flags); + int32_t (*yang_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, + AVDictionary **options); + AVFrame* (*yang_av_frame_alloc)(void); + int32_t (*yang_av_image_get_buffer_size)(enum AVPixelFormat pix_fmt, int32_t width, + int32_t height, int32_t align); + int32_t (*yang_av_image_fill_arrays)(uint8_t *dst_data[4], int32_t dst_linesize[4], + const uint8_t *src, enum AVPixelFormat pix_fmt, int32_t width, + int32_t height, int32_t align); + void (*yang_av_buffer_unref)(AVBufferRef **buf); + void (*yang_av_init_packet)(AVPacket *pkt); + int32_t (*yang_av_hwframe_get_buffer)(AVBufferRef *hwframe_ctx, AVFrame *frame, + int32_t flags); + AVCodec* (*yang_avcodec_find_decoder)(enum AVCodecID id); + AVCodec* (*yang_avcodec_find_decoder_by_name)(const char *name); + AVCodecContext* (*yang_avcodec_alloc_context3)(const AVCodec *codec); + int32_t (*yang_avcodec_send_packet)(AVCodecContext *avctx, + const AVPacket *avpkt); + int32_t (*yang_avcodec_receive_frame)(AVCodecContext *avctx, AVFrame *frame); + int32_t (*yang_av_hwframe_transfer_data)(AVFrame *dst, const AVFrame *src, + int32_t flags); + void (*yang_avcodec_flush_buffers)(AVCodecContext *avctx); + void (*yang_av_frame_free)(AVFrame **frame); + void (*yang_av_free)(void *ptr); + int32_t (*yang_avcodec_close)(AVCodecContext *avctx); +#else + #define yang_avcodec_find_decoder_by_name avcodec_find_decoder_by_name + #define yang_av_free av_free + #define yang_av_hwframe_ctx_alloc av_hwframe_ctx_alloc + #define yang_av_hwframe_ctx_init av_hwframe_ctx_init + #define yang_av_buffer_ref av_buffer_ref + #define yang_av_malloc av_malloc + #define yang_av_hwdevice_ctx_create av_hwdevice_ctx_create + #define yang_avcodec_open2 avcodec_open2 + #define yang_av_frame_alloc av_frame_alloc + #define yang_av_image_get_buffer_size av_image_get_buffer_size + #define yang_av_image_fill_arrays av_image_fill_arrays + #define yang_av_init_packet av_init_packet + #define yang_av_hwframe_get_buffer av_hwframe_get_buffer + #define yang_avcodec_find_decoder avcodec_find_decoder + #define yang_avcodec_alloc_context3 avcodec_alloc_context3 + #define yang_avcodec_send_packet avcodec_send_packet + #define yang_avcodec_receive_frame avcodec_receive_frame + #define yang_av_hwframe_transfer_data av_hwframe_transfer_data + #define yang_avcodec_flush_buffers avcodec_flush_buffers + #define yang_av_frame_free av_frame_free + #define yang_avcodec_close avcodec_close + #define yang_av_buffer_unref av_buffer_unref +#endif + +}; + +#endif /* YANGDECODER_SRC_YANGH2645VIDEODECODERFFMPEG_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangH264Dec.h b/libyangrtc2/src/yangdecoder/YangH264Dec.h new file mode 100644 index 0000000000000000000000000000000000000000..bce5847f96991dac0ed8f570c1a1848471cb58c5 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264Dec.h @@ -0,0 +1,19 @@ +#ifndef SRC_YANGH264DEC_H_ +#define SRC_YANGH264DEC_H_ +#include +struct YangH264DecContext { + int32_t m_width, m_height, m_fps; + int32_t yLen; + int32_t uLen; + int32_t allLen; + void *context; +}; + +struct YangH264DecContext* getYangH264DecContext(); +void init_H264DecCont(struct YangH264DecContext *cont, uint8_t *headers, + int32_t headerLen); +int32_t decode(struct YangH264DecContext *cont, int32_t isIframe, uint8_t *pData, + int32_t nSize, uint8_t *dest, int32_t *pnFrameReturned); +void decode_close(struct YangH264DecContext *cont); + +#endif /* SRC_YANGH264DEC_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.cpp b/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8650b96754adfebcdc1d775f89d58dbaaebf797 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.cpp @@ -0,0 +1,89 @@ +/* + * YangH264DecoderSoft.cpp + * + * Created on: 2020年9月28日 + * Author: yang + */ + +#include "YangH264DecoderSoft.h" +#include +#include +YangH264DecoderSoft::YangH264DecoderSoft() { + m_lib.loadObject("libyangh264dec"); + context=NULL; + m_buffer=NULL; + m_bufLen=0; + yang_getYangH264DecContext=(struct YangH264DecContext *(*)())m_lib.loadFunction("getYangH264DecContext"); + yang_init_H264DecCont=(void (*)(struct YangH264DecContext *cont,uint8_t *headers, int32_t headerLen))m_lib.loadFunction("init_H264DecCont"); + yang_decode=(int32_t (*)(struct YangH264DecContext *cont,int32_t isIframe,uint8_t *pData, int32_t nSize,enum YangYuvType yuvType, + uint8_t *dest, int32_t *pnFrameReturned))m_lib.loadFunction("decode"); + yang_decode_close=(void (*)(struct YangH264DecContext *cont))m_lib.loadFunction("decode_close"); +} + +YangH264DecoderSoft::~YangH264DecoderSoft() { + + //if(m_dec) delete m_dec; + if(m_buffer) delete[] m_buffer; + m_buffer=NULL; + if(context){ + yang_decode_close(context); + context=NULL; + } + yang_getYangH264DecContext=NULL; + yang_init_H264DecCont=NULL; + yang_decode=NULL; + yang_decode_close=NULL; + m_lib.unloadObject(); + +} + +void YangH264DecoderSoft::getH264RtmpHeader(uint8_t *buf, uint8_t *src,int32_t *hLen) { + + int32_t spsLen = *(buf + 12) + 1; + uint8_t *spsStart = buf + 13; + + int32_t ppsLen = *(spsStart + spsLen + 1) + 1; + uint8_t *ppsStart = buf + 13 + spsLen + 2; + *(src + 3) = 0x01; + memcpy(src + 4, spsStart, spsLen); + *(src + 4 + spsLen + 3) = 0x01; + memcpy(src + 4 + spsLen + 4, ppsStart, ppsLen); + *hLen = 8 + spsLen + ppsLen; + /**printf("\n************************************sps*******len=%d\n",spsLen); + for(int32_t i=0;im_width; + *phei=context->m_height; + *pfps=context->m_fps; + if(!m_buffer) m_buffer=new uint8_t[context->m_width*context->m_height*3/2]; + //printf("\ndecode wid=%d,hei=%d,fps=%d....................\n",*pwid,*phei,*pfps); +} + void YangH264DecoderSoft::init(){ + if(context==NULL) context=yang_getYangH264DecContext(); + } + int32_t YangH264DecoderSoft::decode(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback){ + int32_t ret=0; + + if(context) ret=yang_decode(context,1,videoFrame->payload,videoFrame->nb,yuvtype,m_buffer,&m_bufLen); + videoFrame->payload=m_buffer; + videoFrame->nb=m_bufLen; + if(pcallback&&m_bufLen) pcallback->onVideoData(videoFrame); + return ret; + } + + //int32_t YangH264DecoderSoft::decode(int32_t isIframe, uint8_t *pData, int32_t nSize, uint8_t *dest, int32_t *pnFrameReturned){ + //if(context) return yang_decode(context,isIframe,pData,nSize,dest,pnFrameReturned); + //printf("\n*****decodesize===%d....",*pnFrameReturned); + //return 0; + //} diff --git a/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.h b/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.h new file mode 100644 index 0000000000000000000000000000000000000000..ed6967fa02cf75cdd8e5a44d5c8c54853670d953 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264DecoderSoft.h @@ -0,0 +1,40 @@ +/* + * YangH264DecoderSoft.h + * + * Created on: 2020年9月28日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGH264DECODERSOFT_H_ +#define YANGDECODER_SRC_YANGH264DECODERSOFT_H_ +#include "stdint.h" +#include +#include +#include "YangH264Dec.h" + +class YangH264DecoderSoft: public YangVideoDecoder { +public: + YangH264DecoderSoft(); + virtual ~YangH264DecoderSoft(); + void parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, int32_t *phei, int32_t *pfps); + void init(); + int32_t decode(YangFrame* videoFrame,YangYuvType yuvtype,YangDecoderCallback* pcallback); + //int32_t decode(int32_t isIframe, uint8_t *pData, int32_t nSize, uint8_t *dest,int32_t *pnFrameReturned); +private: + uint8_t* m_buffer; + int32_t m_bufLen; +private: + struct YangH264DecContext *context; + void getH264RtmpHeader(uint8_t *buf, uint8_t *src, int32_t *hLen); + YangLoadLib m_lib; + + struct YangH264DecContext* (*yang_getYangH264DecContext)(); + void (*yang_init_H264DecCont)(struct YangH264DecContext *cont, + uint8_t *headers, int32_t headerLen); + int32_t (*yang_decode)(struct YangH264DecContext *cont, int32_t isIframe, + uint8_t *pData, int32_t nSize, enum YangYuvType pyuvType,uint8_t *dest, + int32_t *pnFrameReturned); + void (*yang_decode_close)(struct YangH264DecContext *cont); +}; + +#endif /* YANGDECODER_SRC_YANGH264DECODERSOFT_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangH264DecoderSoftFactory.h b/libyangrtc2/src/yangdecoder/YangH264DecoderSoftFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..a90e0e6542c8f5ba807d2c1f89e0336a7c96eae8 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264DecoderSoftFactory.h @@ -0,0 +1,19 @@ +/* + * YangH264DecoderSoftFactory.h + * + * Created on: 2019-08-30 + * Author: yang + */ + +#ifndef SRC_YANGH264DECODERSOFTFACTORY_H_ +#define SRC_YANGH264DECODERSOFTFACTORY_H_ +#include "yangdecoder/YangVideoDecoder.h" +YangVideoDecoder* yang_createH264Decoder(); +class YangH264DecoderSoftFactory { +public: + YangH264DecoderSoftFactory(); + virtual ~YangH264DecoderSoftFactory(); + YangVideoDecoder* createH264Decoder(); +}; + +#endif /* SRC_YANGH264DECODERSOFTFACTORY_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangH264Header.cpp b/libyangrtc2/src/yangdecoder/YangH264Header.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0cc76f0143fe28590213cb55ddf42832a87ef942 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264Header.cpp @@ -0,0 +1,657 @@ +/* + * YangH264Header.cpp + * + * Created on: 2019年8月17日 + * Author: yang + */ + +#include "YangH264Header1.h" + +YangH264Header::YangH264Header() { + // TODO Auto-generated constructor stub + memset(&m_sps, 0, sizeof(m_sps)); + memset(&m_pps, 0, sizeof(m_pps)); + memset(&packet, 0, sizeof(packet)); + //packet. + nal = (YangNAL*) malloc(sizeof(YangNAL)); + rbsp = (YangRBSP*) malloc(sizeof(YangRBSP)); + rbsp->rbsp_buffer = (uint8_t*) malloc(MAX_MBPAIR_SIZE); + nal->rbsp_buffer = rbsp->rbsp_buffer; + packet.nals = nal; + width = 0; + height = 0; + sl = NULL; + fps=10; +} + + +YangH264Header::~YangH264Header() { + // TODO Auto-generated destructor stub +} + +int32_t YangH264Header::h264_decode_seq_parameter_set(uint8_t *buf, int32_t len) { + //printf("\n%02x,%02x**ind=%d,size_in_bits=%d*plus8=%d*picture_parameter_set\n",*gb->buffer,*(gb->buffer+1), + //gb->index,gb->size_in_bits,gb->size_in_bits_plus8); + /**printf("***************spslen=%d\n",len); + for(int32_t i=0;igb; + int32_t profile_idc, level_idc, constraint_set_flags = 0; + uint32_t sps_id; + int32_t i, log2_max_frame_num_minus4; + Yang_SPS *sps = &m_sps; + int32_t ret; + /** sps->data_size = gb->buffer_end - gb->buffer; + if (sps->data_size > sizeof(sps->data)) { + // av_log(avctx, AV_LOG_DEBUG, "Truncating likely oversized SPS\n"); + sps->data_size = sizeof(sps->data); + } + memcpy(sps->data, gb->buffer, sps->data_size);**/ + + profile_idc = yang_get_bits(gb, 8); + constraint_set_flags |= yang_get_bits1(gb) << 0; // constraint_set0_flag + constraint_set_flags |= yang_get_bits1(gb) << 1; // constraint_set1_flag + constraint_set_flags |= yang_get_bits1(gb) << 2; // constraint_set2_flag + constraint_set_flags |= yang_get_bits1(gb) << 3; // constraint_set3_flag + constraint_set_flags |= yang_get_bits1(gb) << 4; // constraint_set4_flag + constraint_set_flags |= yang_get_bits1(gb) << 5; // constraint_set5_flag + yang_skip_bits(gb, 2); // reserved_zero_2bits + level_idc = yang_get_bits(gb, 8); + sps_id = yang_get_ue_golomb_31(gb); + sps->sps_id = sps_id; + sps->time_offset_length = 24; + sps->profile_idc = profile_idc; + sps->constraint_set_flags = constraint_set_flags; + sps->level_idc = level_idc; + sps->full_range = -1; + + memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4)); + memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8)); + sps->scaling_matrix_present = 0; + sps->colorspace = Yang_SPC_UNSPECIFIED; //2; //AVCOL_SPC_UNSPECIFIED + + if (sps->profile_idc == 100 || // High profile + sps->profile_idc == 110 || // High10 profile + sps->profile_idc == 122 || // High422 profile + sps->profile_idc == 244 || // High444 Predictive profile + sps->profile_idc == 44 || // Cavlc444 profile + sps->profile_idc == 83 || // Scalable Constrained High profile (SVC) + sps->profile_idc == 86 || // Scalable High Intra profile (SVC) + sps->profile_idc == 118 || // Stereo High profile (MVC) + sps->profile_idc == 128 || // Multiview High profile (MVC) + sps->profile_idc == 138 || // Multiview Depth High profile (MVCD) + sps->profile_idc == 144) { // old High444 profile + sps->chroma_format_idc = yang_get_ue_golomb_31(gb); + if (sps->chroma_format_idc == 3) { + sps->residual_color_transform_flag = yang_get_bits1(gb); + + } + sps->bit_depth_luma = yang_get_ue_golomb(gb) + 8; + sps->bit_depth_chroma = yang_get_ue_golomb(gb) + 8; + sps->transform_bypass = yang_get_bits1(gb); + ret = yang_decode_scaling_matrices(gb, sps, NULL, 1, + sps->scaling_matrix4, sps->scaling_matrix8); + + sps->scaling_matrix_present |= ret; + } else { + sps->chroma_format_idc = 1; + sps->bit_depth_luma = 8; + sps->bit_depth_chroma = 8; + } + + log2_max_frame_num_minus4 = yang_get_ue_golomb(gb); + + sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4; + + sps->poc_type = yang_get_ue_golomb_31(gb); + + if (sps->poc_type == 0) { // FIXME #define + unsigned t = yang_get_ue_golomb(gb); + sps->log2_max_poc_lsb = t + 4; + } else if (sps->poc_type == 1) { // FIXME #define + sps->delta_pic_order_always_zero_flag = yang_get_bits1(gb); + sps->offset_for_non_ref_pic = yang_get_se_golomb(gb); + sps->offset_for_top_to_bottom_field = yang_get_se_golomb(gb); + sps->poc_cycle_length = yang_get_ue_golomb(gb); + for (i = 0; i < sps->poc_cycle_length; i++) + sps->offset_for_ref_frame[i] = yang_get_se_golomb(gb); + } + + sps->ref_frame_count = yang_get_ue_golomb_31(gb); + sps->gaps_in_frame_num_allowed_flag = yang_get_bits1(gb); + sps->mb_width = yang_get_ue_golomb(gb) + 1; + sps->mb_height = yang_get_ue_golomb(gb) + 1; + width = sps->mb_width * 16; + height = sps->mb_height * 16; + //if (width == 1920) height = 1080; + //if (width == 320) height = 240; + if (width > 3840) width = 3840; + if (width <= 0) width = 1280; + if (height > 2160) height = 2160; + if (height <= 0) height = 720; + + sps->frame_mbs_only_flag = yang_get_bits1(gb); + + sps->mb_height *= 2 - sps->frame_mbs_only_flag; + + if (!sps->frame_mbs_only_flag) + sps->mb_aff = yang_get_bits1(gb); + else + sps->mb_aff = 0; + + sps->direct_8x8_inference_flag = yang_get_bits1(gb); + sps->crop = yang_get_bits1(gb); + uint32_t crop_left = 0; + uint32_t crop_right = 0; + uint32_t crop_top = 0; + uint32_t crop_bottom = 0; + if (sps->crop) { + crop_left = yang_get_ue_golomb(gb); + crop_right = yang_get_ue_golomb(gb); + crop_top = yang_get_ue_golomb(gb); + crop_bottom = yang_get_ue_golomb(gb); + // int32_t width = 16 * sps->mb_width; + //int32_t height = 16 * sps->mb_height; + sps->crop_left = 0; + sps->crop_right = 0; + sps->crop_top = 0; + sps->crop_bottom = 0; + + + int32_t vsub = (sps->chroma_format_idc == 1) ? 1 : 0; + int32_t hsub = (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ?1 : 0; + int32_t step_x = 1 << hsub; + int32_t step_y = (2 - sps->frame_mbs_only_flag) << vsub; + sps->crop_left = crop_left * step_x; + sps->crop_right = crop_right * step_x; + sps->crop_top = crop_top * step_y; + sps->crop_bottom = crop_bottom * step_y; + } else { + sps->crop_left = 0; + sps->crop_right = 0; + sps->crop_top = 0; + sps->crop_bottom = 0; + } + //printf("\n**************frame_mbs_only_flag=%d,sps->crop=%d,c_left=%d,c_right=%d,c_top=%d,c_bottom=%d\n", + // sps->frame_mbs_only_flag, sps->crop, sps->crop_left, sps->crop_right,sps->crop_top, sps->crop_bottom); + width = width - (sps->crop_right + sps->crop_left); + height = height - (sps->crop_top + sps->crop_bottom); + sps->vui_parameters_present_flag = yang_get_bits1(gb); + if (sps->vui_parameters_present_flag) { + //int32_t ret = + yang_decode_vui_parameters(gb, sps); + } + if(sps->timing_info_present_flag){ + fps=sps->time_scale/(sps->num_units_in_tick); + if(sps->fixed_frame_rate_flag) fps=fps/2; + // printf("\n***********fps=%d\n",fps); + } + /* if the maximum delay is not stored in the SPS, derive it based on the + * level */ + /** if (!sps->bitstream_restriction_flag && + (sps->ref_frame_count || avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)) { + sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + for (i = 0; i < FF_ARRAY_ELEMS(level_max_dpb_mbs); i++) { + if (level_max_dpb_mbs[i][0] == sps->level_idc) { + sps->num_reorder_frames = FFMIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), + sps->num_reorder_frames); + break; + } + } + }**/ + + if (!sps->sar.den) + sps->sar.den = 1; + return 0; +} + +int32_t YangH264Header::h264_decode_picture_parameter_set(uint8_t *buf, int32_t len) { + //printf("\n%02x,%02x**ind=%d,size_in_bits=%d*plus8=%d*picture_parameter_set\n",*gb->buffer,*(gb->buffer+1), + //gb->index,gb->size_in_bits,gb->size_in_bits_plus8); + yang_packet_split(buf, len, 1, 1); + YangGetBitContext *gb = &packet.nals->gb; + const Yang_SPS *sps=&m_sps; + uint32_t pps_id = yang_get_ue_golomb(gb); + Yang_PPS *pps = &m_pps; + int32_t qp_bd_offset=0; + int32_t bits_left=0; + int32_t ret=0; + + /** pps->data_size = gb->buffer_end - gb->buffer; + if (pps->data_size > sizeof(pps->data)) { + // av_log(avctx, AV_LOG_DEBUG, "Truncating likely oversized PPS (%"SIZE_SPECIFIER" > %"SIZE_SPECIFIER")\n", pps->data_size, sizeof(pps->data)); + pps->data_size = sizeof(pps->data); + } + memcpy(pps->data, gb->buffer, pps->data_size);**/ + + pps->sps_id = yang_get_ue_golomb_31(gb); + pps->cabac = yang_get_bits1(gb); + pps->pic_order_present = yang_get_bits1(gb); + pps->slice_group_count = yang_get_ue_golomb(gb) + 1; + if (pps->slice_group_count > 1) { + pps->mb_slice_group_map_type = yang_get_ue_golomb(gb); + } + pps->ref_count[0] = yang_get_ue_golomb(gb) + 1; + pps->ref_count[1] = yang_get_ue_golomb(gb) + 1; + qp_bd_offset = 6 * (sps->bit_depth_luma - 8); + + pps->weighted_pred = yang_get_bits1(gb); + pps->weighted_bipred_idc = yang_get_bits(gb, 2); + pps->init_qp = yang_get_se_golomb(gb) + 26U + qp_bd_offset; + pps->init_qs = yang_get_se_golomb(gb) + 26U + qp_bd_offset; + pps->chroma_qp_index_offset[0] = yang_get_se_golomb(gb); + if (pps->chroma_qp_index_offset[0] < -12 + || pps->chroma_qp_index_offset[0] > 12) { + ret = YangERROR_INVALIDDATA; + } + + pps->deblocking_filter_parameters_present = yang_get_bits1(gb); + pps->constrained_intra_pred = yang_get_bits1(gb); + pps->redundant_pic_cnt_present = yang_get_bits1(gb); + + pps->transform_8x8_mode = 0; + memcpy(pps->scaling_matrix4, sps->scaling_matrix4, + sizeof(pps->scaling_matrix4)); + memcpy(pps->scaling_matrix8, sps->scaling_matrix8, + sizeof(pps->scaling_matrix8)); + + bits_left = len - yang_get_bits_count(gb); + /** if (bits_left > 0 && more_rbsp_data_in_pps(sps, avctx)) { + pps->transform_8x8_mode = yang_get_bits1(gb); + ret = yang_decode_scaling_matrices(gb, sps, pps, 0, + pps->scaling_matrix4, pps->scaling_matrix8); + + // second_chroma_qp_index_offset + pps->chroma_qp_index_offset[1] = yang_get_se_golomb(gb); + if (pps->chroma_qp_index_offset[1] < -12 || pps->chroma_qp_index_offset[1] > 12) { + ret = AVERROR_INVALIDDATA; + + } + } else { + pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0]; + }**/ + pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0]; + yang_build_qp_table(pps, 0, pps->chroma_qp_index_offset[0], + sps->bit_depth_luma); + yang_build_qp_table(pps, 1, pps->chroma_qp_index_offset[1], + sps->bit_depth_luma); + + yang_init_dequant_tables(pps, sps); + + if (pps->chroma_qp_index_offset[0] != pps->chroma_qp_index_offset[1]) + pps->chroma_qp_diff = 1; + + return 0; + +} + +int32_t YangH264Header::yang_packet_split(uint8_t *buf, int32_t length, int32_t isH264, + int32_t small_padding) { + //GetByteContext bc; + int32_t consumed, ret = 0; + + // nal->data=buf; + // nal->size=length; + YangPacket *pkt = &packet; + + // if (!pkt->rbsp.rbsp_buffer) + // return AVERROR(ENOMEM); + + pkt->rbsp.rbsp_buffer_size = 0; + pkt->nb_nals = 0; + + consumed = yang_extract_rbsp(buf, length, small_padding); + ret = yang_init_get_bits(&nal->gb, nal->data, nal->size << 3); + if (ret < 0) + return ret; + + // if (isH264) + ret = yang_parse_nal_header(nal); + // else + // ret = h264_parse_nal_header(nal, logctx); + if (ret <= 0 || nal->size <= 0 || nal->size_bits <= 0) { + + packet.nb_nals--; + } + + return 0; +} + +int32_t YangH264Header::yang_packet_split1(uint8_t *buf, int32_t length, int32_t isH264, + int32_t small_padding) { + //GetByteContext bc; + int32_t ret = 0; + YangPacket *pkt = &packet; + pkt->rbsp.rbsp_buffer_size = 0; + pkt->nb_nals = 0; + nal->data = buf; + nal->raw_data = buf; + nal->size = length; + nal->raw_size = length; + ret = yang_init_get_bits(&nal->gb, nal->data, nal->size << 3); + if (ret < 0) + return ret; + + // if (isH264) + ret = yang_parse_nal_header(nal); + // else + // ret = h264_parse_nal_header(nal, logctx); + if (ret <= 0 || nal->size <= 0 || nal->size_bits <= 0) { + + packet.nb_nals--; + } + + return 0; +} +int32_t YangH264Header::yang_extract_rbsp(uint8_t *src, int32_t length, + int32_t small_padding) { + int32_t i, si, di; + uint8_t *dst; + + packet.nals->skipped_bytes = 0; +#define STARTCODE_TEST \ + if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ + if (src[i + 2] != 3 && src[i + 2] != 0) { \ + /* startcode, so we must be past the end */ \ + length = i; \ + } \ + break; \ + } +#if HAVE_FAST_UNALIGNED +#define FIND_FIRST_ZERO \ + if (i > 0 && !src[i]) \ + i--; \ + while (src[i]) \ + i++ +#if HAVE_FAST_64BIT + for (i = 0; i + 1 < length; i += 9) { + if (!((~AV_RN64(src + i) & + (AV_RN64(src + i) - 0x0100010001000101ULL)) & + 0x8000800080008080ULL)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 7; + } +#else + for (i = 0; i + 1 < length; i += 5) { + if (!((~AV_RN32(src + i) & + (AV_RN32(src + i) - 0x01000101U)) & + 0x80008080U)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 3; + } +#endif /* HAVE_FAST_64BIT */ +#else + for (i = 0; i + 1 < length; i += 2) { + if (src[i]) + continue; + if (i > 0 && src[i - 1] == 0) + i--; + STARTCODE_TEST; + } +#endif /* HAVE_FAST_UNALIGNED */ + + if (i >= length - 1 && small_padding) { // no escaped 0 + nal->data = src; + nal->raw_data = src; + nal->size = length; + nal->raw_size = length; + return length; + } else if (i > length) + i = length; + + // nal->rbsp_buffer = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; + dst = nal->rbsp_buffer; + + memcpy(dst, src, i); + si = di = i; + while (si + 2 < length) { + // remove escapes (very rare 1:2^22) + if (src[si + 2] > 3) { + dst[di++] = src[si++]; + dst[di++] = src[si++]; + } else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) { + if (src[si + 2] == 3) { // escape + dst[di++] = 0; + dst[di++] = 0; + si += 3; + /** + if (nal->skipped_bytes_pos) { + nal->skipped_bytes++; + if (nal->skipped_bytes_pos_size < nal->skipped_bytes) { + nal->skipped_bytes_pos_size *= 2; + // av_assert0(nal->skipped_bytes_pos_size >= nal->skipped_bytes); + // av_reallocp_array(&nal->skipped_bytes_pos, nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos)); + if (!nal->skipped_bytes_pos) { + nal->skipped_bytes_pos_size = 0; + return -12; + } + } + if (nal->skipped_bytes_pos) + nal->skipped_bytes_pos[nal->skipped_bytes-1] = di - 1; + }**/ + continue; + } else + // next start code + goto nsc; + } + + dst[di++] = src[si++]; + } + while (si < length) + dst[di++] = src[si++]; + + nsc: memset(dst + di, 0, Yang_INPUT_BUFFER_PADDING_SIZE); + + nal->data = dst; + nal->size = di; + nal->raw_data = src; + nal->raw_size = si; + packet.rbsp.rbsp_buffer_size += si; + + return si; +} + +void YangH264Header::parseRtmpHeader(uint8_t *buf) { + int32_t spsLen = *(buf + 12) + 1; + uint8_t * spsStart = buf + 13; + int32_t ppsLen = *(spsStart + spsLen + 1) + 1; + uint8_t *ppsStart = buf + 13 + spsLen + 2; + h264_decode_seq_parameter_set(spsStart, spsLen); + h264_decode_picture_parameter_set(ppsStart, ppsLen); + +} +int32_t YangH264Header::h264_slice_header_parse(uint8_t *buf, int32_t length) { + yang_packet_split1(buf, length, 1, 1); + Yang_SPS *sps = &m_sps; + Yang_PPS *pps = &m_pps; + if (sl == NULL) { + sl = (YangSliceContext*) malloc(sizeof(YangSliceContext)); + // sl->gb + } + yang_init_get_bits(&sl->gb, nal->data, nal->size << 3); + // yang_init_get_bits( &sl->gb, buf, length<<3); + sl->gb.index = 8; + + int32_t ret; + uint32_t slice_type, tmp, i; + int32_t field_pic_flag, bottom_field_flag; + //int32_t first_slice = 1; //sl == h->slice_ctx && !h->current_slice; + int32_t picture_structure; + + sl->first_mb_addr = yang_get_ue_golomb_long(&sl->gb); + + slice_type = yang_get_ue_golomb_31(&sl->gb); + + if (slice_type > 4) { + slice_type -= 5; + sl->slice_type_fixed = 1; + } else + sl->slice_type_fixed = 0; + + slice_type = yang_h264_golomb_to_pict_type[slice_type]; + sl->slice_type = slice_type; + sl->slice_type_nos = slice_type & 3; + + if (nal->type == Yang_NAL_IDR_SLICE + && sl->slice_type_nos != Yang_PICTURE_TYPE_I) { + printf("A non-intra slice in an IDR NAL unit.\n"); + return YangERROR_INVALIDDATA; + } + + sl->pps_id = yang_get_ue_golomb(&sl->gb); + if (sl->pps_id >= Yang_MAX_PPS_COUNT) { + printf("pps_id %u out of range\n", sl->pps_id); + return YangERROR_INVALIDDATA; + } + sl->frame_num = yang_get_bits(&sl->gb, sps->log2_max_frame_num); + sl->mb_mbaff = 0; + + if (sps->frame_mbs_only_flag) { + picture_structure = Yang_PICT_FRAME; + } else { + if (!sps->direct_8x8_inference_flag + && slice_type == Yang_PICTURE_TYPE_B) { + return -1; + } + field_pic_flag = yang_get_bits1(&sl->gb); + if (field_pic_flag) { + bottom_field_flag = yang_get_bits1(&sl->gb); + picture_structure = Yang_PICT_TOP_FIELD + bottom_field_flag; + } else { + picture_structure = Yang_PICT_FRAME; + } + } + sl->picture_structure = picture_structure; + sl->mb_field_decoding_flag = picture_structure != Yang_PICT_FRAME; + + if (picture_structure == Yang_PICT_FRAME) { + sl->curr_pic_num = sl->frame_num; + sl->max_pic_num = 1 << sps->log2_max_frame_num; + } else { + sl->curr_pic_num = 2 * sl->frame_num + 1; + sl->max_pic_num = 1 << (sps->log2_max_frame_num + 1); + } + + if (nal->type == Yang_NAL_IDR_SLICE) + yang_get_ue_golomb_long(&sl->gb); /* idr_pic_id */ + + if (sps->poc_type == 0) { + sl->poc_lsb = yang_get_bits(&sl->gb, sps->log2_max_poc_lsb); + + if (pps->pic_order_present == 1 && picture_structure == Yang_PICT_FRAME) + sl->delta_poc_bottom = yang_get_se_golomb(&sl->gb); + } + + if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) { + sl->delta_poc[0] = yang_get_se_golomb(&sl->gb); + + if (pps->pic_order_present == 1 && picture_structure == Yang_PICT_FRAME) + sl->delta_poc[1] = yang_get_se_golomb(&sl->gb); + } + + sl->redundant_pic_count = 0; + if (pps->redundant_pic_cnt_present) + sl->redundant_pic_count = yang_get_ue_golomb(&sl->gb); + + if (sl->slice_type_nos == Yang_PICTURE_TYPE_B) + sl->direct_spatial_mv_pred = yang_get_bits1(&sl->gb); + + ret = yang_h264_parse_ref_count(&sl->list_count, sl->ref_count, &sl->gb, + pps, sl->slice_type_nos, picture_structure); + if (ret < 0) + return ret; + + if (sl->slice_type_nos != Yang_PICTURE_TYPE_I) { + ret = yang_h264_decode_ref_pic_list_reordering(sl); + if (ret < 0) { + sl->ref_count[1] = sl->ref_count[0] = 0; + return ret; + } + } + + sl->pwt.use_weight = 0; + for (i = 0; i < 2; i++) { + sl->pwt.luma_weight_flag[i] = 0; + sl->pwt.chroma_weight_flag[i] = 0; + } + if ((pps->weighted_pred && sl->slice_type_nos == Yang_PICTURE_TYPE_P) + || (pps->weighted_bipred_idc == 1 + && sl->slice_type_nos == Yang_PICTURE_TYPE_B)) { + ret = yang_h264_pred_weight_table(&sl->gb, sps, sl->ref_count, + sl->slice_type_nos, &sl->pwt, picture_structure); + if (ret < 0) + return ret; + } + + sl->explicit_ref_marking = 0; + if (nal->ref_idc) { + ret = yang_h264_decode_ref_pic_marking(sl, &sl->gb, nal); + if (ret < 0) + return YangERROR_INVALIDDATA; + } + + if (sl->slice_type_nos != Yang_PICTURE_TYPE_I && pps->cabac) { + tmp = yang_get_ue_golomb_31(&sl->gb); + if (tmp > 2) { + return YangERROR_INVALIDDATA; + } + sl->cabac_init_idc = tmp; + } + + sl->last_qscale_diff = 0; + tmp = pps->init_qp + (unsigned) yang_get_se_golomb(&sl->gb); + if (tmp > 51 + 6 * (sps->bit_depth_luma - 8)) { + //av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); + return YangERROR_INVALIDDATA; + } + sl->qscale = tmp; + sl->chroma_qp[0] = get_chroma_qp(pps, 0, sl->qscale); + sl->chroma_qp[1] = get_chroma_qp(pps, 1, sl->qscale); + // FIXME qscale / qp ... stuff + if (sl->slice_type == Yang_PICTURE_TYPE_SP) + yang_get_bits1(&sl->gb); /* sp_for_switch_flag */ + if (sl->slice_type == Yang_PICTURE_TYPE_SP + || sl->slice_type == Yang_PICTURE_TYPE_SI) + yang_get_se_golomb(&sl->gb); /* slice_qs_delta */ + + sl->deblocking_filter = 1; + sl->slice_alpha_c0_offset = 0; + sl->slice_beta_offset = 0; + if (pps->deblocking_filter_parameters_present) { + tmp = yang_get_ue_golomb_31(&sl->gb); + if (tmp > 2) { + printf("deblocking_filter_idc %u out of range\n", tmp); + return YangERROR_INVALIDDATA; + } + sl->deblocking_filter = tmp; + if (sl->deblocking_filter < 2) + sl->deblocking_filter ^= 1; // 1<->0 + + if (sl->deblocking_filter) { + int32_t slice_alpha_c0_offset_div2 = yang_get_se_golomb(&sl->gb); + int32_t slice_beta_offset_div2 = yang_get_se_golomb(&sl->gb); + if (slice_alpha_c0_offset_div2 > 6 + || slice_alpha_c0_offset_div2 < -6 + || slice_beta_offset_div2 > 6 + || slice_beta_offset_div2 < -6) { + printf("deblocking filter parameters %d %d out of range\n", + slice_alpha_c0_offset_div2, slice_beta_offset_div2); + return YangERROR_INVALIDDATA; + } + sl->slice_alpha_c0_offset = slice_alpha_c0_offset_div2 * 2; + sl->slice_beta_offset = slice_beta_offset_div2 * 2; + } + } + + return 0; +} + +int32_t YangH264Header::get_bits_count(YangGetBitContext *s) { + return yang_get_bits_count(s); +} diff --git a/libyangrtc2/src/yangdecoder/YangH264Header.h b/libyangrtc2/src/yangdecoder/YangH264Header.h new file mode 100644 index 0000000000000000000000000000000000000000..e7a721ab15e7da0196c012db76cb623cad775b8a --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264Header.h @@ -0,0 +1,220 @@ +/* + * YangH264Header.h + * + * Created on: 2019年8月17日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGH264HEADER_H_ +#define YANGDECODER_SRC_YANGH264HEADER_H_ +#include +#include "stdint.h" +#include "stddef.h" + +//******************sps...27 +//0x00,0x00,0x00,0x01,0x67,0x42,0xc0,0x1f,0xd9,0x00,0x50,0x05,0xba,0x10,0x00,0x00,0x03,0x00,0x10,0x00,0x01,0x00,0x00,0xf1,0x83,0x24,0x80, +//******************pps...9 +//0x00,0x00,0x00,0x01,0x68,0xcb,0x83,0xcb,0x20, + + +#define LEFT_MBS 1 +#define Yang_MAX_SPS_COUNT 32 +#define Yang_MAX_PPS_COUNT 256 +#define Yang_MAX_LOG2_MAX_FRAME_NUM (12 + 4) + +#define Yang_MAX_MMCO_COUNT 66 +#define Yang_PICT_FRAME 3 +#define Yang_EXTENDED_SAR 255 +#define Yang_QP(qP, depth) ((qP) + 6 * ((depth) - 8)) +#define Yang_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define Yang_NAL_IDR_SLICE 5 +#define Yang_PICT_TOP_FIELD 1 +#define Yang_FIELD_PICTURE(h) ((h)->picture_structure != Yang_PICT_FRAME) +//#define Yang_FRAME_MBAFF(h) sps->mb_aff && (h->picture_structure == PICT_FRAME) + +//#define Yang_FIELD_OR_MBAFF_PICTURE(h) (Yang_FRAME_MBAFF(h) || Yang_FIELD_PICTURE(h)) + + +typedef struct YangSliceContext { + // struct H264Context *h264; + YangGetBitContext gb; + // ERContext er; + + int32_t slice_num; + int32_t slice_type; + int32_t slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) + int32_t slice_type_fixed; + + int32_t qscale; + int32_t chroma_qp[2]; // QPc + int32_t qp_thresh; ///< QP threshold to skip loopfilter + int32_t last_qscale_diff; + + // deblock + int32_t deblocking_filter; ///< disable_deblocking_filter_idc with 1 <-> 0 + int32_t slice_alpha_c0_offset; + int32_t slice_beta_offset; + + YangPredWeightTable pwt; + + int32_t prev_mb_skipped; + int32_t next_mb_skipped; + + int32_t chroma_pred_mode; + int32_t intra16x16_pred_mode; + + char intra4x4_pred_mode_cache[5 * 8]; + char (*intra4x4_pred_mode); + + int32_t topleft_mb_xy; + int32_t top_mb_xy; + int32_t topright_mb_xy; + int32_t left_mb_xy[LEFT_MBS]; + + int32_t topleft_type; + int32_t top_type; + int32_t topright_type; + int32_t left_type[LEFT_MBS]; + + const uint8_t *left_block; + int32_t topleft_partition; + + uint32_t topleft_samples_available; + uint32_t top_samples_available; + uint32_t topright_samples_available; + uint32_t left_samples_available; + + ptrdiff_t linesize, uvlinesize; + ptrdiff_t mb_linesize; ///< may be equal to s->linesize or s->linesize * 2, for mbaff + ptrdiff_t mb_uvlinesize; + + int32_t mb_x, mb_y; + int32_t mb_xy; + int32_t resync_mb_x; + int32_t resync_mb_y; + uint32_t first_mb_addr; + // index of the first MB of the next slice + int32_t next_slice_idx; + int32_t mb_skip_run; + int32_t is_complex; + + int32_t picture_structure; + int32_t mb_field_decoding_flag; + int32_t mb_mbaff; ///< mb_aff_frame && mb_field_decoding_flag + + int32_t redundant_pic_count; + + /** + * number of neighbors (top and/or left) that used 8x8 dct + */ + int32_t neighbor_transform_size; + + int32_t direct_spatial_mv_pred; + int32_t col_parity; + int32_t col_fieldoff; + + int32_t cbp; + int32_t top_cbp; + int32_t left_cbp; + + int32_t dist_scale_factor[32]; + int32_t dist_scale_factor_field[2][32]; + int32_t map_col_to_list0[2][16 + 32]; + int32_t map_col_to_list0_field[2][2][16 + 32]; + + /** + * num_ref_idx_l0/1_active_minus1 + 1 + */ + uint32_t ref_count[2]; ///< counts frames or fields, depending on current mb mode + uint32_t list_count; + // H264Ref ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. + // * Reordered version of default_ref_list + // * according to picture reordering in slice header */ + struct { + uint8_t op; + uint32_t val; + } ref_modifications[2][32]; + int32_t nb_ref_modifications[2]; + + uint32_t pps_id; + + const uint8_t *intra_pcm_ptr; + int16_t *dc_val_base; + + uint8_t *bipred_scratchpad; + uint8_t *edge_emu_buffer; + uint8_t (*top_borders[2])[(16 * 3) * 2]; + int32_t bipred_scratchpad_allocated; + int32_t edge_emu_buffer_allocated; + int32_t top_borders_allocated[2]; + + /** + * non zero coeff count cache. + * is 64 if not available. + */ + /** + DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; + DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2]; + DECLARE_ALIGNED(8, int8_t, ref_cache)[2][5 * 8]; + DECLARE_ALIGNED(16, uint8_t, mvd_cache)[2][5 * 8][2]; + uint8_t direct_cache[5 * 8]; + + DECLARE_ALIGNED(8, uint16_t, sub_mb_type)[4]; + + ///< as a DCT coefficient is int32_t in high depth, we need to reserve twice the space. + DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2]; + DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2]; + **/ + ///< as mb is addressed by scantable[i] and scantable is uint8_t we can either + ///< check that i is not too large or ensure that there is some unused stuff after mb + int16_t mb_padding[256 * 2]; + + uint8_t (*mvd_table[2])[2]; + + /** + * Cabac + */ + //CABACContext cabac; + //uint8_t cabac_state[1024]; + int32_t cabac_init_idc; + + YangMMCO mmco[Yang_MAX_MMCO_COUNT]; + int32_t nb_mmco; + int32_t explicit_ref_marking; + + int32_t frame_num; + int32_t poc_lsb; + int32_t delta_poc_bottom; + int32_t delta_poc[2]; + int32_t curr_pic_num; + int32_t max_pic_num; +} YangSliceContext; +#define MAX_MBPAIR_SIZE (256*1024) + + +class YangH264Header { +public: + YangH264Header(); + virtual ~YangH264Header(); + Yang_SPS m_sps; + Yang_PPS m_pps; + YangPacket packet; + YangNAL *nal; + YangRBSP *rbsp; + YangSliceContext *sl; + int32_t width,height,fps; + //void initGb(YangGetBitContext *gb,uint8_t *buf,int32_t bitsize); + int32_t h264_decode_seq_parameter_set(uint8_t *buf,int32_t len);//, int32_t ignore_truncation + int32_t h264_decode_picture_parameter_set(uint8_t *buf,int32_t len); + int32_t yang_packet_split(uint8_t *buf, int32_t length,int32_t isH264, int32_t small_padding); + int32_t h264_slice_header_parse(uint8_t *buf, int32_t length); + int32_t get_bits_count(YangGetBitContext *s); + void parseRtmpHeader(uint8_t *buf); + // void getRtmpHeader(uint8_t *buf,uint8_t *src,int32_t *hLen); +private: + int32_t yang_extract_rbsp( uint8_t *src, int32_t length, int32_t small_padding); + int32_t yang_packet_split1(uint8_t *buf, int32_t length,int32_t isH264, int32_t small_padding); +}; + +#endif /* YANGDECODER_SRC_YANGH264HEADER_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangH264Header1.h b/libyangrtc2/src/yangdecoder/YangH264Header1.h new file mode 100644 index 0000000000000000000000000000000000000000..dcc3f0a5be97f26523dd736181a21966342bdd24 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangH264Header1.h @@ -0,0 +1,709 @@ +#include +#include "memory.h" +#include "stdio.h" + +#include "YangH264Header.h" +//#include "yangbytestream.h" + +static int32_t yang_clip(int32_t a, int32_t amin, int32_t amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} +#define Yang_CHROMA_QP_TABLE_END(d) \ + Yang_QP(0, d), Yang_QP(1, d), Yang_QP(2, d), Yang_QP(3, d), Yang_QP(4, d), Yang_QP(5, d), \ + Yang_QP(6, d), Yang_QP(7, d), Yang_QP(8, d), Yang_QP(9, d), Yang_QP(10, d), Yang_QP(11, d), \ + Yang_QP(12, d), Yang_QP(13, d), Yang_QP(14, d), Yang_QP(15, d), Yang_QP(16, d), Yang_QP(17, d), \ + Yang_QP(18, d), Yang_QP(19, d), Yang_QP(20, d), Yang_QP(21, d), Yang_QP(22, d), Yang_QP(23, d), \ + Yang_QP(24, d), Yang_QP(25, d), Yang_QP(26, d), Yang_QP(27, d), Yang_QP(28, d), Yang_QP(29, d), \ + Yang_QP(29, d), Yang_QP(30, d), Yang_QP(31, d), Yang_QP(32, d), Yang_QP(32, d), Yang_QP(33, d), \ + Yang_QP(34, d), Yang_QP(34, d), Yang_QP(35, d), Yang_QP(35, d), Yang_QP(36, d), Yang_QP(36, d), \ + Yang_QP(37, d), Yang_QP(37, d), Yang_QP(37, d), Yang_QP(38, d), Yang_QP(38, d), Yang_QP(38, d), \ + Yang_QP(39, d), Yang_QP(39, d), Yang_QP(39, d), Yang_QP(39, d) + +/* maximum number of MBs in the DPB for a given level */ +static const int32_t yang_level_max_dpb_mbs[][2] = { + { 10, 396 }, + { 11, 900 }, + { 12, 2376 }, + { 13, 2376 }, + { 20, 2376 }, + { 21, 4752 }, + { 22, 8100 }, + { 30, 8100 }, + { 31, 18000 }, + { 32, 20480 }, + { 40, 32768 }, + { 41, 32768 }, + { 42, 34816 }, + { 50, 110400 }, + { 51, 184320 }, + { 52, 184320 }, +}; + +static const uint8_t yang_default_scaling4[2][16] = { + { 6, 13, 20, 28, 13, 20, 28, 32, + 20, 28, 32, 37, 28, 32, 37, 42 }, + { 10, 14, 20, 24, 14, 20, 24, 27, + 20, 24, 27, 30, 24, 27, 30, 34 } +}; + +static const uint8_t yang_default_scaling8[2][64] = { + { 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 }, + { 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 } +}; + +const uint8_t yang_zigzag_direct[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +const uint8_t yang_zigzag_scan[16+1] = { + 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4, + 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4, + 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4, + 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, +}; + +const uint8_t yang_h264_chroma_qp[7][Yang_QP_MAX_NUM + 1] = { + { Yang_CHROMA_QP_TABLE_END(8) }, + { 0, 1, 2, 3, 4, 5, + Yang_CHROMA_QP_TABLE_END(9) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + Yang_CHROMA_QP_TABLE_END(10) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + Yang_CHROMA_QP_TABLE_END(11) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + 18,19,20,21, 22, 23, + Yang_CHROMA_QP_TABLE_END(12) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + 18,19,20,21, 22, 23, + 24,25,26,27, 28, 29, + Yang_CHROMA_QP_TABLE_END(13) }, + { 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + 18,19,20,21, 22, 23, + 24,25,26,27, 28, 29, + 30,31,32,33, 34, 35, + Yang_CHROMA_QP_TABLE_END(14) }, +}; +const uint8_t yang_h264_quant_div6[Yang_QP_MAX_NUM + 1] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13, + 14,14,14,14, +}; +const uint8_t yang_h264_quant_rem6[Yang_QP_MAX_NUM + 1] = { + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, +}; + +const uint8_t yang_h264_dequant8_coeff_init_scan[16] = { + 0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1 +}; + +const uint8_t yang_h264_dequant8_coeff_init[6][6] = { + { 20, 18, 32, 19, 25, 24 }, + { 22, 19, 35, 21, 28, 26 }, + { 26, 23, 42, 24, 33, 31 }, + { 28, 25, 45, 26, 35, 33 }, + { 32, 28, 51, 30, 40, 38 }, + { 36, 32, 58, 34, 46, 43 }, +}; +const uint8_t yang_h264_dequant4_coeff_init[6][3] = { + { 10, 13, 16 }, + { 11, 14, 18 }, + { 13, 16, 20 }, + { 14, 18, 23 }, + { 16, 20, 25 }, + { 18, 23, 29 }, +}; + +static const YangRational yang_h264_pixel_aspect[17] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 24, 11 }, + { 20, 11 }, + { 32, 11 }, + { 80, 33 }, + { 18, 11 }, + { 15, 11 }, + { 64, 33 }, + { 160, 99 }, + { 4, 3 }, + { 3, 2 }, + { 2, 1 }, +}; + +const uint8_t yang_h264_golomb_to_pict_type[5] = { + Yang_PICTURE_TYPE_P, Yang_PICTURE_TYPE_B, Yang_PICTURE_TYPE_I, + Yang_PICTURE_TYPE_SP, Yang_PICTURE_TYPE_SI +}; +static inline int32_t get_chroma_qp(Yang_PPS *pps, int32_t t, int32_t qscale) +{ + return pps->chroma_qp_table[t][qscale]; +} +static void yang_build_qp_table(Yang_PPS *pps, int32_t t, int32_t index, const int32_t depth) +{ + int32_t i; + const int32_t max_qp = 51 + 6 * (depth - 8); + for (i = 0; i < max_qp + 1; i++) + pps->chroma_qp_table[t][i] = + yang_h264_chroma_qp[depth - 8][yang_clip(i + index, 0, max_qp)]; +} +static void init_dequant8_coeff_table(Yang_PPS *pps, const Yang_SPS *sps) +{ + int32_t i, j, q, x; + const int32_t max_qp = 51 + 6 * (sps->bit_depth_luma - 8); + + for (i = 0; i < 6; i++) { + pps->dequant8_coeff[i] = pps->dequant8_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(pps->scaling_matrix8[j], pps->scaling_matrix8[i], + 64 * sizeof(uint8_t))) { + pps->dequant8_coeff[i] = pps->dequant8_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int32_t shift = yang_h264_quant_div6[q]; + int32_t idx = yang_h264_quant_rem6[q]; + for (x = 0; x < 64; x++) + pps->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = + ((uint32_t)yang_h264_dequant8_coeff_init[idx][yang_h264_dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * + pps->scaling_matrix8[i][x]) << shift; + } + } +} + +static void init_dequant4_coeff_table(Yang_PPS *pps, const Yang_SPS *sps) +{ + int32_t i, j, q, x; + const int32_t max_qp = 51 + 6 * (sps->bit_depth_luma - 8); + for (i = 0; i < 6; i++) { + pps->dequant4_coeff[i] = pps->dequant4_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(pps->scaling_matrix4[j], pps->scaling_matrix4[i], + 16 * sizeof(uint8_t))) { + pps->dequant4_coeff[i] = pps->dequant4_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int32_t shift = yang_h264_quant_div6[q] + 2; + int32_t idx = yang_h264_quant_rem6[q]; + for (x = 0; x < 16; x++) + pps->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = + ((uint32_t)yang_h264_dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * + pps->scaling_matrix4[i][x]) << shift; + } + } +} +static void yang_init_dequant_tables(Yang_PPS *pps, const Yang_SPS *sps) +{ + int32_t i, x; + init_dequant4_coeff_table(pps, sps); + memset(pps->dequant8_coeff, 0, sizeof(pps->dequant8_coeff)); + + if (pps->transform_8x8_mode) + init_dequant8_coeff_table(pps, sps); + if (sps->transform_bypass) { + for (i = 0; i < 6; i++) + for (x = 0; x < 16; x++) + pps->dequant4_coeff[i][0][x] = 1 << 6; + if (pps->transform_8x8_mode) + for (i = 0; i < 6; i++) + for (x = 0; x < 64; x++) + pps->dequant8_coeff[i][0][x] = 1 << 6; + } +} +static int32_t yang_decode_scaling_list(YangGetBitContext *gb, uint8_t *factors, int32_t size, + const uint8_t *jvt_list, + const uint8_t *fallback_list) +{ + int32_t i, last = 8, next = 8; + const uint8_t *scan = size == 16 ? yang_zigzag_scan : yang_zigzag_direct; + if (!yang_get_bits1(gb)) /* matrix not written, we use the predicted one */ + memcpy(factors, fallback_list, size * sizeof(uint8_t)); + else + for (i = 0; i < size; i++) { + if (next) { + int32_t v = yang_get_se_golomb(gb); + next = (last + v) & 0xff; + } + if (!i && !next) { /* matrix not written, we use the preset one */ + memcpy(factors, jvt_list, size * sizeof(uint8_t)); + break; + } + last = factors[scan[i]] = next ? next : last; + } + return 0; +} + +static int32_t yang_decode_scaling_matrices(YangGetBitContext *gb, const Yang_SPS *sps, + const Yang_PPS *pps, int32_t is_sps, + uint8_t(*scaling_matrix4)[16], + uint8_t(*scaling_matrix8)[64]) +{ + int32_t fallback_sps = !is_sps && sps->scaling_matrix_present; + const uint8_t *fallback[4] = { + fallback_sps ? sps->scaling_matrix4[0] : yang_default_scaling4[0], + fallback_sps ? sps->scaling_matrix4[3] : yang_default_scaling4[1], + fallback_sps ? sps->scaling_matrix8[0] : yang_default_scaling8[0], + fallback_sps ? sps->scaling_matrix8[3] : yang_default_scaling8[1] + }; + int32_t ret = 0; + if (yang_get_bits1(gb)) { + ret |= yang_decode_scaling_list(gb, scaling_matrix4[0], 16, yang_default_scaling4[0], fallback[0]); // Intra, Y + ret |= yang_decode_scaling_list(gb, scaling_matrix4[1], 16, yang_default_scaling4[0], scaling_matrix4[0]); // Intra, Cr + ret |= yang_decode_scaling_list(gb, scaling_matrix4[2], 16, yang_default_scaling4[0], scaling_matrix4[1]); // Intra, Cb + ret |= yang_decode_scaling_list(gb, scaling_matrix4[3], 16, yang_default_scaling4[1], fallback[1]); // Inter, Y + ret |= yang_decode_scaling_list(gb, scaling_matrix4[4], 16, yang_default_scaling4[1], scaling_matrix4[3]); // Inter, Cr + ret |= yang_decode_scaling_list(gb, scaling_matrix4[5], 16, yang_default_scaling4[1], scaling_matrix4[4]); // Inter, Cb + if (is_sps || pps->transform_8x8_mode) { + ret |= yang_decode_scaling_list(gb, scaling_matrix8[0], 64, yang_default_scaling8[0], fallback[2]); // Intra, Y + ret |= yang_decode_scaling_list(gb, scaling_matrix8[3], 64, yang_default_scaling8[1], fallback[3]); // Inter, Y + if (sps->chroma_format_idc == 3) { + ret |= yang_decode_scaling_list(gb, scaling_matrix8[1], 64, yang_default_scaling8[0], scaling_matrix8[0]); // Intra, Cr + ret |= yang_decode_scaling_list(gb, scaling_matrix8[4], 64, yang_default_scaling8[1], scaling_matrix8[3]); // Inter, Cr + ret |= yang_decode_scaling_list(gb, scaling_matrix8[2], 64, yang_default_scaling8[0], scaling_matrix8[1]); // Intra, Cb + ret |= yang_decode_scaling_list(gb, scaling_matrix8[5], 64, yang_default_scaling8[1], scaling_matrix8[4]); // Inter, Cb + } + } + if (!ret) + ret = is_sps; + } + + return ret; +} +static int32_t yang_decode_hrd_parameters(YangGetBitContext *gb, Yang_SPS *sps) +{ + int32_t cpb_count=0, i=0; + cpb_count = yang_get_ue_golomb_31(gb) + 1; + + if (cpb_count > 32) { + // av_log(avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); + return YangERROR_INVALIDDATA; + } + + yang_get_bits(gb, 4); /* bit_rate_scale */ + yang_get_bits(gb, 4); /* cpb_size_scale */ + for (i = 0; i < cpb_count; i++) { + yang_get_ue_golomb_long(gb); /* bit_rate_value_minus1 */ + yang_get_ue_golomb_long(gb); /* cpb_size_value_minus1 */ + yang_get_bits1(gb); /* cbr_flag */ + } + sps->initial_cpb_removal_delay_length = yang_get_bits(gb, 5) + 1; + sps->cpb_removal_delay_length = yang_get_bits(gb, 5) + 1; + sps->dpb_output_delay_length = yang_get_bits(gb, 5) + 1; + sps->time_offset_length = yang_get_bits(gb, 5); + sps->cpb_cnt = cpb_count; + return 0; +} +static int32_t yang_decode_vui_parameters(YangGetBitContext *gb,Yang_SPS *sps) +{ + int32_t aspect_ratio_info_present_flag; + uint32_t aspect_ratio_idc; + + aspect_ratio_info_present_flag = yang_get_bits1(gb); + + if (aspect_ratio_info_present_flag) { + aspect_ratio_idc = yang_get_bits(gb, 8); + if (aspect_ratio_idc == Yang_EXTENDED_SAR) { + sps->sar.num = yang_get_bits(gb, 16); + sps->sar.den = yang_get_bits(gb, 16); + } else if (aspect_ratio_idc < Yang_ARRAY_ELEMS(yang_h264_pixel_aspect)) { + sps->sar = yang_h264_pixel_aspect[aspect_ratio_idc]; + } else { + // av_log(avctx, AV_LOG_ERROR, "illegal aspect ratio\n"); + return YangERROR_INVALIDDATA; + } + } else { + sps->sar.num = + sps->sar.den = 0; + } + + if (yang_get_bits1(gb)) /* overscan_info_present_flag */ + yang_get_bits1(gb); /* overscan_appropriate_flag */ + + sps->video_signal_type_present_flag = yang_get_bits1(gb); + if (sps->video_signal_type_present_flag) { + yang_get_bits(gb, 3); /* video_format */ + sps->full_range = yang_get_bits1(gb); /* video_full_range_flag */ + + sps->colour_description_present_flag = yang_get_bits1(gb); + if (sps->colour_description_present_flag) { + sps->color_primaries = yang_get_bits(gb, 8); /* colour_primaries */ + sps->color_trc = yang_get_bits(gb, 8); /* transfer_characteristics */ + sps->colorspace = yang_get_bits(gb, 8); /* matrix_coefficients */ + + // Set invalid values to "unspecified" + // if (!av_color_primaries_name(sps->color_primaries)) + sps->color_primaries = Yang_PRI_UNSPECIFIED; + // if (!av_color_transfer_name(sps->color_trc)) + sps->color_trc = Yang_TRC_UNSPECIFIED; + // if (!av_color_space_name(sps->colorspace)) + sps->colorspace = Yang_SPC_UNSPECIFIED; + } + } + + /* chroma_location_info_present_flag */ + if (yang_get_bits1(gb)) { + /* chroma_sample_location_type_top_field */ + // avctx->chroma_sample_location = yang_get_ue_golomb(gb) + 1; + int32_t chroma_sample_location = yang_get_ue_golomb(gb) + 1; + yang_get_ue_golomb(gb); /* chroma_sample_location_type_bottom_field */ + } + + if (yang_show_bits1(gb) && yang_get_bits_left(gb) < 10) { + // av_log(avctx, AV_LOG_WARNING, "Truncated VUI\n"); + return 0; + } + + sps->timing_info_present_flag = yang_get_bits1(gb); + if (sps->timing_info_present_flag) { + unsigned num_units_in_tick = yang_get_bits_long(gb, 32); + unsigned time_scale = yang_get_bits_long(gb, 32); + if (!num_units_in_tick || !time_scale) { + // av_log(avctx, AV_LOG_ERROR,"time_scale/num_units_in_tick invalid or unsupported (%u/%u)\n", time_scale, num_units_in_tick); + sps->timing_info_present_flag = 0; + } else { + sps->num_units_in_tick = num_units_in_tick; + sps->time_scale = time_scale; + } + sps->fixed_frame_rate_flag = yang_get_bits1(gb); + } + + sps->nal_hrd_parameters_present_flag = yang_get_bits1(gb); + if (sps->nal_hrd_parameters_present_flag) + if (yang_decode_hrd_parameters(gb, sps) < 0) + return YangERROR_INVALIDDATA; + sps->vcl_hrd_parameters_present_flag = yang_get_bits1(gb); + if (sps->vcl_hrd_parameters_present_flag) + if (yang_decode_hrd_parameters(gb, sps) < 0) + return YangERROR_INVALIDDATA; + if (sps->nal_hrd_parameters_present_flag || + sps->vcl_hrd_parameters_present_flag) + yang_get_bits1(gb); /* low_delay_hrd_flag */ + sps->pic_struct_present_flag = yang_get_bits1(gb); + if (!yang_get_bits_left(gb)) + return 0; + sps->bitstream_restriction_flag = yang_get_bits1(gb); + if (sps->bitstream_restriction_flag) { + yang_get_bits1(gb); /* motion_vectors_over_pic_boundaries_flag */ + yang_get_ue_golomb(gb); /* max_bytes_per_pic_denom */ + yang_get_ue_golomb(gb); /* max_bits_per_mb_denom */ + yang_get_ue_golomb(gb); /* log2_max_mv_length_horizontal */ + yang_get_ue_golomb(gb); /* log2_max_mv_length_vertical */ + sps->num_reorder_frames = yang_get_ue_golomb(gb); + yang_get_ue_golomb(gb); /*max_dec_frame_buffering*/ + + if (yang_get_bits_left(gb) < 0) { + sps->num_reorder_frames = 0; + sps->bitstream_restriction_flag = 0; + } + + if (sps->num_reorder_frames > 16U + /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) { + // av_log(avctx, AV_LOG_ERROR, "Clipping illegal num_reorder_frames %d\n", sps->num_reorder_frames); + sps->num_reorder_frames = 16; + return YangERROR_INVALIDDATA; + } + } + + return 0; +} + +int32_t yang_parse_nal_header(YangNAL *nal) +{ + YangGetBitContext *gb = &nal->gb; + + if (yang_get_bits1(gb) != 0) + return YangERROR_INVALIDDATA; + + nal->ref_idc = yang_get_bits(gb, 2); + nal->type = yang_get_bits(gb, 5); + return 1; +} + + +int32_t yang_h264_parse_ref_count(uint32_t *plist_count, uint32_t ref_count[2], + YangGetBitContext *gb, Yang_PPS *pps, + int32_t slice_type_nos, int32_t picture_structure) +{ + int32_t list_count; + int32_t num_ref_idx_active_override_flag; + + // set defaults, might be overridden a few lines later + ref_count[0] = pps->ref_count[0]; + ref_count[1] = pps->ref_count[1]; + + if (slice_type_nos != Yang_PICTURE_TYPE_I) { + unsigned max[2]; + max[0] = max[1] = picture_structure == Yang_PICT_FRAME ? 15 : 31; + + num_ref_idx_active_override_flag = yang_get_bits1(gb); + + if (num_ref_idx_active_override_flag) { + ref_count[0] = yang_get_ue_golomb(gb) + 1; + if (slice_type_nos == Yang_PICTURE_TYPE_B) { + ref_count[1] = yang_get_ue_golomb(gb) + 1; + } else + // full range is spec-ok in this case, even for frames + ref_count[1] = 1; + } + + if (ref_count[0] - 1 > max[0] || ref_count[1] - 1 > max[1]) { + printf("reference overflow %u > %u or %u > %u\n", + ref_count[0] - 1, max[0], ref_count[1] - 1, max[1]); + ref_count[0] = ref_count[1] = 0; + *plist_count = 0; + goto fail; + } + + if (slice_type_nos == Yang_PICTURE_TYPE_B) + list_count = 2; + else + list_count = 1; + } else { + list_count = 0; + ref_count[0] = ref_count[1] = 0; + } + + *plist_count = list_count; + + return 0; +fail: + *plist_count = 0; + ref_count[0] = 0; + ref_count[1] = 0; + return YangERROR_INVALIDDATA; +} + +int32_t yang_h264_decode_ref_pic_list_reordering(YangSliceContext *sl) +{ + int32_t list=0, index=0; + + sl->nb_ref_modifications[0] = 0; + sl->nb_ref_modifications[1] = 0; + + for (list = 0; list < sl->list_count; list++) { + if (!yang_get_bits1(&sl->gb)) // ref_pic_list_modification_flag_l[01] + continue; + + for (index = 0; ; index++) { + uint32_t op = yang_get_ue_golomb_31(&sl->gb); + + if (op == 3) + break; + + if (index >= sl->ref_count[list]) { + printf("reference count overflow\n"); + return YangERROR_INVALIDDATA; + } else if (op > 2) { + printf("illegal modification_of_pic_nums_idc %u\n", op); + return YangERROR_INVALIDDATA; + } + sl->ref_modifications[list][index].val = yang_get_ue_golomb_long(&sl->gb); + sl->ref_modifications[list][index].op = op; + sl->nb_ref_modifications[list]++; + } + } + + return 0; +} +int32_t yang_h264_pred_weight_table(YangGetBitContext *gb, Yang_SPS *sps, + uint32_t *ref_count, int32_t slice_type_nos, + YangPredWeightTable *pwt, + int32_t picture_structure) +{ + int32_t list, i, j; + int32_t luma_def, chroma_def; + + pwt->use_weight = 0; + pwt->use_weight_chroma = 0; + + pwt->luma_log2_weight_denom = yang_get_ue_golomb(gb); + if (pwt->luma_log2_weight_denom > 7U) { + printf( "luma_log2_weight_denom %d is out of range\n", pwt->luma_log2_weight_denom); + pwt->luma_log2_weight_denom = 0; + } + luma_def = 1 << pwt->luma_log2_weight_denom; + + if (sps->chroma_format_idc) { + pwt->chroma_log2_weight_denom = yang_get_ue_golomb(gb); + if (pwt->chroma_log2_weight_denom > 7U) { + printf("chroma_log2_weight_denom %d is out of range\n", pwt->chroma_log2_weight_denom); + pwt->chroma_log2_weight_denom = 0; + } + chroma_def = 1 << pwt->chroma_log2_weight_denom; + } + + for (list = 0; list < 2; list++) { + pwt->luma_weight_flag[list] = 0; + pwt->chroma_weight_flag[list] = 0; + for (i = 0; i < ref_count[list]; i++) { + int32_t luma_weight_flag, chroma_weight_flag; + + luma_weight_flag = yang_get_bits1(gb); + if (luma_weight_flag) { + pwt->luma_weight[i][list][0] = yang_get_se_golomb(gb); + pwt->luma_weight[i][list][1] = yang_get_se_golomb(gb); + if ((char)pwt->luma_weight[i][list][0] != pwt->luma_weight[i][list][0] || + (char)pwt->luma_weight[i][list][1] != pwt->luma_weight[i][list][1]) + goto out_range_weight; + if (pwt->luma_weight[i][list][0] != luma_def || + pwt->luma_weight[i][list][1] != 0) { + pwt->use_weight = 1; + pwt->luma_weight_flag[list] = 1; + } + } else { + pwt->luma_weight[i][list][0] = luma_def; + pwt->luma_weight[i][list][1] = 0; + } + + if (sps->chroma_format_idc) { + chroma_weight_flag = yang_get_bits1(gb); + if (chroma_weight_flag) { + int32_t j; + for (j = 0; j < 2; j++) { + pwt->chroma_weight[i][list][j][0] = yang_get_se_golomb(gb); + pwt->chroma_weight[i][list][j][1] = yang_get_se_golomb(gb); + if ((char)pwt->chroma_weight[i][list][j][0] != pwt->chroma_weight[i][list][j][0] || + (char)pwt->chroma_weight[i][list][j][1] != pwt->chroma_weight[i][list][j][1]) { + pwt->chroma_weight[i][list][j][0] = chroma_def; + pwt->chroma_weight[i][list][j][1] = 0; + goto out_range_weight; + } + if (pwt->chroma_weight[i][list][j][0] != chroma_def || + pwt->chroma_weight[i][list][j][1] != 0) { + pwt->use_weight_chroma = 1; + pwt->chroma_weight_flag[list] = 1; + } + } + } else { + int32_t j; + for (j = 0; j < 2; j++) { + pwt->chroma_weight[i][list][j][0] = chroma_def; + pwt->chroma_weight[i][list][j][1] = 0; + } + } + } + + // for MBAFF + if (picture_structure == Yang_PICT_FRAME) { + pwt->luma_weight[16 + 2 * i][list][0] = pwt->luma_weight[16 + 2 * i + 1][list][0] = pwt->luma_weight[i][list][0]; + pwt->luma_weight[16 + 2 * i][list][1] = pwt->luma_weight[16 + 2 * i + 1][list][1] = pwt->luma_weight[i][list][1]; + if (sps->chroma_format_idc) { + for (j = 0; j < 2; j++) { + pwt->chroma_weight[16 + 2 * i][list][j][0] = pwt->chroma_weight[16 + 2 * i + 1][list][j][0] = pwt->chroma_weight[i][list][j][0]; + pwt->chroma_weight[16 + 2 * i][list][j][1] = pwt->chroma_weight[16 + 2 * i + 1][list][j][1] = pwt->chroma_weight[i][list][j][1]; + } + } + } + } + if (slice_type_nos != Yang_PICTURE_TYPE_B) + break; + } + pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma; + return 0; +out_range_weight: + // avpriv_request_sample(logctx, "Out of range weight"); + return YangERROR_INVALIDDATA; +} +int32_t yang_h264_decode_ref_pic_marking(YangSliceContext *sl, YangGetBitContext *gb, + YangNAL *nal) +{ + int32_t i; + YangMMCO *mmco = sl->mmco; + int32_t nb_mmco = 0; + + if (nal->type == Yang_NAL_IDR_SLICE) { // FIXME fields + yang_skip_bits1(gb); // broken_link + if (yang_get_bits1(gb)) { + mmco[0].opcode = Yang_MMCO_LONG; + mmco[0].long_arg = 0; + nb_mmco = 1; + } + sl->explicit_ref_marking = 1; + } else { + sl->explicit_ref_marking = yang_get_bits1(gb); + if (sl->explicit_ref_marking) { + for (i = 0; i < Yang_MAX_MMCO_COUNT; i++) { + Yang_MMCOOpcode opcode = Yang_MMCOOpcode(yang_get_ue_golomb_31(gb)); + + mmco[i].opcode = opcode; + if (opcode == Yang_MMCO_SHORT2UNUSED || opcode == Yang_MMCO_SHORT2LONG) { + mmco[i].short_pic_num = + (sl->curr_pic_num - yang_get_ue_golomb_long(gb) - 1) & + (sl->max_pic_num - 1); + } + if (opcode == Yang_MMCO_SHORT2LONG || opcode == Yang_MMCO_LONG2UNUSED || + opcode == Yang_MMCO_LONG || opcode == Yang_MMCO_SET_MAX_LONG) { + uint32_t long_arg = yang_get_ue_golomb_31(gb); + if (long_arg >= 32 || + (long_arg >= 16 && !(opcode == Yang_MMCO_SET_MAX_LONG && + long_arg == 16) && + !(opcode == Yang_MMCO_LONG2UNUSED && Yang_FIELD_PICTURE(sl)))) { + printf( "illegal long ref in memory management control operation %d\n", opcode); + return -1; + } + mmco[i].long_arg = long_arg; + } + + if (opcode > (unsigned) Yang_MMCO_LONG) { + printf("illegal memory management control operation %d\n",opcode); + return -1; + } + if (opcode == Yang_MMCO_END) + break; + } + nb_mmco = i; + } + } + + sl->nb_mmco = nb_mmco; + + return 0; +} diff --git a/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.cpp b/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..610e39ccd33698ecbd4591c32730b83a4c6e461a --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.cpp @@ -0,0 +1,114 @@ +/* + * YangHeaderParseFfmpeg.cpp + * + * Created on: 2020年10月13日 + * Author: yang + */ + +#include "YangHeaderParseFfmpeg.h" + +void YangHeaderParseFfmpeg::loadLib() { +//yang_speex_lib_get_mode=(const SpeexMode * (*) (int32_t mode))m_lib.loadFunction(""); + yang_av_frame_alloc = (AVFrame* (*)(void)) m_lib1.loadFunction( + "av_frame_alloc"); + yang_av_buffer_unref = (void (*)(AVBufferRef **buf)) m_lib1.loadFunction( + "av_buffer_unref"); + yang_av_hwframe_ctx_init = (int32_t (*)(AVBufferRef *ref)) m_lib1.loadFunction( + "av_hwframe_ctx_init"); + yang_av_image_get_buffer_size = (int32_t (*)(enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_get_buffer_size"); + yang_av_hwdevice_ctx_create = (int32_t (*)(AVBufferRef **device_ctx, + enum AVHWDeviceType type, const char *device, AVDictionary *opts, + int32_t flags)) m_lib1.loadFunction("av_hwdevice_ctx_create"); + yang_av_hwframe_transfer_data = (int32_t (*)(AVFrame *dst, const AVFrame *src, + int32_t flags)) m_lib1.loadFunction("av_hwframe_transfer_data"); + yang_av_free = (void (*)(void *ptr)) m_lib1.loadFunction("av_free"); + yang_av_frame_free = (void (*)(AVFrame **frame)) m_lib1.loadFunction( + "av_frame_free"); + yang_av_buffer_ref = + (AVBufferRef* (*)(AVBufferRef *buf)) m_lib1.loadFunction( + "av_buffer_ref"); + yang_av_image_fill_arrays = (int32_t (*)(uint8_t *dst_data[4], + int32_t dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_fill_arrays"); + yang_av_hwframe_ctx_alloc = + (AVBufferRef* (*)(AVBufferRef *device_ctx)) m_lib1.loadFunction( + "av_hwframe_ctx_alloc"); + yang_av_malloc = (void* (*)(size_t size)) m_lib1.loadFunction("av_malloc"); + + yang_avcodec_open2 = (int32_t (*)(AVCodecContext *avctx, const AVCodec *codec, + AVDictionary **options)) m_lib.loadFunction("avcodec_open2"); + yang_av_init_packet = (void (*)(AVPacket *pkt)) m_lib.loadFunction( + "av_init_packet"); + yang_av_hwframe_get_buffer = (int32_t (*)(AVBufferRef *hwframe_ctx, + AVFrame *frame, int32_t flags)) m_lib.loadFunction( + "av_hwframe_get_buffer"); + yang_avcodec_find_decoder = + (AVCodec* (*)(enum AVCodecID id)) m_lib.loadFunction( + "avcodec_find_decoder"); + yang_avcodec_alloc_context3 = + (AVCodecContext* (*)(const AVCodec *codec)) m_lib.loadFunction( + "avcodec_alloc_context3"); + yang_avcodec_send_packet = (int32_t (*)(AVCodecContext *avctx, + const AVPacket *avpkt)) m_lib.loadFunction("avcodec_send_packet"); + yang_avcodec_receive_frame = + (int32_t (*)(AVCodecContext *avctx, AVFrame *frame)) m_lib.loadFunction( + "avcodec_receive_frame"); + yang_avcodec_close = (int32_t (*)(AVCodecContext *avctx)) m_lib.loadFunction( + "avcodec_close"); +} + +void YangHeaderParseFfmpeg::unloadLib() { + yang_av_free = NULL; + yang_av_hwframe_ctx_alloc = NULL; + yang_av_hwframe_ctx_init = NULL; + yang_av_buffer_ref = NULL; + yang_av_malloc = NULL; + yang_av_hwdevice_ctx_create = NULL; + yang_avcodec_open2 = NULL; + yang_av_frame_alloc = NULL; + yang_av_image_get_buffer_size = NULL; + yang_av_image_fill_arrays = NULL; + yang_av_init_packet = NULL; + yang_av_hwframe_get_buffer = NULL; + yang_avcodec_find_decoder = NULL; + yang_avcodec_alloc_context3 = NULL; + yang_avcodec_send_packet = NULL; + yang_avcodec_receive_frame = NULL; + yang_av_hwframe_transfer_data = NULL; + yang_av_frame_free = NULL; + yang_avcodec_close = NULL; +} +YangHeaderParseFfmpeg::YangHeaderParseFfmpeg() { + unloadLib(); + +} + +YangHeaderParseFfmpeg::~YangHeaderParseFfmpeg() { + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); +} +void YangHeaderParseFfmpeg::init(){ + m_lib.loadObject("libavcodec"); + m_lib1.loadObject("libavutil"); + loadLib(); +} +void YangHeaderParseFfmpeg::parse(uint8_t* headers,int32_t headerLen){ + AVCodec *t_codec = yang_avcodec_find_decoder(AV_CODEC_ID_H265); + AVCodecContext* t_codecCtx = yang_avcodec_alloc_context3(t_codec); + t_codecCtx->extradata = (uint8_t*) yang_av_malloc(headerLen + AV_INPUT_BUFFER_PADDING_SIZE); + t_codecCtx->extradata_size = headerLen; + memcpy(t_codecCtx->extradata, headers, headerLen); + int32_t ret = yang_avcodec_open2(t_codecCtx, t_codec, NULL); + if (ret < 0) + printf("\navcodec_open2 failure................\n"); + + + yang_avcodec_close(t_codecCtx); + yang_av_free(t_codecCtx); + t_codecCtx=NULL; + +} diff --git a/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.h b/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..1d1fc4ea6f8311eb1058406978ecdbb650d7693b --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangHeaderParseFfmpeg.h @@ -0,0 +1,55 @@ +/* + * YangHeaderParseFfmpeg.h + * + * Created on: 2020年10月13日 + * Author: yang + */ + +#ifndef YANGDECODER_SRC_YANGHEADERPARSEFFMPEG_H_ +#define YANGDECODER_SRC_YANGHEADERPARSEFFMPEG_H_ +#include +#include "yangutil/sys/YangLoadLib.h" +extern "C"{ +#include "libavcodec/avcodec.h" +//#include "libavformat/avformat.h" +#include "libavutil/avutil.h" +#include "libavutil/imgutils.h" +} + +class YangHeaderParseFfmpeg { +public: + YangHeaderParseFfmpeg(); + virtual ~YangHeaderParseFfmpeg(); + void parse(uint8_t* pheader,int32_t pheaderLen); + void init(); +private: + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + + AVBufferRef *(*yang_av_hwframe_ctx_alloc)(AVBufferRef *device_ctx); + int32_t (*yang_av_hwframe_ctx_init)(AVBufferRef *ref); + AVBufferRef *(*yang_av_buffer_ref)(AVBufferRef *buf); + void *(*yang_av_malloc)(size_t size); + int32_t (*yang_av_hwdevice_ctx_create)(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int32_t flags); + int32_t (*yang_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + AVFrame *(*yang_av_frame_alloc)(void); + int32_t (*yang_av_image_get_buffer_size)(enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + int32_t (*yang_av_image_fill_arrays)(uint8_t *dst_data[4], int32_t dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + void (*yang_av_buffer_unref)(AVBufferRef **buf); + void (*yang_av_init_packet)(AVPacket *pkt); + int32_t (*yang_av_hwframe_get_buffer)(AVBufferRef *hwframe_ctx, AVFrame *frame, int32_t flags); + AVCodec *(*yang_avcodec_find_decoder)(enum AVCodecID id); + AVCodecContext *(*yang_avcodec_alloc_context3)(const AVCodec *codec); + int32_t (*yang_avcodec_send_packet)(AVCodecContext *avctx, const AVPacket *avpkt); + int32_t (*yang_avcodec_receive_frame)(AVCodecContext *avctx, AVFrame *frame); + int32_t (*yang_av_hwframe_transfer_data)(AVFrame *dst, const AVFrame *src, int32_t flags); + void (*yang_av_frame_free)(AVFrame **frame); + void (*yang_av_free)(void *ptr); + int32_t (*yang_avcodec_close)(AVCodecContext *avctx); +}; + +#endif /* YANGDECODER_SRC_YANGHEADERPARSEFFMPEG_H_ */ diff --git a/libyangrtc2/src/yangdecoder/YangVideoDecoderHandle.cpp b/libyangrtc2/src/yangdecoder/YangVideoDecoderHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04c77ae33a3729b2fe43a03c588a46129796da95 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangVideoDecoderHandle.cpp @@ -0,0 +1,196 @@ +#include "malloc.h" +#include +#include +#include +#include +#include "stdlib.h" + +#include "yangdecoder/YangDecoderFactory.h" + +YangVideoDecoderHandle::YangVideoDecoderHandle(YangContext *pcontext) { + isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_videoBuffer = NULL; + m_decs = NULL; + m_out_videoBuffer = NULL; + m_context = pcontext; +} + +YangVideoDecoderHandle::~YangVideoDecoderHandle(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_context = NULL; + m_in_videoBuffer = NULL; + m_out_videoBuffer = NULL; + //size_t i = 0; + if (m_decs) { + delete m_decs; + m_decs = NULL; + + } + +} + +void YangVideoDecoderHandle::stop() { + stopLoop(); +} + +void YangVideoDecoderHandle::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + + + +YangVideoBuffer* YangVideoDecoderHandle::getOutVideoBuffer() { + + return m_out_videoBuffer; +} + + + +void YangVideoDecoderHandle::addVideoStream(uint8_t *ps, int32_t puid, + int32_t pisAdd) { + if (pisAdd) { + YangVideoEncDecType aet = ps[0] == 0x17 ? Yang_VED_264 : Yang_VED_265; + + YangDecoderFactory df; + m_decs=df.createVideoDecoder(aet, &m_context->video); + m_decs->m_uid = puid; + m_decs->init(); + int32_t wid = 0, hei = 0, fps = 10; + + m_decs->parseRtmpHeader(ps, 128, &wid, &hei, &fps); + if(m_out_videoBuffer){ + m_out_videoBuffer->m_uid = puid; + m_out_videoBuffer->init(wid, hei, m_context->video.videoDecoderFormat); + m_out_videoBuffer->m_frames = fps; + yang_trace("\ndecode:width==%d,height==%d,fps==%d\n",wid,hei,fps); + yang_trace("\nvideoBuffer:width==%d,height==%d,fps==%d\n",m_out_videoBuffer->m_width,m_out_videoBuffer->m_height,fps); + } + + + } +} + +void YangVideoDecoderHandle::init() { + isInit = 1; +} + +void YangVideoDecoderHandle::setInVideoBuffer(YangVideoDecoderBuffer *pbuf) { + m_in_videoBuffer = pbuf; +} +void YangVideoDecoderHandle::setOutVideoBuffer(YangVideoBuffer *pbuf) { + m_out_videoBuffer = pbuf; + if(m_context&&m_context->streams.m_playBuffer) m_context->streams.m_playBuffer->setInVideoBuffer(pbuf); +} + +void YangVideoDecoderHandle::onAudioData(YangFrame* pframe){ + +} + +void YangVideoDecoderHandle::onVideoData(YangFrame* pframe){ + if(m_out_videoBuffer) { + m_out_videoBuffer->putVideo(pframe); + } +} + + +void YangVideoDecoderHandle::startLoop() { + m_isConvert = 1; + uint8_t *srcVideo = new uint8_t[YANG_VIDEO_ENCODE_BUFFER_LEN]; + uint8_t *temp; + temp = srcVideo + 4; + //int32_t isFFmpeg = 1; //(m_context->videoDecoderType == 1 ? 1 : 0); + int32_t headLen = 0; + //int32_t nalLen = 0; + YangYuvType yuvType=YangI420;//YangYv12; + YangFrame videoFrame; + memset(&videoFrame,0,sizeof(YangFrame)); + int err=0; + while (m_isConvert == 1) { + if (!m_in_videoBuffer) { + yang_usleep(2000); + continue; + } + + + if (m_in_videoBuffer && m_in_videoBuffer->size() == 0) { + yang_usleep(2000); + continue; + } + + + videoFrame.payload=temp; + if (m_in_videoBuffer) + m_in_videoBuffer->getEVideo(&videoFrame); + else + continue; + + + if (videoFrame.frametype == YANG_Frametype_Spspps) { + if (m_decs == NULL) { + addVideoStream(temp, videoFrame.uid, 1); + } + continue; + } + + //compatible flash/flex h264 encode +// if (temp[0] == 0 && temp[1] == 0 && temp[2] == 0 && temp[3] == 0x02) { +// nalLen = temp[9]; +// headLen = nalLen + 10 + 4; +// } else { +// headLen = 0; +// } + + if (m_decs && m_decs->m_state == 0) { + if (!videoFrame.frametype) + continue; + m_decs->m_state = 1; + } + + //if (isFFmpeg) { + // headLen -= 4; + *(temp + headLen) = 0x00; + *(temp + headLen + 1) = 0x00; + *(temp + headLen + 2) = 0x00; + *(temp + headLen + 3) = 0x01; + //} + if (m_decs) { + videoFrame.payload=temp+headLen ; + videoFrame.nb=videoFrame.nb+headLen; + if((err=m_decs->decode(&videoFrame,yuvType,this))!=Yang_Ok){ + if(err>0){ + if(err==2&&m_context) m_context->streams.sendRequest(0,YangRTC_Decoder_Input ); + yang_error("decode video fail.."); + + + }//else{ + // /headLen=4; + //videoFrame.payload=temp + headLen; + //videoFrame.nb=videoFrame.nb - headLen; + //m_decs->decode(&videoFrame,yuvType,this); + // yang_error("ffmpeg decoder receive buffer fail.."); + // yang_trace("\n"); + //for(int i=0;i<100;i++) yang_trace("%02x,",temp[i]); + // } + } + + } + + } + + temp = NULL; + yang_deleteA(srcVideo); +} + +void YangVideoDecoderHandle::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangdecoder/YangVideoDecoderHandles.cpp b/libyangrtc2/src/yangdecoder/YangVideoDecoderHandles.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28faa5f88e835c307f205e53bbbf15a8f8a23f2a --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangVideoDecoderHandles.cpp @@ -0,0 +1,257 @@ +#include "malloc.h" +#include +#include +#include +#include +#include "stdlib.h" + +#include "yangdecoder/YangDecoderFactory.h" + +YangVideoDecoderHandles::YangVideoDecoderHandles(YangContext *pcontext) { + isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_videoBuffer = NULL; + m_decs = new vector(); + m_out_videoBuffer = NULL; + m_context = pcontext; +} + +YangVideoDecoderHandles::~YangVideoDecoderHandles(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_context = NULL; + m_in_videoBuffer = NULL; + m_out_videoBuffer = NULL; + size_t i = 0; + if (m_decs) { + for (i = 0; i < m_decs->size(); i++) { + delete m_decs->at(i); + } + m_decs->clear(); + delete m_decs; + m_decs = NULL; + + } + +} + +void YangVideoDecoderHandles::stop() { + stopLoop(); +} + +void YangVideoDecoderHandles::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +int32_t YangVideoDecoderHandles::getDecoderIndex(int32_t puid) { + for (int32_t i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) + return i; + } + return -1; +} +YangVideoDecoder* YangVideoDecoderHandles::getDecoder(int32_t puid) { + for (int32_t i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) + return m_decs->at(i); + } + return NULL; +} + +YangVideoBuffer* YangVideoDecoderHandles::getVideoBuffer(int32_t puid) { + for (int32_t i = 0; i < (int) m_out_videoBuffer->size(); i++) { + if (m_out_videoBuffer->at(i)->m_uid == puid) + return m_out_videoBuffer->at(i); + } + return NULL; +} + +void YangVideoDecoderHandles::removeAllStream() { + if (m_out_videoBuffer->size() == 0) + return; + int32_t i = 0; + for (i = 0; i < (int) m_out_videoBuffer->size(); i++) { + delete m_out_videoBuffer->at(i); + m_out_videoBuffer->at(i) = NULL; + + } + m_out_videoBuffer->clear(); + if (m_decs->size() == 0) + return; + for (i = 0; i < (int) m_decs->size(); i++) { + delete m_decs->at(i); + m_decs->at(i) = NULL; + } + m_decs->clear(); +} + + +void YangVideoDecoderHandles::removeStream(){ + int32_t i = 0; + for(;m_removeList.size()>0;){ + int32_t puid=m_removeList.front(); + m_removeList.erase(m_removeList.begin()); + + for (i = 0; i < (int) m_out_videoBuffer->size(); i++) { + if (m_out_videoBuffer->at(i)->m_uid == puid) { + delete m_out_videoBuffer->at(i); + m_out_videoBuffer->at(i) = NULL; + m_out_videoBuffer->erase(m_out_videoBuffer->begin() + i); + break; + } + } + if (m_decs->size() == 0) + return; + for (i = 0; i < (int) m_decs->size(); i++) { + if (m_decs->at(i)->m_uid == puid) { + delete m_decs->at(i); + m_decs->at(i) = NULL; + m_decs->erase(m_decs->begin() + i); + return; + } + } + } +} + +void YangVideoDecoderHandles::addVideoStream(uint8_t *ps, int32_t puid, + int32_t pisAdd) { + if (pisAdd) { + YangVideoEncDecType aet = ps[0] == 0x17 ? Yang_VED_264 : Yang_VED_265; + YangDecoderFactory df; + m_decs->push_back(df.createVideoDecoder(aet, &m_context->video)); + m_decs->back()->m_uid = puid; + m_decs->back()->init(); + int32_t wid = 0, hei = 0, fps = 10; + + m_decs->back()->parseRtmpHeader(ps, 128, &wid, &hei, &fps); + m_out_videoBuffer->push_back( + new YangVideoBuffer(m_context->video.bitDepth == 8 ? 1 : 2)); + m_out_videoBuffer->back()->m_uid = puid; + m_out_videoBuffer->back()->init(wid, hei, m_context->video.videoDecoderFormat); + m_out_videoBuffer->back()->m_frames = fps; + yang_trace("\nwidth==%d,height==%d,fps==%d\n",wid,hei,fps); + + int ind=0; + if(m_context&&(ind=m_context->streams.getIndex(puid))>-1){ + m_context->streams.m_playBuffers->at(ind)->setInVideoBuffer(m_out_videoBuffer->back()); + } + + } else { + m_removeList.push_back(puid); + } +} + +void YangVideoDecoderHandles::init() { + isInit = 1; +} + +void YangVideoDecoderHandles::setInVideoBuffer(YangVideoDecoderBuffer *pbuf) { + m_in_videoBuffer = pbuf; +} +void YangVideoDecoderHandles::setOutVideoBuffer(vector *pbuf) { + m_out_videoBuffer = pbuf; +} +void YangVideoDecoderHandles::onAudioData(YangFrame* pframe){ + +} +void YangVideoDecoderHandles::onVideoData(YangFrame* pframe){ + YangVideoBuffer *t_vb = getVideoBuffer(pframe->uid); + if(t_vb) { + t_vb->putVideo(pframe); + } + t_vb=NULL; +} + + +void YangVideoDecoderHandles::startLoop() { + m_isConvert = 1; + uint8_t *srcVideo = new uint8_t[YANG_VIDEO_ENCODE_BUFFER_LEN]; + uint8_t *temp; + temp = srcVideo + 4; + + //int32_t isFFmpeg = 1; //(m_context->videoDecoderType == 1 ? 1 : 0); + int32_t index = 0; + YangVideoDecoder *t_decoder = NULL; + int32_t headLen = 0; + //int32_t nalLen = 0; + YangYuvType yuvType=YangI420;//YangYv12; + YangFrame videoFrame; + memset(&videoFrame,0,sizeof(YangFrame)); + //videoFrame.yuvType=yuvType; + int err=Yang_Ok; + while (m_isConvert == 1) { + if (!m_in_videoBuffer) { + yang_usleep(2000); + continue; + } + + if(m_removeList.size()>0) removeStream(); + + if (m_in_videoBuffer && m_in_videoBuffer->size() == 0) { + yang_usleep(2000); + continue; + } + + videoFrame.payload=temp; + + if (m_in_videoBuffer) m_in_videoBuffer->getEVideo(&videoFrame); + + + if (videoFrame.frametype == YANG_Frametype_Spspps) { + index = getDecoderIndex(videoFrame.uid); + if (index == -1) { + addVideoStream(temp, videoFrame.uid, 1); + } + continue; + } + //compatible flash/flex h264 encode +// if (temp[0] == 0 && temp[1] == 0 && temp[2] == 0 && temp[3] == 0x02) { +// nalLen = temp[9]; +// headLen = nalLen + 10 + 4; +// } else { +// headLen = 4; +// } + + + t_decoder = getDecoder(videoFrame.uid); + + if (t_decoder && t_decoder->m_state == 0) { + if (!videoFrame.frametype) + continue; + t_decoder->m_state = 1; + } + + //if (isFFmpeg) { + // headLen -= 4; + *(temp + headLen) = 0x00; + *(temp + headLen + 1) = 0x00; + *(temp + headLen + 2) = 0x00; + *(temp + headLen + 3) = 0x01; + //} + if (t_decoder) { + videoFrame.payload=temp + headLen; + videoFrame.nb=videoFrame.nb - headLen; + if((err=t_decoder->decode(&videoFrame,yuvType,this))!=Yang_Ok){ + if(err==2&&m_context) m_context->streams.sendRequest(videoFrame.uid,YangRTC_Decoder_Input ); + yang_error("decode video fail..uid===%d",videoFrame.uid); + } + + } + t_decoder = NULL; + } + t_decoder = NULL; + temp = NULL; + yang_deleteA(srcVideo); +} + +void YangVideoDecoderHandles::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.cpp b/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..283d98fe41c2109304fadf828342ced09d5772d5 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.cpp @@ -0,0 +1,492 @@ +#include "YangVideoDecoderIntel.h" +#if HaveLibva +#include "memory.h" +#include +#include "string.h" +#include "sys/ioctl.h" +#include "fcntl.h" +#include "memory.h" +#include "yangutil/yang_unistd.h" +//#include +//#include +#include "string.h" +#include "stdio.h" +#include "xf86drm.h" + +using namespace std; +#define CHECK_VASTATUS(X, MSG) {if ((X) != VA_STATUS_SUCCESS) {cout <<"\n"<m_sps; + Yang_PPS *pps = &header->m_pps; + //YangSliceContext *sl=header->sl; + //(*p_pic_para) = (VAPictureParameterBufferH264){ + p_pic_para->picture_width_in_mbs_minus1 = sps->mb_width - 1;//conf->Video_Width_Zb - 1; + p_pic_para->picture_height_in_mbs_minus1 = sps->mb_height - 1;//conf->Video_Height_Zb - 1; + + p_pic_para->bit_depth_luma_minus8 = sps->bit_depth_luma - 8; + p_pic_para->bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8; + p_pic_para->num_ref_frames = sps->ref_frame_count; + //.seq_fields.bits = { + p_pic_para->seq_fields.bits.chroma_format_idc = sps->chroma_format_idc; + p_pic_para->seq_fields.bits.residual_colour_transform_flag = + sps->residual_color_transform_flag; + p_pic_para->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = + sps->gaps_in_frame_num_allowed_flag; + p_pic_para->seq_fields.bits.frame_mbs_only_flag = sps->frame_mbs_only_flag; + p_pic_para->seq_fields.bits.mb_adaptive_frame_field_flag = sps->mb_aff; + p_pic_para->seq_fields.bits.direct_8x8_inference_flag = + sps->direct_8x8_inference_flag; + p_pic_para->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* Ap_pic_para->seq_fields.bits.3p_pic_para->seq_fields.bits.3p_pic_para->seq_fields.bits.2 */ + p_pic_para->seq_fields.bits.log2_max_frame_num_minus4 = + sps->log2_max_frame_num - 4; + p_pic_para->seq_fields.bits.pic_order_cnt_type = sps->poc_type; + p_pic_para->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = + sps->log2_max_poc_lsb - 4; + p_pic_para->seq_fields.bits.delta_pic_order_always_zero_flag = + sps->delta_pic_order_always_zero_flag; + // }; + p_pic_para->num_slice_groups_minus1 = pps->slice_group_count - 1; + p_pic_para->slice_group_map_type = pps->mb_slice_group_map_type; + p_pic_para->slice_group_change_rate_minus1 = 0; /* FMO is not implemented */ + p_pic_para->pic_init_qp_minus26 = pps->init_qp - 26; //init_qp - 26; + p_pic_para->pic_init_qs_minus26 = pps->init_qs - 26; //init_qs - 26; + p_pic_para->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; + p_pic_para->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; + //.pic_fields.bits = { + p_pic_para->pic_fields.bits.entropy_coding_mode_flag = pps->cabac; + p_pic_para->pic_fields.bits.weighted_pred_flag = pps->weighted_pred; + p_pic_para->pic_fields.bits.weighted_bipred_idc = pps->weighted_bipred_idc; + p_pic_para->pic_fields.bits.transform_8x8_mode_flag = + pps->transform_8x8_mode; + p_pic_para->pic_fields.bits.field_pic_flag = 0; //sl->picture_structure != Yang_PICT_FRAME; + p_pic_para->pic_fields.bits.constrained_intra_pred_flag = + pps->constrained_intra_pred; + p_pic_para->pic_fields.bits.pic_order_present_flag = pps->pic_order_present; + p_pic_para->pic_fields.bits.deblocking_filter_control_present_flag = + pps->deblocking_filter_parameters_present; + p_pic_para->pic_fields.bits.redundant_pic_cnt_present_flag = + pps->redundant_pic_cnt_present; + p_pic_para->pic_fields.bits.reference_pic_flag = 1; //h->nal_ref_idc != 0; + // }, + p_pic_para->frame_num = 0; + // }; + +} +int32_t yang_get_slice_type(YangSliceContext *sl) { + switch (sl->slice_type) { + case Yang_PICTURE_TYPE_P: + return 0; + case Yang_PICTURE_TYPE_B: + return 1; + case Yang_PICTURE_TYPE_I: + return 2; + case Yang_PICTURE_TYPE_SP: + return 3; + case Yang_PICTURE_TYPE_SI: + return 4; + default: + return -1; + } +} +YangVideoDecoderIntel::YangVideoDecoderIntel() { + /**m_va_dpy = NULL; + m_config_id = VA_INVALID_ID; + memset(pics, 0, sizeof(YangDecodePicture)*Para_Bufs); + memset(&m_picPara, 0, sizeof(m_picPara)); + memset(&iq_matrix, 0, sizeof(iq_matrix)); + memset(&image_format, 0, sizeof(image_format)); + memset(&m_slice_param, 0, sizeof(m_slice_param)); + sid=0;va-drm + frameIdx=0; + FieldOrderCnt=0; + m_ref_count=3;**/ + //printf("\n*****YangH264Decoder***********************************Intel\n"); + + m_va_dpy = NULL; + m_config_id = VA_INVALID_ID; + + m_config_id = 0; + m_vaContext = 0; + vas = 0; + memset(pics, 0, sizeof(YangDecodePicture) * Para_Bufs); + memset(&m_picPara, 0, sizeof(m_picPara)); + memset(&iq_matrix, 0, sizeof(iq_matrix)); + memset(&image_format, 0, sizeof(image_format)); + memset(&m_slice_param, 0, sizeof(m_slice_param)); + m_fd = 0; + m_ref_count = 0; + m_ref_count_m1 = 0; + sid = 0; + frameIdx = 0; + FieldOrderCnt = 0; + m_ref_count = 3; + //m_yvp = NULL; + m_width = 0; + m_height = 0; + m_frame = 0; + yLen = 0; + uLen = 0; + uvLen = 0; + allLen = 0; + frameIdx = 0; + FieldOrderCnt = 0; + posNum = 0; + m_isInit = 0; + unloadLib(); +} + +YangVideoDecoderIntel::~YangVideoDecoderIntel() { +// printf("\n**************YangVideoDecoderIntel destruct***************\n"); + closeDevice(); + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); +} + +void YangVideoDecoderIntel::initH264Pic() { + + for (int32_t i = 0; i < 16; i++) { + m_picPara.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + m_picPara.ReferenceFrames[i].picture_id = 0xffffffff; + m_picPara.ReferenceFrames[i].TopFieldOrderCnt = 0; + m_picPara.ReferenceFrames[i].BottomFieldOrderCnt = 0; + } +} + +void YangVideoDecoderIntel::closeDevice() { + //vaDestroySurfaces(m_va_dpy,&m_vaSurface,1); + for (int32_t i = 0; i < Para_Bufs; i++) { + if (m_va_dpy && surface_id[i] != VA_INVALID_ID) { + vas = yang_vaDestroySurfaces(m_va_dpy, &surface_id[i], 1); + CHECK_VASTATUS(vas, "vaDestroySurfaces"); + } + } + if (m_va_dpy && m_vaContext != VA_INVALID_ID) { + vas = yang_vaDestroyContext(m_va_dpy, m_vaContext); + CHECK_VASTATUS(vas, "vaDestroyContext"); + } + if (m_va_dpy && m_config_id != VA_INVALID_ID) { + vas = yang_vaDestroyConfig(m_va_dpy, m_config_id); + CHECK_VASTATUS(vas, "vaDestroyConfig"); + } + if (m_va_dpy) { + vas = yang_vaTerminate(m_va_dpy); + CHECK_VASTATUS(vas, "vaTerminate"); + } + if (m_fd >= 0) + close(m_fd); + m_va_dpy = NULL; + +} + +void YangVideoDecoderIntel::initSlicePara(VASliceParameterBufferH264 *slice264, + uint8_t *p_data, int32_t p_len) { + //initNaluPara(&m_Nalu,p_data); + + YangSliceContext *sl = h264header.sl; + int32_t ret = (h264header.m_sps.mb_aff + && (sl->picture_structure == Yang_PICT_FRAME)) + || sl->picture_structure != Yang_PICT_FRAME; + slice264->slice_data_size = p_len; + slice264->slice_data_offset = 0; + slice264->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; + slice264->slice_data_bit_offset = h264header.get_bits_count(&sl->gb); + slice264->first_mb_in_slice = (sl->mb_y >> ret) * h264header.m_sps.mb_width + + sl->mb_x; + slice264->slice_type = yang_get_slice_type(sl); //sl->slice_type;//m_Nalu.nal_reference_idc;//ff_h264_get_slice_type(sl); + slice264->direct_spatial_mv_pred_flag = + sl->slice_type == Yang_PICTURE_TYPE_B ? + sl->direct_spatial_mv_pred : 0; + slice264->num_ref_idx_l0_active_minus1 = + sl->list_count > 0 ? sl->ref_count[0] - 1 : 0; + slice264->num_ref_idx_l1_active_minus1 = + sl->list_count > 1 ? sl->ref_count[1] - 1 : 0; + slice264->cabac_init_idc = sl->cabac_init_idc; + slice264->slice_qp_delta = sl->qscale - h264header.m_pps.init_qp; + slice264->disable_deblocking_filter_idc = + sl->deblocking_filter < 2 ? + !sl->deblocking_filter : sl->deblocking_filter; + slice264->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2; + slice264->slice_beta_offset_div2 = sl->slice_beta_offset / 2; + slice264->luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; + slice264->chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; + sl = NULL; + if (slice264->slice_type == 2) { + slice264->chroma_weight_l0[0][0] = 0; + slice264->chroma_weight_l0[0][1] = 0; + slice264->chroma_weight_l1[0][0] = 0; + slice264->chroma_weight_l1[0][1] = 0; + slice264->RefPicList0[0].picture_id = 0xffffffff; + } else { + slice264->chroma_weight_l0[0][0] = 1; + slice264->chroma_weight_l0[0][1] = 1; + slice264->chroma_weight_l1[0][0] = 1; + slice264->chroma_weight_l1[0][1] = 1; + } + + for (int32_t i = 0; i < 32; i++) { + slice264->RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + slice264->RefPicList1[i].flags = VA_PICTURE_H264_INVALID; + slice264->RefPicList0[i].picture_id = 0xffffffff; + slice264->RefPicList1[i].picture_id = 0xffffffff; + } +} + +void YangVideoDecoderIntel::cachePic(VAPictureH264 *p_vpic, int32_t p_pocind) { + + if (p_pocind > 0) { + if (p_pocind > m_ref_count_m1) { + memcpy(&m_picPara.ReferenceFrames[m_ref_count_m1], &m_pic[m_ref_count_m1], sizeof(VAPictureH264)); + memcpy(&m_slice_param.RefPicList0[m_ref_count_m1], &m_pic[m_ref_count_m1], sizeof(VAPictureH264)); + } + int32_t i = (p_pocind > m_ref_count_m1 - 1 ? m_ref_count_m1 : p_pocind) - 1; + + for (; i >= 0; i--) { + memcpy(&m_picPara.ReferenceFrames[i], &m_pic[i],sizeof(VAPictureH264)); + memcpy(&m_slice_param.RefPicList0[i], &m_pic[i],sizeof(VAPictureH264)); + memcpy(&m_pic[i + 1], &m_pic[i], sizeof(VAPictureH264)); + } + } + memcpy(&m_pic[0], p_vpic, sizeof(VAPictureH264)); + m_pic[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; + +} +void YangVideoDecoderIntel::init() { + +} +void YangVideoDecoderIntel::parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, + int32_t *phei, int32_t *pfps) { + //printf("\n*****************************header.........\n"); + //for(int32_t i=0;i<60;i++){ + // printf("%02x,",*(p+i)); + //} + //printf("\n**********************************************\n"); + m_lib.loadSysObject("libva"); + m_lib1.loadSysObject("libva-drm"); + loadLib(); + m_fd = open("/dev/dri/renderD128", O_RDWR); + m_va_dpy = yang_vaGetDisplayDRM(m_fd); + int32_t major_version = 0, minor_version = 0; + if (m_va_dpy) + vas = yang_vaInitialize(m_va_dpy, &major_version, &minor_version); + CHECK_VASTATUS(vas, "vaInitialize"); + //printf("Initialised VAAPI connection: version %d.%d,..md=%d\n", major_version, minor_version, m_fd); + image_format.fourcc = VA_FOURCC_NV12; + image_format.depth = 8; + frameIdx = 0; + posNum = 0; + h264header.parseRtmpHeader(p); + initWH(); + *pwid = m_width; + *phei = m_height; + *pfps = h264header.fps; + m_isInit = 1; +} +void YangVideoDecoderIntel::initWH() { + memset(iq_matrix.ScalingList4x4, 0x10, sizeof(iq_matrix.ScalingList4x4)); + memset(iq_matrix.ScalingList8x8[0], 0x10, + sizeof(iq_matrix.ScalingList8x8[0])); + memset(iq_matrix.ScalingList8x8[1], 0x10, + sizeof(iq_matrix.ScalingList8x8[0])); + m_width = h264header.width; + m_height = h264header.height; + //m_yvp->initSdlWin(2,&m_yvp->rects[0], m_width, m_height, 0, 0); +// printf("\nmd=%d*********************intel decode init wid=%d,hei=%d,fps=%d,profile=%d..........%d\n", +// m_fd, m_width, m_height, h264header.fps, +// h264header.m_sps.profile_idc, h264header.m_sps.ref_frame_count); + initPicPara_1(&m_picPara, &h264header); + yLen = m_width * m_height; + uLen = yLen / 4; + allLen = yLen * 3 / 2; + uvLen = yLen / 2; + m_ref_count = h264header.m_sps.ref_frame_count; + if (m_ref_count > 16) + m_ref_count = 16; + if (m_ref_count < 3) + m_ref_count = 3; + m_ref_count_m1 = m_ref_count - 1; + VAConfigAttrib attrib; + VAProfile vap = VAProfileH264ConstrainedBaseline; + if (h264header.m_sps.profile_idc == 77) + vap = VAProfileH264Main; + if (h264header.m_sps.profile_idc == 100 + || h264header.m_sps.profile_idc == 110 + || h264header.m_sps.profile_idc == 122) + vap = VAProfileH264High; + vas = yang_vaCreateConfig(m_va_dpy, vap, VAEntrypointVLD, &attrib, 1, + &m_config_id); + CHECK_VASTATUS(vas, "vaCreateConfig"); + vas = yang_vaCreateSurfaces(m_va_dpy, VA_RT_FORMAT_YUV420, m_width, + m_height, surface_id, Para_Bufs, NULL, 0); + CHECK_VASTATUS(vas, "vaCreateSurfaces"); + + vas = yang_vaCreateContext(m_va_dpy, m_config_id, m_width, m_height, + VA_PROGRESSIVE, &surface_id[0], Para_Bufs, &m_vaContext); + CHECK_VASTATUS(vas, "vaCreateContext"); +} +void YangVideoDecoderIntel::init(YangVideoParam *p_config) { + +} + +int32_t YangVideoDecoderIntel::decode(YangVideoBuffer *pvpl, int32_t isIframe, + uint8_t *pData, int32_t nSize, int64_t ptimestamp, + uint8_t *dest, int32_t *pnFrameReturned) { + + h264header.h264_slice_header_parse(pData, nSize); + initSlicePara(&m_slice_param, pData, nSize); + initH264Pic(); + //m_picPara.frame_num = frameIdx; + if (h264header.sl) + m_picPara.pic_fields.bits.field_pic_flag = + h264header.sl->picture_structure != Yang_PICT_FRAME; + + if (m_slice_param.slice_type == 2) { + posNum = 0; + FieldOrderCnt = 0; + } + m_picPara.CurrPic.picture_id = surface_id[sid]; + m_picPara.CurrPic.frame_idx = frameIdx; + m_picPara.CurrPic.flags = 0; + m_picPara.CurrPic.BottomFieldOrderCnt = FieldOrderCnt; + m_picPara.CurrPic.TopFieldOrderCnt = FieldOrderCnt; + m_picPara.frame_num = posNum; + + cachePic(&m_picPara.CurrPic, posNum); + //yang_printme(&m_slice_param); + //yang_printMe2(&m_picPara); + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAPictureParameterBufferType, sizeof(VAPictureParameterBufferH264), + 1, &m_picPara, &pics[sid].picBuf); + CHECK_VASTATUS(vas, "vaCreateBuffer VAPictureParameterBufferType"); + + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, VAIQMatrixBufferType, + sizeof(VAIQMatrixBufferH264), 1, &iq_matrix, &pics[sid].IQMBuf); + CHECK_VASTATUS(vas, "vaCreateBuffer VAIQMatrixBufferType"); + + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, VASliceParameterBufferType, + sizeof(VASliceParameterBufferH264), 1, &m_slice_param, + &pics[sid].sliceParaBuf); + CHECK_VASTATUS(vas, "vaCreateBuffer VASliceParameterBufferType"); + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, VASliceDataBufferType, + nSize, 1, pData, &pics[sid].sliceDataBuf); + CHECK_VASTATUS(vas, "vaCreateBuffer VASliceDataBufferType"); + + vas = yang_vaBeginPicture(m_va_dpy, m_vaContext, surface_id[sid]); + CHECK_VASTATUS(vas, "vaBeginPicture"); + + bufids[0] = pics[sid].picBuf; + bufids[1] = pics[sid].IQMBuf; + vas = yang_vaRenderPicture(m_va_dpy, m_vaContext, bufids, 2); + CHECK_VASTATUS(vas, "vaRenderPicture 1,2"); + + bufids[0] = pics[sid].sliceParaBuf; + bufids[1] = pics[sid].sliceDataBuf; + vas = yang_vaRenderPicture(m_va_dpy, m_vaContext, bufids, 2); + CHECK_VASTATUS(vas, "vaRenderPicture 3,4"); + + vas = yang_vaEndPicture(m_va_dpy, m_vaContext); + CHECK_VASTATUS(vas, "vaEndPicture"); + vas = yang_vaSyncSurface(m_va_dpy, surface_id[sid]); + CHECK_VASTATUS(vas, "vaSyncSurface"); + + frameIdx++; + if (frameIdx > 15) + frameIdx = 0; + FieldOrderCnt += 2; + posNum++; + //memcpy(&m_old_pic, &m_picPara.CurrPic, sizeof(VAPictureH264)); + // vas = vaPutSurface(m_va_dpy, surface_id[sid], win, 0, 0, m_width, m_height, 0, 0, m_width, m_height, NULL, 0, VA_FRAME_PICTURE); + // CHECK_VASTATUS(vas, "vaPutSurface"); + + uint8_t *picData1; + vas = yang_vaCreateImage(m_va_dpy, &image_format, m_width, m_height, + &m_img); + CHECK_VASTATUS(vas, "vaCreateImage"); + vas = yang_vaGetImage(m_va_dpy, surface_id[sid], 0, 0, m_width, m_height, + m_img.image_id); + CHECK_VASTATUS(vas, "vaGetImage"); + vas = yang_vaMapBuffer(m_va_dpy, m_img.buf, (void**) &picData1); + CHECK_VASTATUS(vas, "vaMapBuffer img"); + + memcpy(dest, picData1, allLen); + *pnFrameReturned = m_img.data_size; + //if (vas == 0) t_yvp.yuv_show(dest, m_width); + if (vas == 0) + pvpl->putVideo(picData1, allLen, ptimestamp); + vas = yang_vaUnmapBuffer(m_va_dpy, m_img.buf); + picData1=NULL; + //mapDrm(sid); + sid++; + if (sid == Para_Bufs) + sid = 0; + return 1; + +} +#endif diff --git a/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.h b/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.h new file mode 100644 index 0000000000000000000000000000000000000000..ff82c58cef31d82d1ea69a4c95579c70a02af550 --- /dev/null +++ b/libyangrtc2/src/yangdecoder/YangVideoDecoderIntel.h @@ -0,0 +1,124 @@ +#ifndef YangVideoDecoderIntel_H +#define YangVideoDecoderIntel_H +//#include "../decoder/YangAudioDecoderHandle.h" +#include "Yang_Config.h" +#if HaveLibva +#include "yangdecoder/YangVideoDecoder.h" +#include "yangutil/yangavtype.h" +//#include "YangInitVaPicPara.h" +#include "va/va.h" +#include "va/va_drm.h" +#include "va/va_drmcommon.h" + +//#include "../yangplayer/YangVideoPlay.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/sys/YangLoadLib.h" +#include "YangH264Header.h" +//#include +//#include "YangVaDevice.h" + +//} + +//#define MAX_PARAM_BUFFERS 16 +#define Para_Bufs 7 +typedef struct YangDecodePicture { + VABufferID picBuf; + VABufferID IQMBuf; + VABufferID sliceParaBuf; + VABufferID sliceDataBuf; + +} YangDecodePicture; + + +class YangVideoDecoderIntel:public YangVideoDecoder +{ +public: + YangVideoDecoderIntel(); + ~YangVideoDecoderIntel(); + void init(); + void init(int32_t iW,int32_t iH); + void init(YangVideoParam *p_config); + int32_t decode(YangVideoBuffer *vpl,int32_t isIframe,uint8_t *pData, int32_t nSize, int64_t ptimestamp,uint8_t *dest, int32_t *pnFrameReturned); + void initWH(); + void parseRtmpHeader(uint8_t *p, int32_t pLen,int32_t *pwid,int32_t *phei,int32_t *pfps); + +protected: + void closeDevice(); +private: + int32_t m_fd; + VADisplay m_va_dpy; + VAConfigID m_config_id; + VAContextID m_vaContext; + + VAStatus vas; + + VAImage m_img; + VAImageFormat image_format; + + YangH264Header h264header; + VAPictureH264 m_pic[16]; + int32_t m_ref_count; + int32_t m_ref_count_m1; + + //VAPictureH264 m_old_pic; + VAPictureParameterBufferH264 m_picPara; + + VABufferID bufids[10]; + VAIQMatrixBufferH264 iq_matrix; + VASliceParameterBufferH264 m_slice_param; + + YangDecodePicture pics[Para_Bufs]; + VASurfaceID surface_id[Para_Bufs]; + int32_t sid; + +private: + void cachePic(VAPictureH264 *p_pic,int32_t p_pocind); + void initH264Pic(); + void initH264Slice(); + int32_t m_width; + int32_t m_height; + int32_t m_frame; + int32_t yLen; + int32_t uLen; + int32_t uvLen; + int32_t allLen; + int32_t frameIdx; + int32_t FieldOrderCnt; + int32_t posNum; + void initSlicePara(VASliceParameterBufferH264 *slice264,uint8_t *p_data,int32_t p_len); + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + VADisplay (*yang_vaGetDisplayDRM)(int32_t fd); + VAStatus (*yang_vaInitialize) ( VADisplay dpy, int32_t *major_version,int32_t *minor_version); + VAStatus (*yang_vaDestroyContext) (VADisplay dpy,VAContextID context); + VAStatus (*yang_vaDestroySurfaces) (VADisplay dpy,VASurfaceID *surfaces,int32_t num_surfaces); + VAStatus (*yang_vaDestroyConfig) (VADisplay dpy,VAConfigID config_id); + VAStatus (*yang_vaTerminate) ( VADisplay dpy); + + + VAStatus (*yang_vaCreateConfig) (VADisplay dpy, VAProfile profile, VAEntrypoint32_t entrypoint, VAConfigAttrib *attrib_list, int32_t num_attribs, VAConfigID *config_id ); + + VAStatus (*yang_vaCreateSurfaces)(VADisplay dpy,uint32_t format,uint32_t width, + uint32_t height,VASurfaceID *surfaces,uint32_t num_surfaces, VASurfaceAttrib *attrib_list, + uint32_t num_attribs); + + VAStatus (*yang_vaCreateContext) (VADisplay dpy,VAConfigID config_id, int32_t picture_width, + int32_t picture_height, int32_t flag, VASurfaceID *render_targets, + int32_t num_render_targets,VAContextID *context); + VAStatus (*yang_vaCreateBuffer) (VADisplay dpy,VAContextID context, VABufferType type, + uint32_t size, uint32_t num_elements, void *data, VABufferID *buf_id + ); + VAStatus (*yang_vaBeginPicture) (VADisplay dpy,VAContextID context,VASurfaceID render_target); + VAStatus (*yang_vaRenderPicture) (VADisplay dpy,VAContextID context, VABufferID *buffers,int32_t num_buffers); + + VAStatus (*yang_vaCreateImage) (VADisplay dpy,VAImageFormat *format, int32_t width, int32_t height, VAImage *image); + VAStatus (*yang_vaEndPicture) (VADisplay dpy,VAContextID context); + VAStatus (*yang_vaGetImage) (VADisplay dpy,VASurfaceID surface, int32_t x, + int32_t y,uint32_t width, uint32_t height,VAImageID image); + VAStatus (*yang_vaMapBuffer) (VADisplay dpy,VABufferID buf_id, void **pbuf); + VAStatus (*yang_vaSyncSurface) (VADisplay dpy,VASurfaceID render_target); + VAStatus (*yang_vaUnmapBuffer) (VADisplay dpy,VABufferID buf_id); +}; +#endif +#endif // YANGH264DECODER_H diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoder.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00c5fbf5d0a51d085a09be83718373838569e4f1 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoder.cpp @@ -0,0 +1,20 @@ +#include "yangencoder/YangAudioEncoder.h" + +#include +#include "yangutil/yang_unistd.h" + +YangAudioEncoder::YangAudioEncoder() { + m_isInit=0; + m_uid=-1; + memset(&m_audioInfo,0,sizeof(YangAudioInfo)); + +} +YangAudioEncoder::~YangAudioEncoder(void) { + //m_context = NULL; +} + +void YangAudioEncoder::setAudioPara(YangAudioInfo *pap){ + memcpy(&m_audioInfo,pap,sizeof(YangAudioInfo)); +} + + diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderAac.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderAac.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f242a4de911197804858512b696d7d3dc030b8d9 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderAac.cpp @@ -0,0 +1,110 @@ +#include "YangAudioEncoderAac.h" + +#include "yangutil/yang_unistd.h" +#include "stdio.h" + +void YangAudioEncoderAac::loadLib(){ + yang_faacEncOpen=(faacEncHandle (*)(unsigned long sampleRate, uint32_t numChannels, + unsigned long *inputSamples, unsigned long *maxOutputBytes))m_lib.loadFunction("faacEncOpen"); + + yang_faacEncSetConfiguration=(int32_t (*)(faacEncHandle hEncoder,faacEncConfigurationPtr config))m_lib.loadFunction("faacEncSetConfiguration"); + yang_faacEncEncode=(int32_t (*)(faacEncHandle hEncoder, int32_t * inputBuffer, uint32_t samplesInput, + uint8_t *outputBuffer, + uint32_t bufferSize))m_lib.loadFunction("faacEncEncode"); + yang_faacEncGetCurrentConfiguration=(faacEncConfigurationPtr + (*)(faacEncHandle hEncoder))m_lib.loadFunction("faacEncGetCurrentConfiguration"); + yang_faacEncClose=(int32_t (*)(faacEncHandle hEncoder))m_lib.loadFunction("faacEncClose"); + +} + +void YangAudioEncoderAac::unloadLib(){ + yang_faacEncGetCurrentConfiguration=NULL; + yang_faacEncOpen=NULL; + yang_faacEncSetConfiguration=NULL; + yang_faacEncEncode=NULL; + yang_faacEncClose=NULL; + +} +YangAudioEncoderAac::YangAudioEncoderAac() { + nSampleRate = 44100; + nChannels = 2; + nInputSamples = 0; + nMaxOutputBytes = 0; + + m_aacBuffer = NULL; + ret = 0; + nPCMBitSize = 0; + nInputSamples = 0; + nMaxOutputBytes = 0; + isRec = 0; + hEncoder = NULL; + isamples = 0; + maxsample = 0; + mnInputSamples = 0; + nRet = 0; + + nBytesRead = 0; + nPCMBufferSize = 0; + frames = 0; + unloadLib(); + +} +YangAudioEncoderAac::~YangAudioEncoderAac(void) { + closeAac(); + yang_delete(m_aacBuffer); + unloadLib(); + m_lib.unloadObject(); +} + + + +void YangAudioEncoderAac::init(YangAudioInfo *pap) { + if(m_isInit) return; + m_lib.loadObject("libfaac"); + loadLib(); + setAudioPara(pap); + hEncoder = yang_faacEncOpen(nSampleRate, nChannels, &nInputSamples,&nMaxOutputBytes); + isamples = nInputSamples; + maxsample = nMaxOutputBytes; + mnInputSamples = nInputSamples * 2; + //printf("\n*****is=%d,maxs=%d,mns=%d\n", isamples, maxsample,mnInputSamples); + m_aacBuffer = new uint8_t[nMaxOutputBytes]; + faacEncConfigurationPtr aconfiguration = yang_faacEncGetCurrentConfiguration(hEncoder); + + aconfiguration->version = MPEG4; + + aconfiguration->aacObjectType = LOW; //MAIN;//LOW;//MAIN; + aconfiguration->allowMidside = 1; + aconfiguration->useTns = 0; + aconfiguration->shortctl = SHORTCTL_NORMAL; + //aconfiguration-> + //aconfiguration->nputformat=FAAC_INPUT_16BIT; + aconfiguration->outputFormat = pap->hasAudioHeader; + + aconfiguration->inputFormat = FAAC_INPUT_16BIT; + aconfiguration->bitRate = 128000 / nChannels; + nRet = yang_faacEncSetConfiguration(hEncoder, aconfiguration); + m_isInit=1; + + +} + +int32_t YangAudioEncoderAac::encoder(YangFrame* pframe,YangEncoderCallback* pcallback){ + if(!hEncoder) return 1; + ret = yang_faacEncEncode(hEncoder,(int32_t *) pframe->payload, isamples, m_aacBuffer, maxsample); + + if (ret > 0&&pcallback){ + pframe->payload=m_aacBuffer; + pframe->nb=ret; + pcallback->onAudioData(pframe); + return Yang_Ok; + }else + return 1; +} + + +void YangAudioEncoderAac::closeAac() { + if(hEncoder) yang_faacEncClose(hEncoder); + hEncoder = NULL; +} + diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderAac.h b/libyangrtc2/src/yangencoder/YangAudioEncoderAac.h new file mode 100644 index 0000000000000000000000000000000000000000..a04885c68f16f6d501c7a709945ebfd70282ccb2 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderAac.h @@ -0,0 +1,54 @@ +#ifndef __AudioAacEncoder__ +#define __AudioAacEncoder__ +#include "faac.h" + +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/sys/YangLoadLib.h" +#include "yangencoder/YangAudioEncoder.h" + +class YangAudioEncoderAac: public YangAudioEncoder +{ +public: + YangAudioEncoderAac(); + ~YangAudioEncoderAac(void); + void init(YangAudioInfo *pap); + int32_t encoder(YangFrame* pframe,YangEncoderCallback* pcallback); + +private: + uint8_t *m_aacBuffer; + + int32_t frames; + int32_t mnInputSamples; + uint32_t isamples, maxsample; + unsigned long nSampleRate; + uint32_t nChannels; + uint32_t nPCMBitSize; + unsigned long nInputSamples; + unsigned long nMaxOutputBytes; + + int32_t nRet; + int32_t nBytesRead; + int32_t nPCMBufferSize; + +private: + YangLoadLib m_lib; + void encoder(int32_t *p_buf); + void closeAac(); + void saveWave(); + int32_t ret;//, isConvert; + int32_t isRec; + faacEncHandle hEncoder; + void loadLib(); + void unloadLib(); + faacEncHandle (*yang_faacEncOpen)(unsigned long sampleRate, uint32_t numChannels, + unsigned long *inputSamples, unsigned long *maxOutputBytes); + int32_t (*yang_faacEncSetConfiguration)(faacEncHandle hEncoder,faacEncConfigurationPtr config); + int32_t (*yang_faacEncEncode)(faacEncHandle hEncoder, int32_t * inputBuffer, uint32_t samplesInput, + uint8_t *outputBuffer, uint32_t bufferSize); + int32_t (*yang_faacEncClose)(faacEncHandle hEncoder); + faacEncConfigurationPtr + (*yang_faacEncGetCurrentConfiguration)(faacEncHandle hEncoder); +}; + +#endif diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderHandle.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d86de052217f03562760e741c0319b1f4d1914bf --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderHandle.cpp @@ -0,0 +1,100 @@ +#include "yangencoder/YangAudioEncoderHandle.h" + +#include "malloc.h" +#include +#include +#include +#include "stdlib.h" +#include "yangencoder/YangEncoderFactory.h" + +YangAudioEncoderHandle::YangAudioEncoderHandle(YangAudioInfo *pcontext) { + m_isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_audioBuffer = NULL; + m_enc = NULL; + m_out_audioBuffer = NULL; + m_context = pcontext; + m_uid=0; + +} + +YangAudioEncoderHandle::~YangAudioEncoderHandle(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + yang_delete(m_enc); + m_context = NULL; + m_in_audioBuffer = NULL; + m_out_audioBuffer = NULL; +} +void YangAudioEncoderHandle::stop() { + stopLoop(); +} + +void YangAudioEncoderHandle::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +void YangAudioEncoderHandle::init() { + if (m_isInit) + return; + YangEncoderFactory ydf; + if (!m_enc) + m_enc = ydf.createAudioEncoder(m_context); + m_enc->init(m_context); + m_isInit = 1; + +} + +void YangAudioEncoderHandle::setInAudioBuffer(YangAudioBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} +void YangAudioEncoderHandle::setOutAudioBuffer(YangAudioEncoderBuffer *pbuf) { + m_out_audioBuffer = pbuf; +} + +void YangAudioEncoderHandle::onVideoData(YangFrame* pframe) { + +} +void YangAudioEncoderHandle::onAudioData(YangFrame* pframe) { + + m_out_audioBuffer->putAudio(pframe); +} +void YangAudioEncoderHandle::startLoop() { + if(m_in_audioBuffer==NULL) return; + m_isConvert = 1; + uint8_t t_buf1[4096]; + + yang_reindex(m_in_audioBuffer); + yang_reindex(m_out_audioBuffer); + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + while (m_isConvert == 1) { + if (m_in_audioBuffer->size() == 0) { + yang_usleep(200); + continue; + } + audioFrame.payload=t_buf1; + audioFrame.uid=m_uid; + audioFrame.nb=0; + if (m_in_audioBuffer->getAudio(&audioFrame)) { + yang_usleep(1000); + continue; + } else { + m_enc->encoder(&audioFrame, this); + + } + } //end + +} + +void YangAudioEncoderHandle::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderHandleCb.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderHandleCb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e7159f496ec72d82260f962c848673c74ccfa33 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderHandleCb.cpp @@ -0,0 +1,95 @@ +#include "yangencoder/YangAudioEncoderHandleCb.h" + +#include "malloc.h" +#include +#include +#include +#include "stdlib.h" +#include "yangencoder/YangEncoderFactory.h" + +YangAudioEncoderHandleCb::YangAudioEncoderHandleCb(YangAudioInfo *pcontext) { + m_isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_audioBuffer = NULL; + m_enc = NULL; + //m_out_audioBuffer = NULL; + m_context = pcontext; + m_cb=NULL; + m_uid=0; +} + +YangAudioEncoderHandleCb::~YangAudioEncoderHandleCb(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + yang_delete(m_enc); + m_context = NULL; + m_in_audioBuffer = NULL; + m_cb=NULL; + +} +void YangAudioEncoderHandleCb::stop() { + stopLoop(); +} + +void YangAudioEncoderHandleCb::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +void YangAudioEncoderHandleCb::init() { + if (m_isInit) + return; + YangEncoderFactory ydf; + if (!m_enc) + m_enc = ydf.createAudioEncoder(m_context); + m_enc->init(m_context); + m_isInit = 1; + +} +void YangAudioEncoderHandleCb::setCallback(YangEncoderCallback* pcb){ + m_cb=pcb; +} +void YangAudioEncoderHandleCb::setInAudioBuffer(YangAudioBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} + + + +void YangAudioEncoderHandleCb::startLoop() { + m_isConvert = 1; + + + uint8_t t_buf1[4096]; + yang_reindex(m_in_audioBuffer); + YangFrame audioFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + audioFrame.uid=m_uid; + while (m_isConvert == 1) { + if (m_in_audioBuffer->size() == 0) { + yang_usleep(200); + continue; + } + audioFrame.payload=t_buf1; + if (m_in_audioBuffer->getAudio(&audioFrame)) { + yang_usleep(2000); + continue; + } else { + + m_enc->encoder(&audioFrame, m_cb); + + } + } //end + +} + +void YangAudioEncoderHandleCb::stopLoop() { + m_isConvert = 0; + +} + diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderMeta.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75d3cc0eae65ccd27e64dcc7345707c2ce5b9b28 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderMeta.cpp @@ -0,0 +1,94 @@ +/* + * YangAudioEncoderMeta.cpp + * + * Created on: 2019年10月8日 + * Author: yang + */ +#include +#include +#include +#include +#include +#include + + + + +void YangAudioEncoderMeta::loadLib(){ + yang_faacEncOpen=(faacEncHandle (*)(unsigned long sampleRate, uint32_t numChannels, + unsigned long *inputSamples, unsigned long *maxOutputBytes))m_lib.loadFunction("faacEncOpen"); + + yang_faacEncSetConfiguration=(int32_t (*)(faacEncHandle hEncoder,faacEncConfigurationPtr config))m_lib.loadFunction("faacEncSetConfiguration"); + yang_faacEncEncode=(int32_t (*)(faacEncHandle hEncoder, int32_t * inputBuffer, uint32_t samplesInput, + uint8_t *outputBuffer, + uint32_t bufferSize))m_lib.loadFunction("faacEncEncode"); + yang_faacEncGetCurrentConfiguration=(faacEncConfigurationPtr + (*)(faacEncHandle hEncoder))m_lib.loadFunction("faacEncGetCurrentConfiguration"); + yang_faacEncClose=(int32_t (*)(faacEncHandle hEncoder))m_lib.loadFunction("faacEncClose"); + + yang_faacEncGetDecoderSpecificInfo=(int32_t (*)(faacEncHandle hEncoder, uint8_t **ppBuffer, + unsigned long *pSizeOfDecoderSpecificInfo))m_lib.loadFunction("faacEncGetDecoderSpecificInfo"); + +} + +void YangAudioEncoderMeta::unloadLib(){ + yang_faacEncGetCurrentConfiguration=NULL; + yang_faacEncOpen=NULL; + yang_faacEncSetConfiguration=NULL; + yang_faacEncEncode=NULL; + yang_faacEncClose=NULL; + yang_faacEncGetDecoderSpecificInfo=NULL; + +} +YangAudioEncoderMeta::YangAudioEncoderMeta(){ + unloadLib(); +} + +YangAudioEncoderMeta::~YangAudioEncoderMeta(){ + unloadLib(); + m_lib.unloadObject(); +} + + +void YangAudioEncoderMeta::createMeta(uint8_t *pasc,int32_t *asclen){ + + m_lib.loadObject("libfaac"); + loadLib(); + faacEncHandle hEncoder=NULL; + unsigned long nSampleRate = 44100; + uint32_t nChannels = 2; + //nPCMBitSize = 16; + unsigned long nInputSamples = 0; + unsigned long nMaxOutputBytes = 0; + hEncoder = yang_faacEncOpen(nSampleRate, nChannels, &nInputSamples,&nMaxOutputBytes); + faacEncConfigurationPtr aconfiguration = yang_faacEncGetCurrentConfiguration(hEncoder); + + aconfiguration->version = MPEG4; + + aconfiguration->aacObjectType = LOW; //MAIN;//LOW;//MAIN; + aconfiguration->allowMidside = 1; + aconfiguration->useTns = 0; + aconfiguration->shortctl = SHORTCTL_NORMAL; + //aconfiguration-> + //aconfiguration->nputformat=FAAC_INPUT_16BIT; + aconfiguration->outputFormat = 0; + + aconfiguration->inputFormat = FAAC_INPUT_16BIT; + aconfiguration->bitRate = 128000 / 2; + //aconfiguration-> + int32_t nRet = yang_faacEncSetConfiguration(hEncoder, aconfiguration); + + + uint8_t *asc=NULL; + unsigned long len=0; + yang_faacEncGetDecoderSpecificInfo(hEncoder, &asc, &len); + if(asc){ + memcpy(pasc,asc,len); + *asclen=len; + yang_faacEncClose(hEncoder); + hEncoder=NULL; + //yang_free(asc); + + } + +} diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5b2124ef5f85cda62fcdddf1543702fef036aea --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.cpp @@ -0,0 +1,163 @@ +#include "YangAudioEncoderMp3.h" + +#include "yangutil/yang_unistd.h" +#include "stdio.h" + +void YangAudioEncoderMp3::loadLib() { + + yang_lame_init = (lame_global_flags* (*)(void))m_lib.loadFunction("lame_init"); + yang_lame_init_params=(int32_t (*)(lame_global_flags *))m_lib.loadFunction("lame_init_params"); + yang_lame_set_preset=(int32_t (*)( lame_global_flags* gfp, int32_t ))m_lib.loadFunction("lame_set_preset"); + yang_lame_set_in_samplerate=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_in_samplerate"); + yang_lame_set_VBR=(int32_t (*)(lame_global_flags *, vbr_mode))m_lib.loadFunction("lame_set_VBR"); + yang_lame_set_mode=(int32_t (*)(lame_global_flags *, MPEG_mode))m_lib.loadFunction("lame_set_mode"); + yang_lame_set_num_channels=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_num_channels"); + yang_lame_set_brate=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_brate"); + yang_lame_set_strict_ISO=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_strict_ISO"); + yang_lame_set_original=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_original"); + yang_lame_set_error_protection=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_error_protection"); + yang_lame_set_extension=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_extension"); + yang_lame_set_disable_reservoir=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_disable_reservoir"); + yang_lame_set_bWriteVbrTag=(int32_t (*)(lame_global_flags *, int))m_lib.loadFunction("lame_set_bWriteVbrTag"); + yang_lame_encode_buffer_interleaved=(int32_t (*)(lame_global_flags* gfp, + int16_t pcm[],int32_t num_samples, uint8_t* mp3buf, + int32_t mp3buf_size ))m_lib.loadFunction("lame_encode_buffer_interleaved"); + yang_lame_close=(int32_t (*) (lame_global_flags *))m_lib.loadFunction("lame_close"); +} + +void YangAudioEncoderMp3::unloadLib() { + yang_lame_init = NULL; + yang_lame_init_params = NULL; + yang_lame_set_preset = NULL; + yang_lame_set_in_samplerate = NULL; + yang_lame_set_VBR = NULL; + yang_lame_set_mode = NULL; + yang_lame_set_num_channels = NULL; + yang_lame_set_brate = NULL; + yang_lame_set_strict_ISO = NULL; + yang_lame_set_original = NULL; + yang_lame_set_error_protection = NULL; + yang_lame_set_extension = NULL; + yang_lame_set_disable_reservoir = NULL; + yang_lame_set_bWriteVbrTag = NULL; + yang_lame_encode_buffer_interleaved = NULL; + yang_lame_close = NULL; +} + +YangAudioEncoderMp3::YangAudioEncoderMp3() { + m_Lame_Sample_Number = 1152; + ret = 0; + preSize = 0; + dwSamples = 0; + dwRead = 0; + dwWrite = 0; + dwDone = 0; + dwFileSize = 0; + m_bufLen = 0; + + dwMP3Buffer = 0; + pMP3Buffer = NULL; + pWAVBuffer = NULL; + gfp = NULL; + temp = NULL; + //isConvert = 0; + unloadLib(); + +} + +YangAudioEncoderMp3::~YangAudioEncoderMp3(void) { + closeMp3(); + yang_deleteA(temp); + yang_deleteA(pWAVBuffer); + yang_deleteA(pMP3Buffer); + unloadLib(); + m_lib.unloadObject(); + +} + +void YangAudioEncoderMp3::init(YangAudioInfo *pap) { + if (m_isInit == 1) + return; + m_lib.loadObject("libmp3lame"); + loadLib(); + setAudioPara(pap); + dwSamples = 0; + dwMP3Buffer = 0; + pMP3Buffer = NULL; + pWAVBuffer = NULL; + + gfp = NULL; + gfp = yang_lame_init(); + yang_lame_set_in_samplerate(gfp, m_audioInfo.sample); + + yang_lame_set_preset(gfp, m_audioInfo.bitrate); + //lame_set_preset( gfp, R3MIX); + yang_lame_set_VBR(gfp, vbr_off); + yang_lame_set_mode(gfp, STEREO); //JOINT_STEREO STEREO + yang_lame_set_num_channels(gfp, 2); + yang_lame_set_brate(gfp, m_audioInfo.bitrate); + //lame_set_quality(gfp,); + yang_lame_set_strict_ISO(gfp, 1); + yang_lame_set_original(gfp, 1); + yang_lame_set_error_protection(gfp, 0); + yang_lame_set_extension(gfp, 0); + yang_lame_set_disable_reservoir(gfp, 1); + yang_lame_set_bWriteVbrTag(gfp, 1); + int32_t ret_code = yang_lame_init_params(gfp); + if (ret_code < 0) { + printf("lame_init_params failure returned %d\n", ret_code); + } else { + //printf("lame_init_params success returned %d\n", ret_code); + } + + dwSamples = 1152 * 2; + dwMP3Buffer = (DWORD) (1.25 * (dwSamples / 2) + 7200); + + pMP3Buffer = new uint8_t[dwMP3Buffer]; + pWAVBuffer = new short[dwSamples * 8]; + + temp = new uint8_t[1152 * 8]; + //dwRead=0; + dwWrite = 0; + dwDone = 0; + dwFileSize = 0; + m_isInit = 1; + dwRead = m_Lame_Sample_Number * 4; + +} + + +int32_t YangAudioEncoderMp3::encoder(YangFrame* pframe,YangEncoderCallback *pcallback) { + memcpy(temp + m_bufLen, pframe->payload, pframe->nb); + + m_bufLen += pframe->nb; + if (m_bufLen < dwRead) + return 1; + + memcpy(pWAVBuffer, temp, dwRead); + dwWrite = yang_lame_encode_buffer_interleaved(gfp, pWAVBuffer, 1152, + pMP3Buffer, 0); + + if (dwWrite > 0) { + pframe->payload=pMP3Buffer; + pframe->nb=dwWrite; + pcallback->onAudioData(pframe); + return Yang_Ok; + + } + m_bufLen -= dwRead; + + if (m_bufLen < dwRead && m_bufLen > 0) { + memcpy(temp, temp + dwRead, m_bufLen); + } + return Yang_Ok; +} + +void YangAudioEncoderMp3::closeMp3() { + if (gfp != NULL) + yang_lame_close(gfp); + gfp = NULL; + ret = 2; + +} + diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.h b/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.h new file mode 100644 index 0000000000000000000000000000000000000000..9c628f169a790483eda4ee8a1a9c0281ceca7906 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderMp3.h @@ -0,0 +1,65 @@ +#ifndef __YangAudioMp3Encoder__ +#define __YangAudioMp3Encoder__ +#include +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +extern "C"{ +#include "lame.h" +} +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangencoder/YangAudioEncoder.h" +#include "yangutil/sys/YangLoadLib.h" +#ifndef _WIN32 +typedef int32_t DWORD ; +#endif +class YangAudioEncoderMp3:public YangAudioEncoder +{ +public: + YangAudioEncoderMp3(); + ~YangAudioEncoderMp3(void); + void init(YangAudioInfo *pap); + int32_t encoder(YangFrame* pframe,YangEncoderCallback* pcallback); + + +private: + uint8_t *temp;//[1153*2+44100*2]; + uint8_t *pMP3Buffer; + short* pWAVBuffer; + lame_global_flags *gfp; + int m_Lame_Sample_Number; + int32_t m_bufLen;//m_Audio_Frame_Size,; + DWORD dwSamples; + DWORD dwRead; + DWORD dwWrite; + DWORD dwDone; + DWORD dwFileSize; + int32_t preSize; + +private: + YangLoadLib m_lib; + void closeMp3(); + int dwMP3Buffer ; + int32_t ret; + void loadLib(); + void unloadLib(); + lame_global_flags * (*yang_lame_init)(void); + int32_t (*yang_lame_init_params)(lame_global_flags *); + int32_t (*yang_lame_set_preset)( lame_global_flags* gfp, int32_t ); + int32_t (*yang_lame_set_in_samplerate)(lame_global_flags *, int); + int32_t (*yang_lame_set_VBR)(lame_global_flags *, vbr_mode); + int32_t (*yang_lame_set_mode)(lame_global_flags *, MPEG_mode); + int32_t (*yang_lame_set_num_channels)(lame_global_flags *, int); + int32_t (*yang_lame_set_brate)(lame_global_flags *, int); + int32_t (*yang_lame_set_strict_ISO)(lame_global_flags *, int); + int32_t (*yang_lame_set_original)(lame_global_flags *, int); + int32_t (*yang_lame_set_error_protection)(lame_global_flags *, int); + int32_t (*yang_lame_set_extension)(lame_global_flags *, int); + int32_t (*yang_lame_set_disable_reservoir)(lame_global_flags *, int); + int32_t (*yang_lame_set_bWriteVbrTag)(lame_global_flags *, int); + int32_t (*yang_lame_encode_buffer_interleaved)(lame_global_flags* gfp, + int16_t pcm[],int32_t num_samples, uint8_t* mp3buf, + int32_t mp3buf_size ); + int32_t (*yang_lame_close) (lame_global_flags *); + +}; +#endif + diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1061233e49b2cb6af08db37a6e13145415cbf140 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.cpp @@ -0,0 +1,180 @@ +/* + * YangAudioEncoderOpus.cpp + * + * Created on: 2019年9月29日 + * Author: yang + */ +#include "YangAudioEncoderOpus.h" + +#include "yangutil/yang_unistd.h" +#include "stdio.h" +#include "string.h" + + +void YangAudioEncoderOpus::loadLib() { + yang_opus_encoder_create = (OpusEncoder* (*)(opus_int32 Fs, int32_t channels, + int32_t application, int32_t *error)) m_lib.loadFunction( + "opus_encoder_create"); + yang_opus_encoder_init = (int32_t (*)(OpusEncoder *st, opus_int32 Fs, + int32_t channels, int32_t application)) m_lib.loadFunction( + "opus_encoder_init"); + yang_opus_encode = + (opus_int32 (*)(OpusEncoder *st, const opus_int16 *pcm, + int32_t frame_size, uint8_t *data, + opus_int32 max_data_bytes)) m_lib.loadFunction( + "opus_encode"); + yang_opus_encoder_ctl = + (int32_t (*)(OpusEncoder *st, int32_t request, ...)) m_lib.loadFunction( + "opus_encoder_ctl"); + yang_opus_encoder_destroy = (void (*)(OpusEncoder *st)) m_lib.loadFunction( + "opus_encoder_destroy"); + yang_opus_strerror = (const char* (*)(int32_t error)) m_lib.loadFunction( + "opus_strerror"); +} + +void YangAudioEncoderOpus::unloadLib() { + yang_opus_encoder_create = NULL; + yang_opus_encoder_init = NULL; + yang_opus_encode = NULL; + yang_opus_encoder_ctl = NULL; + yang_opus_encoder_destroy = NULL; + yang_opus_strerror = NULL; +} +YangAudioEncoderOpus::YangAudioEncoderOpus() { + ret = 0; + m_cbits = NULL; + m_encoder = NULL; + m_input1 = NULL; + m_input = NULL; + m_in = NULL; + m_frameShortSize=0; + m_frameSize=0; + //temp = NULL; + unloadLib(); +} + +YangAudioEncoderOpus::~YangAudioEncoderOpus() { + closeEnc(); + yang_deleteA(m_cbits); + + yang_deleteA(m_in); + yang_deleteA(m_input1); + yang_deleteA(m_input); + + + unloadLib(); + m_lib.unloadObject(); +} + +#define MAX_PACKET_SIZE (3*1276) +void YangAudioEncoderOpus::init(YangAudioInfo *pap) { + if (m_isInit) + return; + + m_lib.loadObject("libopus"); + loadLib(); + setAudioPara(pap); + int32_t err = 0; + + m_encoder = yang_opus_encoder_create(m_audioInfo.sample, m_audioInfo.channel, + OPUS_APPLICATION_VOIP, &err);//OPUS_APPLICATION_AUDIO + if (err < 0) { + fprintf(stderr, "failed to create an Opus encoder: %s\n", + yang_opus_strerror(err)); +#ifdef _MSC_VER + ExitProcess(1); +#else + _exit(0); +#endif + + } + yang_opus_encoder_ctl(m_encoder, OPUS_SET_VBR(0)); + //#define BITRATE 16000 + //#define BITRATE 16000 +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_BITRATE(bitrate_bps)); + if (m_audioInfo.usingMono) + yang_opus_encoder_ctl(m_encoder, + OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_VBR(use_vbr)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_VBR_CONSTRAINT(cvbr)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_COMPLEXITY(10)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_INBAND_FEC(use_inbandfec)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_FORCE_CHANNELS(forcechannels)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_DTX(use_dtx)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); + int32_t skip = 0; + yang_opus_encoder_ctl(m_encoder, OPUS_GET_LOOKAHEAD(&skip)); + yang_opus_encoder_ctl(m_encoder, OPUS_SET_LSB_DEPTH(16)); +//yang_opus_encoder_ctl(m_encoder, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration)); + + m_frameSize=m_audioInfo.sample/50; + + m_frameShortSize=m_frameSize*m_audioInfo.channel; + m_in = new short[m_frameShortSize]; + m_cbits = new uint8_t[MAX_PACKET_SIZE]; + m_input = new uint8_t[m_frameShortSize*2]; + m_input1 = new short[m_frameShortSize]; + m_isInit = 1; + +} + + +int32_t YangAudioEncoderOpus::encoder(YangFrame* pframe,YangEncoderCallback *pcallback) { + if (!m_encoder) return 1; + + memcpy(m_input, pframe->payload, pframe->nb); + for (int32_t i = 0; i < m_frameShortSize; i++) { + m_input1[i] = m_input[2 * i + 1] << 8 | m_input[2 * i]; + } + + ret = yang_opus_encode(m_encoder, m_input1, m_frameSize, m_cbits, MAX_PACKET_SIZE); + if (ret > 0 && pcallback){ + pframe->payload=m_cbits; + pframe->nb=ret; + pcallback->onAudioData(pframe); + + } + + + return Yang_Ok; +} +/** + void YangAudioEncoderOpus::encoder(uint8_t *p_buf,int32_t bufLen){ + if(!m_encoder) return; + if(m_yap.usingMono){ + memcpy(m_input, p_buf, 640); + for (int32_t i=0;i 0 && m_pipe) m_pipe->putPipeData( m_cbits, ret); + }else{ + memcpy(temp + m_bufLen, p_buf, 4096); + m_bufLen = m_bufLen + 4096; + int32_t len = 0; + int32_t frameSize=(m_yap.sample/50)*4; + //int32_t readLen=frameSize; + while (m_bufLen >= frameSize) { + memcpy((char*)m_in, temp + len, frameSize); + ret = yang_opus_encode(m_encoder,m_in, frameSize, m_cbits, MAX_PACKET_SIZE); + if (ret > 0 && m_pipe) m_pipe->putPipeData((uint8_t*) m_cbits, ret); + //printf("%d,",ret); + m_bufLen -= frameSize; + len += frameSize; + } + memcpy(temp, temp + len, m_bufLen); + } + } + + void YangAudioEncoderOpus::encoder(uint8_t *p_buf,int32_t bufLen,uint8_t *p_out,int32_t *outLen){ + + } + **/ +void YangAudioEncoderOpus::closeEnc() { + + if (m_encoder) + yang_opus_encoder_destroy(m_encoder); + m_encoder = NULL; + +} diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.h b/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.h new file mode 100644 index 0000000000000000000000000000000000000000..e7762f32c0d5bb56fdb00860145c8d99cac5d2df --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderOpus.h @@ -0,0 +1,49 @@ +/* + * YangAudioEncoderOpus.h + * + * Created on: 2019年9月29日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGAUDIOENCODEROPUS_H_ +#define YANGENCODER_SRC_YANGAUDIOENCODEROPUS_H_ +#include "opus/opus.h" +#include "yangutil/sys/YangLoadLib.h" +#include "yangencoder/YangAudioEncoder.h" + +class YangAudioEncoderOpus: public YangAudioEncoder { +public: + YangAudioEncoderOpus(); + virtual ~YangAudioEncoderOpus(); + void init(YangAudioInfo *pap); + int32_t encoder(YangFrame* pframe,YangEncoderCallback* pcallback); + +private: + int32_t ret; + int32_t m_frameSize; + int32_t m_frameShortSize; + OpusEncoder *m_encoder; + YangLoadLib m_lib; + + uint8_t *m_cbits; //[YangSpeexBufferSize]; + uint8_t *m_input; + short *m_in; + short *m_input1; //[m_frameSize]; + + + void encoder(uint8_t *p_buf); + void encoder_mono(uint8_t *p_buf); + + void closeEnc(); + void loadLib(); + void unloadLib(); + OpusEncoder *(*yang_opus_encoder_create)(opus_int32 Fs, int32_t channels, int32_t application, int32_t *error); + int32_t (*yang_opus_encoder_init)(OpusEncoder *st, opus_int32 Fs, int32_t channels, int32_t application) ; + opus_int32 (*yang_opus_encode)(OpusEncoder *st,const opus_int16 *pcm, int32_t frame_size, uint8_t *data, + opus_int32 max_data_bytes); + int32_t (*yang_opus_encoder_ctl)(OpusEncoder *st, int32_t request, ...); + void (*yang_opus_encoder_destroy)(OpusEncoder *st); + const char *(*yang_opus_strerror)(int32_t error); +}; + +#endif /* YANGENCODER_SRC_YANGAUDIOENCODEROPUS_H_ */ diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.cpp b/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e51aa1c4ab0fa08c98cf802a7b9cfeea33b3275 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.cpp @@ -0,0 +1,215 @@ +/* + * YangAudioEncoderSpeex.cpp + * + * Created on: 2019年9月8日 + * Author: yang + */ + +#include "YangAudioEncoderSpeex.h" + +#include "yangutil/yang_unistd.h" +#include "stdio.h" +#include "string.h" + + +void YangAudioEncoderSpeex::loadLib() { + yang_speex_lib_get_mode = + (const SpeexMode* (*)(int32_t mode)) m_lib.loadFunction( + "speex_lib_get_mode"); + yang_speex_encoder_ctl = + (int32_t (*)(void *state, int32_t request, void *ptr)) m_lib.loadFunction( + "speex_encoder_ctl"); + yang_speex_encoder_init = + (void* (*)(const SpeexMode *mode)) m_lib.loadFunction( + "speex_encoder_init"); + yang_speex_bits_init = (void (*)(SpeexBits *bits)) m_lib.loadFunction( + "speex_bits_init"); + yang_speex_bits_reset = (void (*)(SpeexBits *bits)) m_lib.loadFunction( + "speex_bits_reset"); + yang_speex_bits_write = + (int32_t (*)(SpeexBits *bits, char *bytes, int32_t max_len)) m_lib.loadFunction( + "speex_bits_write"); + yang_speex_encode = + (int32_t (*)(void *state, float *in, SpeexBits *bits)) m_lib.loadFunction( + "speex_encode"); + yang_speex_encoder_destroy = (void (*)(void *state)) m_lib.loadFunction( + "speex_encoder_destroy"); + yang_speex_bits_destroy = (void (*)(SpeexBits *bits)) m_lib.loadFunction( + "speex_bits_destroy"); +} + +void YangAudioEncoderSpeex::unloadLib() { + yang_speex_lib_get_mode = NULL; + yang_speex_encoder_init = NULL; + yang_speex_bits_init = NULL; + yang_speex_bits_reset = NULL; + yang_speex_bits_write = NULL; + yang_speex_encode = NULL; + yang_speex_encoder_destroy = NULL; + yang_speex_bits_destroy = NULL; +} +YangAudioEncoderSpeex::YangAudioEncoderSpeex() { + //m_context = conf; + isConvert = 0; + m_quality = 8; + m_state = NULL; + ret = 0; + m_cbits = new char[600]; + + m_bufLen = 0; + skip_group_delay = 0; + //m_mode = speex_wb_mode; + temp = NULL; //new char[8096]; + + m_input = NULL; + m_input1 = NULL; + m_in = NULL; + unloadLib(); + +} +YangAudioEncoderSpeex::~YangAudioEncoderSpeex(void) { + closeSpeex(); + yang_deleteA(m_cbits); + yang_deleteA(temp); + //yang_deleteA(m_outData); + yang_deleteA(m_input1); + yang_deleteA(m_input); + yang_deleteA(m_in); + + unloadLib(); + m_lib.unloadObject(); +} + +void YangAudioEncoderSpeex::initSpeexPara() { + //if (m_mode == speex_nb_mode) { + // m_quality = 6; + //m_frameSize = 160; + //} + //if (m_mode == speex_wb_mode) { + m_quality = 10; + // m_frameSize = 320; +// } + //if (m_mode == speex_uwb_mode) { + // m_quality = 10; + // m_frameSize = 640; + //} +} + +void YangAudioEncoderSpeex::init(YangAudioInfo *pap) { + if (m_isInit) + return; + //printf("\n******************************speex is initing.........................\n"); + m_lib.loadObject("libspeex"); + loadLib(); + setAudioPara(pap); + m_state = yang_speex_encoder_init(yang_speex_lib_get_mode(SPEEX_MODEID_WB));//speex_wb_mode &speex_nb_mode); + //speex_lib_get_mode(SPEEX_MODEID_WB); + //const SpeexMode * speex_lib_get_mode (int32_t mode); + //initSpeexPara(); + //m_quality = 8; + m_quality = 10; + //m_frameSize = 320; + //m_channel=1; + //int32_t samplerate = m_context->sample; + yang_speex_encoder_ctl(m_state, SPEEX_SET_QUALITY, &m_quality); + //speex_encoder_ctl(m_state, SPEEX_SET_SAMPLING_RATE, &samplerate); + //int32_t tmp = 0; + //speex_encoder_ctl(m_state, SPEEX_SET_VBR, &tmp); + //tmp = 10; + //speex_encoder_ctl(m_state, SPEEX_SET_QUALITY, &tmp); + //tmp = 1; +// speex_encoder_ctl(m_state, SPEEX_SET_COMPLEXITY, &tmp); + + //speex_encoder_ctl(m_state, SPEEX_GET_BITRATE, &tmp); + //int32_t sam=0; + //speex_encoder_ctl(m_state, SPEEX_GET_SAMPLING_RATE, &sam); + +// m_resample->init(2,m_context->sample,16000); + //speex_encoder_ctl(m_state, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + + // int32_t frameSize=0; +// speex_encoder_ctl(m_state, SPEEX_GET_FRAME_SIZE, &m_frameSize); + //printf("\nframeSize==%d,bitrate==%d,sample=%d\n", m_frameSize,tmp,sam); + if (!m_audioInfo.usingMono) { + m_in = new short[882 * 2]; + temp = new char[1024 * 8]; + m_input = new float[m_audioInfo.frameSize * m_audioInfo.channel]; + m_input1 = new short[m_audioInfo.frameSize * m_audioInfo.channel]; + } else { + m_input1 = new short[320]; + m_input = new float[320]; + } + + //SPEEX_SET_BITRATE + yang_speex_bits_init(&m_bits); + + m_isInit = 1; + //speex_encode_stereo() + +} + + +int32_t YangAudioEncoderSpeex::encoder(YangFrame* pframe,YangEncoderCallback *pcallback) { + + if (!m_state) + return 1; + if (m_audioInfo.usingMono) { + memcpy((char*) m_input1, pframe->payload, 640); + for (int32_t i = 0; i < 320; i++) { + m_input[i] = m_input1[i]; + } + yang_speex_bits_reset(&m_bits); + //speex_encode_int(m_state, m_in, &m_bits); + yang_speex_encode(m_state, m_input, &m_bits); + ret = yang_speex_bits_write(&m_bits, m_cbits, 300); + //printf("m%d,",ret); + if (ret > 0 && pcallback) { + pframe->payload=(uint8_t*) m_cbits; + pframe->nb=ret; + pcallback->onAudioData(pframe); + return Yang_Ok; + } + return 1; + //if (ret > 0 && m_pipe) m_pipe->putPipeData((uint8_t*) m_cbits, ret); + } + return 1; + +} + +/** + void YangAudioEncoderSpeex::encoder(uint8_t *p_buf,int32_t bufLen,YangAudioEncoderBuffer* pbuf){ + if(!m_state) return; + if(m_yap.usingMono){ + memcpy((char*)m_input1, p_buf, 640); + for(int32_t i=0;i<320;i++){ + m_input[i]=m_input1[i]; + } + yang_speex_bits_reset(&m_bits); + //speex_encode_int(m_state, m_in, &m_bits); + yang_speex_encode(m_state,m_input, &m_bits); + ret = yang_speex_bits_write(&m_bits, m_cbits, 300); + //printf("m%d,",ret); + if (ret > 0 && pbuf) pbuf->putAudio((uint8_t*) m_cbits, ret); + }else{ + + } + } + void YangAudioEncoderSpeex::encoder(uint8_t *p_buf,int32_t bufLen,uint8_t *p_out,int32_t *outLen){ + + } + void YangAudioEncoderSpeex::encoder_mono(char *p_buf){ + + + //printf("%d,",ret); + + } + + + **/ +void YangAudioEncoderSpeex::closeSpeex() { + if (m_state) + yang_speex_encoder_destroy(m_state); + m_state = NULL; + yang_speex_bits_destroy(&m_bits); + //hEncoder = NULL; +} diff --git a/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.h b/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.h new file mode 100644 index 0000000000000000000000000000000000000000..95148c11be65b98298c56ac9a388b11f88a76967 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangAudioEncoderSpeex.h @@ -0,0 +1,58 @@ +/* + * YangAudioEncoderSpeex.h + * + * Created on: 2019年9月8日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGAUDIOENCODERSPEEX_H_ +#define YANGENCODER_SRC_YANGAUDIOENCODERSPEEX_H_ + +#include "speex/speex.h" +//#include "../../yangaudioproc/YangResample.h" +#include "yangutil/sys/YangLoadLib.h" +#include "yangencoder/YangAudioEncoder.h" +//#define YangSpeexBufferSize 1024 + +class YangAudioEncoderSpeex: public YangAudioEncoder { +public: + YangAudioEncoderSpeex(); + virtual ~YangAudioEncoderSpeex(); + void init(YangAudioInfo *pap); + int32_t encoder(YangFrame* pframe,YangEncoderCallback* pcallback); + +private: + int32_t isConvert; + SpeexBits m_bits; + + YangLoadLib m_lib; + void initSpeexPara(); + int32_t m_quality; + int32_t ret; + spx_int32_t skip_group_delay; + void *m_state; + char *m_cbits; //[YangSpeexBufferSize]; + int32_t m_bufLen; + char *temp; + float *m_input; + short *m_input1; //[m_frameSize]; + short *m_in; //[m_frameSize]; + + void encoder(char *p_buf); + void encoder_mono(char *p_buf); + void closeSpeex(); + void saveWave(); + void loadLib(); + void unloadLib(); + const SpeexMode * (*yang_speex_lib_get_mode) (int32_t mode); + void *(*yang_speex_encoder_init)(const SpeexMode *mode); + void (*yang_speex_bits_init)(SpeexBits *bits); + void (*yang_speex_bits_reset)(SpeexBits *bits); + int32_t (*yang_speex_bits_write)(SpeexBits *bits, char *bytes, int32_t max_len); + int32_t (*yang_speex_encode)(void *state, float *in, SpeexBits *bits); + void (*yang_speex_encoder_destroy)(void *state); + void (*yang_speex_bits_destroy)(SpeexBits *bits); + int32_t (*yang_speex_encoder_ctl)(void *state, int32_t request, void *ptr); +}; + +#endif /* YANGENCODER_SRC_YANGAUDIOENCODERSPEEX_H_ */ diff --git a/libyangrtc2/src/yangencoder/YangEncoderFactory.cpp b/libyangrtc2/src/yangencoder/YangEncoderFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..332e35d7dd7520da06f24f9f22d8f0eb0fa91792 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangEncoderFactory.cpp @@ -0,0 +1,76 @@ +/* + * YangAudioEncoderFactory.cpp + * + * Created on: 2019年9月3日 + * Author: yang + */ + +#include "YangH264EncoderIntel.h" +#include "YangH264EncoderSoft.h" +#include "YangH265EncoderSoft.h" +#include "YangVideoEncoderFfmpeg.h" +#include "yangencoder/YangEncoderFactory.h" + +#include "YangAudioEncoderAac.h" +#include "YangAudioEncoderMp3.h" +#include "YangAudioEncoderOpus.h" +#include "YangAudioEncoderSpeex.h" +#include "YangH264EncoderMeta.h" +#include "YangH265EncoderMeta.h" +#include "YangFfmpegEncoderMeta.h" +#include + +YangEncoderFactory::YangEncoderFactory() { + + +} + +YangEncoderFactory::~YangEncoderFactory() { + +} +YangVideoEncoderMeta* YangEncoderFactory::createVideoEncoderMeta(YangVideoInfo *pcontext){ + if(pcontext->videoEncHwType>0) return new YangFfmpegEncoderMeta(); + if(pcontext->videoEncoderType==0) return new YangH264EncoderMeta(); + if(pcontext->videoEncoderType==1) return new YangH265EncoderMeta(); + return new YangH264EncoderMeta(); +} + + +YangAudioEncoder *YangEncoderFactory::createAudioEncoder(YangAudioEncDecType paet,YangAudioInfo *pcontext){ + if(paet==Yang_AED_MP3) return new YangAudioEncoderMp3(); + if(paet==Yang_AED_SPEEX) return new YangAudioEncoderSpeex(); + if(paet==Yang_AED_OPUS) return new YangAudioEncoderOpus(); + return new YangAudioEncoderAac(); +} +YangAudioEncoder *YangEncoderFactory::createAudioEncoder(YangAudioInfo *pcontext){ + YangAudioEncDecType maet=Yang_AED_AAC; + + if(pcontext->audioEncoderType==1) maet=Yang_AED_MP3; + if(pcontext->audioEncoderType==2) maet=Yang_AED_SPEEX; + if(pcontext->audioEncoderType==3) maet=Yang_AED_OPUS; + return createAudioEncoder(maet,pcontext); +} + +YangVideoEncoder* YangEncoderFactory::createVideoEncoder(YangVideoEncDecType paet,YangVideoInfo *pcontext){ + if(pcontext->videoEncHwType==0){ + //printf("\n*********************pate===%d\n",paet); + if (paet == Yang_VED_264) return new YangH264EncoderSoft(); + if (paet == Yang_VED_265) return new YangH265EncoderSoft(); + }else{ + #if Yang_GPU_Encoding + YangGpuEncoderFactory gf; + return gf.createGpuEncoder(); +#else + return new YangVideoEncoderFfmpeg(paet,pcontext->videoEncHwType); +#endif + } + + return new YangH264EncoderSoft(); +} + YangVideoEncoder* YangEncoderFactory::createVideoEncoder(YangVideoInfo *pcontext){ + YangVideoEncDecType maet=Yang_VED_264; + if(pcontext->videoEncoderType==0) maet=Yang_VED_264; + if(pcontext->videoEncoderType==1) maet=Yang_VED_265; + //if(pcontext->audioEncoderType==2) maet=Yang_AE_SPEEX; + return createVideoEncoder(maet,pcontext); + } diff --git a/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.cpp b/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a6b330405af4fa489930e24c081410f88be0dec --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.cpp @@ -0,0 +1,288 @@ +/* + * YangFfmpegEncoderMeta.cpp + * + * Created on: 2020年9月26日 + * Author: yang + */ + +#include "YangFfmpegEncoderMeta.h" +#include "YangVideoEncoderFfmpeg.h" +#include +#include +YangFfmpegEncoderMeta::YangFfmpegEncoderMeta() { +#if Yang_Ffmpeg_UsingSo + unloadLib(); +#endif + +} + +YangFfmpegEncoderMeta::~YangFfmpegEncoderMeta() { +#if Yang_Ffmpeg_UsingSo + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); +#endif +} + +#if Yang_Ffmpeg_UsingSo +void YangFfmpegEncoderMeta::loadLib() { + yang_av_buffer_unref = (void (*)(AVBufferRef **buf)) m_lib1.loadFunction( + "av_buffer_unref"); + yang_av_hwframe_ctx_init = (int32_t (*)(AVBufferRef *ref)) m_lib1.loadFunction( + "av_hwframe_ctx_init"); + yang_av_frame_alloc = (AVFrame* (*)(void)) m_lib1.loadFunction( + "av_frame_alloc"); + yang_av_image_get_buffer_size = (int32_t (*)(enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_get_buffer_size"); + yang_av_hwdevice_ctx_create = (int32_t (*)(AVBufferRef **device_ctx, + enum AVHWDeviceType type, const char *device, AVDictionary *opts, + int32_t flags)) m_lib1.loadFunction("av_hwdevice_ctx_create"); + yang_av_hwframe_transfer_data = (int32_t (*)(AVFrame *dst, const AVFrame *src, + int32_t flags)) m_lib1.loadFunction("av_hwframe_transfer_data"); + yang_av_free = (void (*)(void *ptr)) m_lib1.loadFunction("av_free"); + yang_av_frame_free = (void (*)(AVFrame **frame)) m_lib1.loadFunction( + "av_frame_free"); + yang_av_buffer_ref = + (AVBufferRef* (*)(AVBufferRef *buf)) m_lib1.loadFunction( + "av_buffer_ref"); + yang_av_image_fill_arrays = (int32_t (*)(uint8_t *dst_data[4], + int32_t dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_fill_arrays"); + yang_av_hwframe_ctx_alloc = + (AVBufferRef* (*)(AVBufferRef *device_ctx)) m_lib1.loadFunction( + "av_hwframe_ctx_alloc"); + yang_av_hwframe_get_buffer = (int32_t (*)(AVBufferRef *hwframe_ctx, + AVFrame *frame, int32_t flags)) m_lib1.loadFunction( + "av_hwframe_get_buffer"); + yang_av_malloc = (void* (*)(size_t size)) m_lib1.loadFunction("av_malloc"); + + yang_avcodec_alloc_context3 = + (AVCodecContext* (*)(const AVCodec *codec)) m_lib.loadFunction( + "avcodec_alloc_context3"); + yang_av_init_packet = (void (*)(AVPacket *pkt)) m_lib.loadFunction( + "av_init_packet"); + yang_avcodec_find_encoder_by_name = + (AVCodec* (*)(const char *name)) m_lib.loadFunction( + "avcodec_find_encoder_by_name"); + yang_avcodec_open2 = (int32_t (*)(AVCodecContext *avctx, const AVCodec *codec, + AVDictionary **options)) m_lib.loadFunction("avcodec_open2"); + yang_avcodec_send_frame = (int32_t (*)(AVCodecContext *avctx, + const AVFrame *frame)) m_lib.loadFunction("avcodec_send_frame"); + yang_avcodec_receive_packet = (int32_t (*)(AVCodecContext *avctx, + AVPacket *avpkt)) m_lib.loadFunction("avcodec_receive_packet"); + yang_avcodec_close = (int32_t (*)(AVCodecContext *avctx)) m_lib.loadFunction( + "avcodec_close"); +} +void YangFfmpegEncoderMeta::unloadLib() { + yang_av_hwframe_ctx_alloc = NULL; + yang_av_hwframe_ctx_init = NULL; + yang_av_buffer_unref = NULL; + yang_avcodec_find_encoder_by_name = NULL; + yang_av_hwdevice_ctx_create = NULL; + yang_av_frame_alloc = NULL; + yang_avcodec_open2 = NULL; + yang_av_image_get_buffer_size = NULL; + yang_av_malloc = NULL; + yang_av_image_fill_arrays = NULL; + yang_av_init_packet = NULL; + yang_av_hwframe_get_buffer = NULL; + yang_av_hwframe_transfer_data = NULL; + yang_avcodec_send_frame = NULL; + yang_avcodec_receive_packet = NULL; + yang_av_frame_free = NULL; + yang_avcodec_close = NULL; + yang_av_free = NULL; +} +#endif +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) +//void ConvertYCbCr2BGR(uint8_t *pYUV,uint8_t *pBGR,int32_t iWidth,int32_t iHeight); +//void ConvertRGB2YUV(int32_t w,int32_t h,uint8_t *bmp,uint8_t *yuv); +//int32_t g_m_fx2=2; +void YangFfmpegEncoderMeta::yang_find_next_start_code(YangVideoEncDecType pve,uint8_t *buf,int32_t bufLen,int32_t *vpsPos,int32_t *vpsLen,int32_t *spsPos,int32_t *spsLen,int32_t *ppsPos,int32_t *ppsLen) +{ + int32_t i = 0; + // printf("\n**********************extradate.....=%d\n",bufLen); + // for(int32_t j=0;jdata); + frames_ctx->format = ctxformat; + frames_ctx->sw_format = swformat; + + frames_ctx->width = pwid; + frames_ctx->height = phei; + frames_ctx->initial_pool_size = 0; + if ((err = yang_av_hwframe_ctx_init(hw_frames_ref)) < 0) { + yang_error("Failed to initialize VAAPI frame context.Error code: %d\n", + ret); + yang_av_buffer_unref(&hw_frames_ref); + return err; + } + ctx->hw_frames_ctx = yang_av_buffer_ref(hw_frames_ref); + ctx->hw_device_ctx = yang_av_buffer_ref(hw_device_ctx); + // ctx->hwaccel_flags=1; + if (!ctx->hw_frames_ctx) + err = AVERROR(ENOMEM); + + yang_av_buffer_unref(&hw_frames_ref); + return err; +} + +enum AVPixelFormat get_hw_format22(AVCodecContext *ctx, + const enum AVPixelFormat *pix_fmts) { + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Intel) return AV_PIX_FMT_VAAPI; + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Nvdia) return AV_PIX_FMT_CUDA; + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Android) return AV_PIX_FMT_MEDIACODEC; + return AV_PIX_FMT_VAAPI; +} +void YangFfmpegEncoderMeta::yang_getSpsPps(YangH2645Conf *pconf, + YangVideoInfo *p_yvp, YangVideoEncInfo *penc) { +#if Yang_Ffmpeg_UsingSo + m_lib.loadObject("libavcodec"); + m_lib1.loadObject("libavutil"); + loadLib(); +#endif + YangVideoEncDecType m_encoderType=(YangVideoEncDecType)p_yvp->videoEncoderType; + YangVideoHwType m_hwType=(YangVideoHwType)p_yvp->videoEncHwType; + AVCodec *m_codec=NULL; + AVCodecContext *m_codecCtx = NULL; + AVBufferRef *hw_device_ctx=NULL; + //hevc_vaapi nvenc nvdec vdpau h264_nvenc + if(m_encoderType==Yang_VED_264){ + if(m_hwType==YangV_Hw_Intel) m_codec = yang_avcodec_find_encoder_by_name("h264_vaapi");//avcodec_find_encoder(AV_CODEC_ID_H264); + if(m_hwType==YangV_Hw_Nvdia) m_codec = yang_avcodec_find_encoder_by_name("h264_nvenc"); + if(m_hwType==YangV_Hw_Android) m_codec = yang_avcodec_find_encoder_by_name("h264_mediacodec"); + }else if(m_encoderType==Yang_VED_265){ + if(m_hwType==YangV_Hw_Intel) m_codec = yang_avcodec_find_encoder_by_name("hevc_vaapi"); + if(m_hwType==YangV_Hw_Nvdia) m_codec = yang_avcodec_find_encoder_by_name("hevc_nvenc"); + if(m_hwType==YangV_Hw_Android) m_codec = yang_avcodec_find_encoder_by_name("hevc_mediacodec"); + } + m_codecCtx = yang_avcodec_alloc_context3(m_codec); + YangVideoEncoderFfmpeg::initParam(m_codecCtx,p_yvp,penc); + m_codecCtx->get_format = get_hw_format22; // AV_PIX_FMT_NV12;//get_hw_format; + int32_t ret=0; + //AV_HWDEVICE_TYPE_CUDA + YangVideoEncoderFfmpeg::g_hwType=(YangVideoHwType)p_yvp->videoEncHwType; + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Intel){ + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI,"/dev/dri/renderD128", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_VAAPI; + }else if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Nvdia){ + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA,"CUDA", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_CUDA; + }else if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Android){ + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_MEDIACODEC,"MEDIACODEC", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_MEDIACODEC; + } + //YangVideoEncoderFfmpeg::g_hwType=m_codecCtx->pix_fmt ; + if(ret<0){ + printf("\nhw create error!..ret=%d\n",ret); + exit(1); + } + //ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA,"CUDA", NULL, 0); + //AV_PIX_FMT_NV12;//AV_PIX_FMT_VAAPI;AV_PIX_FMT_YUV420P;//AV_PIX_FMT_CUDA + //AV_PIX_FMT_CUDA + AVPixelFormat ctxformat,swformat; + if(p_yvp->videoEncHwType==YangV_Hw_Intel) ctxformat = AV_PIX_FMT_VAAPI; + if(p_yvp->videoEncHwType==YangV_Hw_Nvdia) ctxformat = AV_PIX_FMT_CUDA; + if(p_yvp->videoEncHwType==YangV_Hw_Android) ctxformat = AV_PIX_FMT_MEDIACODEC; + if(p_yvp->bitDepth==8) swformat = AV_PIX_FMT_NV12; + if(p_yvp->bitDepth==10) swformat = AV_PIX_FMT_P010; + if(p_yvp->bitDepth==16) swformat = AV_PIX_FMT_P016; + if ((ret = set_hwframe_ctx(ctxformat,swformat,p_yvp,m_codecCtx, hw_device_ctx, p_yvp->outWidth, + p_yvp->outHeight)) < 0) { + printf("Failed to set hwframe context.\n"); + //goto close; + } + + m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + ret = yang_avcodec_open2(m_codecCtx, m_codec, NULL); + if (ret < 0){ + printf("\navcodec_open2 failure................\n"); + exit(1); + } + int32_t vpsPos=0,vpsLen=0; + int32_t spsPos=0,ppsPos=0; + int32_t spsLen=0,ppsLen=0; + yang_find_next_start_code(m_encoderType,m_codecCtx->extradata,m_codecCtx->extradata_size,&vpsPos,&vpsLen,&spsPos,&spsLen,&ppsPos,&ppsLen); + if(m_encoderType==Yang_VED_265) { + pconf->vpsLen=vpsLen; + memcpy(pconf->vps,m_codecCtx->extradata+vpsPos,vpsLen); + //printf("\n**************vpsLen===%d...\n",pconf->vpsLen); + //for(int32_t i=0;ivpsLen;i++) printf("%02x,",pconf->vps[i]); + } + pconf->spsLen=spsLen; + pconf->ppsLen=ppsLen; + memcpy(pconf->sps,m_codecCtx->extradata+spsPos,spsLen); + memcpy(pconf->pps,m_codecCtx->extradata+ppsPos,ppsLen); + + + yang_av_buffer_unref(&hw_device_ctx); + if (m_codecCtx){ + yang_avcodec_close(m_codecCtx); + yang_av_free(m_codecCtx); + } + m_codecCtx = NULL; + +} + +//Conf264 t_conf264; + + + +void YangFfmpegEncoderMeta::yang_initVmd(YangVideoMeta *p_vmd, + YangVideoInfo *p_yvp, YangVideoEncInfo *penc) { + if (!p_vmd->isInit) { + + yang_getSpsPps(&p_vmd->mp4Meta, p_yvp,penc); + if(p_yvp->videoEncoderType==Yang_VED_264) yang_getConfig_Flv_H264(&p_vmd->mp4Meta, p_vmd->livingMeta.buffer,&p_vmd->livingMeta.bufLen); + if(p_yvp->videoEncoderType==Yang_VED_265) yang_getConfig_Flv_H265(&p_vmd->mp4Meta, p_vmd->livingMeta.buffer,&p_vmd->livingMeta.bufLen); + // yang_getH265Config_Flv(&p_vmd->mp4Meta, p_vmd->flvMeta.buffer, &p_vmd->flvMeta.bufLen); + p_vmd->isInit = 1; + } +} diff --git a/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.h b/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..24ba43255cc82998b67beb6e83a08b87dbda9624 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangFfmpegEncoderMeta.h @@ -0,0 +1,87 @@ +/* + * YangFfmpegEncoderMeta.h + * + * Created on: 2020年9月26日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGFFMPEGENCODERMETA_H_ +#define YANGENCODER_SRC_YANGFFMPEGENCODERMETA_H_ +#include "yangutil/sys/YangLoadLib.h" +#include +#include + +extern "C"{ +#include "libavcodec/avcodec.h" +//#include "libavformat/avformat.h" +#include "libavutil/avutil.h" +#include "libavutil/imgutils.h" +} +#include +class YangFfmpegEncoderMeta:public YangVideoEncoderMeta { +public: + YangFfmpegEncoderMeta(); + virtual ~YangFfmpegEncoderMeta(); + void yang_initVmd(YangVideoMeta *p_vmd, YangVideoInfo *p_config, YangVideoEncInfo *penc); + private: + void yang_find_next_start_code(YangVideoEncDecType pve,uint8_t *buf,int32_t bufLen,int32_t *vpsPos,int32_t *vpsLen,int32_t *spsPos,int32_t *spsLen,int32_t *ppsPos,int32_t *ppsLen); + int32_t set_hwframe_ctx(AVPixelFormat ctxformat,AVPixelFormat swformat,YangVideoInfo *yvp,AVCodecContext *ctx, AVBufferRef *hw_device_ctx,int32_t pwid,int32_t phei); + + void yang_getH2645Config(uint8_t *p_configBuf, int32_t *p_configLen, + YangVideoInfo *p_config); + + //void yang_getH265Config_1(YangVideoParam *p_config, YangH2645Conf *p265); + void yang_getSpsPps(YangH2645Conf *p265, YangVideoInfo *config, YangVideoEncInfo *penc); + //void initParam(x265_param *param,YangVideoParam *yvp, int32_t p_rc_method); +#if Yang_Ffmpeg_UsingSo + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + AVBufferRef *(*yang_av_hwframe_ctx_alloc)(AVBufferRef *device_ctx); + int32_t (*yang_av_hwframe_ctx_init)(AVBufferRef *ref); + void (*yang_av_buffer_unref)(AVBufferRef **buf); + AVCodec *(*yang_avcodec_find_encoder_by_name)(const char *name); + int32_t (*yang_av_hwdevice_ctx_create)(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int32_t flags); + AVFrame *(*yang_av_frame_alloc)(void); + int32_t (*yang_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + int32_t (*yang_av_image_get_buffer_size)(enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + void *(*yang_av_malloc)(size_t size); + int32_t (*yang_av_image_fill_arrays)(uint8_t *dst_data[4], int32_t dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + void (*yang_av_init_packet)(AVPacket *pkt); + int32_t (*yang_av_hwframe_get_buffer)(AVBufferRef *hwframe_ctx, AVFrame *frame, int32_t flags); + int32_t (*yang_av_hwframe_transfer_data)(AVFrame *dst, const AVFrame *src, int32_t flags); + int32_t (*yang_avcodec_send_frame)(AVCodecContext *avctx, const AVFrame *frame); + int32_t (*yang_avcodec_receive_packet)(AVCodecContext *avctx, AVPacket *avpkt); + void (*yang_av_frame_free)(AVFrame **frame); + int32_t (*yang_avcodec_close)(AVCodecContext *avctx); + void (*yang_av_free)(void *ptr); + AVBufferRef *(*yang_av_buffer_ref)(AVBufferRef *buf); + AVCodecContext *(*yang_avcodec_alloc_context3)(const AVCodec *codec); +#else +#define yang_av_hwframe_ctx_alloc av_hwframe_ctx_alloc +#define yang_av_hwframe_ctx_init av_hwframe_ctx_init +#define yang_av_buffer_unref av_buffer_unref +#define yang_avcodec_find_encoder_by_name avcodec_find_encoder_by_name +#define yang_av_hwdevice_ctx_create av_hwdevice_ctx_create +#define yang_av_frame_alloc av_frame_alloc +#define yang_avcodec_open2 avcodec_open2 +#define yang_av_image_get_buffer_size av_image_get_buffer_size +#define yang_av_malloc av_malloc +#define yang_av_image_fill_arrays av_image_fill_arrays +#define yang_av_init_packet av_init_packet +#define yang_av_hwframe_get_buffer av_hwframe_get_buffer +#define yang_av_hwframe_transfer_data av_hwframe_transfer_data +#define yang_avcodec_send_frame avcodec_send_frame +#define yang_avcodec_receive_packet avcodec_receive_packet +#define yang_av_frame_free av_frame_free +#define yang_avcodec_close avcodec_close +#define yang_av_free av_free +#define yang_av_buffer_ref av_buffer_ref +#define yang_avcodec_alloc_context3 avcodec_alloc_context3 +#endif +}; + +#endif /* YANGENCODER_SRC_YANGFFMPEGENCODERMETA_H_ */ diff --git a/libyangrtc2/src/yangencoder/YangH264EncHeader.cpp b/libyangrtc2/src/yangencoder/YangH264EncHeader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..faa7c7fe89486ea445895867ca1ad9fd20124745 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncHeader.cpp @@ -0,0 +1,220 @@ +/* + * YangH264EncHeader.cpp + * + * Created on: 2019年10月18日 + * Author: yang + */ + +#include "YangH264EncHeader.h" + +#include "malloc.h" +#include "yangutil/yang_unistd.h" +#include +//#include + +#if YangLibva +#include "string.h" +#ifdef _WIN32 +#include +#else +#include "va/va.h" +#include +#endif +void initYangMeta(YangMeataData *pmd,YangVideoParam *pcontext){ + pmd->width=pcontext->outWidth ; + pmd->height=pcontext->outHeight; + pmd->width_align=(pcontext->outWidth + 15) & (~15); + pmd->height_align=(pcontext->outHeight + 15) & (~15); + pmd->gop_size=20; + pmd->num_ref_frames=2; + pmd->numShortTerm=0; + pmd->constraint_set_flag=0; + pmd->h264_packedheader=0;/*supportpackheader?*/ + pmd->h264_maxref=(1<<16|1); + pmd->h264_entropy_mode=0;//1;/*cabac*/ + pmd->MaxFrameNum=(2<<16); + pmd->MaxPicOrderCntLsb=(2<<8); + pmd->Log2MaxFrameNum=16; + pmd->Log2MaxPicOrderCntLsb=4;//8; + + pmd->frame_coded=0; + pmd->frame_bitrate=1024000; + pmd->frame_slices=1; + pmd->frame_size=0; + pmd->initial_qp=26; + pmd->minimal_qp=26; + pmd->intra_period=pmd->gop_size; + pmd->intra_idr_period=pmd->gop_size; + pmd->ip_period=1;//3; + pmd->rc_mode=0; +} +#ifndef _WIN32 +void initVaSeq(YangMeataData *pmd,VAEncSequenceParameterBufferH264 *sps){ + sps->seq_parameter_set_id=0; + sps->level_idc = 31;//41 /*SH_LEVEL_3*/; + sps->intra_period = pmd->intra_period; + sps->intra_idr_period = pmd->intra_idr_period; + sps->ip_period = pmd->ip_period; + + sps->bits_per_second = pmd->frame_bitrate; + sps->max_num_ref_frames = pmd->num_ref_frames; + sps->picture_width_in_mbs = pmd->width_align / 16; + sps->picture_height_in_mbs = pmd->height_align / 16; + + sps->seq_fields.bits.chroma_format_idc = 1; + sps->seq_fields.bits.frame_mbs_only_flag = 1; + sps->seq_fields.bits.mb_adaptive_frame_field_flag=0; + sps->seq_fields.bits.seq_scaling_matrix_present_flag=0; + sps->seq_fields.bits.direct_8x8_inference_flag = 1; + sps->seq_fields.bits.log2_max_frame_num_minus4 = 4;//pmd->Log2MaxFrameNum - 4; + sps->seq_fields.bits.pic_order_cnt_type=0; + sps->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =pmd->Log2MaxPicOrderCntLsb - 4; + sps->seq_fields.bits.delta_pic_order_always_zero_flag=0; + + sps->time_scale = 50; + sps->num_units_in_tick = 1; /* Tc = num_units_in_tick / time_sacle */ + sps->bit_depth_chroma_minus8=0; + sps->bit_depth_luma_minus8=0; + if (pmd->width != pmd->width_align || pmd->height != pmd->height_align) { + sps->frame_cropping_flag = 1; + sps->frame_crop_left_offset = 0; + sps->frame_crop_right_offset = (pmd->width_align - pmd->width) + / 2; + sps->frame_crop_top_offset = 0; + sps->frame_crop_bottom_offset =(pmd->height_align - pmd->height) / 2; + } + // sps->vui_parameters_present_flag=1; + // sps->vui_fields.bits.bitstream_restriction_flag=1; + // sps->vui_fields.bits.log2_max_mv_length_horizontal=15,sps->vui_fields.bits.log2_max_mv_length_vertical=15; + // sps->vui_fields.bits.timing_info_present_flag=1; +} +void initVaPic(YangMeataData *pmd,VAEncPictureParameterBufferH264 *pps){ + pps->pic_fields.bits.entropy_coding_mode_flag = pmd->h264_entropy_mode; + pps->pic_fields.bits.deblocking_filter_control_present_flag = 1; + pps->pic_init_qp = pmd->initial_qp; +} +void initVaPara(YangMeataData *pmd,VAEncSequenceParameterBufferH264 *sps,VAEncPictureParameterBufferH264 *pps){ + initVaSeq(pmd,sps); + initVaPic(pmd,pps); +} +#endif +/** +void printSeq(VAEncSequenceParameterBufferH264 *sps){ + printf("\n%02x,%02x,%02x,%02x\n%d,%d,%d,%d\n%02x,%d,%02x,%d\n%d,%d,%d,%d,%02x\nvui_fields:%d,%d,%d,%d,%d,%d,%d,%d\nseq_fields.bits:%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + sps->seq_parameter_set_id,sps->aspect_ratio_idc,sps->bit_depth_chroma_minus8, + sps->bit_depth_luma_minus8,sps->bits_per_second,sps->intra_idr_period,sps->intra_period,sps->ip_period,// + sps->level_idc,sps->max_num_ref_frames,sps->num_ref_frames_in_pic_order_cnt_cycle,sps->num_units_in_tick, + sps->offset_for_non_ref_pic,sps->sar_width,sps->sar_height,sps->time_scale,sps->vui_parameters_present_flag, + sps->vui_fields.bits.aspect_ratio_info_present_flag,sps->vui_fields.bits.bitstream_restriction_flag,sps->vui_fields.bits.fixed_frame_rate_flag, + sps->vui_fields.bits.log2_max_mv_length_horizontal,sps->vui_fields.bits.log2_max_mv_length_vertical,sps->vui_fields.bits.low_delay_hrd_flag, + sps->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,sps->vui_fields.bits.timing_info_present_flag, + sps->seq_fields.bits.chroma_format_idc,sps->seq_fields.bits.delta_pic_order_always_zero_flag,sps->seq_fields.bits.direct_8x8_inference_flag, + sps->seq_fields.bits.frame_mbs_only_flag,sps->seq_fields.bits.log2_max_frame_num_minus4,sps->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4, + sps->seq_fields.bits.mb_adaptive_frame_field_flag,sps->seq_fields.bits.pic_order_cnt_type,sps->seq_fields.bits.seq_scaling_matrix_present_flag + ); +} +void printPic(VAEncPictureParameterBufferH264 *pps){ + printf("\n%02x,%hd,%02x,%02x,%02x,%02x,\npic_fields:%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",pps->chroma_qp_index_offset,pps->frame_num,pps->num_ref_idx_l0_active_minus1,pps->num_ref_idx_l1_active_minus1, + pps->pic_init_qp,pps->second_chroma_qp_index_offset,pps->pic_fields.bits.constrained_intra_pred_flag,pps->pic_fields.bits.deblocking_filter_control_present_flag, + pps->pic_fields.bits.entropy_coding_mode_flag,pps->pic_fields.bits.idr_pic_flag,pps->pic_fields.bits.pic_order_present_flag,pps->pic_fields.bits.pic_scaling_matrix_present_flag, + pps->pic_fields.bits.redundant_pic_cnt_present_flag,pps->pic_fields.bits.reference_pic_flag,pps->pic_fields.bits.transform_8x8_mode_flag, + pps->pic_fields.bits.weighted_bipred_idc,pps->pic_fields.bits.weighted_pred_flag + + ); +}**/ + +void setZbVmd(uint8_t *sps,int32_t spsLen,uint8_t *pps,int32_t pps_len,uint8_t *configBuf,int32_t *zbLen){ + configBuf[0] = 0x17; + configBuf[1] = 0x00; + configBuf[2] = 0x00; + configBuf[3] = 0x00; + configBuf[4] = 0x00; + configBuf[5] = 0x01; + configBuf[6] = sps[1]; + configBuf[7] = sps[2]; + configBuf[8] = sps[3]; //0x29; //AVCLevelIndication1f + configBuf[9] = 0xff; //03;//ff;//0x03; AVCLevelIndication + configBuf[10] = 0xe1; //01;//e1;//01;numOfSequenceParameterSets + char * szTmp = (char*) configBuf + 11; + + short slen = spsLen; //spslen(short) + slen = htons(slen); + memcpy(szTmp, &slen, sizeof(short)); + szTmp += sizeof(short); + + memcpy(szTmp, sps,spsLen); + szTmp += spsLen; + *szTmp = 0x01; + szTmp += 1; + slen = pps_len; //spslen(short) + slen = htons(slen); + + memcpy(szTmp, &slen, sizeof(short)); + szTmp += sizeof(short); + memcpy(szTmp, pps, pps_len); + //printf("...%d.....\n",bs.p-bs.p_start); + szTmp += pps_len; + *zbLen = szTmp - (char*) configBuf; + szTmp = NULL; +} +void yang_find_next_start_code(uint8_t *buf,int32_t bufLen,int32_t *spsPos,int32_t *spsLen,int32_t *ppsPos,int32_t *ppsLen) +{ + int32_t i = 0; + + *spsPos=0;*ppsPos=0; + while (i >>>>>>>>>>>>>>>>>>>%d\n",spsLen); + for(i=0;i>>>>>>>>>>>>>>>>>>>.%d\n",ppsLen); + for(i=0;i>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");**/ + +} +#endif +/** +YangH264EncHeader::YangH264EncHeader() { + // TODO Auto-generated constructor stub + +} + +YangH264EncHeader::~YangH264EncHeader() { + // TODO Auto-generated destructor stub +} + +int32_t YangH264EncHeader::setSps(uint8_t *sps_buffer,int32_t *spsLen){ + +} + int32_t YangH264EncHeader::setPPS(uint8_t *pps_buffer,int32_t *ppsLen){ + + }**/ diff --git a/libyangrtc2/src/yangencoder/YangH264EncHeader.h b/libyangrtc2/src/yangencoder/YangH264EncHeader.h new file mode 100644 index 0000000000000000000000000000000000000000..530f2f9676354fd0078c2c3584a6d645aae59c0d --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncHeader.h @@ -0,0 +1,66 @@ +/* + * YangH264EncHeader.h + * + * Created on: 2019年10月18日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGH264ENCHEADER_H_ +#define YANGENCODER_SRC_YANGH264ENCHEADER_H_ +#include "stdint.h" + +#if YangLibva +#ifndef _WIN32 +#include "va/va.h" +#endif +#include "yangutil/yangavtype.h" + +struct YangMeataData { + int32_t width; + int32_t height; + int32_t width_align; + int32_t height_align; + int32_t num_ref_frames; + int32_t numShortTerm; + int32_t constraint_set_flag; + int32_t h264_packedheader; /* support pack header? */ + int32_t h264_maxref; + int32_t h264_entropy_mode; /* cabac */ + int32_t MaxFrameNum; + int32_t MaxPicOrderCntLsb; + int32_t Log2MaxFrameNum; + int32_t Log2MaxPicOrderCntLsb; + int32_t gop_size; + int32_t frame_coded; + int32_t frame_bitrate; + int32_t frame_slices; + double frame_size; + int32_t initial_qp; + int32_t minimal_qp; + int32_t intra_period; + int32_t intra_idr_period; + int32_t ip_period; + int32_t rc_mode; +}; +void initYangMeta(YangMeataData *pmd, YangVideoParam *ini); +#ifndef _WIN32 +void initVaSeq(YangMeataData *pmd, VAEncSequenceParameterBufferH264 *sps); +void initVaPic(YangMeataData *pmd, VAEncPictureParameterBufferH264 *pps); +void initVaPara(YangMeataData *pmd, VAEncSequenceParameterBufferH264 *sps, + VAEncPictureParameterBufferH264 *pps); +void printSeq(VAEncSequenceParameterBufferH264 *sps); +void printPic(VAEncPictureParameterBufferH264 *pps); +#endif +void setZbVmd(uint8_t *sps, int32_t spsLen, uint8_t *pps, int32_t ppsLen, + uint8_t *zbconf, int32_t *zbLen); +void setZbVmd_f(uint8_t *buf,int32_t bufLen,uint8_t *configBuf,int32_t *zbLen); +/**class YangH264EncHeader { + public: + YangH264EncHeader(); + virtual ~YangH264EncHeader(); + int32_t setSps(uint8_t *sps_buffer,int32_t *spsLen); + int32_t setPPS(uint8_t *pps_buffer,int32_t *ppsLen); + }; + **/ +#endif /* YANGENCODER_SRC_YANGH264ENCHEADER_H_ */ +#endif diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderIntel.cpp b/libyangrtc2/src/yangencoder/YangH264EncoderIntel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..815fa4c90adc7b9f8543a83d8806ab66155b8482 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderIntel.cpp @@ -0,0 +1,996 @@ +#include "YangH264EncoderIntel1.h" +#ifndef _WIN32 +#if YangLibva +void YangH264EncoderIntel::loadLib(){ + //const SpeexMode * (*yang_speex_lib_get_mode) (int32_t mode); + yang_vaGetConfigAttributes=(VAStatus (*) (VADisplay dpy, VAProfile profile, VAEntrypoint32_t entrypoint, + VAConfigAttrib *attrib_list, int32_t num_attribs))m_lib.loadFunction("vaGetConfigAttributes"); + yang_vaDeriveImage=(VAStatus (*) (VADisplay dpy,VASurfaceID surface,VAImage *image))m_lib.loadFunction("vaDeriveImage"); + yang_vaDestroyImage=(VAStatus (*) (VADisplay dpy,VAImageID image))m_lib.loadFunction("vaDestroyImage"); + + yang_vaInitialize=(VAStatus (*) ( VADisplay dpy, int32_t *major_version,int32_t *minor_version))m_lib.loadFunction("vaInitialize"); + //yang_NeAACDecOpen=(NEAACDECAPI NeAACDecHandle (*)(void))m_lib.loadFunction(""); + yang_vaGetDisplayDRM=(VADisplay (*)(int32_t fd))m_lib1.loadFunction("vaGetDisplayDRM"); + + yang_vaDestroyContext=(VAStatus (*) (VADisplay dpy,VAContextID context))m_lib.loadFunction("vaDestroyContext"); + yang_vaDestroySurfaces=(VAStatus (*) (VADisplay dpy,VASurfaceID *surfaces,int32_t num_surfaces))m_lib.loadFunction("vaDestroySurfaces"); + yang_vaDestroyConfig=(VAStatus (*) (VADisplay dpy,VAConfigID config_id))m_lib.loadFunction("vaDestroyConfig"); + yang_vaTerminate=(VAStatus (*) ( VADisplay dpy))m_lib.loadFunction("vaTerminate"); + + + yang_vaCreateConfig=(VAStatus (*) (VADisplay dpy, VAProfile profile, VAEntrypoint32_t entrypoint, VAConfigAttrib *attrib_list, int32_t num_attribs, VAConfigID *config_id ))m_lib.loadFunction("vaCreateConfig"); + + yang_vaCreateSurfaces=(VAStatus (*)(VADisplay dpy,uint32_t format,uint32_t width, + uint32_t height,VASurfaceID *surfaces,uint32_t num_surfaces, VASurfaceAttrib *attrib_list, + uint32_t num_attribs))m_lib.loadFunction("vaCreateSurfaces"); + + yang_vaCreateContext=(VAStatus (*) (VADisplay dpy,VAConfigID config_id, int32_t picture_width, + int32_t picture_height, int32_t flag, VASurfaceID *render_targets, + int32_t num_render_targets,VAContextID *context))m_lib.loadFunction("vaCreateContext"); + yang_vaCreateBuffer=(VAStatus (*) (VADisplay dpy,VAContextID context, VABufferType type, + uint32_t size, uint32_t num_elements, void *data, VABufferID *buf_id + ))m_lib.loadFunction("vaCreateBuffer"); + yang_vaBeginPicture=(VAStatus (*) (VADisplay dpy,VAContextID context,VASurfaceID render_target))m_lib.loadFunction("vaBeginPicture"); + yang_vaRenderPicture=(VAStatus (*) (VADisplay dpy,VAContextID context, VABufferID *buffers,int32_t num_buffers))m_lib.loadFunction("vaRenderPicture"); + + yang_vaCreateImage=(VAStatus (*) (VADisplay dpy,VAImageFormat *format, int32_t width, int32_t height, VAImage *image))m_lib.loadFunction("vaCreateImage"); + yang_vaEndPicture=(VAStatus (*) (VADisplay dpy,VAContextID context))m_lib.loadFunction("vaEndPicture"); + yang_vaGetImage=(VAStatus (*) (VADisplay dpy,VASurfaceID surface, int32_t x, + int32_t y,uint32_t width, uint32_t height,VAImageID image))m_lib.loadFunction("vaGetImage"); + yang_vaMapBuffer=(VAStatus (*) (VADisplay dpy,VABufferID buf_id, void **pbuf))m_lib.loadFunction("vaMapBuffer"); + yang_vaSyncSurface=(VAStatus (*) (VADisplay dpy,VASurfaceID render_target))m_lib.loadFunction("vaSyncSurface"); + yang_vaUnmapBuffer=(VAStatus (*) (VADisplay dpy,VABufferID buf_id))m_lib.loadFunction("vaUnmapBuffer"); + +} + +void YangH264EncoderIntel::unloadLib(){ + yang_vaGetDisplayDRM=NULL; + yang_vaGetConfigAttributes=NULL; + yang_vaDeriveImage=NULL; + yang_vaDestroyImage=NULL; + yang_vaInitialize=NULL; + yang_vaDestroyContext=NULL; + yang_vaDestroySurfaces=NULL; + yang_vaDestroyConfig=NULL; + yang_vaTerminate=NULL; + + yang_vaCreateConfig=NULL; + yang_vaCreateSurfaces=NULL; + + yang_vaCreateContext=NULL; + yang_vaCreateBuffer=NULL; + yang_vaBeginPicture=NULL; + yang_vaRenderPicture=NULL; + + yang_vaCreateImage=NULL; + yang_vaEndPicture=NULL; + yang_vaGetImage=NULL; + yang_vaMapBuffer=NULL; + yang_vaSyncSurface=NULL; + yang_vaUnmapBuffer=NULL; + + + +} +YangH264EncoderIntel::YangH264EncoderIntel() { + //printf("\n*****YangH264Encoder***********************************Intel\n"); + //YangH264Encoder(); + //m_context = pcontext; + + m_config_id = VA_INVALID_ID; + m_config_id = 0; + m_vaContext = 0; + vas = 0; + //memset(pics, 0, sizeof(YangDecodePicture) * Para_Bufs); + memset(&m_pic_param, 0, sizeof(m_pic_param)); + memset(&image_format, 0, sizeof(image_format)); + memset(&m_slice_param, 0, sizeof(m_slice_param)); + memset(&m_seq_param, 0, sizeof(m_seq_param)); + memset(&m_ymd,0,sizeof(m_ymd)); + + m_fd = 0; + //m_ref_count = 0; + //m_ref_count_m1 = 0; + sid = 0; + frameIdx = 0; + FieldOrderCnt = 0; + //m_inWidth = 0; +// m_inHeight = 0; +// m_outWidth = 0; +// m_outHeight = 0; + m_frame = 0; + yLen = 0; + uLen = 0; + uvLen = 0; + allLen = 0; + frameIdx = 0; + FieldOrderCnt = 0; + posNum = 0; + m_isInit = 0; + m_vap_size = sizeof(VAPictureH264); + enc_packed_header_idx = 0; + m_width_mbaligned = 0; + m_height_mbaligned = 0; + current_frame_type = 0; + initYangMeta(&m_ymd,&m_yvp); + /**num_ref_frames = m_ymd.num_ref_frames; + numShortTerm = m_ymd.numShortTerm; + constraint_set_flag = m_ymd.constraint_set_flag; + h264_packedheader = m_ymd.h264_packedheader; //support pack header? + h264_maxref = m_ymd.h264_maxref; + h264_entropy_mode = m_ymd.h264_entropy_mode; // cabac + MaxFrameNum = m_ymd.MaxFrameNum; + MaxPicOrderCntLsb = m_ymd.MaxPicOrderCntLsb; + Log2MaxFrameNum = m_ymd.Log2MaxFrameNum; + Log2MaxPicOrderCntLsb = m_ymd.Log2MaxPicOrderCntLsb; + frame_count = m_ymd.frame_count; + frame_coded = m_ymd.frame_coded; + frame_bitrate = m_ymd.frame_bitrate; + frame_slices = m_ymd.frame_slices; + frame_size = m_ymd.frame_size; + initial_qp = m_ymd.initial_qp; + minimal_qp = m_ymd.minimal_qp; + intra_period = m_ymd.intra_period; + intra_idr_period = m_ymd.intra_idr_period; + ip_period = m_ymd.ip_period; + rc_mode = m_ymd.rc_mode;**/ + current_frame_encoding = 0; + current_frame_display = 0; + current_IDR_display = 0; + current_frame_num = 0; + misc_priv_type = 0; + misc_priv_value = 0; + h264_profile = VAProfileH264ConstrainedBaseline; + config_attrib_num = 0, + + m_va_dpy = NULL; + + m_vmd = NULL; + //isConvert = 0; + unloadLib(); +} + +YangH264EncoderIntel::~YangH264EncoderIntel() { + closeDevice(); + m_va_dpy = NULL; + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); + +} + +void YangH264EncoderIntel::closeDevice() { + //vaDestroySurfaces(m_va_dpy,&m_vaSurface,1); + for (int32_t i = 0; i < Para_Bufs; i++) { + if (m_va_dpy && src_surface[i] != VA_INVALID_ID) { + vas = yang_vaDestroySurfaces(m_va_dpy, &src_surface[i], 1); + CHECK_VASTATUS(vas, "vaDestroySurfaces"); + } + } + if (m_va_dpy && m_vaContext != VA_INVALID_ID) { + vas = yang_vaDestroyContext(m_va_dpy, m_vaContext); + CHECK_VASTATUS(vas, "vaDestroyContext"); + } + if (m_va_dpy && m_config_id != VA_INVALID_ID) { + vas = yang_vaDestroyConfig(m_va_dpy, m_config_id); + CHECK_VASTATUS(vas, "vaDestroyConfig"); + } + if (m_va_dpy) { + vas = yang_vaTerminate(m_va_dpy); + CHECK_VASTATUS(vas, "vaTerminate"); + } + if (m_fd >= 0) + close(m_fd); + m_va_dpy = NULL; + +} + +void YangH264EncoderIntel::setVideoMetaData(YangVideoMeta *pvmd){ + //if(1) return; + uint32_t length_in_bits=0,length_in_bits1=0; + uint8_t *packedseq_buffer = NULL; + uint8_t *packedpic_buffer = NULL; + length_in_bits = build_packed_seq_buffer(&packedseq_buffer); + length_in_bits1 = build_packed_pic_buffer(&packedpic_buffer); + memset(pvmd->livingMeta.buffer,0,sizeof(pvmd->livingMeta.buffer)); + setZbVmd(packedseq_buffer+4,(length_in_bits+7)/8-4,packedpic_buffer+4,(length_in_bits1+7)/8-4,pvmd->livingMeta.buffer,&pvmd->livingMeta.bufLen); + + free(packedseq_buffer); + free(packedpic_buffer); + packedseq_buffer=NULL; + packedpic_buffer=NULL; +} + +int32_t YangH264EncoderIntel::render_packedsequence(void) { + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; + VABufferID packedseq_para_bufid, packedseq_data_bufid, render_id[2]; + uint32_t length_in_bits=0; + uint8_t *packedseq_buffer = NULL; + VAStatus va_status; + + length_in_bits = build_packed_seq_buffer(&packedseq_buffer); + //printf("\n*************sps********************%d\n",length_in_bits/8); + //for(int32_t j=0;j> 16) & 0xffff); + } + + if (attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED) + printf("Support %d slices\n", attrib[VAConfigAttribEncMaxSlices].value); + + if (attrib[VAConfigAttribEncSliceStructure].value != VA_ATTRIB_NOT_SUPPORTED) { + int32_t tmp = attrib[VAConfigAttribEncSliceStructure].value; + + printf("Support VAConfigAttribEncSliceStructure\n"); + + if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS) + printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS\n"); + if (tmp & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) + printf("Support VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS\n"); + if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) + printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS\n"); + } + if (attrib[VAConfigAttribEncMacroblockInfo].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support VAConfigAttribEncMacroblockInfo\n"); + } + + vas = yang_vaCreateConfig(m_va_dpy, h264_profile, VAEntrypointEncSlice, + &config_attrib[0], config_attrib_num, &m_config_id); + CHECK_VASTATUS(vas, "vaCreateConfig"); + + + m_ymd.constraint_set_flag |= (1 << 0 | 1 << 1); /* Annex A.2.2 */ + //m_ymd.ip_period = 1; + + vas = yang_vaCreateSurfaces(m_va_dpy, VA_RT_FORMAT_YUV420, m_width_mbaligned, + m_height_mbaligned, src_surface, Para_Bufs, NULL, 0); + CHECK_VASTATUS(vas, "vaCreateSurfaces"); + + //vas = vaCreateSurfaces(m_va_dpy, VA_RT_FORMAT_YUV420, m_width_mbaligned,m_height_mbaligned, &ref_surface[0], Para_Bufs, NULL, 0); + //CHECK_VASTATUS(vas, "vaCreateSurfaces ref"); + + //VASurfaceID *tmp_surfaceid = (VASurfaceID *) calloc(2 * Para_Bufs, sizeof(VASurfaceID)); + //memcpy(tmp_surfaceid, src_surface, Para_Bufs * sizeof(VASurfaceID)); + //memcpy(tmp_surfaceid + Para_Bufs, ref_surface,Para_Bufs * sizeof(VASurfaceID)); +// vas = vaCreateContext(m_va_dpy, m_config_id, m_width_mbaligned, +// m_height_mbaligned, VA_PROGRESSIVE, tmp_surfaceid, 2 * Para_Bufs, +// &m_vaContext); + vas = yang_vaCreateContext(m_va_dpy, m_config_id, m_width_mbaligned, + m_height_mbaligned, VA_PROGRESSIVE, src_surface, Para_Bufs, + &m_vaContext); + CHECK_VASTATUS(vas, "vaCreateContext"); + //free(tmp_surfaceid); + + int32_t codedbuf_size = 0; + codedbuf_size = (m_width_mbaligned * m_height_mbaligned * 400) / (16 * 16); + for (int32_t i = 0; i < Para_Bufs; i++) { + /* create coded buffer once for all + * other VA buffers which won't be used again after vaRenderPicture. + * so APP can always vaCreateBuffer for every frame + * but coded buffer need to be mapped and accessed after vaRenderPicture/vaEndPicture + * so VA won't maintain the coded buffer + */ + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, VAEncCodedBufferType, + codedbuf_size, 1, NULL, &coded_buf[i]); + CHECK_VASTATUS(vas, "vaCreateBuffer"); + } + frameIdx = 0; + posNum = 0; + m_isInit=1; +// printSeq(&m_seq_param); + //printPic(&m_pic_param); + +} + +void YangH264EncoderIntel::render_packedslice() { + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; + VABufferID packedslice_para_bufid, packedslice_data_bufid, render_id[2]; + uint32_t length_in_bits; + uint8_t *packedslice_buffer = NULL; + //VAStatus va_status; + + length_in_bits = build_packed_slice_buffer(&packedslice_buffer); + packedheader_param_buffer.type = VAEncPackedHeaderSlice; + packedheader_param_buffer.bit_length = length_in_bits; + packedheader_param_buffer.has_emulation_bytes = 0; + + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncPackedHeaderParameterBufferType, + sizeof(packedheader_param_buffer), 1, &packedheader_param_buffer, + &packedslice_para_bufid); + CHECK_VASTATUS(vas, "vaCreateBuffer"); + + vas = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncPackedHeaderDataBufferType, (length_in_bits + 7) / 8, 1, + packedslice_buffer, &packedslice_data_bufid); + CHECK_VASTATUS(vas, "vaCreateBuffer"); + + render_id[0] = packedslice_para_bufid; + render_id[1] = packedslice_data_bufid; + vas = yang_vaRenderPicture(m_va_dpy, m_vaContext, render_id, 2); + CHECK_VASTATUS(vas, "vaRenderPicture"); + + free(packedslice_buffer); +} +int32_t YangH264EncoderIntel::upload_surface_yuv(VASurfaceID surface_id, + int32_t src_width, int32_t src_height, uint8_t *src_Y, + uint8_t *src_U, uint8_t *src_V) { + VAImage surface_image; + uint8_t *surface_p = NULL, *Y_start = NULL, *U_start = NULL; + int32_t Y_pitch = 0, U_pitch = 0, row; + + vas = yang_vaDeriveImage(m_va_dpy, surface_id, &surface_image); + CHECK_VASTATUS(vas, "vaDeriveImage"); + + yang_vaMapBuffer(m_va_dpy, surface_image.buf, (void **) &surface_p); + // assert(VA_STATUS_SUCCESS == va_status); + + Y_start = surface_p; + Y_pitch = surface_image.pitches[0]; + U_start = (uint8_t *) surface_p + surface_image.offsets[1]; + U_pitch = surface_image.pitches[1]; + + /* copy Y plane */ + for (row = 0; row < src_height; row++) { + uint8_t *Y_row = Y_start + row * Y_pitch; + memcpy(Y_row, src_Y + row * src_width, src_width); + } + //int32_t j = 0; + for (row = 0; row < src_height / 2; row++) { + uint8_t *U_row = U_start + row * U_pitch; + // uint8_t *u_ptr = NULL, *v_ptr = NULL; + + memcpy(U_row, src_U + row * src_width, src_width); + + } + yang_vaUnmapBuffer(m_va_dpy, surface_image.buf); + yang_vaDestroyImage(m_va_dpy, surface_image.image_id); + return Yang_Ok; +} +int32_t YangH264EncoderIntel::calc_poc(int32_t pic_order_cnt_lsb) { + static int32_t PicOrderCntMsb_ref = 0, pic_order_cnt_lsb_ref = 0; + int32_t prevPicOrderCntMsb, prevPicOrderCntLsb; + int32_t PicOrderCntMsb, TopFieldOrderCnt; + + if (current_frame_type == FRAME_IDR) + prevPicOrderCntMsb = prevPicOrderCntLsb = 0; + else { + prevPicOrderCntMsb = PicOrderCntMsb_ref; + prevPicOrderCntLsb = pic_order_cnt_lsb_ref; + } + + if ((pic_order_cnt_lsb < prevPicOrderCntLsb) + && ((prevPicOrderCntLsb - pic_order_cnt_lsb) + >= (int) (m_ymd.MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb + m_ymd.MaxPicOrderCntLsb; + else if ((pic_order_cnt_lsb > prevPicOrderCntLsb) + && ((pic_order_cnt_lsb - prevPicOrderCntLsb) + > (int) (m_ymd.MaxPicOrderCntLsb / 2))) + PicOrderCntMsb = prevPicOrderCntMsb - m_ymd.MaxPicOrderCntLsb; + else + PicOrderCntMsb = prevPicOrderCntMsb; + + TopFieldOrderCnt = PicOrderCntMsb + pic_order_cnt_lsb; + + if (current_frame_type != FRAME_B) { + PicOrderCntMsb_ref = PicOrderCntMsb; + pic_order_cnt_lsb_ref = pic_order_cnt_lsb; + } + + return TopFieldOrderCnt; +} +int32_t YangH264EncoderIntel::render_slice(void) { + VABufferID slice_param_buf; + VAStatus va_status; + int32_t i; + + update_RefPicList(); + + /* one frame, one slice */ + m_slice_param.macroblock_address = 0; + m_slice_param.num_macroblocks = m_width_mbaligned * m_height_mbaligned + / (16 * 16); /* Measured by MB */ + m_slice_param.slice_type = + (current_frame_type == FRAME_IDR) ? 2 : current_frame_type; + if (current_frame_type == FRAME_IDR) { + if (current_frame_encoding != 0) + ++m_slice_param.idr_pic_id; + } else if (current_frame_type == FRAME_P) { + int32_t refpiclist0_max = m_ymd.h264_maxref & 0xffff; + memcpy(m_slice_param.RefPicList0, RefPicList0_P, + refpiclist0_max * sizeof(VAPictureH264)); + + for (i = refpiclist0_max; i < 32; i++) { + m_slice_param.RefPicList0[i].picture_id = VA_INVALID_SURFACE; + m_slice_param.RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + } + } else if (current_frame_type == FRAME_B) { + int32_t refpiclist0_max = m_ymd.h264_maxref & 0xffff; + int32_t refpiclist1_max = (m_ymd.h264_maxref >> 16) & 0xffff; + + memcpy(m_slice_param.RefPicList0, RefPicList0_B, + refpiclist0_max * sizeof(VAPictureH264)); + for (i = refpiclist0_max; i < 32; i++) { + m_slice_param.RefPicList0[i].picture_id = VA_INVALID_SURFACE; + m_slice_param.RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + } + + memcpy(m_slice_param.RefPicList1, RefPicList1_B, + refpiclist1_max * sizeof(VAPictureH264)); + for (i = refpiclist1_max; i < 32; i++) { + m_slice_param.RefPicList1[i].picture_id = VA_INVALID_SURFACE; + m_slice_param.RefPicList1[i].flags = VA_PICTURE_H264_INVALID; + } + } + + m_slice_param.slice_alpha_c0_offset_div2 = 0; + m_slice_param.slice_beta_offset_div2 = 0; + m_slice_param.direct_spatial_mv_pred_flag = 1; + m_slice_param.pic_order_cnt_lsb = (current_frame_display + - current_IDR_display) % m_ymd.MaxPicOrderCntLsb; + + if (m_ymd.h264_packedheader&& (config_attrib[enc_packed_header_idx].value & VA_ENC_PACKED_HEADER_SLICE)) + render_packedslice(); + + va_status = yang_vaCreateBuffer(m_va_dpy, m_vaContext,VAEncSliceParameterBufferType, sizeof(m_slice_param), 1, + &m_slice_param, &slice_param_buf); + CHECK_VASTATUS(va_status, "vaCreateBuffer");; + + va_status = yang_vaRenderPicture(m_va_dpy, m_vaContext, &slice_param_buf, 1); + CHECK_VASTATUS(va_status, "vaRenderPicture"); + + return Yang_Ok; +} + +int32_t YangH264EncoderIntel::update_RefPicList(void) { + uint32_t current_poc = CurrentCurrPic.TopFieldOrderCnt; + + if (current_frame_type == FRAME_P) { + memcpy(RefPicList0_P, ReferenceFrames, + m_ymd.numShortTerm * sizeof(VAPictureH264)); + sort_one(RefPicList0_P, 0, m_ymd.numShortTerm - 1, 0, 1); + } + + if (current_frame_type == FRAME_B) { + memcpy(RefPicList0_B, ReferenceFrames, + m_ymd.numShortTerm * sizeof(VAPictureH264)); + sort_two(RefPicList0_B, 0, m_ymd.numShortTerm - 1, current_poc, 0, 1, 0, 1); + + memcpy(RefPicList1_B, ReferenceFrames, + m_ymd.numShortTerm * sizeof(VAPictureH264)); + sort_two(RefPicList1_B, 0, m_ymd.numShortTerm - 1, current_poc, 0, 0, 1, 0); + } + + return Yang_Ok; +} + +int32_t YangH264EncoderIntel::render_picture(void) { + VABufferID m_pic_param_buf; + VAStatus va_status; + int32_t i = 0; + + m_pic_param.CurrPic.picture_id = src_surface[sid]; + m_pic_param.CurrPic.frame_idx = frameIdx; + m_pic_param.CurrPic.flags = 0; + m_pic_param.CurrPic.TopFieldOrderCnt = calc_poc( + (current_frame_display - current_IDR_display) % m_ymd.MaxPicOrderCntLsb); + m_pic_param.CurrPic.BottomFieldOrderCnt = + m_pic_param.CurrPic.TopFieldOrderCnt; + CurrentCurrPic = m_pic_param.CurrPic; + + /**if (getenv("TO_DEL")) { // set RefPicList into ReferenceFrames + + update_RefPicList(); // calc RefPicList + memset(m_pic_param.ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); // invalid all + if (current_frame_type == FRAME_P) { + m_pic_param.ReferenceFrames[0] = RefPicList0_P[0]; + } else if (current_frame_type == FRAME_B) { + m_pic_param.ReferenceFrames[0] = RefPicList0_B[0]; + m_pic_param.ReferenceFrames[1] = RefPicList1_B[0]; + } + } else { + **/ + memcpy(m_pic_param.ReferenceFrames, ReferenceFrames,m_ymd.numShortTerm * sizeof(VAPictureH264)); + for (i = m_ymd.numShortTerm; i < Para_Bufs; i++) { + m_pic_param.ReferenceFrames[i].picture_id = VA_INVALID_SURFACE; + m_pic_param.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + } + //} + + m_pic_param.pic_fields.bits.idr_pic_flag =(current_frame_type == FRAME_IDR); + m_pic_param.pic_fields.bits.reference_pic_flag = (current_frame_type!= FRAME_B); + + m_pic_param.frame_num = frameIdx; + m_pic_param.coded_buf = coded_buf[sid]; + m_pic_param.last_picture = (current_frame_encoding == m_ymd.gop_size); + + //initVaPic(&m_ymd,&m_pic_param); + + va_status = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncPictureParameterBufferType, sizeof(m_pic_param), 1, + &m_pic_param, &m_pic_param_buf); + CHECK_VASTATUS(va_status, "vaCreateBuffer");; + + va_status = yang_vaRenderPicture(m_va_dpy, m_vaContext, &m_pic_param_buf, 1); + CHECK_VASTATUS(va_status, "vaRenderPicture"); + + return Yang_Ok; +} +int32_t YangH264EncoderIntel::render_sequence(void) { + VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2]; + VAStatus va_status; + VAEncMiscParameterBuffer *misc_param, *misc_param_tmp; + VAEncMiscParameterRateControl *misc_rate_ctrl; + //initVaSeq(&m_ymd,&m_seq_param); + va_status = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncSequenceParameterBufferType, sizeof(m_seq_param), 1, + &m_seq_param, &seq_param_buf); + CHECK_VASTATUS(va_status, "vaCreateBuffer"); + + va_status = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncMiscParameterBufferType, + sizeof(VAEncMiscParameterBuffer) + + sizeof(VAEncMiscParameterRateControl), 1, NULL, + &rc_param_buf); + CHECK_VASTATUS(va_status, "vaCreateBuffer"); + + yang_vaMapBuffer(m_va_dpy, rc_param_buf, (void **) &misc_param); + misc_param->type = VAEncMiscParameterTypeRateControl; + misc_rate_ctrl = (VAEncMiscParameterRateControl *) misc_param->data; + memset(misc_rate_ctrl, 0, sizeof(*misc_rate_ctrl)); + misc_rate_ctrl->bits_per_second = m_ymd.frame_bitrate; + misc_rate_ctrl->target_percentage = 66; + misc_rate_ctrl->window_size = 1000; + misc_rate_ctrl->initial_qp = m_ymd.initial_qp; + misc_rate_ctrl->min_qp = m_ymd.minimal_qp; + misc_rate_ctrl->basic_unit_size = 0; + yang_vaUnmapBuffer(m_va_dpy, rc_param_buf); + + render_id[0] = seq_param_buf; + render_id[1] = rc_param_buf; + + va_status = yang_vaRenderPicture(m_va_dpy, m_vaContext, &render_id[0], 2); + CHECK_VASTATUS(va_status, "vaRenderPicture");; + + if (misc_priv_type != 0) { + va_status = yang_vaCreateBuffer(m_va_dpy, m_vaContext, + VAEncMiscParameterBufferType, sizeof(VAEncMiscParameterBuffer), + 1, NULL, &misc_param_tmpbuf); + CHECK_VASTATUS(va_status, "vaCreateBuffer"); + yang_vaMapBuffer(m_va_dpy, misc_param_tmpbuf, (void **) &misc_param_tmp); + misc_param_tmp->type = (VAEncMiscParameterType) misc_priv_type; + misc_param_tmp->data[0] = misc_priv_value; + yang_vaUnmapBuffer(m_va_dpy, misc_param_tmpbuf); + + va_status = yang_vaRenderPicture(m_va_dpy, m_vaContext, &misc_param_tmpbuf,1); + } + + return Yang_Ok; +} +int32_t YangH264EncoderIntel::update_ReferenceFrames(void) { + int32_t i; + if (current_frame_type == FRAME_B) + return Yang_Ok; + CurrentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; + m_ymd.numShortTerm++; + if (m_ymd.numShortTerm > m_ymd.num_ref_frames) + m_ymd.numShortTerm = m_ymd.num_ref_frames; + for (i = m_ymd.numShortTerm - 1; i > 0; i--) + ReferenceFrames[i] = ReferenceFrames[i - 1]; + ReferenceFrames[0] = CurrentCurrPic; + + if (current_frame_type != FRAME_B) + current_frame_num++; + if (current_frame_num > m_ymd.MaxFrameNum) + current_frame_num = 0; + + return Yang_Ok; +} + +int32_t YangH264EncoderIntel::encode(uint8_t *buf, int32_t buflen, uint8_t *dest, + int32_t *destLen, int32_t *frametype) { + upload_surface_yuv(src_surface[sid], m_yvp.outWidth, m_yvp.outHeight, buf, + buf + yLen, NULL); + encoding2display_order(current_frame_encoding, m_ymd.intra_period, + m_ymd.intra_idr_period, m_ymd.ip_period, ¤t_frame_display, + ¤t_frame_type); + if (current_frame_type == FRAME_IDR) { + m_ymd.numShortTerm = 0; + current_frame_num = 0; + current_IDR_display = current_frame_display; + } + + vas = yang_vaBeginPicture(m_va_dpy, m_vaContext, src_surface[sid]); + CHECK_VASTATUS(vas, "vaBeginPicture"); + + if (current_frame_type == FRAME_IDR) { + render_sequence(); + render_picture(); + if (m_ymd.h264_packedheader) { + render_packedsequence(); + render_packedpicture(); + } + *frametype = 1; + //if (rc_mode == VA_RC_CBR) + // render_packedsei(); + //render_hrd(); + } else { + //render_sequence(); + render_picture(); + *frametype = 0; + //if (rc_mode == VA_RC_CBR) + // render_packedsei(); + //render_hrd(); + } + render_slice(); + vas = yang_vaEndPicture(m_va_dpy, m_vaContext); + CHECK_VASTATUS(vas, "vaEndPicture");; + + vas = yang_vaSyncSurface(m_va_dpy, src_surface[sid]); + CHECK_VASTATUS(vas, "vaSyncSurface"); + VACodedBufferSegment *buf_list = NULL; + + //uint32_t coded_size = 0; + + vas = yang_vaMapBuffer(m_va_dpy, coded_buf[sid], (void **) (&buf_list)); + CHECK_VASTATUS(vas, "vaMapBuffer"); + *destLen = 0; + while (buf_list != NULL) { + memcpy(dest + (*destLen), buf_list->buf, buf_list->size);//fwrite(buf_list->buf, 1, buf_list->size, coded_fp); + (*destLen) += buf_list->size; + buf_list = (VACodedBufferSegment *) buf_list->next; + + } + yang_vaUnmapBuffer(m_va_dpy, coded_buf[sid]); + update_ReferenceFrames(); + + printf("%d-%d,",current_frame_type, *destLen); + if(current_frame_encoding%15==0) printf("\n"); + + current_frame_encoding++; + if(current_frame_encoding==m_ymd.gop_size) current_frame_encoding=0; + sid++; + if (sid == Para_Bufs) + sid = 0; + return 1; + +} +/** +void YangH264EncoderIntel::startLoop() { + isConvert = 1; + int32_t isTrans = (m_inWidth != m_outWidth ? 1 : 0); + int64_t videoTimestamp = 0; + int32_t videoDestLen = 0; + int32_t frameType = 0; + uint8_t *videoDest = new uint8_t[1024 * 256]; + + int32_t m_in_File_Size = + m_context->videoCaptureFormat>0 ? + m_inWidth * m_inHeight * 3 / 2 : m_inWidth * m_inHeight * 2; + //int32_t m_in_File_Size1 = m_inWidth * m_inHeight * 3 / 2; + int32_t m_out_File_Size = m_outWidth * m_outHeight * 3 / 2; + uint8_t *videoSrc = new uint8_t[m_inWidth * m_inHeight * 3 / 2]; + uint8_t videoSrc1[m_out_File_Size]; //=new uint8_t[m_in_File_Size1]; + int64_t preVideostamp = 0; + printf("\n**************************start Zbhd encoding..........."); + YangConvert con; + //if(isTrans) con.initNv12_resize(inWidth,inHeight,outWidth,outHeight); + //uint8_t *t_in; + //uint8_t *t_out; + + if (m_in_videoBuffer != NULL) m_in_videoBuffer->resetIndex(); + if (m_out_videoBuffer != NULL) m_out_videoBuffer->resetIndex(); + int32_t is16bit=1; + if(m_context->videoCaptureFormat>0) is16bit=0; + while (isConvert == 1) { + + if (m_in_videoBuffer->size() == 0) { + //printf("***listsize=%d\n",vlist->getSize()); + yang_usleep(20000); + //printf("**"); + continue; + } + //if (isTrans) { + // m_in_videoBuffer->getVideo(t_in, m_in_File_Size, &videoTimestamp); + //util1.getVideoZ(videoSrc,m_in_File_Size,&videoTimestamp); + // if (preVideostamp == 0) { + // preVideostamp = videoTimestamp; + // } + // if (videoTimestamp - preVideostamp <= 0) + // continue; + + //con.YUY2toNV12(inWidth,inHeight,videoSrc,videoSrc1); + //con.nv12_nearest_scale(videoSrc1,p264Pic->img.plane[0]); + // con.mpu->pu->resize(); + // memcpy(videoSrc1, t_out, m_out_File_Size); + //con.YUY2toI420(outWidth,outHeight,con.mpu->pu->out,p264Pic->img.plane[0]); + + //con.resize_NV12(videoSrc1,p264Pic->img.plane[0],inWidth,inHeight,outWidth,outHeight); + //con.resize_Yuy2_NV12(videoSrc,p264Pic->img.plane[0],inWidth,inHeight,outWidth,outHeight); + //memcpy(p264Pic->img.plane[0],t_out,m_out_File_Size); + // } else { + // util1.getVideoZ(p264Pic->img.plane[0],m_in_File_Size,&videoTimestamp); + //util1.YUY2toI420(inWidth, inHeight, util1.getVideoIn(&videoTimestamp), p264Pic->img.plane[0]); + + if(is16bit){ + if (isTrans) + con.resize_Yuy2_NV12(m_in_videoBuffer->getVideoIn(&videoTimestamp),videoSrc1,m_inWidth,m_inHeight,m_outWidth,m_outHeight); + else + con.YUY2toNV12(m_inWidth,m_inHeight,m_in_videoBuffer->getVideoIn(&videoTimestamp), videoSrc1); + }else{ + if(isTrans) + con.resize_NV12(m_in_videoBuffer->getVideoIn(&videoTimestamp),videoSrc1,m_inWidth,m_inHeight,m_outWidth,m_outHeight); + else + memcpy(videoSrc1,m_in_videoBuffer->getVideoIn(&videoTimestamp),m_in_File_Size); + } + if (preVideostamp == 0) { + preVideostamp = videoTimestamp; + } + if (videoTimestamp - preVideostamp <= 0) + continue; + //} + + encode(videoSrc1, m_out_File_Size, videoDest, &videoDestLen, + &frameType); + if (videoDestLen > 4) { + //writeFile(videoDest,videoDestLen); + m_out_videoBuffer->putEVideo(videoDest, videoDestLen, videoTimestamp, + frameType); + } + //printf("%d-%d,",frameType, videoDestLen); + + } + //util1.close(); + //util_z.close(); + //t_in = NULL; + //t_out = NULL; + //con.mpu->pu->close(); + //con.mpu->pu = NULL; + //util_z.close(); + // delete[] srcVideoSource; + yang_deleteA(videoSrc); + yang_deleteA(videoDest); + +} + +void YangH264EncoderIntel::stopLoop() { + isConvert = 0; + +} +**/ +#endif +#endif diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderIntel.h b/libyangrtc2/src/yangencoder/YangH264EncoderIntel.h new file mode 100644 index 0000000000000000000000000000000000000000..cb51676b47dfacafb3acc7433a968949325e701e --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderIntel.h @@ -0,0 +1,165 @@ +#ifndef YangH264EncoderIntel_H +#define YangH264EncoderIntel_H + +#ifndef _WIN32 +#include "yangencoder/YangVideoEncoder.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include +#if YangLibva +#include "va/va.h" +#include "va/va_enc_h264.h" +#include "va/va_drm.h" +#include "va/va_drmcommon.h" + +#include "yangutil/sys/YangLoadLib.h" +#include "YangH264EncHeader.h" +#define Para_Bufs 16 + +struct bitstream { + uint32_t *buffer; + int32_t bit_offset; + int32_t max_size_in_dword; +}; + + +class YangH264EncoderIntel: public YangVideoEncoder { +public: + YangH264EncoderIntel(); + ~YangH264EncoderIntel(); + //void init(YangIni *pcontext); + void init(YangVideoParam *pvp,YangVideoEncParam *penc); + + int32_t encode(uint8_t *buf, int32_t buflen, uint8_t *dest, int32_t *destLen,int32_t *frametype); + void setVideoMetaData(YangVideoMeta *pvmd); + void parseRtmpHeader(uint8_t *p,int32_t pLen,int32_t *pwid,int32_t *phei,int32_t *pfps); + +protected: + //void stopLoop(); + //void startLoop(); +private: + + YangVideoMeta *m_vmd; + YangMeataData m_ymd; + int32_t m_fd; + VADisplay m_va_dpy; + VAConfigID m_config_id; + VAContextID m_vaContext; + + VAStatus vas; + + VAImage m_img; + VAImageFormat image_format; + + // YangH264Header h264header; + VAPictureH264 m_pic[16]; + //int32_t m_ref_count; + //int32_t m_ref_count_m1; + + VAPictureH264 CurrentCurrPic; + VAEncPictureParameterBufferH264 m_pic_param; + VAEncSliceParameterBufferH264 m_slice_param; + VAEncSequenceParameterBufferH264 m_seq_param; + VABufferID bufids[10]; + + //YangDecodePicture pics[Para_Bufs]; + VASurfaceID src_surface[Para_Bufs]; + //VASurfaceID ref_surface[Para_Bufs]; + VABufferID coded_buf[Para_Bufs]; + int32_t sid; + +private: + //int32_t isConvert; + //int32_t m_inWidth; + //int32_t m_inHeight; + int32_t m_width_mbaligned; + int32_t m_height_mbaligned; + + int32_t m_frame; + int32_t yLen; + int32_t uLen; + int32_t uvLen; + int32_t allLen; + int32_t frameIdx; + int32_t FieldOrderCnt; + int32_t posNum; + int32_t m_vap_size; + + int32_t current_frame_type; + VAConfigAttrib attrib[VAConfigAttribTypeMax]; + VAConfigAttrib config_attrib[VAConfigAttribTypeMax]; + unsigned int64_t current_frame_encoding; + unsigned int64_t current_frame_display; + unsigned int64_t current_IDR_display; + uint32_t current_frame_num; + int32_t misc_priv_type; + int32_t misc_priv_value; + VAProfile h264_profile; + // int32_t current_frame_type; + int32_t config_attrib_num, enc_packed_header_idx; + +//#define current_slot (current_frame_display % Para_Bufs) + VAPictureH264 ReferenceFrames[16], RefPicList0_P[32], RefPicList0_B[32],RefPicList1_B[32]; + void initSlicePara(VASliceParameterBufferH264 *slice264,uint8_t *p_data, int32_t p_len); + int32_t render_packedpicture(void); + int32_t render_packedsequence(void); + int32_t render_slice(void); + int32_t render_picture(void); + int32_t render_sequence(void); + int32_t update_RefPicList(void); + void slice_header(bitstream *bs); + void pps_rbsp(bitstream *bs); + void sps_rbsp(bitstream *bs); + int32_t calc_poc(int32_t pic_order_cnt_lsb); + void render_packedslice(); + int32_t build_packed_slice_buffer(uint8_t **header_buffer); + int32_t build_packed_seq_buffer(uint8_t **header_buffer); + int32_t build_packed_pic_buffer(uint8_t **header_buffer); + int32_t update_ReferenceFrames(void); + int32_t upload_surface_yuv(VASurfaceID surface_id, int32_t src_width,int32_t src_height, uint8_t *src_Y, uint8_t *src_U,uint8_t *src_V); + int32_t upload_surface_yuv(VADisplay va_dpy, VASurfaceID surface_id, int32_t src_fourcc, int32_t src_width, int32_t src_height, uint8_t *src_Y, + uint8_t *src_U, uint8_t *src_V); +private: + + void closeDevice(); + // int32_t build_packed_seq_buffer(uint8_t **header_buffer) + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + + VAStatus (*yang_vaGetConfigAttributes) (VADisplay dpy, VAProfile profile, VAEntrypoint32_t entrypoint, VAConfigAttrib *attrib_list, int32_t num_attribs); + VAStatus (*yang_vaDeriveImage) (VADisplay dpy,VASurfaceID surface,VAImage *image); + VAStatus (*yang_vaDestroyImage) (VADisplay dpy,VAImageID image); + VADisplay (*yang_vaGetDisplayDRM)(int32_t fd); + VAStatus (*yang_vaInitialize) ( VADisplay dpy, int32_t *major_version,int32_t *minor_version); + VAStatus (*yang_vaDestroyContext) (VADisplay dpy,VAContextID context); + VAStatus (*yang_vaDestroySurfaces) (VADisplay dpy,VASurfaceID *surfaces,int32_t num_surfaces); + VAStatus (*yang_vaDestroyConfig) (VADisplay dpy,VAConfigID config_id); + VAStatus (*yang_vaTerminate) ( VADisplay dpy); + + + VAStatus (*yang_vaCreateConfig) (VADisplay dpy, VAProfile profile, VAEntrypoint32_t entrypoint, VAConfigAttrib *attrib_list, int32_t num_attribs, VAConfigID *config_id ); + + VAStatus (*yang_vaCreateSurfaces)(VADisplay dpy,uint32_t format,uint32_t width, + uint32_t height,VASurfaceID *surfaces,uint32_t num_surfaces, VASurfaceAttrib *attrib_list, + uint32_t num_attribs); + + VAStatus (*yang_vaCreateContext) (VADisplay dpy,VAConfigID config_id, int32_t picture_width, + int32_t picture_height, int32_t flag, VASurfaceID *render_targets, + int32_t num_render_targets,VAContextID *context); + VAStatus (*yang_vaCreateBuffer) (VADisplay dpy,VAContextID context, VABufferType type, + uint32_t size, uint32_t num_elements, void *data, VABufferID *buf_id + ); + VAStatus (*yang_vaBeginPicture) (VADisplay dpy,VAContextID context,VASurfaceID render_target); + VAStatus (*yang_vaRenderPicture) (VADisplay dpy,VAContextID context, VABufferID *buffers,int32_t num_buffers); + + VAStatus (*yang_vaCreateImage) (VADisplay dpy,VAImageFormat *format, int32_t width, int32_t height, VAImage *image); + VAStatus (*yang_vaEndPicture) (VADisplay dpy,VAContextID context); + VAStatus (*yang_vaGetImage) (VADisplay dpy,VASurfaceID surface, int32_t x, + int32_t y,uint32_t width, uint32_t height,VAImageID image); + VAStatus (*yang_vaMapBuffer) (VADisplay dpy,VABufferID buf_id, void **pbuf); + VAStatus (*yang_vaSyncSurface) (VADisplay dpy,VASurfaceID render_target); + VAStatus (*yang_vaUnmapBuffer) (VADisplay dpy,VABufferID buf_id); +}; +#endif +#endif +#endif // YANGH264DECODER_H diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderIntel1.h b/libyangrtc2/src/yangencoder/YangH264EncoderIntel1.h new file mode 100644 index 0000000000000000000000000000000000000000..f1ba2253c634b2c945a8b23b5f28146b684a06fc --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderIntel1.h @@ -0,0 +1,792 @@ +#include "YangH264EncoderIntel.h" +#ifndef _WIN32 +#include "memory.h" +#include +#include "string.h" +#include "sys/ioctl.h" +#include "fcntl.h" +#include "memory.h" +#include "yangutil/yang_unistd.h" +//#include +//#include +#include "string.h" +#include "stdio.h" +#if YangLibva +#include "xf86drm.h" + +//#include "yangutil/video/yangconvert.h" +using namespace std; +#define CHECK_VASTATUS(X, MSG) {if ((X) != VA_STATUS_SUCCESS) {cout <<"\n_ERROR:"<max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING; + bs->buffer = (unsigned int*) calloc(bs->max_size_in_dword * sizeof(int), 1); + bs->bit_offset = 0; +} + +void bitstream_end(bitstream *bs) { + int32_t pos = (bs->bit_offset >> 5); + int32_t bit_offset = (bs->bit_offset & 0x1f); + int32_t bit_left = 32 - bit_offset; + + if (bit_offset) { + bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left)); + } +} + +void bitstream_put_ui(bitstream *bs, uint32_t val, int32_t size_in_bits) { + int32_t pos = (bs->bit_offset >> 5); + int32_t bit_offset = (bs->bit_offset & 0x1f); + int32_t bit_left = 32 - bit_offset; + + if (!size_in_bits) + return; + + bs->bit_offset += size_in_bits; + + if (bit_left > size_in_bits) { + bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val); + } else { + size_in_bits -= bit_left; + bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits); + bs->buffer[pos] = va_swap32(bs->buffer[pos]); + + if (pos + 1 == bs->max_size_in_dword) { + bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING; + bs->buffer = (unsigned int*) realloc(bs->buffer, + bs->max_size_in_dword * sizeof(unsigned int)); + } + + bs->buffer[pos + 1] = val; + } +} + +void bitstream_put_ue(bitstream *bs, uint32_t val) { + int32_t size_in_bits = 0; + int32_t tmp_val = ++val; + + while (tmp_val) { + tmp_val >>= 1; + size_in_bits++; + } + + bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero + bitstream_put_ui(bs, val, size_in_bits); +} + +void bitstream_put_se(bitstream *bs, int32_t val) { + uint32_t new_val; + + if (val <= 0) + new_val = -2 * val; + else + new_val = 2 * val - 1; + + bitstream_put_ue(bs, new_val); +} + +void bitstream_byte_aligning(bitstream *bs, int32_t bit) { + int32_t bit_offset = (bs->bit_offset & 0x7); + int32_t bit_left = 8 - bit_offset; + int32_t new_val; + + if (!bit_offset) + return; + + //assert(bit == 0 || bit == 1); + + if (bit) + new_val = (1 << bit_left) - 1; + else + new_val = 0; + + bitstream_put_ui(bs, new_val, bit_left); +} + +void rbsp_trailing_bits(bitstream *bs) { + bitstream_put_ui(bs, 1, 1); + bitstream_byte_aligning(bs, 0); +} + +void nal_start_code_prefix(bitstream *bs) { + bitstream_put_ui(bs, 0x00000001, 32); +} + +void nal_header(bitstream *bs, int32_t nal_ref_idc, int32_t nal_unit_type) { + bitstream_put_ui(bs, 0, 1); /* forbidden_zero_bit: 0 */ + bitstream_put_ui(bs, nal_ref_idc, 2); + bitstream_put_ui(bs, nal_unit_type, 5); +} + +int32_t build_packed_sei_buffer_timing(uint32_t init_cpb_removal_length, + uint32_t init_cpb_removal_delay, + uint32_t init_cpb_removal_delay_offset, + uint32_t cpb_removal_length, uint32_t cpb_removal_delay, + uint32_t dpb_output_length, uint32_t dpb_output_delay, + uint8_t **sei_buffer) { + uint8_t *byte_buf; + int32_t bp_byte_size, i, pic_byte_size; + + bitstream nal_bs; + bitstream sei_bp_bs, sei_pic_bs; + + bitstream_start(&sei_bp_bs); + bitstream_put_ue(&sei_bp_bs, 0); /*seq_parameter_set_id*/ + bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay, cpb_removal_length); + bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay_offset, + cpb_removal_length); + if (sei_bp_bs.bit_offset & 0x7) { + bitstream_put_ui(&sei_bp_bs, 1, 1); + } + bitstream_end(&sei_bp_bs); + bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8; + + bitstream_start(&sei_pic_bs); + bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length); + bitstream_put_ui(&sei_pic_bs, dpb_output_delay, dpb_output_length); + if (sei_pic_bs.bit_offset & 0x7) { + bitstream_put_ui(&sei_pic_bs, 1, 1); + } + bitstream_end(&sei_pic_bs); + pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8; + + bitstream_start(&nal_bs); + nal_start_code_prefix(&nal_bs); + nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI); + + /* Write the SEI buffer period data */ + bitstream_put_ui(&nal_bs, 0, 8); + bitstream_put_ui(&nal_bs, bp_byte_size, 8); + + byte_buf = (uint8_t *) sei_bp_bs.buffer; + for (i = 0; i < bp_byte_size; i++) { + bitstream_put_ui(&nal_bs, byte_buf[i], 8); + } + free(byte_buf); + /* write the SEI timing data */ + bitstream_put_ui(&nal_bs, 0x01, 8); + bitstream_put_ui(&nal_bs, pic_byte_size, 8); + + byte_buf = (uint8_t *) sei_pic_bs.buffer; + for (i = 0; i < pic_byte_size; i++) { + bitstream_put_ui(&nal_bs, byte_buf[i], 8); + } + free(byte_buf); + + rbsp_trailing_bits(&nal_bs); + bitstream_end(&nal_bs); + + *sei_buffer = (uint8_t *) nal_bs.buffer; + + return nal_bs.bit_offset; +} + + +char *rc_to_string(int32_t rcmode) { + switch (rcmode) { + case VA_RC_NONE: + return "NONE"; + case VA_RC_CBR: + return "CBR"; + case VA_RC_VBR: + return "VBR"; + case VA_RC_VCM: + return "VCM"; + case VA_RC_CQP: + return "CQP"; + case VA_RC_VBR_CONSTRAINED: + return "VBR_CONSTRAINED"; + default: + return "Unknown"; + } +} +/** + void YangH264EncoderIntel::initSlicePara(VASliceParameterBufferH264 *slice264, + uint8_t *p_data, int32_t p_len) { + //initNaluPara(&m_Nalu,p_data); + + + YangSliceContext *sl = h264header.sl; + int32_t ret = (h264header.m_sps.mb_aff + && (sl->picture_structure == Yang_PICT_FRAME)) + || sl->picture_structure != Yang_PICT_FRAME; + slice264->slice_data_size = p_len; + slice264->slice_data_offset = 0; + slice264->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; + slice264->slice_data_bit_offset = h264header.get_bits_count(&sl->gb); + slice264->first_mb_in_slice = (sl->mb_y >> ret) * h264header.m_sps.mb_width + + sl->mb_x; + slice264->slice_type = yang_get_slice_type(sl); //sl->slice_type;//m_Nalu.nal_reference_idc;//ff_h264_get_slice_type(sl); + slice264->direct_spatial_mv_pred_flag = + sl->slice_type == Yang_PICTURE_TYPE_B ? + sl->direct_spatial_mv_pred : 0; + slice264->num_ref_idx_l0_active_minus1 = + sl->list_count > 0 ? sl->ref_count[0] - 1 : 0; + slice264->num_ref_idx_l1_active_minus1 = + sl->list_count > 1 ? sl->ref_count[1] - 1 : 0; + slice264->cabac_init_idc = sl->cabac_init_idc; + slice264->slice_qp_delta = sl->qscale - h264header.m_pps.init_qp; + slice264->disable_deblocking_filter_idc = + sl->deblocking_filter < 2 ? + !sl->deblocking_filter : sl->deblocking_filter; + slice264->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2; + slice264->slice_beta_offset_div2 = sl->slice_beta_offset / 2; + slice264->luma_log2_weight_denom = sl->pwt.luma_log2_weight_denom; + slice264->chroma_log2_weight_denom = sl->pwt.chroma_log2_weight_denom; + sl = NULL; + if(slice264->slice_type==2) + { + slice264->chroma_weight_l0[0][0]=0; + slice264->chroma_weight_l0[0][1]=0; + slice264->chroma_weight_l1[0][0]=0; + slice264->chroma_weight_l1[0][1]=0; + slice264->RefPicList0[0].picture_id = 0xffffffff; + }else{ + slice264->chroma_weight_l0[0][0]=1; + slice264->chroma_weight_l0[0][1]=1; + slice264->chroma_weight_l1[0][0]=1; + slice264->chroma_weight_l1[0][1]=1; + } + + for (int32_t i = 0; i < 32; i++) { + slice264->RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + slice264->RefPicList1[i].flags = VA_PICTURE_H264_INVALID; + slice264->RefPicList0[i].picture_id = 0xffffffff; + slice264->RefPicList1[i].picture_id = 0xffffffff; + } + + }**/ +/** + void YangH264EncoderIntel::cachePic(VAPictureH264 *p_vpic, int32_t p_pocind) { + + if (p_pocind > 0) { + int32_t i = (p_pocind > m_ref_count_m1 - 1 ? m_ref_count_m1 : p_pocind) - 1; + + for (int32_t i = p_pocind - 1; i > 0; i--) + memcpy(&m_pic_param.ReferenceFrames[i], + &m_pic_param.ReferenceFrames[i - 1], m_vap_size); + } + memcpy(&m_pic_param.ReferenceFrames[0], p_vpic, m_vap_size); + + m_pic_param.ReferenceFrames[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; + + }**/ +/**void initPicPara_1(VAPictureParameterBufferH264 *p_pic_para,YangH264Header *header){ + //Yang_SPS *sps, Yang_PPS *pps) { + Yang_SPS *sps=&header->m_sps; + Yang_PPS *pps=&header->m_pps; + //YangSliceContext *sl=header->sl; + //(*p_pic_para) = (VAPictureParameterBufferH264){ + p_pic_para->picture_width_in_mbs_minus1 = sps->mb_width-1;//conf->Video_Width_Zb - 1; + p_pic_para->picture_height_in_mbs_minus1 = sps->mb_height-1;//conf->Video_Height_Zb - 1; + + p_pic_para->bit_depth_luma_minus8 = sps->bit_depth_luma-8; + p_pic_para->bit_depth_chroma_minus8 = sps->bit_depth_chroma-8; + p_pic_para->num_ref_frames = sps->ref_frame_count; + //.seq_fields.bits = { + p_pic_para->seq_fields.bits.chroma_format_idc = sps->chroma_format_idc; + p_pic_para->seq_fields.bits.residual_colour_transform_flag = sps->residual_color_transform_flag; + p_pic_para->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = + sps->gaps_in_frame_num_allowed_flag; + p_pic_para->seq_fields.bits.frame_mbs_only_flag = sps->frame_mbs_only_flag; + p_pic_para->seq_fields.bits.mb_adaptive_frame_field_flag = + sps->mb_aff; + p_pic_para->seq_fields.bits.direct_8x8_inference_flag = + sps->direct_8x8_inference_flag; + p_pic_para->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; //Ap_pic_para->seq_fields.bits.3p_pic_para->seq_fields.bits.3p_pic_para->seq_fields.bits.2 + p_pic_para->seq_fields.bits.log2_max_frame_num_minus4 = + sps->log2_max_frame_num - 4; + p_pic_para->seq_fields.bits.pic_order_cnt_type = sps->poc_type; + p_pic_para->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = + sps->log2_max_poc_lsb - 4; + p_pic_para->seq_fields.bits.delta_pic_order_always_zero_flag = + sps->delta_pic_order_always_zero_flag; + // }; + p_pic_para->num_slice_groups_minus1 = pps->slice_group_count - 1; + p_pic_para->slice_group_map_type = pps->mb_slice_group_map_type; + p_pic_para->slice_group_change_rate_minus1 =0; // + p_pic_para->pic_init_qp_minus26 = pps->init_qp-26; //init_qp - 26; + p_pic_para->pic_init_qs_minus26 = pps->init_qs-26; //init_qs - 26; + p_pic_para->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; + p_pic_para->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; + //.pic_fields.bits = { + p_pic_para->pic_fields.bits.entropy_coding_mode_flag =pps->cabac; + p_pic_para->pic_fields.bits.weighted_pred_flag = pps->weighted_pred; + p_pic_para->pic_fields.bits.weighted_bipred_idc = pps->weighted_bipred_idc; + p_pic_para->pic_fields.bits.transform_8x8_mode_flag =pps->transform_8x8_mode; + p_pic_para->pic_fields.bits.field_pic_flag =0;//sl->picture_structure != Yang_PICT_FRAME; + p_pic_para->pic_fields.bits.constrained_intra_pred_flag = + pps->constrained_intra_pred; + p_pic_para->pic_fields.bits.pic_order_present_flag = + pps->pic_order_present; + p_pic_para->pic_fields.bits.deblocking_filter_control_present_flag = + pps->deblocking_filter_parameters_present; + p_pic_para->pic_fields.bits.redundant_pic_cnt_present_flag = + pps->redundant_pic_cnt_present; + p_pic_para->pic_fields.bits.reference_pic_flag = 1; //h->nal_ref_idc != 0; + // }, + p_pic_para->frame_num = 0; + // }; + + } + int32_t yang_get_slice_type( YangSliceContext *sl) + { + switch (sl->slice_type) { + case Yang_PICTURE_TYPE_P: + return 0; + case Yang_PICTURE_TYPE_B: + return 1; + case Yang_PICTURE_TYPE_I: + return 2; + case Yang_PICTURE_TYPE_SP: + return 3; + case Yang_PICTURE_TYPE_SI: + return 4; + default: + return -1; + } + }**/ + +void encoding2display_order(unsigned int64_t encoding_order, int32_t intra_period, + int32_t intra_idr_period, int32_t ip_period, + unsigned int64_t *displaying_order, int32_t *frame_type) { + int32_t encoding_order_gop = 0; + + if (intra_period == 1) { /* all are I/IDR frames */ + *displaying_order = encoding_order; + if (intra_idr_period == 0) + *frame_type = (encoding_order == 0) ? FRAME_IDR : FRAME_I; + else + *frame_type = + (encoding_order % intra_idr_period == 0) ? + FRAME_IDR : FRAME_I; + return; + } + + if (intra_period == 0) + intra_idr_period = 0; + + /* new sequence like + * IDR PPPPP IPPPPP + * IDR (PBB)(PBB)(IBB)(PBB) + */ + encoding_order_gop = + (intra_idr_period == 0) ? + encoding_order : + (encoding_order + % (intra_idr_period + ((ip_period == 1) ? 0 : 1))); + + if (encoding_order_gop == 0) { /* the first frame */ + *frame_type = FRAME_IDR; + *displaying_order = encoding_order; + } else if (((encoding_order_gop - 1) % ip_period) != 0) { /* B frames */ + *frame_type = FRAME_B; + *displaying_order = encoding_order - 1; + } else if ((intra_period != 0) && /* have I frames */ + (encoding_order_gop >= 2) + && ((ip_period == 1 && encoding_order_gop % intra_period == 0) + || /* for IDR PPPPP IPPPP */ + /* for IDR (PBB)(PBB)(IBB) */ + (ip_period >= 2 + && ((encoding_order_gop - 1) / ip_period + % (intra_period / ip_period)) == 0))) { + *frame_type = FRAME_I; + *displaying_order = encoding_order + ip_period - 1; + } else { + *frame_type = FRAME_P; + *displaying_order = encoding_order + ip_period - 1; + } +} + +#define partition(ref, field, key, ascending) \ + while (i <= j) { \ + if (ascending) { \ + while (ref[i].field < key) \ + i++; \ + while (ref[j].field > key) \ + j--; \ + } else { \ + while (ref[i].field > key) \ + i++; \ + while (ref[j].field < key) \ + j--; \ + } \ + if (i <= j) { \ + tmp = ref[i]; \ + ref[i] = ref[j]; \ + ref[j] = tmp; \ + i++; \ + j--; \ + } \ + } \ + +void sort_one(VAPictureH264 ref[], int32_t left, int32_t right, int32_t ascending, + int32_t frame_idx) { + int32_t i = left, j = right; + uint32_t key; + VAPictureH264 tmp; + + if (frame_idx) { + key = ref[(left + right) / 2].frame_idx; + partition(ref, frame_idx, key, ascending); + } else { + key = ref[(left + right) / 2].TopFieldOrderCnt; + partition(ref, TopFieldOrderCnt, (signed int32_t )key, ascending); + } + + /* recursion */ + if (left < j) + sort_one(ref, left, j, ascending, frame_idx); + + if (i < right) + sort_one(ref, i, right, ascending, frame_idx); +} + +void sort_two(VAPictureH264 ref[], int32_t left, int32_t right, uint32_t key, + uint32_t frame_idx, int32_t partition_ascending, int32_t list0_ascending, + int32_t list1_ascending) { + int32_t i = left, j = right; + VAPictureH264 tmp; + + if (frame_idx) { + partition(ref, frame_idx, key, partition_ascending); + } else { + partition(ref, TopFieldOrderCnt, (signed int32_t )key, partition_ascending); + } + + sort_one(ref, left, i - 1, list0_ascending, frame_idx); + sort_one(ref, j + 1, right, list1_ascending, frame_idx); +} + +void YangH264EncoderIntel::sps_rbsp(bitstream *bs) { + int32_t profile_idc = PROFILE_IDC_BASELINE; + + // if (h264_profile == VAProfileH264High) + // profile_idc = PROFILE_IDC_HIGH; + // else if (h264_profile == VAProfileH264Main) + //profile_idc = PROFILE_IDC_MAIN; + + bitstream_put_ui(bs, profile_idc, 8); /* profile_idc */ + bitstream_put_ui(bs, !!(m_ymd.constraint_set_flag & 1), 1); /* constraint_set0_flag */ + bitstream_put_ui(bs, !!(m_ymd.constraint_set_flag & 2), 1); /* constraint_set1_flag */ + bitstream_put_ui(bs, !!(m_ymd.constraint_set_flag & 4), 1); /* constraint_set2_flag */ + bitstream_put_ui(bs, !!(m_ymd.constraint_set_flag & 8), 1); /* constraint_set3_flag */ + bitstream_put_ui(bs, 0, 4); /* reserved_zero_4bits */ + bitstream_put_ui(bs, m_seq_param.level_idc, 8); /* level_idc */ + bitstream_put_ue(bs, m_seq_param.seq_parameter_set_id); /* seq_parameter_set_id */ + + if (profile_idc == PROFILE_IDC_HIGH) { + bitstream_put_ue(bs, 1); /* chroma_format_idc = 1, 4:2:0 */ + bitstream_put_ue(bs, 0); /* bit_depth_luma_minus8 */ + bitstream_put_ue(bs, 0); /* bit_depth_chroma_minus8 */ + bitstream_put_ui(bs, 0, 1); /* qpprime_y_zero_transform_bypass_flag */ + bitstream_put_ui(bs, 0, 1); /* seq_scaling_matrix_present_flag */ + } + + bitstream_put_ue(bs, m_seq_param.seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */ + bitstream_put_ue(bs, m_seq_param.seq_fields.bits.pic_order_cnt_type); /* pic_order_cnt_type */ + + if (m_seq_param.seq_fields.bits.pic_order_cnt_type == 0) + bitstream_put_ue(bs, + m_seq_param.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4); /* log2_max_pic_order_cnt_lsb_minus4 */ + else { + //assert(0); + } + + bitstream_put_ue(bs, m_seq_param.max_num_ref_frames); /* num_ref_frames */ + bitstream_put_ui(bs, 0, 1); /* gaps_in_frame_num_value_allowed_flag */ + + bitstream_put_ue(bs, m_seq_param.picture_width_in_mbs - 1); /* pic_width_in_mbs_minus1 */ + bitstream_put_ue(bs, m_seq_param.picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */ + bitstream_put_ui(bs, m_seq_param.seq_fields.bits.frame_mbs_only_flag, 1); /* frame_mbs_only_flag */ + + if (!m_seq_param.seq_fields.bits.frame_mbs_only_flag) { + // assert(0); + } + + bitstream_put_ui(bs, m_seq_param.seq_fields.bits.direct_8x8_inference_flag, + 1); /* direct_8x8_inference_flag */ + bitstream_put_ui(bs, m_seq_param.frame_cropping_flag, 1); /* frame_cropping_flag */ + + if (m_seq_param.frame_cropping_flag) { + bitstream_put_ue(bs, m_seq_param.frame_crop_left_offset); /* frame_crop_left_offset */ + bitstream_put_ue(bs, m_seq_param.frame_crop_right_offset); /* frame_crop_right_offset */ + bitstream_put_ue(bs, m_seq_param.frame_crop_top_offset); /* frame_crop_top_offset */ + bitstream_put_ue(bs, m_seq_param.frame_crop_bottom_offset); /* frame_crop_bottom_offset */ + } + + //if ( frame_bit_rate < 0 ) { //TODO EW: the vui header isn't correct + //if (!m_seq_param.vui_parameters_present_flag) { + if (1) { + bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */ + } else { + bitstream_put_ui(bs, m_seq_param.vui_parameters_present_flag, 1); /* vui_parameters_present_flag */ + bitstream_put_ui(bs, m_seq_param.vui_fields.bits.aspect_ratio_info_present_flag, 1); /* aspect_ratio_info_present_flag */ + bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */ + bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */ + bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */ + bitstream_put_ui(bs, m_seq_param.vui_fields.bits.timing_info_present_flag, 1); /* timing_info_present_flag */ + if(m_seq_param.vui_fields.bits.timing_info_present_flag){ + bitstream_put_ui(bs, 15, 32); + bitstream_put_ui(bs, 50, 32); + bitstream_put_ui(bs, m_seq_param.vui_fields.bits.fixed_frame_rate_flag, 1); + } + bitstream_put_ui(bs, 0, 1); /* nal_hrd_parameters_present_flag */ + if(0){ + // hrd_parameters + bitstream_put_ue(bs, 0); /* cpb_cnt_minus1 */ + bitstream_put_ui(bs, 4, 4); /* bit_rate_scale */ + bitstream_put_ui(bs, 6, 4); /* cpb_size_scale */ + + bitstream_put_ue(bs, m_ymd.frame_bitrate - 1); /* bit_rate_value_minus1[0] */ + bitstream_put_ue(bs, m_ymd.frame_bitrate * 8 - 1); /* cpb_size_value_minus1[0] */ + bitstream_put_ui(bs, 1, 1); /* cbr_flag[0] */ + + bitstream_put_ui(bs, 23, 5); /* initial_cpb_removal_delay_length_minus1 */ + bitstream_put_ui(bs, 23, 5); /* cpb_removal_delay_length_minus1 */ + bitstream_put_ui(bs, 23, 5); /* dpb_output_delay_length_minus1 */ + bitstream_put_ui(bs, 23, 5); /* time_offset_length */ + } + bitstream_put_ui(bs, 0, 1); /* vcl_hrd_parameters_present_flag */ + bitstream_put_ui(bs, 0, 1); /* low_delay_hrd_flag */ + + bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */ + bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */ + } + + rbsp_trailing_bits(bs); /* rbsp_trailing_bits */ +} + +int32_t YangH264EncoderIntel::build_packed_pic_buffer( + uint8_t **header_buffer) { + bitstream bs; + + bitstream_start(&bs); + nal_start_code_prefix(&bs); + nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS); + pps_rbsp(&bs); + bitstream_end(&bs); + + *header_buffer = (uint8_t *) bs.buffer; + return bs.bit_offset; +} + +int32_t YangH264EncoderIntel::build_packed_slice_buffer( + uint8_t **header_buffer) { + bitstream bs; + int32_t is_idr = !!m_pic_param.pic_fields.bits.idr_pic_flag; + int32_t is_ref = !!m_pic_param.pic_fields.bits.reference_pic_flag; + + bitstream_start(&bs); + nal_start_code_prefix(&bs); + + if (IS_I_SLICE(m_slice_param.slice_type)) { + nal_header(&bs, NAL_REF_IDC_HIGH, is_idr ? NAL_IDR : NAL_NON_IDR); + } else if (IS_P_SLICE(m_slice_param.slice_type)) { + nal_header(&bs, NAL_REF_IDC_MEDIUM, NAL_NON_IDR); + } else { + //assert(IS_B_SLICE(slice_param.slice_type)); + nal_header(&bs, is_ref ? NAL_REF_IDC_LOW : NAL_REF_IDC_NONE, + NAL_NON_IDR); + } + + slice_header(&bs); + bitstream_end(&bs); + + *header_buffer = (uint8_t *) bs.buffer; + return bs.bit_offset; +} + +int32_t YangH264EncoderIntel::build_packed_seq_buffer( + uint8_t **header_buffer) { + bitstream bs; + + bitstream_start(&bs); + nal_start_code_prefix(&bs); + nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS); + sps_rbsp(&bs); + bitstream_end(&bs); + + *header_buffer = (uint8_t *) bs.buffer; + return bs.bit_offset; +} + +void YangH264EncoderIntel::pps_rbsp(bitstream *bs) { + bitstream_put_ue(bs, m_pic_param.pic_parameter_set_id); /* m_pic_parameter_set_id */ + bitstream_put_ue(bs, m_pic_param.seq_parameter_set_id); /* seq_parameter_set_id */ + + bitstream_put_ui(bs, m_pic_param.pic_fields.bits.entropy_coding_mode_flag, + 1); /* entropy_coding_mode_flag */ + + bitstream_put_ui(bs, 0, 1); /* pic_order_present_flag: 0 */ + + bitstream_put_ue(bs, 0); /* num_slice_groups_minus1 */ + + bitstream_put_ue(bs, m_pic_param.num_ref_idx_l0_active_minus1); /* num_ref_idx_l0_active_minus1 */ + bitstream_put_ue(bs, m_pic_param.num_ref_idx_l1_active_minus1); /* num_ref_idx_l1_active_minus1 1 */ + + bitstream_put_ui(bs, m_pic_param.pic_fields.bits.weighted_pred_flag, 1); /* weighted_pred_flag: 0 */ + bitstream_put_ui(bs, m_pic_param.pic_fields.bits.weighted_bipred_idc, 2); /* weighted_bipred_idc: 0 */ + + bitstream_put_se(bs, m_pic_param.pic_init_qp - 26); /* pic_init_qp_minus26 */ + bitstream_put_se(bs, 0); /* pic_init_qs_minus26 */ + bitstream_put_se(bs, 0); /* chroma_qp_index_offset */ + + bitstream_put_ui(bs, + m_pic_param.pic_fields.bits.deblocking_filter_control_present_flag, + 1); /* deblocking_filter_control_present_flag */ + bitstream_put_ui(bs, 0, 1); /* constrained_intra_pred_flag */ + bitstream_put_ui(bs, 0, 1); /* redundant_pic_cnt_present_flag */ + + /* more_rbsp_data */ + bitstream_put_ui(bs, m_pic_param.pic_fields.bits.transform_8x8_mode_flag, + 1); /*transform_8x8_mode_flag */ + bitstream_put_ui(bs, 0, 1); /* pic_scaling_matrix_present_flag */ + bitstream_put_se(bs, m_pic_param.second_chroma_qp_index_offset); /*second_chroma_qp_index_offset */ + + rbsp_trailing_bits(bs); +} + +void YangH264EncoderIntel::slice_header(bitstream *bs) { + int32_t first_mb_in_slice = m_slice_param.macroblock_address; + + bitstream_put_ue(bs, first_mb_in_slice); /* first_mb_in_slice: 0 */ + bitstream_put_ue(bs, m_slice_param.slice_type); /* slice_type */ + bitstream_put_ue(bs, m_slice_param.pic_parameter_set_id); /* m_pic_parameter_set_id: 0 */ + bitstream_put_ui(bs, m_pic_param.frame_num, + m_seq_param.seq_fields.bits.log2_max_frame_num_minus4 + 4); /* frame_num */ + + /* frame_mbs_only_flag == 1 */ + if (!m_seq_param.seq_fields.bits.frame_mbs_only_flag) { + /* FIXME: */ + // assert(0); + } + + if (m_pic_param.pic_fields.bits.idr_pic_flag) + bitstream_put_ue(bs, m_slice_param.idr_pic_id); /* idr_pic_id: 0 */ + + if (m_seq_param.seq_fields.bits.pic_order_cnt_type == 0) { + bitstream_put_ui(bs, m_pic_param.CurrPic.TopFieldOrderCnt, + m_seq_param.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + + 4); + /* pic_order_present_flag == 0 */ + } else { + /* FIXME: */ + // assert(0); + } + + /* redundant_pic_cnt_present_flag == 0 */ + /* slice type */ + if (IS_P_SLICE(m_slice_param.slice_type)) { + bitstream_put_ui(bs, m_slice_param.num_ref_idx_active_override_flag, 1); /* num_ref_idx_active_override_flag: */ + + if (m_slice_param.num_ref_idx_active_override_flag) + bitstream_put_ue(bs, m_slice_param.num_ref_idx_l0_active_minus1); + + /* ref_pic_list_reordering */ + bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l0: 0 */ + } else if (IS_B_SLICE(m_slice_param.slice_type)) { + bitstream_put_ui(bs, m_slice_param.direct_spatial_mv_pred_flag, 1); /* direct_spatial_mv_pred: 1 */ + + bitstream_put_ui(bs, m_slice_param.num_ref_idx_active_override_flag, 1); /* num_ref_idx_active_override_flag: */ + + if (m_slice_param.num_ref_idx_active_override_flag) { + bitstream_put_ue(bs, m_slice_param.num_ref_idx_l0_active_minus1); + bitstream_put_ue(bs, m_slice_param.num_ref_idx_l1_active_minus1); + } + + /* ref_pic_list_reordering */ + bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l0: 0 */ + bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l1: 0 */ + } + + if ((m_pic_param.pic_fields.bits.weighted_pred_flag + && IS_P_SLICE(m_slice_param.slice_type)) + || ((m_pic_param.pic_fields.bits.weighted_bipred_idc == 1) + && IS_B_SLICE(m_slice_param.slice_type))) { + /* FIXME: fill weight/offset table */ + // assert(0); + } + + /* dec_ref_pic_marking */ + if (m_pic_param.pic_fields.bits.reference_pic_flag) { /* nal_ref_idc != 0 */ + uint8_t no_output_of_prior_pics_flag = 0; + uint8_t long_term_reference_flag = 0; + uint8_t adaptive_ref_pic_marking_mode_flag = 0; + + if (m_pic_param.pic_fields.bits.idr_pic_flag) { + bitstream_put_ui(bs, no_output_of_prior_pics_flag, 1); /* no_output_of_prior_pics_flag: 0 */ + bitstream_put_ui(bs, long_term_reference_flag, 1); /* long_term_reference_flag: 0 */ + } else { + bitstream_put_ui(bs, adaptive_ref_pic_marking_mode_flag, 1); /* adaptive_ref_pic_marking_mode_flag: 0 */ + } + } + + if (m_pic_param.pic_fields.bits.entropy_coding_mode_flag + && !IS_I_SLICE(m_slice_param.slice_type)) + bitstream_put_ue(bs, m_slice_param.cabac_init_idc); /* cabac_init_idc: 0 */ + + bitstream_put_se(bs, m_slice_param.slice_qp_delta); /* slice_qp_delta: 0 */ + + /* ignore for SP/SI */ + + if (m_pic_param.pic_fields.bits.deblocking_filter_control_present_flag) { + bitstream_put_ue(bs, m_slice_param.disable_deblocking_filter_idc); /* disable_deblocking_filter_idc: 0 */ + + if (m_slice_param.disable_deblocking_filter_idc != 1) { + bitstream_put_se(bs, m_slice_param.slice_alpha_c0_offset_div2); /* slice_alpha_c0_offset_div2: 2 */ + bitstream_put_se(bs, m_slice_param.slice_beta_offset_div2); /* slice_beta_offset_div2: 2 */ + } + } + + if (m_pic_param.pic_fields.bits.entropy_coding_mode_flag) { + bitstream_byte_aligning(bs, 1); + } +} +#endif +#endif diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderMeta.cpp b/libyangrtc2/src/yangencoder/YangH264EncoderMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46068985aed6469492857442044c51e4c2cb1682 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderMeta.cpp @@ -0,0 +1,118 @@ +#include "YangH264EncoderMeta.h" +#include +#include +#include +#include +#include +#include "YangH264EncoderSoft.h" +YangH264EncoderMeta::YangH264EncoderMeta() { + m_lib.loadObject("libx264"); + loadLib(); +} +YangH264EncoderMeta::~YangH264EncoderMeta() { + unloadLib(); + m_lib.unloadObject(); +} +void YangH264EncoderMeta::loadLib() { + yang_x264_param_default = (void (*)(x264_param_t*)) m_lib.loadFunction( + "x264_param_default"); + yang_x264_param_default_preset = (int32_t (*)(x264_param_t*, const char *preset, + const char *tune)) m_lib.loadFunction("x264_param_default_preset"); + char s[30]; + memset(s, 0, 30); + sprintf(s, "x264_encoder_open_%d", X264_BUILD); + yang_x264_encoder_open = (x264_t* (*)(x264_param_t*)) m_lib.loadFunction(s); + yang_x264_param_apply_profile = + (int32_t (*)(x264_param_t*, const char *profile)) m_lib.loadFunction( + "x264_param_apply_profile"); + yang_x264_picture_alloc = (int32_t (*)(x264_picture_t *pic, int32_t i_csp, + int32_t i_width, int32_t i_height)) m_lib.loadFunction( + "x264_picture_alloc"); + yang_x264_encoder_headers = (int32_t (*)(x264_t*, x264_nal_t **pp_nal, + int32_t *pi_nal)) m_lib.loadFunction("x264_encoder_headers"); + yang_x264_picture_clean = + (void (*)(x264_picture_t *pic)) m_lib.loadFunction( + "x264_picture_clean"); + yang_x264_encoder_close = (void (*)(x264_t*)) m_lib.loadFunction( + "x264_encoder_close"); +} +void YangH264EncoderMeta::unloadLib() { + yang_x264_param_default_preset = NULL; + yang_x264_encoder_open = NULL; + yang_x264_param_default = NULL; + yang_x264_param_apply_profile = NULL; + yang_x264_picture_alloc = NULL; + yang_x264_encoder_headers = NULL; + yang_x264_picture_clean = NULL; + yang_x264_encoder_close = NULL; +} +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) + +void YangH264EncoderMeta::yang_getSpsPps(YangH2645Conf *p264, + YangVideoInfo *config, YangVideoEncInfo *penc) { + x264_t *p264Handle = NULL; + x264_param_t *param = new x264_param_t(); + if (penc->preset < 5) + yang_x264_param_default_preset(param, x264_preset_names[penc->preset], + "zerolatency"); + else + yang_x264_param_default(param); + + YangH264EncoderSoft::initX264Param(config, penc, param); + yang_x264_param_apply_profile(param, x264_profile_names[0]); + if ((p264Handle = yang_x264_encoder_open(param)) == NULL) { + printf("x264_encoder_open failed/n"); +#ifdef _MSC_VER + ExitProcess(1); +#else + _exit(1); + #endif + + } + int32_t iNal = 0; + x264_nal_t *p264Nal = NULL; + + yang_x264_encoder_headers(p264Handle, &p264Nal, &iNal); + + + for (int32_t i = 0; i < iNal; ++i) { + switch (p264Nal[i].i_type) { + case NAL_SPS: + + p264->spsLen = p264Nal[i].i_payload - 4; + //spsBuf + memcpy(p264->sps, p264Nal[i].p_payload + 4, p264->spsLen); + // put_be32((char*)spsBuf,sps_len); + + break; + case NAL_PPS: + p264->ppsLen = p264Nal[i].i_payload - 4; + + memcpy(p264->pps, p264Nal[i].p_payload + 4, p264->ppsLen); + // put_be32((char*)ppsBuf,pps_len); + + break; + default: + break; + } + } + + yang_x264_encoder_close(p264Handle); + p264Handle = NULL; + delete param; + param = NULL; + p264Nal = NULL; + +} + +void YangH264EncoderMeta::yang_initVmd(YangVideoMeta *p_vmd, + YangVideoInfo *p_config, YangVideoEncInfo *penc) { + if (!p_vmd->isInit) { + yang_getSpsPps(&p_vmd->mp4Meta, p_config, penc); + yang_getConfig_Flv_H264(&p_vmd->mp4Meta, p_vmd->livingMeta.buffer, + &p_vmd->livingMeta.bufLen); + + p_vmd->isInit = 1; + } +} + diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderMeta.h b/libyangrtc2/src/yangencoder/YangH264EncoderMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..0b2507f5de2b303f340ef646950faa29876317e8 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderMeta.h @@ -0,0 +1,34 @@ +#ifndef __YangH264VmdHandle__ +#define __YangH264VmdHandle__ +#include "yangutil/sys/YangLoadLib.h" +#include +#include +#include + +#include "x264.h" +class YangH264EncoderMeta:public YangVideoEncoderMeta{ +public: + YangH264EncoderMeta(); + ~YangH264EncoderMeta(); + void yang_initVmd(YangVideoMeta *p_vmd, YangVideoInfo *p_config, YangVideoEncInfo *penc); +private: + void yang_getH264Config(uint8_t *p_configBuf, int32_t *p_configLen, + YangVideoInfo *p_config); + //void yang_getH264Config_Flv(YangH2645Conf *p_264, uint8_t *configBuf, int32_t *p_configLen); + //void yang_getH264Config_1(YangVideoParam *p_config, YangH2645Conf *p264); + void yang_getSpsPps(YangH2645Conf *p264, YangVideoInfo *config, YangVideoEncInfo *penc); + + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + void (*yang_x264_param_default)(x264_param_t*); + int32_t (* yang_x264_param_default_preset)( x264_param_t *, const char *preset, const char *tune ); + int32_t (*yang_x264_param_apply_profile)(x264_param_t*, const char *profile); + int32_t (*yang_x264_picture_alloc)(x264_picture_t *pic, int32_t i_csp, int32_t i_width, int32_t i_height); + int32_t (*yang_x264_encoder_headers)(x264_t*, x264_nal_t **pp_nal, int32_t *pi_nal); + void (*yang_x264_picture_clean)(x264_picture_t *pic); + void (*yang_x264_encoder_close)(x264_t*); + x264_t* (*yang_x264_encoder_open)(x264_param_t*); +}; + +#endif diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderSoft.cpp b/libyangrtc2/src/yangencoder/YangH264EncoderSoft.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9272742fab5f0bca86f8d30621301a0e83da18cd --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderSoft.cpp @@ -0,0 +1,217 @@ +#include "YangH264EncoderSoft.h" +#include +#include +#include + + +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) + +int32_t YangH264EncoderSoft::hex2bin(char *str, char **hex) { + char *ptr; + int32_t i, l = strlen(str); + if (l & 1) + return 0; + *hex = (char*) malloc(l / 2); + ptr = *hex; + if (!ptr) + return 0; + for (i = 0; i < l; i += 2) + *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i + 1]); + return l / 2; +} + +void YangH264EncoderSoft::loadLib() { + yang_x264_param_default = (void (*)(x264_param_t*)) m_lib.loadFunction( + "x264_param_default"); + yang_x264_param_default_preset = (int32_t (*)(x264_param_t*, const char *preset, + const char *tune)) m_lib.loadFunction("x264_param_default_preset"); + yang_x264_param_apply_profile = + (int32_t (*)(x264_param_t*, const char *profile)) m_lib.loadFunction( + "x264_param_apply_profile"); + char s[30]; + memset(s, 0, 30); + sprintf(s, "x264_encoder_open_%d", X264_BUILD); + yang_x264_encoder_open = (x264_t* (*)(x264_param_t*)) m_lib.loadFunction(s); + yang_x264_picture_alloc = (int32_t (*)(x264_picture_t *pic, int32_t i_csp, + int32_t i_width, int32_t i_height)) m_lib.loadFunction( + "x264_picture_alloc"); + yang_x264_encoder_encode = + (int32_t (*)(x264_t*, x264_nal_t **pp_nal, int32_t *pi_nal, + x264_picture_t *pic_in, x264_picture_t *pic_out)) m_lib.loadFunction( + "x264_encoder_encode"); + yang_x264_picture_clean = + (void (*)(x264_picture_t *pic)) m_lib.loadFunction( + "x264_picture_clean"); + yang_x264_encoder_close = (void (*)(x264_t*)) m_lib.loadFunction( + "x264_encoder_close"); +} +void YangH264EncoderSoft::unloadLib() { + yang_x264_param_default_preset = NULL; + yang_x264_param_default = NULL; + yang_x264_param_apply_profile = NULL; + yang_x264_picture_alloc = NULL; + yang_x264_encoder_encode = NULL; + yang_x264_picture_clean = NULL; + yang_x264_encoder_close = NULL; + yang_x264_encoder_open = NULL; +} +YangH264EncoderSoft::YangH264EncoderSoft() { + m_nal = NULL; + m_264Nal = NULL; + m_sendKeyframe=0; + m_264Pic = NULL; + m_264Handle = NULL; + nal_len = 0; + destLength = 0; + m_i264Nal = 0; + nal_len = 0; + m_hasHeader=false; + unloadLib(); +} + +YangH264EncoderSoft::~YangH264EncoderSoft(void) { + yang_x264_picture_clean(m_264Pic); + yang_x264_encoder_close(m_264Handle); + m_264Pic = NULL; + m_264Handle = NULL; + m_264Nal = NULL; + + m_nal = NULL; + unloadLib(); + m_lib.unloadObject(); + +} +void YangH264EncoderSoft::sendKeyFrame(){ + m_sendKeyframe=1; +} + +void YangH264EncoderSoft::setVideoMetaData(YangVideoMeta *pvmd) { + +} +void YangH264EncoderSoft::initX264Param(YangVideoInfo *pvp, + YangVideoEncInfo *penc, x264_param_t *param) { + param->i_width = pvp->outWidth; //set frame width + param->i_height = pvp->outHeight; //set frame height + param->i_bframe = 0; + param->b_cabac = 0; + param->i_bitdepth = pvp->bitDepth; + + + param->b_interlaced = 0; + //param->rc.i_rc_method = X264_RC_ABR; //X264_RC_CQP ;////X264_RC_CQP X264_RC_CRF + param->i_level_idc = penc->level_idc; + //param->rc.i_bitrate = pvp->rate;//512; + + if (penc->preset > 4) { + param->rc.i_qp_min = 10; + param->rc.i_qp_max = 30; + param->rc.i_qp_constant = 26; + } + + param->i_fps_num = pvp->frame; //30; + param->i_fps_den = 1; + param->i_keyint_max = pvp->frame * 6; + param->i_keyint_min = pvp->frame; + param->i_log_level = X264_LOG_ERROR; //X264_LOG_NONE;//X264_LOG_DEBUG;//X264_LOG_NONE; + param->i_threads=penc->enc_threads; + + param->rc.b_mb_tree = 0; + +} +int32_t YangH264EncoderSoft::init(YangVideoInfo *pvp, YangVideoEncInfo *penc) { + if (m_isInit == 1) return Yang_Ok; + m_lib.loadObject("libx264"); + loadLib(); + setVideoPara(pvp, penc); + x264_param_t *param = new x264_param_t(); + if (penc->preset < 5) + yang_x264_param_default_preset(param, x264_preset_names[penc->preset], + "zerolatency"); + else + yang_x264_param_default(param); + //if (penc->preset < 5) + // yang_x264_param_default_preset(param, x264_preset_names[penc->preset], x264_tune_names[7]); + yang_x264_param_apply_profile(param, x264_profile_names[0]); + initX264Param(pvp, penc, param); + m_hasHeader=!penc->createMeta; + param->b_repeat_headers=m_hasHeader?1:0; + + m_264Pic = new x264_picture_t(); + memset(m_264Pic, 0, sizeof(x264_picture_t)); + //set default param + param->b_sliced_threads = 0; + //param->i_threads = penc->enc_threads; + if ((m_264Handle = yang_x264_encoder_open(param)) == NULL) { + printf("RE init x264_encoder_open failed\n"); + exit(1); + } + int32_t x264Format = pvp->bitDepth == 8 ? X264_CSP_I420 : X264_CSP_HIGH_DEPTH; + //x264_picture_alloc + yang_x264_picture_alloc(m_264Pic, x264Format,param->i_width, param->i_height); + m_264Pic->i_type = X264_TYPE_AUTO; + + m_isInit = 1; + delete param; + param = NULL; + return Yang_Ok; + +} + +int32_t YangH264EncoderSoft::encode(YangFrame* pframe, YangEncoderCallback* pcallback) { + int nalutype=0; + bool isKeyFrame=false; + memcpy(m_264Pic->img.plane[0], pframe->payload,pframe->nb); + //m_nal = m_vbuffer; + destLength = 0; + int32_t frametype = YANG_Frametype_P; + if(m_sendKeyframe==1) { + m_sendKeyframe=2; + m_264Pic->i_type = X264_TYPE_IDR;//X264_TYPE_AUTO; + } + if (yang_x264_encoder_encode(m_264Handle, &m_264Nal, &m_i264Nal, m_264Pic, + &pic_out) < 0) { + fprintf( stderr, "x264_encoder_encode failed/n"); + } + + for (int32_t i = 0; i < m_i264Nal; i++) { + m_nal = m_264Nal[i].p_payload; + nalutype=m_nal[4]& kNalTypeMask; + if ((m_nal[3]& kNalTypeMask) == YangAvcNaluTypeIDR) { + nal_len = 3; + isKeyFrame=true; + + } else { + if ((m_nal[4] & 0x60) == 0 || nalutype == YangAvcNaluTypeSPS || nalutype == YangAvcNaluTypePPS){ + if(!m_hasHeader) continue; + isKeyFrame=true; + } + nal_len = 4; + + } + + if(m_hasHeader&&isKeyFrame) { + yang_put_be32((char*)(m_vbuffer + destLength),(uint32_t)(m_264Nal[i].i_payload-4)); + memcpy(m_vbuffer + destLength+4, m_nal + nal_len, m_264Nal[i].i_payload - nal_len); + destLength += (m_264Nal[i].i_payload - nal_len+4); + }else{ + memcpy(m_vbuffer + destLength, m_nal + nal_len, m_264Nal[i].i_payload - nal_len); + destLength += (m_264Nal[i].i_payload - nal_len); + } + if (m_264Nal[i].i_type == NAL_SLICE_IDR) frametype = YANG_Frametype_I; + + + } + pframe->payload=m_vbuffer; + pframe->frametype=frametype; + pframe->nb=destLength; + if(pcallback) pcallback->onVideoData(pframe); + if(m_sendKeyframe==2) { + m_264Pic->i_type = X264_TYPE_AUTO;//X264_TYPE_AUTO; + m_sendKeyframe=0; + yang_trace("\n********************sendkey.......................frametype==%d\n",frametype); + } + + return 1; +} + + diff --git a/libyangrtc2/src/yangencoder/YangH264EncoderSoft.h b/libyangrtc2/src/yangencoder/YangH264EncoderSoft.h new file mode 100644 index 0000000000000000000000000000000000000000..9878ee7dbbbcf2effe3e6c64d44f7b187bf80b8d --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH264EncoderSoft.h @@ -0,0 +1,55 @@ +#ifndef __YangH264EncoderSoft__ +#define __YangH264EncoderSoft__ +#include +#include +#include +#include +#include +#include + + + +class YangH264EncoderSoft: public YangVideoEncoder { +public: + YangH264EncoderSoft(); + ~YangH264EncoderSoft(void); + static void initX264Param(YangVideoInfo *pvp,YangVideoEncInfo *penc,x264_param_t *param); + int32_t init(YangVideoInfo *pvp,YangVideoEncInfo *penc); + + void setVideoMetaData(YangVideoMeta *pvmd); + void parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, int32_t *phei, int32_t *pfps); + void sendKeyFrame(); +private: + + int32_t m_sendKeyframe; + int32_t encode(YangFrame* pframe, YangEncoderCallback* pcallback); +protected: + int32_t hex2bin(char *str, char **hex); + + uint8_t *m_nal; + int32_t nal_len, destLength; + x264_nal_t *m_264Nal; + int32_t m_i264Nal; + x264_picture_t *m_264Pic; + x264_t *m_264Handle; + x264_picture_t pic_out; + YangLoadLib m_lib; + + void saveFile(char *fileName, uint8_t *pBuffer, int32_t BufferLen); + +private: + + bool m_hasHeader; + + void loadLib(); + void unloadLib(); + void (*yang_x264_param_default)( x264_param_t * ); + int32_t (*yang_x264_param_default_preset)( x264_param_t *, const char *preset, const char *tune ); + int32_t (*yang_x264_param_apply_profile)( x264_param_t *, const char *profile ); + int32_t (*yang_x264_picture_alloc)( x264_picture_t *pic, int32_t i_csp, int32_t i_width, int32_t i_height ); + int32_t (*yang_x264_encoder_encode)( x264_t *, x264_nal_t **pp_nal, int32_t *pi_nal, x264_picture_t *pic_in, x264_picture_t *pic_out ); + void (*yang_x264_picture_clean)( x264_picture_t *pic ); + void (*yang_x264_encoder_close)( x264_t * ); + x264_t* (*yang_x264_encoder_open)( x264_param_t * ); +}; +#endif diff --git a/libyangrtc2/src/yangencoder/YangH265EncoderMeta.cpp b/libyangrtc2/src/yangencoder/YangH265EncoderMeta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..261d8f97e5f1958dea416a6060d39289ef4d475e --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH265EncoderMeta.cpp @@ -0,0 +1,122 @@ +/* + * YangH265EncoderMeta.cpp + * + * Created on: 2020年10月14日 + * Author: yang + */ +#include "YangH265EncoderMeta.h" +#include +#include +#include "YangH265EncoderSoft.h" + +YangH265EncoderMeta::YangH265EncoderMeta() { + + m_lib.loadObject("libx265"); + loadLib(); +} + +YangH265EncoderMeta::~YangH265EncoderMeta() { + unloadLib(); + m_lib.unloadObject(); +} + +void YangH265EncoderMeta::loadLib() { + + yang_x265_param_default = (void (*)(x265_param*)) m_lib.loadFunction( + "x265_param_default"); + yang_x265_param_default_preset=(int32_t (*)(x265_param *, const char *preset, const char *tune))m_lib.loadFunction("x265_param_default_preset"); + char s[30]; + memset(s, 0, 30); + sprintf(s, "x265_encoder_open_%d", X265_BUILD); + //sprintf(s,"x265_encoder_open"); + yang_x265_encoder_open = + (x265_encoder* (*)(x265_param*)) m_lib.loadFunction(s); + yang_x265_param_alloc = (x265_param* (*)(void)) m_lib.loadFunction( + "x265_param_alloc"); + yang_x265_param_free = (void (*)(x265_param*)) m_lib.loadFunction( + "x265_param_free"); + yang_x265_param_apply_profile = + (int32_t (*)(x265_param*, const char *profile)) m_lib.loadFunction( + "x265_param_apply_profile"); +// yang_x265_picture_alloc=(int32_t (*)( x265_picture *pic, int32_t i_csp, int32_t i_width, int32_t i_height ))m_lib.loadFunction("x265_picture_alloc"); + yang_x265_encoder_headers = (int32_t (*)(x265_encoder*, x265_nal **pp_nal, + int32_t *pi_nal)) m_lib.loadFunction("x265_encoder_headers"); + //yang_x265_picture_clean=(void (*)( x265_picture_t *pic ))m_lib.loadFunction("x265_picture_clean"); + yang_x265_encoder_close = (void (*)(x265_encoder*)) m_lib.loadFunction( + "x265_encoder_close"); +} +void YangH265EncoderMeta::unloadLib() { + yang_x265_param_default_preset=NULL; + yang_x265_encoder_open = NULL; + yang_x265_param_alloc = NULL; + yang_x265_param_free = NULL; + yang_x265_param_default = NULL; + yang_x265_param_apply_profile = NULL; + //yang_x265_picture_alloc=NULL; + yang_x265_encoder_headers = NULL; + //yang_x265_picture_clean=NULL; + yang_x265_encoder_close = NULL; +} +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) +; + +void YangH265EncoderMeta::yang_getSpsPps(YangH2645Conf *p264, + YangVideoInfo *p_yvp, YangVideoEncInfo *penc) { + x265_encoder *p265Handle = NULL; + x265_param *param = yang_x265_param_alloc(); + yang_x265_param_default(param); //set default param + if(penc->preset<5) yang_x265_param_default_preset(param,x265_preset_names[penc->preset],x265_tune_names[3]); + YangH265EncoderSoft::initX265Param(p_yvp,penc,param); + yang_x265_param_apply_profile(param, x265_profile_names[0]); + if ((p265Handle = yang_x265_encoder_open(param)) == NULL) { + printf("x265_encoder_open failed/n"); + return; + } + int32_t iNal = 0; + x265_nal *p264Nal = NULL; +//int32_t iResult = + yang_x265_encoder_headers(p265Handle, &p264Nal, &iNal); +//spsBuf=new uint8_t[128]; + + for (int32_t i = 0; i < iNal; ++i) { + switch (p264Nal[i].type) { + case NAL_UNIT_VPS: + p264->vpsLen = p264Nal[i].sizeBytes - 4; + memcpy(p264->vps, p264Nal[i].payload + 4, p264->vpsLen); + + break; + case NAL_UNIT_SPS: + p264->spsLen = p264Nal[i].sizeBytes - 4; + memcpy(p264->sps, p264Nal[i].payload + 4, p264->spsLen); + + break; + case NAL_UNIT_PPS: + p264->ppsLen = p264Nal[i].sizeBytes - 4; + memcpy(p264->pps, p264Nal[i].payload + 4, p264->ppsLen); + + break; + default: + break; + } + } + + yang_x265_encoder_close(p265Handle); + p265Handle = NULL; + yang_x265_param_free(param); + param = NULL; + + p264Nal = NULL; + +} + + +void YangH265EncoderMeta::yang_initVmd(YangVideoMeta *p_vmd, + YangVideoInfo *p_config, YangVideoEncInfo *penc) { + if (!p_vmd->isInit) { + yang_getSpsPps(&p_vmd->mp4Meta, p_config,penc); + yang_getConfig_Flv_H265(&p_vmd->mp4Meta, p_vmd->livingMeta.buffer, + &p_vmd->livingMeta.bufLen); + // yang_getH265Config_Flv(&p_vmd->mp4Meta, p_vmd->flvMeta.buffer, &p_vmd->flvMeta.bufLen); + p_vmd->isInit = 1; + } +} diff --git a/libyangrtc2/src/yangencoder/YangH265EncoderMeta.h b/libyangrtc2/src/yangencoder/YangH265EncoderMeta.h new file mode 100644 index 0000000000000000000000000000000000000000..529a690e4e0fb6a43f0ec9ac8cb038463f09917d --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH265EncoderMeta.h @@ -0,0 +1,44 @@ +/* + * YangH265EncoderMeta.h + * + * Created on: 2020年10月14日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGH265ENCODERMETA_H_ +#define YANGENCODER_SRC_YANGH265ENCODERMETA_H_ +#include "yangutil/sys/YangLoadLib.h" +#include +#include + +#include "x265.h" +#include + +class YangH265EncoderMeta:public YangVideoEncoderMeta { +public: + YangH265EncoderMeta(); + virtual ~YangH265EncoderMeta(); + void yang_initVmd(YangVideoMeta *p_vmd, YangVideoInfo *p_config, YangVideoEncInfo *penc); +private: + void yang_getH265Config(uint8_t *p_configBuf, int32_t *p_configLen, + YangVideoInfo *p_config); + //void yang_getH265Config_Flv(YangH2645Conf *p_265, uint8_t *configBuf, int32_t *p_configLen); + //void yang_getH265Config_1(YangVideoParam *p_config, YangH2645Conf *p265); + void yang_getSpsPps(YangH2645Conf *p265, YangVideoInfo *config, YangVideoEncInfo *penc); + //void initParam(x265_param *param,YangVideoParam *yvp, int32_t p_rc_method); + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + x265_param *(*yang_x265_param_alloc)(void); + void (*yang_x265_param_free)(x265_param *); + void (*yang_x265_param_default)(x265_param*); + int32_t (*yang_x265_param_default_preset)(x265_param *, const char *preset, const char *tune); + int32_t (*yang_x265_param_apply_profile)(x265_param*, const char *profile); + //int32_t (*yang_x265_picture_alloc)(x265_picture_t *pic, int32_t i_csp, int32_t i_width, int32_t i_height); + int32_t (*yang_x265_encoder_headers)(x265_encoder*, x265_nal **pp_nal, int32_t *pi_nal); + //void (*yang_x265_picture_clean)(x265_picture *pic); + void (*yang_x265_encoder_close)(x265_encoder*); + x265_encoder* (*yang_x265_encoder_open)(x265_param*); +}; + +#endif /* YANGENCODER_SRC_YANGH265ENCODERMETA_H_ */ diff --git a/libyangrtc2/src/yangencoder/YangH265EncoderSoft.cpp b/libyangrtc2/src/yangencoder/YangH265EncoderSoft.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6de88c268c20f74dc8530cad74be60111c7b5aa4 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH265EncoderSoft.cpp @@ -0,0 +1,217 @@ +#include "YangH265EncoderSoft.h" +#include +#include +#include +#include + + + + +#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) + +int32_t YangH265EncoderSoft::hex2bin(char *str, char **hex) { + char *ptr; + int32_t i, l = strlen(str); + if (l & 1) + return 0; + *hex = (char*) malloc(l / 2); + ptr = *hex; + if (!ptr) + return 0; + for (i = 0; i < l; i += 2) + *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i + 1]); + return l / 2; +} + + + + +void YangH265EncoderSoft::loadLib(){ + yang_x265_param_default=(void (*)( x265_param * ))m_lib.loadFunction("x265_param_default"); + yang_x265_param_apply_profile=(int32_t (*)( x265_param *, const char *profile ))m_lib.loadFunction("x265_param_apply_profile"); + yang_x265_param_default_preset=(int32_t (*)(x265_param *, const char *preset, const char *tune))m_lib.loadFunction("x265_param_default_preset"); + char s[30]; + memset(s,0,30); + sprintf(s,"x265_encoder_open_%d",X265_BUILD); + yang_x265_param_alloc =(x265_param *(*)(void))m_lib.loadFunction("x265_param_alloc"); + yang_x265_param_free=(void (*)(x265_param *))m_lib.loadFunction("x265_param_free"); + yang_x265_encoder_open=(x265_encoder* (*)( x265_param * ))m_lib.loadFunction(s); + yang_x265_picture_alloc=(x265_picture* (*)())m_lib.loadFunction("x265_picture_alloc"); + yang_x265_picture_init=(void (*)(x265_param *param, x265_picture *pic))m_lib.loadFunction("x265_picture_init"); + yang_x265_encoder_encode=(int32_t (*)( x265_encoder *, x265_nal **pp_nal,uint32_t *pi_nal, x265_picture *pic_in, x265_picture *pic_out ))m_lib.loadFunction("x265_encoder_encode"); + yang_x265_picture_free=(void (*)( x265_picture *pic ))m_lib.loadFunction("x265_picture_free"); + yang_x265_encoder_close=(void (*)( x265_encoder * ))m_lib.loadFunction("x265_encoder_close"); +} +void YangH265EncoderSoft::unloadLib(){ + yang_x265_param_default_preset=NULL; + yang_x265_param_alloc=NULL; + yang_x265_param_free=NULL; + yang_x265_param_default=NULL; + yang_x265_param_apply_profile=NULL; + yang_x265_picture_alloc=NULL; + yang_x265_picture_init=NULL; + yang_x265_encoder_encode=NULL; + yang_x265_picture_free=NULL; + yang_x265_encoder_close=NULL; + yang_x265_encoder_open=NULL; +} +YangH265EncoderSoft::YangH265EncoderSoft() { + m_nal = NULL; + m_265Nal = NULL; + m_265Pic = NULL; + m_265Handle = NULL; + nal_len = 0; + destLength = 0; + m_i265Nal = 0; + nal_len = 0; + m_frametype=0; + m_hasHeader=false; + m_buffer=NULL; + unloadLib(); +} + +YangH265EncoderSoft::~YangH265EncoderSoft(void) { + yang_free(m_buffer); + m_265Pic->planes[0]=NULL; + m_265Pic->planes[1]=NULL; + m_265Pic->planes[2]=NULL; + yang_x265_picture_free(m_265Pic); + yang_x265_encoder_close(m_265Handle); + //x265_encoder_close + m_265Pic = NULL; + m_265Handle = NULL; + m_265Nal = NULL; + + m_nal = NULL; + + unloadLib(); + m_lib.unloadObject(); +} +void YangH265EncoderSoft::sendKeyFrame(){ + m_sendKeyframe=1; + +} +void YangH265EncoderSoft::setVideoMetaData(YangVideoMeta *pvmd) { + +} +void YangH265EncoderSoft::initX265Param(YangVideoInfo *pvp,YangVideoEncInfo *penc,x265_param *param){ + + param->sourceBitDepth=pvp->bitDepth; + //param->bRepeatHeaders=0;//wrtie spspps + param->sourceWidth = pvp->outWidth; //set frame width + param->sourceHeight = pvp->outHeight; //set frame height + param->interlaceMode=0; + + //param->b_cabac = 0; + param->bframes = 0; + +// param->analyse.i_weighted_pred = X265_WEIGHTP_NONE; +// param->analyse.b_weighted_bipred = 0; + // p265Param->b_interlaced=0; + //param->rc.aqMode = X265_RC_ABR; //X265_RC_CQP ;////X265_RC_CQP X265_RC_CRF + param->internalCsp=X265_CSP_I420; + param->levelIdc = penc->level_idc;//31; + //param->rc.bitrate = pvp->rate; + if(penc->preset>4){ + param->rc.qpMin= 10; + param->rc.qpMax = 30; + //param->rc.qp = 26; + } + param->fpsNum = pvp->frame; //30; + param->fpsDenom=1; + + param->keyframeMax = pvp->frame * 3; + param->logLevel = X265_LOG_NONE; + //param->p + //param->analyse.i_me_method=X265_ME_DIA; + //param->rc.b_mb_tree = 0; + //x265_param_apply_profile(param, x265_profile_names[0]); + +} +int32_t YangH265EncoderSoft::init(YangVideoInfo *pvp,YangVideoEncInfo *penc) { + if (m_isInit == 1) + return Yang_Ok; + m_lib.loadObject("libx265"); + loadLib(); + setVideoPara(pvp,penc); + x265_param *param = yang_x265_param_alloc(); + m_265Pic = new x265_picture(); + + memset(m_265Pic, 0, sizeof(x265_picture)); + //x265_param_default(param); + //x265_param_default_present() + yang_x265_param_default(param); //set default param + if(penc->preset<5) yang_x265_param_default_preset(param,x265_preset_names[penc->preset],x265_tune_names[3]); + initX265Param(pvp,penc,param); + m_hasHeader=!penc->createMeta; + param->bRepeatHeaders=m_hasHeader?1:0; + int32_t profileIndex=0; + if(pvp->bitDepth==10) profileIndex=1; + if(pvp->bitDepth==12) profileIndex=12; + + yang_x265_param_apply_profile(param, x265_profile_names[profileIndex]); + //x265_encoder_open + if ((m_265Handle = yang_x265_encoder_open(param)) == NULL) { + + exit(0); + return yang_error_wrap(1,"RE init x265_encoder_open failed"); + } + //x265_picture_alloc + m_265Pic=yang_x265_picture_alloc(); + yang_x265_picture_init(param,m_265Pic); + int32_t bitLen=param->sourceBitDepth==8?1:2; + int32_t fileLen=bitLen*param->sourceWidth*param->sourceHeight*3/2; + int32_t allLen=bitLen*param->sourceWidth*param->sourceHeight; + m_buffer=(uint8_t*)malloc(fileLen); + + m_265Pic->planes[0]=m_buffer; + m_265Pic->planes[1]=m_buffer+allLen; + m_265Pic->planes[2]=m_buffer+allLen*5/4; + m_265Pic->stride[0]=param->sourceWidth; + m_265Pic->stride[1]=param->sourceWidth/2; + m_265Pic->stride[2]=param->sourceWidth/2; + + m_isInit = 1; + yang_x265_param_free(param); + param = NULL; + return Yang_Ok; + +} + +int32_t YangH265EncoderSoft::encode(YangFrame* pframe, YangEncoderCallback* pcallback){ + memcpy(m_265Pic->planes[0], pframe->payload, pframe->nb); + //m_nal = m_vbuffer; + destLength = 0; + + m_frametype = YANG_Frametype_P; + if (m_sendKeyframe == 1) { + m_sendKeyframe = 2; + m_265Pic->sliceType = X265_TYPE_IDR; //X265_TYPE_AUTO; + } + if (yang_x265_encoder_encode(m_265Handle, &m_265Nal, &m_i265Nal, m_265Pic, + NULL) < 0) { + fprintf( stderr, "x265_encoder_encode failed/n"); + } + + for (uint32_t i = 0; i < m_i265Nal; i++) { + m_nal = m_265Nal[i].payload; + if (m_265Nal[i].type >= YANG_NAL_UNIT_CODED_SLICE_BLA&&m_265Nal[i].type <= YANG_NAL_UNIT_CODED_SLICE_CRA) + m_frametype = YANG_Frametype_I; + memcpy(m_vbuffer + destLength, m_nal + 4, m_265Nal[i].sizeBytes - 4); + destLength += (m_265Nal[i].sizeBytes - 4); + + } + pframe->payload = m_vbuffer; + pframe->frametype = m_frametype; + pframe->nb = destLength; + + if (pcallback) + pcallback->onVideoData(pframe); + if (m_sendKeyframe == 2) { + m_265Pic->sliceType = X265_TYPE_AUTO; //X264_TYPE_AUTO; + m_sendKeyframe = 0; + } + return 1; +} + + diff --git a/libyangrtc2/src/yangencoder/YangH265EncoderSoft.h b/libyangrtc2/src/yangencoder/YangH265EncoderSoft.h new file mode 100644 index 0000000000000000000000000000000000000000..7b742fa7732468413252f8c66e77cb92bc4b2a5a --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangH265EncoderSoft.h @@ -0,0 +1,74 @@ +/* + * YangH265EncoderSoft.h + * + * Created on: 2020年10月14日 + * Author: yang + */ + +#ifndef YANGENCODER_SRC_YANGH265ENCODERSOFT_H_ +#define YANGENCODER_SRC_YANGH265ENCODERSOFT_H_ + + +#include +#include +#include +#include +#include +#include + + + +class YangH265EncoderSoft : public YangVideoEncoder { +public: + YangH265EncoderSoft(); + virtual ~YangH265EncoderSoft(); + static void initX265Param(YangVideoInfo *pvp,YangVideoEncInfo *penc,x265_param *param); + int32_t init(YangVideoInfo *pvp,YangVideoEncInfo *penc); + void setVideoMetaData(YangVideoMeta *pvmd); + void parseRtmpHeader(uint8_t *p, int32_t pLen, int32_t *pwid, int32_t *phei, int32_t *pfps); + void sendKeyFrame(); +private: + int32_t m_inWidth; + int32_t m_inHeight; + int32_t m_outWidth; + int32_t m_outHeight; + int32_t m_sendKeyframe; + + int32_t encode(YangFrame* pframe, YangEncoderCallback* pcallback); +protected: + bool m_hasHeader; + int32_t hex2bin(char *str, char **hex); + uint8_t *m_nal; + int32_t nal_len, destLength; + //void saveFile(char *fileName, uint8_t *pBuffer, int32_t BufferLen); + +private: + uint8_t *m_buffer; + + int32_t m_frametype; + + x265_nal *m_265Nal; + uint32_t m_i265Nal; + x265_picture *m_265Pic; + x265_encoder *m_265Handle; + +private: + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + x265_param* (*yang_x265_param_alloc)(void); + void (*yang_x265_param_free)(x265_param*); + void (*yang_x265_param_default)(x265_param*); + int32_t (*yang_x265_param_default_preset)(x265_param*, const char *preset, const char *tune); + int32_t (*yang_x265_param_apply_profile)(x265_param*, const char *profile); + + x265_picture* (*yang_x265_picture_alloc)(); + void (*yang_x265_picture_init)(x265_param *param, x265_picture *pic); + int32_t (*yang_x265_encoder_encode)(x265_encoder*, x265_nal **pp_nal,uint32_t *pi_nal, x265_picture *pic_in, x265_picture *pic_out); + void (*yang_x265_picture_free)(x265_picture *pic); + //x265_picture_free + void (*yang_x265_encoder_close)(x265_encoder*); + x265_encoder* (*yang_x265_encoder_open)(x265_param*); +}; + +#endif /* YANGENCODER_SRC_YANGH265ENCODERSOFT_H_ */ diff --git a/libyangrtc2/src/yangencoder/YangVideoEncoder.cpp b/libyangrtc2/src/yangencoder/YangVideoEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d34c960f7939447b677c89419105492aca4c9f0 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangVideoEncoder.cpp @@ -0,0 +1,26 @@ +/* + * YangH246Encoder.cpp + * + * Created on: 2019年10月16日 + * Author: yang + */ + +#include +#include + +YangVideoEncoder::YangVideoEncoder() { + m_isInit=0; + memset(&m_videoInfo,0,sizeof(YangVideoInfo)); + m_vbuffer=new uint8_t[YANG_VIDEO_ENCODE_BUFFER_LEN]; +} + +YangVideoEncoder::~YangVideoEncoder() { + if(m_vbuffer) delete m_vbuffer; + m_vbuffer=NULL; +} + +void YangVideoEncoder::setVideoPara(YangVideoInfo *pap,YangVideoEncInfo *penc){ + memcpy(&m_videoInfo,pap,sizeof(YangVideoInfo)); + memcpy(&m_enc,penc,sizeof(YangVideoEncInfo)); +} + diff --git a/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.cpp b/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..206265e98c0d386adcca2e3bd71fd1448c8c05b1 --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.cpp @@ -0,0 +1,319 @@ +#include "YangVideoEncoderFfmpeg.h" +#include "YangH264EncHeader.h" +#if Yang_Ffmpeg_UsingSo +void YangVideoEncoderFfmpeg::loadLib() { + yang_av_buffer_unref = (void (*)(AVBufferRef **buf)) m_lib1.loadFunction( + "av_buffer_unref"); + yang_av_hwframe_ctx_init = (int32_t (*)(AVBufferRef *ref)) m_lib1.loadFunction( + "av_hwframe_ctx_init"); + yang_av_frame_alloc = (AVFrame* (*)(void)) m_lib1.loadFunction( + "av_frame_alloc"); + yang_av_image_get_buffer_size = (int32_t (*)(enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_get_buffer_size"); + yang_av_hwdevice_ctx_create = (int32_t (*)(AVBufferRef **device_ctx, + enum AVHWDeviceType type, const char *device, AVDictionary *opts, + int32_t flags)) m_lib1.loadFunction("av_hwdevice_ctx_create"); + yang_av_hwframe_transfer_data = (int32_t (*)(AVFrame *dst, const AVFrame *src, + int32_t flags)) m_lib1.loadFunction("av_hwframe_transfer_data"); + yang_av_free = (void (*)(void *ptr)) m_lib1.loadFunction("av_free"); + yang_av_frame_free = (void (*)(AVFrame **frame)) m_lib1.loadFunction( + "av_frame_free"); + yang_av_buffer_ref = + (AVBufferRef* (*)(AVBufferRef *buf)) m_lib1.loadFunction( + "av_buffer_ref"); + yang_av_image_fill_arrays = (int32_t (*)(uint8_t *dst_data[4], + int32_t dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, + int32_t width, int32_t height, int32_t align)) m_lib1.loadFunction( + "av_image_fill_arrays"); + yang_av_hwframe_ctx_alloc = + (AVBufferRef* (*)(AVBufferRef *device_ctx)) m_lib1.loadFunction( + "av_hwframe_ctx_alloc"); + yang_av_hwframe_get_buffer = (int32_t (*)(AVBufferRef *hwframe_ctx, + AVFrame *frame, int32_t flags)) m_lib1.loadFunction( + "av_hwframe_get_buffer"); + yang_av_malloc = (void* (*)(size_t size)) m_lib1.loadFunction("av_malloc"); + + yang_avcodec_alloc_context3 = + (AVCodecContext* (*)(const AVCodec *codec)) m_lib.loadFunction( + "avcodec_alloc_context3"); + yang_av_init_packet = (void (*)(AVPacket *pkt)) m_lib.loadFunction( + "av_init_packet"); + yang_avcodec_find_encoder_by_name = + (AVCodec* (*)(const char *name)) m_lib.loadFunction( + "avcodec_find_encoder_by_name"); + yang_avcodec_open2 = (int32_t (*)(AVCodecContext *avctx, const AVCodec *codec, + AVDictionary **options)) m_lib.loadFunction("avcodec_open2"); + yang_avcodec_send_frame = (int32_t (*)(AVCodecContext *avctx, + const AVFrame *frame)) m_lib.loadFunction("avcodec_send_frame"); + yang_avcodec_receive_packet = (int32_t (*)(AVCodecContext *avctx, + AVPacket *avpkt)) m_lib.loadFunction("avcodec_receive_packet"); + yang_avcodec_close = (int32_t (*)(AVCodecContext *avctx)) m_lib.loadFunction( + "avcodec_close"); +} +void YangVideoEncoderFfmpeg::unloadLib() { + yang_av_hwframe_ctx_alloc = NULL; + yang_av_hwframe_ctx_init = NULL; + yang_av_buffer_unref = NULL; + yang_avcodec_find_encoder_by_name = NULL; + yang_av_hwdevice_ctx_create = NULL; + yang_av_frame_alloc = NULL; + yang_avcodec_open2 = NULL; + yang_av_image_get_buffer_size = NULL; + yang_av_malloc = NULL; + yang_av_image_fill_arrays = NULL; + yang_av_init_packet = NULL; + yang_av_hwframe_get_buffer = NULL; + yang_av_hwframe_transfer_data = NULL; + yang_avcodec_send_frame = NULL; + yang_avcodec_receive_packet = NULL; + yang_av_frame_free = NULL; + yang_avcodec_close = NULL; + yang_av_free = NULL; +} +#endif +enum AVPixelFormat get_hw_format(AVCodecContext *ctx, + const enum AVPixelFormat *pix_fmts) { + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Intel) return AV_PIX_FMT_VAAPI; + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Nvdia) return AV_PIX_FMT_CUDA; + if(YangVideoEncoderFfmpeg::g_hwType==YangV_Hw_Android) return AV_PIX_FMT_MEDIACODEC; + return AV_PIX_FMT_VAAPI; + /** const enum AVPixelFormat *p; + + for (p = pix_fmts; *p != -1; p++) { + if (*p == hw_pix_fmt) + return *p; + } + + fprintf(stderr, "Failed to get HW surface format.\n"); + return AV_PIX_FMT_NONE;**/ +} +YangVideoHwType YangVideoEncoderFfmpeg::g_hwType=YangV_Hw_Intel; +int32_t YangVideoEncoderFfmpeg::set_hwframe_ctx(AVPixelFormat ctxformat,AVPixelFormat swformat,YangVideoInfo *yvp,AVCodecContext *ctx, + AVBufferRef *hw_device_ctx, int32_t pwid, int32_t phei) { + AVBufferRef *hw_frames_ref; + AVHWFramesContext *frames_ctx = NULL; + int32_t err = 0; + + if (!(hw_frames_ref = yang_av_hwframe_ctx_alloc(hw_device_ctx))) { + printf("Failed to create VAAPI frame context.\n"); + return -1; + } + frames_ctx = (AVHWFramesContext*) (hw_frames_ref->data); + frames_ctx->format = ctxformat; + frames_ctx->sw_format = swformat; + frames_ctx->width = pwid; + frames_ctx->height = phei; + frames_ctx->initial_pool_size = 20; + if ((err = yang_av_hwframe_ctx_init(hw_frames_ref)) < 0) { + printf("Failed to initialize VAAPI frame context.Error code: %d\n", + ret); + yang_av_buffer_unref(&hw_frames_ref); + return err; + } + ctx->hw_frames_ctx = yang_av_buffer_ref(hw_frames_ref); + ctx->hw_device_ctx = yang_av_buffer_ref(hw_device_ctx); + // ctx->hwaccel_flags=1; + if (!ctx->hw_frames_ctx) + err = AVERROR(ENOMEM); + + yang_av_buffer_unref(&hw_frames_ref); + return err; +} + +YangVideoEncoderFfmpeg::YangVideoEncoderFfmpeg(int32_t ptype,int32_t phwtype) { + usingVaapi = 1; //pcontext->usingHwDec == 2 ? 1 : 0; + m_encoderType=(YangVideoEncDecType)ptype; + g_hwType=(YangVideoHwType)phwtype; + m_frame = NULL; + yLen =m_videoInfo.outWidth * m_videoInfo.outHeight; + uLen = yLen / 4; + allLen = yLen * 3 / 2; + buffer = NULL; + ret = 0; + m_codec = NULL; + hw_device_ctx = NULL; + frame_mem_gpu = NULL; + m_usingHw=true; +#if Yang_Ffmpeg_UsingSo + unloadLib(); +#endif + +} +YangVideoEncoderFfmpeg::~YangVideoEncoderFfmpeg() { + encode_close(); +#if Yang_Ffmpeg_UsingSo + unloadLib(); + m_lib.unloadObject(); + m_lib1.unloadObject(); +#endif + +} +void YangVideoEncoderFfmpeg::sendKeyFrame(){ + m_sendKeyframe=1; +} +void YangVideoEncoderFfmpeg::setVideoMetaData(YangVideoMeta *pvmd) { + + /**setZbVmd_f(m_codecCtx->extradata, m_codecCtx->extradata_size, + pvmd->livingMeta.buffer, &pvmd->livingMeta.bufLen);**/ + //printf("\n....%d\n",m_codecCtx->extradata_size); + // for(int32_t i=0;iextradata_size;i++){ + // printf("%02x,",*(m_codecCtx->extradata+i)); + // } +} +void YangVideoEncoderFfmpeg::initParam(AVCodecContext *p_codecCtx,YangVideoInfo *pvp,YangVideoEncInfo *penc){ + p_codecCtx->bit_rate = 1000 *pvp->rate; + //p_codecCtx->global_quality + printf("\nbitrate===%d\n",(int)p_codecCtx->bit_rate ); + p_codecCtx->width = pvp->outWidth; + p_codecCtx->height = pvp->outHeight; + p_codecCtx->profile = pvp->videoEncoderType==Yang_VED_264?FF_PROFILE_H264_CONSTRAINED_BASELINE:FF_PROFILE_HEVC_MAIN; //66; + //p_codecCtx->gop_size = pvp->frame; + //p_codecCtx->level = penc->level_idc; + + p_codecCtx->time_base.den=1;// = (AVRational){1, pvp->frame }; + p_codecCtx->time_base.num=pvp->frame; + p_codecCtx->framerate.den = pvp->frame;//(AVRational){pvp->frame , 1}; + p_codecCtx->framerate.num=1; + //p_codecCtx->time_base = (AVRational ) { 1, pvp->frame }; + if(pvp->videoEncoderType==Yang_VED_264) p_codecCtx->has_b_frames=0; + +} +int32_t YangVideoEncoderFfmpeg::init(YangVideoInfo *pvp,YangVideoEncInfo *penc) { + //AVCodecID codec_id = AV_CODEC_ID_H264; + // av_register_all(); + // avcodec_register_all(); + // avcodec_register(AV_CODEC_ID_H264); + //m_codec = avcodec_find_encoder_by_name("h264_vaapi");//avcodec_find_encoder(AV_CODEC_ID_H264); +#if Yang_Ffmpeg_UsingSo + m_lib.loadObject("libavcodec"); + m_lib1.loadObject("libavutil"); + loadLib(); +#endif + setVideoPara(pvp,penc); + usingVaapi=1; + yLen =m_videoInfo.outWidth * m_videoInfo.outHeight; + uLen = yLen / 4; + allLen = yLen * 3 / 2; + //hevc_vaapi nvenc nvdec vdpau h264_nvenc + if(m_encoderType==Yang_VED_264){ + if(g_hwType==YangV_Hw_Intel) m_codec = yang_avcodec_find_encoder_by_name("h264_vaapi");//avcodec_find_encoder(AV_CODEC_ID_H264); + if(g_hwType==YangV_Hw_Nvdia) { + m_codec = yang_avcodec_find_encoder_by_name("h264_nvenc"); + + } + if(g_hwType==YangV_Hw_Android) m_codec = yang_avcodec_find_encoder_by_name("h264_mediacodec"); + }else if(m_encoderType==Yang_VED_265){ + if(g_hwType==YangV_Hw_Intel) { + m_codec = yang_avcodec_find_encoder_by_name("hevc_vaapi"); + } + if(g_hwType==YangV_Hw_Nvdia) m_codec = yang_avcodec_find_encoder_by_name("hevc_nvenc"); + if(g_hwType==YangV_Hw_Android) m_codec = yang_avcodec_find_encoder_by_name("hevc_mediacodec"); + } + + m_codecCtx = yang_avcodec_alloc_context3(m_codec); + initParam(m_codecCtx,pvp,penc); + m_codecCtx->get_format = get_hw_format; // AV_PIX_FMT_NV12;//get_hw_format; + if(g_hwType==YangV_Hw_Intel){ + + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI,"/dev/dri/renderD128", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_VAAPI; + }else if(g_hwType==YangV_Hw_Nvdia){ + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA,"CUDA", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_CUDA; + }else if(g_hwType==YangV_Hw_Android){ + ret = yang_av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_MEDIACODEC,"MEDIACODEC", NULL, 0); + m_codecCtx->pix_fmt = AV_PIX_FMT_MEDIACODEC; + } + //AVPixelFormat format= pvp->videoEncoderFormat==0?AV_PIX_FMT_NV12:AV_PIX_FMT_YUV420P; + AVPixelFormat format= AV_PIX_FMT_NV12;//AV_PIX_FMT_YUV420P; + if(pvp->bitDepth==10) format = AV_PIX_FMT_P010; + if(pvp->bitDepth==16) format = AV_PIX_FMT_P016; + + if ((ret = set_hwframe_ctx(m_codecCtx->pix_fmt,format,&m_videoInfo,m_codecCtx, hw_device_ctx, m_videoInfo.outWidth, + m_videoInfo.outHeight)) < 0) { + printf("Failed to set hwframe context.\n"); + //goto close; + } + + m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + ret = yang_avcodec_open2(m_codecCtx, m_codec, NULL); + if (ret < 0){ + printf("\navcodec_open2 failure................\n"); + exit(1); + } + + m_frame = yang_av_frame_alloc(); + m_frame->width = m_codecCtx->width; + m_frame->height = m_codecCtx->height; + m_frame->format =format; + // int32_t numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P,m_width,m_height); + int32_t numBytes = yang_av_image_get_buffer_size(format, m_videoInfo.outWidth,m_videoInfo.outHeight, 1); + buffer = (uint8_t*) yang_av_malloc(numBytes * sizeof(uint8_t)); + yang_av_image_fill_arrays(m_frame->data, m_frame->linesize, buffer, + format, m_videoInfo.outWidth, m_videoInfo.outHeight, 1); + yang_av_init_packet(&packet); + frame_mem_gpu = yang_av_frame_alloc(); + frame_mem_gpu->format = m_codecCtx->pix_fmt; + frame_mem_gpu->width = m_codecCtx->width; + frame_mem_gpu->height = m_codecCtx->height; + ret = yang_av_hwframe_get_buffer(m_codecCtx->hw_frames_ctx, frame_mem_gpu, + 0); + if (ret < 0) + printf("\nERROR:av_hwframe_get_buffer failure!\n"); + + m_isInit = 1; + return Yang_Ok; + +} +int32_t YangVideoEncoderFfmpeg::encode(YangFrame* pframe, YangEncoderCallback* pcallback) { + if(!m_codecCtx) return Yang_Ok; + if(m_sendKeyframe==1) { + m_sendKeyframe=2; + m_frame->pict_type=AV_PICTURE_TYPE_I; + } + memcpy(m_frame->data[0], pframe->payload, yLen); + memcpy(m_frame->data[1], pframe->payload + yLen, uLen * 2); + yang_av_hwframe_transfer_data(frame_mem_gpu, m_frame, 0); + ret = yang_avcodec_send_frame(m_codecCtx, frame_mem_gpu); + ret = yang_avcodec_receive_packet(m_codecCtx, &packet); + int32_t destLen=0; + if (ret != 0) { + //destLen = 0; + return Yang_Ok; + } + destLen = packet.size-4; + int32_t frametype=YANG_Frametype_P; + memcpy(m_vbuffer, packet.data+4, destLen); + if(m_encoderType==Yang_VED_264) frametype=m_vbuffer[0]==0x67?YANG_Frametype_I:YANG_Frametype_P; + if(m_encoderType==Yang_VED_265) frametype=m_vbuffer[0]==0x40?YANG_Frametype_I:YANG_Frametype_P; + pframe->payload=m_vbuffer; + pframe->frametype=frametype; + pframe->nb=destLen; + if(pcallback) pcallback->onVideoData(pframe); + if(m_sendKeyframe==2) { + m_frame->pict_type=AV_PICTURE_TYPE_NONE; + m_sendKeyframe=0; + } + return 1; +} + +void YangVideoEncoderFfmpeg::encode_close() { +// av_parser_close(pCodecParserCtx); + if (usingVaapi) { + yang_av_buffer_unref(&hw_device_ctx); + yang_av_frame_free(&frame_mem_gpu); + } + yang_av_frame_free(&m_frame); + m_frame = NULL; + if (m_codecCtx){ + yang_avcodec_close(m_codecCtx); + yang_av_free(m_codecCtx); + } + m_codecCtx = NULL; + if(buffer) yang_av_free(buffer); + buffer = NULL; + +} + diff --git a/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.h b/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..8b0eaedd6e9d96d84b61d1f5567ff6ac36ae614e --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangVideoEncoderFfmpeg.h @@ -0,0 +1,99 @@ +#ifndef YANGH264DECODERFFMPEG_H +#define YANGH264DECODERFFMPEG_H +#include +#include +#include +extern "C"{ +#include +#include +#include + +} +class YangVideoEncoderFfmpeg : public YangVideoEncoder +{ + public: + YangVideoEncoderFfmpeg(int32_t pencType,int32_t phwtype); + ~YangVideoEncoderFfmpeg(); + int32_t init(YangVideoInfo *pvp,YangVideoEncInfo *penc); + static void initParam(AVCodecContext *p_codecCtx,YangVideoInfo *pvp,YangVideoEncInfo *penc); + static YangVideoHwType g_hwType; + //void encode(uint8_t *src,int32_t buflen, uint8_t *dest, int32_t *destLen, int32_t *frametype); + //int32_t encode(uint8_t *buf, int32_t buflen, uint8_t *dest, int32_t *destLen,int32_t *frametype); + int32_t encode(YangFrame* pframe, YangEncoderCallback* pcallback); + void setVideoMetaData(YangVideoMeta *pvmd); + void sendKeyFrame(); + void parseRtmpHeader(uint8_t *p,int32_t pLen,int32_t *pwid,int32_t *phei,int32_t *pfps); + protected: + + private: + int32_t ret; + YangVideoEncDecType m_encoderType; + int32_t m_sendKeyframe; + AVCodec *m_codec; + AVCodecContext *m_codecCtx = NULL; + AVPacket packet; + AVFrame *m_frame; + bool m_usingHw; + + int32_t yLen; + int32_t uLen; + int32_t allLen; + uint8_t* buffer =NULL; + int32_t usingVaapi; + AVBufferRef *hw_device_ctx; + AVFrame *frame_mem_gpu; + int32_t set_hwframe_ctx(AVPixelFormat ctxformat,AVPixelFormat swformat,YangVideoInfo *yvp,AVCodecContext *ctx, AVBufferRef *hw_device_ctx,int32_t pwid,int32_t phei); + private: + void encode_close(); +#if Yang_Ffmpeg_UsingSo + YangLoadLib m_lib,m_lib1; + void loadLib(); + void unloadLib(); + AVBufferRef *(*yang_av_hwframe_ctx_alloc)(AVBufferRef *device_ctx); + int32_t (*yang_av_hwframe_ctx_init)(AVBufferRef *ref); + void (*yang_av_buffer_unref)(AVBufferRef **buf); + AVCodec *(*yang_avcodec_find_encoder_by_name)(const char *name); + int32_t (*yang_av_hwdevice_ctx_create)(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int32_t flags); + AVFrame *(*yang_av_frame_alloc)(void); + int32_t (*yang_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + int32_t (*yang_av_image_get_buffer_size)(enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + void *(*yang_av_malloc)(size_t size); + int32_t (*yang_av_image_fill_arrays)(uint8_t *dst_data[4], int32_t dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int32_t width, int32_t height, int32_t align); + void (*yang_av_init_packet)(AVPacket *pkt); + int32_t (*yang_av_hwframe_get_buffer)(AVBufferRef *hwframe_ctx, AVFrame *frame, int32_t flags); + int32_t (*yang_av_hwframe_transfer_data)(AVFrame *dst, const AVFrame *src, int32_t flags); + int32_t (*yang_avcodec_send_frame)(AVCodecContext *avctx, const AVFrame *frame); + int32_t (*yang_avcodec_receive_packet)(AVCodecContext *avctx, AVPacket *avpkt); + void (*yang_av_frame_free)(AVFrame **frame); + int32_t (*yang_avcodec_close)(AVCodecContext *avctx); + void (*yang_av_free)(void *ptr); + AVBufferRef *(*yang_av_buffer_ref)(AVBufferRef *buf); + AVCodecContext *(*yang_avcodec_alloc_context3)(const AVCodec *codec); +#else +#define yang_av_hwframe_ctx_alloc av_hwframe_ctx_alloc +#define yang_av_hwframe_ctx_init av_hwframe_ctx_init +#define yang_av_buffer_unref av_buffer_unref +#define yang_avcodec_find_encoder_by_name avcodec_find_encoder_by_name +#define yang_av_hwdevice_ctx_create av_hwdevice_ctx_create +#define yang_av_frame_alloc av_frame_alloc +#define yang_avcodec_open2 avcodec_open2 +#define yang_av_image_get_buffer_size av_image_get_buffer_size +#define yang_av_malloc av_malloc +#define yang_av_image_fill_arrays av_image_fill_arrays +#define yang_av_init_packet av_init_packet +#define yang_av_hwframe_get_buffer av_hwframe_get_buffer +#define yang_av_hwframe_transfer_data av_hwframe_transfer_data +#define yang_avcodec_send_frame avcodec_send_frame +#define yang_avcodec_receive_packet avcodec_receive_packet +#define yang_av_frame_free av_frame_free +#define yang_avcodec_close avcodec_close +#define yang_av_free av_free +#define yang_av_buffer_ref av_buffer_ref +#define yang_avcodec_alloc_context3 avcodec_alloc_context3 +#endif +}; + +#endif // YANGH264DECODERFFMPEG_H diff --git a/libyangrtc2/src/yangencoder/YangVideoEncoderHandle.cpp b/libyangrtc2/src/yangencoder/YangVideoEncoderHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74401648fff60659c4b0b4a5e9f54306712f227a --- /dev/null +++ b/libyangrtc2/src/yangencoder/YangVideoEncoderHandle.cpp @@ -0,0 +1,192 @@ + +#include +#include + +#include +#include +#include +#include + +#include +#include + + + +YangVideoEncoderHandle::YangVideoEncoderHandle(YangVideoInfo *pcontext, + YangVideoEncInfo *enc) { + m_isInit = 0; + m_isStart = 0; + m_isConvert = 1; + m_in_videoBuffer = NULL; + m_out_videoBuffer = NULL; + m_para = pcontext; + m_enc = enc; + m_vmd = NULL; + m_sendKeyframe=0; + m_uid=0; +} + +YangVideoEncoderHandle::~YangVideoEncoderHandle(void) { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_para = NULL; + m_enc = NULL; + m_in_videoBuffer = NULL; + m_out_videoBuffer = NULL; + m_vmd = NULL; + +} +void YangVideoEncoderHandle::stop() { + stopLoop(); +} + +void YangVideoEncoderHandle::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangVideoEncoderHandle::sendKeyframe(){ + m_sendKeyframe=1; +} +void YangVideoEncoderHandle::setVideoMetaData(YangVideoMeta *pvmd) { + m_vmd = pvmd; +} + +void YangVideoEncoderHandle::init() { + m_isInit = 1; + +} + +void YangVideoEncoderHandle::setInVideoBuffer(YangVideoBuffer *plist) { + m_in_videoBuffer = plist; +} +void YangVideoEncoderHandle::setOutVideoBuffer(YangVideoEncoderBuffer *plist) { + m_out_videoBuffer = plist; +} +void YangVideoEncoderHandle::onVideoData(YangFrame* pframe){ + + if (pframe->nb > 4) { + // yang_trace("\n%d:",pframe->nb); + //for(int i=0;i<50;i++) yang_trace("%02x,",pframe->payload[i]); + m_out_videoBuffer->putEVideo(pframe); + } +} +void YangVideoEncoderHandle::onAudioData(YangFrame* pframe){ + +} +void YangVideoEncoderHandle::startLoop() { + m_isConvert = 1; + YangVideoInfo para; + YangYuvConvert yuv; + memcpy(¶, m_para, sizeof(YangVideoInfo)); + //int32_t is12bit = yvp.videoCaptureFormat > 0 ? 1 : 0; + int32_t isTrans = (para.width != para.outWidth ? 1 : 0); + int32_t isHw=m_para->videoEncHwType; + //int64_t videoTimestamp = 0; + int32_t bitLen = para.bitDepth == 8 ? 1 : 2; + int32_t m_in_fileSize = bitLen * para.width * para.height * 3 / 2; + int32_t m_out_fileSize = bitLen * para.outWidth * para.outHeight * 3 / 2; + + uint8_t *outVideoSrc = NULL; + if (isTrans) { + outVideoSrc = new uint8_t[para.outWidth * para.outHeight * 3 / 2]; + } + + if (m_in_videoBuffer != NULL) + m_in_videoBuffer->resetIndex(); + if (m_out_videoBuffer != NULL) + m_out_videoBuffer->resetIndex(); + + YangEncoderFactory ydf; + YangVideoEncoder *t_Encoder = ydf.createVideoEncoder(m_para); + + t_Encoder->init(¶, m_enc); + t_Encoder->setVideoMetaData(m_vmd); + + uint8_t* nv12Src=NULL; + //uint8_t* tmpNv12=NULL; + if(isHw) nv12Src=new uint8_t[m_in_fileSize]; + int64_t t_preTimestamp=0; + int32_t wid=m_para->width; + int32_t hei=m_para->height; + YangFrame videoFrame; + memset(&videoFrame,0,sizeof(YangFrame)); + + while (m_isConvert == 1) { + if (m_in_videoBuffer->size() == 0) { + yang_usleep(20000); + continue; + } + uint8_t *tmp=NULL; + uint8_t *tmpsrc=NULL; + + tmpsrc=m_in_videoBuffer->getVideoRef(&videoFrame); + + if(!tmpsrc) continue; + + if(isHw){ + + if(tmpsrc){ + //tmpNv12=m_in_videoBuffer->getVideoIn(&videoTimestamp); + if(para.videoEncoderFormat==YangI420) { + yuv.i420tonv12(tmpsrc,nv12Src,wid,hei); + tmp=nv12Src; + } + if(para.videoEncoderFormat==YangArgb){ + tmp=tmpsrc; + } + } + + }else{ + tmp=tmpsrc; + //tmp=m_in_videoBuffer->getVideoIn(&videoTimestamp); + } + + + if(t_preTimestamp){ + if(videoFrame.timestamp<=t_preTimestamp){ + tmp=NULL; + continue; + } + } + t_preTimestamp=videoFrame.timestamp; + if(m_sendKeyframe==1){ + t_Encoder->sendKeyFrame(); + m_sendKeyframe=0; + } + //videoFrame.timestamp=frame->timestamp; + videoFrame.uid=m_uid; + + if (isTrans) { + yuv.scaleI420(tmp, + outVideoSrc, para.width, para.height, para.outWidth, + para.outHeight); + videoFrame.payload=outVideoSrc; + videoFrame.nb=m_out_fileSize; + + t_Encoder->encode(&videoFrame,this); + } else { + videoFrame.payload=tmp; + videoFrame.nb=m_in_fileSize; + t_Encoder->encode(&videoFrame,this); + + } + tmp=NULL; + + } + //tmpNv12=NULL; + yang_deleteA(outVideoSrc); + yang_deleteA(nv12Src); + yang_delete(t_Encoder); + + +} + +void YangVideoEncoderHandle::stopLoop() { + m_isConvert = 0; + +} diff --git a/libyangrtc2/src/yangencoder/lame.h b/libyangrtc2/src/yangencoder/lame.h new file mode 100644 index 0000000000000000000000000000000000000000..c3694b3ba32b42fa701624d5ade322f9910766de --- /dev/null +++ b/libyangrtc2/src/yangencoder/lame.h @@ -0,0 +1,1342 @@ +/* + * Interface to MP3 LAME encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame.h,v 1.192 2017/08/31 14:14:46 robert Exp $ */ + +#ifndef LAME_LAME_H +#define LAME_LAME_H + +/* for size_t typedef */ +#include +/* for va_list typedef */ +#include +/* for FILE typedef, TODO: remove when removing lame_mp3_tags_fid */ +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef void (*lame_report_function)(const char *format, va_list ap); + +#if defined(WIN32) || defined(_WIN32) +#undef CDECL +#define CDECL __cdecl +#else +#define CDECL +#endif + +#define DEPRECATED_OR_OBSOLETE_CODE_REMOVED 1 + +typedef enum vbr_mode_e { + vbr_off=0, + vbr_mt, /* obsolete, same as vbr_mtrh */ + vbr_rh, + vbr_abr, + vbr_mtrh, + vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ + vbr_default=vbr_mtrh /* change this to change the default VBR mode of LAME */ +} vbr_mode; + + +/* MPEG modes */ +typedef enum MPEG_mode_e { + STEREO = 0, + JOINT_STEREO, + DUAL_CHANNEL, /* LAME doesn't supports this! */ + MONO, + NOT_SET, + MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} MPEG_mode; + +/* Padding types */ +typedef enum Padding_type_e { + PAD_NO = 0, + PAD_ALL, + PAD_ADJUST, + PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} Padding_type; + + + +/*presets*/ +typedef enum preset_mode_e { + /*values from 8 to 320 should be reserved for abr bitrates*/ + /*for abr I'd suggest to directly use the targeted bitrate as a value*/ + ABR_8 = 8, + ABR_320 = 320, + + V9 = 410, /*Vx to match Lame and VBR_xx to match FhG*/ + VBR_10 = 410, + V8 = 420, + VBR_20 = 420, + V7 = 430, + VBR_30 = 430, + V6 = 440, + VBR_40 = 440, + V5 = 450, + VBR_50 = 450, + V4 = 460, + VBR_60 = 460, + V3 = 470, + VBR_70 = 470, + V2 = 480, + VBR_80 = 480, + V1 = 490, + VBR_90 = 490, + V0 = 500, + VBR_100 = 500, + + + + /*still there for compatibility*/ + R3MIX = 1000, + STANDARD = 1001, + EXTREME = 1002, + INSANE = 1003, + STANDARD_FAST = 1004, + EXTREME_FAST = 1005, + MEDIUM = 1006, + MEDIUM_FAST = 1007 +} preset_mode; + + +/*asm optimizations*/ +typedef enum asm_optimizations_e { + MMX = 1, + AMD_3DNOW = 2, + SSE = 3 +} asm_optimizations; + + +/* psychoacoustic model */ +typedef enum Psy_model_e { + PSY_GPSYCHO = 1, + PSY_NSPSYTUNE = 2 +} Psy_model; + + +/* buffer considerations */ +typedef enum buffer_constraint_e { + MDB_DEFAULT=0, + MDB_STRICT_ISO=1, + MDB_MAXIMUM=2 +} buffer_constraint; + + +struct lame_global_struct; +typedef struct lame_global_struct lame_global_flags; +typedef lame_global_flags *lame_t; + + + + +/*********************************************************************** + * + * The LAME API + * These functions should be called, in this order, for each + * MP3 file to be encoded. See the file "API" for more documentation + * + ***********************************************************************/ + + +/* + * REQUIRED: + * initialize the encoder. sets default for all encoder parameters, + * returns NULL if some malloc()'s failed + * otherwise returns pointer to structure needed for all future + * API calls. + */ +lame_global_flags * CDECL lame_init(void); +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* obsolete version */ +int32_t CDECL lame_init_old(lame_global_flags *); +#endif + +/* + * OPTIONAL: + * set as needed to override defaults + */ + +/******************************************************************** + * input stream description + ***********************************************************************/ +/* number of samples. default = 2^32-1 */ +int32_t CDECL lame_set_num_samples(lame_global_flags *, unsigned long); +unsigned long CDECL lame_get_num_samples(const lame_global_flags *); + +/* input sample rate in Hz. default = 44100hz */ +int32_t CDECL lame_set_in_samplerate(lame_global_flags *, int); +int32_t CDECL lame_get_in_samplerate(const lame_global_flags *); + +/* number of channels in input stream. default=2 */ +int32_t CDECL lame_set_num_channels(lame_global_flags *, int); +int32_t CDECL lame_get_num_channels(const lame_global_flags *); + +/* + scale the input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int32_t CDECL lame_set_scale(lame_global_flags *, float); +float CDECL lame_get_scale(const lame_global_flags *); + +/* + scale the channel 0 (left) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int32_t CDECL lame_set_scale_left(lame_global_flags *, float); +float CDECL lame_get_scale_left(const lame_global_flags *); + +/* + scale the channel 1 (right) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int32_t CDECL lame_set_scale_right(lame_global_flags *, float); +float CDECL lame_get_scale_right(const lame_global_flags *); + +/* + output sample rate in Hz. default = 0, which means LAME picks best value + based on the amount of compression. MPEG only allows: + MPEG1 32, 44.1, 48khz + MPEG2 16, 22.05, 24 + MPEG2.5 8, 11.025, 12 + (not used by decoding routines) +*/ +int32_t CDECL lame_set_out_samplerate(lame_global_flags *, int); +int32_t CDECL lame_get_out_samplerate(const lame_global_flags *); + + +/******************************************************************** + * general control parameters + ***********************************************************************/ +/* 1=cause LAME to collect data for an MP3 frame analyzer. default=0 */ +int32_t CDECL lame_set_analysis(lame_global_flags *, int); +int32_t CDECL lame_get_analysis(const lame_global_flags *); + +/* + 1 = write a Xing VBR header frame. + default = 1 + this variable must have been added by a Hungarian notation Windows programmer :-) +*/ +int32_t CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); +int32_t CDECL lame_get_bWriteVbrTag(const lame_global_flags *); + +/* 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 */ +int32_t CDECL lame_set_decode_only(lame_global_flags *, int); +int32_t CDECL lame_get_decode_only(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* 1=encode a Vorbis .ogg file. default=0 */ +/* DEPRECATED */ +int32_t CDECL lame_set_ogg(lame_global_flags *, int); +int32_t CDECL lame_get_ogg(const lame_global_flags *); +#endif + +/* + internal algorithm selection. True quality is determined by the bitrate + but this variable will effect quality by selecting expensive or cheap algorithms. + quality=0..9. 0=best (very slow). 9=worst. + recommended: 2 near-best quality, not too slow + 5 good quality, fast + 7 ok quality, really fast +*/ +int32_t CDECL lame_set_quality(lame_global_flags *, int); +int32_t CDECL lame_get_quality(const lame_global_flags *); + +/* + mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono + default: lame picks based on compression ration and input channels +*/ +int32_t CDECL lame_set_mode(lame_global_flags *, MPEG_mode); +MPEG_mode CDECL lame_get_mode(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + mode_automs. Use a M/S mode with a switching threshold based on + compression ratio + DEPRECATED +*/ +int32_t CDECL lame_set_mode_automs(lame_global_flags *, int); +int32_t CDECL lame_get_mode_automs(const lame_global_flags *); +#endif + +/* + force_ms. Force M/S for all frames. For testing only. + default = 0 (disabled) +*/ +int32_t CDECL lame_set_force_ms(lame_global_flags *, int); +int32_t CDECL lame_get_force_ms(const lame_global_flags *); + +/* use free_format? default = 0 (disabled) */ +int32_t CDECL lame_set_free_format(lame_global_flags *, int); +int32_t CDECL lame_get_free_format(const lame_global_flags *); + +/* perform ReplayGain analysis? default = 0 (disabled) */ +int32_t CDECL lame_set_findReplayGain(lame_global_flags *, int); +int32_t CDECL lame_get_findReplayGain(const lame_global_flags *); + +/* decode on the fly. Search for the peak sample. If the ReplayGain + * analysis is enabled then perform the analysis on the decoded data + * stream. default = 0 (disabled) + * NOTE: if this option is set the build-in decoder should not be used */ +int32_t CDECL lame_set_decode_on_the_fly(lame_global_flags *, int); +int32_t CDECL lame_get_decode_on_the_fly(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* DEPRECATED: now does the same as lame_set_findReplayGain() + default = 0 (disabled) */ +int32_t CDECL lame_set_ReplayGain_input(lame_global_flags *, int); +int32_t CDECL lame_get_ReplayGain_input(const lame_global_flags *); + +/* DEPRECATED: now does the same as + lame_set_decode_on_the_fly() && lame_set_findReplayGain() + default = 0 (disabled) */ +int32_t CDECL lame_set_ReplayGain_decode(lame_global_flags *, int); +int32_t CDECL lame_get_ReplayGain_decode(const lame_global_flags *); + +/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() + default = 0 (disabled) */ +int32_t CDECL lame_set_findPeakSample(lame_global_flags *, int); +int32_t CDECL lame_get_findPeakSample(const lame_global_flags *); +#endif + +/* counters for gapless encoding */ +int32_t CDECL lame_set_nogap_total(lame_global_flags*, int); +int32_t CDECL lame_get_nogap_total(const lame_global_flags*); + +int32_t CDECL lame_set_nogap_currentindex(lame_global_flags* , int); +int32_t CDECL lame_get_nogap_currentindex(const lame_global_flags*); + + +/* + * OPTIONAL: + * Set printf like error/debug/message reporting functions. + * The second argument has to be a pointer to a function which looks like + * void my_debugf(const char *format, va_list ap) + * { + * (void) vfprintf(stdout, format, ap); + * } + * If you use NULL as the value of the pointer in the set function, the + * lame buildin function will be used (prints to stderr). + * To quiet any output you have to replace the body of the example function + * with just "return;" and use it in the set function. + */ +int32_t CDECL lame_set_errorf(lame_global_flags *, lame_report_function); +int32_t CDECL lame_set_debugf(lame_global_flags *, lame_report_function); +int32_t CDECL lame_set_msgf (lame_global_flags *, lame_report_function); + + + +/* set one of brate compression ratio. default is compression ratio of 11. */ +int32_t CDECL lame_set_brate(lame_global_flags *, int); +int32_t CDECL lame_get_brate(const lame_global_flags *); +int32_t CDECL lame_set_compression_ratio(lame_global_flags *, float); +float CDECL lame_get_compression_ratio(const lame_global_flags *); + + +int32_t CDECL lame_set_preset( lame_global_flags* gfp, int32_t ); +int32_t CDECL lame_set_asm_optimizations( lame_global_flags* gfp, int, int32_t ); + + + +/******************************************************************** + * frame params + ***********************************************************************/ +/* mark as copyright. default=0 */ +int32_t CDECL lame_set_copyright(lame_global_flags *, int); +int32_t CDECL lame_get_copyright(const lame_global_flags *); + +/* mark as original. default=1 */ +int32_t CDECL lame_set_original(lame_global_flags *, int); +int32_t CDECL lame_get_original(const lame_global_flags *); + +/* error_protection. Use 2 bytes from each frame for CRC checksum. default=0 */ +int32_t CDECL lame_set_error_protection(lame_global_flags *, int); +int32_t CDECL lame_get_error_protection(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) */ +int32_t CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); +#endif + +/* MP3 'private extension' bit Meaningless. default=0 */ +int32_t CDECL lame_set_extension(lame_global_flags *, int); +int32_t CDECL lame_get_extension(const lame_global_flags *); + +/* enforce strict ISO compliance. default=0 */ +int32_t CDECL lame_set_strict_ISO(lame_global_flags *, int); +int32_t CDECL lame_get_strict_ISO(const lame_global_flags *); + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* disable the bit reservoir. For testing only. default=0 */ +int32_t CDECL lame_set_disable_reservoir(lame_global_flags *, int); +int32_t CDECL lame_get_disable_reservoir(const lame_global_flags *); + +/* select a different "best quantization" function. default=0 */ +int32_t CDECL lame_set_quant_comp(lame_global_flags *, int); +int32_t CDECL lame_get_quant_comp(const lame_global_flags *); +int32_t CDECL lame_set_quant_comp_short(lame_global_flags *, int); +int32_t CDECL lame_get_quant_comp_short(const lame_global_flags *); + +int32_t CDECL lame_set_experimentalX(lame_global_flags *, int); /* compatibility*/ +int32_t CDECL lame_get_experimentalX(const lame_global_flags *); + +/* another experimental option. for testing only */ +int32_t CDECL lame_set_experimentalY(lame_global_flags *, int); +int32_t CDECL lame_get_experimentalY(const lame_global_flags *); + +/* another experimental option. for testing only */ +int32_t CDECL lame_set_experimentalZ(lame_global_flags *, int); +int32_t CDECL lame_get_experimentalZ(const lame_global_flags *); + +/* Naoki's psycho acoustic model. default=0 */ +int32_t CDECL lame_set_exp_nspsytune(lame_global_flags *, int); +int32_t CDECL lame_get_exp_nspsytune(const lame_global_flags *); + +void CDECL lame_set_msfix(lame_global_flags *, double); +float CDECL lame_get_msfix(const lame_global_flags *); + + +/******************************************************************** + * VBR control + ***********************************************************************/ +/* Types of VBR. default = vbr_off = CBR */ +int32_t CDECL lame_set_VBR(lame_global_flags *, vbr_mode); +vbr_mode CDECL lame_get_VBR(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest */ +int32_t CDECL lame_set_VBR_q(lame_global_flags *, int); +int32_t CDECL lame_get_VBR_q(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest, Range [0,...,10[ */ +int32_t CDECL lame_set_VBR_quality(lame_global_flags *, float); +float CDECL lame_get_VBR_quality(const lame_global_flags *); + +/* Ignored except for VBR=vbr_abr (ABR mode) */ +int32_t CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); +int32_t CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); + +int32_t CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); +int32_t CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); + +int32_t CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); +int32_t CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); + +/* + 1=strictly enforce VBR_min_bitrate. Normally it will be violated for + analog silence +*/ +int32_t CDECL lame_set_VBR_hard_min(lame_global_flags *, int); +int32_t CDECL lame_get_VBR_hard_min(const lame_global_flags *); + +/* for preset */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int32_t CDECL lame_set_preset_expopts(lame_global_flags *, int); +#endif + +/******************************************************************** + * Filtering control + ***********************************************************************/ +/* freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled */ +int32_t CDECL lame_set_lowpassfreq(lame_global_flags *, int); +int32_t CDECL lame_get_lowpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int32_t CDECL lame_set_lowpasswidth(lame_global_flags *, int); +int32_t CDECL lame_get_lowpasswidth(const lame_global_flags *); + +/* freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled */ +int32_t CDECL lame_set_highpassfreq(lame_global_flags *, int); +int32_t CDECL lame_get_highpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int32_t CDECL lame_set_highpasswidth(lame_global_flags *, int); +int32_t CDECL lame_get_highpasswidth(const lame_global_flags *); + + +/******************************************************************** + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + ***********************************************************************/ + +/* only use ATH for masking */ +int32_t CDECL lame_set_ATHonly(lame_global_flags *, int); +int32_t CDECL lame_get_ATHonly(const lame_global_flags *); + +/* only use ATH for short blocks */ +int32_t CDECL lame_set_ATHshort(lame_global_flags *, int); +int32_t CDECL lame_get_ATHshort(const lame_global_flags *); + +/* disable ATH */ +int32_t CDECL lame_set_noATH(lame_global_flags *, int); +int32_t CDECL lame_get_noATH(const lame_global_flags *); + +/* select ATH formula */ +int32_t CDECL lame_set_ATHtype(lame_global_flags *, int); +int32_t CDECL lame_get_ATHtype(const lame_global_flags *); + +/* lower ATH by this many db */ +int32_t CDECL lame_set_ATHlower(lame_global_flags *, float); +float CDECL lame_get_ATHlower(const lame_global_flags *); + +/* select ATH adaptive adjustment type */ +int32_t CDECL lame_set_athaa_type( lame_global_flags *, int); +int32_t CDECL lame_get_athaa_type( const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* select the loudness approximation used by the ATH adaptive auto-leveling */ +int32_t CDECL lame_set_athaa_loudapprox( lame_global_flags *, int); +int32_t CDECL lame_get_athaa_loudapprox( const lame_global_flags *); +#endif + +/* adjust (in dB) the point32_t below which adaptive ATH level adjustment occurs */ +int32_t CDECL lame_set_athaa_sensitivity( lame_global_flags *, float); +float CDECL lame_get_athaa_sensitivity( const lame_global_flags* ); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* OBSOLETE: predictability limit (ISO tonality formula) */ +int32_t CDECL lame_set_cwlimit(lame_global_flags *, int); +int32_t CDECL lame_get_cwlimit(const lame_global_flags *); +#endif + +/* + allow blocktypes to differ between channels? + default: 0 for jstereo, 1 for stereo +*/ +int32_t CDECL lame_set_allow_diff_short(lame_global_flags *, int); +int32_t CDECL lame_get_allow_diff_short(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int32_t CDECL lame_set_useTemporal(lame_global_flags *, int); +int32_t CDECL lame_get_useTemporal(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int32_t CDECL lame_set_interChRatio(lame_global_flags *, float); +float CDECL lame_get_interChRatio(const lame_global_flags *); + +/* disable short blocks */ +int32_t CDECL lame_set_no_short_blocks(lame_global_flags *, int); +int32_t CDECL lame_get_no_short_blocks(const lame_global_flags *); + +/* force short blocks */ +int32_t CDECL lame_set_force_short_blocks(lame_global_flags *, int); +int32_t CDECL lame_get_force_short_blocks(const lame_global_flags *); + +/* Input PCM is emphased PCM (for instance from one of the rarely + emphased CDs), it is STRONGLY not recommended to use this, because + psycho does not take it into account, and last but not least many decoders + ignore these bits */ +int32_t CDECL lame_set_emphasis(lame_global_flags *, int); +int32_t CDECL lame_get_emphasis(const lame_global_flags *); + + + +/************************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/************************************************************************/ +/* version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) */ +int32_t CDECL lame_get_version(const lame_global_flags *); + +/* encoder delay */ +int32_t CDECL lame_get_encoder_delay(const lame_global_flags *); + +/* + padding appended to the input to make sure decoder can fully decode + all input. Note that this value can only be calculated during the + call to lame_encoder_flush(). Before lame_encoder_flush() has + been called, the value of encoder_padding = 0. +*/ +int32_t CDECL lame_get_encoder_padding(const lame_global_flags *); + +/* size of MPEG frame */ +int32_t CDECL lame_get_framesize(const lame_global_flags *); + +/* number of PCM samples buffered, but not yet encoded to mp3 data. */ +int32_t CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); + +/* + size (bytes) of mp3 data buffered, but not yet encoded. + this is the number of bytes which would be output by a call to + lame_encode_flush_nogap. NOTE: lame_encode_flush() will return + more bytes than this because it will encode the reamining buffered + PCM samples before flushing the mp3 buffers. +*/ +int32_t CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); + +/* number of frames encoded so far */ +int32_t CDECL lame_get_frameNum(const lame_global_flags *); + +/* + lame's estimate of the total number of frames to be encoded + only valid if calling program set num_samples +*/ +int32_t CDECL lame_get_totalframes(const lame_global_flags *); + +/* RadioGain value. Multiplied by 10 and rounded to the nearest. */ +int32_t CDECL lame_get_RadioGain(const lame_global_flags *); + +/* AudiophileGain value. Multipled by 10 and rounded to the nearest. */ +int32_t CDECL lame_get_AudiophileGain(const lame_global_flags *); + +/* the peak sample */ +float CDECL lame_get_PeakSample(const lame_global_flags *); + +/* Gain change required for preventing clipping. The value is correct only if + peak sample searching was enabled. If negative then the waveform + already does not clip. The value is multiplied by 10 and rounded up. */ +int32_t CDECL lame_get_noclipGainChange(const lame_global_flags *); + +/* user-specified scale factor required for preventing clipping. Value is + correct only if peak sample searching was enabled and no user-specified + scaling was performed. If negative then either the waveform already does + not clip or the value cannot be determined */ +float CDECL lame_get_noclipScale(const lame_global_flags *); + +/* returns the limit of PCM samples, which one can pass in an encode call + under the constrain of a provided buffer of size buffer_size */ +int32_t CDECL lame_get_maximum_number_of_samples(lame_t gfp, size_t buffer_size); + + + + +/* + * REQUIRED: + * sets more internal configuration based on data provided above. + * returns -1 if something failed. + */ +int32_t CDECL lame_init_params(lame_global_flags *); + + +/* + * OPTIONAL: + * get the version number, in a string. of the form: + * "3.63 (beta)" or just "3.63". + */ +const char* CDECL get_lame_version ( void ); +const char* CDECL get_lame_short_version ( void ); +const char* CDECL get_lame_very_short_version ( void ); +const char* CDECL get_psy_version ( void ); +const char* CDECL get_lame_url ( void ); +const char* CDECL get_lame_os_bitness ( void ); + +/* + * OPTIONAL: + * get the version numbers in numerical form. + */ +typedef struct { + /* generic LAME version */ + int32_t major; + int32_t minor; + int32_t alpha; /* 0 if not an alpha version */ + int32_t beta; /* 0 if not a beta version */ + + /* version of the psy model */ + int32_t psy_major; + int32_t psy_minor; + int32_t psy_alpha; /* 0 if not an alpha version */ + int32_t psy_beta; /* 0 if not a beta version */ + + /* compile time features */ + const char *features; /* Don't make assumptions about the contents! */ +} lame_version_t; +void CDECL get_lame_version_numerical(lame_version_t *); + + +/* + * OPTIONAL: + * print32_t internal lame configuration to message handler + */ +void CDECL lame_print_config(const lame_global_flags* gfp); + +void CDECL lame_print_internals( const lame_global_flags *gfp); + + +/* + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * + * return code number of bytes output in mp3buf. Can be 0 + * -1: mp3buf was too small + * -2: malloc() problem + * -3: lame_init_params() not called + * -4: psycho acoustic problems + * + * The required mp3buf_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buf_size in bytes = 1.25*num_samples + 7200 + * + * I think a tighter bound could be: (mt, March 2000) + * MPEG1: + * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 + * MPEG2: + * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 + * + * but test first if you use that! + * + * set mp3buf_size = 0 and LAME will not check if mp3buf_size is + * large enough. + * + * NOTE: + * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels + * will be averaged into the L channel before encoding only the L channel + * This will overwrite the data in buffer_l[] and buffer_r[]. + * +*/ +int32_t CDECL lame_encode_buffer ( + lame_global_flags* gfp, /* global context handle */ + const int16_t buffer_l [], /* PCM data for left channel */ + const int16_t buffer_r [], /* PCM data for right channel */ + const int32_t nsamples, /* number of samples per channel */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but input has L & R channel data interleaved. + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int32_t CDECL lame_encode_buffer_interleaved( + lame_global_flags* gfp, /* global context handlei */ + int16_t pcm[], /* PCM data for left and right + channel, interleaved */ + int32_t num_samples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + int32_t mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + */ +int32_t CDECL lame_encode_buffer_float( + lame_global_flags* gfp, /* global context handle */ + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int32_t nsamples, /* number of samples per channel */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int32_t CDECL lame_encode_buffer_ieee_float( + lame_t gfp, + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int32_t nsamples, + uint8_t * mp3buf, + const int32_t mp3buf_size); +int32_t CDECL lame_encode_buffer_interleaved_ieee_float( + lame_t gfp, + const float pcm[], /* PCM data for left and right + channel, interleaved */ + const int32_t nsamples, + uint8_t * mp3buf, + const int32_t mp3buf_size); + +/* as lame_encode_buffer, but for 'double's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int32_t CDECL lame_encode_buffer_ieee_double( + lame_t gfp, + const double pcm_l [], /* PCM data for left channel */ + const double pcm_r [], /* PCM data for right channel */ + const int32_t nsamples, + uint8_t * mp3buf, + const int32_t mp3buf_size); +int32_t CDECL lame_encode_buffer_interleaved_ieee_double( + lame_t gfp, + const double pcm[], /* PCM data for left and right + channel, interleaved */ + const int32_t nsamples, + uint8_t * mp3buf, + const int32_t mp3buf_size); + +/* as lame_encode_buffer, but for long's + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + * + * This scaling was a mistake (doesn't allow one to exploit full + * precision of type 'long'. Use lame_encode_buffer_long2() instead. + * + */ +int32_t CDECL lame_encode_buffer_long( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int32_t nsamples, /* number of samples per channel */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + +/* Same as lame_encode_buffer_long(), but with correct scaling. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'long'. Data should be in the range: +/- 2^(8*size(long)-1) + * + */ +int32_t CDECL lame_encode_buffer_long2( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int32_t nsamples, /* number of samples per channel */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for int's + * !! NOTE: !! input should be scaled to the maximum range of 'int' + * If int32_t is 4 bytes, then the values should range from + * +/- 2147483648. + * + * This routine does not (and cannot, without loosing precision) use + * the same scaling as the rest of the lame_encode_buffer() routines. + * + */ +int32_t CDECL lame_encode_buffer_int( + lame_global_flags* gfp, /* global context handle */ + const int32_t buffer_l [], /* PCM data for left channel */ + const int32_t buffer_r [], /* PCM data for right channel */ + const int32_t nsamples, /* number of samples per channel */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but for interleaved data. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'int32_t'. Data should be in the range: +/- 2^(8*size(int32_t)-1) + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int +lame_encode_buffer_interleaved_int( + lame_t gfp, + const int32_t pcm [], /* PCM data for left and right + channel, interleaved */ + const int32_t nsamples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + const int32_t mp3buf_size ); /* number of valid octets in this + stream */ + + + +/* + * REQUIRED: + * lame_encode_flush will flush the intenal PCM buffers, padding with + * 0's to make sure the final frame is complete, and then flush + * the internal MP3 buffers, and thus may return a + * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * will also write id3v1 tags (if any) into the bitstream + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int32_t CDECL lame_encode_flush( + lame_global_flags * gfp, /* global context handle */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + int32_t size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * lame_encode_flush_nogap will flush the internal mp3 buffers and pad + * the last frame with ancillary data so it is a complete mp3 frame. + * + * 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * After a call to this routine, the outputed mp3 data is complete, but + * you may continue to encode new PCM samples and write future mp3 data + * to a different file. The two mp3 files will play back with no gaps + * if they are concatenated together. + * + * This routine will NOT write id3v1 tags into the bitstream. + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int32_t CDECL lame_encode_flush_nogap( + lame_global_flags * gfp, /* global context handle */ + uint8_t* mp3buf, /* pointer to encoded MP3 stream */ + int32_t size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * Normally, this is called by lame_init_params(). It writes id3v2 and + * Xing headers into the front of the bitstream, and sets frame counters + * and bitrate histogram data to 0. You can also call this after + * lame_encode_flush_nogap(). + */ +int32_t CDECL lame_init_bitstream( + lame_global_flags * gfp); /* global context handle */ + + + +/* + * OPTIONAL: some simple statistics + * a bitrate histogram to visualize the distribution of used frame sizes + * a stereo mode histogram to visualize the distribution of used stereo + * modes, useful in joint-stereo mode only + * 0: LR left-right encoded + * 1: LR-I left-right and intensity encoded (currently not supported) + * 2: MS mid-side encoded + * 3: MS-I mid-side and intensity encoded (currently not supported) + * + * attention: don't call them after lame_encode_finish + * suggested: lame_encode_flush -> lame_*_hist -> lame_close + */ + +void CDECL lame_bitrate_hist( + const lame_global_flags * gfp, + int32_t bitrate_count[14] ); +void CDECL lame_bitrate_kbps( + const lame_global_flags * gfp, + int32_t bitrate_kbps [14] ); +void CDECL lame_stereo_mode_hist( + const lame_global_flags * gfp, + int32_t stereo_mode_count[4] ); + +void CDECL lame_bitrate_stereo_mode_hist ( + const lame_global_flags * gfp, + int32_t bitrate_stmode_count[14][4] ); + +void CDECL lame_block_type_hist ( + const lame_global_flags * gfp, + int32_t btype_count[6] ); + +void CDECL lame_bitrate_block_type_hist ( + const lame_global_flags * gfp, + int32_t bitrate_btype_count[14][6] ); + +#if (DEPRECATED_OR_OBSOLETE_CODE_REMOVED && 0) +#else +/* + * OPTIONAL: + * lame_mp3_tags_fid will rewrite a Xing VBR tag to the mp3 file with file + * pointer fid. These calls perform forward and backwards seeks, so make + * sure fid is a real file. Make sure lame_encode_flush has been called, + * and all mp3 data has been written to the file before calling this + * function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME because + * the output is not a regular file, this call does nothing + * NOTE: + * LAME wants to read from the file to skip an optional ID3v2 tag, so + * make sure you opened the file for writing and reading. + * NOTE: + * You can call lame_get_lametag_frame instead, if you want to insert + * the lametag yourself. +*/ +void CDECL lame_mp3_tags_fid(lame_global_flags *, FILE* fid); +#endif + +/* + * OPTIONAL: + * lame_get_lametag_frame copies the final LAME-tag into 'buffer'. + * The function returns the number of bytes copied into buffer, or + * the required buffer size, if the provided buffer is too small. + * Function failed, if the return value is larger than 'size'! + * Make sure lame_encode flush has been called before calling this function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME, + * this call does nothing and returns 0. + * NOTE: + * LAME inserted an empty frame in the beginning of mp3 audio data, + * which you have to replace by the final LAME-tag frame after encoding. + * In case there is no ID3v2 tag, usually this frame will be the very first + * data in your mp3 file. If you put some other leading data into your + * file, you'll have to do some bookkeeping about where to write this buffer. + */ +size_t CDECL lame_get_lametag_frame( + const lame_global_flags *, uint8_t* buffer, size_t size); + +/* + * REQUIRED: + * final call to free all remaining buffers + */ +int32_t CDECL lame_close (lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + * OBSOLETE: + * lame_encode_finish combines lame_encode_flush() and lame_close() in + * one call. However, once this call is made, the statistics routines + * will no longer work because the data will have been cleared, and + * lame_mp3_tags_fid() cannot be called to add data to the VBR header + */ +int32_t CDECL lame_encode_finish( + lame_global_flags* gfp, + uint8_t* mp3buf, + int32_t size ); +#endif + + + + + + +/********************************************************************* + * + * decoding + * + * a simple interface to mpglib, part of mpg123, is also included if + * libmp3lame is compiled with HAVE_MPGLIB + * + *********************************************************************/ + +struct hip_global_struct; +typedef struct hip_global_struct hip_global_flags; +typedef hip_global_flags *hip_t; + + +typedef struct { + int32_t header_parsed; /* 1 if header was parsed and following data was + computed */ + int32_t stereo; /* number of channels */ + int32_t samplerate; /* sample rate */ + int32_t bitrate; /* bitrate */ + int32_t mode; /* mp3 frame type */ + int32_t mode_ext; /* mp3 frame type */ + int32_t framesize; /* number of samples per mp3 frame */ + + /* this data is only computed if mpglib detects a Xing VBR header */ + unsigned long nsamp; /* number of samples in mp3 file. */ + int32_t totalframes; /* total number of frames in mp3 file */ + + /* this data is not currently computed by the mpglib routines */ + int32_t framenum; /* frames decoded counter */ +} mp3data_struct; + +/* required call to initialize decoder */ +hip_t CDECL hip_decode_init(void); + +/* cleanup call to exit decoder */ +int32_t CDECL hip_decode_exit(hip_t gfp); + +/* HIP reporting functions */ +void CDECL hip_set_errorf(hip_t gfp, lame_report_function f); +void CDECL hip_set_debugf(hip_t gfp, lame_report_function f); +void CDECL hip_set_msgf (hip_t gfp, lame_report_function f); + +/********************************************************************* + * input 1 mp3 frame, output (maybe) pcm data. + * + * nout = hip_decode(hip, mp3buf,len,pcm_l,pcm_r); + * + * input: + * len : number of bytes of mp3 data in mp3buf + * mp3buf[len] : mp3 data to be decoded + * + * output: + * nout: -1 : decoding error + * 0 : need more data before we can complete the decode + * >0 : returned 'nout' samples worth of data in pcm_l,pcm_r + * pcm_l[nout] : left channel data + * pcm_r[nout] : right channel data + * + *********************************************************************/ +int32_t CDECL hip_decode( hip_t gfp + , uint8_t * mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode, and also returns mp3 header data */ +int32_t CDECL hip_decode_headers( hip_t gfp + , uint8_t* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode, but returns at most one frame */ +int32_t CDECL hip_decode1( hip_t gfp + , uint8_t* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode1, but returns at most one frame and mp3 header data */ +int32_t CDECL hip_decode1_headers( hip_t gfp + , uint8_t* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode1_headers, but also returns enc_delay and enc_padding + from VBR Info tag, (-1 if no info tag was found) */ +int32_t CDECL hip_decode1_headersB( hip_t gfp + , uint8_t* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + , int32_t *enc_delay + , int32_t *enc_padding + ); + + + +/* OBSOLETE: + * lame_decode... functions are there to keep old code working + * but it is strongly recommended to replace calls by hip_decode... + * function calls, see above. + */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int32_t CDECL lame_decode_init(void); +int32_t CDECL lame_decode( + uint8_t * mp3buf, + int32_t len, + short pcm_l[], + short pcm_r[] ); +int32_t CDECL lame_decode_headers( + uint8_t* mp3buf, + int32_t len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int32_t CDECL lame_decode1( + uint8_t* mp3buf, + int32_t len, + short pcm_l[], + short pcm_r[] ); +int32_t CDECL lame_decode1_headers( + uint8_t* mp3buf, + int32_t len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int32_t CDECL lame_decode1_headersB( + uint8_t* mp3buf, + int32_t len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int32_t *enc_delay, + int32_t *enc_padding ); +int32_t CDECL lame_decode_exit(void); + +#endif /* obsolete lame_decode API calls */ + + +/********************************************************************* + * + * id3tag stuff + * + *********************************************************************/ + +/* + * id3tag.h -- Interface to write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* utility to obtain alphabetically sorted list of genre names with numbers */ +void CDECL id3tag_genre_list( + void (*handler)(int, const char *, void *), + void* cookie); + +void CDECL id3tag_init (lame_t gfp); + +/* force addition of version 2 tag */ +void CDECL id3tag_add_v2 (lame_t gfp); + +/* add only a version 1 tag */ +void CDECL id3tag_v1_only (lame_t gfp); + +/* add only a version 2 tag */ +void CDECL id3tag_v2_only (lame_t gfp); + +/* pad version 1 tag with spaces instead of nulls */ +void CDECL id3tag_space_v1 (lame_t gfp); + +/* pad version 2 tag with extra 128 bytes */ +void CDECL id3tag_pad_v2 (lame_t gfp); + +/* pad version 2 tag with extra n bytes */ +void CDECL id3tag_set_pad (lame_t gfp, size_t n); + +void CDECL id3tag_set_title(lame_t gfp, const char* title); +void CDECL id3tag_set_artist(lame_t gfp, const char* artist); +void CDECL id3tag_set_album(lame_t gfp, const char* album); +void CDECL id3tag_set_year(lame_t gfp, const char* year); +void CDECL id3tag_set_comment(lame_t gfp, const char* comment); + +/* return -1 result if track number is out of ID3v1 range + and ignored for ID3v1 */ +int32_t CDECL id3tag_set_track(lame_t gfp, const char* track); + +/* return non-zero result if genre name or number is invalid + result 0: OK + result -1: genre number out of range + result -2: no valid ID3v1 genre name, mapped to ID3v1 'Other' + but taken as-is for ID3v2 genre tag */ +int32_t CDECL id3tag_set_genre(lame_t gfp, const char* genre); + +/* return non-zero result if field name is invalid */ +int32_t CDECL id3tag_set_fieldvalue(lame_t gfp, const char* fieldvalue); + +/* return non-zero result if image type is invalid */ +int32_t CDECL id3tag_set_albumart(lame_t gfp, const char* image, size_t size); + +/* lame_get_id3v1_tag copies ID3v1 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v1 tag. + */ +size_t CDECL lame_get_id3v1_tag(lame_t gfp, uint8_t* buffer, size_t size); + +/* lame_get_id3v2_tag copies ID3v2 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v2 tag. + */ +size_t CDECL lame_get_id3v2_tag(lame_t gfp, uint8_t* buffer, size_t size); + +/* normaly lame_init_param writes ID3v2 tags into the audio stream + * Call lame_set_write_id3tag_automatic(gfp, 0) before lame_init_param + * to turn off this behaviour and get ID3v2 tag with above function + * write it yourself into your file. + */ +void CDECL lame_set_write_id3tag_automatic(lame_global_flags * gfp, int); +int32_t CDECL lame_get_write_id3tag_automatic(lame_global_flags const* gfp); + +/* experimental */ +int32_t CDECL id3tag_set_textinfo_latin1(lame_t gfp, char const *id, char const *text); + +/* experimental */ +int32_t CDECL id3tag_set_comment_latin1(lame_t gfp, char const *lang, char const *desc, char const *text); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* experimental */ +int32_t CDECL id3tag_set_textinfo_ucs2(lame_t gfp, char const *id, unsigned short const *text); + +/* experimental */ +int32_t CDECL id3tag_set_comment_ucs2(lame_t gfp, char const *lang, + unsigned short const *desc, unsigned short const *text); + +/* experimental */ +int32_t CDECL id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue); +#endif + +/* experimental */ +int32_t CDECL id3tag_set_fieldvalue_utf16(lame_t gfp, const unsigned short *fieldvalue); + +/* experimental */ +int32_t CDECL id3tag_set_textinfo_utf16(lame_t gfp, char const *id, unsigned short const *text); + +/* experimental */ +int32_t CDECL id3tag_set_comment_utf16(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text); + + +/*********************************************************************** +* +* list of valid bitrates [kbps] & sample frequencies [Hz]. +* first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) +* 1: MPEG-1 values (sample frequencies 32...48 kHz) +* 2: MPEG-2.5 values (sample frequencies 8...12 kHz) +***********************************************************************/ + +extern const int32_t bitrate_table [3][16]; +extern const int32_t samplerate_table [3][ 4]; + +/* access functions for use in DLL, global vars are not exported */ +int32_t CDECL lame_get_bitrate(int32_t mpeg_version, int32_t table_index); +int32_t CDECL lame_get_samplerate(int32_t mpeg_version, int32_t table_index); + + +/* maximum size of albumart image (128KB), which affects LAME_MAXMP3BUFFER + as well since lame_encode_buffer() also returns ID3v2 tag data */ +#define LAME_MAXALBUMART (128 * 1024) + +/* maximum size of mp3buffer needed if you encode at most 1152 samples for + each call to lame_encode_buffer. see lame_encode_buffer() below + (LAME_MAXMP3BUFFER is now obsolete) */ +#define LAME_MAXMP3BUFFER (16384 + LAME_MAXALBUMART) + + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82 + +} lame_errorcodes_t; + +#if defined(__cplusplus) +} +#endif +#endif /* LAME_LAME_H */ + diff --git a/libyangrtc2/src/yangplayer/YangPlayFactory.cpp b/libyangrtc2/src/yangplayer/YangPlayFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..774ae4a765dcc94bcb348d5705160eef1ab68653 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayFactory.cpp @@ -0,0 +1,33 @@ +/* + * YangPlayFactory.cpp + * + * Created on: 2020年9月4日 + * Author: yang + */ + +//#include +#include + +#include +YangPlayFactory::YangPlayFactory() { + // TODO Auto-generated constructor stub + +} + +YangPlayFactory::~YangPlayFactory() { + // TODO Auto-generated destructor stub +} + +YangAudioPlay* YangPlayFactory::createAudioPlay(YangAudioInfo *pcontext){ +#ifndef _WIN32 + return NULL;//if(pcontext->audioPlayType==1) return new YangAudioPlayAlsa(pcontext); +#endif + return NULL;// new YangAudioPlaySdl(pcontext); +} + +YangAudioPlay *YangPlayFactory::createAudioPlay(YangAudioPlayType paet,YangAudioInfo *pcontext){ +#ifndef _WIN32 + return NULL;//if(paet==Yang_AP_ALSA) return new YangAudioPlayAlsa(pcontext); +#endif + return NULL;//new YangAudioPlaySdl(pcontext); +} diff --git a/libyangrtc2/src/yangplayer/YangPlayReceive.cpp b/libyangrtc2/src/yangplayer/YangPlayReceive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0073a75fa98c984c7d864238143ddf9e11634ba7 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayReceive.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include + + +YangPlayReceive::YangPlayReceive(YangContext* pcontext) { + m_context=pcontext; + m_isStart = 0; + m_out_videoBuffer = NULL; + m_out_audioBuffer = NULL; + isReceived = 0; + isReceiveConvert = 0; + m_headLen = 1; //pcontext->audio.audioDecoderType == 0 ? 2 : 1; + m_recv = NULL; +} + +YangPlayReceive::~YangPlayReceive() { + disConnect(); + if (isReceiveConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + + if (m_recv) + delete m_recv; + m_recv = NULL; + + m_out_audioBuffer = NULL; + m_out_videoBuffer = NULL; + m_context=NULL; +} + +void YangPlayReceive::disConnect() { + if(m_recv) m_recv->disConnectServer(); + yang_delete(m_recv); + +} +void YangPlayReceive::setBuffer(YangAudioEncoderBuffer *al, + YangVideoDecoderBuffer *vl) { + m_out_audioBuffer = al; + m_out_videoBuffer = vl; +} +void YangPlayReceive::receiveAudio(YangFrame *audioFrame) { + audioFrame->payload += m_headLen; + audioFrame->nb -= m_headLen; + m_out_audioBuffer->putPlayAudio(audioFrame); +} +void YangPlayReceive::receiveVideo(YangFrame *videoFrame) { + if(videoFrame==NULL||videoFrame->payload==NULL) return; + uint8_t *temp = videoFrame->payload; + int videoLen=videoFrame->nb; + + if( (temp[0] == 0x27|| temp[0] == 0x2c)&&temp[1] == 0x01){ + videoFrame->payload = temp + 5; + videoFrame->nb -= 5; + videoFrame->frametype = YANG_Frametype_P; + if(yang_hasH264Pframe(videoFrame->payload)) m_out_videoBuffer->putEVideo(videoFrame); + return; + } + if ((temp[0] == 0x17 || temp[0] == 0x1c) ) { + if(temp[1] == 0x00){ + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + return; + } + if(temp[1] == 0x01){ + + YangH264NaluData nalu; + videoFrame->payload=temp+5; + videoFrame->nb=videoLen-5; + + yang_parseH264Nalu(videoFrame,&nalu); + + if(nalu.spsppsPos>-1){ + uint8_t meta[200] = { 0 }; + videoFrame->payload=meta; + yang_getH264SpsppseNalu(videoFrame,temp+5+nalu.spsppsPos); + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + } + if(nalu.keyframePos>-1){ + videoFrame->payload = temp + 5+nalu.keyframePos; + videoFrame->nb = videoLen-5-nalu.keyframePos; + videoFrame->frametype =YANG_Frametype_I; + m_out_videoBuffer->putEVideo(videoFrame); + + } + } + } +} + +int32_t YangPlayReceive::init(int32_t nettype, string server, int32_t pport, + string stream) { + //m_play= + YangStreamFactory sf; + if (!m_recv) + m_recv = sf.createStreamHandle(nettype, 0,m_context); + YangStreamConfig streamConf; + streamConf.app = "live"; + streamConf.streamOptType = Yang_Stream_Play; + streamConf.uid = 0; + + streamConf.localIp = "127.0.0.1"; + streamConf.localPort = 8100; + streamConf.serverIp = server; + streamConf.serverPort = pport; + streamConf.stream = stream; + m_recv->init(&streamConf); + m_recv->m_videoStream = 1; + m_recv->setReceiveCallback(this); + m_recv->m_uid = 0; + int32_t ret = m_recv->connectServer(); + if (ret) + return ret; + m_recv->m_streamInit = 1; + return ret; + +} +void YangPlayReceive::stop() { + isReceiveConvert = 0; +} +void YangPlayReceive::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangPlayReceive::startLoop() { + + yang_reindex(m_out_audioBuffer); + yang_reindex(m_out_videoBuffer); + + int32_t bufLen = 0; + int32_t retCode = Yang_Ok; + isReceiveConvert = 1; + isReceived = 1; + + while (isReceiveConvert == 1) { + if (!m_recv) { + yang_usleep(10000); + continue; + } + + if (!m_recv->m_streamInit) + continue; + bufLen = 0; + //tuid=m_players.at(i)->m_uid; + retCode = m_recv->receiveData(&bufLen); + + + //if (retCode) { + // yang_error("Receive Data Error:%d", retCode); + // break; + //} + if (bufLen == 0) + yang_usleep(2000); + } //end while + + isReceived = 0; +} diff --git a/libyangrtc2/src/yangplayer/YangPlayerBase.cpp b/libyangrtc2/src/yangplayer/YangPlayerBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f91b84c519188338aeaca824ed59abc68cc830a3 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayerBase.cpp @@ -0,0 +1,65 @@ +#include + +YangPlayerBase::YangPlayerBase() +{ + + m_ydb=NULL; + m_ypb=NULL; + +} + +YangPlayerBase::~YangPlayerBase() +{ + + yang_delete(m_ydb); + yang_delete(m_ypb); +} + +void YangPlayerBase::stopAll(){ + if(m_ydb) m_ydb->stopAll(); + if(m_ypb) m_ypb->stopAll(); +} + + +void YangPlayerBase::init(YangContext* pcontext){ + //YangAudioInfo* audio=&pcontext->audio; + if(m_ydb==NULL) { + m_ydb=new YangPlayerDecoder(pcontext); + //m_ydb->m_audio.sample=audio->sample; + //m_ydb->m_audio.channel=audio->channel; + //m_ydb->m_audio.usingMono=audio->usingMono; + //m_ydb->m_audio.audioDecoderType=audio->audioDecoderType; + m_ydb->initAudioDecoder(); + m_ydb->initVideoDecoder(); + } + + if(m_ypb==NULL) { + m_ypb=new YangPlayerPlay(); + m_ypb->initAudioPlay(pcontext); + //m_ypb->initVideoPlay(m_ydb->m_videoDec); + //m_ydb->m_videoDec->m_yvp=m_ypb-> + m_ypb->setInAudioList(m_ydb->getOutAudioBuffer()); + //m_ypb->setInVideoList(m_ydb->getOutVideoBuffer()); + } + +} + +void YangPlayerBase::startAudioDecoder(YangAudioEncoderBuffer *prr){ + m_ydb->setInAudioBuffer(prr); + m_ydb->startAudioDecoder(); +} +void YangPlayerBase::startVideoDecoder(YangVideoDecoderBuffer *prr){ + m_ydb->setInVideoBuffer(prr); + m_ydb->startVideoDecoder(); +} + +void YangPlayerBase::startAudioPlay(YangContext* paudio) { + //m_ydb->startDecoder(); + if(m_ypb){ + m_ypb->initAudioPlay(paudio); + m_ypb->startAudioPlay(); + } +} + + + diff --git a/libyangrtc2/src/yangplayer/YangPlayerDecoder.cpp b/libyangrtc2/src/yangplayer/YangPlayerDecoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c84d5ef6771ae3d0b8369e7dadf643f3c5195f0 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayerDecoder.cpp @@ -0,0 +1,117 @@ +/* + * YangDeocoderBase.cpp + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#include "pthread.h" +#include +#include +#include +#include "yangdecoder/YangDecoderFactory.h" + +YangPlayerDecoder::YangPlayerDecoder(YangContext* pcontext) { + m_context=pcontext; + m_out_audioBuffer=NULL; + m_out_videoBuffer=NULL; + m_audioDec=NULL; + m_videoDec=NULL; + /** + m_audio.audioCacheNum=50; + m_audio.audioDecoderType=0; + m_audio.usingMono=0; + m_audio.channel=2; + m_audio.sample=44100; + + m_video.bitDepth=8; + m_video.videoCacheNum=20; + m_video.evideoCacheNum=20; + m_video.videoDecoderType=0; + m_video.videoDecHwType=0;**/ +} + +YangPlayerDecoder::~YangPlayerDecoder() { + if(m_audioDec&&m_audioDec->m_isStart){ + m_audioDec->stop(); + while(m_audioDec->m_isStart){ + yang_usleep(1000); + } + } + if(m_videoDec&&m_videoDec->m_isStart){ + m_videoDec->stop(); + while(m_videoDec->m_isStart){ + yang_usleep(1000); + } + } + //yang_usleep(50000); + yang_delete(m_audioDec); + yang_delete(m_videoDec); + //int32_t i=0; + if(m_out_videoBuffer){ + delete m_out_videoBuffer;m_out_videoBuffer=NULL; + } + if(m_out_audioBuffer){ + delete m_out_audioBuffer;m_out_audioBuffer=NULL; + } + +} +void YangPlayerDecoder::stopAll(){ + if(m_audioDec) m_audioDec->stop(); + if(m_videoDec) m_videoDec->stop(); +} + + +void YangPlayerDecoder::initAudioDecoder(){ + if(m_out_audioBuffer==NULL) { + m_out_audioBuffer=new YangAudioPlayBuffer(); + + } + if(m_audioDec==NULL) { + // YangDecoderFactory df; + //YangAudioParam audio={0}; + + m_audioDec=new YangAudioDecoderHandle(m_context); + m_audioDec->init(); + m_audioDec->setOutAudioBuffer(m_out_audioBuffer); + } +} + +void YangPlayerDecoder::initVideoDecoder(){ + //YangConfig *p_config = m_context; + if(m_out_videoBuffer==NULL) { + m_out_videoBuffer=new YangVideoBuffer(1); + //m_out_videoBuffer->m_syn=&m_syn; + } + //m_context->videoBuffers=m_out_videoBuffer; +// YangDecoderFactory df; + if(m_videoDec==NULL) { + + m_videoDec=new YangVideoDecoderHandle(m_context); + m_videoDec->init(); + m_videoDec->setOutVideoBuffer(m_out_videoBuffer); + } + +} + +void YangPlayerDecoder::startAudioDecoder(){ + if(m_audioDec&&!m_audioDec->m_isStart) if(m_audioDec) m_audioDec->start(); +} + +void YangPlayerDecoder::startVideoDecoder(){ + if(m_videoDec&&!m_videoDec->m_isStart) m_videoDec->start(); +} + +void YangPlayerDecoder::setInVideoBuffer(YangVideoDecoderBuffer *pvel){ + if(m_videoDec!=NULL) m_videoDec->setInVideoBuffer(pvel); +} +void YangPlayerDecoder::setInAudioBuffer(YangAudioEncoderBuffer *pael){ + if(m_audioDec!=NULL) m_audioDec->setInAudioBuffer(pael); +} +YangVideoBuffer* YangPlayerDecoder::getOutVideoBuffer(){ + return m_out_videoBuffer; +} +YangAudioPlayBuffer* YangPlayerDecoder::getOutAudioBuffer(){ + return m_out_audioBuffer; +} + diff --git a/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.cpp b/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2de8c067c9126c5b98bb749cf780aca8fc92849b --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.cpp @@ -0,0 +1,148 @@ +#include "YangPlayerHandleImpl.h" +#include +#include +#include +#include +#include + + +YangPlayerHandle* YangPlayerHandle::createPlayerHandle(YangContext* pcontext,YangSysMessageI* pmessage){ + return new YangPlayerHandleImpl(pcontext,pmessage); +} +YangPlayerHandleImpl::YangPlayerHandleImpl(YangContext* pcontext,YangSysMessageI* pmessage) { + m_context=pcontext; + m_message=pmessage; + m_recv = NULL; + m_play = NULL; + m_rtcRecv=NULL; + m_outVideoBuffer = NULL; + m_outAudioBuffer = NULL; + m_url.netType=0; + m_url.port=1935; +} + +YangPlayerHandleImpl::~YangPlayerHandleImpl() { + if(m_rtcRecv) m_rtcRecv->disConnect(); + yang_delete(m_recv); + yang_delete(m_play); + yang_delete(m_rtcRecv); + yang_delete(m_outVideoBuffer); + yang_delete(m_outAudioBuffer); + +} + +void YangPlayerHandleImpl::stopPlay(){ + if(m_rtcRecv) { + m_rtcRecv->disConnect(); + } + if(m_recv){ + m_recv->disConnect(); + } + if(m_play) m_play->stopAll(); + yang_stop(m_rtcRecv); + yang_stop_thread(m_rtcRecv); + yang_delete(m_rtcRecv); + + //yang_delete(m_play); + yang_stop(m_recv); + yang_stop_thread(m_recv); + yang_delete(m_recv); + + yang_delete(m_play); + +} +int YangPlayerHandleImpl::play(string url,int32_t localPort) { + m_url.app=""; + m_url.server=""; + m_url.stream=""; + m_url.port=0; + if(yang_srs_url_parse((char*)url.c_str(),&m_url)) return 1; + + stopPlay(); + printf("\nnetType==%d,server=%s,port=%d,app=%s,stream=%s\n",m_url.netType,m_url.server.c_str(),m_url.port,m_url.app.c_str(),m_url.stream.c_str()); + m_context->sys.transType=m_url.netType; + if(m_context->streams.m_playBuffer) m_context->streams.m_playBuffer->setTranstype(m_url.netType); + if(m_url.netType ==Yang_Webrtc){ + + return playRtc(0,m_url.server,localPort,m_url.server,1985,m_url.app,m_url.stream); + + } + return 1; + /** + if (!m_play) { + m_play = new YangPlayerBase(); + + m_context->audio.sample=44100; + m_context->audio.channel=2; + m_context->audio.audioDecoderType=0; + m_context->audio.usingMono=0; + m_context->audio.aIndex=-1; + m_play->init(m_context); + } + initList(); + m_play->startAudioDecoder(m_outAudioBuffer); + m_play->startVideoDecoder(m_outVideoBuffer); + m_play->startAudioPlay(m_context); + //m_play->startVideoPlay(); + + + if (!m_recv) { + + m_recv = new YangPlayReceive(m_context); //sf.createStreamBase(m_url.netType,0,m_context); + m_recv->setBuffer(m_outAudioBuffer, m_outVideoBuffer); + } + if(m_recv->init(m_url.netType, m_url.server, m_url.port, m_url.stream)){ + printf("\n connect server failure!"); + return 1; + } + + m_recv->start(); + return Yang_Ok; + **/ + +} + +int32_t YangPlayerHandleImpl::playRtc(int32_t puid,std::string localIp,int32_t localPort, std::string server, int32_t pport,std::string app,std::string stream){ + + stopPlay(); + if (!m_play) { + m_play = new YangPlayerBase(); + + m_context->audio.sample=48000; + m_context->audio.channel=2; + m_context->audio.audioDecoderType=3; + m_context->audio.usingMono=0; + m_context->audio.aIndex=-1; + m_play->init(m_context); + } + initList(); + m_play->startAudioDecoder(m_outAudioBuffer); + m_play->startVideoDecoder(m_outVideoBuffer); + + m_play->startAudioPlay(m_context); + + + if(m_rtcRecv==NULL) { + m_rtcRecv=new YangRtcReceive(m_context,m_message); + m_rtcRecv->setBuffer(m_outAudioBuffer, m_outVideoBuffer); + m_rtcRecv->init(puid,localIp,localPort,server,pport,app,stream); + } + + m_rtcRecv->start(); + + return Yang_Ok; +} + +YangVideoBuffer* YangPlayerHandleImpl::getVideoBuffer(){ + if(m_play) return m_play->m_ydb->getOutVideoBuffer(); + return NULL; +} + +void YangPlayerHandleImpl::initList() { + if (m_outAudioBuffer == NULL) { + m_outAudioBuffer = new YangAudioEncoderBuffer(10); + } + if (m_outVideoBuffer == NULL) + m_outVideoBuffer = new YangVideoDecoderBuffer(); + +} diff --git a/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.h b/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..e498a93e959ac2b10fc56b1331f071111f4d7ac2 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayerHandleImpl.h @@ -0,0 +1,37 @@ + +#ifndef YANGMEETING_INCLUDE_YANGPLAYERHANDLE_H_ +#define YANGMEETING_INCLUDE_YANGPLAYERHANDLE_H_ +#include +#include +#include +#include +#include +#include +#include "YangRtcReceive.h" + + +class YangPlayerHandleImpl :public YangPlayerHandle{ +public: + YangPlayerHandleImpl(YangContext* pcontext,YangSysMessageI* pmessage); + virtual ~YangPlayerHandleImpl(); + YangVideoBuffer* getVideoBuffer(); + int play(string url,int32_t localport); + + int32_t playRtc(int32_t puid,std::string localIp,int32_t localPort, std::string server, int32_t pport,std::string app,std::string stream); + void stopPlay(); +protected: + + YangUrlData m_url; + void initList(); + YangPlayReceive *m_recv; + YangPlayerBase *m_play; + YangRtcReceive *m_rtcRecv; + +private: + YangContext* m_context; + YangVideoDecoderBuffer* m_outVideoBuffer; + YangAudioEncoderBuffer* m_outAudioBuffer; + YangSysMessageI* m_message; +}; + +#endif /* YANGMEETING_INCLUDE_YANGPLAYERHANDLE_H_ */ diff --git a/libyangrtc2/src/yangplayer/YangPlayerPlay.cpp b/libyangrtc2/src/yangplayer/YangPlayerPlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..495311e87eda32d6c68edf60bc78331ae61d463d --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangPlayerPlay.cpp @@ -0,0 +1,79 @@ +/* + * YangPlayBase.cpp + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#include +#include + + + +YangPlayerPlay::YangPlayerPlay() { + m_audioPlay=NULL; + vm_audio_player_start=0; +} + +YangPlayerPlay::~YangPlayerPlay() { + //m_context=NULL; + yang_stop(m_audioPlay); + yang_stop_thread(m_audioPlay); + +} +void YangPlayerPlay::stopAll(){ + if(m_audioPlay) m_audioPlay->stop(); + +} +void YangPlayerPlay::initAudioPlay(YangContext* paudio){ + + if (m_audioPlay == NULL) { +#ifdef _WIN32 + m_audioPlay = new YangWinAudioApiRender(paudio); +#else + m_audioPlay = new YangAudioPlayAlsa(paudio); +#endif + m_audioPlay->init(); + + } + +} +/** +void YangPlayerPlay::initVideoPlay(YangVideoDecoderHandle *handle){ + if (vm_videoPlay == NULL) { + vm_videoPlay = new YangVideoPlay(); + vm_videoPlay->init(); + //handle->m_yvp=vm_videoPlay; + } + +} + +void YangPlayerPlay::setInVideoList(vector *pvideoList){ + if(vm_videoPlay!=NULL) vm_videoPlay->setVideoList(pvideoList);//setAudioList(paudioList); +} +void YangPlayerPlay::startVideoPlay(){ + //if(vm_audio_player_start) return; + vm_videoPlay->start(); + //vm_audio_player_start=1; +} +int32_t YangPlayerPlay::getIsAecInit(){ + if(vm_audioPlay!=NULL) return vm_audioPlay->m_aecInit; + return 0; +} +//F_initSdlWin YangPlayApp::getInitSdlWin(){ +// return vm_contexttSdlWin; +//} + +void YangPlayerPlay::setAec(YangAecBase *paec){ + if(vm_audioPlay!=NULL) vm_audioPlay->setAecBase(paec); +} +**/ +void YangPlayerPlay::startAudioPlay(){ + if(vm_audio_player_start) return; + m_audioPlay->start(); + vm_audio_player_start=1; +} +void YangPlayerPlay::setInAudioList(YangAudioPlayBuffer *paudioList){ + if(m_audioPlay!=NULL) m_audioPlay->setAudioBuffer(paudioList); +} + diff --git a/libyangrtc2/src/yangplayer/YangRtcReceive.cpp b/libyangrtc2/src/yangplayer/YangRtcReceive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4213e98c9d65ba3a4856c04923c8c0a858a11431 --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangRtcReceive.cpp @@ -0,0 +1,204 @@ +#include "YangRtcReceive.h" + +#include +#include + +YangRtcReceive::YangRtcReceive(YangContext* pcontext,YangSysMessageI* pmessage) { + m_message=pmessage; + m_context=pcontext; + m_isStart = 0; + m_out_videoBuffer = NULL; + m_out_audioBuffer = NULL; + m_isReceived = 0; + m_loops = 0; + m_headLen = 1; //pcontext->audio.audioDecoderType == 0 ? 2 : 1; + m_recv = NULL; + m_waitState = 0; + pthread_mutex_init(&m_lock,NULL); + pthread_cond_init(&m_cond_mess,NULL); +// m_lock = PTHREAD_MUTEX_INITIALIZER; +// m_cond_mess = PTHREAD_COND_INITIALIZER; + +} + +YangRtcReceive::~YangRtcReceive() { + disConnect(); + if (m_loops) { + while (m_isStart) { + yang_usleep(1000); + } + } + yang_delete(m_recv); + + + m_out_audioBuffer = NULL; + m_out_videoBuffer = NULL; + m_message=NULL; + pthread_mutex_destroy(&m_lock); + pthread_cond_destroy(&m_cond_mess); +} + +void YangRtcReceive::disConnect() { + if (m_recv) + m_recv->disconnectServer(); + stop(); + + yang_delete(m_recv); +} +void YangRtcReceive::setBuffer(YangAudioEncoderBuffer *al, + YangVideoDecoderBuffer *vl) { + m_out_audioBuffer = al; + m_out_videoBuffer = vl; +} +void YangRtcReceive::setMediaConfig(int32_t puid, YangAudioParam *audio,YangVideoParam *video){ + +} +void YangRtcReceive::receiveAudio(YangFrame *audioFrame) { + if(audioFrame==NULL||!audioFrame->payload) return; + m_out_audioBuffer->putPlayAudio(audioFrame); +} +void YangRtcReceive::receiveVideo(YangFrame *videoFrame) { + if(videoFrame==NULL||videoFrame->payload==NULL) return; + uint8_t *temp = videoFrame->payload; + int videoLen=videoFrame->nb; + + if(temp[0] == 0x27&&temp[1] == 0x01){ + videoFrame->payload = temp + 5; + videoFrame->nb -= 5; + videoFrame->frametype = YANG_Frametype_P; + if(yang_hasH264Pframe(videoFrame->payload)) m_out_videoBuffer->putEVideo(videoFrame); + return; + } + + if (temp[0] == 0x17) { + if(temp[1] == 0x00){ + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + return; + } + if(temp[1] == 0x01){ + videoFrame->payload=temp+5; + videoFrame->nb=videoLen-5; + + yang_parseH264Nalu(videoFrame,&m_nalu); + + if(m_nalu.spsppsPos>-1){ + uint8_t meta[200] = { 0 }; + videoFrame->payload=meta; + yang_getH264SpsppseNalu(videoFrame,temp+5+m_nalu.spsppsPos); + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + } + if(m_nalu.keyframePos>-1){ + videoFrame->payload = temp + 5+m_nalu.keyframePos; + videoFrame->nb = videoLen-5-m_nalu.keyframePos; + videoFrame->frametype =YANG_Frametype_I; + m_out_videoBuffer->putEVideo(videoFrame); + + } + } + } + + if( temp[0] == 0x2c&&temp[1] == 0x01){ + videoFrame->payload = temp + 5; + videoFrame->nb -= 5; + videoFrame->frametype = YANG_Frametype_P; + m_out_videoBuffer->putEVideo(videoFrame); + return; + } + if ( temp[0] == 0x1c ) { + if(temp[1] == 0x00){ + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + return; + } + if(temp[1] == 0x01){ + videoFrame->payload=temp+5; + videoFrame->nb=videoLen-5; + + yang_parseH265Nalu(videoFrame,&m_nalu); + + if(m_nalu.spsppsPos>-1){ + uint8_t meta[200] = { 0 }; + videoFrame->payload=meta; + yang_getH265SpsppseNalu(videoFrame,temp+5+m_nalu.spsppsPos); + videoFrame->frametype = YANG_Frametype_Spspps; + m_out_videoBuffer->putEVideo(videoFrame); + } + if(m_nalu.keyframePos>-1){ + videoFrame->payload = temp + 5+m_nalu.keyframePos; + videoFrame->nb = videoLen-5-m_nalu.keyframePos; + videoFrame->frametype =YANG_Frametype_I; + m_out_videoBuffer->putEVideo(videoFrame); + + } + } + } + +} + +int32_t YangRtcReceive::init(int32_t puid, string localIp, int32_t localPort, + string server, int32_t pport, string app, string stream) { + m_conf.localIp = localIp; + m_conf.localPort = localPort; + m_conf.serverIp = server; + m_conf.serverPort = pport; + m_conf.app = app; + m_conf.stream = stream; + m_conf.uid = puid; + m_conf.streamOptType = Yang_Stream_Play; + if (!m_recv) + m_recv = YangRtcHandle::createRtcHandle(m_context); + m_recv->setReceiveCallback(this); + + //m_recv->setMediaParam(NULL, NULL, &m_rtcinfo); + + m_recv->init(&m_conf); + return Yang_Ok; + +} +void YangRtcReceive::stop() { + m_loops = 0; + if (m_recv) + m_recv->disconnectServer(); + //pthread_mutex_unlock(&m_lock); + + if (m_waitState) { + pthread_mutex_lock(&m_lock); + pthread_cond_signal(&m_cond_mess); + pthread_mutex_unlock(&m_lock); + + } +} +void YangRtcReceive::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangRtcReceive::startLoop() { + + yang_reindex(m_out_audioBuffer); + yang_reindex(m_out_videoBuffer); + m_loops = 1; + m_isReceived = 1; + int err=Yang_Ok; + if ((err=m_recv->connectRtcServer())!=Yang_Ok) { + m_loops=0; + if(m_message) m_message->failure(err); + }else{ + if(m_message) m_message->success(); + } + + pthread_mutex_lock(&m_lock); + while (m_loops == 1) { + m_waitState = 1; + + pthread_cond_wait(&m_cond_mess, &m_lock); + m_waitState = 0; + } //end while + + if (m_recv) + m_recv->disconnectServer(); + m_isReceived = 0; + pthread_mutex_unlock(&m_lock); +} diff --git a/libyangrtc2/src/yangplayer/YangRtcReceive.h b/libyangrtc2/src/yangplayer/YangRtcReceive.h new file mode 100644 index 0000000000000000000000000000000000000000..28c7d35ae8136ee50552564fa09ece3f8a34a36a --- /dev/null +++ b/libyangrtc2/src/yangplayer/YangRtcReceive.h @@ -0,0 +1,54 @@ +#ifndef SRC_YANGPLAYER_SRC_YANGRTCRECEIVE_H_ +#define SRC_YANGPLAYER_SRC_YANGRTCRECEIVE_H_ +#include +#include +#include +#include +#include +#include +#include +#include + + + +using namespace std; +class YangRtcReceive : public YangThread, public YangReceiveCallback,public YangMediaConfigCallback{ +public: + YangRtcReceive(YangContext* pcontext,YangSysMessageI* pmessage); + virtual ~YangRtcReceive(); + void receiveAudio(YangFrame* audioFrame); + void receiveVideo(YangFrame* videoFrame); + //void handleKeyframe(YangFrame* videoFrame); + int32_t init(int32_t puid,string localIp,int32_t localPort, string server, int32_t pport,string app, string stream); + void setBuffer(YangAudioEncoderBuffer *al,YangVideoDecoderBuffer *vl); + void disConnect(); + void play(char* pserverStr,char *streamName); + void setMediaConfig(int32_t puid, YangAudioParam *audio,YangVideoParam *video); + YangRtcHandle *m_recv; + int32_t m_isReceived; //,isHandled; + int32_t m_loops; //,isHandleAllInvoke; + int32_t m_isStart; + void stop(); +protected: + void run(); + void startLoop(); + YangContext* m_context; + YangSysMessageI* m_message; + + + +private: + pthread_mutex_t m_lock; + pthread_cond_t m_cond_mess; + YangStreamConfig m_conf; + int32_t m_waitState; + int32_t m_headLen; + YangAudioEncoderBuffer *m_out_audioBuffer; + YangVideoDecoderBuffer *m_out_videoBuffer; + YangRtcInfo m_rtcinfo; + YangH264NaluData m_nalu; + + //uint8_t* m_keyBuf; +}; + +#endif /* SRC_YANGPLAYER_SRC_YANGRTCRECEIVE_H_ */ diff --git a/libyangrtc2/src/yangpush/YangPushCapture.cpp b/libyangrtc2/src/yangpush/YangPushCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..200f7e3c488e121104540f8216e667278dbb89b5 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushCapture.cpp @@ -0,0 +1,328 @@ +#include +#include +#include +#include +//#include +//#include +#include + + +YangPushCapture::YangPushCapture(YangContext *pcontext) { + m_context=pcontext; + + m_out_audioBuffer = NULL; + m_screenCapture=NULL; + m_videoCapture=NULL; + m_audioCapture=NULL; + + + m_out_videoBuffer=NULL; + m_screen_pre_videoBuffer=NULL; + m_screen_out_videoBuffer=NULL; + m_pre_videoBuffer=new YangVideoBuffer(pcontext->video.bitDepth==8?1:2); + m_pre_videoBuffer->isPreview=1; + m_pre_videoBuffer->m_frames=pcontext->video.frame; + m_isConvert=0; + m_isStart=0; +#if Yang_HaveVr + m_out_vr_pre_videoBuffer=NULL; +#endif +} + +YangPushCapture::~YangPushCapture() { + m_context=NULL; + stopAll(); + yang_stop_thread(this); + yang_stop_thread(m_audioCapture); + yang_stop_thread(m_videoCapture); + yang_stop_thread(m_screenCapture); + + + yang_delete(m_audioCapture); + yang_delete(m_videoCapture); + yang_delete(m_screenCapture); + + yang_delete(m_out_audioBuffer); + yang_delete(m_pre_videoBuffer); + yang_delete(m_out_videoBuffer); +#if Yang_HaveVr + yang_delete(m_out_vr_pre_videoBuffer); +#endif + m_screen_pre_videoBuffer=NULL; + m_screen_out_videoBuffer=NULL; + //yang_delete(m_screen_pre_videoBuffer); + +} + + +void YangPushCapture::startAudioCaptureState() { + if(m_audioCapture) m_audioCapture->setCatureStart(); +} +void YangPushCapture::stopAudioCaptureState() { + if(m_audioCapture) m_audioCapture->setCatureStop(); +} +void YangPushCapture::setAec(YangAecBase *paec) { + if (m_audioCapture) { + m_audioCapture->setAec(paec); + } +} +void YangPushCapture::setInAudioBuffer(vector *pbuf){ + if(m_audioCapture!=NULL) m_audioCapture->setInAudioBuffer(pbuf); +} +void YangPushCapture::startAudioCapture() { + if (m_audioCapture && !m_audioCapture->m_isStart) + m_audioCapture->start(); +} +YangAudioBuffer* YangPushCapture::getOutAudioBuffer() { + return m_out_audioBuffer; +} +int32_t YangPushCapture::initAudio(YangPreProcess *pp) { + if (m_out_audioBuffer == NULL) { + if (m_context->audio.usingMono) + m_out_audioBuffer = new YangAudioBuffer(m_context->audio.audioCacheNum); + else + m_out_audioBuffer = new YangAudioBuffer(m_context->audio.audioCacheNum); + } + if (m_audioCapture == NULL) { + YangCaptureFactory m_capture; + m_audioCapture = m_capture.createRecordAudioCapture(m_context); //new YangAudioCapture(m_context); + int32_t ret=m_audioCapture->init(); + if(ret){ + if(ret==ERROR_SYS_NoAudioDevice||ret==ERROR_SYS_NoAudioCaptureDevice) { + yang_error("ERROR_SYS_NoAudioDevice"); + return ret; + } + + } + m_audioCapture->setPreProcess(pp); + m_audioCapture->setOutAudioBuffer(m_out_audioBuffer); + + m_audioCapture->setCatureStop(); + } + stopAudioCaptureState(); + return Yang_Ok; +} + + + + +void YangPushCapture::stopAll(){ + stop(); + yang_stop(m_audioCapture); + yang_stop(m_videoCapture); + yang_stop(m_screenCapture); + +} + + +void YangPushCapture::startVideoCaptureState() { + m_videoCapture->initstamp(); + m_videoCapture->setVideoCaptureStart(); +} + +void YangPushCapture::startScreenCaptureState() { + + m_screenCapture->setVideoCaptureStart(); +} + +void YangPushCapture::stopVideoCaptureState() { + if(m_videoCapture) m_videoCapture->setVideoCaptureStop(); + +} +void YangPushCapture::stopScreenCaptureState(){ + if(m_screenCapture) m_screenCapture->setVideoCaptureStop(); +} +void YangPushCapture::change(int32_t st) { + +} + + +int32_t YangPushCapture::initVideo(){ + if(m_out_videoBuffer==NULL) m_out_videoBuffer = new YangVideoBuffer(m_context->video.bitDepth==8?1:2); + int32_t err=Yang_Ok; + if (m_videoCapture == NULL) { + YangCaptureFactory cf; + + m_videoCapture = cf.createRecordVideoCapture(&m_context->video);//new YangVideoCapture(m_context); + if((err=m_videoCapture->init())!=Yang_Ok){ + return yang_error_wrap(err,"video capture init fail!"); + } + + m_out_videoBuffer->init(m_context->video.width,m_context->video.height,m_context->video.videoEncoderFormat); + m_pre_videoBuffer->init(m_context->video.width,m_context->video.height,m_context->video.videoEncoderFormat); + m_videoCapture->setOutVideoBuffer(m_out_videoBuffer); + m_videoCapture->setPreVideoBuffer(m_pre_videoBuffer); + //m_videoCapture->setVideoCaptureStart(); + } + stopVideoCaptureState(); + return err; + +} + +int32_t YangPushCapture::initScreen(){ + int32_t err=Yang_Ok; + if (m_screenCapture == NULL) { + YangCaptureFactory cf; + + m_screenCapture = cf.createScreenCapture(m_context);//new YangVideoCapture(m_context); + + if((err=m_screenCapture->init())!=Yang_Ok){ + return yang_error_wrap(err,"screen capture fail...."); + } + + m_screen_out_videoBuffer=m_screenCapture->getOutVideoBuffer(); + m_screen_pre_videoBuffer=m_screenCapture->getPreVideoBuffer(); + + //m_screenCapture->setVideoCaptureStart(); + } + stopVideoCaptureState(); + return err; +} + +void YangPushCapture::startVideoCapture(){ + if(m_videoCapture&&!m_videoCapture->m_isStart) m_videoCapture->start(); +} +void YangPushCapture::startScreenCapture(){ + if(m_screenCapture&&!m_screenCapture->m_isStart) m_screenCapture->start(); +} +YangVideoBuffer * YangPushCapture::getOutVideoBuffer(){ + + return m_out_videoBuffer; +} + +YangVideoBuffer * YangPushCapture::getPreVideoBuffer(){ + + return m_pre_videoBuffer; +} +void YangPushCapture::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangPushCapture::stop() { + stopLoop(); +} +void YangPushCapture::stopLoop() { + m_isConvert = 0; +} +#if Yang_HaveVr +#include +void YangPushCapture::startLoop() { + + m_isConvert = 1; + int32_t inWidth = m_context->video.width; + int32_t inHeight = m_context->video.height; + int64_t prestamp = 0; + long az = inWidth * inHeight * 2; + uint8_t *srcData=new uint8_t[az];// { 0 }; + //if (is12bits) + az = inWidth * inHeight * 3 / 2; + + //mf.getYangMatImage(); + + uint8_t *matDst=new uint8_t[inWidth * inHeight * 2]; + uint8_t *matSrcRgb=new uint8_t [inWidth * inHeight * 3]; + uint8_t *matSrcBgr=new uint8_t [inWidth * inHeight * 3]; + YangYuvConvert yuv; + + + YangMatImageCv *mat = new YangMatImageCv(); + mat->initImg(m_context->bgFilename, m_context->video.width, m_context->video.height, 3); + yang_trace("bgfilename===%s",m_context->bgFilename); + YangFrame videoFrame; + memset(&videoFrame,0,sizeof(YangFrame)); + while (m_isConvert == 1) { + + if (m_out_vr_pre_videoBuffer->size() == 0) { + yang_usleep(1000); + continue; + } + videoFrame.payload=srcData; + videoFrame.nb=az; + m_out_vr_pre_videoBuffer->getVideo(&videoFrame); + yuv.I420torgb24(srcData, matSrcRgb, inWidth, inHeight); + yang_rgbtobgr(matSrcRgb, matSrcBgr, inWidth, inHeight); + mat->matImage(matSrcBgr, matDst); + + if (videoFrame.timestamp - prestamp <= 0) { + prestamp = videoFrame.timestamp; + continue; + } + prestamp = videoFrame.timestamp; + videoFrame.payload=matDst; + videoFrame.nb=az; + if (m_videoCapture->getVideoCaptureState()) + m_out_videoBuffer->putVideo(&videoFrame); + m_pre_videoBuffer->putVideo(&videoFrame); + + } + + yang_delete(mat); + yang_deleteA(srcData); + yang_deleteA(matDst); + yang_deleteA(matSrcRgb); + yang_deleteA(matSrcBgr); + + +} +void YangPushCapture::addVr(){ + if (m_out_vr_pre_videoBuffer == NULL) + m_out_vr_pre_videoBuffer = new YangVideoBuffer(m_context->video.width, + m_context->video.height, 12, m_context->video.bitDepth == 8 ? 1 : 2); + + m_out_vr_pre_videoBuffer->resetIndex(); + + m_pre_videoBuffer->resetIndex(); + m_out_videoBuffer->resetIndex(); + m_videoCapture->setPreVideoBuffer(m_out_vr_pre_videoBuffer); + m_videoCapture->setOutVideoBuffer(NULL);//(m_out_vr_pre_videoBuffer); + start(); +} +void YangPushCapture::delVr(){ + stop(); + while(m_isStart){ + yang_usleep(1000); + } + m_pre_videoBuffer->resetIndex(); + m_out_videoBuffer->resetIndex(); + m_videoCapture->setOutVideoBuffer(m_out_videoBuffer); + m_videoCapture->setPreVideoBuffer(m_pre_videoBuffer); +} +#endif +YangVideoBuffer* YangPushCapture::getScreenOutVideoBuffer() { + return m_screen_out_videoBuffer; +} + +YangVideoBuffer* YangPushCapture::getScreenPreVideoBuffer() { + return m_screen_pre_videoBuffer; +} + +void YangPushCapture::startCamera() { + initVideo(); + startVideoCapture(); +} + +void YangPushCapture::startScreen() { + initScreen(); + startScreenCapture(); +} + +void YangPushCapture::stopCamera() { + yang_stop(m_videoCapture); + yang_stop_thread(m_videoCapture); + yang_delete(m_videoCapture); +} + +void YangPushCapture::stopScreen() { + yang_stop(m_screenCapture); + yang_stop_thread(m_screenCapture); + yang_delete(m_screenCapture); +} + +void YangPushCapture::setScreenInterval(int32_t pinterval) { + if(m_screenCapture) m_screenCapture->setInterval(pinterval); +} + +void YangPushCapture::setDrawmouse(bool isDraw) { + if(m_screenCapture) m_screenCapture->setDrawmouse(isDraw); +} diff --git a/libyangrtc2/src/yangpush/YangPushEncoder.cpp b/libyangrtc2/src/yangpush/YangPushEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab8789254333e24f34bac52b49df55d621f50cbf --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushEncoder.cpp @@ -0,0 +1,110 @@ +#include "pthread.h" +#include +#include +#include +#include "yangencoder/YangEncoderFactory.h" + +YangPushEncoder::YangPushEncoder(YangContext *pcontext) { + m_ae=NULL; + m_ve=NULL; + m_out_videoBuffer = NULL; + m_out_auidoBuffer = NULL; + + m_context = pcontext; + m_videoInfo=&pcontext->video; + m_vmd = NULL; +} + +YangPushEncoder::~YangPushEncoder() { + stopAll(); + yang_stop_thread(m_ae); + yang_stop_thread(m_ve); + + yang_delete(m_ae); + yang_delete(m_ve); + + yang_delete(m_out_videoBuffer); //=NULL; + yang_delete(m_out_auidoBuffer); //=NULL; + + yang_free(m_vmd); + m_context = NULL; +} +void YangPushEncoder::stopAll() { + yang_stop(m_ae); + yang_stop(m_ve); + +} + +void YangPushEncoder::deleteVideoEncoder(){ + yang_stop(m_ve); + yang_stop_thread(m_ve); + yang_delete(m_ve); + yang_free(m_vmd); + m_vmd=NULL; +} +YangVideoMeta* YangPushEncoder::getOutVideoMetaData() { + return m_vmd; +} +void YangPushEncoder::setVideoInfo(YangVideoInfo* pvideo){ + if(pvideo) m_videoInfo=pvideo; +} +void YangPushEncoder::initAudioEncoder() { + if (m_out_auidoBuffer == NULL) + m_out_auidoBuffer = new YangAudioEncoderBuffer(m_context->audio.audioCacheNum); + if (m_ae == NULL) { + // YangEncoderFactory yf; + m_ae = new YangAudioEncoderHandle(&m_context->audio); + m_ae->setOutAudioBuffer(m_out_auidoBuffer); + m_ae->init(); + } + +} +void YangPushEncoder::initVideoEncoder() { + if (m_out_videoBuffer == NULL) + m_out_videoBuffer = new YangVideoEncoderBuffer(m_context->video.evideoCacheNum); + if(m_context&&m_context->enc.createMeta){ + if (m_vmd == NULL) + m_vmd = (YangVideoMeta*) calloc(1, sizeof(YangVideoMeta)); + YangEncoderFactory fac; + YangVideoEncoderMeta *yvh = fac.createVideoEncoderMeta(m_videoInfo); + yvh->yang_initVmd(m_vmd, m_videoInfo,&m_context->enc); + yang_delete(yvh); + } + if (m_ve == NULL) { + // YangEncoderFactory yf; + m_ve = new YangVideoEncoderHandle(m_videoInfo, &m_context->enc); + m_ve->setOutVideoBuffer(m_out_videoBuffer); + m_ve->init(); + m_ve->setVideoMetaData(m_vmd); + } +} +void YangPushEncoder::sendKeyframe(){ + if(m_ve) m_ve->sendKeyframe(); +} +void YangPushEncoder::startAudioEncoder() { + if (m_ae && !m_ae->m_isStart) { + m_ae->start(); + yang_usleep(1000); + } +} +void YangPushEncoder::startVideoEncoder() { + if (m_ve && !m_ve->m_isStart) { + m_ve->start(); + yang_usleep(2000); + } +} +void YangPushEncoder::setInAudioBuffer(YangAudioBuffer *pbuf) { + if (m_ae != NULL) + m_ae->setInAudioBuffer(pbuf); +} +void YangPushEncoder::setInVideoBuffer(YangVideoBuffer *pbuf) { + if (m_ve != NULL) + m_ve->setInVideoBuffer(pbuf); +} +YangAudioEncoderBuffer* YangPushEncoder::getOutAudioBuffer() { + return m_out_auidoBuffer; +} +YangVideoEncoderBuffer* YangPushEncoder::getOutVideoBuffer() { + return m_out_videoBuffer; +} + diff --git a/libyangrtc2/src/yangpush/YangPushEncoder.h b/libyangrtc2/src/yangpush/YangPushEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..e321bda1fb7374d1134523804e6d853c094c26f9 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushEncoder.h @@ -0,0 +1,43 @@ +#ifndef YANGAPP_YangPushEncoder_H_ +#define YANGAPP_YangPushEncoder_H_ + +#include "yangencoder/YangAudioEncoderHandle.h" +#include "yangencoder/YangVideoEncoderHandle.h" +#include "yangutil/buffer/YangAudioBuffer.h" +#include "yangutil/buffer/YangAudioEncoderBuffer.h" +#include "yangutil/buffer/YangVideoBuffer.h" +#include "yangutil/buffer/YangVideoEncoderBuffer.h" +#include "yangutil/sys/YangIni.h" +class YangPushEncoder { +public: + YangPushEncoder(YangContext *pcontext); + virtual ~YangPushEncoder(); +public: + void setVideoInfo(YangVideoInfo* pvideo); + void initVideoEncoder(); + void initAudioEncoder(); + void startAudioEncoder(); + void startVideoEncoder(); + void setInAudioBuffer(YangAudioBuffer *pal); + void setInVideoBuffer(YangVideoBuffer *pvl); + YangAudioEncoderBuffer * getOutAudioBuffer(); + YangVideoEncoderBuffer * getOutVideoBuffer(); + YangVideoMeta * getOutVideoMetaData(); + void stopAll(); + void sendKeyframe(); + + void deleteVideoEncoder(); +private: + + YangVideoEncoderHandle *m_ve; + YangAudioEncoderHandle *m_ae; + + YangAudioEncoderBuffer *m_out_auidoBuffer; + YangVideoEncoderBuffer *m_out_videoBuffer; + + YangContext *m_context; + YangVideoMeta *m_vmd; + YangVideoInfo* m_videoInfo; +}; + +#endif /* YANGAPP_YANGENCODERAPP_H_ */ diff --git a/libyangrtc2/src/yangpush/YangPushFactory.cpp b/libyangrtc2/src/yangpush/YangPushFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4de1d15abdd0da6f8f764ac388e8282a575c5c2a --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushFactory.cpp @@ -0,0 +1,37 @@ + +#include +#include "YangPushMessageHandle.h" +YangPushFactory::YangPushFactory() { + + +} + +YangPushFactory::~YangPushFactory() { + +} + +YangPushHandle* YangPushFactory::createPushHandle(bool hasAudio,bool initVideo,int pvideotype, YangVideoInfo *screenvideo, YangVideoInfo *outvideo, YangContext *pcontext, + YangSysMessageI *pmessage) { + return new YangPushHandleImpl(hasAudio,initVideo,pvideotype,screenvideo,outvideo,pcontext, pmessage); +} + +YangSysMessageHandle* YangPushFactory::createPushMessageHandle(bool hasAudio,bool initVideo, + int pvideotype, YangVideoInfo *screenvideo, YangVideoInfo *outvideo, YangContext *pcontext, + YangSysMessageI *pmessage,YangSysMessageHandleI* pmessagehandle) { + return new YangPushMessageHandle(hasAudio,pvideotype,screenvideo,outvideo,pcontext, pmessage,pmessagehandle); +} + +YangVideoBuffer* YangPushFactory::getPreVideoBuffer(YangSysMessageHandle* pmessageHandle){ + if(!pmessageHandle) return NULL; + YangPushMessageHandle* mess=dynamic_cast(pmessageHandle); + if(mess&&mess->m_push) return mess->m_push->getPreVideoBuffer(); + return NULL; + +} + +YangSendVideoI* YangPushFactory::getSendVideo(YangSysMessageHandle* pmessageHandle){ + if(!pmessageHandle) return NULL; + YangPushMessageHandle* mess=dynamic_cast(pmessageHandle); + if(mess&&mess->m_push) return mess->m_push->getSendVideo(); + return NULL; +} diff --git a/libyangrtc2/src/yangpush/YangPushHandleImpl.cpp b/libyangrtc2/src/yangpush/YangPushHandleImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b99e767aee337544c35e59a99b9c44ae2f4312a --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushHandleImpl.cpp @@ -0,0 +1,235 @@ +#include +#include +#include + +#include + +YangPushHandle::YangPushHandle() { + +} +YangPushHandle::~YangPushHandle() { + +} + +YangPushHandleImpl::YangPushHandleImpl(bool phasAudio,bool initVideo,int pvideotype,YangVideoInfo* screenvideo,YangVideoInfo* outvideo,YangContext* pcontext,YangSysMessageI* pmessage) { + m_pub = NULL; + m_videoState=pvideotype; + m_screenInfo=screenvideo; + m_outInfo=outvideo; + m_context = pcontext; + m_message = pmessage; + m_cap = new YangPushPublish(m_context); + m_cap->setCaptureType(m_videoState); + m_hasAudio = phasAudio; + m_isInit=initVideo; + init(); + m_send=NULL; + m_rec=NULL; + + +} + +YangPushHandleImpl::~YangPushHandleImpl() { + if (m_pub) + m_pub->disConnectMediaServer(); + if (m_cap) + m_cap->stopAll(); + yang_delete(m_pub); + yang_delete(m_cap); + yang_delete(m_rec); + +} +void YangPushHandleImpl::disconnect() { + if (m_cap) { + if(m_hasAudio) m_cap->stopAudioCaptureState(); + m_cap->stopVideoCaptureState(); + m_cap->stopScreenCaptureState(); + } + stopPublish(); +} +void YangPushHandleImpl::init() { + if(m_isInit) return; + changeSrc(m_videoState,true); + m_isInit=true; +} +void YangPushHandleImpl::startCapture() { + +} +YangSendVideoI* YangPushHandleImpl::getSendVideo(){ + if(m_send==NULL&&m_videoState==Yang_VideoSrc_OutInterface) { + m_send=new YangSendVideoImpl(); + if(m_cap){ + m_send->m_outVideoBuffer=m_cap->getOutVideoBuffer(); + m_send->m_outPreVideoBuffer=m_cap->getOutPreVideoBuffer(); + } + } + return m_send; +} +void YangPushHandleImpl::switchToCamera(bool pisinit) { + m_videoState = Yang_VideoSrc_Camera; + if(m_cap) m_cap->setCaptureType(m_videoState); + if(m_cap) m_cap->setVideoInfo(&m_context->video); + if(!pisinit) stopScreen(); + + startCamera(); +} + +void YangPushHandleImpl::switchToScreen(bool pisinit) { + + m_videoState = Yang_VideoSrc_Screen; + if(m_cap) m_cap->setCaptureType(m_videoState); + if(m_cap) m_cap->setVideoInfo(m_screenInfo); + + if(!pisinit) stopCamera(); + + startScreen(); + +} + +void YangPushHandleImpl::recordFile(char *filename) { + m_context->enc.createMeta=1; + if(m_rec==NULL) m_rec=new YangRecordHandle(m_context); + if(m_hasAudio) { + m_hasAudio=bool(m_cap->startAudioCapture()==Yang_Ok); + } + m_rec->init(m_cap->getPushCapture()); + m_rec->recordFile(filename); + if (m_hasAudio) + m_cap->startAudioCaptureState(); + if (m_videoState == Yang_VideoSrc_Camera) + m_cap->startVideoCaptureState(); + else if(m_videoState == Yang_VideoSrc_Screen){ + m_cap->startScreenCaptureState(); + } + +} + +void YangPushHandleImpl::stopRecord() { + if(m_rec) m_rec->stopRecord(); + yang_delete(m_rec); + if(m_cap) m_cap->deleteVideoEncoding(); +} + +void YangPushHandleImpl::switchToOutside(bool pisinit){ + if(m_cap) m_cap->setCaptureType(m_videoState); + if(m_cap) m_cap->setVideoInfo(m_outInfo); + +} +void YangPushHandleImpl::changeSrc(int videoSrcType,bool pisinit){ + m_videoState=videoSrcType; + if(m_videoState==Yang_VideoSrc_Camera){ + switchToCamera(pisinit); + }else if(m_videoState==Yang_VideoSrc_Screen){ + switchToScreen(pisinit); + }else if(m_videoState==Yang_VideoSrc_OutInterface) { + switchToOutside(pisinit); + } +} +void YangPushHandleImpl::setScreenInterval(int32_t pinterval) { + if(m_cap) m_cap->setScreenInterval(pinterval); +} + +void YangPushHandleImpl::setDrawmouse(bool isDraw) { + if(m_cap) m_cap->setDrawmouse(isDraw); +} + +void YangPushHandleImpl::stopPublish() { + if (m_pub) { + m_pub->disConnectMediaServer(); + } + yang_stop(m_pub); + yang_stop_thread(m_pub); + yang_delete(m_pub); + if(m_cap) m_cap->deleteVideoEncoding(); +} +YangVideoBuffer* YangPushHandleImpl::getPreVideoBuffer() { + if (m_videoState == Yang_VideoSrc_Camera) { + if (m_cap) return m_cap->getPreVideoBuffer(); + } else if (m_videoState == Yang_VideoSrc_Screen) { + if (m_cap) return m_cap->getScreenPreVideoBuffer(); + }else if (m_videoState == Yang_VideoSrc_OutInterface) { + if(m_cap) return m_cap->getOutPreVideoBuffer(); + } + return NULL; +} +void YangPushHandleImpl::setScreenVideoInfo(int videoSrcType,YangVideoInfo* pvideo){ + m_videoState = videoSrcType; + if (videoSrcType == Yang_VideoSrc_Screen) { + m_screenInfo = pvideo; + } else if (m_videoState == Yang_VideoSrc_OutInterface) { + m_outInfo = pvideo; + } +} + + + +int YangPushHandleImpl::publish(string url, string localIp, int32_t localPort) { + + int err = Yang_Ok; + if (yang_srs_url_parse((char*) url.c_str(), &m_url)) + return 1; + + stopPublish(); + yang_trace("\nnetType==%d,server=%s,port=%d,app=%s,stream=%s\n", + m_url.netType, m_url.server.c_str(), m_url.port, m_url.app.c_str(), + m_url.stream.c_str()); + + if (m_pub == NULL) { + m_pub = new YangRtcPublish(m_context); + + } + if(m_hasAudio) { + m_hasAudio=bool(m_cap->startAudioCapture()==Yang_Ok); + } + if (m_hasAudio) { + + m_cap->initAudioEncoding(); + } + + m_cap->initVideoEncoding(); + m_cap->setNetBuffer(m_pub); + + if (m_hasAudio) + m_cap->startAudioEncoding(); + m_cap->startVideoEncoding(); + if ((err = m_pub->init(m_url.netType, m_url.server, localIp, localPort, + 1985, m_url.app, m_url.stream)) != Yang_Ok) { + return yang_error_wrap(err, " connect server failure!"); + } + + m_pub->start(); + if (m_hasAudio) + m_cap->startAudioCaptureState(); + if (m_videoState == Yang_VideoSrc_Camera) + m_cap->startVideoCaptureState(); + else if(m_videoState == Yang_VideoSrc_Screen){ + m_cap->startScreenCaptureState(); + } + return err; + +} + +void YangPushHandleImpl::startCamera() { + if(m_cap) m_cap->startCamera(); +} + +void YangPushHandleImpl::startScreen() { + if(m_cap) m_cap->startScreen(); +} + +void YangPushHandleImpl::stopCamera() { + if(m_cap) m_cap->stopCamera(); +} + +void YangPushHandleImpl::stopScreen() { + if(m_cap) m_cap->stopScreen(); +} +#if Yang_HaveVr +void YangPushHandleImpl::addVr(){ + if(m_cap) m_cap->addVr(); +} +void YangPushHandleImpl::delVr(){ + if(m_cap) m_cap->delVr(); + +} +#endif diff --git a/libyangrtc2/src/yangpush/YangPushHandleImpl.h b/libyangrtc2/src/yangpush/YangPushHandleImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..2788851c28a511dcbaa706e4284c74b39761c616 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushHandleImpl.h @@ -0,0 +1,58 @@ +#ifndef YANGPUSH_YANGPUSHHANDLEIMPL_H_ +#define YANGPUSH_YANGPUSHHANDLEIMPL_H_ +#include +#include +#include +#include +#include +#include +class YangPushHandleImpl :public YangPushHandle{ +public: + YangPushHandleImpl(bool hasAudio,bool initVideo,int pvideotype,YangVideoInfo* screenvideo,YangVideoInfo* outvideo,YangContext* pcontext,YangSysMessageI* pmessage); + virtual ~YangPushHandleImpl(); + void init(); + void startCapture(); + int publish(string url,string localIp,int32_t localport); + void setScreenVideoInfo(int videoSrcType,YangVideoInfo* pvideo); + void setScreenInterval(int32_t pinterval); + YangVideoBuffer* getPreVideoBuffer(); + void recordFile(char* filename); + void stopRecord(); + void disconnect(); + void changeSrc(int videoSrcType,bool pisinit); + void setDrawmouse(bool isDraw); + void addVr(); + void delVr(); + + YangSendVideoI* getSendVideo(); + YangSendVideoImpl* m_send; + +private: + void startCamera(); + void startScreen(); + void stopCamera(); + void stopScreen(); + void stopPublish(); + + void switchToCamera(bool pisinit); + void switchToScreen(bool pisinit); + void switchToOutside(bool pisinit); + +private: + bool m_hasAudio; + int m_videoState; + bool m_isInit; + + YangPushPublish* m_cap; + YangRtcPublish* m_pub; + YangRecordHandle *m_rec; + YangContext* m_context; + YangUrlData m_url; + YangSysMessageI* m_message; + YangVideoInfo* m_screenInfo; + + YangVideoInfo* m_outInfo; + +}; + +#endif /* YANGPUSH_YANGPUSHHANDLEIMPL_H_ */ diff --git a/libyangrtc2/src/yangpush/YangPushMessageHandle.cpp b/libyangrtc2/src/yangpush/YangPushMessageHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfcf36fc9a1cd5dd8fdae88d9165174ecfee8edb --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushMessageHandle.cpp @@ -0,0 +1,110 @@ +#include "YangPushMessageHandle.h" +#include +#include +#include +#include +#include +#include +#include +#include + +YangPushMessageHandle::YangPushMessageHandle(bool hasAudio,int pvideotype,YangVideoInfo* screenvideo,YangVideoInfo* outvideo,YangContext* pcontext,YangSysMessageI* pmessage,YangSysMessageHandleI* pmessageHandle) { + +// m_receive = prec; + m_context=pcontext; + m_receive= pmessageHandle; + m_push = new YangPushHandleImpl(hasAudio,false,pvideotype,screenvideo,outvideo,pcontext,pmessage); + +} + +YangPushMessageHandle::~YangPushMessageHandle() { + deleteAll(); +} +void YangPushMessageHandle::initAll(){ + +} +void YangPushMessageHandle::deleteAll(){ + m_context=NULL; + yang_delete(m_push); +} + +void YangPushMessageHandle::handleMessage(YangSysMessage *mss) { + + //int32_t uid = mss->uid; + int32_t ret = Yang_Ok; + + switch (mss->messageId) { + case YangM_Push_StartVideoCapture: + { + if(m_push) m_push->changeSrc(Yang_VideoSrc_Camera,false); + break; + } + case YangM_Push_StartScreenCapture: + { + if(m_push) m_push->changeSrc(Yang_VideoSrc_Screen,false); + break; + } + case YangM_Push_StartOutCapture: + { + if(m_push) m_push->changeSrc(Yang_VideoSrc_OutInterface,false); + break; + } + case YangM_Push_Publish_Start: + { + if(mss->user&&m_push) ret = m_push->publish((char*)mss->user,yang_getLocalInfo().c_str(),m_context->sys.rtcLocalPort); + break; + } + case YangM_Push_Publish_Stop: + { + if(m_push) m_push->disconnect(); + break; + } + case YangM_Push_Record_Start: + { + if(mss->user&&m_push) m_push->recordFile((char*)mss->user); + break; + } + case YangM_Push_Record_Stop: + { + if(m_push) m_push->stopRecord(); + break; + } + case YangM_Push_SwitchToCamera: + { + if(m_push) + m_push->changeSrc(Yang_VideoSrc_Camera,false); + break; + } + case YangM_Push_SwitchToScreen: + { + if(m_push) + m_push->changeSrc(Yang_VideoSrc_Screen,false); + break; + } + case YangM_Sys_Setvr: + ret =Yang_Ok; +#if Yang_HaveVr + if(m_push) m_push->addVr(); +#endif + break; + case YangM_Sys_UnSetvr: + ret = Yang_Ok; +#if Yang_HaveVr + if(m_push) m_push->delVr(); +#endif + break; + + + } + + if (mss->handle) { + if (ret) + mss->handle->failure(ret); + else + mss->handle->success(); + } + + if (m_receive) + m_receive->receiveSysMessage(mss,ret); +} + diff --git a/libyangrtc2/src/yangpush/YangPushMessageHandle.h b/libyangrtc2/src/yangpush/YangPushMessageHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..337ee64e7d690ce2041ebb22bc1361672708392a --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushMessageHandle.h @@ -0,0 +1,34 @@ +/* + * YangMeetingHandle.cpp + * + * Created on: 2019年10月13日 + * Author: yang + */ + +#ifndef SRC_YANGMEETING_SRC_YangPushMessageHandle_H_ +#define SRC_YANGMEETING_SRC_YangPushMessageHandle_H_ +#include "YangPushHandleImpl.h" + +#include +#include +#include +#include "yangutil/sys/YangThread.h" + +using namespace std; + +class YangPushMessageHandle :public YangSysMessageHandle{ +public: + YangPushMessageHandle(bool hasAudio,int pvideotype,YangVideoInfo* screenvideo,YangVideoInfo* outvideo,YangContext* pcontext,YangSysMessageI* pmessage,YangSysMessageHandleI* pmessageHandle); + virtual ~YangPushMessageHandle(); + + void initAll(); + void deleteAll(); + void handleMessage(YangSysMessage* mss); + YangPushHandleImpl* m_push; +private: + YangContext *m_context; + YangSysMessageHandleI *m_receive; + +}; + +#endif /* SRC_YANGMEETING_SRC_YangPushMessageHandle_H_ */ diff --git a/libyangrtc2/src/yangpush/YangPushPublish.cpp b/libyangrtc2/src/yangpush/YangPushPublish.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e01f00bb64ee4183385f12ba1023c263159b95c5 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangPushPublish.cpp @@ -0,0 +1,216 @@ +#include +#include + + +YangPushPublish::YangPushPublish(YangContext *pcontext) { + m_context = pcontext; + m_context->streams.setSendRequestCallback(this); + m_videoInfo=&pcontext->video; + m_encoder = NULL; + m_capture = NULL; + m_outPreVideoBuffer=NULL; + m_outVideoBuffer=NULL; + isStartAudioCapture = 0, isStartVideoCapture = 0,isStartScreenCapture=0; + isStartAudioEncoder = 0, isStartVideoEncoder = 0; + m_captureType=Yang_VideoSrc_Camera; + +} + +YangPushPublish::~YangPushPublish() { + stopAll(); + m_context = NULL; + + yang_delete(m_encoder); + yang_delete(m_capture); + yang_delete(m_outPreVideoBuffer); + yang_delete(m_outVideoBuffer); +} +void YangPushPublish::sendRequest(int32_t puid,uint32_t ssrc,YangRequestType req){ + if(req==Yang_Req_Sendkeyframe) { + sendKeyframe(); + } + if(req==Yang_Req_Connected) { + //printf("\nsendRequest........audio=%d,video=%d.....",m_isPubAudio,m_isPubVideo); + + } +} +void YangPushPublish::setCaptureType(int pct){ + m_captureType=pct; +} +void YangPushPublish::setVideoInfo(YangVideoInfo* pvideo){ + m_videoInfo=pvideo; + if(m_captureType==Yang_VideoSrc_OutInterface) { + if(m_outVideoBuffer==NULL) m_outVideoBuffer=new YangVideoBuffer(pvideo->width,pvideo->height,pvideo->videoEncoderFormat,m_context->video.bitDepth==8?1:2); + if(m_outPreVideoBuffer==NULL) m_outPreVideoBuffer=new YangVideoBuffer(pvideo->width,pvideo->height,pvideo->videoEncoderFormat,m_context->video.bitDepth==8?1:2); + } +} +void YangPushPublish::stopAll(){ + if(m_capture) m_capture->stopAll(); + if(m_encoder) m_encoder->stopAll(); +} +void YangPushPublish::sendKeyframe(){ + if(m_encoder) m_encoder->sendKeyframe(); +} + +YangPushCapture* YangPushPublish::getPushCapture(){ + return m_capture; +} + +int32_t YangPushPublish::startAudioCapture() { + if (isStartAudioCapture == 1) return Yang_Ok; + if (m_capture == NULL) m_capture=new YangPushCapture(m_context); + int32_t err=Yang_Ok; + if((err=m_capture->initAudio(NULL))!=Yang_Ok) return yang_error_wrap(err,"init audioCapture fail"); + + m_capture->startAudioCapture(); + isStartAudioCapture = 1; + return err; + +} +int32_t YangPushPublish::startVideoCapture() { + if (isStartVideoCapture == 1) return Yang_Ok; + if (m_capture == NULL) m_capture=new YangPushCapture(m_context); + int32_t err=Yang_Ok; + if((err=m_capture->initVideo())!=Yang_Ok) return yang_error_wrap(err,"init videoCapture fail"); + m_capture->startVideoCapture(); + isStartVideoCapture = 1; + return err; +} + +int32_t YangPushPublish::startScreenCapture(){ + if (isStartScreenCapture == 1) return Yang_Ok; + if (m_capture == NULL) m_capture=new YangPushCapture(m_context); + m_capture->initScreen(); + m_capture->startScreenCapture(); + isStartScreenCapture = 1; + return Yang_Ok; +} +void YangPushPublish::setNetBuffer(YangRtcPublish *prr){ + yang_reindex(m_encoder->getOutAudioBuffer()); + yang_reindex(m_encoder->getOutVideoBuffer()); + m_encoder->getOutVideoBuffer()->resetIndex(); + prr->setInAudioList(m_encoder->getOutAudioBuffer()); + prr->setInVideoList(m_encoder->getOutVideoBuffer()); + prr->setInVideoMetaData(m_encoder->getOutVideoMetaData()); +} +void YangPushPublish::initAudioEncoding() { + + if (isStartAudioEncoder == 1) return; + if (m_encoder == NULL) + m_encoder = new YangPushEncoder(m_context); + m_encoder->initAudioEncoder(); + m_encoder->setInAudioBuffer(m_capture->getOutAudioBuffer()); + //prr->setInAudioList(m_encoder->getOutAudioBuffer()); + isStartAudioEncoder = 1; +} + +void YangPushPublish::change(int32_t st){ + if(m_capture) m_capture->change(st); +} +void YangPushPublish::setInAudioBuffer(vector *pbuf){ + if(m_capture) m_capture->setInAudioBuffer(pbuf); +} +void YangPushPublish::initVideoEncoding() { + if (isStartVideoEncoder == 1) return; + if (m_encoder == NULL) + m_encoder = new YangPushEncoder(m_context); + m_encoder->setVideoInfo(m_videoInfo); + + m_encoder->initVideoEncoder(); + if(m_captureType==Yang_VideoSrc_Camera){ + m_encoder->setInVideoBuffer(m_capture->getOutVideoBuffer()); + }else if(m_captureType==Yang_VideoSrc_Screen){ + m_encoder->setInVideoBuffer(m_capture->getScreenOutVideoBuffer()); + }else if(m_captureType==Yang_VideoSrc_OutInterface){ + m_encoder->setInVideoBuffer(m_outVideoBuffer); + } + isStartVideoEncoder = 1; +} +void YangPushPublish::startAudioEncoding() { + if (m_encoder) + m_encoder->startAudioEncoder(); +} +void YangPushPublish::startVideoEncoding() { + if (m_encoder) + m_encoder->startVideoEncoder(); +} +void YangPushPublish::deleteVideoEncoding(){ + if(m_encoder) m_encoder->deleteVideoEncoder(); + isStartVideoEncoder=0; + +} +void YangPushPublish::startAudioCaptureState() { + if (m_capture ) + m_capture->startAudioCaptureState(); +} +YangVideoBuffer* YangPushPublish::getPreVideoBuffer(){ + if (m_capture ) return m_capture->getPreVideoBuffer(); + return NULL; +} + +void YangPushPublish::startVideoCaptureState() { + if (m_capture ) + m_capture->startVideoCaptureState(); +} +void YangPushPublish::startScreenCaptureState(){ + if (m_capture ) + m_capture->startScreenCaptureState(); +} +void YangPushPublish::stopAudioCaptureState() { + if (m_capture ) + m_capture->stopAudioCaptureState(); +} +void YangPushPublish::stopVideoCaptureState() { + if (m_capture ) + m_capture->stopVideoCaptureState(); +} +void YangPushPublish::stopScreenCaptureState(){ + if (m_capture ) + m_capture->stopScreenCaptureState(); +} +#if Yang_HaveVr +void YangPushPublish::addVr(){ + if (m_capture ) m_capture->addVr(); +} +void YangPushPublish::delVr(){ + if (m_capture ) m_capture->delVr(); +} +#endif +YangVideoBuffer* YangPushPublish::getScreenPreVideoBuffer() { + if (m_capture ) return m_capture->getScreenPreVideoBuffer(); + return NULL; +} +YangVideoBuffer* YangPushPublish::getScreenOutVideoBuffer() { + if (m_capture ) return m_capture->getScreenOutVideoBuffer(); + return NULL; +} +YangVideoBuffer* YangPushPublish::getOutPreVideoBuffer(){ + return m_outPreVideoBuffer; +} + YangVideoBuffer* YangPushPublish::getOutVideoBuffer(){ + return m_outVideoBuffer; + + } +void YangPushPublish::startCamera() { + startVideoCapture(); +} + +void YangPushPublish::startScreen() { + startScreenCapture(); +} + +void YangPushPublish::stopCamera() { + if (m_capture ) m_capture->stopCamera(); +} + +void YangPushPublish::stopScreen() { + if (m_capture ) m_capture->stopScreen(); +} + +void YangPushPublish::setScreenInterval(int32_t pinterval) { + if(m_capture) m_capture->setScreenInterval(pinterval); +} + +void YangPushPublish::setDrawmouse(bool isDraw) { + if(m_capture) m_capture->setDrawmouse(isDraw); +} diff --git a/libyangrtc2/src/yangpush/YangRtcPublish.cpp b/libyangrtc2/src/yangpush/YangRtcPublish.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffa3a8af88dd7f4c3dda59ef1dbad2495382d9b1 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangRtcPublish.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include "yangstream/YangStreamFactory.h" +#include +#include +#include +#include +#include +YangRtcPublish::YangRtcPublish(YangContext *pcontext) { + m_context = pcontext; + + m_in_videoBuffer = NULL; + m_in_audioBuffer = NULL; + m_isStart = 0; + m_isConvert = 0; + m_vmd = NULL; + m_audioEncoderType = m_context->audio.audioEncoderType; + m_netState = 1; + m_isInit = 0; + isPublished = 0; + + m_transType=Yang_Webrtc; + notifyState=0; +} + +YangRtcPublish::~YangRtcPublish() { + if (m_isConvert) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_context = NULL; + m_in_videoBuffer = NULL; + m_in_audioBuffer = NULL; + m_vmd = NULL; +} + + +int32_t YangRtcPublish::connectServer(int32_t puid){ + return m_pushs.back()->connectServer(); +} + + + +int32_t YangRtcPublish::reconnectMediaServer() { + return m_pushs.back()->reconnect(); + +} + +int32_t YangRtcPublish::init(int32_t nettype, string server, string localIp,int32_t localPort,int32_t pport, + string app,string stream) { + YangStreamFactory sf; + int32_t ret = 0; + YangStreamConfig streamConf; + streamConf.app=app; + streamConf.streamOptType=Yang_Stream_Publish; + streamConf.serverIp=server; + streamConf.serverPort=pport; + streamConf.stream=stream; + streamConf.uid=0;//0 singleuser 1 multiuser + + streamConf.localIp=localIp; + streamConf.localPort=localPort; + + if (m_pushs.size() == 0) { + m_pushs.push_back(sf.createStreamHandle(m_context->sys.transType,0,m_context)); + m_pushs.back()->init(&streamConf); + + } + + + if (m_pushs.back()->isconnected()) return Yang_Ok; + ret = m_pushs.back()->connectServer(); + + if (ret) return ret; + m_pushs.back()->m_streamInit = 1; + yang_reindex(m_in_audioBuffer); + yang_reindex(m_in_videoBuffer); + return Yang_Ok; + +} +int32_t YangRtcPublish::connectMediaServer() { + if(m_pushs.size()>0) return Yang_Ok; + + return Yang_Ok; +} +int32_t YangRtcPublish::disConnectMediaServer() { + if (m_pushs.size() > 0) { + m_pushs.back()->m_streamInit = 0; + delete m_pushs.back(); + m_pushs.back() = NULL; + m_pushs.clear(); + } + return Yang_Ok; +} +void YangRtcPublish::stop() { + m_isConvert = 0; +} + +void YangRtcPublish::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} + +void YangRtcPublish::setInAudioList(YangAudioEncoderBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} +void YangRtcPublish::setInVideoList(YangVideoEncoderBuffer *pbuf) { + m_in_videoBuffer = pbuf; +} +void YangRtcPublish::setInVideoMetaData(YangVideoMeta *pvmd) { + m_vmd = pvmd; +} + +void YangRtcPublish::startLoop() { + + isPublished = 0; + m_isConvert = 1; + + YangStreamCapture data; + + YangFrame audioFrame; + YangFrame videoFrame; + memset(&audioFrame,0,sizeof(YangFrame)); + memset(&videoFrame,0,sizeof(YangFrame)); + data.initAudio(m_context->sys.transType,m_context->audio.sample, m_context->audio.channel, + (YangAudioEncDecType) m_context->audio.audioEncoderType); + data.initVideo(m_context->sys.transType); + YangVideoEncDecType videoType = (YangVideoEncDecType) m_context->video.videoEncoderType; + + int32_t ret = Yang_Ok; + isPublished = 1; + notifyState=1; + YangVideoMeta* vmd=NULL; + if(!m_context->enc.createMeta){ + vmd=new YangVideoMeta(); + } + //uint8_t* tmp=NULL; + YangH264NaluData nalu; + //uint8_t meta[200] = { 0 }; + + while (m_isConvert == 1) { + + + if ((m_in_videoBuffer && m_in_videoBuffer->size() == 0) + && (m_in_audioBuffer && m_in_audioBuffer->size() == 0)) { + yang_usleep(2000); + continue; + } + if (m_pushs.size() == 0 || !m_pushs.back()->m_streamInit) { + yang_usleep(500); + continue; + } + YangStreamHandle* stream=m_pushs.back(); + + if(stream->isconnected()){ + if(notifyState&&m_transTypestreams.sendRequest(0,0,Yang_Req_Connected); + notifyState=0; + } + + }else{ + yang_usleep(500); + continue; + } + + if (m_in_audioBuffer && m_in_audioBuffer->size() > 0) { + + audioFrame.payload = m_in_audioBuffer->getAudioRef(&audioFrame); + data.setAudioData(&audioFrame); + + //for (i = 0; i < m_pushs.size(); i++) { + ret = stream->publishAudioData(&data); + if (ret&&!stream->isconnected()) { + stream->m_streamInit = 0; + stream->disConnectServer(); + //yang_post_message(YangM_Sys_PushMediaServerError,m_pushs.back()->m_uid,NULL); + } + //} + } + + if (m_in_videoBuffer && m_in_videoBuffer->size() > 0) { + + videoFrame.payload = m_in_videoBuffer->getEVideoRef(&videoFrame); + + if (videoFrame.frametype == YANG_Frametype_I) { + + if (m_vmd) { + data.setVideoMeta(m_vmd->livingMeta.buffer, + m_vmd->livingMeta.bufLen, videoType); + //if (ret) continue; + } else { + if (!vmd->isInit) { + if (videoType == Yang_VED_264) { + yang_createH264Meta(vmd, &videoFrame); + yang_getConfig_Flv_H264(&vmd->mp4Meta, + vmd->livingMeta.buffer, + &vmd->livingMeta.bufLen); + } else if (videoType == Yang_VED_265) { + yang_createH265Meta(vmd, &videoFrame); + yang_getConfig_Flv_H265(&vmd->mp4Meta, + vmd->livingMeta.buffer, + &vmd->livingMeta.bufLen); + } + } + data.setVideoMeta(vmd->livingMeta.buffer, + vmd->livingMeta.bufLen, videoType); + } + data.setVideoFrametype(YANG_Frametype_Spspps); + ret = stream->publishVideoData(&data); + + + + if (!m_context->enc.createMeta) { + memset(&nalu, 0, sizeof(YangH264NaluData)); + yang_parseH264Nalu(&videoFrame, &nalu); + if (nalu.keyframePos > -1) { + videoFrame.payload += nalu.keyframePos + 4; + videoFrame.nb -= (nalu.keyframePos + 4); + + } else { + videoFrame.payload = NULL; + continue; + } + } + } + + data.setVideoData(&videoFrame, videoType); + //for (i = 0; i < m_pushs.size(); i++) { + ret = stream->publishVideoData(&data); + if (ret && !stream->isconnected()) { + stream->m_streamInit = 0; + stream->disConnectServer(); + + } + + } //end + } + isPublished = 0; + yang_delete(vmd); +} diff --git a/libyangrtc2/src/yangpush/YangSendVideoImpl.cpp b/libyangrtc2/src/yangpush/YangSendVideoImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddbf0b0392cf93af3f83e0f90d191158f2cda14b --- /dev/null +++ b/libyangrtc2/src/yangpush/YangSendVideoImpl.cpp @@ -0,0 +1,41 @@ +#include + +YangSendVideoImpl::YangSendVideoImpl() { + m_outVideoBuffer=NULL; + m_outPreVideoBuffer=NULL; + m_width=1920; + m_height=1080; + m_buf=NULL; + m_len=0; + memset(&m_videoFrame,0,sizeof(YangFrame)); + +} + +YangSendVideoImpl::~YangSendVideoImpl() { + yang_deleteA(m_buf); +} +void YangSendVideoImpl::init(int32_t wid,int32_t hei){ + m_width=wid; + m_height=hei; +} +void YangSendVideoImpl::putVideoRgba(uint8_t *data, int len,int64_t timestamp) { + if(m_buf==NULL){ + m_len=m_width*m_height*3/2; + m_buf=new uint8_t[m_len]; + + } + + m_yuv.bgratoI420(data,m_buf,m_width,m_height); + putVideoI420(m_buf,m_len,timestamp); + +} + +void YangSendVideoImpl::putVideoI420(uint8_t *data, int len,int64_t timestamp) { + m_videoFrame.payload=data; + m_videoFrame.nb=len; + m_videoFrame.timestamp=timestamp; + if(m_outVideoBuffer) m_outVideoBuffer->putVideo(&m_videoFrame); + if(m_outPreVideoBuffer) m_outPreVideoBuffer->putVideo(&m_videoFrame); + + +} diff --git a/libyangrtc2/src/yangpush/YangSendVideoImpl.h b/libyangrtc2/src/yangpush/YangSendVideoImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..a572f2136fd0a3d82d8fde85de19d2c8933a9798 --- /dev/null +++ b/libyangrtc2/src/yangpush/YangSendVideoImpl.h @@ -0,0 +1,29 @@ +#ifndef SRC_YANGPUSH_YANGSENDVIDEOIMPL_H_ +#define SRC_YANGPUSH_YANGSENDVIDEOIMPL_H_ +#include +#include +#include +class YangSendVideoImpl:public YangSendVideoI { +public: + YangSendVideoImpl(); + virtual ~YangSendVideoImpl(); + void putVideoRgba(uint8_t* data,int len,int64_t timestamp); + void putVideoI420(uint8_t* data,int len,int64_t timestamp); + void init(int32_t wid,int32_t hei); + + + YangVideoBuffer* m_outPreVideoBuffer; + YangVideoBuffer* m_outVideoBuffer; +private: + YangYuvConvert m_yuv; + YangFrame m_videoFrame; + uint8_t* m_buf; + + int32_t m_width; + int32_t m_height; + int32_t m_len; + + +}; + +#endif /* SRC_YANGPUSH_YANGSENDVIDEOIMPL_H_ */ diff --git a/libyangrtc2/src/yangrecord/YangFlvWrite.cpp b/libyangrtc2/src/yangrecord/YangFlvWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbffd8a8a2f0dc1558be7aca910b90ec4bbb0b19 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangFlvWrite.cpp @@ -0,0 +1,483 @@ +#include + +#include +#include +#include +#include +#include +#include "yangutil/yang_unistd.h" +#include "yangutil/sys/YangAmf.h" +#define REFERENCE_TIME int64_t +//#define _T(x) x +typedef uint8_t uint8; + + +//----------------------------------------------------------------------------- +// +// FLVWriter class +// +//----------------------------------------------------------------------------- + +YangFlvWriter::YangFlvWriter(char* fileName, YangAudioInfo *paudio,YangVideoInfo *pvideo) + +{ + m_audio=paudio; + m_video=pvideo; + m_Video_Bit_Count = m_video->videoCaptureFormat==0?16:12; + m_Video_Width = m_video->width; + m_Video_Height = m_video->height; + + video_codec = FLV_CODEC_H264; + audio_codec = m_audio->audioEncoderType==0?FLV_CODEC_AAC:FLV_CODEC_MP3; + + video_raw_size = 0; + time_first_ms = 0; + time_last_ms = 0; + video_frames = 0; + audio_channels = 0; + audio_samplerate = 0; + is_first = true; + duration_ms = 0; + video_fps = 0; + file_size = 0; + vcount = 0; + vtime = 0; + atime = 0; + perSt = (m_audio->audioEncoderType==0?1024.0:1152.0) * 1000.0 / 44100.0; + atime1 = 0; + //vtime1 = 0; + vtcou = 0; + file = fopen(fileName,"wb"); + pre_vt=0; + framerate=30; + pre_at=0; + metadatapos=0; + i_bitrate=0; + i_level_idc=0; + last_tag_size=0; + + +} + +YangFlvWriter::~YangFlvWriter() { + m_audio=NULL; + m_video=NULL; + + Reset(); +} + +int32_t YangFlvWriter::Reset() { + + video_raw_size = 0; + video_frames = 0; + audio_channels = 0; + audio_samplerate = 0; + last_tag_size = 0; + video_fps = 0; + file_size = 0; + + // no streams... + video_codec = FLV_CODEC_H264; + audio_codec = m_audio->audioEncoderType==0?FLV_CODEC_AAC:FLV_CODEC_MP3; + + time_first_ms = 0; + time_last_ms = 0; + duration_ms = 0; + is_first = true; + vtime = 0; + atime = 0; + + return 0; +} + +int32_t YangFlvWriter::Start() { + + // write the file header + BYTE header[9] = { 'F', 'L', 'V', // FLV file signature + 0x01, // FLV file version = 1 + 0, // Flags - modified later + 0, 0, 0, 9 // size of the header + }; + + header[4] |= 0x01; + //header[4] |= 0x04; + //rewind(file); + //io->Seek(0); + file_size = 0; + fwrite(header, 1, sizeof(header), file); + + metadatapos = ftell(file); + WriteMetaData(); + + file_size = ftell(file); + metadatapos = file_size; + return 0; +} + +int32_t YangFlvWriter::Stop() { + + BYTE prev[4]; + //long ttt=vtime; + prev[0] = (last_tag_size >> 24) & 0xff; + prev[1] = (last_tag_size >> 16) & 0xff; + prev[2] = (last_tag_size >> 8) & 0xff; + prev[3] = (last_tag_size >> 0) & 0xff; + fwrite(prev, 1, 4, file); + uint8_t last[] = { 0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x17, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10 }; + last[4] = (vtime >> 16) & 0xff; // TimeStamp UI24 + last[5] = (vtime >> 8) & 0xff; + last[6] = (vtime >> 0) & 0xff; + last[7] = (vtime >> 24) & 0xff; + file_size += (4 + sizeof(last)); + fwrite(last, 1, sizeof(last), file); + //printf("\nvtime==%d,atime=%d,filesieze=%d\n", vtime, atime,file_size); + rewind(file); + fseek(file, 9, SEEK_SET); + WriteMetaData(); + + return 0; +} +void YangFlvWriter::Close() { + Stop(); + fflush(file); + fclose(file); + file = NULL; +} +int32_t YangFlvWriter::MakeAVCc(char* data, int32_t size, char *output_data, + int32_t output_size) { + if (!data || size <= 0) + return -1; + int32_t ps_size = (data[0] << 8) | (data[1]); + int32_t ss_size = (data[ps_size + 2] << 8) | (data[ps_size + 3]); + int32_t buf_size = 6 + ps_size + 2 + 1 + ss_size + 2; + + if (buf_size > output_size) + return -1; + + char* temp = data; + char* output_temp = output_data; + + output_temp[0] = 1; + output_temp[1] = temp[3]; + output_temp[2] = temp[4]; + output_temp[3] = temp[5]; + output_temp[4] = 0xff; + output_temp[5] = 0xe1; + output_temp += 6; + + memcpy(output_temp, temp, ps_size + 2); + output_temp += ps_size + 2; + temp += ps_size + 2; + + output_temp[0] = 1; + output_temp += 1; + + memcpy(output_temp, temp, ss_size + 2); + + return buf_size; +} + +void YangFlvWriter::WriteVideoInfo(uint8_t* buf1, int32_t buflen) { + + /**BYTE prev[4]; + BYTE tag_hdr[16]; + int32_t tag_data_size(0); + int32_t towrite(0); + BYTE *data(NULL); + int32_t size(0);**/ + + memset(tag_hdr, 0, sizeof(tag_hdr)); + //memset(prev,0,4); + prev[0] = (last_tag_size >> 24) & 0xff; + prev[1] = (last_tag_size >> 16) & 0xff; + prev[2] = (last_tag_size >> 8) & 0xff; + prev[3] = (last_tag_size >> 0) & 0xff; + fwrite(prev, 1, 4, file); + + //int32_t extradata_size = MakeAVCc(video_extradata.data, video_extradata.size, extradata, sizeof(extradata)); + //tag_data_size = 5 + extradata_size; + tag_hdr[0] = 0x09; + tag_hdr[11] = 0x17; + //towrite = 16; + //data = (BYTE*)extradata; + //size = extradata_size; + + tag_hdr[1] = (buflen >> 16) & 0xff; + tag_hdr[2] = (buflen >> 8) & 0xff; + tag_hdr[3] = (buflen >> 0) & 0xff; + + //last_tag_size = tag_data_size + 11; + fwrite(tag_hdr, 1, 11, file); + fwrite(buf1, 1, buflen, file); + +} + +int32_t YangFlvWriter::WriteAudioPacket(YangFrame* audioFrame) { + if (!file) + return 0; + //printf("%d,",p_len); + //BYTE tag_hdr[20]; + memset(tag_hdr, 0, sizeof(tag_hdr)); + tag_hdr[0] = 0x08; + int p_len=audioFrame->nb; + int32_t tag_data_size = p_len; + tag_data_size += 1; + tag_hdr[1] = ((p_len + 1) >> 16) & 0xff; + tag_hdr[2] = ((p_len + 1) >> 8) & 0xff; + tag_hdr[3] = ((p_len + 1) >> 0) & 0xff; + + //__int64 timestamp_ms = 0; + pre_at = atime; + + + vtcou++; + atime1 += perSt; + atime = (unsigned int) atime1; + tag_hdr[4] = (pre_at >> 16) & 0xff; // TimeStamp UI24 + tag_hdr[5] = (pre_at >> 8) & 0xff; + tag_hdr[6] = (pre_at >> 0) & 0xff; + tag_hdr[7] = (pre_at >> 24) & 0xff; // TimestampExtended UI8 + + // keep track of the last timestamp + time_last_ms = pre_at; + duration_ms = time_last_ms; // for now we consider the last timestamp duration + + // StreamID = always 0 + tag_hdr[8] = 0; + tag_hdr[9] = 0; + tag_hdr[10] = 0; + + /* + Now write the TAG + */ + + // 1. previous tag size + //BYTE prev[4]; + prev[0] = (last_tag_size >> 24) & 0xff; + prev[1] = (last_tag_size >> 16) & 0xff; + prev[2] = (last_tag_size >> 8) & 0xff; + prev[3] = (last_tag_size >> 0) & 0xff; + + fwrite(prev, 1, 4, file); + tag_hdr[11] = 0x2f; + fwrite(tag_hdr, 1, 12, file); + fwrite(audioFrame->payload, 1, p_len, file); + last_tag_size = p_len + 12; + file_size = ftell(file); //io->GetPosition(); + return 1; + +} +int32_t YangFlvWriter::WriteVideoPacket(YangFrame* videoFrame) { + if (!file) + return 0; + + + memset(tag_hdr, 0, sizeof(tag_hdr)); + // we support only two streams + + tag_hdr[0] = 0x09; + //printf("-a%d-", vtime); + // tag size + int32_t len=videoFrame->nb; + int32_t tag_data_size = len; + + // VIDEO DATA follows after the tag + tag_data_size += 5; + + tag_hdr[1] = ((len + 9) >> 16) & 0xff; + tag_hdr[2] = ((len + 9) >> 8) & 0xff; + tag_hdr[3] = ((len + 9) >> 0) & 0xff; + + time_first_ms = 0; // we will offset all timestamps by this value + pre_vt=vtime; + vtime = videoFrame->timestamp; + //printf("%d,",p_timestamp); + //vcount++; + + tag_hdr[4] = (pre_vt >> 16) & 0xff; // TimeStamp UI24 + tag_hdr[5] = (pre_vt >> 8) & 0xff; + tag_hdr[6] = (pre_vt >> 0) & 0xff; + tag_hdr[7] = (pre_vt >> 24) & 0xff; // TimestampExtended UI8 + + // keep track of the last timestamp + time_last_ms = pre_vt; + duration_ms = time_last_ms; // for now we consider the last timestamp duration + + // StreamID = always 0 + tag_hdr[8] = 0; + tag_hdr[9] = 0; + tag_hdr[10] = 0; + + /* + Now write the TAG + */ + + // 1. previous tag size + + prev[0] = (last_tag_size >> 24) & 0xff; + prev[1] = (last_tag_size >> 16) & 0xff; + prev[2] = (last_tag_size >> 8) & 0xff; + prev[3] = (last_tag_size >> 0) & 0xff; + + fwrite(prev, 1, 4, file); + + if (videoFrame->frametype == 1) + tag_hdr[11] = 0x17; + else + tag_hdr[11] = 0x27; + + tag_hdr[12] = 0x01; + //int32_t diff=33; + // tag_hdr[15]=0x42; + tag_hdr[19] = len & 0xff; + tag_hdr[18] = len >> 8; + tag_hdr[17] = len >> 16; + tag_hdr[16] = len >> 24; + + fwrite(tag_hdr, 1, 20, file); + fwrite(videoFrame->payload, 1, len, file); + + video_raw_size += len; //packet->size; + video_frames += 1; + + last_tag_size = len + 20; + file_size = ftell(file); //io->GetPosition(); + return 0; +} + +int32_t YangFlvWriter::WriteMetaData() { + + /* + We assemble some basic onMetaData structure. + */ + //Flash::AS_String name; + //Flash::AS_ECMA_Array vals; + + //name.value = _T("onMetaData"); + + /* + We create the following metadata + */ + char meta[1024]; + char * szTmp=meta; + + // char * szTmp=(char *)temp; + + // szTmp=yang_put_byte(szTmp, AMF_STRING ); + // szTmp=put_amf_string(szTmp, "@setDataFrame" ); + szTmp=yang_put_byte(szTmp, AMF_STRING ); + szTmp=put_amf_string(szTmp, "onMetaData" ); + szTmp=yang_put_byte(szTmp, AMF_OBJECT ); + + szTmp=put_amf_string( szTmp, "metadatacreator" ); + szTmp=yang_put_byte(szTmp, AMF_STRING ); + szTmp=put_amf_string( szTmp, "FLV Mux" ); + + szTmp=put_amf_string( szTmp, "duration" ); + szTmp=put_amf_double( szTmp, vtime/1000 ); + + szTmp=put_amf_string( szTmp, "filesize" ); + szTmp=put_amf_double( szTmp, file_size ); + + szTmp=put_amf_string( szTmp, "lasttimestamp" ); + szTmp=put_amf_double( szTmp, time_last_ms/1000 ); + + + szTmp=put_amf_string( szTmp, "hasVideo" ); + szTmp=put_amf_double( szTmp, 1 ); + + + + //szTmp=put_amf_string( szTmp, "Custom" ); + + szTmp=put_amf_string( szTmp, "width" ); + szTmp=put_amf_double( szTmp, m_Video_Width ); + + szTmp=put_amf_string( szTmp, "height" ); + szTmp=put_amf_double( szTmp, m_Video_Height ); + + szTmp=put_amf_string( szTmp, "framerate" ); + szTmp=put_amf_double( szTmp, m_video->frame); + + szTmp=put_amf_string( szTmp, "videocodecid" ); + szTmp=yang_put_byte(szTmp, AMF_STRING ); + szTmp=put_amf_string( szTmp, "avc1" ); + + szTmp=put_amf_string( szTmp, "videodatarate" ); + szTmp=put_amf_double( szTmp, i_bitrate ); + + szTmp=put_amf_string( szTmp, "avclevel" ); + szTmp=put_amf_double( szTmp, i_level_idc ); + + szTmp=put_amf_string( szTmp, "avcprofile" ); + szTmp=put_amf_double( szTmp, 0x42 ); + + szTmp=put_amf_string( szTmp, "videokeyframe_frequency" ); + szTmp=put_amf_double( szTmp, 3 ); + // szTmp=put_amf_string( szTmp, "" ); + + szTmp=put_amf_string( szTmp, "hasAudio" ); + szTmp=put_amf_double( szTmp, 1); + + szTmp=put_amf_string( szTmp, "audiocodecid" ); + szTmp=put_amf_double( szTmp, 2 ); + + + szTmp=put_amf_string( szTmp, "audiosamplesize" ); + szTmp=put_amf_double( szTmp, 16 ); + + szTmp=put_amf_string( szTmp, "stereo" ); + szTmp=put_amf_double( szTmp, 1 ); + + szTmp=put_amf_string( szTmp, "audiosamplerate" ); + szTmp=put_amf_double( szTmp, 44100 ); + + szTmp=put_amf_string( szTmp, "" ); + szTmp=yang_put_byte( szTmp, AMF_OBJECT_END ); + + int32_t total_size=szTmp-meta; + BYTE tag_hdr[] = { 0, 0, 0, 0, // previous tag size + 0x12, // Type UI8 = Script Data Tag, + (total_size >> 16) & 0xff, // DataSize UI24 + (total_size >> 8) & 0xff, (total_size >> 0) & 0xff, 0, 0, 0, 0, // TimeStamp UI24 + TimestampExtended UI8 + 0, 0, 0 // StreamID UI24 (always 0) + }; + + fwrite(tag_hdr, 1, sizeof(tag_hdr), file); + fwrite(meta, 1, total_size, file); + last_tag_size = (sizeof(tag_hdr) + total_size - 4); // the first 4 bytes don't count + szTmp=NULL; + + + return 0; +} + + +char * YangFlvWriter::put_amf_string( char *c, const char *str ) +{ + uint16_t len = strlen( str ); + c=yang_put_be16( c, len ); + memcpy(c,str,len); + return c+len; +} +char * YangFlvWriter::put_amf_double( char *c, double d ) +{ + *c++ = 0; /* type: Number */ + { + uint8_t *ci, *co; + ci = (uint8_t *)&d; + co = (uint8_t *)c; + co[0] = ci[7]; + co[1] = ci[6]; + co[2] = ci[5]; + co[3] = ci[4]; + co[4] = ci[3]; + co[5] = ci[2]; + co[6] = ci[1]; + co[7] = ci[0]; + } + return c+8; +} + diff --git a/libyangrtc2/src/yangrecord/YangMp4File.cpp b/libyangrtc2/src/yangrecord/YangMp4File.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc0115acb40c5c6d76f2d5df1f7bec442ac80279 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangMp4File.cpp @@ -0,0 +1,190 @@ +#include +#include +void YangMp4File::loadLib() { + yang_MP4TagsAlloc = (const MP4Tags* (*)(void)) m_lib.loadFunction("MP4TagsAlloc"); + yang_MP4TagsFree=(void (*)( const MP4Tags* tags )) m_lib.loadFunction("MP4TagsFree"); + yang_MP4Create =(MP4FileHandle (*)(const char *fileName, uint32_t flags)) m_lib.loadFunction("MP4Create"); + yang_MP4TagsFetch =(bool (*)(const MP4Tags *tags, MP4FileHandle hFile)) m_lib.loadFunction("MP4TagsFetch"); + yang_MP4TagsSetSortArtist = (bool (*)(const MP4Tags*, const char*)) m_lib.loadFunction("MP4TagsSetSortArtist"); + yang_MP4TagsStore =(bool (*)(const MP4Tags *tags, MP4FileHandle hFile)) m_lib.loadFunction("MP4TagsStore"); + yang_MP4SetTimeScale =(bool (*)(MP4FileHandle hFile, uint32_t value)) m_lib.loadFunction("MP4SetTimeScale"); + yang_MP4SetVideoProfileLevel =(void (*)(MP4FileHandle hFile, uint8_t value))m_lib.loadFunction("MP4SetVideoProfileLevel"); + yang_MP4SetAudioProfileLevel =(void (*)(MP4FileHandle hFile, uint8_t value))m_lib.loadFunction("MP4SetAudioProfileLevel"); + yang_MP4AddAudioTrack =(MP4TrackId (*)(MP4FileHandle hFile, uint32_t timeScale,MP4Duration sampleDuration, uint8_t audioType))m_lib.loadFunction("MP4AddAudioTrack"); + yang_MP4AddH264VideoTrack = (MP4TrackId (*)(MP4FileHandle hFile,uint32_t timeScale, MP4Duration sampleDuration, uint16_t width, + uint16_t height, uint8_t AVCProfileIndication,uint8_t profile_compat,uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne))m_lib.loadFunction("MP4AddH264VideoTrack"); + yang_MP4SetTrackESConfiguration =(bool (*)(MP4FileHandle hFile, MP4TrackId trackId,const uint8_t *pConfig, uint32_t configSize))m_lib.loadFunction("MP4SetTrackESConfiguration"); + yang_MP4AddH264SequenceParameterSet =(void (*)(MP4FileHandle hFile, MP4TrackId trackId,const uint8_t *pSequence, uint16_t sequenceLen)) m_lib.loadFunction( + "MP4AddH264SequenceParameterSet"); + yang_MP4AddH264PictureParameterSet =(void (*)(MP4FileHandle hFile, MP4TrackId trackId, + const uint8_t *pPict, uint16_t pictLen)) m_lib.loadFunction("MP4AddH264PictureParameterSet"); + yang_MP4WriteSample = (bool (*)(MP4FileHandle hFile, MP4TrackId trackId,const uint8_t *pBytes, uint32_t numBytes, MP4Duration duration, + MP4Duration renderingOffset, bool isSyncSample)) m_lib.loadFunction("MP4WriteSample"); + yang_MP4Close =(void (*)(MP4FileHandle hFile, uint32_t flags)) m_lib.loadFunction("MP4Close"); + + yang_MP4AddH265VideoTrack=(MP4TrackId (*)( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t isIso)) m_lib.loadFunction("MP4AddH265VideoTrack"); + yang_MP4AddH265SequenceParameterSet=(void (*)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen )) m_lib.loadFunction("MP4AddH265SequenceParameterSet"); + yang_MP4AddH265PictureParameterSet=(void (*)( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen )) m_lib.loadFunction("MP4AddH265PictureParameterSet"); + yang_MP4AddH265VideoParameterSet=(void (*) (MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen)) m_lib.loadFunction("MP4AddH265VideoParameterSet"); + yang_MP4GetTrackTimeScale=(uint32_t (*) ( + MP4FileHandle hFile, + MP4TrackId trackId )) m_lib.loadFunction("MP4GetTrackTimeScale"); + yang_MP4SetTrackTimeScale=(bool (*) ( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t value )) m_lib.loadFunction("MP4SetTrackTimeScale"); +} + +void YangMp4File::unloadLib() { + yang_MP4AddH265VideoTrack=NULL; + yang_MP4AddH265SequenceParameterSet=NULL; + yang_MP4AddH265PictureParameterSet=NULL; + yang_MP4AddH265VideoParameterSet=NULL; + yang_MP4TagsAlloc = NULL; + yang_MP4TagsFree=NULL; + yang_MP4Create = NULL; + yang_MP4TagsFetch = NULL; + yang_MP4TagsSetSortArtist = NULL; + yang_MP4TagsStore = NULL; + yang_MP4SetTimeScale = NULL; + yang_MP4SetVideoProfileLevel = NULL; + yang_MP4SetAudioProfileLevel = NULL; + yang_MP4AddAudioTrack = NULL; + yang_MP4AddH264VideoTrack = NULL; + yang_MP4SetTrackESConfiguration = NULL; + yang_MP4AddH264SequenceParameterSet = NULL; + yang_MP4AddH264PictureParameterSet = NULL; + yang_MP4WriteSample = NULL; + yang_MP4Close = NULL; +} +YangMp4File::~YangMp4File(void) { + closeMp4(); + unloadLib(); + m_lib.unloadObject(); +} + +YangMp4File::YangMp4File(char *fileName, YangVideoInfo *pcontext) { + m_context = pcontext; + m_MP4hFile = MP4_INVALID_FILE_HANDLE; + m_mp4Audiotrack = 0; + m_mp4Videotrack = 0; + m_ntracks = 0, m_trackno = 0; + m_ndiscs = 0, m_discno = 0; + m_newtick = 0; + m_oldtick = 0; + m_newalltick = 0, m_oldalltick = 0; + m_tmptick = 0; + m_tick = 0; + m_cou = 0; + m_interval = 2 * (1000 / m_context->frame) * 90; + m_interval1 = 2 * (1000 / m_context->frame); + + m_artist = NULL; + + m_total_samples = 0; + m_encoded_samples = 0; + m_delay_samples = 0; + m_frameSize = 0; + //hEncoder=NULL; + + yang_trace("\ncreate mp4 file======%s", fileName); + m_lib.loadObject("libmp4v2"); + loadLib(); + //MP4Create + m_MP4hFile = yang_MP4Create(fileName, 0); + +} +void YangMp4File::init(uint8_t *p_spsBuf, int32_t p_spsLen) { + + const MP4Tags *tags = yang_MP4TagsAlloc(); + yang_MP4TagsFetch(tags, m_MP4hFile); + yang_MP4TagsStore(tags, m_MP4hFile); + yang_MP4SetTimeScale(m_MP4hFile, 90000); + m_mp4Audiotrack = yang_MP4AddAudioTrack(m_MP4hFile, 44100, 1024,MP4_MPEG4_AUDIO_TYPE); + // MP4SetAudioProfileLevel(MP4hFile, 0x0F); + //mp4Videotrack = MP4AddH264VideoTrack(MP4hFile, 90000, 90000/config.Frame_Num, config.Video_Width,config.Video_Height,0x42,0xc0,0x1f,3); + //MP4AddH265VideoTrack + if(m_context->videoEncoderType==1){ + //printf("\n**********MP4AddH265VideoTrack***********\n"); + m_mp4Videotrack = yang_MP4AddH265VideoTrack(m_MP4hFile, 90000, -1, + m_context->width, m_context->height, 0); + + }else{ + m_mp4Videotrack = yang_MP4AddH264VideoTrack(m_MP4hFile, 90000, -1, + m_context->width, m_context->height, //0x42, 0xc0, 0x1f, 3); + *(p_spsBuf+1), *(p_spsBuf+2), *(p_spsBuf+3), 3); + } + m_frameSize = 1024; + m_delay_samples = 1024; + if(tags) yang_MP4TagsFree(tags); + tags=NULL; + + +} +void YangMp4File::WriteVideoInfo(uint8_t *p_vpsBuf,int32_t p_vpsLen,uint8_t *p_spsBuf, int32_t p_spsLen,uint8_t *p_ppsBuf, int32_t p_ppsLen) { + //for(int32_t i=0;ivideoEncoderType==1){ + //MP4AddH265VideoParameterSet + //MP4SetVideoProfileLevel + // yang_MP4SetVideoProfileLevel(m_MP4hFile, *(p_spsBuf));//0x7f); + //printf("\n****************MP4AddH265VideoParameterSet**************************\n");0x08 + + yang_MP4SetVideoProfileLevel(m_MP4hFile, 0x08);//0x7f); + yang_MP4AddH265VideoParameterSet(m_MP4hFile, m_mp4Videotrack, p_vpsBuf,p_vpsLen); + yang_MP4AddH265SequenceParameterSet(m_MP4hFile, m_mp4Videotrack, p_spsBuf,p_spsLen); + yang_MP4AddH265PictureParameterSet(m_MP4hFile, m_mp4Videotrack, p_ppsBuf, p_ppsLen); + yang_MP4SetTrackTimeScale(m_MP4hFile, m_mp4Videotrack,90000); + //printf("\nvpsLen=%d,spsLen=%d,ppsLen=%d",p_vpsLen,p_spsLen,p_ppsLen); + + }else{ + yang_MP4SetVideoProfileLevel(m_MP4hFile, *(p_spsBuf+1));//0x7f); + yang_MP4AddH264SequenceParameterSet(m_MP4hFile, m_mp4Videotrack, p_spsBuf,p_spsLen); + yang_MP4AddH264PictureParameterSet(m_MP4hFile, m_mp4Videotrack, p_ppsBuf, p_ppsLen); + } + //printf("\n1****************timescale====%d**************************\n",yang_MP4GetTrackTimeScale(m_MP4hFile, m_mp4Videotrack)); + +} +void YangMp4File::WriteAudioInfo(uint8_t *pasc, unsigned long pasclen,uint8_t *buf1, int32_t buflen) { + yang_MP4SetAudioProfileLevel(m_MP4hFile, 0x0f); + yang_MP4SetTrackESConfiguration(m_MP4hFile, m_mp4Audiotrack, pasc, pasclen); +} +int32_t YangMp4File::WriteAudioPacket(YangFrame* audioFrame) { + yang_MP4WriteSample(m_MP4hFile, m_mp4Audiotrack, audioFrame->payload, audioFrame->nb, -1, 0, 0); + m_encoded_samples += m_frameSize; + return 1; +} + +int32_t YangMp4File::WriteVideoPacket(YangFrame* vidoeFrame) { + + yang_MP4WriteSample(m_MP4hFile, m_mp4Videotrack, vidoeFrame->payload, vidoeFrame->nb, vidoeFrame->timestamp, 0, 0); + + return 1; +} + +void YangMp4File::closeMp4() { + if (m_MP4hFile != NULL) + yang_MP4Close(m_MP4hFile, 0); + m_MP4hFile = NULL; +} diff --git a/libyangrtc2/src/yangrecord/YangMp4FileApp.cpp b/libyangrtc2/src/yangrecord/YangMp4FileApp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a5c49ac084f4cbd75b08a39c860ad3ea326ed94 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangMp4FileApp.cpp @@ -0,0 +1,80 @@ +/* + * YangRecordHandle.cpp + * + * Created on: 2020年10月4日 + * Author: yang + */ + +#include + +#include + + + +YangMp4FileApp::YangMp4FileApp(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc) { + m_audio=paudio; + m_video=pvideo; + m_encPara=penc; + m_enc=NULL; + m_rec=NULL; + m_isPause=0; +} + +YangMp4FileApp::~YangMp4FileApp() { + m_audio=NULL; + m_video=NULL; + m_enc=NULL; + yang_delete(m_enc); + yang_delete(m_rec); +} +void YangMp4FileApp::init(){ + + if(!m_enc) { + m_enc=new YangRecEncoder(m_audio,m_video,m_encPara); + m_enc->initAudioEncoder(); + m_enc->initVideoEncoder(); + //m_enc->setInAudioBuffer(m_cap->m_out_al); + //m_enc->setInVideoBuffer(m_cap->m_out_vl); + } + if(!m_rec) { + m_rec=new YangRecordMp4(m_audio,m_video,m_encPara); + m_rec->setInAudioBuffer(m_enc->getOutAudioBuffer()); + m_rec->setInVideoBuffer(m_enc->getOutVideoBuffer()); + } +} +void YangMp4FileApp::setFileTimeLen(int32_t ptlen_min){ + if(m_rec) m_rec->setFileTimeLen(ptlen_min); +} +void YangMp4FileApp::setInAudioBuffer(YangAudioBuffer *pbuf){ + if(m_enc) m_enc->setInAudioBuffer(pbuf); +} + void YangMp4FileApp::setInVideoBuffer(YangVideoBuffer *pbuf){ + if(m_enc) m_enc->setInVideoBuffer(pbuf); + } + void YangMp4FileApp::pauseRecord(){ + if(m_rec) m_rec->pauseRec(); + m_isPause=1; + } + void YangMp4FileApp::resumeRecord(){ + if(!m_isPause) return; + if(m_rec) m_rec->resumeRec(); + m_isPause=0; + } +void YangMp4FileApp::startRecordMp4(char *filename0,int32_t p_module,int32_t p_isMp4) +{ + + if(m_rec){ + m_rec->initPara(m_enc->getOutVideoMetaData(),filename0,1); + m_rec->start(); + + } + if(m_enc) { + m_enc->startAudioEncoder(); + m_enc->startVideoEncoder(); + } + +} +void YangMp4FileApp::stopRecordMp4(){ + m_rec->stop(); + yang_sleep(1); +} diff --git a/libyangrtc2/src/yangrecord/YangRecEncoder.cpp b/libyangrtc2/src/yangrecord/YangRecEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53fa99a6b327b40af38eac97cf9e7d4c46258a47 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecEncoder.cpp @@ -0,0 +1,108 @@ +/* + * YangEncoderBase.cpp + * + * Created on: 2019年10月11日 + * Author: yang + */ +#include +#include +//include + + +#include "pthread.h" +#include +#include +#include + + +YangRecEncoder::YangRecEncoder(YangAudioInfo *paudio, YangVideoInfo *pvideo, + YangVideoEncInfo *penc) { + m_ve=NULL; + m_ae=NULL; + m_audio = paudio; + m_video = pvideo; + m_enc = penc; + m_vmd = NULL; + m_out_videoBuffer = NULL; + m_out_auidoBuffer = NULL; + +} + +YangRecEncoder::~YangRecEncoder() { + if(m_ae) m_ae->stop(); + if(m_ve) m_ve->stop(); + if(m_ae){ + while(m_ae->m_isStart) yang_usleep(500); + } + if(m_ve){ + while(m_ve->m_isStart) yang_usleep(500); + } + yang_delete(m_ae); + yang_delete(m_ve); + m_audio = NULL; + m_video = NULL; + m_enc = NULL; + yang_free(m_vmd); + yang_delete(m_out_videoBuffer); //=NULL; + yang_delete(m_out_auidoBuffer); //=NULL; +} +YangVideoMeta* YangRecEncoder::getOutVideoMetaData() { + return m_vmd; +} + +void YangRecEncoder::initAudioEncoder() { + if (m_out_auidoBuffer == NULL) + m_out_auidoBuffer = new YangAudioEncoderBuffer(m_audio->audioCacheNum); + if (m_ae == NULL) { + // YangEncoderFactory yf; + m_ae = new YangAudioEncoderHandle(m_audio); + m_ae->setOutAudioBuffer(m_out_auidoBuffer); + m_ae->init(); + } + +} +void YangRecEncoder::initVideoEncoder() { + if (m_out_videoBuffer == NULL) + m_out_videoBuffer = new YangVideoEncoderBuffer(m_video->videoCacheNum); + if (m_vmd == NULL) + m_vmd = (YangVideoMeta*) calloc(1, sizeof(YangVideoMeta)); + YangEncoderFactory fac; + YangVideoEncoderMeta *yvh = fac.createVideoEncoderMeta(m_video); + yvh->yang_initVmd(m_vmd, m_video, m_enc); + yang_delete(yvh); + if (m_ve == NULL) { + // YangEncoderFactory yf; + m_ve = new YangVideoEncoderHandle(m_video, m_enc); + m_ve->setOutVideoBuffer(m_out_videoBuffer); + m_ve->init(); + m_ve->setVideoMetaData(m_vmd); + } +} +void YangRecEncoder::startAudioEncoder() { + if (m_ae && !m_ae->m_isStart) { + m_ae->start(); + yang_usleep(1000); + } +} +void YangRecEncoder::startVideoEncoder() { + if (m_ve && !m_ve->m_isStart) { + m_ve->start(); + yang_usleep(2000); + } +} +void YangRecEncoder::setInAudioBuffer(YangAudioBuffer *pbuf) { + if (m_ae != NULL) + m_ae->setInAudioBuffer(pbuf); +} +void YangRecEncoder::setInVideoBuffer(YangVideoBuffer *pbuf) { + //printf("\n.......................%u\n",m_ve); + if (m_ve != NULL) + m_ve->setInVideoBuffer(pbuf); +} +YangAudioEncoderBuffer* YangRecEncoder::getOutAudioBuffer() { + return m_out_auidoBuffer; +} +YangVideoEncoderBuffer* YangRecEncoder::getOutVideoBuffer() { + return m_out_videoBuffer; +} + diff --git a/libyangrtc2/src/yangrecord/YangRecord.cpp b/libyangrtc2/src/yangrecord/YangRecord.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39216b02015c45b3fd298daef12f2ebf99d5fec7 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecord.cpp @@ -0,0 +1,195 @@ +/* + * YangRecord.cpp + * + * Created on: 2020年10月11日 + * Author: yang + */ + +#include +#include +#include +#include +#include +#include + +YangRecord::YangRecord(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc) { + m_audio=paudio; + m_video=pvideo; + m_enc=penc; + videoDestLen = 0; + preVideotimestamp = 0; + minusStamp = 0; + oldalltick = 0, alltick = 0; + isMp4 = 1; + curVideoTimestamp = 0; + basestamp=0; + m_prePauseTime=0,m_afterPauseTime=0; + m_pauseTime=0; + m_fileId=0; + m_alltime=0; + m_alltime1=0; + m_fileTimeLen=3600; + m_isCreateNewFile=0; + memset(&m_mp4Para,0,sizeof(m_mp4Para)); + mp4 = NULL; + flv = NULL; + +} + +YangRecord::~YangRecord(void) { + m_audio=NULL; + m_video=NULL; + m_enc=NULL; + yang_free(m_mp4Para.fileName); + m_mp4Para.vmd=NULL; + yang_delete(mp4); + yang_delete(flv); +} + + +void YangRecord::writeAudioData(YangFrame* audioFrame) { + if (audioFrame->nb < 0 || audioFrame->nb > 1000) return; + if (isMp4){ + mp4->WriteAudioPacket(audioFrame); + } + else + flv->WriteAudioPacket(audioFrame); +} + + +void YangRecord::writeVideoData(YangFrame* videoFrame) { + if(m_alltime>m_fileTimeLen){ + m_isCreateNewFile=1; + m_alltime=0; + m_alltime1=0; + } + if(m_isCreateNewFile&&videoFrame->frametype){ + // int64_t t1=m_time.getMilliTick(); + createNewfile(); + // int64_t t2=m_time.getMilliTick()-t1; + // printf("\n**************************differ==================%lld",t2); + m_isCreateNewFile=0; + m_alltime=0; + m_alltime1=0; + } + if (basestamp == 0) basestamp = videoFrame->timestamp; + if (isMp4) { + alltick = (videoFrame->timestamp - basestamp-m_pauseTime) * 9 / 100; + //if(m_pauseTime) printf("%lld-%lld-%lld,",videoTimestamp,basestamp,m_pauseTime); + minusStamp = alltick - oldalltick; + m_alltime1+=minusStamp; + m_alltime=m_alltime1/90000; + //printf("v%lld,",videoTimestamp); + yang_put_be32((char*)videoFrame->payload,videoFrame->nb); + videoFrame->nb+=4; + videoFrame->timestamp=minusStamp; + mp4->WriteVideoPacket(videoFrame); + //oldalltick += minusStamp; + oldalltick=alltick; + } else { + curVideoTimestamp = (videoFrame->timestamp - basestamp-m_pauseTime) / 1000; + m_alltime=curVideoTimestamp/1000; + //curVideoTimestamp = (videoTimestamp - basestamp-m_pauseTime) / 100; + videoFrame->timestamp=curVideoTimestamp; + flv->WriteVideoPacket(videoFrame); + } + +} + + +void YangRecord::pauseRec(){ + m_prePauseTime=yang_get_milli_tick();//m_time.getMilliTick(); +} + void YangRecord::resumeRec(){ + + m_afterPauseTime=yang_get_milli_tick();//m_time.getMilliTick(); + m_pauseTime+=m_afterPauseTime-m_prePauseTime; + //printf("") + } + void YangRecord::initRecPara(){ + //videoTimestamp = 0; + //videoBufLen = 0; + preVideotimestamp = 0; + minusStamp = 0; + oldalltick = 0, alltick = 0; + curVideoTimestamp = 0; + basestamp=0; + m_prePauseTime=0,m_afterPauseTime=0; + m_pauseTime=0; + //if(m_in_audioBuffer) m_in_audioBuffer->resetIndex(); + //if(m_in_videoBuffer) m_in_videoBuffer->resetIndex(); + } + void YangRecord::createNewfile(){ + closeRec(); + char filename1[128]; + memset(filename1,0,128); + memcpy(filename1,m_mp4Para.fileName,strlen(m_mp4Para.fileName)-4); + m_fileId++; + char filename[255]; + memset(filename,0,255); + sprintf(filename,"%s_%d.%s",filename1,m_fileId,isMp4?"mp4":"flv"); + createFile(filename); + initRecPara(); + + } + void YangRecord::createFile(char* filename){ + if (isMp4) { + mp4 = new YangMp4File(filename, m_video); + mp4->init(m_mp4Para.vmd->mp4Meta.sps, m_mp4Para.vmd->mp4Meta.spsLen); + uint8_t pasc[1024]; + int32_t pasclen=0; + YangAudioEncoderMeta yem; + yem.createMeta(pasc,&pasclen); + memset(m_mp4Para.asc,0,10); + memcpy(m_mp4Para.asc,pasc,pasclen); + m_mp4Para.ascLen=pasclen; + //printf("\n*************************aselen==%d\n",pasclen); + //for(int32_t i=0;iWriteAudioInfo(pasc,pasclen,NULL, 0); + mp4->WriteVideoInfo(m_mp4Para.vmd->mp4Meta.vps, m_mp4Para.vmd->mp4Meta.vpsLen,m_mp4Para.vmd->mp4Meta.sps, m_mp4Para.vmd->mp4Meta.spsLen, + m_mp4Para.vmd->mp4Meta.pps, m_mp4Para.vmd->mp4Meta.ppsLen); + } else { + flv = new YangFlvWriter(filename, m_audio,m_video); + flv->framerate = m_video->frame; + flv->i_bitrate = (double)m_video->rate; + flv->i_level_idc = 31; + flv->Start(); + + flv->WriteVideoInfo(m_mp4Para.vmd->livingMeta.buffer, m_mp4Para.vmd->livingMeta.bufLen); + //flv->WriteAudioHeadPacket(); + + } + + } +void YangRecord::initPara(YangVideoMeta *p_vmd,char *filename, int32_t p_isMp4) { + //printf("\n*************filename===%s",filename); + isMp4 = p_isMp4; + m_mp4Para.vmd=p_vmd; + int32_t flen=strlen(filename); + m_mp4Para.fileName=(char*)malloc(flen+1); + memset(m_mp4Para.fileName,0,flen+1); + memcpy(m_mp4Para.fileName,filename,flen); + createFile(filename); + +} +void YangRecord::setFileTimeLen(int32_t ptlen_min){ + m_fileTimeLen=ptlen_min*60; +} +void YangRecord::closeRec() { + if (mp4 != NULL) { + mp4->closeMp4(); + printf("................mp4 is closed!\n"); + yang_delete(mp4); + } + if (flv != NULL) { + flv->Close(); + printf("................flv is closed!\n"); + yang_delete(flv); + } + +} + + + + diff --git a/libyangrtc2/src/yangrecord/YangRecordApp.cpp b/libyangrtc2/src/yangrecord/YangRecordApp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..acfd82da306cde4bda7bf3e6079f94aed21b4699 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecordApp.cpp @@ -0,0 +1,70 @@ +/* + * YangRecZbHandle.cpp + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#include +#include + +YangRecordApp::YangRecordApp(YangContext* pcontext) { + m_context=pcontext; + m_context->video.videoCacheNum*=2; + m_context->audio.audioCacheNum*=2; + m_cap=NULL; + m_rec=NULL; + +} + +YangRecordApp::~YangRecordApp() { + + yang_delete(m_cap); + yang_delete(m_rec); + m_context=NULL; +} + + +void YangRecordApp::init(){ + if(!m_cap){ + m_cap=new YangRecordCapture(m_context); + m_cap->initAudio(NULL); + m_cap->initVideo(); + m_cap->startAudioCapture(); + m_cap->startVideoCapture(); + } + if(!m_rec){ + m_rec=new YangMp4FileApp(&m_context->audio,&m_context->video,&m_context->enc); + m_rec->init(); + m_rec->setInAudioBuffer(m_cap->getOutAudioBuffer()); + m_rec->setInVideoBuffer(m_cap->getOutVideoBuffer()); + //m_rec->setFileTimeLen(1); + } +} +void YangRecordApp::pauseRecord(){ + if(m_cap) m_cap->startPauseCaptureState(); + if(m_rec) m_rec->pauseRecord(); +} +void YangRecordApp::resumeRecord(){ + if(m_rec) m_rec->resumeRecord(); + if(m_cap) m_cap->stopPauseCaptureState(); + +} +void YangRecordApp::recordFile(char* filename){ + m_rec->startRecordMp4(filename,1,1); + yang_sleep(1); + m_cap->startVideoCaptureState(); + m_cap->startAudioCaptureState(); +} +void YangRecordApp::stopRecord(){ + m_cap->stopAudioCaptureState(); + m_cap->stopVideoCaptureState(); + m_cap->m_audioCapture->stop(); + m_cap->m_videoCapture->stop(); + m_rec->m_enc->m_ae->stop(); + m_rec->m_enc->m_ve->stop(); + //m_rec->m_enc-> + yang_sleep(1); + + m_rec->stopRecordMp4(); +} diff --git a/libyangrtc2/src/yangrecord/YangRecordCapture.cpp b/libyangrtc2/src/yangrecord/YangRecordCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc7681b3c94f32849f941f34c2ceb03d785c369a --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecordCapture.cpp @@ -0,0 +1,341 @@ +/* + * YangCaptureBase.cpp + * + * Created on: 2019年10月11日 + * Author: yang + */ + +#include +//#include "yangavutil/video/YangMatImage.h" +//#include "yangavutil/vr/YangMatImageCv.h" +#include "yangavutil/video/YangYuvConvert.h" +#include "yangavutil/video/YangYuvUtil.h" +#include "yangavutil/video/YangBmp.h" +#include + +YangRecordCapture::YangRecordCapture(YangContext* pcontext) { + //m_audio = paudio; + //m_video = pvideo; + m_context=pcontext; + m_audioCapture = NULL; + m_videoCapture = NULL; + m_screenCapture = NULL; + + m_out_audioBuffer = NULL; + m_out_videoBuffer = NULL; + m_pre_videoBuffer = new YangVideoBuffer(m_context->video.width, m_context->video.height, m_context->video.videoEncoderFormat, + m_context->video.bitDepth == 8 ? 1 : 2); + m_vr_videoBuffer = NULL; + m_screen_videoBuffer = NULL; + m_pre_videoBuffer->isPreview = 1; + m_isStart = 0; + m_isConvert = 0; + m_isScreen = 0; + +} + +YangRecordCapture::~YangRecordCapture() { + if (m_audioCapture) + m_audioCapture->stop(); + if (m_videoCapture) + m_videoCapture->stop(); + + if (m_audioCapture) { + while (m_audioCapture->m_isStart) { + yang_usleep(1000); + } + } + if (m_videoCapture) { + while (m_videoCapture->m_isStart) { + yang_usleep(1000); + } + } + m_context=NULL; + yang_delete(m_pre_videoBuffer); + yang_delete(m_out_videoBuffer); + yang_delete(m_out_audioBuffer); + //yang_delete(m_aecPlay_al); + //yang_usleep(5000); + + yang_delete(m_audioCapture); + yang_delete(m_videoCapture); + +} +void YangRecordCapture::stop() { + stopLoop(); +} + +void YangRecordCapture::run() { + m_isStart = 1; + if (m_isScreen) + startScreenLoop(); + else + startVrLoop(); + m_isStart = 0; +} +void YangRecordCapture::stopLoop() { + m_isConvert = 0; +} + +void YangRecordCapture::startAudioCaptureState() { + m_audioCapture->setCatureStart(); +} +void YangRecordCapture::startVideoCaptureState() { + m_videoCapture->initstamp(); + m_videoCapture->setVideoCaptureStart(); +} +void YangRecordCapture::startPauseCaptureState() { + m_audioCapture->setCatureStop(); + m_videoCapture->setVideoCaptureStop(); + +} +void YangRecordCapture::stopPauseCaptureState() { + m_videoCapture->setVideoCaptureStart(); + m_audioCapture->setCatureStart(); +} +void YangRecordCapture::stopAudioCaptureState() { + m_audioCapture->setCatureStop(); +} +void YangRecordCapture::stopVideoCaptureState() { + m_videoCapture->setVideoCaptureStop(); + +} + +void YangRecordCapture::initAudio(YangPreProcess *pp) { + if (m_out_audioBuffer == NULL) { + if (m_context->audio.usingMono) + m_out_audioBuffer = new YangAudioBuffer(m_context->audio.audioCacheNum); + else + m_out_audioBuffer = new YangAudioBuffer(m_context->audio.audioCacheNum); + } + if (m_audioCapture == NULL) { + m_audioCapture = m_capture.createRecordAudioCapture(m_context); //.createAudioCapture(m_context);//new YangAudioCapture(m_context); + m_audioCapture->setPreProcess(pp); + m_audioCapture->setOutAudioBuffer(m_out_audioBuffer); + m_audioCapture->init(); + m_audioCapture->setCatureStop(); + } + stopAudioCaptureState(); +} +void YangRecordCapture::initVideo() { + if (m_out_videoBuffer == NULL) + m_out_videoBuffer = new YangVideoBuffer(m_context->video.width, m_context->video.height, + m_context->video.videoEncoderFormat, m_context->video.bitDepth == 8 ? 1 : 2); + if (m_videoCapture == NULL) { + m_videoCapture = m_capture.createVideoCapture(&m_context->video); //new YangVideoCapture(m_context); + m_videoCapture->setOutVideoBuffer(m_out_videoBuffer); + m_videoCapture->setPreVideoBuffer(m_pre_videoBuffer); + m_videoCapture->setVideoCaptureStart(); + m_videoCapture->init(); + } + stopVideoCaptureState(); +} +void YangRecordCapture::startAudioCapture() { + if (m_audioCapture && !m_audioCapture->m_isStart) + m_audioCapture->start(); +} +void YangRecordCapture::startVideoCapture() { + if (m_videoCapture && !m_videoCapture->m_isStart) + m_videoCapture->start(); +} +void YangRecordCapture::stopAudioCapture() { + if (m_audioCapture) + m_audioCapture->stop(); +} +void YangRecordCapture::stopVideoCapture() { + if (m_videoCapture) + m_videoCapture->stop(); +} +YangAudioBuffer* YangRecordCapture::getOutAudioBuffer() { + return m_out_audioBuffer; +} +YangVideoBuffer* YangRecordCapture::getOutVideoBuffer() { + return m_out_videoBuffer; +} + +YangVideoBuffer* YangRecordCapture::getPreVideoBuffer() { + return m_pre_videoBuffer; +} +void YangRecordCapture::setInAudioBuffer(vector *pbuf) { + if (m_audioCapture != NULL) + m_audioCapture->setInAudioBuffer(pbuf); +} +void YangRecordCapture::setAec(YangAecBase *paec) { + if (m_audioCapture) { + m_audioCapture->setAec(paec); + // if(m_aecPlay_al==NULL){ + // m_aecPlay_al=new YangAudioBuffer(m_audio->usingMono?640:4096,m_audio->audioCacheNum); + // if(paec!=NULL){ + // m_ac->setAec(paec); + // m_ac->setPlayAudoBuffer(m_aecPlay_al); + // paec->setPlayBuffer(m_aecPlay_al); + // } + // } + } +} +void YangRecordCapture::startVr(char *pbg) { + m_bgFileName = string(pbg); + if (m_vr_videoBuffer == NULL) + m_vr_videoBuffer = new YangVideoBuffer(m_context->video.width,m_context->video.height, + m_context->video.videoEncoderFormat, m_context->video.bitDepth == 8 ? 1 : 2); + if (m_videoCapture) { + m_videoCapture->setPreVideoBuffer(m_vr_videoBuffer); + m_videoCapture->setOutVideoBuffer(NULL); + } + yang_reindex(m_pre_videoBuffer); + yang_reindex(m_out_videoBuffer); + start(); +} + +void YangRecordCapture::stopVr() { + stop(); + yang_reindex(m_pre_videoBuffer); + yang_reindex(m_out_videoBuffer); + if (m_videoCapture) { + m_videoCapture->setPreVideoBuffer(m_pre_videoBuffer); + m_videoCapture->setOutVideoBuffer(m_out_videoBuffer); + } + +} + +void YangRecordCapture::startScreen() { + m_isScreen = 1; + if (m_screen_videoBuffer == NULL) + m_screen_videoBuffer = new YangVideoBuffer(m_context->video.width, + m_context->video.height, m_context->video.videoEncoderFormat, m_context->video.bitDepth == 8 ? 1 : 2); + if (m_videoCapture) { + m_videoCapture->setPreVideoBuffer(NULL); + m_videoCapture->setOutVideoBuffer(NULL); + } + + if (m_screenCapture) { + //m_screenCapture->setPreVideoBuffer(m_screen_videoBuffer); + //m_screenCapture->setOutVideoBuffer(m_screen_videoBuffer); + } + yang_reindex(m_pre_videoBuffer); + yang_reindex(m_screen_videoBuffer); + start(); +} +void YangRecordCapture::stopScreen() { + m_isScreen = 0; + if (m_videoCapture) { + m_videoCapture->setPreVideoBuffer(m_pre_videoBuffer); + m_videoCapture->setOutVideoBuffer(m_out_videoBuffer); + } +} + +void YangRecordCapture::startVrLoop() { + /** + printf("\n***************start vr..................."); + m_isConvert = 1; + int32_t inWidth = m_video->width; + int32_t inHeight = m_video->height; + //int32_t is12bits = m_video->videoCaptureFormat > 0 ? 1 : 0; + + //int64_t videoTimestamp = 0, + int64_t prestamp = 0; + //int64_t videoTimestamp1 = 0; + long az = inWidth * inHeight * 2; + uint8_t *srcData=new uint8_t[az];// { 0 }; + //if (is12bits) + az = inWidth * inHeight * 3 / 2; + + YangMatImageCv *mat = new YangMatImageCv(); //mf.getYangMatImage(); + + uint8_t *matDst=new uint8_t[m_video->width * m_video->height * 2]; + uint8_t *matSrcRgb=new uint8_t [m_video->width * m_video->height * 3]; + uint8_t *matSrcBgr=new uint8_t [m_video->width * m_video->height * 3]; + YangYuvConvert yuv; + + if (mat) + mat->initImg((char*) m_bgFileName.c_str(), m_video->width,m_video->height, 3); + //yang_rgbtobgr(mat->m_bkData, matSrcBgr, inWidth, inHeight); + //yuv.rgb24toI420(matSrcBgr, matDst, m_video->width, m_video->height); + //YangBmp bmp; + //bmp.create_bmpheader(inWidth,inHeight); + //yang_rgbtobgr(mat->m_bkData,matSrcBgr,inWidth,inHeight); + //bmp.save_bmp("/home/yang/test.bmp",(char*)matSrcBgr,inHeight*inWidth*3); + + // printf("\n***********************vr capture is starting...***********************\n"); + * + YangFrame videoFrame; +memset(&videoFrame,0,sizeof(YangFrame)); + while (m_isConvert == 1) { + if (mat) { + if (m_vr_videoBuffer->size() == 0) { + yang_usleep(1000); + continue; + } + videoFrame.payload=srcData; + videoFrame.nb=az; + m_vr_videoBuffer->getVideo(&videoFrame); + yuv.I420torgb24(srcData, matSrcRgb, inWidth, inHeight); + yang_rgbtobgr(matSrcRgb, matSrcBgr, inWidth, inHeight); + mat->matImage(matSrcBgr, matDst); + + } + if (videoFrame.timestamp - prestamp <= 0) { + prestamp = videoFrame.timestamp; + continue; + } + + prestamp = videoFrame.timestamp; + videoFrame.payload=matDst; + videoFrame.nb=az; + if (m_videoCapture->getVideoCaptureState()) m_out_videoBuffer->putVideo(&videoFrame); + m_pre_videoBuffer->putVideo(&videoFrame); + } + //if (videoTimestamp - prestamp <= 0) continue; + //prestamp = videoTimestamp; + + yang_delete(mat); + yang_deleteA(srcData); + yang_deleteA(matDst); + yang_deleteA(matSrcRgb); + yang_deleteA(matSrcBgr); + **/ +} +void YangRecordCapture::startScreenLoop() { + /** + + m_isConvert = 1; + int32_t inWidth = m_video->width; + int32_t inHeight = m_video->height; + //int32_t is12bits = m_video->videoCaptureFormat > 0 ? 1 : 0; + + int64_t videoTimestamp = 0, prestamp = 0; + //int64_t videoTimestamp1 = 0; + long az = inWidth * inHeight * 2; + uint8_t srcData[az] = { 0 }; + //if (is12bits) + az = inWidth * inHeight * 3 / 2; + + YangMatImageCv *mat = new YangMatImageCv(); //mf.getYangMatImage(); + uint8_t matDst[m_video->width * m_video->height * 2]; + YangYuvConvert yuv; + + while (m_isConvert == 1) { + + if (m_screen_videoBuffer->size() == 0) { + yang_usleep(1000); + continue; + } + m_screen_videoBuffer->getVideo(srcData, az, &videoTimestamp); + + if (videoTimestamp - prestamp <= 0) { + prestamp = videoTimestamp; + continue; + } + + prestamp = videoTimestamp; + + if (m_videoCapture->getVideoCaptureState()) + m_out_videoBuffer->putVideo(matDst, az, videoTimestamp); + m_pre_videoBuffer->putVideo(matDst, az, videoTimestamp); + } + //if (videoTimestamp - prestamp <= 0) continue; + //prestamp = videoTimestamp; + yang_delete(mat); + **/ +} + diff --git a/libyangrtc2/src/yangrecord/YangRecordHandle.cpp b/libyangrtc2/src/yangrecord/YangRecordHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4be5dece0c017b7730085f3cf7fbf064dbe5776d --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecordHandle.cpp @@ -0,0 +1,66 @@ +/* + * YangRecZbHandle.cpp + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#include +#include + +YangRecordHandle::YangRecordHandle(YangContext* pcontext) { + m_context=pcontext; + m_context->video.videoCacheNum*=2; + m_context->audio.audioCacheNum*=2; + m_cap=NULL; + m_rec=NULL; + +} + +YangRecordHandle::~YangRecordHandle() { + m_cap=NULL; + //yang_delete(m_cap); + yang_delete(m_rec); + m_context=NULL; +} + + +void YangRecordHandle::init(YangPushCapture* pcap){ + m_cap=pcap; + if(!m_rec){ + m_rec=new YangMp4FileApp(&m_context->audio,&m_context->video,&m_context->enc); + m_rec->init(); + m_rec->setInAudioBuffer(m_cap->getOutAudioBuffer()); + m_rec->setInVideoBuffer(m_cap->getOutVideoBuffer()); + //m_rec->setFileTimeLen(1); + } +} +/** +void YangRecordHandle::pauseRecord(){ + if(m_cap) m_cap->startPauseCaptureState(); + if(m_rec) m_rec->pauseRecord(); +} +void YangRecordHandle::resumeRecord(){ + if(m_rec) m_rec->resumeRecord(); + if(m_cap) m_cap->stopPauseCaptureState(); + +} + +**/ +void YangRecordHandle::recordFile(char* filename){ + m_rec->startRecordMp4(filename,1,1); + yang_sleep(1); + //m_cap->startVideoCaptureState(); + //m_cap->startAudioCaptureState(); +} +void YangRecordHandle::stopRecord(){ + m_cap->stopAudioCaptureState(); + m_cap->stopVideoCaptureState(); +// m_cap->stopAll(); + m_rec->m_enc->m_ae->stop(); + m_rec->m_enc->m_ve->stop(); + //m_rec->m_enc-> + yang_sleep(1); + + m_rec->stopRecordMp4(); +} diff --git a/libyangrtc2/src/yangrecord/YangRecordHandle.h b/libyangrtc2/src/yangrecord/YangRecordHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..d6509c42d39eaa6da8a1115f07e10caca334d26c --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecordHandle.h @@ -0,0 +1,33 @@ +/* + * YangRecZbHandle.h + * + * Created on: 2020年10月8日 + * Author: yang + */ + +#ifndef YANGRECORD_INCLUDE_YangRecordHandle_H_ +#define YANGRECORD_INCLUDE_YangRecordHandle_H_ +#include +#include +#include +#include + +class YangRecordHandle { +public: + YangRecordHandle(YangContext* pcontext); + virtual ~YangRecordHandle(); + YangPushCapture *m_cap; + YangMp4FileApp *m_rec; + void init(YangPushCapture* pcap); + void recordFile(char* filename); + void stopRecord(); + //void pauseRecord(); + //void resumeRecord(); + +private: + YangContext* m_context; + + +}; + +#endif /* YANGRECORD_INCLUDE_YangRecordHandle_H_ */ diff --git a/libyangrtc2/src/yangrecord/YangRecordMp4.cpp b/libyangrtc2/src/yangrecord/YangRecordMp4.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d324350b2776221bc852ba8836abf6d70f377ea8 --- /dev/null +++ b/libyangrtc2/src/yangrecord/YangRecordMp4.cpp @@ -0,0 +1,260 @@ +#include +#include +#include +#include "yangutil/sys/YangLog.h" +#include "time.h" +#include "yangutil/yang_unistd.h" +YangRecordMp4::YangRecordMp4(YangAudioInfo *paudio,YangVideoInfo *pvideo,YangVideoEncInfo *penc) { + m_audio=paudio; + m_video=pvideo; + m_enc=penc; + m_isConvert = 1; + m_isStart=0; + videoDestLen = 0; + frameType = 1; + //audioBufLen = 0; + m_videoTimestamp = 0; + //videoBufLen = 0; + m_preVideotimestamp = 0; + m_mp4Stamp = 0; + oldalltick = 0, alltick = 0; + isMp4 = 1; + curVideoTimestamp = 0; + m_startStamp=0; + m_prePauseTime=0,m_afterPauseTime=0; + m_pauseTime=0; + m_fileId=0; + m_alltime=0; + m_alltime1=0; + m_fileTimeLen=3600; + m_isCreateNewFile=0; + memset(&m_mp4Para,0,sizeof(m_mp4Para)); + srcVideoSource=NULL; + srcAudioSource=NULL; + m_in_audioBuffer=NULL; + m_in_videoBuffer=NULL; + mp4 = NULL; + flv = NULL; + memset(&m_audioFrame,0,sizeof(YangFrame)); + memset(&m_videoFrame,0,sizeof(YangFrame)); + +} + +YangRecordMp4::~YangRecordMp4(void) { + m_audio=NULL; + m_video=NULL; + m_enc=NULL; + yang_free(m_mp4Para.fileName); + m_mp4Para.vmd=NULL; + m_in_audioBuffer=NULL; + m_in_videoBuffer=NULL; + yang_deleteA(srcVideoSource); + yang_deleteA(srcAudioSource); + yang_delete(mp4); + yang_delete(flv); +} +void YangRecordMp4::stop() { + stopLoop(); +} + +void YangRecordMp4::run() { + m_isStart=1; + startLoop(); + m_isStart=0; +} +void YangRecordMp4::setInVideoBuffer(YangVideoEncoderBuffer *pbuf) { + m_in_videoBuffer = pbuf; +} +void YangRecordMp4::setInAudioBuffer(YangAudioEncoderBuffer *pbuf) { + m_in_audioBuffer = pbuf; +} + + +void YangRecordMp4::writeAudioData() { + + m_in_audioBuffer->getAudio(&m_audioFrame); +// printf("a%d,",audioBufLen); + if (m_audioFrame.nb < 0 || m_audioFrame.nb > 1000) return; + if (isMp4) + mp4->WriteAudioPacket(&m_audioFrame); + else + flv->WriteAudioPacket(&m_audioFrame); +} + +//int32_t tcou=0; +void YangRecordMp4::writeVideoData() { + m_videoFrame.payload=srcVideoSource+4; + m_in_videoBuffer->getEVideo(&m_videoFrame); + + m_videoTimestamp=m_videoFrame.timestamp; + if(m_alltime>m_fileTimeLen){ + m_isCreateNewFile=1; + m_alltime=0; + m_alltime1=0; + } + if(m_isCreateNewFile&&frameType){ + // int64_t t1=m_time.getMilliTick(); + createNewfile(); + m_isCreateNewFile=0; + m_alltime=0; + m_alltime1=0; + } + if (m_startStamp == 0) m_startStamp = m_videoTimestamp; + + if (isMp4) { + + alltick = (m_videoTimestamp - m_startStamp-m_pauseTime) * 9 / 100; + + m_mp4Stamp = alltick - oldalltick; + m_alltime1+=m_mp4Stamp; + m_alltime=m_alltime1/90000; + + yang_put_be32((char*)srcVideoSource,m_videoFrame.nb); + m_videoFrame.payload=srcVideoSource; + m_videoFrame.nb+=4; + m_videoFrame.timestamp=m_mp4Stamp; + + mp4->WriteVideoPacket(&m_videoFrame); + oldalltick=alltick; + } else { + curVideoTimestamp = (m_videoTimestamp - m_startStamp-m_pauseTime) / 1000; + m_alltime=curVideoTimestamp/1000; + m_videoFrame.payload=srcVideoSource; + m_videoFrame.timestamp=curVideoTimestamp; + //curVideoTimestamp = (videoTimestamp - basestamp-m_pauseTime) / 100; + flv->WriteVideoPacket(&m_videoFrame); + } + +} + + +void YangRecordMp4::pauseRec(){ + m_prePauseTime=yang_get_milli_tick(); +} + void YangRecordMp4::resumeRec(){ + + m_afterPauseTime=yang_get_milli_tick();//m_time.getMilliTick(); + m_pauseTime+=m_afterPauseTime-m_prePauseTime; + //printf("") + } + void YangRecordMp4::initRecPara(){ + m_preVideotimestamp = 0; + m_mp4Stamp = 0; + oldalltick = 0, alltick = 0; + curVideoTimestamp = 0; + m_startStamp=0; + m_prePauseTime=0,m_afterPauseTime=0; + m_pauseTime=0; + //if(m_in_audioBuffer) m_in_audioBuffer->resetIndex(); + //if(m_in_videoBuffer) m_in_videoBuffer->resetIndex(); + } + void YangRecordMp4::createNewfile(){ + closeRec(); + char filename1[256]; + memset(filename1,0,256); + memcpy(filename1,m_mp4Para.fileName,strlen(m_mp4Para.fileName)-4); + m_fileId++; + char filename[300]; + memset(filename,0,300); + sprintf(filename,"%s_%d.%s",filename1,m_fileId,isMp4?"mp4":"flv"); + createFile(filename); + initRecPara(); + + } + void YangRecordMp4::createFile(char* filename){ + if (isMp4) { + mp4 = new YangMp4File(filename, m_video); + mp4->init(m_mp4Para.vmd->mp4Meta.sps, m_mp4Para.vmd->mp4Meta.spsLen); + uint8_t pasc[1024]; + int32_t pasclen=0; + YangAudioEncoderMeta yem; + yem.createMeta(pasc,&pasclen); + memset(m_mp4Para.asc,0,10); + memcpy(m_mp4Para.asc,pasc,pasclen); + m_mp4Para.ascLen=pasclen; + mp4->WriteAudioInfo(pasc,pasclen,NULL, 0); + mp4->WriteVideoInfo(m_mp4Para.vmd->mp4Meta.vps, m_mp4Para.vmd->mp4Meta.vpsLen,m_mp4Para.vmd->mp4Meta.sps, m_mp4Para.vmd->mp4Meta.spsLen, + m_mp4Para.vmd->mp4Meta.pps, m_mp4Para.vmd->mp4Meta.ppsLen); + } else { + flv = new YangFlvWriter(filename, m_audio,m_video); + flv->framerate = m_video->frame; + flv->i_bitrate = (double)m_video->rate; + flv->i_level_idc = 31; + flv->Start(); + + flv->WriteVideoInfo(m_mp4Para.vmd->livingMeta.buffer, m_mp4Para.vmd->livingMeta.bufLen); + //flv->WriteAudioHeadPacket(); + + } + + } +void YangRecordMp4::initPara(YangVideoMeta *p_vmd,char *filename, int32_t p_isMp4) { + isMp4 = p_isMp4; + m_mp4Para.vmd=p_vmd; + int32_t flen=strlen(filename); + m_mp4Para.fileName=(char*)malloc(flen+1); + memset(m_mp4Para.fileName,0,flen+1); + memcpy(m_mp4Para.fileName,filename,flen); + createFile(filename); + +} +void YangRecordMp4::setFileTimeLen(int32_t ptlen_min){ + m_fileTimeLen=ptlen_min*60; +} +void YangRecordMp4::closeRec() { + if (mp4 != NULL) { + mp4->closeMp4(); + yang_trace("\n................mp4 is closed!\n"); + yang_delete(mp4); + } + if (flv != NULL) { + flv->Close(); + yang_trace("\n................flv is closed!\n"); + yang_delete(flv); + } + +} + + +void YangRecordMp4::startLoop() { + m_isConvert = 1; + + if(srcVideoSource==NULL) srcVideoSource=new uint8_t[512*1024]; + if(srcAudioSource==NULL) srcAudioSource=new uint8_t[2048]; + m_audioFrame.payload=srcAudioSource; + m_videoFrame.payload=srcVideoSource; + srcVideoSource[0]=0x00; + srcVideoSource[1]=0x00; + srcVideoSource[2]=0x00; + srcVideoSource[3]=0x01; + while (m_isConvert == 1) { + if (m_in_videoBuffer->size() > 5) { + yang_info("write cache big..%d\n", m_in_videoBuffer->size()); + } + if (m_in_videoBuffer->size() ==0 && m_in_audioBuffer->size() ==0) { + + yang_usleep(2000); + continue; + } + + + if(m_in_audioBuffer->size()>1) writeAudioData(); + if(m_in_videoBuffer->size()){ + writeVideoData(); + + } + + } + //while (m_in_videoBuffer->size()> 1 || m_in_audioBuffer->size() > 0) { + // writeAudioData(); + //writeVideoData(); + //} + + closeRec(); + +} +void YangRecordMp4::stopLoop() { + m_isConvert = 0; +} + + diff --git a/libyangrtc2/src/yangrtmp/YangInvokeBuffer.cpp b/libyangrtc2/src/yangrtmp/YangInvokeBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0510f8b008d1acbbae9b1992a89cf8c578206c03 --- /dev/null +++ b/libyangrtc2/src/yangrtmp/YangInvokeBuffer.cpp @@ -0,0 +1,69 @@ +/* + * InvokeList.cpp + * + * Created on: 2019年9月27日 + * Author: yang + */ + +#include + +#include "stddef.h" +#include "memory.h" +#include "malloc.h" +#define Yang_Invoke_len 512 + +YangInvokeBuffer::YangInvokeBuffer() { + index=0; + tmp=NULL; + tmp1=NULL; + a_len=Yang_Invoke_len; + pac_len=sizeof(RTMPPacket); + newIndex=0; + size=0; + m_cache_num=50; + //m_cache_num_cap=m_cache_num*a_len; + //memset(&vkpac,0,sizeof(VokePacket)); + //memset(&vkpac2,0,sizeof(VokePacket)); + cache=(char*)malloc((a_len)*m_cache_num); +} + +YangInvokeBuffer::~YangInvokeBuffer() { + // TODO Auto-generated destructor stub +} + +void YangInvokeBuffer::reset(){ + index=0; + newIndex=0; + size=0; + +} +void YangInvokeBuffer::resetIndex(){ + index=0; + newIndex=0; + size=0; +} +void YangInvokeBuffer::putPacket(RTMPPacket *pac) +{ + tmp=cache+(index*a_len); + index++; + memcpy(tmp,pac,pac_len); + // int32_t tlen= pac->m_nBodySize+RTMP_MAX_HEADER_SIZE; + // if(tlen+pac_len>Yang_Invoke_len){ + // printf("\nexcced.Error.................Invoke size....................%d\n",tlen); + // tlen=Yang_Invoke_len-pac_len; + // } + if(pac->m_body) memcpy(tmp+pac_len,pac->m_body,pac->m_nBodySize); + if(index==m_cache_num) index=0; + size++; +} + +void YangInvokeBuffer::getPacket(RTMPPacket *pac) +{ + tmp1=cache+(newIndex*a_len); + memcpy(pac,tmp1,pac_len); + if(pac->m_nBodySize>0) pac->m_body=tmp1+pac_len; + // memcpy(p-18,tmp1+pac_len,vkpac2.m_nBodySize+18); + newIndex++; + if(newIndex==m_cache_num) newIndex=0; + size=size-1; + } diff --git a/libyangrtc2/src/yangrtmp/YangRtmpBase.cpp b/libyangrtc2/src/yangrtmp/YangRtmpBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2d83a721dee4961f1c5c53c9d7d9aeecd85fed7 --- /dev/null +++ b/libyangrtc2/src/yangrtmp/YangRtmpBase.cpp @@ -0,0 +1,3329 @@ +/* + * YangLibRtmp.cpp + * + * Created on: 2019年9月2日 + * Author: yang + */ +#include "YangRtmpBase1.h" +//char *NetStatusEvent[4]={"NetConnection.Connect.Success","NetConnection.Connect.Failed","NetConnection.Connect.Closed","NetConnection.Connect.Rejected"}; + + +YangRtmpBase::YangRtmpBase() { + RTMP_ctrlC = 0; + r = NULL; + m_errState=Yang_Ok; +} +YangRtmpBase::~YangRtmpBase() { + RTMP_Close(); +} +void YangRtmpBase::RTMP_Close() { + if (r) { + CloseInternal(0); + free(r); + r = NULL; + } + //printf("\n***************RTMP_Close**************\n"); +} + + +AVal* YangRtmpBase::getPlayPath() { + return &r->Link.curPath; +} +int32_t YangRtmpBase::SendFCPublish() { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_FCPublish); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, getPlayPath()); + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::SendFCUnpublish() { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_FCUnpublish); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, getPlayPath()); + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendPublish() { + //printf("\n**********************SendPublish\n"); + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x04; /* source channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = r->m_stream_id; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_publish); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, getPlayPath()); + if (!enc) + return FALSE; + + + enc = AMF_EncodeString(enc, pend, &av_live); + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::RTMP_SendPause(int32_t DoPause, int32_t iTime) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x08; /* video channel */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_pause); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeBoolean(enc, pend, DoPause); + enc = AMF_EncodeNumber(enc, pend, (double) iTime); + + packet.m_nBodySize = enc - packet.m_body; + + yang_debug( "%s, %d, pauseTime=%d", __FUNCTION__, DoPause, + iTime); + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::RTMP_Pause(int32_t DoPause) { + if (DoPause) r->m_pauseStamp =r->m_mediaChannel < r->m_channelsAllocatedIn ?r->m_channelTimestamp[r->m_mediaChannel] : 0; + return RTMP_SendPause(DoPause, r->m_pauseStamp); +} + +int32_t YangRtmpBase::SendBytesReceived() { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + + packet.m_nChannel = 0x02; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_BYTES_READ_REPORT; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + packet.m_nBodySize = 4; + + AMF_EncodeInt32(packet.m_body, pend, r->m_nBytesIn); /* hard coded for now */ + r->m_nBytesInSent = r->m_nBytesIn; + + /*RTMP_Log(RTMP_LOGDEBUG, "Send bytes report. 0x%x (%d bytes)", (unsigned int)m_nBytesIn, m_nBytesIn); */ + return yangSendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendPlay() { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x08; /* we make 8 our stream channel */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = r->m_stream_id; /*0x01000000; */ + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_play); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + + yang_debug( "%s, seekTime=%d, stopTime=%d, sending play: %s", + __FUNCTION__, r->Link.seekTime, r->Link.stopTime, + getPlayPath()->av_val); + enc = AMF_EncodeString(enc, pend, getPlayPath()); + if (!enc) + return FALSE; + + /* Optional parameters start and len. + * + * start: -2, -1, 0, positive number + * -2: looks for a live stream, then a recorded stream, + * if not found any open a live stream + * -1: plays a live stream + * >=0: plays a recorded streams from 'start' milliseconds + */ + //if (r->Link.lFlags & RTMP_LF_LIVE) + enc = AMF_EncodeNumber(enc, pend, -1000.0); + /**else { + if (r->Link.seekTime > 0.0) + enc = AMF_EncodeNumber(enc, pend, r->Link.seekTime); // resume from here + else + enc = AMF_EncodeNumber(enc, pend, 0.0); //-2000.0); recorded as default, -2000.0 is not reliable since that freezes the player if the stream is not found + }**/ + if (!enc) + return FALSE; + + /* len: -1, 0, positive number + * -1: plays live or recorded stream to the end (default) + * 0: plays a frame 'start' ms away from the beginning + * >0: plays a live or recoded stream for 'len' milliseconds + */ + /*enc += EncodeNumber(enc, -1.0); *//* len */ + if (r->Link.stopTime) { + enc = AMF_EncodeNumber(enc, pend, r->Link.stopTime - r->Link.seekTime); + if (!enc) + return FALSE; + } + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::SendPlaylist() { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x08; /* we make 8 our stream channel */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = r->m_stream_id; /*0x01000000; */ + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_set_playlist); + enc = AMF_EncodeNumber(enc, pend, 0); + *enc++ = AMF_NULL; + *enc++ = AMF_ECMA_ARRAY; + *enc++ = 0; + *enc++ = 0; + *enc++ = 0; + *enc++ = AMF_OBJECT; + enc = AMF_EncodeNamedString(enc, pend, &av_0, getPlayPath()); + if (!enc) + return FALSE; + if (enc + 3 >= pend) + return FALSE; + *enc++ = 0; + *enc++ = 0; + *enc++ = AMF_OBJECT_END; + + packet.m_nBodySize = enc - packet.m_body; + printf("\n***********av_set_playlist..................."); + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::SendSecureTokenResponse(AVal *resp) { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_secureTokenResponse); + enc = AMF_EncodeNumber(enc, pend, 0.0); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, resp); + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} +/* + from http://jira.red5.org/confluence/display/docs/Ping: + + Ping is the most mysterious message in RTMP and till now we haven't fully interpreted it yet. In summary, Ping message is used as a special command that are exchanged between client and server. This page aims to document all known Ping messages. Expect the list to grow. + + The type of Ping packet is 0x4 and contains two mandatory parameters and two optional parameters. The first parameter is the type of Ping and in short integer. The second parameter is the target of the ping. As Ping is always sent in Channel 2 (control channel) and the target object in RTMP header is always 0 which means the Connection object, it's necessary to put an extra parameter to indicate the exact target object the Ping is sent to. The second parameter takes this responsibility. The value has the same meaning as the target object field in RTMP header. (The second value could also be used as other purposes, like RTT Ping/Pong. It is used as the timestamp.) The third and fourth parameters are optional and could be looked upon as the parameter of the Ping packet. Below is an unexhausted list of Ping messages. + + * type 0: Clear the stream. No third and fourth parameters. The second parameter could be 0. After the connection is established, a Ping 0,0 will be sent from server to client. The message will also be sent to client on the start of Play and in response of a Seek or Pause/Resume request. This Ping tells client to re-calibrate the clock with the timestamp of the next packet server sends. + * type 1: Tell the stream to clear the playing buffer. + * type 3: Buffer time of the client. The third parameter is the buffer time in millisecond. + * type 4: Reset a stream. Used together with type 0 in the case of VOD. Often sent before type 0. + * type 6: Ping the client from server. The second parameter is the current time. + * type 7: Pong reply from client. The second parameter is the time the server sent with his ping request. + * type 26: SWFVerification request + * type 27: SWFVerification response + */ +int32_t YangRtmpBase::RTMP_SendCtrl(short nType, uint32_t nObject, + uint32_t nTime) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + int32_t nSize; + char *buf; + + yang_debug( "sending ctrl. type: 0x%04x", + (unsigned short) nType); + + packet.m_nChannel = 0x02; /* control channel (ping) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_CONTROL; + packet.m_nTimeStamp = 0; /* RTMP_GetTime(); */ + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + switch (nType) { + case 0x03: + nSize = 10; + break; /* buffer time */ + case 0x1A: + nSize = 3; + break; /* SWF verify request */ + case 0x1B: + nSize = 44; + break; /* SWF verify response */ + default: + nSize = 6; + break; + } + + packet.m_nBodySize = nSize; + + buf = packet.m_body; + buf = AMF_EncodeInt16(buf, pend, nType); + + if (nType == 0x1B) { + } else if (nType == 0x1A) { + *buf = nObject & 0xff; + } else { + if (nSize > 2) + buf = AMF_EncodeInt32(buf, pend, nObject); + + if (nSize > 6) + buf = AMF_EncodeInt32(buf, pend, nTime); + } + + return sendPacket(&packet, FALSE); +} +//int32_t rtmpCou=0; +int32_t YangRtmpBase::RTMP_SendCtrlPong(short nType, char *p, int32_t len) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *buf; + packet.m_nChannel = 0x02; /* control channel (ping) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE;//RTMP_PACKET_SIZE_MEDIUM;//RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_CONTROL; + packet.m_nTimeStamp = 0; /* RTMP_GetTime(); */ + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + packet.m_nBodySize = 6; + buf = packet.m_body; + buf = AMF_EncodeInt16(buf, pend, nType); + memcpy(packet.m_body + 2, p, 4); +// printf("\n.................send pong......................\n"); + //if(rtmpCou==0) return 1; + //rtmpCou++; + //printf("\n.................send pong......................\n"); + //return sendPacket(&packet, FALSE); + return yangSendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendCheckBW() { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; /* RTMP_GetTime(); */ + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av__checkbw); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + + packet.m_nBodySize = enc - packet.m_body; + + /* triggers _onbwcheck and eventually results in _onbwdone */ + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::SendCheckBWResult(double txn) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0x16 * r->m_nBWCheckCounter; /* temp inc value. till we figure it out. */ + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av__result); + enc = AMF_EncodeNumber(enc, pend, txn); + *enc++ = AMF_NULL; + enc = AMF_EncodeNumber(enc, pend, (double) r->m_nBWCheckCounter++); + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendPong(double txn) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0x16 * r->m_nBWCheckCounter; /* temp inc value. till we figure it out. */ + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_pong); + enc = AMF_EncodeNumber(enc, pend, txn); + *enc++ = AMF_NULL; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::RTMP_SendSeek(int32_t iTime) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x08; /* video channel */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_seek); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeNumber(enc, pend, (double) iTime); + + packet.m_nBodySize = enc - packet.m_body; + + r->m_read.flags |= RTMP_READ_SEEKING; + r->m_read.nResumeTS = 0; + + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::RTMP_SendServerBW() { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + + packet.m_nChannel = 0x02; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_SERVER_BW; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + packet.m_nBodySize = 4; + + AMF_EncodeInt32(packet.m_body, pend, r->m_nServerBW); + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::RTMP_SendClientBW() { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + + packet.m_nChannel = 0x02; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_CLIENT_BW; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + packet.m_nBodySize = 5; + + AMF_EncodeInt32(packet.m_body, pend, r->m_nClientBW); + packet.m_body[4] = r->m_nClientBW2; + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::SendDeleteStream(double dStreamId) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_deleteStream); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeNumber(enc, pend, dStreamId); + + packet.m_nBodySize = enc - packet.m_body; + + /* no response expected */ + return sendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendCloseStream(double dStreamId) { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_closeStream); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeNumber(enc, pend, dStreamId); + + packet.m_nBodySize = enc - packet.m_body; + + /* no response expected */ + return sendPacket(&packet, FALSE); +} +int32_t YangRtmpBase::SendReleaseStream() { + //printf("\n******************SendReleaseStream=%s\n",getPlayPath()->av_val); + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; //RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_releaseStream); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, getPlayPath()); + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} + +/* Read from the stream until we get a media packet. + * Returns -3 if Play.Close/Stop, -2 if fatal error, -1 if no more media + * packets, 0 if ignorable error, >0 if there is a media packet + */ + +int32_t YangRtmpBase::sendPacket(RTMPPacket *packet, int32_t queue) { + const RTMPPacket *prevPacket; + uint32_t last = 0; + int32_t nSize; + int32_t hSize, cSize; + char *header, *hptr, *hend, hbuf[RTMP_MAX_HEADER_SIZE], c; + uint32_t t; + char *buffer; //, *tbuf = NULL, *toff = NULL; + int32_t nChunkSize; + //int32_t tlen; + + // @remark debug info by http://github.com/ossrs/srs + if (packet->m_packetType == 8 || packet->m_packetType == 9) { + //_srs_state = 3; + } + + if (packet->m_nChannel >= r->m_channelsAllocatedOut) { + int32_t n = packet->m_nChannel + 10; + RTMPPacket **packets = (RTMPPacket**) realloc(r->m_vecChannelsOut, + sizeof(RTMPPacket*) * n); + if (!packets) { + free(r->m_vecChannelsOut); + r->m_vecChannelsOut = NULL; + r->m_channelsAllocatedOut = 0; + return FALSE; + } + r->m_vecChannelsOut = packets; + memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, + sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut)); + r->m_channelsAllocatedOut = n; + } + + prevPacket = r->m_vecChannelsOut[packet->m_nChannel]; + if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE) { + + if (prevPacket->m_nBodySize + == packet->m_nBodySize&& prevPacket->m_packetType == packet->m_packetType + && packet->m_headerType == RTMP_PACKET_SIZE_MEDIUM) + packet->m_headerType = RTMP_PACKET_SIZE_SMALL; + + if (prevPacket->m_nTimeStamp + == packet->m_nTimeStamp&& packet->m_headerType == RTMP_PACKET_SIZE_SMALL) + packet->m_headerType = RTMP_PACKET_SIZE_MINIMUM; + last = prevPacket->m_nTimeStamp; + } + + if (packet->m_headerType > 3) { + yang_error( + "sanity failed!! trying to send header of type: 0x%02x.", + (uint8_t) packet->m_headerType); + return FALSE; + } + + nSize = packetSize[packet->m_headerType]; + hSize = nSize; + cSize = 0; + t = packet->m_nTimeStamp - last; + + if (packet->m_body) { + header = packet->m_body - nSize; + hend = packet->m_body; + } else { + header = hbuf + 6; + hend = hbuf + sizeof(hbuf); + } + + if (packet->m_nChannel > 319) + cSize = 2; + else if (packet->m_nChannel > 63) + cSize = 1; + if (cSize) { + header -= cSize; + hSize += cSize; + } + + if (t >= 0xffffff) { + header -= 4; + hSize += 4; + yang_warn( "Larger timestamp than 24-bit: 0x%x", t); + } + + hptr = header; + c = packet->m_headerType << 6; + switch (cSize) { + case 0: + c |= packet->m_nChannel; + break; + case 1: + break; + case 2: + c |= 1; + break; + } + *hptr++ = c; + if (cSize) { + int32_t tmp = packet->m_nChannel - 64; + *hptr++ = tmp & 0xff; + if (cSize == 2) + *hptr++ = tmp >> 8; + } + + if (nSize > 1) { + hptr = AMF_EncodeInt24(hptr, hend, t > 0xffffff ? 0xffffff : t); + } + + if (nSize > 4) { + hptr = AMF_EncodeInt24(hptr, hend, packet->m_nBodySize); + *hptr++ = packet->m_packetType; + } + + if (nSize > 8) + hptr += EncodeInt32LE(hptr, packet->m_nInfoField2); + + if (t >= 0xffffff) + hptr = AMF_EncodeInt32(hptr, hend, t); + + nSize = packet->m_nBodySize; + buffer = packet->m_body; + nChunkSize = r->m_outChunkSize; + + //yang_debug( "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket, nSize); + + while (nSize + hSize) { + int32_t wrote; + + if (nSize < nChunkSize) + nChunkSize = nSize; + + //yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) header, hSize); + // yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) buffer, nChunkSize); + wrote = WriteN(header, nChunkSize + hSize); + if (!wrote) + return FALSE; + nSize -= nChunkSize; + buffer += nChunkSize; + hSize = 0; + if (nSize > 0) { + header = buffer - 1; + hSize = 1; + if (cSize) { + header -= cSize; + hSize += cSize; + } + if (t >= 0xffffff) { + header -= 4; + hSize += 4; + } + *header = (0xc0 | c); + if (cSize) { + int32_t tmp = packet->m_nChannel - 64; + header[1] = tmp & 0xff; + if (cSize == 2) + header[2] = tmp >> 8; + } + if (t >= 0xffffff) { + char *extendedTimestamp = header + 1 + cSize; + AMF_EncodeInt32(extendedTimestamp, extendedTimestamp + 4, t); + } + } + } + + if (packet->m_packetType == RTMP_PACKET_TYPE_INVOKE) { + AVal method; + char *ptr; + ptr = packet->m_body + 1; + AMF_DecodeString(ptr, &method); + yang_debug( "Invoking %s", method.av_val); + + if (queue) { + int32_t txn; + ptr += 3 + method.av_len; + txn = (int) AMF_DecodeNumber(ptr); + AV_queue(&r->m_methodCalls, &r->m_numCalls, &method, txn); + } + } + + if (!r->m_vecChannelsOut[packet->m_nChannel]) + r->m_vecChannelsOut[packet->m_nChannel] = (RTMPPacket*) malloc( + sizeof(RTMPPacket)); + memcpy(r->m_vecChannelsOut[packet->m_nChannel], packet, sizeof(RTMPPacket)); + return TRUE; +} +int32_t YangRtmpBase::yangSendPacket(RTMPPacket *packet, int32_t queue) { + const RTMPPacket *prevPacket; + uint32_t last = 0; + int32_t nSize; + int32_t hSize, cSize; + char *header, *hptr, *hend, hbuf[RTMP_MAX_HEADER_SIZE], c; + uint32_t t; + char *buffer; //, *tbuf = NULL, *toff = NULL; + int32_t nChunkSize; + //int32_t tlen; + + // @remark debug info by http://github.com/ossrs/srs + if (packet->m_packetType == 8 || packet->m_packetType == 9) { + //_srs_state = 3; + } + + if (packet->m_nChannel >= r->m_channelsAllocatedOut) { + int32_t n = packet->m_nChannel + 10; + RTMPPacket **packets = (RTMPPacket**) realloc(r->m_vecChannelsOut, + sizeof(RTMPPacket*) * n); + if (!packets) { + free(r->m_vecChannelsOut); + r->m_vecChannelsOut = NULL; + r->m_channelsAllocatedOut = 0; + return FALSE; + } + r->m_vecChannelsOut = packets; + memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, + sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut)); + r->m_channelsAllocatedOut = n; + } + + prevPacket = r->m_vecChannelsOut[packet->m_nChannel]; + if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE) { + + //if (prevPacket->m_nBodySize == packet->m_nBodySize&& prevPacket->m_packetType == packet->m_packetType&& packet->m_headerType == RTMP_PACKET_SIZE_MEDIUM) + //packet->m_headerType = RTMP_PACKET_SIZE_SMALL; + //if (prevPacket->m_nTimeStamp== packet->m_nTimeStamp&& packet->m_headerType == RTMP_PACKET_SIZE_SMALL) + //packet->m_headerType = RTMP_PACKET_SIZE_MINIMUM; + last = prevPacket->m_nTimeStamp; + } + + if (packet->m_headerType > 3) { + yang_error( + "sanity failed!! trying to send header of type: 0x%02x.", + (uint8_t) packet->m_headerType); + return FALSE; + } + + nSize = packetSize[packet->m_headerType]; + hSize = nSize; + cSize = 0; + t = packet->m_nTimeStamp - last; + + if (packet->m_body) { + header = packet->m_body - nSize; + hend = packet->m_body; + } else { + header = hbuf + 6; + hend = hbuf + sizeof(hbuf); + } + + if (packet->m_nChannel > 319) + cSize = 2; + else if (packet->m_nChannel > 63) + cSize = 1; + if (cSize) { + header -= cSize; + hSize += cSize; + } + + if (t >= 0xffffff) { + header -= 4; + hSize += 4; + yang_warn( "Larger timestamp than 24-bit: 0x%x", t); + } + + hptr = header; + c = packet->m_headerType << 6; + switch (cSize) { + case 0: + c |= packet->m_nChannel; + break; + case 1: + break; + case 2: + c |= 1; + break; + } + *hptr++ = c; + if (cSize) { + int32_t tmp = packet->m_nChannel - 64; + *hptr++ = tmp & 0xff; + if (cSize == 2) + *hptr++ = tmp >> 8; + } + + if (nSize > 1) { + hptr = AMF_EncodeInt24(hptr, hend, t > 0xffffff ? 0xffffff : t); + } + + if (nSize > 4) { + hptr = AMF_EncodeInt24(hptr, hend, packet->m_nBodySize); + *hptr++ = packet->m_packetType; + } + + if (nSize > 8) + hptr += EncodeInt32LE(hptr, packet->m_nInfoField2); + + if (t >= 0xffffff) + hptr = AMF_EncodeInt32(hptr, hend, t); + + nSize = packet->m_nBodySize; + buffer = packet->m_body; + nChunkSize = r->m_outChunkSize; + + yang_debug( "%s: fd=%d, size=%d", __FUNCTION__, + r->m_sb.sb_socket, nSize); + + while (nSize + hSize) { + int32_t wrote; + + if (nSize < nChunkSize) + nChunkSize = nSize; + + // yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) header, hSize); + // yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) buffer, nChunkSize); + wrote = WriteN(header, nChunkSize + hSize); + if (!wrote) + return FALSE; + nSize -= nChunkSize; + buffer += nChunkSize; + hSize = 0; + if (nSize > 0) { + header = buffer - 1; + hSize = 1; + if (cSize) { + header -= cSize; + hSize += cSize; + } + if (t >= 0xffffff) { + header -= 4; + hSize += 4; + } + *header = (0xc0 | c); + if (cSize) { + int32_t tmp = packet->m_nChannel - 64; + header[1] = tmp & 0xff; + if (cSize == 2) + header[2] = tmp >> 8; + } + if (t >= 0xffffff) { + char *extendedTimestamp = header + 1 + cSize; + AMF_EncodeInt32(extendedTimestamp, extendedTimestamp + 4, t); + } + } + } + + if (packet->m_packetType == RTMP_PACKET_TYPE_INVOKE) { + AVal method; + char *ptr; + ptr = packet->m_body + 1; + AMF_DecodeString(ptr, &method); + yang_debug( "Invoking %s", method.av_val); + + if (queue) { + int32_t txn; + ptr += 3 + method.av_len; + txn = (int) AMF_DecodeNumber(ptr); + AV_queue(&r->m_methodCalls, &r->m_numCalls, &method, txn); + } + } + + if (!r->m_vecChannelsOut[packet->m_nChannel]) + r->m_vecChannelsOut[packet->m_nChannel] = (RTMPPacket*) malloc( + sizeof(RTMPPacket)); + memcpy(r->m_vecChannelsOut[packet->m_nChannel], packet, sizeof(RTMPPacket)); + return TRUE; +} + +int32_t YangRtmpBase::RTMP_Serve() { + return SHandShake(); +} + +int32_t YangRtmpBase::ReadN(char *buffer, int32_t n) { + if(!r) return 0; + int32_t nOriginalSize = n; + int32_t avail; + char *ptr; + + r->m_sb.sb_timedout = FALSE; + +#ifdef _DEBUG + memset(buffer, 0, n); +#endif + + // @remark debug info by http://github.com/ossrs/srs + //_srs_rbytes += n; + + ptr = buffer; + while (n > 0) { + int32_t nBytes = 0, nRead; + /**if (r->Link.protocol & RTMP_FEATURE_HTTP) { + int32_t refill = 0; + while (!r->m_resplen) { + int32_t ret; + if (r->m_sb.sb_size < 13 || refill) { + if (!r->m_unackd) + HTTP_Post(r, RTMPT_IDLE, "", 1); + if (RTMPSockBuf_Fill(this, &r->m_sb) < 1) { + if (!r->m_sb.sb_timedout){ + if(m_socketClose) (*m_socketClose)(1); + RTMP_Close(); + } + return 0; + } + } + if ((ret = HTTP_read(this, r, 0)) == -1) { + yang_debug( "%s, No valid HTTP response found", + __FUNCTION__); + RTMP_Close(); + return 0; + } else if (ret == -2) { + refill = 1; + } else { + refill = 0; + } + } + if (r->m_resplen && !r->m_sb.sb_size) + RTMPSockBuf_Fill(this, &r->m_sb); + avail = r->m_sb.sb_size; + if (avail > r->m_resplen) + avail = r->m_resplen; + } else {**/ + if(!r) return 0; + avail = r->m_sb.sb_size; + if (avail == 0) { + if (r&&RTMPSockBuf_Fill(&r->m_sb) < 1) { + if (r&&!r->m_sb.sb_timedout) { + //if (m_socketClose) m_socketClose->socketClose(1); //(*m_socketClose)(1); + yang_error( + "%s, failed to read RTMP packet.timeout,%d", + __FUNCTION__, r->m_sb.sb_socket); + handleError(ERROR_SOCKET_Timeout); + return 0; + //RTMP_Close(); + } + return 0; + } + if(!r) return 0; + avail = r->m_sb.sb_size; + } + //} + nRead = ((n < avail) ? n : avail); + if (nRead > 0) { + memcpy(ptr, r->m_sb.sb_start, nRead); + r->m_sb.sb_start += nRead; + r->m_sb.sb_size -= nRead; + nBytes = nRead; + r->m_nBytesIn += nRead; + if (r->m_bSendCounter + && r->m_nBytesIn + > (r->m_nBytesInSent + r->m_nClientBW / 10)) + if (!SendBytesReceived()) + return FALSE; + } + //yang_debug( "%s: %d bytes\n", __FUNCTION__, nBytes); + + if (nBytes == 0) { + yang_error( "%s, RTMP socket closed by peer", + __FUNCTION__); + /*goto again; */ + //if (m_socketClose) m_socketClose->socketClose(0); //(*m_socketClose)(0); + handleError(ERROR_SOCKET_Close); + break; + } + + // if (r->Link.protocol & RTMP_FEATURE_HTTP) r->m_resplen -= nBytes; + n -= nBytes; + ptr += nBytes; + } + + return nOriginalSize - n; +} + +int32_t YangRtmpBase::WriteN(const char *buffer, int32_t n) { + const char *ptr = buffer; + // @remark debug info by http://github.com/ossrs/srs + //_srs_sbytes += n; + + while (n > 0) { + int32_t nBytes; + nBytes = RTMPSockBuf_Send(&r->m_sb, ptr, n); + /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d\n", __FUNCTION__, nBytes); */ + if (nBytes < 0) { + int32_t sockerr = GetSockError(); + yang_error( "%s, RTMP send error %d (%d bytes)", + __FUNCTION__, sockerr, n); + + if (sockerr == EINTR && !RTMP_ctrlC) + continue; + //if (m_socketClose) m_socketClose->socketClose(2); //(*m_socketClose)(2); + + handleError(ERROR_SOCKET_Close_Wr); + //RTMP_Close(); + n = 1; + break; + } + + if (nBytes == 0) + break; + + n -= nBytes; + ptr += nBytes; + } + return n == 0; +} +int32_t YangRtmpBase::SendUsherToken(AVal *usherToken) { + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + yang_debug( "UsherToken: %s", usherToken->av_val); + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_NetStream_Authenticate_UsherToken); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, usherToken); + + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, FALSE); +} + +int32_t YangRtmpBase::RTMP_SendCreateStream() { + RTMPPacket packet; + char pbuf[256], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_createStream); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; /* NULL */ + + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::SendFCSubscribe(AVal *subscribepath) { + //printf("\n*******SendFCSubscribe***********\n"); + RTMPPacket packet; + char pbuf[512], *pend = pbuf + sizeof(pbuf); + char *enc; + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + yang_debug( "FCSubscribe: %s", subscribepath->av_val); + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_FCSubscribe); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, subscribepath); + + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + //printf("\n*******SendFCSubscribe***********\n"); + //yang_error( "FCSubscribe: %s", subscribepath->av_val); + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::add_addr_info(struct sockaddr_in *service, AVal *host, + int32_t port) { + char *hostname; + int32_t ret = TRUE; + if (host->av_val[host->av_len]) { + hostname = (char*) malloc(host->av_len + 1); + memcpy(hostname, host->av_val, host->av_len); + hostname[host->av_len] = '\0'; + } else { + hostname = host->av_val; + } + + service->sin_addr.s_addr = inet_addr(hostname); + if (service->sin_addr.s_addr == INADDR_NONE) { + struct hostent *host = gethostbyname(hostname); + if (host == NULL || host->h_addr== NULL) + { + yang_error( "Problem accessing the DNS. (addr: %s)", hostname); + ret = FALSE; + goto finish; + } + service->sin_addr = *(struct in_addr*) host->h_addr; + } + + service->sin_port = htons(port); + finish: if (hostname != host->av_val) + free(hostname); + return ret; +} +int32_t YangRtmpBase::SocksNegotiate() { + unsigned long addr; + struct sockaddr_in service; + memset(&service, 0, sizeof(struct sockaddr_in)); + + add_addr_info(&service, &r->Link.hostname, r->Link.port); + addr = htonl(service.sin_addr.s_addr); + + { + char packet[] = { 4, 1, /* SOCKS 4, connect */ + (r->Link.port >> 8) & 0xFF, (r->Link.port) & 0xFF, (char) (addr >> 24) + & 0xFF, (char) (addr >> 16) & 0xFF, (char) (addr >> 8) & 0xFF, + (char) addr & 0xFF, 0 }; /* NULL terminate */ + + WriteN(packet, sizeof packet); + + if (ReadN(packet, 8) != 8) + return FALSE; + + if (packet[0] == 0 && packet[1] == 90) { + return TRUE; + } else { + yang_error( "%s, SOCKS returned error code %d", + __FUNCTION__, packet[1]); + return FALSE; + } + } +} + +int32_t YangRtmpBase::RTMP_SetOpt(const AVal *opt, AVal *arg) { + int32_t i; + void *v; + + for (i = 0; options[i].name.av_len; i++) { + if (opt->av_len != options[i].name.av_len) + continue; + if (strcasecmp(opt->av_val, options[i].name.av_val)) + continue; + v = (char*) r + options[i].off; + switch (options[i].otype) { + case OPT_STR: { + AVal *aptr = (AVal*) v; + *aptr = *arg; + } + break; + case OPT_INT: { + long l = strtol(arg->av_val, NULL, 0); + *(int*) v = l; + } + break; + case OPT_BOOL: { + int32_t j, fl; + fl = *(int*) v; + for (j = 0; truth[j].av_len; j++) { + if (arg->av_len != truth[j].av_len) + continue; + if (strcasecmp(arg->av_val, truth[j].av_val)) + continue; + fl |= options[i].omisc; + break; + } + *(int*) v = fl; + } + break; + case OPT_CONN: + if (parseAMF(&r->Link.extras, arg, &r->Link.edepth)) + return FALSE; + break; + } + break; + } + if (!options[i].name.av_len) { + yang_error( "Unknown option %s", opt->av_val); + RTMP_OptUsage(); + return FALSE; + } + + return TRUE; +} + +void YangRtmpBase::HandleCtrl(const RTMPPacket *packet) { + short nType = -1; + uint32_t tmp; + if (packet->m_body && packet->m_nBodySize >= 2) + nType = AMF_DecodeInt16(packet->m_body); + //yang_debug( "%s, received ctrl. type: %d, len: %d", __FUNCTION__, nType, packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + if (packet->m_nBodySize >= 6) { + switch (nType) { + case 0: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream Begin %d", __FUNCTION__, + tmp); + break; + + case 1: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream EOF %d", __FUNCTION__, tmp); + if (r->m_pausing == 1) + r->m_pausing = 2; + break; + + case 2: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream Dry %d", __FUNCTION__, tmp); + break; + + case 4: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream IsRecorded %d", __FUNCTION__, + tmp); + break; + + case 6: /* server ping. reply with pong. */ + tmp = AMF_DecodeInt32(packet->m_body + 2); + // yang_debug( "%s, Ping %d", __FUNCTION__, tmp); + //printf("\n***len=%d**tmp=%u**nType=%hd\n",packet->m_nBodySize,tmp,nType); + //RTMP_SendCtrl(0x07, tmp, 0); + RTMP_SendCtrlPong(0x07, packet->m_body + 2, 4); + //RTMP_SendCtrl(0x07, tmp, tmp); + break; + + /* FMS 3.5 servers send the following two controls to let the client + * know when the server has sent a complete buffer. I.e., when the + * server has sent an amount of data equal to m_nBufferMS in duration. + * The server meters its output so that data arrives at the client + * in realtime and no faster. + * + * The rtmpdump program tries to set m_nBufferMS as large as + * possible, to force the server to send data as fast as possible. + * In practice, the server appears to cap this at about 1 hour's + * worth of data. After the server has sent a complete buffer, and + * sends this BufferEmpty message, it will wait until the play + * duration of that buffer has passed before sending a new buffer. + * The BufferReady message will be sent when the new buffer starts. + * (There is no BufferReady message for the very first buffer; + * presumably the Stream Begin message is sufficient for that + * purpose.) + * + * If the network speed is much faster than the data bitrate, then + * there may be long delays between the end of one buffer and the + * start of the next. + * + * Since usually the network allows data to be sent at + * faster than realtime, and rtmpdump wants to download the data + * as fast as possible, we use this RTMP_LF_BUFX hack: when we + * get the BufferEmpty message, we send a Pause followed by an + * Unpause. This causes the server to send the next buffer immediately + * instead of waiting for the full duration to elapse. (That's + * also the purpose of the ToggleStream function, which rtmpdump + * calls if we get a read timeout.) + * + * Media player apps don't need this hack since they are just + * going to play the data in realtime anyway. It also doesn't work + * for live streams since they obviously can only be sent in + * realtime. And it's all moot if the network speed is actually + * slower than the media bitrate. + */ + case 31: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream BufferEmpty %d", + __FUNCTION__, tmp); + if (!(r->Link.lFlags & RTMP_LF_BUFX)) + break; + if (!r->m_pausing) { + r->m_pauseStamp = + r->m_mediaChannel < r->m_channelsAllocatedIn ? + r->m_channelTimestamp[r->m_mediaChannel] : 0; + RTMP_SendPause( TRUE, r->m_pauseStamp); + r->m_pausing = 1; + } else if (r->m_pausing == 2) { + RTMP_SendPause( FALSE, r->m_pauseStamp); + r->m_pausing = 3; + } + break; + + case 32: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream BufferReady %d", + __FUNCTION__, tmp); + break; + + default: + tmp = AMF_DecodeInt32(packet->m_body + 2); + yang_debug( "%s, Stream xx %d", __FUNCTION__, tmp); + break; + } + + } + + if (nType == 0x1A) { + yang_debug( "%s, SWFVerification ping received: ", + __FUNCTION__); + if (packet->m_nBodySize > 2 && packet->m_body[2] > 0x01) { + yang_error( + "%s: SWFVerification Type %d request not supported! Patches welcome...", + __FUNCTION__, packet->m_body[2]); + } + + yang_error( + "%s: Ignoring SWFVerification request, no CRYPTO support!", + __FUNCTION__); + } +} + +void YangRtmpBase::freePacket(RTMPPacket *packet) { + RTMPPacket_Free(packet); +} + +int32_t YangRtmpBase::RTMP_ToggleStream() { + int32_t res; + + if (!r->m_pausing) { + if (RTMP_IsTimedout(r) && r->m_read.status == RTMP_READ_EOF) + r->m_read.status = 0; + + res = RTMP_SendPause( TRUE, r->m_pauseStamp); + if (!res) + return res; + + r->m_pausing = 1; + sleep(1); + } + res = RTMP_SendPause( FALSE, r->m_pauseStamp); + r->m_pausing = 3; + return res; +} + +void YangRtmpBase::RTMP_DeleteStream() { + if (r->m_stream_id < 0) + return; + + r->m_bPlaying = FALSE; + + SendDeleteStream(r->m_stream_id); + r->m_stream_id = -1; +} + +int32_t YangRtmpBase::readPacket(RTMPPacket *packet) { + uint8_t hbuf[RTMP_MAX_HEADER_SIZE] = { 0 }; + char *header = (char*) hbuf; + int32_t nSize, hSize, nToRead, nChunk; + int32_t didAlloc = FALSE; + int32_t extendedTimestamp; + + yang_debug( "%s: fd=%d", __FUNCTION__, r->m_sb.sb_socket); + + if (ReadN((char*) hbuf, 1) == 0) { + yang_error( "%s, failed to read RTMP packet header", + __FUNCTION__); + return FALSE; + } + + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + packet->m_nChannel = (hbuf[0] & 0x3f); + header++; + if (packet->m_nChannel == 0) { + if (ReadN((char*) &hbuf[1], 1) != 1) { + yang_error( + "%s, failed to read RTMP packet header 2nd byte", + __FUNCTION__); + return FALSE; + } + packet->m_nChannel = hbuf[1]; + packet->m_nChannel += 64; + header++; + } else if (packet->m_nChannel == 1) { + int32_t tmp; + if (ReadN((char*) &hbuf[1], 2) != 2) { + yang_error( + "%s, failed to read RTMP packet header 3nd byte", + __FUNCTION__); + return FALSE; + } + tmp = (hbuf[2] << 8) + hbuf[1]; + packet->m_nChannel = tmp + 64; + yang_debug( "%s, m_nChannel: %0x", __FUNCTION__, + packet->m_nChannel); + header += 2; + } + + nSize = packetSize[packet->m_headerType]; + + if (packet->m_nChannel >= r->m_channelsAllocatedIn) { + int32_t n = packet->m_nChannel + 10; + int32_t *timestamp = (int*) realloc(r->m_channelTimestamp, sizeof(int) * n); + RTMPPacket **packets = (RTMPPacket**) realloc(r->m_vecChannelsIn, + sizeof(RTMPPacket*) * n); + if (!timestamp) + free(r->m_channelTimestamp); + if (!packets) + free(r->m_vecChannelsIn); + r->m_channelTimestamp = timestamp; + r->m_vecChannelsIn = packets; + if (!timestamp || !packets) { + r->m_channelsAllocatedIn = 0; + return FALSE; + } + memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, + sizeof(int) * (n - r->m_channelsAllocatedIn)); + memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, + sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn)); + r->m_channelsAllocatedIn = n; + } + + if (nSize == RTMP_LARGE_HEADER_SIZE) + packet->m_hasAbsTimestamp = TRUE; + + else if (nSize < RTMP_LARGE_HEADER_SIZE) { + if (r->m_vecChannelsIn[packet->m_nChannel]) + memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel], sizeof(RTMPPacket)); + } + + nSize--; + + if (nSize > 0 && ReadN(header, nSize) != nSize) { + yang_error( + "%s, failed to read RTMP packet header. type: %x", __FUNCTION__, + (unsigned int) hbuf[0]); + return FALSE; + } + + hSize = nSize + (header - (char*) hbuf); + + if (nSize >= 3) { + packet->m_nTimeStamp = AMF_DecodeInt24(header); + + /*RTMP_Log(RTMP_LOGDEBUG, "%s, reading RTMP packet chunk on channel %x, headersz %i, timestamp %i, abs timestamp %i", __FUNCTION__, packet.m_nChannel, nSize, packet.m_nTimeStamp, packet.m_hasAbsTimestamp); */ + + if (nSize >= 6) { + packet->m_nBodySize = AMF_DecodeInt24(header + 3); + packet->m_nBytesRead = 0; + + if (nSize > 6) { + packet->m_packetType = header[6]; + + if (nSize == 11) + packet->m_nInfoField2 = DecodeInt32LE(header + 7); + } + } + } + + extendedTimestamp = packet->m_nTimeStamp == 0xffffff; + if (extendedTimestamp) { + if (ReadN(header + nSize, 4) != 4) { + yang_error( "%s, failed to read extended timestamp", + __FUNCTION__); + return FALSE; + } + packet->m_nTimeStamp = AMF_DecodeInt32(header + nSize); + hSize += 4; + } + + // RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)hbuf, hSize); + + if (packet->m_nBodySize > 0 && packet->m_body == NULL) { + if (!RTMPPacket_Alloc(packet, packet->m_nBodySize)) { + yang_debug( "%s, failed to allocate packet", + __FUNCTION__); + return FALSE; + } + didAlloc = TRUE; + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + } + + nToRead = packet->m_nBodySize - packet->m_nBytesRead; + nChunk = r->m_inChunkSize; + if (nToRead < nChunk) + nChunk = nToRead; + + /* Does the caller want the raw chunk? */ + if (packet->m_chunk) { + packet->m_chunk->c_headerSize = hSize; + memcpy(packet->m_chunk->c_header, hbuf, hSize); + packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead; + packet->m_chunk->c_chunkSize = nChunk; + } + + if (ReadN(packet->m_body + packet->m_nBytesRead, nChunk) != nChunk) { + yang_error( + "%s, failed to read RTMP packet body. len: %u", __FUNCTION__, + packet->m_nBodySize); + return FALSE; + } + + // RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)packet->m_body + packet->m_nBytesRead, nChunk); + + packet->m_nBytesRead += nChunk; + + /* keep the packet as ref for other packets on this channel */ + if (!r->m_vecChannelsIn[packet->m_nChannel]) + r->m_vecChannelsIn[packet->m_nChannel] = (RTMPPacket*) malloc( + sizeof(RTMPPacket)); + memcpy(r->m_vecChannelsIn[packet->m_nChannel], packet, sizeof(RTMPPacket)); + if (extendedTimestamp) { + r->m_vecChannelsIn[packet->m_nChannel]->m_nTimeStamp = 0xffffff; + } + + if (RTMPPacket_IsReady(packet)) { + /* make packet's timestamp absolute */ + if (!packet->m_hasAbsTimestamp) + packet->m_nTimeStamp += r->m_channelTimestamp[packet->m_nChannel]; /* timestamps seem to be always relative!! */ + + r->m_channelTimestamp[packet->m_nChannel] = packet->m_nTimeStamp; + + /* reset the data from the stored packet. we keep the header since we may use it later if a new packet for this channel */ + /* arrives and requests to re-use some info (small packet header) */ + r->m_vecChannelsIn[packet->m_nChannel]->m_body = NULL; + r->m_vecChannelsIn[packet->m_nChannel]->m_nBytesRead = 0; + r->m_vecChannelsIn[packet->m_nChannel]->m_hasAbsTimestamp = FALSE; /* can only be false if we reuse header */ + } else { + packet->m_body = NULL; /* so it won't be erased on free */ + } + + return TRUE; +} + +int32_t YangRtmpBase::yangReadPacket(RTMPPacket *packet, char *pszbody) { + //if(m_errState!=0) return 0; + uint8_t hbuf[RTMP_MAX_HEADER_SIZE] = { 0 }; + char *header = (char*) hbuf; + int32_t nSize, hSize, nToRead, nChunk; + //int32_t didAlloc = FALSE; + int32_t extendedTimestamp; + + // RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d", __FUNCTION__, r->m_sb.sb_socket); + + if (ReadN((char*) hbuf, 1) == 0) { + printf( "failed to read RTMP packet header\n"); + return FALSE; + } + + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + packet->m_nChannel = (hbuf[0] & 0x3f); + header++; + if (packet->m_nChannel == 0) { + if (ReadN((char*) &hbuf[1], 1) != 1) { + printf("%s, failed to read RTMP packet header 2nd byte\n",__FUNCTION__); + return FALSE; + } + packet->m_nChannel = hbuf[1]; + packet->m_nChannel += 64; + header++; + } else if (packet->m_nChannel == 1) { + int32_t tmp; + if (ReadN((char*) &hbuf[1], 2) != 2) { + printf("%s, failed to read RTMP packet header 3nd byte\n",__FUNCTION__); + return FALSE; + } + tmp = (hbuf[2] << 8) + hbuf[1]; + packet->m_nChannel = tmp + 64; + //yang_debug( "%s, m_nChannel: %0x", __FUNCTION__, packet->m_nChannel); + header += 2; + } + + nSize = packetSize[packet->m_headerType]; + + if (packet->m_nChannel >= r->m_channelsAllocatedIn) { + int32_t n = packet->m_nChannel + 10; + int32_t *timestamp = (int*) realloc(r->m_channelTimestamp, sizeof(int) * n); + RTMPPacket **packets = (RTMPPacket**) realloc(r->m_vecChannelsIn, + sizeof(RTMPPacket*) * n); + if (!timestamp) + free(r->m_channelTimestamp); + if (!packets) + free(r->m_vecChannelsIn); + r->m_channelTimestamp = timestamp; + r->m_vecChannelsIn = packets; + if (!timestamp || !packets) { + r->m_channelsAllocatedIn = 0; + printf("\n......m_channelsAllocatedIn error.....\n"); + return FALSE; + } + memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, + sizeof(int) * (n - r->m_channelsAllocatedIn)); + memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, + sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn)); + r->m_channelsAllocatedIn = n; + } + + if (nSize == RTMP_LARGE_HEADER_SIZE) /* if we get a full header the timestamp is absolute */ + packet->m_hasAbsTimestamp = TRUE; + + else if (nSize < RTMP_LARGE_HEADER_SIZE) { /* using values from the last message of this channel */ + if (r->m_vecChannelsIn[packet->m_nChannel]) + memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel], + sizeof(RTMPPacket)); + } + + nSize--; + + if (nSize > 0 && ReadN(header, nSize) != nSize) { + printf("%s, failed to read RTMP packet header. type: %x", __FUNCTION__, (unsigned int) hbuf[0]); + yang_error("%s, failed to read RTMP packet header. type: %x", __FUNCTION__, (unsigned int) hbuf[0]); + return FALSE; + } + + hSize = nSize + (header - (char*) hbuf); + + if (nSize >= 3) { + packet->m_nTimeStamp = AMF_DecodeInt24(header); + + /*RTMP_Log(RTMP_LOGDEBUG, "%s, reading RTMP packet chunk on channel %x, headersz %i, timestamp %i, abs timestamp %i", __FUNCTION__, packet.m_nChannel, nSize, packet.m_nTimeStamp, packet.m_hasAbsTimestamp); */ + + if (nSize >= 6) { + packet->m_nBodySize = AMF_DecodeInt24(header + 3); + packet->m_nBytesRead = 0; + + if (nSize > 6) { + packet->m_packetType = header[6]; + + if (nSize == 11) + packet->m_nInfoField2 = DecodeInt32LE(header + 7); + } + } + } + + extendedTimestamp = packet->m_nTimeStamp == 0xffffff; + if (extendedTimestamp) { + if (ReadN(header + nSize, 4) != 4) { + printf( "%s, failed to read extended timestamp",__FUNCTION__); + return FALSE; + } + packet->m_nTimeStamp = AMF_DecodeInt32(header + nSize); + hSize += 4; + } + + //RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)hbuf, hSize); + + if (packet->m_nBodySize > 0 && packet->m_body == NULL) { + if (packet->m_nBodySize > 256000){ + printf("\nread size too big..."); + return 1; + } + packet->m_body = pszbody; + //didAlloc = TRUE; + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + } + + nToRead = packet->m_nBodySize - packet->m_nBytesRead; + nChunk = r->m_inChunkSize; + if (nToRead < nChunk) + nChunk = nToRead; + + + if (packet->m_chunk) { + packet->m_chunk->c_headerSize = hSize; + memcpy(packet->m_chunk->c_header, hbuf, hSize); + packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead; + packet->m_chunk->c_chunkSize = nChunk; + } + + if (ReadN(packet->m_body + packet->m_nBytesRead, nChunk) != nChunk) { + printf("%s, failed to read RTMP packet body. len: %u", __FUNCTION__,packet->m_nBodySize); + return FALSE; + } + + //RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)packet->m_body + packet->m_nBytesRead, nChunk); + + packet->m_nBytesRead += nChunk; + + /* keep the packet as ref for other packets on this channel */ + if (!r->m_vecChannelsIn[packet->m_nChannel]) + r->m_vecChannelsIn[packet->m_nChannel] = (RTMPPacket*) malloc( + sizeof(RTMPPacket)); + memcpy(r->m_vecChannelsIn[packet->m_nChannel], packet, sizeof(RTMPPacket)); + if (extendedTimestamp) { + r->m_vecChannelsIn[packet->m_nChannel]->m_nTimeStamp = 0xffffff; + } + + if (RTMPPacket_IsReady(packet)) { + /* make packet's timestamp absolute */ + if (!packet->m_hasAbsTimestamp) + packet->m_nTimeStamp += r->m_channelTimestamp[packet->m_nChannel]; /* timestamps seem to be always relative!! */ + + r->m_channelTimestamp[packet->m_nChannel] = packet->m_nTimeStamp; + + /* reset the data from the stored packet. we keep the header since we may use it later if a new packet for this channel */ + /* arrives and requests to re-use some info (small packet header) */ + r->m_vecChannelsIn[packet->m_nChannel]->m_body = NULL; + r->m_vecChannelsIn[packet->m_nChannel]->m_nBytesRead = 0; + r->m_vecChannelsIn[packet->m_nChannel]->m_hasAbsTimestamp = FALSE; /* can only be false if we reuse header */ + } else { + packet->m_body = NULL; /* so it won't be erased on free */ + } + + return TRUE; +} +/** + int32_t YangRtmpLib::yangReadPacket(RTMPPacket *packet, char *pszbody) { + uint8_t hbuf[RTMP_MAX_HEADER_SIZE] = { 0 }; + char *header = (char*) hbuf; + int32_t nSize, hSize, nToRead, nChunk; + // int32_t didAlloc = FALSE; + int32_t extendedTimestamp; + + yang_debug( "%s: fd=%d", __FUNCTION__, r->m_sb.sb_socket); + + if (ReadN((char*) hbuf, 1) == 0) { + yang_error( "%s, failed to read RTMP packet header", + __FUNCTION__); + return FALSE; + } + //if(hbuf[0]==0x43) yang_error( "%s, read RTMP packet channel 3......",__FUNCTION__); + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + packet->m_nChannel = (hbuf[0] & 0x3f); + header++; + if (packet->m_nChannel == 0) { + if (ReadN((char*) &hbuf[1], 1) != 1) { + yang_error( + "%s, failed to read RTMP packet header 2nd byte", + __FUNCTION__); + return FALSE; + } + packet->m_nChannel = hbuf[1]; + packet->m_nChannel += 64; + header++; + } else if (packet->m_nChannel == 1) { + int32_t tmp; + if (ReadN((char*) &hbuf[1], 2) != 2) { + yang_error( + "%s, failed to read RTMP packet header 3nd byte", + __FUNCTION__); + return FALSE; + } + tmp = (hbuf[2] << 8) + hbuf[1]; + packet->m_nChannel = tmp + 64; + yang_debug( "%s, m_nChannel: %0x", __FUNCTION__, + packet->m_nChannel); + header += 2; + } else if (packet->m_nChannel == 2) { + if (packet->m_headerType == 0x03) { + packet->m_nBodySize = 6; + if (packet->m_body == NULL) { + packet->m_body = pszbody; + //didAlloc = TRUE; + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + } + if (ReadN(packet->m_body, 6) != 6) { + yang_error( + "%s, failed to read RTMP packet header. type: %x", + __FUNCTION__, (unsigned int) hbuf[0]); + return FALSE; + } + if (packet->m_body[1] == 0x06) { + packet->m_packetType = 0x04; + packet->m_nBytesRead = 6; + packet->m_nBodySize = 6; + } + return TRUE; + } + } else if (packet->m_nChannel == 3) { + //printf("\n%02x........................read Pakcet shareobject 3...............\n",hbuf[0]); + } + + nSize = packetSize[packet->m_headerType]; + + if (packet->m_nChannel >= r->m_channelsAllocatedIn) { + int32_t n = packet->m_nChannel + 10; + int32_t *timestamp = (int*) realloc(r->m_channelTimestamp, sizeof(int) * n); + RTMPPacket **packets = (RTMPPacket**) realloc(r->m_vecChannelsIn, + sizeof(RTMPPacket*) * n); + if (!timestamp) + free(r->m_channelTimestamp); + if (!packets) + free(r->m_vecChannelsIn); + r->m_channelTimestamp = timestamp; + r->m_vecChannelsIn = packets; + if (!timestamp || !packets) { + r->m_channelsAllocatedIn = 0; + return FALSE; + } + memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, + sizeof(int) * (n - r->m_channelsAllocatedIn)); + memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, + sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn)); + r->m_channelsAllocatedIn = n; + } + + if (nSize == RTMP_LARGE_HEADER_SIZE) {// if we get a full header the timestamp is absolute + packet->m_hasAbsTimestamp = TRUE; + + } else if (nSize < RTMP_LARGE_HEADER_SIZE) { // using values from the last message of this channel + //printf("%d-%d,",nSize,RTMP_LARGE_HEADER_SIZE); + if (packet->m_nChannel == 0x03 && packet->m_headerType == 0x01) { + packet->m_nBytesRead = 0; + packet->m_hasAbsTimestamp = FALSE; + if (r->m_vecChannelsIn[packet->m_nChannel]->m_body) + memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel], + sizeof(RTMPPacket)); + } else { + if (r->m_vecChannelsIn[packet->m_nChannel]) + memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel], + sizeof(RTMPPacket)); + } + } + + nSize--; + + if (nSize > 0 && ReadN(header, nSize) != nSize) { + yang_error( + "%s, failed to read RTMP packet header. type: %x", __FUNCTION__, + (unsigned int) hbuf[0]); + return FALSE; + } + hSize = nSize + (header - (char*) hbuf); + if (nSize >= 3) { + packet->m_nTimeStamp = AMF_DecodeInt24(header); + + //RTMP_Log(RTMP_LOGDEBUG, "%s, reading RTMP packet chunk on channel %x, headersz %i, timestamp %i, abs timestamp %i", __FUNCTION__, packet.m_nChannel, nSize, packet.m_nTimeStamp, packet.m_hasAbsTimestamp); + + if (nSize >= 6) { + packet->m_nBodySize = AMF_DecodeInt24(header + 3); + packet->m_nBytesRead = 0; + + if (nSize > 6) { + packet->m_packetType = header[6]; + + if (nSize == 11) + packet->m_nInfoField2 = DecodeInt32LE(header + 7); + } + } + } + + extendedTimestamp = packet->m_nTimeStamp == 0xffffff; + if (extendedTimestamp) { + if (ReadN(header + nSize, 4) != 4) { + yang_error( "%s, failed to read extended timestamp", + __FUNCTION__); + return FALSE; + } + packet->m_nTimeStamp = AMF_DecodeInt32(header + nSize); + hSize += 4; + } + + yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) hbuf, hSize); + + if (packet->m_nBodySize > 0 && packet->m_body == NULL) { + if (packet->m_nBodySize > 256000) + return 1; + packet->m_body = pszbody; + //didAlloc = TRUE; + packet->m_headerType = (hbuf[0] & 0xc0) >> 6; + } + + nToRead = packet->m_nBodySize - packet->m_nBytesRead; + nChunk = r->m_inChunkSize; + if (nToRead < nChunk) + nChunk = nToRead; + if (packet->m_nBodySize > 256000) + return 1; + // Does the caller want the raw chunk? + if (packet->m_chunk) { + packet->m_chunk->c_headerSize = hSize; + memcpy(packet->m_chunk->c_header, hbuf, hSize); + packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead; + packet->m_chunk->c_chunkSize = nChunk; + } + + if (ReadN(packet->m_body + packet->m_nBytesRead, nChunk) != nChunk) { + yang_error( + "%s, failed to read RTMP packet body. len: %u", __FUNCTION__, + packet->m_nBodySize); + return FALSE; + } + + yang_LogHexString(Yang_LOGDEBUG2, + (uint8_t*) packet->m_body + packet->m_nBytesRead, nChunk); + + packet->m_nBytesRead += nChunk; + + // keep the packet as ref for other packets on this channel + if (!r->m_vecChannelsIn[packet->m_nChannel]) + r->m_vecChannelsIn[packet->m_nChannel] = (RTMPPacket*) malloc( + sizeof(RTMPPacket)); + memcpy(r->m_vecChannelsIn[packet->m_nChannel], packet, sizeof(RTMPPacket)); + if (extendedTimestamp) { + r->m_vecChannelsIn[packet->m_nChannel]->m_nTimeStamp = 0xffffff; + } + + if (RTMPPacket_IsReady(packet)) { + //make packet's timestamp absolute + if (!packet->m_hasAbsTimestamp) + packet->m_nTimeStamp += r->m_channelTimestamp[packet->m_nChannel]; + + r->m_channelTimestamp[packet->m_nChannel] = packet->m_nTimeStamp; + + + r->m_vecChannelsIn[packet->m_nChannel]->m_body = NULL; + r->m_vecChannelsIn[packet->m_nChannel]->m_nBytesRead = 0; + r->m_vecChannelsIn[packet->m_nChannel]->m_hasAbsTimestamp = FALSE; + } else { + packet->m_body = NULL; + } + + // @remark debug info by http://github.com/ossrs/srs + if (packet->m_packetType == 8 || packet->m_packetType == 9) { + //_srs_state = 3; + } + + return TRUE; + }**/ +int32_t YangRtmpBase::HandShake(int32_t FP9HandShake) { + int32_t i; + uint32_t uptime, suptime; + int32_t bMatch; + char type; + char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf + 1; + char serversig[RTMP_SIG_SIZE]; + + clientbuf[0] = 0x03; /* not encrypted */ + + uptime = htonl(RTMP_GetTime()); + memcpy(clientsig, &uptime, 4); + + memset(&clientsig[4], 0, 4); + +#ifdef _DEBUG + for (i = 8; i < RTMP_SIG_SIZE; i++) + clientsig[i] = 0xff; +#else + for (i = 8; i < RTMP_SIG_SIZE; i++) + clientsig[i] = (char) (rand() % 256); +#endif + + if (!WriteN(clientbuf, RTMP_SIG_SIZE + 1)) + return FALSE; + + if (ReadN(&type, 1) != 1) /* 0x03 or 0x06 */ + return FALSE; + + yang_debug( "%s: Type Answer : %02X", __FUNCTION__, type); + + if (type != clientbuf[0]) + yang_warn( + "%s: Type mismatch: client sent %d, server answered %d", + __FUNCTION__, clientbuf[0], type); + + if (ReadN(serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) + return FALSE; + + /* decode server response */ + + memcpy(&suptime, serversig, 4); + suptime = ntohl(suptime); + + yang_debug( "%s: Server Uptime : %d", __FUNCTION__, suptime); + yang_debug( "%s: FMS Version : %d.%d.%d.%d", __FUNCTION__, + serversig[4], serversig[5], serversig[6], serversig[7]); + + /* 2nd part of handshake */ + if (!WriteN(serversig, RTMP_SIG_SIZE)) + return FALSE; + + if (ReadN(serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) + return FALSE; + + bMatch = (memcmp(serversig, clientsig, RTMP_SIG_SIZE) == 0); + if (!bMatch) { + yang_warn( "%s, client signature does not match!", + __FUNCTION__); + } + return TRUE; +} + +int32_t YangRtmpBase::SHandShake() { + int32_t i; + char serverbuf[RTMP_SIG_SIZE + 1], *serversig = serverbuf + 1; + char clientsig[RTMP_SIG_SIZE]; + uint32_t uptime; + int32_t bMatch; + + if (ReadN(serverbuf, 1) != 1) /* 0x03 or 0x06 */ + return FALSE; + + yang_debug( "%s: Type Request : %02X", __FUNCTION__, + serverbuf[0]); + + if (serverbuf[0] != 3) { + yang_error( "%s: Type unknown: client sent %02X", + __FUNCTION__, serverbuf[0]); + return FALSE; + } + + uptime = htonl(RTMP_GetTime()); + memcpy(serversig, &uptime, 4); + + memset(&serversig[4], 0, 4); +#ifdef _DEBUG + for (i = 8; i < RTMP_SIG_SIZE; i++) + serversig[i] = 0xff; +#else + for (i = 8; i < RTMP_SIG_SIZE; i++) + serversig[i] = (char) (rand() % 256); +#endif + + if (!WriteN(serverbuf, RTMP_SIG_SIZE + 1)) + return FALSE; + + if (ReadN(clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) + return FALSE; + + /* decode client response */ + + memcpy(&uptime, clientsig, 4); + uptime = ntohl(uptime); + + yang_debug( "%s: Client Uptime : %d", __FUNCTION__, uptime); + yang_debug( "%s: Player Version: %d.%d.%d.%d", __FUNCTION__, + clientsig[4], clientsig[5], clientsig[6], clientsig[7]); + + /* 2nd part of handshake */ + if (!WriteN(clientsig, RTMP_SIG_SIZE)) + return FALSE; + + if (ReadN(clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) + return FALSE; + + bMatch = (memcmp(serversig, clientsig, RTMP_SIG_SIZE) == 0); + if (!bMatch) { + yang_warn( "%s, client signature does not match!", + __FUNCTION__); + } + return TRUE; +} + +int32_t YangRtmpBase::RTMP_SendChunk(RTMPChunk *chunk) { + int32_t wrote; + char hbuf[RTMP_MAX_HEADER_SIZE]; + + yang_debug( "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket, chunk->c_chunkSize); + //yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) chunk->c_header, chunk->c_headerSize); + if (chunk->c_chunkSize) { + char *ptr = chunk->c_chunk - chunk->c_headerSize; + // yang_LogHexString(Yang_LOGDEBUG2, (uint8_t*) chunk->c_chunk, chunk->c_chunkSize); + /* save header bytes we're about to overwrite */ + memcpy(hbuf, ptr, chunk->c_headerSize); + memcpy(ptr, chunk->c_header, chunk->c_headerSize); + wrote = WriteN(ptr, chunk->c_headerSize + chunk->c_chunkSize); + memcpy(ptr, hbuf, chunk->c_headerSize); + } else + wrote = WriteN(chunk->c_header, chunk->c_headerSize); + return wrote; +} + +int32_t YangRtmpBase::RTMP_Write(const char *buf, int32_t size) { + RTMPPacket *pkt = &r->m_write; + char *pend, *enc; + int32_t s2 = size, ret, num; + + pkt->m_nChannel = 0x04; /* source channel */ + pkt->m_nInfoField2 = r->m_stream_id; + + while (s2) { + if (!pkt->m_nBytesRead) { + if (size < 11) { + /* FLV pkt too small */ + return 0; + } + + if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V') { + buf += 13; + s2 -= 13; + } + + pkt->m_packetType = *buf++; + pkt->m_nBodySize = AMF_DecodeInt24(buf); + buf += 3; + pkt->m_nTimeStamp = AMF_DecodeInt24(buf); + buf += 3; + pkt->m_nTimeStamp |= *buf++ << 24; + buf += 3; + s2 -= 11; + + if (((pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO + || pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) + && !pkt->m_nTimeStamp) + || pkt->m_packetType == RTMP_PACKET_TYPE_INFO) { + pkt->m_headerType = RTMP_PACKET_SIZE_LARGE; + if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO) + pkt->m_nBodySize += 16; + } else { + pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM; + } + + if (!RTMPPacket_Alloc(pkt, pkt->m_nBodySize)) { + yang_debug( "%s, failed to allocate packet", + __FUNCTION__); + return FALSE; + } + enc = pkt->m_body; + pend = enc + pkt->m_nBodySize; + if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO) { + enc = AMF_EncodeString(enc, pend, &av_setDataFrame); + pkt->m_nBytesRead = enc - pkt->m_body; + } + } else { + enc = pkt->m_body + pkt->m_nBytesRead; + } + num = pkt->m_nBodySize - pkt->m_nBytesRead; + if (num > s2) + num = s2; + memcpy(enc, buf, num); + pkt->m_nBytesRead += num; + s2 -= num; + buf += num; + if (pkt->m_nBytesRead == pkt->m_nBodySize) { + ret = sendPacket(pkt, FALSE); + RTMPPacket_Free(pkt); + pkt->m_nBytesRead = 0; + if (!ret) + return -1; + buf += 4; + s2 -= 4; + if (s2 < 0) + break; + + } + + } + return size + s2; +} + +void YangRtmpBase::RTMP_Init() { + +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD(2,2);//create 16bit data + if(WSAStartup(wVersionRequested,&wsaData)!=0) + { + yang_error("Load WinSock Failed!"); + exit(1); + return; + } +#endif + memset(r, 0, sizeof(RTMP)); + r->m_sb.sb_socket = -1; + r->m_inChunkSize = RTMP_DEFAULT_CHUNKSIZE; + r->m_outChunkSize = RTMP_DEFAULT_CHUNKSIZE; + r->m_nBufferMS = 0; + r->m_nClientBW = 2500000; + r->m_nClientBW2 = 2; + r->m_nServerBW = 2500000; + r->m_fAudioCodecs = 3191.0; + r->m_fVideoCodecs = 252.0; + r->Link.timeout = 30; + r->Link.swfAge = 30; + + memset(&r->netStatus, 0, sizeof(struct YangNetStatus)); + r->m_numInvokes = 0; + // @remark debug info by http://github.com/ossrs/srs + //_srs_state = 1; +} + +int32_t YangRtmpBase::initConnect(RTMPPacket *cp) { + struct sockaddr_in service; + //printf("\n****************RTMP_Connect************1\n"); + if (!r->Link.hostname.av_len) + return ERROR_SOCKET; + + memset(&service, 0, sizeof(struct sockaddr_in)); + service.sin_family = AF_INET; + //printf("\n****************RTMP_Connect************2\n"); + //if (r->Link.socksport) { + /* Connect via SOCKS */ + //if (!add_addr_info(&service, &r->Link.sockshost, r->Link.socksport)) + // return FALSE; + //} else { + /* Connect directly */ + //if (!add_addr_info(&service, &r->Link.hostname, r->Link.port)) + //return FALSE; + //} + add_addr_info(&service, &r->Link.hostname, r->Link.port); + if (!RTMP_Connect0((struct sockaddr*) &service)) + return ERROR_CONNECT_Fail; + + r->m_bSendCounter = TRUE; + //printf("\n****************RTMP_Connect************3\n"); + if(RTMP_Connect1(cp)) return Yang_Ok; + return ERROR_CONNECT_Fail; +} +void YangRtmpBase::handleError(int32_t perrCode){ + m_errState=perrCode; +} +int32_t YangRtmpBase::RTMP_Connect0(struct sockaddr *service) { + int32_t on = 1; + r->m_sb.sb_timedout = FALSE; + r->m_pausing = 0; + r->m_fDuration = 0.0; + r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (r->m_sb.sb_socket != -1) { + if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0) { + int32_t err = GetSockError(); + yang_error( "%s, failed to connect socket. %d (%s)", + __FUNCTION__, err, strerror(err)); + handleError(ERROR_SOCKET); + //RTMP_Close(); + return FALSE; + } + + if (r->Link.socksport) { + yang_debug( "%s ... SOCKS negotiation", + __FUNCTION__); + if (!SocksNegotiate()) { + yang_error( "%s, SOCKS negotiation failed.", + __FUNCTION__); + handleError(ERROR_SOCKET_Negotiation); + //RTMP_Close(); + return FALSE; + } + } + } else { + // RTMP_Log(RTMP_LOGERROR, "%s, failed to create socket. Error: %d", __FUNCTION__, + //GetSockError()); + return FALSE; + } + + /* set timeout */ + //{ + SET_RCVTIMEO(tv, r->Link.timeout); + if (setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &tv, + sizeof(tv))) { + yang_error( "%s, Setting socket timeout to %ds failed!", + __FUNCTION__, r->Link.timeout); + } + //} + + setsockopt(r->m_sb.sb_socket, IPPROTO_TCP, TCP_NODELAY, (char*) &on, + sizeof(on)); + + // @remark debug info by http://github.com/ossrs/srs + //_srs_state = 2; + + return TRUE; +} +int32_t YangRtmpBase::RTMP_Connect1(RTMPPacket *cp) { + //printf("\n****************RTMP_Connect1************\n"); + yang_debug( "%s, ... connected, handshaking", __FUNCTION__); + if (!HandShake( TRUE)) { + yang_error( "%s, handshake failed.", __FUNCTION__); + handleError(ERROR_CONNECT_Handshaked); + //RTMP_Close(); + return FALSE; + } + yang_debug( "%s, handshaked", __FUNCTION__); + + if (!SendConnectPacket(cp)) { + yang_error( "%s, RTMP connect failed.", __FUNCTION__); + handleError(ERROR_CONNECT_Fail); + //RTMP_Close(); + return FALSE; + } + return TRUE; +} +int32_t YangRtmpBase::SendConnectPacket(RTMPPacket *cp) { + + RTMPPacket packet; + char pbuf[4096], *pend = pbuf + sizeof(pbuf); + char *enc; + + if (cp) + return sendPacket(cp, TRUE); + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_LARGE; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_connect); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_OBJECT; + + enc = AMF_EncodeNamedString(enc, pend, &av_app, &r->Link.app); + if (!enc) + return FALSE; + if (r->m_isPublish) { + enc = AMF_EncodeNamedString(enc, pend, &av_type, &av_nonprivate); + if (!enc) + return FALSE; + } + if (r->Link.flashVer.av_len) { + enc = AMF_EncodeNamedString(enc, pend, &av_flashVer, &r->Link.flashVer); + if (!enc) + return FALSE; + } + if (r->Link.swfUrl.av_len) { + enc = AMF_EncodeNamedString(enc, pend, &av_swfUrl, &r->Link.swfUrl); + if (!enc) + return FALSE; + } + if (r->Link.tcUrl.av_len) { + enc = AMF_EncodeNamedString(enc, pend, &av_tcUrl, &r->Link.tcUrl); + if (!enc) + return FALSE; + } + if (!(r->m_isPublish)) { + enc = AMF_EncodeNamedBoolean(enc, pend, &av_fpad, FALSE); + if (!enc) + return FALSE; + enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0); + if (!enc) + return FALSE; + enc = AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, + r->m_fAudioCodecs); + if (!enc) + return FALSE; + enc = AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, + r->m_fVideoCodecs); + if (!enc) + return FALSE; + enc = AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0); + if (!enc) + return FALSE; + if (r->Link.pageUrl.av_len) { + enc = AMF_EncodeNamedString(enc, pend, &av_pageUrl, + &r->Link.pageUrl); + if (!enc) + return FALSE; + } + } + if (r->m_fEncoding != 0.0 || r->m_bSendEncoding) { /* AMF0, AMF3 not fully supported yet */ + enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, + r->m_fEncoding); + if (!enc) + return FALSE; + } + if (enc + 3 >= pend) + return FALSE; + *enc++ = 0; + *enc++ = 0; /* end of object - 0x00 0x00 0x09 */ + *enc++ = AMF_OBJECT_END; + + /* add auth string */ + if (r->Link.auth.av_len) { + enc = AMF_EncodeBoolean(enc, pend, r->Link.lFlags & RTMP_LF_AUTH); + if (!enc) + return FALSE; + enc = AMF_EncodeString(enc, pend, &r->Link.auth); + if (!enc) + return FALSE; + } + if (r->Link.extras.o_num) { + int32_t i; + for (i = 0; i < r->Link.extras.o_num; i++) { + enc = AMFProp_Encode(&r->Link.extras.o_props[i], enc, pend); + if (!enc) + return FALSE; + } + } + packet.m_nBodySize = enc - packet.m_body; + + return sendPacket(&packet, TRUE); +} + +int32_t YangRtmpBase::clientPacket(RTMPPacket *packet) { + //if(packet->m_packetType>0x04) printf("\n..................packetType=%02x\n",packet->m_packetType); + int32_t bHasMediaPacket = 0; + switch (packet->m_packetType) { + case RTMP_PACKET_TYPE_CHUNK_SIZE: + /* chunk size */ + HandleChangeChunkSize(r, packet); + break; + + case RTMP_PACKET_TYPE_BYTES_READ_REPORT: + /* bytes read report */ + yang_debug( "%s, received: bytes read report", + __FUNCTION__); + break; + + case RTMP_PACKET_TYPE_CONTROL: + /* ctrl */ + HandleCtrl(packet); + break; + + case RTMP_PACKET_TYPE_SERVER_BW: + /* server bw */ + HandleServerBW( packet); + break; + + case RTMP_PACKET_TYPE_CLIENT_BW: + /* client bw */ + HandleClientBW(packet); + break; + + case RTMP_PACKET_TYPE_AUDIO: + /* audio data */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + HandleAudio(r, packet); + bHasMediaPacket = 1; + if (!r->m_mediaChannel) + r->m_mediaChannel = packet->m_nChannel; + if (!r->m_pausing) + r->m_mediaStamp = packet->m_nTimeStamp; + break; + + case RTMP_PACKET_TYPE_VIDEO: + /* video data */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + HandleVideo(r, packet); + bHasMediaPacket = 1; + if (!r->m_mediaChannel) + r->m_mediaChannel = packet->m_nChannel; + if (!r->m_pausing) + r->m_mediaStamp = packet->m_nTimeStamp; + break; + + case RTMP_PACKET_TYPE_FLEX_STREAM_SEND: + /* flex stream send */ + yang_debug( + "%s, flex stream send, size %u bytes, not supported, ignoring", + __FUNCTION__, packet->m_nBodySize); + break; + + case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT: + /* flex shared object */ + yang_error( + "%s, flex shared object, size %u bytes, not supported, ignoring", + __FUNCTION__, packet->m_nBodySize); + break; + + case RTMP_PACKET_TYPE_FLEX_MESSAGE: + /* flex message */ + { + yang_debug( + "%s, flex message, size %u bytes, not fully supported", + __FUNCTION__, packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + /* some DEBUG code */ +#if 0 + RTMP_LIB_AMFObject obj; + int32_t nRes = obj.Decode(packet.m_body+1, packet.m_nBodySize-1); + if(nRes < 0) { + yang_error( "%s, error decoding AMF3 packet", __FUNCTION__); + /*return; */ + } + + obj.Dump(); +#endif + //printf("\n************RTMP_PACKET_TYPE_FLEX_MESSAGE**************\n"); + if (HandleInvoke(packet->m_body + 1, packet->m_nBodySize - 1) == 1) + bHasMediaPacket = 2; + break; + } + case RTMP_PACKET_TYPE_INFO: + /* metadata (notify) */ + yang_debug( "%s, received: notify %u bytes", + __FUNCTION__, packet->m_nBodySize); + if (HandleMetadata(packet->m_body, packet->m_nBodySize)) + bHasMediaPacket = 1; + break; + + case RTMP_PACKET_TYPE_SHARED_OBJECT: + //if(m_handleShareObject!=NULL) (*m_handleShareObject)(packet->m_body, packet->m_nBodySize); + //if (m_shareobj) m_shareobj->parseSharedObject((uint8_t*)packet->m_body, packet->m_nBodySize); + //printf("%s, shared object",__FUNCTION__); + yang_debug( "%s, shared object", __FUNCTION__); + + break; + + case RTMP_PACKET_TYPE_INVOKE: + /* invoke */ + yang_debug( "%s, received: invoke %u bytes", + __FUNCTION__, packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + // @remark debug info by http://github.com/ossrs/srs + while (1) { + // String(_result) + char *p = packet->m_body; + int32_t nb = packet->m_nBodySize; + // Marker. + if (nb < 1) { + yang_error( "ignore string marker for nb=%d", + nb); + break; + } + AMFDataType t = (AMFDataType) p[0]; + if (t != AMF_STRING) { + //char ss[300]; + + yang_error( + "....ignore string marker for type=%d,len=%d,header=%d", + t, nb, packet->m_headerType); + //if(nb==21){ + //for(int32_t i=0;ip_type == AMF_OBJECT + || prop->p_type == AMF_ECMA_ARRAY) { + obj = prop->p_vu.p_object; + for (j = 0; j < obj.o_num; j++) { + prop = &obj.o_props[j]; + //if (AVMATCH(&prop->p_name, &_const_srs_server_ip)) { + // if (_srs_ip) { free(_srs_ip); } + // _srs_ip = (char*) malloc(prop->p_vu.p_aval.av_len + 1); + // memcpy(_srs_ip, prop->p_vu.p_aval.av_val,prop->p_vu.p_aval.av_len); _srs_ip[prop->p_vu.p_aval.av_len] = 0; + //} else if (AVMATCH(&prop->p_name, &_const_srs_pid)) { + // _srs_pid = (int) prop->p_vu.p_number; + //} else if (AVMATCH(&prop->p_name, &_const_srs_cid)) { + // _srs_cid = (int) prop->p_vu.p_number; + //} + } + break; + } + } + + // Print32_t info.RTMP_LOGDEBUG RTMP_LOGINFO + // if (_srs_pid > 0) { + // yang_Logs(Yang_LOGINFO, "SRS ip=%s, pid=%d, cid=%d", _srs_ip, _srs_pid, _srs_cid); + // } + + break; + } + //printf("\n************RTMP_PACKET_TYPE_INVOKE****************************************\n"); + if (HandleInvoke(packet->m_body, packet->m_nBodySize) == 1) + bHasMediaPacket = 2; + break; + + case RTMP_PACKET_TYPE_FLASH_VIDEO: { + /* go through FLV packets and handle metadata packets */ + uint32_t pos = 0; + uint32_t nTimeStamp = packet->m_nTimeStamp; + + while (pos + 11 < packet->m_nBodySize) { + uint32_t dataSize = AMF_DecodeInt24(packet->m_body + pos + 1); /* size without header (11) and prevTagSize (4) */ + + if (pos + 11 + dataSize + 4 > packet->m_nBodySize) { + yang_warn( "Stream corrupt?!"); + break; + } + if (packet->m_body[pos] == 0x12) { + HandleMetadata(packet->m_body + pos + 11, dataSize); + } else if (packet->m_body[pos] == 8 || packet->m_body[pos] == 9) { + nTimeStamp = AMF_DecodeInt24(packet->m_body + pos + 4); + nTimeStamp |= (packet->m_body[pos + 7] << 24); + } + pos += (11 + dataSize + 4); + } + if (!r->m_pausing) + r->m_mediaStamp = nTimeStamp; + + /* FLV tag(s) */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: FLV tag(s) %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + bHasMediaPacket = 1; + break; + } + default: + yang_debug( "%s, unknown packet type received: 0x%02x", + __FUNCTION__, packet->m_packetType); + + } + + return bHasMediaPacket; +} +int32_t YangRtmpBase::clientPacket_conn(RTMPPacket *packet) { + int32_t bHasMediaPacket = 0; + switch (packet->m_packetType) { + case RTMP_PACKET_TYPE_CHUNK_SIZE: + /* chunk size */ + HandleChangeChunkSize(r, packet); + break; + + case RTMP_PACKET_TYPE_BYTES_READ_REPORT: + /* bytes read report */ + yang_debug( "%s, received: bytes read report", + __FUNCTION__); + break; + + case RTMP_PACKET_TYPE_CONTROL: + /* ctrl */ + HandleCtrl(packet); + break; + + case RTMP_PACKET_TYPE_SERVER_BW: + /* server bw */ + HandleServerBW(packet); + break; + + case RTMP_PACKET_TYPE_CLIENT_BW: + /* client bw */ + HandleClientBW( packet); + break; + + case RTMP_PACKET_TYPE_AUDIO: + /* audio data */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + HandleAudio(r, packet); + bHasMediaPacket = 1; + if (!r->m_mediaChannel) + r->m_mediaChannel = packet->m_nChannel; + if (!r->m_pausing) + r->m_mediaStamp = packet->m_nTimeStamp; + break; + + case RTMP_PACKET_TYPE_VIDEO: + /* video data */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + HandleVideo(r, packet); + bHasMediaPacket = 1; + if (!r->m_mediaChannel) + r->m_mediaChannel = packet->m_nChannel; + if (!r->m_pausing) + r->m_mediaStamp = packet->m_nTimeStamp; + break; + + case RTMP_PACKET_TYPE_FLEX_STREAM_SEND: + /* flex stream send */ + yang_debug( + "%s, flex stream send, size %u bytes, not supported, ignoring", + __FUNCTION__, packet->m_nBodySize); + break; + + case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT: + /* flex shared object */ + yang_debug( + "%s, flex shared object, size %u bytes, not supported, ignoring", + __FUNCTION__, packet->m_nBodySize); + break; + + case RTMP_PACKET_TYPE_FLEX_MESSAGE: + /* flex message */ + { + yang_debug( + "%s, flex message, size %u bytes, not fully supported", + __FUNCTION__, packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + /* some DEBUG code */ +#if 0 + RTMP_LIB_AMFObject obj; + int32_t nRes = obj.Decode(packet.m_body+1, packet.m_nBodySize-1); + if(nRes < 0) { + yang_error( "%s, error decoding AMF3 packet", __FUNCTION__); + /*return; */ + } + + obj.Dump(); +#endif + //printf("\n************RTMP_PACKET_TYPE_FLEX_MESSAGE**************\n"); + if (HandleInvoke(packet->m_body + 1, packet->m_nBodySize - 1) == 1) + bHasMediaPacket = 2; + break; + } + case RTMP_PACKET_TYPE_INFO: + /* metadata (notify) */ + yang_debug( "%s, received: notify %u bytes", + __FUNCTION__, packet->m_nBodySize); + if (HandleMetadata( packet->m_body, packet->m_nBodySize)) + bHasMediaPacket = 1; + break; + + case RTMP_PACKET_TYPE_SHARED_OBJECT: + //if(m_handleShareObject!=NULL) (*m_handleShareObject)(packet->m_body, packet->m_nBodySize); + //if (m_shareobj) m_shareobj->parseSharedObject((uint8_t*)packet->m_body, packet->m_nBodySize); + yang_debug( "%s, shared object", __FUNCTION__); + + break; + + case RTMP_PACKET_TYPE_INVOKE: + /* invoke */ + yang_debug( "%s, received: invoke %u bytes", + __FUNCTION__, packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + // @remark debug info by http://github.com/ossrs/srs + while (1) { + // String(_result) + char *p = packet->m_body; + int32_t nb = packet->m_nBodySize; + // Marker. + if (nb < 1) { + yang_error( "ignore string marker for nb=%d", + nb); + break; + } + AMFDataType t = (AMFDataType) p[0]; + if (t != AMF_STRING) { + yang_error( "ignore string marker for type=%d", + t); + break; + } + nb--; + p++; + // String content. + if (nb < 2) { + yang_error( "ignore string data for nb=%d", nb); + break; + } + AVal _result; + AMF_DecodeString(p, &_result); + nb -= (int) _result.av_len + 2; + p += (int) _result.av_len + 2; + + // Number(0.0) + // Marker + if (nb < 1) { + yang_error( "ignore number marker for nb=%d", + nb); + break; + } + t = (AMFDataType) p[0]; + if (t != AMF_NUMBER) { + yang_error( "ignore number marker for type=%d", + t); + break; + } + nb--; + p++; + // Number content. + if (nb < 8) { + yang_error( "ignore number data for nb=%d", nb); + break; + } + double tid = AMF_DecodeNumber(p); + (void) tid; + nb -= 8; + p += 8; + + // Object + // Marker + if (nb < 1) { + yang_error( "ignore object marker for nb=%d", + nb); + break; + } + t = (AMFDataType) p[0]; + if (t != AMF_OBJECT) { + //yang_error( "ignore object marker for type=%d", t); + break; + } + nb--; + p++; + // Object info content + AMFObject obj; + if (nb < 3) { + yang_error( "ignore object eof for nb=%d", nb); + break; + } + int32_t nRes = -1; + if ((nRes = AMF_Decode(&obj, p, nb, TRUE)) < 0) { + yang_error( "decode object failed, ret=%d", + nRes); + break; + } + nb -= nRes; + p += nRes; + + // Object + // Marker + if (nb < 1) { + yang_error( "ignore object marker for nb=%d", + nb); + break; + } + t = (AMFDataType) p[0]; + if (t != AMF_OBJECT) { + //yang_error( "ignore object marker for type=%d", t); + break; + } + nb--; + p++; + // Object data content + if (nb < 3) { + yang_error( "ignore object eof for nb=%d", nb); + break; + } + if ((nRes = AMF_Decode(&obj, p, nb, TRUE)) < 0) { + yang_error( "decode object failed, ret=%d", + nRes); + break; + } + nb -= nRes; + p += nRes; + // Parse data object. + int32_t i, j; + for (i = 0; i < obj.o_num; i++) { + AMFObjectProperty *prop = &obj.o_props[i]; + if (prop->p_type == AMF_OBJECT + || prop->p_type == AMF_ECMA_ARRAY) { + obj = prop->p_vu.p_object; + for (j = 0; j < obj.o_num; j++) { + prop = &obj.o_props[j]; + // if (AVMATCH(&prop->p_name, &_const_srs_server_ip)) { + // if (_srs_ip) { free(_srs_ip); } + // _srs_ip = (char*) malloc(prop->p_vu.p_aval.av_len + 1); + // memcpy(_srs_ip, prop->p_vu.p_aval.av_val,prop->p_vu.p_aval.av_len); + // _srs_ip[prop->p_vu.p_aval.av_len] = 0; + // } else if (AVMATCH(&prop->p_name, &_const_srs_pid)) { + // _srs_pid = (int) prop->p_vu.p_number; + //} else if (AVMATCH(&prop->p_name, &_const_srs_cid)) { + // _srs_cid = (int) prop->p_vu.p_number; + // } + } + break; + } + } + + // Print32_t info.RTMP_LOGDEBUG RTMP_LOGINFO + // if (_srs_pid > 0) { + // yang_Logs(Yang_LOGINFO, "SRS ip=%s, pid=%d, cid=%d", _srs_ip, _srs_pid, _srs_cid); + // } + + break; + } + //printf("\n************RTMP_PACKET_TYPE_INVOKE****************************************\n"); + if (HandleInvoke(packet->m_body, packet->m_nBodySize) == 1) + bHasMediaPacket = 2; + break; + + case RTMP_PACKET_TYPE_FLASH_VIDEO: { + /* go through FLV packets and handle metadata packets */ + uint32_t pos = 0; + uint32_t nTimeStamp = packet->m_nTimeStamp; + + while (pos + 11 < packet->m_nBodySize) { + uint32_t dataSize = AMF_DecodeInt24(packet->m_body + pos + 1); /* size without header (11) and prevTagSize (4) */ + + if (pos + 11 + dataSize + 4 > packet->m_nBodySize) { + yang_warn( "Stream corrupt?!"); + break; + } + if (packet->m_body[pos] == 0x12) { + HandleMetadata(packet->m_body + pos + 11, dataSize); + } else if (packet->m_body[pos] == 8 || packet->m_body[pos] == 9) { + nTimeStamp = AMF_DecodeInt24(packet->m_body + pos + 4); + nTimeStamp |= (packet->m_body[pos + 7] << 24); + } + pos += (11 + dataSize + 4); + } + if (!r->m_pausing) + r->m_mediaStamp = nTimeStamp; + + /* FLV tag(s) */ + /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: FLV tag(s) %lu bytes", __FUNCTION__, packet.m_nBodySize); */ + bHasMediaPacket = 1; + break; + } + default: + yang_debug( "%s, unknown packet type received: 0x%02x", + __FUNCTION__, packet->m_packetType); + + } + + return bHasMediaPacket; +} + +int32_t YangRtmpBase::HandleInvoke(const char *body, uint32_t nBodySize) { + //printf("\n*************HandleInvoke**************\n"); + AMFObject obj; + AVal method; + double txn; + int32_t ret = 0, nRes; + if (body[0] != 0x02) /* make sure it is a string method name we start with */ + { + yang_warn( + "%s, Sanity failed. no string method in invoke packet", + __FUNCTION__); + return 0; + } + + nRes = AMF_Decode(&obj, body, nBodySize, FALSE); + if (nRes < 0) { + yang_error( "%s, error decoding invoke packet", + __FUNCTION__); + return 0; + } + + AMF_Dump(&obj); + AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method); + txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1)); + + if (AVMATCH(&method, &av__result)) { + // printf("\n*************av__result**************\n"); + AVal methodInvoked = { 0 }; + int32_t i; + for (i = 0; i < r->m_numCalls; i++) { + if (r->m_methodCalls[i].num == (int) txn) { + methodInvoked = r->m_methodCalls[i].name; + AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE); + break; + } + } + if (!methodInvoked.av_val) { + yang_debug("%s, received result id %f without matching request", + __FUNCTION__, txn); + goto leave; + } + //yang_error( "%s, received result for method call <%s>", __FUNCTION__, methodInvoked.av_val); + if (AVMATCH(&methodInvoked, &av_connect)) { + // printf("\n*************av_connect**************\n"); + + yang_handleconn( &obj); + if (r->Link.token.av_len) { + AMFObjectProperty p; + if (RTMP_FindFirstMatchingProperty(&obj, &av_secureToken, &p)) { + DecodeTEA(&r->Link.token, &p.p_vu.p_aval); + SendSecureTokenResponse(&p.p_vu.p_aval); + } + } + r->m_bConnected = TRUE; + } else if (AVMATCH(&methodInvoked, &av_createStream)) { + + r->m_stream_id = (int) AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3)); + + if (r->m_isPublish) { + SendPublish(); + //newPubStreamId = r->m_stream_id; + + } else { + SendPlay(); + RTMP_SendCtrl(3, r->m_stream_id, r->m_nBufferMS); + } + } else if (AVMATCH(&methodInvoked, &av_FCSubscribe)) { + + + } else if (AVMATCH(&methodInvoked,&av_play) || AVMATCH(&methodInvoked, &av_publish)) { + //printf("\n**********response..***av_play av_publish**************\n"); + r->m_bPlaying = TRUE; + //m_streamState = 0; + } + free(methodInvoked.av_val); + } else if (AVMATCH(&method, &av_onBWDone)) { + if (!r->m_nBWCheckCounter) + SendCheckBW(); + } else if (AVMATCH(&method, &av_FCSubscribe)) { + //printf( "\n**********av_onFCSubscribe*************************************\n"); + } else if (AVMATCH(&method, &av_onFCUnsubscribe)) { + //printf("\nstop publish.....av_onFCUnsubscribe"); + //RTMP_Close(); + ret = 1; + } else if (AVMATCH(&method, &av_ping)) { + SendPong(txn); + } else if (AVMATCH(&method, &av__onbwcheck)) { + SendCheckBWResult(txn); + } else if (AVMATCH(&method, &av__onbwdone)) { + int32_t i; + for (i = 0; i < r->m_numCalls; i++) + if (AVMATCH(&r->m_methodCalls[i].name, &av__checkbw)) { + AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE); + break; + } + } else if (AVMATCH(&method, &av__error)) { + yang_error( "rtmp server sent error"); + } else if (AVMATCH(&method, &av_close)) { + yang_error( "rtmp server requested close"); + handleError(ERROR_REQUEST_Close); + //RTMP_Close(); + } else if (AVMATCH(&method, &av_onStatus)) { + //printf("\n*************av_onStatus**********************\n"); + AMFObject obj2; + AVal code, level,description; + AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2); + AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code); + AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level); + AMFProp_GetString(AMF_GetProp(&obj2, &av_description, -1), &description); + if (AVMATCH(&code, + &av_NetStream_Failed) || AVMATCH(&code, &av_NetStream_Play_Failed)|| AVMATCH(&code, &av_NetStream_Play_StreamNotFound)|| AVMATCH(&code, &av_NetConnection_Connect_InvalidApp)) { + //m_streamState = 1; + yang_error( "av_NetStream_Error:..: %s,..level==%s,..desc==%s", code.av_val,level.av_val,description.av_val); + } + + else if (AVMATCH(&code, + &av_NetStream_Play_Start) || AVMATCH(&code, &av_NetStream_Play_PublishNotify)) { + //printf("\n*************play start**********************\n"); + int32_t i; + r->m_bPlaying = TRUE; + //m_streamState = 0; + for (i = 0; i < r->m_numCalls; i++) { + if (AVMATCH(&r->m_methodCalls[i].name, &av_play)) { + AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE); + break; + } + } + } + + else if (AVMATCH(&code, &av_NetStream_Publish_Start)) { + int32_t i; + r->m_bPlaying = TRUE; + //m_streamState = 0; + //printf( "\n************av_NetStream_Publish_Start*****************\n"); + for (i = 0; i < r->m_numCalls; i++) { + if (AVMATCH(&r->m_methodCalls[i].name, &av_publish)) { + AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE); + break; + } + } + } else if (AVMATCH(&code, &av_NetStream_Unpublish_Success)) { + //printf( "\n************NetStream.Unpublish.Success*****************\n"); + } + + else if (AVMATCH(&code, &av_NetStream_Publish_BadName)) { + //m_streamState = 1; + //printf("\n************av_NetStream_Publish_BadName*****************\n"); + } + /* Return 1 if this is a Play.Complete or Play.Stop */ + else if (AVMATCH(&code, + &av_NetStream_Play_Complete) || AVMATCH(&code, &av_NetStream_Play_Stop) || AVMATCH(&code, &av_NetStream_Play_UnpublishNotify)) { + + //printf("\n********av_NetStream_Play_Complete****av_NetStream_Play_Stop******av_NetStream_Play_UnpublishNotify*\n"); + //RTMP_Close(); + ret = 1; + } + + else if (AVMATCH(&code, &av_NetStream_Seek_Notify)) { + r->m_read.flags &= ~RTMP_READ_SEEKING; + } + + else if (AVMATCH(&code, &av_NetStream_Pause_Notify)) { + if (r->m_pausing == 1 || r->m_pausing == 2) { + RTMP_SendPause( FALSE, r->m_pauseStamp); + r->m_pausing = 3; + } + } + } else if (AVMATCH(&method, &av_playlist_ready)) { + int32_t i; + for (i = 0; i < r->m_numCalls; i++) { + if (AVMATCH(&r->m_methodCalls[i].name, &av_set_playlist)) { + AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE); + break; + } + } + } else { + + } + leave: AMF_Reset(&obj); + return ret; +} + +int32_t YangRtmpBase::connectServer() { + //int32_t rtmpRet= RTMP_Connect( NULL); + //yang_usleep(1); + RTMPPacket packet = { 0 }; + r->m_mediaChannel = 0; + //printf( "\n**********************RTMP_ConnectStream***start***********************\n"); + while (!r->m_bConnected && RTMP_IsConnected() && readPacket(&packet)) { + if (RTMPPacket_IsReady(&packet)) { + if (!packet.m_nBodySize) + continue; + if ((packet.m_packetType == RTMP_PACKET_TYPE_AUDIO) + || (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO) + || (packet.m_packetType == RTMP_PACKET_TYPE_INFO)) { + yang_warn("Received FLV packet before play()! Ignoring."); + RTMPPacket_Free(&packet); + continue; + } + + clientPacket_conn(&packet); + // if (m_shareobj != NULL&& packet.m_packetType == RTMP_PACKET_TYPE_INVOKE) + // m_shareobj->getMyId(packet.m_body, packet.m_nBodySize); + RTMPPacket_Free(&packet); + } + } + + return r->m_bConnected; +} + + +void YangRtmpBase::setPublishState(int32_t p_pubstate) { + r->m_isPublish = p_pubstate; + r->Link.protocol |= RTMP_FEATURE_WRITE; +} +int32_t YangRtmpBase::connectRtmpServer(YangStreamOptType pisPublish,char *serverIp,char *app,int32_t port){ + setPublishState((int)pisPublish); + //printf("\n0********connectRtmpServer****...........................\n"); + if(initConnect(NULL)){ + return ERROR_CONNECT_Fail; + } + //printf("\n1********connectRtmpServer****...........................\n"); + if(!connectServer()) return ERROR_CONNECT_Fail; + return Yang_Ok; +} +int32_t YangRtmpBase::HandleStream(char *psName,YangStreamOptType pisPublish,int32_t puid) { + //printf("\n1*******************%s %s start....\n",isPublish ? "Publish" : "Play", psName); + + //m_isHandleStream = 1; + //m_streamState = -1; + int32_t isPublish=(int)pisPublish; + r->m_isPublish = isPublish; + //r->Link.streamType = streamType; + memset(pathChar, 0, sizeof(pathChar)); + //r->Link.curPath.av_val=pathChar; + r->Link.curPath.av_len = strlen(psName); + memcpy(pathChar, psName, r->Link.curPath.av_len); + + //m_curStreamType = streamType; + + if (isPublish) { + SendReleaseStream(); + SendFCPublish(); + } + + RTMP_SendCreateStream(); + if (!isPublish) { + SendFCSubscribe(getPlayPath()); + } + r->m_bPlaying = 0; + r->m_mediaChannel = 0; + //int32_t cou = 0; + RTMPPacket packet = { 0 }; + while (!r->m_bPlaying && readPacket(&packet)) { + if (RTMPPacket_IsReady(&packet)) { + if (!packet.m_nBodySize) + continue; + if ((packet.m_packetType == RTMP_PACKET_TYPE_AUDIO) + || (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO) + || (packet.m_packetType == RTMP_PACKET_TYPE_INFO)) { + RTMPPacket_Free(&packet); + continue; + } + clientPacket(&packet); + RTMPPacket_Free(&packet); + } + } + //m_isHandleStream = 0; + //printf("\n5*******************%s %s end....%s\n", isPublish?"Publish":"Play",psName, + // r->m_bPlaying == 1 ? "sucess!" : "failure!"); + //m_errState=Yang_Ok; + + return r->m_bPlaying?Yang_Ok:ERROR_RTMP_PlayFailure; +} +//int32_t YangRtmpBase::receive(char* p,int32_t *plen){ + //pac.m_body=p; + //return yangReadPacket(&pac, p); +//} diff --git a/libyangrtc2/src/yangrtmp/YangRtmpBase1.h b/libyangrtc2/src/yangrtmp/YangRtmpBase1.h new file mode 100644 index 0000000000000000000000000000000000000000..e93c33a1419454164f2f2022f9816ac8379cd8b5 --- /dev/null +++ b/libyangrtc2/src/yangrtmp/YangRtmpBase1.h @@ -0,0 +1,1902 @@ +#include +#include +#include +#include +#include + +#include "yangutil/sys/YangLog.h" +#include +#include + +#ifdef _WIN32 + +#include +#include +#include +#ifdef _MSC_VER /* MSVC */ +#define snprintf _snprintf +#define strcasecmp stricmp +#define strncasecmp strnicmp +#define vsnprintf _vsnprintf +#endif + +//#define GetSockError() WSAGetLastError() +//#define SetSockError(e) WSASetLastError(e) +#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) +//#define EWOULDBLOCK WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */ +#define sleep(n) Sleep(n*1000) +//#define msleep(n) Sleep(n) +//#define SET_RCVTIMEO(tv,s) int32_t tv = s*1000 +#else /* !_WIN32 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "stddef.h" +#define GetSockError() errno +#define SetSockError(e) errno = e +#undef closesocket +#define closesocket(s) close(s) +#define msleep(n) yang_usleep(n*1000) +#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +#endif + +#undef OSS +#ifdef _WIN32 +#define OSS "WIN" +#elif defined(__sun__) +#define OSS "SOL" +#elif defined(__APPLE__) +#define OSS "MAC" +#elif defined(__linux__) +#define OSS "LNX" +#else +#define OSS "GNU" +#endif +#define DEF_VERSTR OSS " 10,0,32,18" + +#if 0 /* unused */ +SAVC(bgHasStream); + +int +SendBGHasStream(RTMP *r, double dId, AVal *playpath) +{ + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_bgHasStream); + enc = AMF_EncodeNumber(enc, pend, dId); + *enc++ = AMF_NULL; + + enc = AMF_EncodeString(enc, pend, playpath); + if (enc == NULL) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return RTMP_SendPacket(r, &packet, TRUE); +} +#endif + +#ifndef _WIN32 +int32_t clk_tck; +#endif + +#ifdef _DEBUG +extern FILE *netstackdump; +extern FILE *netstackdump_read; +#endif + +// @remark debug info by http://github.com/ossrs/srs + +const char DEFAULT_FLASH_VER[] = DEF_VERSTR; + const AVal RTMP_DefaultFlashVer = { (char *) DEF_VERSTR, sizeof(DEF_VERSTR) - 1 }; + + + //const AVal _const_srs_server_ip = AVC("srs_server_ip"); + // const AVal _const_srs_pid = AVC("srs_pid"); + //const AVal _const_srs_cid = AVC("srs_id"); + SAVC(app); + SAVC(connect); + SAVC(flashVer); + SAVC(swfUrl); + SAVC(pageUrl); + SAVC(tcUrl); + SAVC(fpad); + SAVC(capabilities); + SAVC(audioCodecs); + SAVC(videoCodecs); + SAVC(videoFunction); + SAVC(objectEncoding); + SAVC(secureToken); + SAVC(secureTokenResponse); + SAVC(type); + SAVC(nonprivate); + + SAVC(seek); + SAVC(createStream); + SAVC(FCSubscribe); + SAVC(releaseStream); + SAVC(FCPublish); + SAVC(FCUnpublish); + SAVC(publish); + SAVC(live); + SAVC(record); + SAVC(deleteStream); + SAVC(closeStream); + SAVC(pause); + SAVC(_checkbw); + SAVC(_result); + SAVC(ping); + SAVC(pong); + SAVC(play); + SAVC(set_playlist); + SAVC(0); + + SAVC(onBWDone); + SAVC(onFCSubscribe); + SAVC(onFCUnsubscribe); + SAVC(_onbwcheck); + SAVC(_onbwdone); + SAVC(_error); + SAVC(close); + SAVC(code); + SAVC(level); + SAVC(description); + SAVC(onStatus); + SAVC(playlist_ready); + SAVC(onMetaData); + SAVC(duration); + SAVC(video); + SAVC(audio); + const AVal av_NetStream_Authenticate_UsherToken = + AVC("NetStream.Authenticate.UsherToken"); + const AVal av_setDataFrame = AVC("@setDataFrame"); + const AVal av_NetStream_Failed = AVC("NetStream.Failed"); + const AVal av_NetStream_Play_Failed = AVC("NetStream.Play.Failed"); + const AVal av_NetStream_Play_StreamNotFound = + AVC("NetStream.Play.StreamNotFound"); + const AVal av_NetConnection_Connect_InvalidApp = + AVC("NetConnection.Connect.InvalidApp"); + const AVal av_NetStream_Play_Start = AVC("NetStream.Play.Start"); + const AVal av_NetStream_Play_Complete = AVC("NetStream.Play.Complete"); + const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop"); + const AVal av_NetStream_Seek_Notify = AVC("NetStream.Seek.Notify"); + const AVal av_NetStream_Pause_Notify = AVC("NetStream.Pause.Notify"); + const AVal av_NetStream_Play_PublishNotify = + AVC("NetStream.Play.PublishNotify"); + const AVal av_NetStream_Play_UnpublishNotify = + AVC("NetStream.Play.UnpublishNotify"); + const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start"); + const AVal av_NetStream_Publish_BadName = AVC("NetStream.Publish.BadName"); + const AVal av_NetStream_Unpublish_Success = AVC("NetStream.Unpublish.Success"); + const AVal av_NetConnection_Connect_Rejected =AVC("NetConnection.Connect.Rejected"); + + typedef enum { + RTMPT_OPEN = 0, RTMPT_SEND, RTMPT_IDLE, RTMPT_CLOSE + } RTMPTCmd; +const int32_t packetSize[] = { 12, 8, 4, 1 }; + +const char *optinfo[] = { "string", "integer", "boolean", "AMF" }; + +const char RTMPProtocolStrings[][7] = { "RTMP", "RTMPT", "RTMPE", "RTMPTE", + "RTMPS", "RTMPTS", "", "", "RTMFP" }; + +const char RTMPProtocolStringsLower[][7] = { "rtmp", "rtmpt", "rtmpe", "rtmpte", + "rtmps", "rtmpts", "", "", "rtmfp" }; + +const char *RTMPT_cmds[] = { "open", "send", "idle", "close" }; +const char flvHeader[] = { 'F', 'L', 'V', 0x01, 0x00, /* 0x04 == audio, 0x01 == video */ +0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00 }; + + +const AVal truth[] = { + AVC("1"), + AVC("on"), + AVC("yes"), + AVC("true"), { 0, 0 } }; + + struct urlopt { + AVal name; + off_t off; + int32_t otype; + int32_t omisc; + char *use; + } options[] = { { AVC("socks"), OFF(Link.sockshost), OPT_STR, 0, + (char*)"Use the specified SOCKS proxy" }, { AVC("app"), OFF(Link.app), OPT_STR, + 0,(char*) "Name of target app on server" }, { AVC("tcUrl"), OFF(Link.tcUrl), + OPT_STR, 0,(char*) "URL to played stream" }, { AVC("pageUrl"), OFF( + Link.pageUrl), OPT_STR, 0, (char*)"URL of played media's web page" }, { + AVC("swfUrl"), OFF(Link.swfUrl), OPT_STR, 0, (char*)"URL to player SWF file" }, + { AVC("flashver"), OFF(Link.flashVer), OPT_STR, 0, + (char*)"Flash version string (default " DEF_VERSTR ")" }, + { AVC("conn"), OFF(Link.extras), OPT_CONN, 0, + (char*)"Append arbitrary AMF data to Connect message" }, { + AVC("playpath"), OFF(Link.curPatht), OPT_STR, 0, + (char*)"Path to target media on server" }, { AVC("playlist"), OFF( + Link.lFlags), OPT_BOOL, RTMP_LF_PLST, + (char*)"Set playlist before play command" }, { AVC("live"), OFF( + Link.lFlags), OPT_BOOL, 0x0002, + (char*)"Stream is live, no seeking possible" }, { AVC("subscribe"), + OFF(Link.subscribepath), OPT_STR, 0, (char*)"Stream to subscribe to" }, + { AVC("jtv"), OFF(Link.usherToken), OPT_STR, 0, + (char*)"Justin.tv authentication token" }, { AVC("token"), OFF( + Link.token), OPT_STR, 0, (char*)"Key for SecureToken response" }, { + AVC("swfVfy"), OFF(Link.lFlags), OPT_BOOL, RTMP_LF_SWFV, + (char*)"Perform SWF Verification" }, { AVC("swfAge"), OFF(Link.swfAge), + OPT_INT, 0, (char*)"Number of days to use cached SWF hash" }, { + AVC("start"), OFF(Link.seekTime), OPT_INT, 0, + (char*)"Stream start position in milliseconds" }, { AVC("stop"), OFF( + Link.stopTime), OPT_INT, 0, + (char*)"Stream stop position in milliseconds" }, { AVC("buffer"), OFF( + m_nBufferMS), OPT_INT, 0, (char*)"Buffer time in milliseconds" }, { + AVC("timeout"), OFF(Link.timeout), OPT_INT, 0, + (char*)"Session timeout in seconds" }, { AVC("pubUser"), OFF( + Link.pubUser), OPT_STR, 0, (char*)"Publisher username" }, { + AVC("pubPasswd"), OFF(Link.pubPasswd), OPT_STR, 0, + (char*)"Publisher password" }, { { NULL, 0 }, 0, 0 } }; + + + +int32_t YangRtmpBase::yang_ParseURL( char *url, int32_t *protocol, AVal *host, + uint32_t *port, AVal *app) { + char *p, *end, *col, *ques, *slash; + + yang_debug( "Parsing..."); + + *protocol = RTMP_PROTOCOL_RTMP; + *port = 0; + //playpath->av_len = 0; + //playpath->av_val = NULL; + app->av_len = 0; + app->av_val = NULL; + + /* Old School Parsing */ + + /* look for usual :// pattern */ + p = (char*) strstr(url, "://"); + if (!p) { + yang_error( "RTMP URL: No :// in url!"); + return FALSE; + } + { + int32_t len = (int) (p - url); + + if (len == 4 && strncasecmp(url, "rtmp", 4) == 0) + *protocol = RTMP_PROTOCOL_RTMP; + else if (len == 5 && strncasecmp(url, "rtmpt", 5) == 0) + *protocol = RTMP_PROTOCOL_RTMPT; + else if (len == 5 && strncasecmp(url, "rtmps", 5) == 0) + *protocol = RTMP_PROTOCOL_RTMPS; + else if (len == 5 && strncasecmp(url, "rtmpe", 5) == 0) + *protocol = RTMP_PROTOCOL_RTMPE; + else if (len == 5 && strncasecmp(url, "rtmfp", 5) == 0) + *protocol = RTMP_PROTOCOL_RTMFP; + else if (len == 6 && strncasecmp(url, "rtmpte", 6) == 0) + *protocol = RTMP_PROTOCOL_RTMPTE; + else if (len == 6 && strncasecmp(url, "rtmpts", 6) == 0) + *protocol = RTMP_PROTOCOL_RTMPTS; + else { + yang_warn( "Unknown protocol!\n"); + goto parsehost; + } + } + + yang_debug( "Parsed protocol: %d", *protocol); + + parsehost: + /* let's get the hostname */ + p += 3; + + /* check for sudden death */ + if (*p == 0) { + yang_warn( "No hostname in URL!"); + return FALSE; + } + + end = p + strlen(p); + col = strchr(p, ':'); + ques = strchr(p, '?'); + slash = strchr(p, '/'); + + { + int32_t hostlen; + if (slash) + hostlen = slash - p; + else + hostlen = end - p; + if (col && col - p < hostlen) + hostlen = col - p; + + if (hostlen < 256) { + host->av_val = p; + host->av_len = hostlen; + yang_debug( "Parsed host : %.*s", hostlen, + host->av_val); + } else { + yang_warn( "Hostname exceeds 255 characters!"); + } + + p += hostlen; + } + + /* get the port number if available */ + if (*p == ':') { + uint32_t p2; + p++; + p2 = atoi(p); + if (p2 > 65535) { + yang_warn( "Invalid port number!"); + } else { + *port = p2; + } + } + + if (!slash) { + yang_warn( "No application or playpath in URL!"); + return TRUE; + } + p = slash + 1; + + { + /* parse application + * + * rtmp://host[:port]/app[/appinstance][/...] + * application = app[/appinstance] + */ + + char *slash2, *slash3 = NULL, *slash4 = NULL; + int32_t applen, appnamelen; + + slash2 = strchr(p, '/'); + if (slash2) + slash3 = strchr(slash2 + 1, '/'); + if (slash3) + slash4 = strchr(slash3 + 1, '/'); + + applen = end - p; /* ondemand, pass all parameters as app */ + appnamelen = applen; /* ondemand length */ + + if (ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ + appnamelen = ques - p; + } else if (strncmp(p, "ondemand/", 9) == 0) { + /* app = ondemand/foobar, only pass app=ondemand */ + applen = 8; + appnamelen = 8; + } else { /* app!=ondemand, so app is app[/appinstance] */ + if (slash4) + appnamelen = slash4 - p; + else if (slash3) + appnamelen = slash3 - p; + else if (slash2) + appnamelen = slash2 - p; + + applen = appnamelen; + } + + app->av_val = p; + app->av_len = applen; + yang_debug( "Parsed app : %.*s", applen, p); + + p += appnamelen; + } + + if (*p == '/') + p++; + + /**if (end-p) { + AVal av = {p, end-p}; + RTMP_ParsePlaypath(&av, playpath); + }**/ + + return TRUE; +} +void YangRtmpBase::RTMPPacket_Reset(RTMPPacket *p) { + p->m_headerType = 0; + p->m_packetType = 0; + p->m_nChannel = 0; + p->m_nTimeStamp = 0; + p->m_nInfoField2 = 0; + p->m_hasAbsTimestamp = FALSE; + p->m_nBodySize = 0; + p->m_nBytesRead = 0; +} + +uint32_t YangRtmpBase::RTMP_GetTime() { +#ifdef _DEBUG + return 0; +#elif defined(_WIN32) + return timeGetTime(); +#else + struct tms t; + if (!clk_tck) + clk_tck = sysconf(_SC_CLK_TCK); + return times(&t) * 1000 / clk_tck; +#endif +} + +void YangRtmpBase::RTMP_UserInterrupt() { + RTMP_ctrlC = TRUE; +} + +void YangRtmpBase::SocksSetup(AVal *sockshost) { + if (sockshost->av_len) { + const char *socksport = strchr(sockshost->av_val, ':'); + char *hostname = strdup(sockshost->av_val); + + if (socksport) + hostname[socksport - sockshost->av_val] = '\0'; + r->Link.sockshost.av_val = hostname; + r->Link.sockshost.av_len = strlen(hostname); + + r->Link.socksport = socksport ? atoi(socksport + 1) : 1080; + yang_debug( "Connecting via SOCKS proxy: %s:%d", + r->Link.sockshost.av_val, r->Link.socksport); + } else { + r->Link.sockshost.av_val = NULL; + r->Link.sockshost.av_len = 0; + r->Link.socksport = 0; + } +} +int32_t YangRtmpBase::RTMPPacket_Alloc(RTMPPacket *p, uint32_t nSize) { + char *ptr; + if (nSize > SIZE_MAX - RTMP_MAX_HEADER_SIZE) + return FALSE; + ptr = (char*) calloc(1, nSize + RTMP_MAX_HEADER_SIZE); + if (!ptr) + return FALSE; + p->m_body = ptr + RTMP_MAX_HEADER_SIZE; + p->m_nBytesRead = 0; + return TRUE; +} + +void YangRtmpBase::RTMPPacket_Free(RTMPPacket *p) { + if (p->m_body) { + free(p->m_body - RTMP_MAX_HEADER_SIZE); + p->m_body = NULL; + } +} + +void YangRtmpBase::RTMPPacket_Dump(RTMPPacket *p) { + yang_debug( + "RTMP PACKET: packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %u. body: 0x%02x", + p->m_packetType, p->m_nChannel, p->m_nTimeStamp, p->m_nInfoField2, + p->m_nBodySize, p->m_body ? (uint8_t) p->m_body[0] : 0); +} + +int32_t RTMP_LibVersion() { + return RTMP_LIB_VERSION; +} + +void YangRtmpBase::RTMP_OptUsage() { + int32_t i; + + yang_error( "Valid RTMP options are:\n"); + for (i = 0; options[i].name.av_len; i++) { + yang_error( "%10s %-7s %s\n", options[i].name.av_val, + optinfo[options[i].otype], options[i].use); + } +} + +int32_t YangRtmpBase::parseAMF(AMFObject *obj, AVal *av, int32_t *depth) { + AMFObjectProperty prop = { { 0, 0 } }; + int32_t i; + char *p, *arg = av->av_val; + + if (arg[1] == ':') { + p = (char *) arg + 2; + switch (arg[0]) { + case 'B': + prop.p_type = AMF_BOOLEAN; + prop.p_vu.p_number = atoi(p); + break; + case 'S': + prop.p_type = AMF_STRING; + prop.p_vu.p_aval.av_val = p; + prop.p_vu.p_aval.av_len = av->av_len - (p - arg); + break; + case 'N': + prop.p_type = AMF_NUMBER; + prop.p_vu.p_number = strtod(p, NULL); + break; + case 'Z': + prop.p_type = AMF_NULL; + break; + case 'O': + i = atoi(p); + if (i) { + prop.p_type = AMF_OBJECT; + } else { + (*depth)--; + return 0; + } + break; + default: + return -1; + } + } else if (arg[2] == ':' && arg[0] == 'N') { + p = strchr(arg + 3, ':'); + if (!p || !*depth) + return -1; + prop.p_name.av_val = (char *) arg + 3; + prop.p_name.av_len = p - (arg + 3); + + p++; + switch (arg[1]) { + case 'B': + prop.p_type = AMF_BOOLEAN; + prop.p_vu.p_number = atoi(p); + break; + case 'S': + prop.p_type = AMF_STRING; + prop.p_vu.p_aval.av_val = p; + prop.p_vu.p_aval.av_len = av->av_len - (p - arg); + break; + case 'N': + prop.p_type = AMF_NUMBER; + prop.p_vu.p_number = strtod(p, NULL); + break; + case 'O': + prop.p_type = AMF_OBJECT; + break; + default: + return -1; + } + } else + return -1; + + if (*depth) { + AMFObject *o2; + for (i = 0; i < *depth; i++) { + o2 = &obj->o_props[obj->o_num - 1].p_vu.p_object; + obj = o2; + } + } + AMF_AddProp(obj, &prop); + if (prop.p_type == AMF_OBJECT) + (*depth)++; + return 0; +} + +void AV_erase(RTMP_METHOD *vals, int32_t *num, int32_t i, int32_t freeit) { + if (freeit) + free(vals[i].name.av_val); + (*num)--; + for (; i < *num; i++) { + vals[i] = vals[i + 1]; + } + vals[i].name.av_val = NULL; + vals[i].name.av_len = 0; + vals[i].num = 0; +} + +void RTMP_DropRequest(RTMP *r, int32_t i, int32_t freeit) { + AV_erase(r->m_methodCalls, &r->m_numCalls, i, freeit); +} + +void AV_queue(RTMP_METHOD **vals, int32_t *num, AVal *av, int32_t txn) { + char *tmp; + if (!(*num & 0x0f)) + *vals = (RTMP_METHOD*) realloc(*vals, + (*num + 16) * sizeof(RTMP_METHOD)); + tmp = (char*) malloc(av->av_len + 1); + memcpy(tmp, av->av_val, av->av_len); + tmp[av->av_len] = '\0'; + (*vals)[*num].num = txn; + (*vals)[*num].name.av_len = av->av_len; + (*vals)[(*num)++].name.av_val = tmp; +} + +void AV_clear(RTMP_METHOD *vals, int32_t num) { + int32_t i; + for (i = 0; i < num; i++) + free(vals[i].name.av_val); + free(vals); +} + +int32_t RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name, + AMFObjectProperty * p) { + int32_t n; + /* this is a small object search to locate the "duration" property */ + for (n = 0; n < obj->o_num; n++) { + AMFObjectProperty *prop = AMF_GetProp(obj, NULL, n); + + if (AVMATCH(&prop->p_name, name)) { + memcpy(p, prop, sizeof(*prop)); + return TRUE; + } + + if (prop->p_type == AMF_OBJECT || prop->p_type == AMF_ECMA_ARRAY) { + if (RTMP_FindFirstMatchingProperty(&prop->p_vu.p_object, name, p)) + return TRUE; + } + } + return FALSE; +} + +/* Like above, but only check if name is a prefix of property */ +int32_t RTMP_FindPrefixProperty(AMFObject *obj, const AVal *name, + AMFObjectProperty * p) { + int32_t n; + for (n = 0; n < obj->o_num; n++) { + AMFObjectProperty *prop = AMF_GetProp(obj, NULL, n); + + if (prop->p_name.av_len > name->av_len + && !memcmp(prop->p_name.av_val, name->av_val, name->av_len)) { + memcpy(p, prop, sizeof(*prop)); + return TRUE; + } + + if (prop->p_type == AMF_OBJECT) { + if (RTMP_FindPrefixProperty(&prop->p_vu.p_object, name, p)) + return TRUE; + } + } + return FALSE; +} + +int32_t YangRtmpBase::DumpMetaData(AMFObject *obj) { + AMFObjectProperty *prop; + int32_t n, len; + for (n = 0; n < obj->o_num; n++) { + char str[256] = ""; + prop = AMF_GetProp(obj, NULL, n); + switch (prop->p_type) { + case AMF_OBJECT: + case AMF_ECMA_ARRAY: + case AMF_STRICT_ARRAY: + if (prop->p_name.av_len) + yang_info( "%.*s:", prop->p_name.av_len, + prop->p_name.av_val); + DumpMetaData(&prop->p_vu.p_object); + break; + case AMF_NUMBER: + snprintf(str, 255, "%.2f", prop->p_vu.p_number); + break; + case AMF_BOOLEAN: + snprintf(str, 255, "%s", + prop->p_vu.p_number != 0. ? "TRUE" : "FALSE"); + break; + case AMF_STRING: + len = snprintf(str, 255, "%.*s", prop->p_vu.p_aval.av_len, + prop->p_vu.p_aval.av_val); + if (len >= 1 && str[len - 1] == '\n') + str[len - 1] = '\0'; + break; + case AMF_DATE: + snprintf(str, 255, "timestamp:%.2f", prop->p_vu.p_number); + break; + default: + snprintf(str, 255, "INVALID TYPE 0x%02x", + (uint8_t) prop->p_type); + } + if (str[0] && prop->p_name.av_len) { + yang_info( " %-22.*s%s", prop->p_name.av_len, + prop->p_name.av_val, str); + } + } + return FALSE; +} + +int32_t YangRtmpBase::HandleMetadata(char *body, uint32_t len) { + /* allright we get some info here, so parse it and print32_t it */ + /* also keep duration or filesize to make a nice progress bar */ + + AMFObject obj; + AVal metastring; + int32_t ret = FALSE; + + int32_t nRes = AMF_Decode(&obj, body, len, FALSE); + if (nRes < 0) { + yang_error( "%s, error decoding meta data packet", + __FUNCTION__); + return FALSE; + } + + AMF_Dump(&obj); + AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &metastring); + + if (AVMATCH(&metastring, &av_onMetaData)) { + AMFObjectProperty prop; + /* Show metadata */ + yang_info( "Metadata:"); + DumpMetaData(&obj); + if (RTMP_FindFirstMatchingProperty(&obj, &av_duration, &prop)) { + r->m_fDuration = prop.p_vu.p_number; + /*RTMP_Log(RTMP_LOGDEBUG, "Set duration: %.2f", m_fDuration); */ + } + /* Search for audio or video tags */ + if (RTMP_FindPrefixProperty(&obj, &av_video, &prop)) + r->m_read.dataType |= 1; + if (RTMP_FindPrefixProperty(&obj, &av_audio, &prop)) + r->m_read.dataType |= 4; + ret = TRUE; + } + AMF_Reset(&obj); + return ret; +} + +void YangRtmpBase::HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet) { + if (packet->m_nBodySize >= 4) { + r->m_inChunkSize = AMF_DecodeInt32(packet->m_body); + yang_debug( "%s, received: chunk size change to %d", + __FUNCTION__, r->m_inChunkSize); + } +} + +void HandleAudio(RTMP *r, const RTMPPacket *packet) { +} + +void HandleVideo(RTMP *r, const RTMPPacket *packet) { +} + +void YangRtmpBase::HandleServerBW(const RTMPPacket *packet) { + r->m_nServerBW = AMF_DecodeInt32(packet->m_body); + yang_debug( "%s: server BW = %d", __FUNCTION__, r->m_nServerBW); +} + +void YangRtmpBase::HandleClientBW(const RTMPPacket *packet) { + r->m_nClientBW = AMF_DecodeInt32(packet->m_body); + if (packet->m_nBodySize > 4) + r->m_nClientBW2 = packet->m_body[4]; + else + r->m_nClientBW2 = -1; + yang_debug( "%s: client BW = %d %d", __FUNCTION__, + r->m_nClientBW, r->m_nClientBW2); +} + +int32_t DecodeInt32LE(const char *data) { + uint8_t *c = (uint8_t *) data; + uint32_t val; + + val = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0]; + return val; +} + +int32_t EncodeInt32LE(char *output, int32_t nVal) { + output[0] = nVal; + nVal >>= 8; + output[1] = nVal; + nVal >>= 8; + output[2] = nVal; + nVal >>= 8; + output[3] = nVal; + return 4; +} + +int32_t YangRtmpBase::RTMPSockBuf_Fill( RTMPSockBuf *sb) { + if(!r) return 0; + int32_t nBytes; + + if (!sb->sb_size) + sb->sb_start = sb->sb_buf; + + while (1) { + nBytes = sizeof(sb->sb_buf) - 1 - sb->sb_size- (sb->sb_start - sb->sb_buf); + { + nBytes = recv(sb->sb_socket, sb->sb_start + sb->sb_size, nBytes, 0); + } + if (nBytes != -1) { + sb->sb_size += nBytes; + } else { + int32_t sockerr = GetSockError(); + yang_error("%s, recv returned %d. GetSockError(): %d (%s)",__FUNCTION__, nBytes, sockerr, strerror(sockerr)); + if (sockerr == EINTR && !RTMP_ctrlC) + continue; + + if (sockerr == EWOULDBLOCK || sockerr == EAGAIN) { + sb->sb_timedout = TRUE; + nBytes = 0; + } + } + break; + } + + return nBytes; +} +#ifdef _WIN32 +#define MSG_NOSIGNAL 0 +#endif +int32_t YangRtmpBase::RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int32_t len) { + return send(sb->sb_socket, buf, len, MSG_NOSIGNAL); +} + +int32_t YangRtmpBase::RTMPSockBuf_Close(RTMPSockBuf *sb) { + if (sb->sb_socket != -1) + return closesocket(sb->sb_socket); + return 0; +} + +void DecodeTEA(AVal *key, AVal *text) { + uint32_t *v, k[4] = { 0 }, u; + uint32_t z, y, sum = 0, e, DELTA = 0x9e3779b9; + int32_t p, q; + int32_t i, n; + uint8_t *ptr, *out; + + /* prep key: pack 1st 16 chars into 4 LittleEndian ints */ + ptr = (uint8_t *) key->av_val; + u = 0; + n = 0; + v = k; + p = key->av_len > 16 ? 16 : key->av_len; + for (i = 0; i < p; i++) { + u |= ptr[i] << (n * 8); + if (n == 3) { + *v++ = u; + u = 0; + n = 0; + } else { + n++; + } + } + /* any trailing chars */ + if (u) + *v = u; + + /* prep text: hex2bin, multiples of 4 */ + n = (text->av_len + 7) / 8; + out = (uint8_t*) malloc(n * 8); + ptr = (uint8_t *) text->av_val; + v = (uint32_t *) out; + for (i = 0; i < n; i++) { + u = (HEX2BIN(ptr[0]) << 4) + HEX2BIN(ptr[1]); + u |= ((HEX2BIN(ptr[2]) << 4) + HEX2BIN(ptr[3])) << 8; + u |= ((HEX2BIN(ptr[4]) << 4) + HEX2BIN(ptr[5])) << 16; + u |= ((HEX2BIN(ptr[6]) << 4) + HEX2BIN(ptr[7])) << 24; + *v++ = u; + ptr += 8; + } + v = (uint32_t *) out; + + /* http://www.movable-type.co.uk/scripts/tea-block.html */ +#define MX (((z>>5)^(y<<2)) + ((y>>3)^(z<<4))) ^ ((sum^y) + (k[(p&3)^e]^z)); + z = v[n - 1]; + y = v[0]; + q = 6 + 52 / n; + sum = q * DELTA; + while (sum != 0) { + e = sum >> 2 & 3; + for (p = n - 1; p > 0; p--) + z = v[p - 1], y = v[p] -= MX + ; + z = v[n - 1]; + y = v[0] -= MX + ; + sum -= DELTA; + } + + text->av_len /= 2; + memcpy(text->av_val, out, text->av_len); + free(out); +} +/** +int32_t HTTP_Post(RTMP *r, RTMPTCmd cmd, const char *buf, int32_t len) { + char hbuf[512]; + int32_t hlen = snprintf(hbuf, sizeof(hbuf), "POST /%s%s/%d HTTP/1.1\r\n" + "Host: %.*s:%d\r\n" + "Accept: *\r\n" + "User-Agent: Shockwave Flash\r\n" + "Connection: Keep-Alive\r\n" + "Cache-Control: no-cache\r\n" + "Content-type: application/x-fcs\r\n" + "Content-length: %d\r\n\r\n", RTMPT_cmds[cmd], + r->m_clientID.av_val ? r->m_clientID.av_val : "", r->m_msgCounter, + r->Link.hostname.av_len, r->Link.hostname.av_val, r->Link.port, + len); + RTMPSockBuf_Send(&r->m_sb, hbuf, hlen); + hlen = RTMPSockBuf_Send(&r->m_sb, buf, len); + r->m_msgCounter++; + r->m_unackd++; + return hlen; +} + +int32_t HTTP_read(YangRtmpLib *ylr, RTMP *r, int32_t fill) { + char *ptr; + int32_t hlen; + + restart: if (fill) + RTMPSockBuf_Fill(ylr, &r->m_sb); + if (r->m_sb.sb_size < 13) { + if (fill) + goto restart; + return -2; + } + if (strncmp(r->m_sb.sb_start, "HTTP/1.1 200 ", 13)) + return -1; + r->m_sb.sb_start[r->m_sb.sb_size] = '\0'; + if (!strstr(r->m_sb.sb_start, "\r\n\r\n")) { + if (fill) + goto restart; + return -2; + } + + ptr = r->m_sb.sb_start + sizeof("HTTP/1.1 200"); + while ((ptr = strstr(ptr, "Content-"))) { + if (!strncasecmp(ptr + 8, "length:", 7)) + break; + ptr += 8; + } + if (!ptr) + return -1; + hlen = atoi(ptr + 16); + ptr = strstr(ptr + 16, "\r\n\r\n"); + if (!ptr) + return -1; + ptr += 4; + if (ptr + (r->m_clientID.av_val ? 1 : hlen) + > r->m_sb.sb_start + r->m_sb.sb_size) { + if (fill) + goto restart; + return -2; + } + r->m_sb.sb_size -= ptr - r->m_sb.sb_start; + r->m_sb.sb_start = ptr; + r->m_unackd--; + + if (!r->m_clientID.av_val) { + r->m_clientID.av_len = hlen; + r->m_clientID.av_val = (char*) malloc(hlen + 1); + if (!r->m_clientID.av_val) + return -1; + r->m_clientID.av_val[0] = '/'; + memcpy(r->m_clientID.av_val + 1, ptr, hlen - 1); + r->m_clientID.av_val[hlen] = 0; + r->m_sb.sb_size = 0; + } else { + r->m_polling = *ptr++; + r->m_resplen = hlen - 1; + r->m_sb.sb_start++; + r->m_sb.sb_size--; + } + return 0; +} +**/ +int32_t YangRtmpBase::RTMP_IsConnected() { + return r->m_sb.sb_socket != -1; +} +double RTMP_GetDuration(RTMP *r) { + return r->m_fDuration; +} + +int32_t RTMP_Socket(RTMP *r) { + return r->m_sb.sb_socket; +} + +int32_t RTMP_IsTimedout(RTMP *r) { + return r->m_sb.sb_timedout; +} + +void RTMP_UpdateBufferMS(YangRtmpBase *ylr, RTMP *r) { + ylr->RTMP_SendCtrl(3, r->m_stream_id, r->m_nBufferMS); +} +void YangRtmpBase::CloseInternal(int32_t reconnect) { + int32_t i; +if(!r) return; + if (RTMP_IsConnected()) { + if (r->m_stream_id > 0&&(m_errState>4||m_errState==0)) { + i = r->m_stream_id; + r->m_stream_id = 0; + if (r->m_isPublish) SendFCUnpublish(); + SendDeleteStream(i); + } + if (r->m_clientID.av_val) { + //HTTP_Post(r, RTMPT_CLOSE, "", 1); + free(r->m_clientID.av_val); + r->m_clientID.av_val = NULL; + r->m_clientID.av_len = 0; + } + RTMPSockBuf_Close(&r->m_sb); + } + + r->m_stream_id = -1; + r->m_sb.sb_socket = -1; + r->m_nBWCheckCounter = 0; + r->m_nBytesIn = 0; + r->m_nBytesInSent = 0; + + if (r->m_read.flags & RTMP_READ_HEADER) { + free(r->m_read.buf); + r->m_read.buf = NULL; + } + r->m_read.dataType = 0; + r->m_read.flags = 0; + r->m_read.status = 0; + r->m_read.nResumeTS = 0; + r->m_read.nIgnoredFrameCounter = 0; + r->m_read.nIgnoredFlvFrameCounter = 0; + + r->m_write.m_nBytesRead = 0; + RTMPPacket_Free(&r->m_write); + if(r&&r->m_vecChannelsIn){ + //for (i = 0; i < r->m_channelsAllocatedIn; i++) { + // if (r->m_vecChannelsIn[i]) { + // RTMPPacket_Free(r->m_vecChannelsIn[i]); + // } + // } + free(r->m_vecChannelsIn); + } + r->m_vecChannelsIn = NULL; + free(r->m_channelTimestamp); + r->m_channelTimestamp = NULL; + r->m_channelsAllocatedIn = 0; + if(r&&r->m_vecChannelsOut){ + //for (i = 0; i < r->m_channelsAllocatedOut; i++) { + // if (r->m_vecChannelsOut[i]) { + // RTMPPacket_Free(r->m_vecChannelsOut[i]); + // } + // } + free(r->m_vecChannelsOut); + } + r->m_vecChannelsOut = NULL; + r->m_channelsAllocatedOut = 0; + AV_clear(r->m_methodCalls, r->m_numCalls); + r->m_methodCalls = NULL; + r->m_numCalls = 0; + r->m_numInvokes = 0; + + r->m_bPlaying = FALSE; + r->m_sb.sb_size = 0; + + r->m_msgCounter = 0; + r->m_resplen = 0; + r->m_unackd = 0; + + if ((r->Link.lFlags & RTMP_LF_FTCU) && !reconnect) { + free(r->Link.tcUrl.av_val); + r->Link.tcUrl.av_val = NULL; + r->Link.lFlags ^= RTMP_LF_FTCU; + } + if ((r->Link.lFlags & RTMP_LF_FAPU) && !reconnect) { + free(r->Link.app.av_val); + r->Link.app.av_val = NULL; + r->Link.lFlags ^= RTMP_LF_FAPU; + } + + //if (!reconnect) { + //free(r->Link.playpath0.av_val); + //r->Link.playpath0.av_val = NULL; + // } + +} + +void YangRtmpBase::RTMP_SetupStream(int32_t protocol, AVal *host, uint32_t port, + AVal *sockshost, AVal *playpath, AVal *tcUrl, AVal *swfUrl, + AVal *pageUrl, AVal *app, AVal *auth, AVal *swfSHA256Hash, + uint32_t swfSize, AVal *flashVer, AVal *subscribepath, AVal *usherToken, + int32_t dStart, int32_t dStop, int32_t bLiveStream, int64_t timeout) { + yang_debug( "Protocol : %s", RTMPProtocolStrings[protocol & 7]); + yang_debug( "Hostname : %.*s", host->av_len, host->av_val); + yang_debug( "Port : %d", port); + yang_debug( "Playpath : %s", playpath->av_val); + + if (tcUrl && tcUrl->av_val) + yang_debug( "tcUrl : %s", tcUrl->av_val); + if (swfUrl && swfUrl->av_val) + yang_debug( "swfUrl : %s", swfUrl->av_val); + if (pageUrl && pageUrl->av_val) + yang_debug( "pageUrl : %s", pageUrl->av_val); + if (app && app->av_val) + yang_debug( "app : %.*s", app->av_len, app->av_val); + if (auth && auth->av_val) + yang_debug( "auth : %s", auth->av_val); + if (subscribepath && subscribepath->av_val) + yang_debug( "subscribepath : %s", subscribepath->av_val); + if (usherToken && usherToken->av_val) + yang_debug( "NetStream.Authenticate.UsherToken : %s", + usherToken->av_val); + if (flashVer && flashVer->av_val) + yang_debug( "flashVer : %s", flashVer->av_val); + if (dStart > 0) + yang_debug( "StartTime : %d msec", dStart); + if (dStop > 0) + yang_debug( "StopTime : %d msec", dStop); + + yang_debug( "live : %s", bLiveStream ? "yes" : "no"); + yang_debug( "timeout : %ld sec", timeout); + + SocksSetup(sockshost); + + if (tcUrl && tcUrl->av_len) + r->Link.tcUrl = *tcUrl; + if (swfUrl && swfUrl->av_len) + r->Link.swfUrl = *swfUrl; + if (pageUrl && pageUrl->av_len) + r->Link.pageUrl = *pageUrl; + if (app && app->av_len) + r->Link.app = *app; + if (auth && auth->av_len) { + r->Link.auth = *auth; + r->Link.lFlags |= RTMP_LF_AUTH; + } + if (flashVer && flashVer->av_len) + r->Link.flashVer = *flashVer; + else + r->Link.flashVer = RTMP_DefaultFlashVer; + if (subscribepath && subscribepath->av_len) + r->Link.subscribepath = *subscribepath; + if (usherToken && usherToken->av_len) + r->Link.usherToken = *usherToken; + r->Link.seekTime = dStart; + r->Link.stopTime = dStop; + //if (bLiveStream) r->Link.lFlags |= RTMP_LF_LIVE; + r->Link.timeout = timeout; + + r->Link.protocol = protocol; + r->Link.hostname = *host; + r->Link.port = port; + // r->Link.playpatht = *playpath; + + if (r->Link.port == 0) + r->Link.port = 1935; +} +void RTMP_ParsePlaypath(AVal *in, AVal *out) { + int32_t addMP4 = 0; + int32_t addMP3 = 0; + int32_t subExt = 0; + const char *playpath = in->av_val; + const char *temp, *q, *ext = NULL; + const char *ppstart = playpath; + char *streamname, *destptr, *p; + + int32_t pplen = in->av_len; + + out->av_val = NULL; + out->av_len = 0; + + if ((*ppstart == '?') && + (temp=strstr(ppstart, "slist=")) != 0) { + ppstart = temp+6; + pplen = strlen(ppstart); + + temp = strchr(ppstart, '&'); + if (temp) { + pplen = temp-ppstart; + } + } + + q = strchr(ppstart, '?'); + if (pplen >= 4) { + if (q) + ext = q-4; + else + ext = &ppstart[pplen-4]; + if ((strncmp(ext, ".f4v", 4) == 0) || + (strncmp(ext, ".mp4", 4) == 0)) { + addMP4 = 1; + subExt = 1; + /* Only remove .flv from rtmp URL, not slist params */ + } else if ((ppstart == playpath) && + (strncmp(ext, ".flv", 4) == 0)) { + subExt = 1; + } else if (strncmp(ext, ".mp3", 4) == 0) { + addMP3 = 1; + subExt = 1; + } + } + + streamname = (char *)malloc((pplen+4+1)*sizeof(char)); + if (!streamname) + return; + + destptr = streamname; + if (addMP4) { + if (strncmp(ppstart, "mp4:", 4)) { + strcpy(destptr, "mp4:"); + destptr += 4; + } else { + subExt = 0; + } + } else if (addMP3) { + if (strncmp(ppstart, "mp3:", 4)) { + strcpy(destptr, "mp3:"); + destptr += 4; + } else { + subExt = 0; + } + } + + for (p=(char *)ppstart; pplen >0;) { + /* skip extension */ + if (subExt && p == ext) { + p += 4; + pplen -= 4; + continue; + } + if (*p == '%') { + uint32_t c; + sscanf(p+1, "%02x", &c); + *destptr++ = c; + pplen -= 3; + p += 3; + } else { + *destptr++ = *p++; + pplen--; + } + } + *destptr = '\0'; + + out->av_val = streamname; + out->av_len = destptr - streamname; +} +int32_t YangRtmpBase::RTMP_ParseURL(char *url, int32_t *protocol, AVal *host, uint32_t *port, + AVal *playpath, AVal *app) +{ + char *p, *end, *col, *ques, *slash; + + yang_debug( "Parsing..."); + + *protocol = RTMP_PROTOCOL_RTMP; + *port = 0; + playpath->av_len = 0; + playpath->av_val = NULL; + app->av_len = 0; + app->av_val = NULL; + + /* Old School Parsing */ + + /* look for usual :// pattern */ + p = strstr(url, "://"); + if(!p) { + yang_error( "RTMP URL: No :// in url!"); + return FALSE; + } + { + int32_t len = (int)(p-url); + + if(len == 4 && strncasecmp(url, "rtmp", 4)==0) + *protocol = RTMP_PROTOCOL_RTMP; + else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPT; + else if(len == 5 && strncasecmp(url, "rtmps", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPS; + else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPE; + else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0) + *protocol = RTMP_PROTOCOL_RTMFP; + else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0) + *protocol = RTMP_PROTOCOL_RTMPTE; + else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0) + *protocol = RTMP_PROTOCOL_RTMPTS; + else { + yang_warn( "Unknown protocol!\n"); + goto parsehost; + } + } + + yang_debug( "Parsed protocol: %d", *protocol); + +parsehost: + /* let's get the hostname */ + p+=3; + + /* check for sudden death */ + if(*p==0) { + yang_warn( "No hostname in URL!"); + return FALSE; + } + + end = p + strlen(p); + col = strchr(p, ':'); + ques = strchr(p, '?'); + slash = strchr(p, '/'); + + { + int32_t hostlen; + if(slash) + hostlen = slash - p; + else + hostlen = end - p; + if(col && col -p < hostlen) + hostlen = col - p; + + if(hostlen < 256) { + host->av_val = p; + host->av_len = hostlen; + yang_debug( "Parsed host : %.*s", hostlen, host->av_val); + } else { + yang_warn( "Hostname exceeds 255 characters!"); + } + + p+=hostlen; + } + + /* get the port number if available */ + if(*p == ':') { + uint32_t p2; + p++; + p2 = atoi(p); + if(p2 > 65535) { + yang_warn( "Invalid port number!"); + } else { + *port = p2; + } + } + + if(!slash) { + yang_warn( "No application or playpath in URL!"); + return TRUE; + } + p = slash+1; + + { + /* parse application + * + * rtmp://host[:port]/app[/appinstance][/...] + * application = app[/appinstance] + */ + + char *slash2, *slash3 = NULL, *slash4 = NULL; + int32_t applen, appnamelen; + + slash2 = strchr(p, '/'); + if(slash2) + slash3 = strchr(slash2+1, '/'); + if(slash3) + slash4 = strchr(slash3+1, '/'); + + applen = end-p; /* ondemand, pass all parameters as app */ + appnamelen = applen; /* ondemand length */ + + if(ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ + appnamelen = ques-p; + } + else if(strncmp(p, "ondemand/", 9)==0) { + /* app = ondemand/foobar, only pass app=ondemand */ + applen = 8; + appnamelen = 8; + } + else { /* app!=ondemand, so app is app[/appinstance] */ + if(slash4) + appnamelen = slash4-p; + else if(slash3) + appnamelen = slash3-p; + else if(slash2) + appnamelen = slash2-p; + + applen = appnamelen; + } + + app->av_val = p; + app->av_len = applen; + yang_debug( "Parsed app : %.*s", applen, p); + + p += appnamelen; + } + + if (*p == '/') + p++; + + if (end-p) { + AVal av; + av.av_val=p; + av.av_len=end-p;//{p, end-p}; + RTMP_ParsePlaypath(&av, playpath); + } + + return TRUE; +} +int32_t YangRtmpBase::RTMP_ParseURL1(char *url, int32_t *protocol, AVal *host, uint32_t *port,AVal *app) +{ + char *p, *end, *col, *ques, *slash; + + yang_debug( "Parsing..."); + + *protocol = RTMP_PROTOCOL_RTMP; + *port = 0; +// playpath->av_len = 0; + //playpath->av_val = NULL; + app->av_len = 0; + app->av_val = NULL; + + /* Old School Parsing */ + + /* look for usual :// pattern */ + p = strstr(url, "://"); + if(!p) { + yang_error( "RTMP URL: No :// in url!"); + return FALSE; + } + { + int32_t len = (int)(p-url); + + if(len == 4 && strncasecmp(url, "rtmp", 4)==0) + *protocol = RTMP_PROTOCOL_RTMP; + else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPT; + else if(len == 5 && strncasecmp(url, "rtmps", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPS; + else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0) + *protocol = RTMP_PROTOCOL_RTMPE; + else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0) + *protocol = RTMP_PROTOCOL_RTMFP; + else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0) + *protocol = RTMP_PROTOCOL_RTMPTE; + else if(len == 6 && strncasecmp(url, "rtmpts", 6)==0) + *protocol = RTMP_PROTOCOL_RTMPTS; + else { + yang_warn( "Unknown protocol!\n"); + goto parsehost; + } + } + + yang_debug( "Parsed protocol: %d", *protocol); + +parsehost: + /* let's get the hostname */ + p+=3; + + /* check for sudden death */ + if(*p==0) { + yang_warn( "No hostname in URL!"); + return FALSE; + } + + end = p + strlen(p); + col = strchr(p, ':'); + ques = strchr(p, '?'); + slash = strchr(p, '/'); + + { + int32_t hostlen; + if(slash) + hostlen = slash - p; + else + hostlen = end - p; + if(col && col -p < hostlen) + hostlen = col - p; + + if(hostlen < 256) { + host->av_val = p; + host->av_len = hostlen; + yang_debug( "Parsed host : %.*s", hostlen, host->av_val); + } else { + yang_warn( "Hostname exceeds 255 characters!"); + } + + p+=hostlen; + } + + /* get the port number if available */ + if(*p == ':') { + uint32_t p2; + p++; + p2 = atoi(p); + if(p2 > 65535) { + yang_warn( "Invalid port number!"); + } else { + *port = p2; + } + } + + if(!slash) { + yang_warn( "No application or playpath in URL!"); + return TRUE; + } + p = slash+1; + + { + /* parse application + * + * rtmp://host[:port]/app[/appinstance][/...] + * application = app[/appinstance] + */ + + char *slash2, *slash3 = NULL, *slash4 = NULL; + int32_t applen, appnamelen; + + slash2 = strchr(p, '/'); + if(slash2) + slash3 = strchr(slash2+1, '/'); + if(slash3) + slash4 = strchr(slash3+1, '/'); + + applen = end-p; /* ondemand, pass all parameters as app */ + appnamelen = applen; /* ondemand length */ + + if(ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ + appnamelen = ques-p; + } + else if(strncmp(p, "ondemand/", 9)==0) { + /* app = ondemand/foobar, only pass app=ondemand */ + applen = 8; + appnamelen = 8; + } + else { /* app!=ondemand, so app is app[/appinstance] */ + if(slash4) + appnamelen = slash4-p; + else if(slash3) + appnamelen = slash3-p; + else if(slash2) + appnamelen = slash2-p; + + applen = appnamelen; + } + + app->av_val = p; + app->av_len = applen; + yang_debug( "Parsed app : %.*s", applen, p); + + p += appnamelen; + } + + if (*p == '/') + p++; + + if (end-p) { + AVal av; + av.av_val=p; + av.av_len=end-p;//{p, end-p}; + //RTMP_ParsePlaypath(&av, playpath); + } + + return TRUE; +} +int32_t YangRtmpBase::yang_SetupURL(char *url,int32_t pport) { + // r->Link.count=1; + // r->Link.curIndex=0; + AVal opt, arg; + char *p1, *p2, *ptr = strchr(url, ' '); + int32_t ret=0, len=0; + uint32_t port = 0;//pport; + + if (ptr) *ptr = '\0'; + len = strlen(url); + while (ptr) { + *ptr++ = '\0'; + p1 = ptr; + p2 = strchr(p1, '='); + if (!p2) + break; + opt.av_val = p1; + opt.av_len = p2 - p1; + *p2++ = '\0'; + arg.av_val = p2; + ptr = strchr(p2, ' '); + if (ptr) { + *ptr = '\0'; + arg.av_len = ptr - p2; + /* skip repeated spaces */ + while (ptr[1] == ' ') + *ptr++ = '\0'; + } else { + arg.av_len = strlen(p2); + } + + /* unescape */ + port = arg.av_len; + for (p1 = p2; port > 0;) { + if (*p1 == '\\') { + uint32_t c; + if (port < 3) + return FALSE; + sscanf(p1 + 1, "%02x", &c); + *p2++ = c; + port -= 3; + p1 += 3; + } else { + *p2++ = *p1++; + port--; + } + } + arg.av_len = p2 - arg.av_val; + + ret = RTMP_SetOpt(&opt, &arg); + if (!ret) + return ret; + } + + SocksSetup( &r->Link.sockshost); + + if (r->Link.port == 0) + r->Link.port = 1935; + return TRUE; +} + +void YangRtmpBase::yang_handleconn(AMFObject *pob) { + char nstr[128], vstr[128]; + + for (int32_t n = 0; n < pob->o_num; n++) { + if (pob->o_props[n].p_type == AMF_OBJECT) { + AMFObject *ob1 = &pob->o_props[n].p_vu.p_object; + for (int32_t m = 0; m < ob1->o_num; m++) { + memset(nstr,0,sizeof(nstr)); + memset(vstr,0,sizeof(vstr)); + if (ob1->o_props[m].p_type == AMF_STRING) { + memcpy(nstr,ob1->o_props[m].p_name.av_val,ob1->o_props[m].p_name.av_len); + memcpy(vstr,ob1->o_props[m].p_vu.p_aval.av_val,ob1->o_props[m].p_vu.p_aval.av_len); + if(strcmp("code",nstr)==0) {memset(r->netStatus.code,0,sizeof(r->netStatus.code));strcpy(r->netStatus.code,vstr);} + if(strcmp("description",nstr)==0) {memset(r->netStatus.description,0,sizeof(r->netStatus.description));strcpy(r->netStatus.description,vstr);} + if(strcmp("fmsVer",nstr)==0) {memset(r->netStatus.fmsVer,0,sizeof(r->netStatus.fmsVer));strcpy(r->netStatus.fmsVer,vstr);} + //snprintf(nstr, 255, "%s", ob1->o_props[m].p_name.av_val); + //snprintf(vstr, 255, "%s",ob1->o_props[m].p_vu.p_aval.av_val); + } + //printf("\n\name=%s,value=%s\n",nstr,vstr); + + } + ob1 = NULL; + } + } +} + + + +void YangRtmpBase::initRTMP(char *serverIp, char *app, int32_t port) { + if (r == NULL) { + r = (RTMP*) calloc(1, sizeof(RTMP)); + RTMP_Init(); + char url[128]; + memset(pathChar, 0, sizeof(pathChar)); + r->Link.curPath.av_val = pathChar; + r->Link.curPath.av_len = 0; + r->Link.port = port; + //initAVStreams(); + /**char app[30]; + memset(app,0,30); + sprintf(app,"%s","live");**/ + memset(url, 0, sizeof(url)); + sprintf(url, "rtmp://%s/%s", serverIp, app); + //printf("\nurl========================%s\n",url); + int32_t tsize = strlen(url); + r->Link.tcUrl.av_val = (char*) malloc(tsize + 1); + r->Link.tcUrl.av_len = tsize; + memcpy(r->Link.tcUrl.av_val, url, tsize); + r->Link.tcUrl.av_val[tsize] = '\0'; + + tsize = strlen(app); + r->Link.app.av_val = (char*) malloc(tsize + 1); + r->Link.app.av_len = tsize; + memcpy(r->Link.app.av_val, app, tsize); + r->Link.app.av_val[tsize] = '\0'; + + tsize = strlen(serverIp); + r->Link.hostname.av_val = (char*) malloc(tsize + 1); + r->Link.hostname.av_len = tsize; + memcpy(r->Link.hostname.av_val, serverIp, tsize); + r->Link.hostname.av_val[tsize] = '\0'; + + r->Link.protocol = 0; + //printf("url================%s",url); + yang_SetupURL(url, port); + //r->Link.curVideoPlayIndex = 0; + //r->Link.curAudioPlayIndex = 0; + // r->Link.audioPlayCount = 0; + //r->Link.videoPlayCount = 0; + // r->Link.curVideoPubIndex = 0; + // r->Link.curAudioPubIndex = 0; + // r->Link.audioPubCount = 0; + // r->Link.videoPubCount = 0; + } + //if(pflag==YangRtmpRead) r->Link.lFlags|= RTMP_LF_LIVE; + //int32_t rtmpRet= RTMP_Connect( NULL); +} +void YangRtmpBase::initRTMP(char *serverIp, char *app, int32_t pmeetingId,int32_t port) { + if (r == NULL) { + r = (RTMP*) calloc(1, sizeof(RTMP)); + RTMP_Init(); + char url[128]; + + //initAVStreams(); + memset(pathChar, 0, 30); + r->Link.curPath.av_val = pathChar; + r->Link.curPath.av_len = 0; + + r->Link.port = port; + + memset(url, 0, sizeof(url)); + sprintf(url, "%s/%d", app, pmeetingId); + int32_t tsize = strlen(url); + r->Link.app.av_val = (char*) malloc(tsize + 1); + r->Link.app.av_len = tsize; + memcpy(r->Link.app.av_val, url, tsize); + r->Link.app.av_val[tsize] = '\0'; + + memset(url, 0, sizeof(url)); + sprintf(url, "rtmp://%s/%s/%d", serverIp, app, pmeetingId); + //printf("\nurl===%s", url); + tsize = strlen(url); + r->Link.tcUrl.av_val = (char*) malloc(tsize + 1); + r->Link.tcUrl.av_len = tsize; + memcpy(r->Link.tcUrl.av_val, url, tsize); + r->Link.tcUrl.av_val[tsize] = '\0'; + + tsize = strlen(serverIp); + r->Link.hostname.av_val = (char*) malloc(tsize + 1); + r->Link.hostname.av_len = tsize; + memcpy(r->Link.hostname.av_val, serverIp, tsize); + r->Link.hostname.av_val[tsize] = '\0'; + + r->Link.protocol = 0; + + yang_SetupURL(url, port); + //r->Link.curVideoPlayIndex = 0; + //r->Link.curAudioPlayIndex = 0; + //r->Link.audioPlayCount = 0; + //r->Link.videoPlayCount = 0; + //r->Link.curVideoPubIndex = 0; + //r->Link.curAudioPubIndex = 0; + //r->Link.audioPubCount = 0; + //r->Link.videoPubCount = 0; + } + //if(pflag==YangRtmpRead) r->Link.lFlags|= RTMP_LF_LIVE; + //int32_t rtmpRet= RTMP_Connect( NULL); +} +int32_t YangRtmpBase::RTMP_SetupURL(char *url) { + AVal opt, arg; + char *p1, *p2, *ptr = strchr(url, ' '); + int32_t ret, len; + uint32_t port = 0; + + if (ptr) + *ptr = '\0'; + + len = strlen(url); + //ret = RTMP_ParseURL(url, &r->Link.protocol, &r->Link.hostname, &port,&r->Link.pubVideoPath[0], &r->Link.app); + ret = RTMP_ParseURL1(url, &r->Link.protocol, &r->Link.hostname, &port, + &r->Link.app); + if (!ret) + return ret; + r->Link.port = port; + // r->Link.playpath = r->Link.playpath0; + + while (ptr) { + *ptr++ = '\0'; + p1 = ptr; + p2 = strchr(p1, '='); + if (!p2) + break; + opt.av_val = p1; + opt.av_len = p2 - p1; + *p2++ = '\0'; + arg.av_val = p2; + ptr = strchr(p2, ' '); + if (ptr) { + *ptr = '\0'; + arg.av_len = ptr - p2; + /* skip repeated spaces */ + while (ptr[1] == ' ') + *ptr++ = '\0'; + } else { + arg.av_len = strlen(p2); + } + + /* unescape */ + port = arg.av_len; + for (p1 = p2; port > 0;) { + if (*p1 == '\\') { + uint32_t c; + if (port < 3) + return FALSE; + sscanf(p1 + 1, "%02x", &c); + *p2++ = c; + port -= 3; + p1 += 3; + } else { + *p2++ = *p1++; + port--; + } + } + arg.av_len = p2 - arg.av_val; + + ret = RTMP_SetOpt(&opt, &arg); + if (!ret) + return ret; + } + + if (!r->Link.tcUrl.av_len) { + r->Link.tcUrl.av_val = url; + if (r->Link.app.av_len) { + if (r->Link.app.av_val < url + len) { + /* if app is part of original url, just use it */ + r->Link.tcUrl.av_len = r->Link.app.av_len + + (r->Link.app.av_val - url); + } else { + len = r->Link.hostname.av_len + r->Link.app.av_len + + sizeof("rtmpte://:65535/"); + r->Link.tcUrl.av_val = (char*) malloc(len); + r->Link.tcUrl.av_len = snprintf(r->Link.tcUrl.av_val, len, + "%s://%.*s:%d/%.*s", + RTMPProtocolStringsLower[r->Link.protocol], + r->Link.hostname.av_len, r->Link.hostname.av_val, + r->Link.port, r->Link.app.av_len, r->Link.app.av_val); + r->Link.lFlags |= RTMP_LF_FTCU; + } + } else { + r->Link.tcUrl.av_len = strlen(url); + } + } + +#ifdef CRYPTO + if ((r->Link.lFlags & RTMP_LF_SWFV) && r->Link.swfUrl.av_len) + RTMP_HashSWF(r->Link.swfUrl.av_val, &r->Link.SWFSize, + (uint8_t *)r->Link.SWFHash, r->Link.swfAge); +#endif + + SocksSetup(&r->Link.sockshost); + + if (r->Link.port == 0) { + if (r->Link.protocol & RTMP_FEATURE_SSL) + r->Link.port = 443; + else if (r->Link.protocol & RTMP_FEATURE_HTTP) + r->Link.port = 80; + else + r->Link.port = 1935; + } + return TRUE; +} + +//void YangLibRtmp::RTMP_EnableWrite() { +// r->Link.protocol |= RTMP_FEATURE_WRITE; +//} + +void YangRtmpBase::setBufferMS(int32_t size) { + r->m_nBufferMS = size; +} +/** +int32_t YangRtmpLib::RTMP_GetNextMediaPacket(RTMPPacket *packet) { + int32_t bHasMediaPacket = 0; + + while (!bHasMediaPacket && RTMP_IsConnected(r) && readPacket(packet)) { + if (!RTMPPacket_IsReady(packet) || !packet->m_nBodySize) { + continue; + } + + bHasMediaPacket = clientPacket(packet); + + if (!bHasMediaPacket) { + RTMPPacket_Free(packet); + } else if (r->m_pausing == 3) { + if (packet->m_nTimeStamp <= r->m_mediaStamp) { + bHasMediaPacket = 0; +#ifdef _DEBUG + yang_debug( + "Skipped type: %02X, size: %d, TS: %d ms, abs TS: %d, pause: %d ms", + packet->m_packetType, packet->m_nBodySize, + packet->m_nTimeStamp, packet->m_hasAbsTimestamp, + r->m_mediaStamp); +#endif + RTMPPacket_Free(packet); + continue; + } + r->m_pausing = 0; + } + } + + if (bHasMediaPacket) + r->m_bPlaying = TRUE; + else if (r->m_sb.sb_timedout && !r->m_pausing) + r->m_pauseStamp = + r->m_mediaChannel < r->m_channelsAllocatedIn ? + r->m_channelTimestamp[r->m_mediaChannel] : 0; + + return bHasMediaPacket; +} +**/ +/** + AVal YangRtmpLib::getPlayPath1() { + if (r->m_isPublish) { + if (r->Link.streamType == YangAudioStream) { + return r->Link.pubAudioPath[r->Link.curAudioPubIndex]; + } else + return r->Link.pubVideoPath[r->Link.curVideoPubIndex]; + } else { + if (r->Link.streamType == YangAudioStream) { + return r->Link.playAudioPath[r->Link.curAudioPlayIndex]; + } else + return r->Link.playVideoPath[r->Link.curVideoPlayIndex]; + } + }**/ diff --git a/libyangrtc2/src/yangrtp/YangAudioPayload.cpp b/libyangrtc2/src/yangrtp/YangAudioPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f260a362fd7980ff78ddf0434d2eefd3a8b83dd4 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangAudioPayload.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +YangAudioPayload::YangAudioPayload() +{ + m_channel = 0; +} + +YangAudioPayload::YangAudioPayload(uint8_t pt, std::string encode_name, int32_t sample, int32_t channel) + :YangCodecPayload(pt, encode_name, sample) +{ + m_type = "audio"; + m_channel = channel; + m_opus_param.minptime = 0; + m_opus_param.use_inband_fec = false; + m_opus_param.usedtx = false; +} + +YangAudioPayload::~YangAudioPayload() +{ +} + +YangAudioPayload* YangAudioPayload::copy() +{ + YangAudioPayload* cp = new YangAudioPayload(); + + cp->m_type = m_type; + cp->m_pt = m_pt; + cp->m_pt_of_publisher = m_pt_of_publisher; + cp->m_name = m_name; + cp->m_sample = m_sample; + cp->m_rtcp_fbs = m_rtcp_fbs; + cp->m_channel = m_channel; + cp->m_opus_param = m_opus_param; + + return cp; +} + + +YangMediaPayloadType YangAudioPayload::generate_media_payload_type() +{ + YangMediaPayloadType media_payload_type(m_pt); + + media_payload_type.m_encoding_name = m_name; + media_payload_type.m_clock_rate = m_sample; + if (m_channel != 0) { + media_payload_type.m_encoding_param = yang_int2str(m_channel); + } + media_payload_type.m_rtcp_fb = m_rtcp_fbs; + + std::ostringstream format_specific_param; + if (m_opus_param.minptime) { + format_specific_param << "minptime=" << m_opus_param.minptime; + } + if (m_opus_param.use_inband_fec) { + format_specific_param << ";useinbandfec=1"; + } + if (m_opus_param.usedtx) { + format_specific_param << ";usedtx=1"; + } + media_payload_type.m_format_specific_param = format_specific_param.str(); + + return media_payload_type; +} + +int32_t YangAudioPayload::set_opus_param_desc(std::string fmtp) +{ + int32_t err = Yang_Ok; + std::vector vec = yang_splits(fmtp, ";"); + for (size_t i = 0; i < vec.size(); ++i) { + std::vector kv = yang_splits(vec[i], "="); + if (kv.size() == 2) { + if (kv[0] == "minptime") { + m_opus_param.minptime = (int)::atol(kv[1].c_str()); + } else if (kv[0] == "useinbandfec") { + m_opus_param.use_inband_fec = (kv[1] == "1") ? true : false; + } else if (kv[0] == "usedtx") { + m_opus_param.usedtx = (kv[1] == "1") ? true : false; + } + } else { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid opus param=%s", vec[i].c_str()); + } + } + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangAudioPayload.h b/libyangrtc2/src/yangrtp/YangAudioPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..34869b41fb91a25c619a57b8ce6ba8a61b1ec5ed --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangAudioPayload.h @@ -0,0 +1,35 @@ +#ifndef SRC_YANGRTP_YANGAUDIOPAYLOAD_H_ +#define SRC_YANGRTP_YANGAUDIOPAYLOAD_H_ + +#include +class YangAudioPayload : public YangCodecPayload +{ + struct SrsOpusParameter + { + int32_t minptime; + bool use_inband_fec; + bool usedtx; + + SrsOpusParameter() { + minptime = 0; + use_inband_fec = false; + usedtx = false; + } + }; + +public: + int32_t m_channel; + SrsOpusParameter m_opus_param; +public: + YangAudioPayload(); + YangAudioPayload(uint8_t pt, std::string encode_name, int32_t sample, int32_t channel); + virtual ~YangAudioPayload(); +public: + virtual YangAudioPayload* copy(); + virtual YangMediaPayloadType generate_media_payload_type(); +public: + int32_t set_opus_param_desc(std::string fmtp); +}; + + +#endif /* SRC_YANGRTP_YANGAUDIOPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangCodecPayload.cpp b/libyangrtc2/src/yangrtp/YangCodecPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1092da07e284e6032da12799f2b0aa25bf2ac221 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangCodecPayload.cpp @@ -0,0 +1,45 @@ +#include + + + +YangCodecPayload::YangCodecPayload() +{ + m_pt_of_publisher = m_pt = 0; + m_sample = 0; +} + +YangCodecPayload::YangCodecPayload(uint8_t pt, std::string encode_name, int32_t sample) +{ + m_pt_of_publisher = m_pt = pt; + m_name = encode_name; + m_sample = sample; +} + +YangCodecPayload::~YangCodecPayload() +{ +} + +YangCodecPayload* YangCodecPayload::copy() +{ + YangCodecPayload* cp = new YangCodecPayload(); + + cp->m_type = m_type; + cp->m_pt = m_pt; + cp->m_pt_of_publisher = m_pt_of_publisher; + cp->m_name = m_name; + cp->m_sample = m_sample; + cp->m_rtcp_fbs = m_rtcp_fbs; + + return cp; +} + +YangMediaPayloadType YangCodecPayload::generate_media_payload_type() +{ + YangMediaPayloadType media_payload_type(m_pt); + + media_payload_type.m_encoding_name = m_name; + media_payload_type.m_clock_rate = m_sample; + media_payload_type.m_rtcp_fb = m_rtcp_fbs; + + return media_payload_type; +} diff --git a/libyangrtc2/src/yangrtp/YangCodecPayload.h b/libyangrtc2/src/yangrtp/YangCodecPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..944dc326459cf6554d8419e3eeeead7eeaffb9b3 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangCodecPayload.h @@ -0,0 +1,28 @@ +#ifndef SRC_YANGRTP_YANGCODECPAYLOAD_H_ +#define SRC_YANGRTP_YANGCODECPAYLOAD_H_ +#include +#include +#include +#include +// TODO: FIXME: Rename it. +class YangCodecPayload +{ +public: + std::string m_type; + uint8_t m_pt; + // for publish, equals to PT of itself; + // for subscribe, is the PT of publisher; + uint8_t m_pt_of_publisher; + std::string m_name; + int32_t m_sample; + + std::vector m_rtcp_fbs; +public: + YangCodecPayload(); + YangCodecPayload(uint8_t pt, std::string encode_name, int32_t sample); + virtual ~YangCodecPayload(); +public: + virtual YangCodecPayload* copy(); + virtual YangMediaPayloadType generate_media_payload_type(); +}; +#endif /* SRC_YANGRTP_YANGCODECPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangMediaPayloadType.cpp b/libyangrtc2/src/yangrtp/YangMediaPayloadType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c17a30cad45a8683086e50f537e3473e5fb7262 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangMediaPayloadType.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#define kCRLF "\r\n" +YangMediaPayloadType::YangMediaPayloadType(int32_t payload_type) +{ + m_payload_type = payload_type; + m_clock_rate = 0; +} + +YangMediaPayloadType::~YangMediaPayloadType() +{ +} + +int32_t YangMediaPayloadType::encode(std::stringstream& os) +{ + int32_t err = Yang_Ok; + + os << "a=rtpmap:" << m_payload_type << " " << m_encoding_name << "/" << m_clock_rate; + if (!m_encoding_param.empty()) { + os << "/" << m_encoding_param; + } + os << kCRLF; + + for (std::vector::iterator iter = m_rtcp_fb.begin(); iter != m_rtcp_fb.end(); ++iter) { + os << "a=rtcp-fb:" << m_payload_type << " " << *iter << kCRLF; + } + + if (!m_format_specific_param.empty()) { + os << "a=fmtp:" << m_payload_type << " " << m_format_specific_param + // TODO: FIXME: Remove the test code bellow. + // << ";x-google-max-bitrate=6000;x-google-min-bitrate=5100;x-google-start-bitrate=5000" + << kCRLF; + } + + return err; +} + diff --git a/libyangrtc2/src/yangrtp/YangMediaPayloadType.h b/libyangrtc2/src/yangrtp/YangMediaPayloadType.h new file mode 100644 index 0000000000000000000000000000000000000000..1d982eddf8fc1dbdacad5812e3ba26b50f1ed135 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangMediaPayloadType.h @@ -0,0 +1,24 @@ +#ifndef SRC_YANGRTP_YANGMEDIAPAYLOADTYPE_H_ +#define SRC_YANGRTP_YANGMEDIAPAYLOADTYPE_H_ +#include +#include +#include +class YangMediaPayloadType +{ +public: + YangMediaPayloadType(int32_t payload_type); + virtual ~YangMediaPayloadType(); + + int32_t encode(std::stringstream& os); +public: + int32_t m_payload_type; + + std::string m_encoding_name; + int32_t m_clock_rate; + std::string m_encoding_param; + + std::vector m_rtcp_fb; + std::string m_format_specific_param; +}; + +#endif /* SRC_YANGRTP_YANGMEDIAPAYLOADTYPE_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangMixQueue.cpp b/libyangrtc2/src/yangrtp/YangMixQueue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c08e32d423076357b40fd74a576d3dd0d7e2b00e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangMixQueue.cpp @@ -0,0 +1,81 @@ +#include +#include + +YangMixQueue::YangMixQueue() +{ + nb_videos = 0; + nb_audios = 0; + m_audio_size=YANG_MIX_CORRECT_PURE_AV_AUDIO; + m_video_size=YANG_MIX_CORRECT_PURE_AV_VIDEO; +} + +YangMixQueue::~YangMixQueue() +{ + clear(); +} +void YangMixQueue::setAudioSize(uint32_t asize){ + m_audio_size=asize; +} + void YangMixQueue::setVideoSize(uint32_t vsize){ + m_video_size=vsize; + } +void YangMixQueue::clear() +{ + std::multimap::iterator it; + for (it = msgs.begin(); it != msgs.end(); ++it) { + YangMessage* msg = it->second; + yang_delete(msg); + } + msgs.clear(); + + nb_videos = 0; + nb_audios = 0; +} + +void YangMixQueue::push(YangMessage* msg) +{ + msgs.insert(std::make_pair(msg->timestamp, msg)); + + if (msg->mediaType==1) { + nb_videos++; + } else { + nb_audios++; + } +} + +YangMessage* YangMixQueue::pop() +{ + bool mix_ok = false; + + // pure video + if (nb_videos >= m_video_size && nb_audios == 0) { + mix_ok = true; + } + + // pure audio + if (nb_audios >= m_audio_size && nb_videos == 0) { + mix_ok = true; + } + + // got 1 video and 1 audio, mix ok. + if (nb_videos >= 1 && nb_audios >= 1) { + mix_ok = true; + } + + if (!mix_ok) { + return NULL; + } + + // pop the first msg. + std::multimap::iterator it = msgs.begin(); + YangMessage* msg = it->second; + msgs.erase(it); + + if (msg->mediaType==1) { + nb_videos--; + } else { + nb_audios--; + } + + return msg; +} diff --git a/libyangrtc2/src/yangrtp/YangMixQueue.h b/libyangrtc2/src/yangrtp/YangMixQueue.h new file mode 100644 index 0000000000000000000000000000000000000000..8e8223c052d04e6d9b1d6153c7d80fb2fe6bac0e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangMixQueue.h @@ -0,0 +1,25 @@ +#ifndef SRC_YANGRTP_YANGMIXQUEUE_H_ +#define SRC_YANGRTP_YANGMIXQUEUE_H_ +#include +#include +#define YANG_MIX_CORRECT_PURE_AV_VIDEO 10 +#define YANG_MIX_CORRECT_PURE_AV_AUDIO 5 +class YangMixQueue +{ +private: + uint32_t nb_videos; + uint32_t nb_audios; + int m_audio_size; + int m_video_size; + std::multimap msgs; +public: + YangMixQueue(); + virtual ~YangMixQueue(); +public: + virtual void clear(); + virtual void push(YangMessage* msg); + virtual YangMessage* pop(); + void setAudioSize(uint32_t asize); + void setVideoSize(uint32_t vsize); +}; +#endif /* SRC_YANGRTP_YANGMIXQUEUE_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangPublishNackBuffer.cpp b/libyangrtc2/src/yangrtp/YangPublishNackBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72b5e9b50dcd2c75f140639a9c360a70b0d11f05 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangPublishNackBuffer.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +YangPublishNackBuffer::YangPublishNackBuffer(int32_t capacity) { + m_capacity = (uint16_t)capacity; + m_queue = new YangPublishBuffer*[m_capacity]; + memset(m_queue, 0, sizeof(YangPublishBuffer*) * capacity); + +} + +YangPublishNackBuffer::~YangPublishNackBuffer() { + for (int32_t i = 0; i < m_capacity; ++i) { + YangPublishBuffer* pkt = m_queue[i]; + yang_delete(pkt); + } + yang_deleteA(m_queue); +} +YangPublishBuffer* YangPublishNackBuffer::at(uint16_t seq) { + return m_queue[seq % m_capacity]; +} + +void YangPublishNackBuffer::set(uint16_t at, char* data,int plen) +{ + YangPublishBuffer* p = m_queue[at % m_capacity]; + yang_delete(p); + if(data){ + YangPublishBuffer *p1=new YangPublishBuffer(); + p1->payload=data; + p1->nb=plen; + p1->seq=at; + m_queue[at % m_capacity] = p1; + }else{ + m_queue[at % m_capacity]=NULL; + } +} + +void YangPublishNackBuffer::remove(uint16_t at) +{ + set(at, NULL,0); +} diff --git a/libyangrtc2/src/yangrtp/YangPublishNackBuffer.h b/libyangrtc2/src/yangrtp/YangPublishNackBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..dbb202aa7be555e19c2cf8932be8c75d837726a0 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangPublishNackBuffer.h @@ -0,0 +1,25 @@ +#ifndef SRC_YANGRTP_YANGPUBLISHNACKBUFFER_H_ +#define SRC_YANGRTP_YANGPUBLISHNACKBUFFER_H_ +#include +//#include +struct YangPublishBuffer{ + uint16_t seq; + int nb; + char* payload; + +}; +class YangPublishNackBuffer { +public: + YangPublishNackBuffer(int32_t capacity); + virtual ~YangPublishNackBuffer(); + + void set(uint16_t at, char* p,int plen); + void remove(uint16_t at); + YangPublishBuffer* at(uint16_t seq); +private: + uint16_t m_capacity; + // Ring bufer. + YangPublishBuffer** m_queue; +}; + +#endif /* SRC_YANGRTP_YANGPUBLISHNACKBUFFER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRedPayload.cpp b/libyangrtc2/src/yangrtp/YangRedPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c02acef760e2d550b9e04420947794e5c829c30 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRedPayload.cpp @@ -0,0 +1,47 @@ +#include +#include + +YangRedPayload::YangRedPayload() +{ + m_channel = 0; +} + +YangRedPayload::YangRedPayload(uint8_t pt, std::string encode_name, int32_t sample, int32_t channel) + :YangCodecPayload(pt, encode_name, sample) +{ + m_channel = channel; +} + +YangRedPayload::~YangRedPayload() +{ +} + +YangRedPayload* YangRedPayload::copy() +{ + YangRedPayload* cp = new YangRedPayload(); + + cp->m_type = m_type; + cp->m_pt = m_pt; + cp->m_pt_of_publisher = m_pt_of_publisher; + cp->m_name = m_name; + cp->m_sample = m_sample; + cp->m_rtcp_fbs = m_rtcp_fbs; + cp->m_channel = m_channel; + + return cp; +} + +YangMediaPayloadType YangRedPayload::generate_media_payload_type() +{ + YangMediaPayloadType media_payload_type(m_pt); + + media_payload_type.m_encoding_name = m_name; + media_payload_type.m_clock_rate = m_sample; + if (m_channel != 0) { + media_payload_type.m_encoding_param = yang_int2str(m_channel); + } + media_payload_type.m_rtcp_fb = m_rtcp_fbs; + + return media_payload_type; +} + diff --git a/libyangrtc2/src/yangrtp/YangRedPayload.h b/libyangrtc2/src/yangrtp/YangRedPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..e966700e7774909c267f89aa293d1a7a4ac27420 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRedPayload.h @@ -0,0 +1,16 @@ +#ifndef SRC_YANGRTP_YANGREDPAYLOAD_H_ +#define SRC_YANGRTP_YANGREDPAYLOAD_H_ +#include +class YangRedPayload : public YangCodecPayload +{ +public: + int32_t m_channel; +public: + YangRedPayload(); + YangRedPayload(uint8_t pt, std::string encode_name, int32_t sample, int32_t channel); + virtual ~YangRedPayload(); +public: + virtual YangRedPayload* copy(); + virtual YangMediaPayloadType generate_media_payload_type(); +}; +#endif /* SRC_YANGRTP_YANGREDPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcp.h b/libyangrtc2/src/yangrtp/YangRtcp.h new file mode 100644 index 0000000000000000000000000000000000000000..0d1566a9d2555a83afdad185d3542b085795a6af --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcp.h @@ -0,0 +1,47 @@ + + +#ifndef YANGWEBRTC_YANGRTCRTCP_H_ +#define YANGWEBRTC_YANGRTCRTCP_H_ + +#include + +// RTCP Packet Types, @see http://www.networksorcery.com/enp/protocol/rtcp.htm +enum YangRtcpType +{ + YangRtcpType_fir = 192, + YangRtcpType_sr = 200, + YangRtcpType_rr = 201, + YangRtcpType_sdes = 202, + YangRtcpType_bye = 203, + YangRtcpType_app = 204, + YangRtcpType_rtpfb = 205, + YangRtcpType_psfb = 206, + YangRtcpType_xr = 207, +}; + + + +// RTCP Header, @see http://tools.ietf.org/html/rfc3550#section-6.1 +// @remark The header must be 4 bytes, which align with the max field size 2B. +struct YangRtcpHeader +{ + uint16_t rc:5; + uint16_t padding:1; + uint16_t version:2; + uint16_t type:8; + + uint16_t length:16; + + YangRtcpHeader() { + rc = 0; + padding = 0; + version = 0; + type = 0; + length = 0; + } +}; + + + + +#endif /* YANGWEBRTC_YANGRTCRTCP_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpApp.cpp b/libyangrtc2/src/yangrtp/YangRtcpApp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b77297694d6d8a8a1a11ea4fdbbdd07fb9b2ac49 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpApp.cpp @@ -0,0 +1,169 @@ +#include +#include + +YangRtcpApp::YangRtcpApp() +{ + m_ssrc = 0; + m_header.padding = 0; + m_header.type = YangRtcpType_app; + m_header.rc = 0; + m_header.version = kRtcpVersion; +} + +YangRtcpApp::~YangRtcpApp() +{ +} + +bool YangRtcpApp::is_rtcp_app(uint8_t *data, int32_t nb_data) +{ + if (!data || nb_data <12) { + return false; + } + + YangRtcpHeader *header = (YangRtcpHeader*)data; + if (header->version == kRtcpVersion + && header->type == YangRtcpType_app + && ntohs(header->length) >= 2) { + return true; + } + + return false; +} + +uint8_t YangRtcpApp::type() const +{ + return YangRtcpType_app; +} + +uint8_t YangRtcpApp::get_subtype() const +{ + return m_header.rc; +} + +string YangRtcpApp::get_name() const +{ + return string((char*)m_name, strnlen((char*)m_name, 4)); +} + +int32_t YangRtcpApp::get_payload(uint8_t*& payload, int& len) +{ + len = m_payload_len; + payload = m_payload; + + return Yang_Ok; +} + +int32_t YangRtcpApp::set_subtype(uint8_t type) +{ + if(31 < type) { + return yang_error_wrap(ERROR_RTC_RTCP, "invalid type: %d", type); + } + + m_header.rc = type; + + return Yang_Ok; +} + +int32_t YangRtcpApp::set_name(std::string name) +{ + if(name.length() > 4) { + return yang_error_wrap(ERROR_RTC_RTCP, "invalid name length %zu", name.length()); + } + + memset(m_name, 0, sizeof(m_name)); + memcpy(m_name, name.c_str(), name.length()); + + return Yang_Ok; +} + +int32_t YangRtcpApp::set_payload(uint8_t* payload, int32_t len) +{ + if(len > (kRtcpPacketSize - 12)) { + return yang_error_wrap(ERROR_RTC_RTCP, "invalid payload length %d", len); + } + + m_payload_len = (len + 3)/ 4 * 4;; + memcpy(m_payload, payload, len); + if (m_payload_len > len) { + memset(&m_payload[len], 0, m_payload_len - len); //padding + } + m_header.length = m_payload_len/4 + 3 - 1; + + return Yang_Ok; +} + +int32_t YangRtcpApp::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc3550#section-6.7 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| subtype | PT=APP=204 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC/CSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | name (ASCII) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | application-dependent data ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + if (m_header.type != YangRtcpType_app || !buffer->require(4)) { + return yang_error_wrap(ERROR_RTC_RTCP, "not rtcp app"); + } + + buffer->read_bytes((char *)m_name, sizeof(m_name)); + + // TODO: FIXME: Should check size? + m_payload_len = (m_header.length + 1) * 4 - 8 - sizeof(m_name); + if (m_payload_len > 0) { + buffer->read_bytes((char *)m_payload, m_payload_len); + } + + return Yang_Ok; +} + +uint64_t YangRtcpApp::nb_bytes() +{ + return sizeof(YangRtcpHeader) + sizeof(m_ssrc) + sizeof(m_name) + m_payload_len; +} + +int32_t YangRtcpApp::encode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc3550#section-6.7 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| subtype | PT=APP=204 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC/CSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | name (ASCII) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | application-dependent data ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + if(Yang_Ok != (err = encode_header(buffer))) { + return yang_error_wrap(err, "encode header"); + } + + buffer->write_bytes((char*)m_name, sizeof(m_name)); + buffer->write_bytes((char*)m_payload, m_payload_len); + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpApp.h b/libyangrtc2/src/yangrtp/YangRtcpApp.h new file mode 100644 index 0000000000000000000000000000000000000000..628b3b44a409a3df396e6a3e335dc0c2a67d169c --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpApp.h @@ -0,0 +1,33 @@ +#ifndef SRC_YANGRTP_YANGRTCPAPP_H_ +#define SRC_YANGRTP_YANGRTCPAPP_H_ +#include + + +class YangRtcpApp : public YangRtcpCommon +{ +private: + uint8_t m_name[4]; +public: + YangRtcpApp(); + virtual ~YangRtcpApp(); + + static bool is_rtcp_app(uint8_t *data, int32_t nb_data); + + virtual uint8_t type() const; + + uint8_t get_subtype() const; + std::string get_name() const; + int32_t get_payload(uint8_t*& payload, int& len); + + int32_t set_subtype(uint8_t type); + int32_t set_name(std::string name); + int32_t set_payload(uint8_t* payload, int32_t len); +// interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + + +#endif /* SRC_YANGRTP_YANGRTCPAPP_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpCommon.cpp b/libyangrtc2/src/yangrtp/YangRtcpCommon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..284548e987602d21aa6eded0c9dffb1a1f2d075a --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpCommon.cpp @@ -0,0 +1,97 @@ +#include +#include +YangRtcpCommon::YangRtcpCommon(): m_ssrc(0), m_data(NULL), m_nb_data(0) +{ + m_payload_len = 0; +} + +YangRtcpCommon::~YangRtcpCommon() +{ +} + +uint8_t YangRtcpCommon::type() const +{ + return m_header.type; +} + +uint8_t YangRtcpCommon::get_rc() const +{ + return m_header.rc; +} + +uint32_t YangRtcpCommon::get_ssrc() +{ + return m_ssrc; +} + +void YangRtcpCommon::set_ssrc(uint32_t ssrc) +{ + m_ssrc = ssrc; +} + +char* YangRtcpCommon::data() +{ + return m_data; +} + +int32_t YangRtcpCommon::size() +{ + return m_nb_data; +} + +int32_t YangRtcpCommon::decode_header(YangBuffer *buffer) +{ + if (!buffer->require(sizeof(YangRtcpHeader) + 4)) { + return yang_error_wrap(ERROR_RTC_RTCP, "require %d", sizeof(YangRtcpHeader) + 4); + } + + buffer->read_bytes((char*)(&m_header), sizeof(YangRtcpHeader)); + m_header.length = ntohs(m_header.length); + + int32_t payload_len = m_header.length * 4; + if (payload_len > buffer->left()) { + return yang_error_wrap(ERROR_RTC_RTCP, + "require payload len=%u, buffer left=%u", payload_len, buffer->left()); + } + m_ssrc = buffer->read_4bytes(); + + return Yang_Ok; +} + +int32_t YangRtcpCommon::encode_header(YangBuffer *buffer) +{ + if(! buffer->require(sizeof(YangRtcpHeader) + 4)) { + return yang_error_wrap(ERROR_RTC_RTCP, "require %d", sizeof(YangRtcpHeader) + 4); + } + m_header.length = htons(m_header.length); + buffer->write_bytes((char*)(&m_header), sizeof(YangRtcpHeader)); + buffer->write_4bytes(m_ssrc); + + return Yang_Ok; +} + +int32_t YangRtcpCommon::decode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_payload_len = (m_header.length + 1) * 4 - sizeof(YangRtcpHeader) - 4; + buffer->read_bytes((char *)m_payload, m_payload_len); + + return err; +} + +uint64_t YangRtcpCommon::nb_bytes() +{ + return sizeof(YangRtcpHeader) + 4 + m_payload_len; +} + +int32_t YangRtcpCommon::encode(YangBuffer *buffer) +{ + return yang_error_wrap(ERROR_RTC_RTCP, "not implement"); +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpCommon.h b/libyangrtc2/src/yangrtp/YangRtcpCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..8b2bdcab03ccacbcf645e06cf6b650ece79bd80d --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpCommon.h @@ -0,0 +1,65 @@ +#ifndef SRC_YANGRTP_YANGRTCPCOMMON_H_ +#define SRC_YANGRTP_YANGRTCPCOMMON_H_ + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +struct YangRtcpRB +{ + uint32_t ssrc; + uint8_t fraction_lost; + uint32_t lost_packets; + uint32_t highest_sn; + uint32_t jitter; + uint32_t lsr; + uint32_t dlsr; + + YangRtcpRB() { + ssrc = 0; + fraction_lost = 0; + lost_packets = 0; + highest_sn = 0; + jitter = 0; + lsr = 0; + dlsr = 0; + } +}; + +class YangRtcpCommon +{ +protected: + YangRtcpHeader m_header; + uint32_t m_ssrc; + uint8_t m_payload[kRtcpPacketSize]; + int32_t m_payload_len; + + char* m_data; + int32_t m_nb_data; +protected: + int32_t decode_header(YangBuffer *buffer); + int32_t encode_header(YangBuffer *buffer); +public: + YangRtcpCommon(); + virtual ~YangRtcpCommon(); + virtual uint8_t type() const; + virtual uint8_t get_rc() const; + + uint32_t get_ssrc(); + void set_ssrc(uint32_t ssrc); + + char* data(); + int32_t size(); +// interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; +#endif /* SRC_YANGRTP_YANGRTCPCOMMON_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpCompound.cpp b/libyangrtc2/src/yangrtp/YangRtcpCompound.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42377b65a8a62127d1a7ebf85e1cb6584f793f6f --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpCompound.cpp @@ -0,0 +1,150 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +YangRtcpCompound::YangRtcpCompound(): m_nb_bytes(0), m_data(NULL), m_nb_data(0) +{ +} + +YangRtcpCompound::~YangRtcpCompound() +{ + clear(); +} + +YangRtcpCommon* YangRtcpCompound::get_next_rtcp() +{ + if(m_rtcps.empty()) { + return NULL; + } + YangRtcpCommon *rtcp = m_rtcps.back(); + m_rtcps.pop_back(); + return rtcp; +} + +int32_t YangRtcpCompound::add_rtcp(YangRtcpCommon *rtcp) +{ + int32_t new_len = rtcp->nb_bytes(); + if((new_len + m_nb_bytes) > kRtcpPacketSize) { + return yang_error_wrap(ERROR_RTC_RTCP, "overflow, new rtcp: %d, current: %d", new_len, m_nb_bytes); + } + m_nb_bytes += new_len; + m_rtcps.push_back(rtcp); + + return Yang_Ok; +} + +int32_t YangRtcpCompound::decode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + m_data = buffer->data(); + m_nb_data = buffer->size(); + + while (!buffer->empty()) { + YangRtcpCommon* rtcp = NULL; + YangRtcpHeader* header = (YangRtcpHeader*)(buffer->head()); + if (header->type == YangRtcpType_sr) { + rtcp = new YangRtcpSR(); + } else if (header->type == YangRtcpType_rr) { + rtcp = new YangRtcpRR(); + } else if (header->type == YangRtcpType_rtpfb) { + if(1 == header->rc) { + //nack + rtcp = new YangRtcpNack(); + } else if (15 == header->rc) { + //twcc + rtcp = new YangRtcpTWCC(); + } + } else if(header->type == YangRtcpType_psfb) { + if(1 == header->rc) { + // pli + rtcp = new YangRtcpPli(); + } else if(2 == header->rc) { + //sli + rtcp = new YangRtcpSli(); + } else if(3 == header->rc) { + //rpsi + rtcp = new YangRtcpRpsi(); + } else { + // common psfb + rtcp = new YangRtcpPsfbCommon(); + } + } else if(header->type == YangRtcpType_xr) { + rtcp = new YangRtcpXr(); + } else { + rtcp = new YangRtcpCommon(); + } + + if(Yang_Ok != (err = rtcp->decode(buffer))) { + yang_delete(rtcp); + + // @doc https://tools.ietf.org/html/rfc3550#section-6.4.2 + // An empty RR packet (RC = 0) MUST be put at the head of a compound + // RTCP packet when there is no data transmission or reception to + // report. e.g. {80 c9 00 01 00 00 00 01} + if (ERROR_RTC_RTCP_EMPTY_RR == err) { + //srs_freep(err); + continue; + } + + return yang_error_wrap(err, "decode rtcp type=%u rc=%u", header->type, header->rc); + } + + m_rtcps.push_back(rtcp); + } + + return err; +} + +uint64_t YangRtcpCompound::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpCompound::encode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + if(!buffer->require(m_nb_bytes)) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", m_nb_bytes); + } + + vector::iterator it; + for(it = m_rtcps.begin(); it != m_rtcps.end(); ++it) { + YangRtcpCommon *rtcp = *it; + if((err = rtcp->encode(buffer)) != Yang_Ok) { + return yang_error_wrap(err, "encode compound type:%d", rtcp->type()); + } + } + + clear(); + return err; +} + +void YangRtcpCompound::clear() +{ + vector::iterator it; + for(it = m_rtcps.begin(); it != m_rtcps.end(); ++it) { + YangRtcpCommon *rtcp = *it; + delete rtcp; + rtcp = NULL; + } + m_rtcps.clear(); + m_nb_bytes = 0; +} + +char* YangRtcpCompound::data() +{ + return m_data; +} + +int32_t YangRtcpCompound::size() +{ + return m_nb_data; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpCompound.h b/libyangrtc2/src/yangrtp/YangRtcpCompound.h new file mode 100644 index 0000000000000000000000000000000000000000..935a6821ddcd4430efdf353bb2c0419524475706 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpCompound.h @@ -0,0 +1,32 @@ + +#ifndef SRC_YANGRTP_YANGRTCPCOMPOUND_H_ +#define SRC_YANGRTP_YANGRTCPCOMPOUND_H_ +#include + +class YangRtcpCompound //: public IYangCodec +{ +private: + std::vector m_rtcps; + int32_t m_nb_bytes; + char* m_data; + int32_t m_nb_data; +public: + YangRtcpCompound(); + virtual ~YangRtcpCompound(); + + // TODO: FIXME: Should rename it to pop(), because it's not a GET method. + YangRtcpCommon* get_next_rtcp(); + int32_t add_rtcp(YangRtcpCommon *rtcp); + void clear(); + + char* data(); + int32_t size(); + +// interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + +#endif /* SRC_YANGRTP_YANGRTCPCOMPOUND_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpNack.cpp b/libyangrtc2/src/yangrtp/YangRtcpNack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e41645edd6893fdd00b9e484bfa160b8d70b1f6 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpNack.cpp @@ -0,0 +1,173 @@ +#include +#include + +YangRtcpNack::YangRtcpNack(uint32_t sender_ssrc) +{ + m_header.padding = 0; + m_header.type = YangRtcpType_rtpfb; + m_header.rc = 1; + m_header.version = kRtcpVersion; + m_ssrc = sender_ssrc; + m_media_ssrc_ = 0; +} + +YangRtcpNack::~YangRtcpNack() +{ +} + +uint32_t YangRtcpNack::get_media_ssrc() const +{ + return m_media_ssrc_; +} + +vector YangRtcpNack::get_lost_sns() const +{ + vector sn; + for(set::iterator it = m_lost_sns.begin(); it != m_lost_sns.end(); ++it) { + sn.push_back(*it); + } + return sn; +} + +bool YangRtcpNack::empty() +{ + return m_lost_sns.empty(); +} + +void YangRtcpNack::set_media_ssrc(uint32_t ssrc) +{ + m_media_ssrc_ = ssrc; +} + +void YangRtcpNack::add_lost_sn(uint16_t sn) +{ + m_lost_sns.insert(sn); +} + +int32_t YangRtcpNack::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + + Generic NACK + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PID | BLP | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_media_ssrc_ = buffer->read_4bytes(); + char bitmask[20]; + for(int32_t i = 0; i < (m_header.length - 2); i++) { + uint16_t pid = buffer->read_2bytes(); + uint16_t blp = buffer->read_2bytes(); + m_lost_sns.insert(pid); + memset(bitmask, 0, 20); + for(int32_t j=0; j<16; j++) { + bitmask[j] = (blp & ( 1 << j )) >> j ? '1' : '0'; + if((blp & ( 1 << j )) >> j) + m_lost_sns.insert(pid+j+1); + } + bitmask[16] = '\n'; + //srs_info("[%d] %d / %s", i, pid, bitmask); + } + + return err; +} +uint64_t YangRtcpNack::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpNack::encode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + + Generic NACK + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PID | BLP | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + vector chunks; + do { + YangPidBlp chunk; + chunk.in_use = false; + uint16_t pid = 0; + for(set::iterator it = m_lost_sns.begin(); it != m_lost_sns.end(); ++it) { + uint16_t sn = *it; + + if(!chunk.in_use) { + chunk.pid = sn; + chunk.blp = 0; + chunk.in_use = true; + pid = sn; + continue; + } + if((sn - pid) < 1) { + yang_info("skip seq %d", sn); + } else if( (sn - pid) > 16) { + // add new chunk + chunks.push_back(chunk); + chunk.in_use = false; + } else { + chunk.blp |= 1 << (sn-pid-1); + } + } + if(chunk.in_use) { + chunks.push_back(chunk); + } + + m_header.length = 2 + chunks.size(); + if(Yang_Ok != (err = encode_header(buffer))) { + err = yang_error_wrap(err, "encode header"); + break; + } + + buffer->write_4bytes(m_media_ssrc_); + for(vector::iterator it_chunk = chunks.begin(); it_chunk != chunks.end(); it_chunk++) { + buffer->write_2bytes(it_chunk->pid); + // yang_trace("\nsend seq====%hu",it_chunk->pid); + buffer->write_2bytes(it_chunk->blp); + } + } while(0); + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpNack.h b/libyangrtc2/src/yangrtp/YangRtcpNack.h new file mode 100644 index 0000000000000000000000000000000000000000..3d4a4ce541037b996a2beec6a84f48a9f05ccab9 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpNack.h @@ -0,0 +1,35 @@ +#ifndef SRC_YANGRTP_YANGRTCPNACK_H_ +#define SRC_YANGRTP_YANGRTCPNACK_H_ +#include +#include +#include +class YangRtcpNack : public YangRtcpCommon +{ +private: + struct YangPidBlp { + uint16_t pid; + uint16_t blp; + bool in_use; + }; + + uint32_t m_media_ssrc_; + std::set m_lost_sns; +public: + YangRtcpNack(uint32_t sender_ssrc = 0); + virtual ~YangRtcpNack(); + + uint32_t get_media_ssrc() const; + std::vector get_lost_sns() const; + bool empty(); + + void set_media_ssrc(uint32_t ssrc); + void add_lost_sn(uint16_t sn); + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + + +#endif /* SRC_YANGRTP_YANGRTCPNACK_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpPli.cpp b/libyangrtc2/src/yangrtp/YangRtcpPli.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2396ced6c5e6466a7ff9b81003a3e1876a2b8d1d --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpPli.cpp @@ -0,0 +1,81 @@ +#include +#include + + +YangRtcpPli::YangRtcpPli(uint32_t sender_ssrc/*= 0*/) +{ + m_header.padding = 0; + m_header.type = YangRtcpType_psfb; + m_header.rc = kPLI; + m_header.version = kRtcpVersion; + m_ssrc = sender_ssrc; +} + +YangRtcpPli::~YangRtcpPli() +{ +} + +int32_t YangRtcpPli::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + */ + + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_media_ssrc = buffer->read_4bytes(); + return err; +} + +uint64_t YangRtcpPli::nb_bytes() +{ + return 12; +} + +int32_t YangRtcpPli::encode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + */ + int32_t err = Yang_Ok; + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + m_header.length = 2; + if(Yang_Ok != (err = encode_header(buffer))) { + return yang_error_wrap(err, "encode header"); + } + + buffer->write_4bytes(m_media_ssrc); + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpPli.h b/libyangrtc2/src/yangrtp/YangRtcpPli.h new file mode 100644 index 0000000000000000000000000000000000000000..53e26459b3c6672efb9a82b85c821ddd8c5db25f --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpPli.h @@ -0,0 +1,17 @@ +#ifndef SRC_YANGRTP_YANGRTCPPLI_H_ +#define SRC_YANGRTP_YANGRTCPPLI_H_ +#include +class YangRtcpPli : public YangRtcpPsfbCommon +{ +public: + YangRtcpPli(uint32_t sender_ssrc = 0); + virtual ~YangRtcpPli(); + + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + +#endif /* SRC_YANGRTP_YANGRTCPPLI_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.cpp b/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac0d8da7ae9b39810b53a1875b7373c0f81a60f9 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.cpp @@ -0,0 +1,68 @@ +#include +#include + + +YangRtcpPsfbCommon::YangRtcpPsfbCommon() +{ + m_header.padding = 0; + m_header.type = YangRtcpType_psfb; + m_header.rc = 1; + m_header.version = kRtcpVersion; + //ssrc_ = sender_ssrc; +} + +YangRtcpPsfbCommon::~YangRtcpPsfbCommon() +{ + +} + +uint32_t YangRtcpPsfbCommon::get_media_ssrc() const +{ + return m_media_ssrc; +} + +void YangRtcpPsfbCommon::set_media_ssrc(uint32_t ssrc) +{ + m_media_ssrc = ssrc; +} + +int32_t YangRtcpPsfbCommon::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + */ + + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_media_ssrc = buffer->read_4bytes(); + int32_t len = (m_header.length + 1) * 4 - 12; + buffer->skip(len); + return err; +} + +uint64_t YangRtcpPsfbCommon::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpPsfbCommon::encode(YangBuffer *buffer) +{ + return yang_error_wrap(ERROR_RTC_RTCP, "not support"); +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.h b/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..ebc875377b4e43f3da81caa59c7cecc3fd444f40 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpPsfbCommon.h @@ -0,0 +1,21 @@ +#ifndef SRC_YANGRTP_YANGRTCPPSFBCOMMON_H_ +#define SRC_YANGRTP_YANGRTCPPSFBCOMMON_H_ +#include + +class YangRtcpPsfbCommon : public YangRtcpCommon +{ +protected: + uint32_t m_media_ssrc; +public: + YangRtcpPsfbCommon(); + virtual ~YangRtcpPsfbCommon(); + + uint32_t get_media_ssrc() const; + void set_media_ssrc(uint32_t ssrc); + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; +#endif /* SRC_YANGRTP_YANGRTCPPSFBCOMMON_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpRR.cpp b/libyangrtc2/src/yangrtp/YangRtcpRR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a0c9ac945e64494901305271cb2006b5aeda577 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpRR.cpp @@ -0,0 +1,223 @@ +#include +#include +#include + + +YangRtcpRR::YangRtcpRR(uint32_t sender_ssrc) +{ + m_header.padding = 0; + m_header.type = YangRtcpType_rr; + m_header.rc = 0; + m_header.version = kRtcpVersion; + m_header.length = 7; + m_ssrc = sender_ssrc; + // TODO: FIXME: Fix warning. + // memset(&m_rb, 0, sizeof(YangRtcpRB)); +} +YangRtcpRR::~YangRtcpRR() +{ +} + +uint8_t YangRtcpRR::type() const +{ + return YangRtcpType_rr; +} + +uint32_t YangRtcpRR::get_rb_ssrc() const +{ + return m_rb.ssrc; +} + +float YangRtcpRR::get_lost_rate() const +{ + return m_rb.fraction_lost / 256; +} + +uint32_t YangRtcpRR::get_lost_packets() const +{ + return m_rb.lost_packets; +} + +uint32_t YangRtcpRR::get_highest_sn() const +{ + return m_rb.highest_sn; +} + +uint32_t YangRtcpRR::get_jitter() const +{ + return m_rb.jitter; +} + +uint32_t YangRtcpRR::get_lsr() const +{ + return m_rb.lsr; +} + +uint32_t YangRtcpRR::get_dlsr() const +{ + return m_rb.dlsr; +} + +void YangRtcpRR::set_rb_ssrc(uint32_t ssrc) +{ + m_rb.ssrc = ssrc; +} + +void YangRtcpRR::set_lost_rate(float rate) +{ + m_rb.fraction_lost = rate * 256; +} + +void YangRtcpRR::set_lost_packets(uint32_t count) +{ + m_rb.lost_packets = count; +} + +void YangRtcpRR::set_highest_sn(uint32_t sn) +{ + m_rb.highest_sn = sn; +} + +void YangRtcpRR::set_jitter(uint32_t jitter) +{ + m_rb.jitter = jitter; +} + +void YangRtcpRR::set_lsr(uint32_t lsr) +{ + m_rb.lsr = lsr; +} + +void YangRtcpRR::set_dlsr(uint32_t dlsr) +{ + m_rb.dlsr = dlsr; +} + +void YangRtcpRR::set_sender_ntp(uint64_t ntp) +{ + uint32_t lsr = (uint32_t)((ntp >> 16) & 0x00000000FFFFFFFF); + m_rb.lsr = lsr; +} + +int32_t YangRtcpRR::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc3550#section-6.4.2 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=RR=201 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + // @doc https://tools.ietf.org/html/rfc3550#section-6.4.2 + // An empty RR packet (RC = 0) MUST be put at the head of a compound + // RTCP packet when there is no data transmission or reception to + // report. e.g. {80 c9 00 01 00 00 00 01} + if(m_header.rc == 0) { + return yang_error_wrap(ERROR_RTC_RTCP_EMPTY_RR, "rc=0"); + } + + // TODO: FIXME: Security check for read. + m_rb.ssrc = buffer->read_4bytes(); + m_rb.fraction_lost = buffer->read_1bytes(); + m_rb.lost_packets = buffer->read_3bytes(); + m_rb.highest_sn = buffer->read_4bytes(); + m_rb.jitter = buffer->read_4bytes(); + m_rb.lsr = buffer->read_4bytes(); + m_rb.dlsr = buffer->read_4bytes(); + + // TODO: FIXME: Security check for read. + if(m_header.rc > 1) { + char buf[1500]; + buffer->read_bytes(buf, (m_header.rc -1 ) * 24); + } + + return err; +} + +uint64_t YangRtcpRR::nb_bytes() +{ + return (m_header.length + 1) * 4; +} + +int32_t YangRtcpRR::encode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc3550#section-6.4.2 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=RR=201 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + m_header.rc = 1; + if(Yang_Ok != (err = encode_header(buffer))) { + return yang_error_wrap(err, "encode header"); + } + + buffer->write_4bytes(m_rb.ssrc); + buffer->write_1bytes(m_rb.fraction_lost); + buffer->write_3bytes(m_rb.lost_packets); + buffer->write_4bytes(m_rb.highest_sn); + buffer->write_4bytes(m_rb.jitter); + buffer->write_4bytes(m_rb.lsr); + buffer->write_4bytes(m_rb.dlsr); + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpRR.h b/libyangrtc2/src/yangrtp/YangRtcpRR.h new file mode 100644 index 0000000000000000000000000000000000000000..586ad6233c251061cabc1d8759a32dbe327fd1a9 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpRR.h @@ -0,0 +1,40 @@ +#ifndef SRC_YANGRTP_YANGRTCPRR_H_ +#define SRC_YANGRTP_YANGRTCPRR_H_ + +#include +#include +class YangRtcpRR : public YangRtcpCommon +{ +private: + YangRtcpRB m_rb; +public: + YangRtcpRR(uint32_t sender_ssrc = 0); + virtual ~YangRtcpRR(); + + // overload SrsRtcpCommon + virtual uint8_t type() const; + + uint32_t get_rb_ssrc() const; + float get_lost_rate() const; + uint32_t get_lost_packets() const; + uint32_t get_highest_sn() const; + uint32_t get_jitter() const; + uint32_t get_lsr() const; + uint32_t get_dlsr() const; + + void set_rb_ssrc(uint32_t ssrc); + void set_lost_rate(float rate); + void set_lost_packets(uint32_t count); + void set_highest_sn(uint32_t sn); + void set_jitter(uint32_t jitter); + void set_lsr(uint32_t lsr); + void set_dlsr(uint32_t dlsr); + void set_sender_ntp(uint64_t ntp); + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); + +}; +#endif /* SRC_YANGRTP_YANGRTCPRR_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpRpsi.cpp b/libyangrtc2/src/yangrtp/YangRtcpRpsi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f6ca3c32b66bb965c00b366bf72fef834105db0 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpRpsi.cpp @@ -0,0 +1,74 @@ +#include +#include +#include + +YangRtcpRpsi::YangRtcpRpsi(uint32_t sender_ssrc/* = 0*/) +{ + m_pb = 0; + m_payload_type = 0; + m_native_rpsi = NULL; + m_nb_native_rpsi = 0; + + m_header.padding = 0; + m_header.type = YangRtcpType_psfb; + m_header.rc = kRPSI; + m_header.version = kRtcpVersion; + m_ssrc = sender_ssrc; +} + +YangRtcpRpsi::~YangRtcpRpsi() +{ +} + +int32_t YangRtcpRpsi::decode(YangBuffer *buffer) +{ +/* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + + + @doc: https://tools.ietf.org/html/rfc4585#section-6.3.3 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PB |0| Payload Type| Native RPSI bit string | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | defined per codec ... | Padding (0) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_media_ssrc = buffer->read_4bytes(); + int32_t len = (m_header.length + 1) * 4 - 12; + buffer->skip(len); + return err; +} + +uint64_t YangRtcpRpsi::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpRpsi::encode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpRpsi.h b/libyangrtc2/src/yangrtp/YangRtcpRpsi.h new file mode 100644 index 0000000000000000000000000000000000000000..345bdc0e0e69c8462821830d5ded1e0b3fbce4ea --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpRpsi.h @@ -0,0 +1,27 @@ + +#ifndef SRC_YANGRTP_YANGRTCPRPSI_H_ +#define SRC_YANGRTP_YANGRTCPRPSI_H_ + +#include +#include + +class YangRtcpRpsi : public YangRtcpPsfbCommon +{ +private: + uint8_t m_pb; + uint8_t m_payload_type; + char* m_native_rpsi; + int32_t m_nb_native_rpsi; + +public: + YangRtcpRpsi(uint32_t sender_ssrc = 0); + virtual ~YangRtcpRpsi(); + + // interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + +#endif /* SRC_YANGRTP_YANGRTCPRPSI_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpSR.cpp b/libyangrtc2/src/yangrtp/YangRtcpSR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2633448c51f455d93cf57cd29a53163f37b910c6 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpSR.cpp @@ -0,0 +1,195 @@ +#include +#include + + +YangRtcpSR::YangRtcpSR() +{ + m_header.padding = 0; + m_header.type = YangRtcpType_sr; + m_header.rc = 0; + m_header.version = kRtcpVersion; + m_header.length = 6; + + m_ssrc = 0; + m_ntp = 0; + m_rtp_ts = 0; + m_send_rtp_packets = 0; + m_send_rtp_bytes = 0; + m_send_rtp_bytes = 0; +} + +YangRtcpSR::~YangRtcpSR() +{ +} + +uint8_t YangRtcpSR::get_rc() const +{ + return m_header.rc; +} + +uint8_t YangRtcpSR::type() const +{ + return YangRtcpType_sr; +} + +uint64_t YangRtcpSR::get_ntp() const +{ + return m_ntp; +} + +uint32_t YangRtcpSR::get_rtp_ts() const +{ + return m_rtp_ts; +} + +uint32_t YangRtcpSR::get_rtp_send_packets() const +{ + return m_send_rtp_packets; +} + +uint32_t YangRtcpSR::get_rtp_send_bytes() const +{ + return m_send_rtp_bytes; +} + +void YangRtcpSR::set_ntp(uint64_t ntp) +{ + m_ntp = ntp; +} + +void YangRtcpSR::set_rtp_ts(uint32_t ts) +{ + m_rtp_ts = ts; +} + +void YangRtcpSR::set_rtp_send_packets(uint32_t packets) +{ + m_send_rtp_packets = packets; +} + +void YangRtcpSR::set_rtp_send_bytes(uint32_t bytes) +{ + m_send_rtp_bytes = bytes; +} + +int32_t YangRtcpSR::decode(YangBuffer *buffer) +{ + /* @doc: https://tools.ietf.org/html/rfc3550#section-6.4.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=SR=200 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +sender | NTP timestamp, most significant word | +info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NTP timestamp, least significant word | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | RTP timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's packet count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's octet count | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_ntp = buffer->read_8bytes(); + m_rtp_ts = buffer->read_4bytes(); + m_send_rtp_packets = buffer->read_4bytes(); + m_send_rtp_bytes = buffer->read_4bytes(); + + if(m_header.rc > 0) { + char buf[1500]; + buffer->read_bytes(buf, m_header.rc * 24); + } + + return err; +} + +uint64_t YangRtcpSR::nb_bytes() +{ + return (m_header.length + 1) * 4; +} + +int32_t YangRtcpSR::encode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + /* @doc: https://tools.ietf.org/html/rfc3550#section-6.4.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=SR=200 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +sender | NTP timestamp, most significant word | +info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NTP timestamp, least significant word | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | RTP timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's packet count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's octet count | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + if(Yang_Ok != (err = encode_header(buffer))) { + return yang_error_wrap(err, "encode header"); + } + + buffer->write_8bytes(m_ntp); + buffer->write_4bytes(m_rtp_ts); + buffer->write_4bytes(m_send_rtp_packets); + buffer->write_4bytes(m_send_rtp_bytes); + + return err; +} + diff --git a/libyangrtc2/src/yangrtp/YangRtcpSR.h b/libyangrtc2/src/yangrtp/YangRtcpSR.h new file mode 100644 index 0000000000000000000000000000000000000000..8ed08b0bb4769b21f750d37b57a0583813acff7b --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpSR.h @@ -0,0 +1,39 @@ +#ifndef SRC_YANGRTP_YANGRTCPSR_H_ +#define SRC_YANGRTP_YANGRTCPSR_H_ + +#include + + + +class YangRtcpSR : public YangRtcpCommon +{ +private: + uint64_t m_ntp; + uint32_t m_rtp_ts; + uint32_t m_send_rtp_packets; + uint32_t m_send_rtp_bytes; + +public: + YangRtcpSR(); + virtual ~YangRtcpSR(); + + uint8_t get_rc() const; + // overload SrsRtcpCommon + virtual uint8_t type() const; + uint64_t get_ntp() const; + uint32_t get_rtp_ts() const; + uint32_t get_rtp_send_packets() const; + uint32_t get_rtp_send_bytes() const; + + void set_ntp(uint64_t ntp); + void set_rtp_ts(uint32_t ts); + void set_rtp_send_packets(uint32_t packets); + void set_rtp_send_bytes(uint32_t bytes); + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + +#endif /* SRC_YANGRTP_YANGRTCPSR_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpSli.cpp b/libyangrtc2/src/yangrtp/YangRtcpSli.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6baa643690d12017b5256a810111e84d357de509 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpSli.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +YangRtcpSli::YangRtcpSli(uint32_t sender_ssrc/*= 0*/) +{ + m_first = 0; + m_number = 0; + m_picture = 0; + + m_header.padding = 0; + m_header.type = YangRtcpType_psfb; + m_header.rc = kSLI; + m_header.version = kRtcpVersion; + m_ssrc = sender_ssrc; +} + +YangRtcpSli::~YangRtcpSli() +{ +} + + +int32_t YangRtcpSli::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/rfc4585#section-6.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT | PT | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : Feedback Control Information (FCI) : + : : + + + @doc: https://tools.ietf.org/html/rfc4585#section-6.3.2 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | First | Number | PictureID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_media_ssrc = buffer->read_4bytes(); + int32_t len = (m_header.length + 1) * 4 - 12; + buffer->skip(len); + return err; +} + +uint64_t YangRtcpSli::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpSli::encode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + + return err; +} + diff --git a/libyangrtc2/src/yangrtp/YangRtcpSli.h b/libyangrtc2/src/yangrtp/YangRtcpSli.h new file mode 100644 index 0000000000000000000000000000000000000000..571118828556a8e95f6b2fe8c32d6d8d0d07909f --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpSli.h @@ -0,0 +1,24 @@ +#ifndef SRC_YANGRTP_YANGRTCPSLI_H_ +#define SRC_YANGRTP_YANGRTCPSLI_H_ + +#include +#include +class YangRtcpSli : public YangRtcpPsfbCommon +{ +private: + uint16_t m_first; + uint16_t m_number; + uint8_t m_picture; +public: + YangRtcpSli(uint32_t sender_ssrc = 0); + virtual ~YangRtcpSli(); + + // interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + + +#endif /* SRC_YANGRTP_YANGRTCPSLI_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpTWCC.cpp b/libyangrtc2/src/yangrtp/YangRtcpTWCC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b39f012fd2c40c64aeb59eaa105cbb378396767a --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpTWCC.cpp @@ -0,0 +1,507 @@ +#include +#include + +YangRtcpTWCC::SrsRtcpTWCCChunk::SrsRtcpTWCCChunk() + : size(0), all_same(true), has_large_delta(false) +{ +} + +YangRtcpTWCC::YangRtcpTWCC(uint32_t sender_ssrc) : m_pkt_len(0) +{ + m_header.padding = 0; + m_header.type = YangRtcpType_rtpfb; + m_header.rc = 15; + m_header.version = kRtcpVersion; + m_ssrc = sender_ssrc; + m_media_ssrc = 0; + m_base_sn = 0; + m_reference_time = 0; + m_fb_pkt_count = 0; + m_next_base_sn = 0; +} + +YangRtcpTWCC::~YangRtcpTWCC() +{ +} + +void YangRtcpTWCC::clear() +{ + m_encoded_chucks.clear(); + m_pkt_deltas.clear(); + m_recv_packets.clear(); + m_recv_sns.clear(); + m_next_base_sn = 0; +} + +uint32_t YangRtcpTWCC::get_media_ssrc() const +{ + return m_media_ssrc; +} +uint16_t YangRtcpTWCC::get_base_sn() const +{ + return m_base_sn; +} + +uint32_t YangRtcpTWCC::get_reference_time() const +{ + return m_reference_time; +} + +uint8_t YangRtcpTWCC::get_feedback_count() const +{ + return m_fb_pkt_count; +} + +vector YangRtcpTWCC::get_packet_chucks() const +{ + return m_encoded_chucks; +} + +vector YangRtcpTWCC::get_recv_deltas() const +{ + return m_pkt_deltas; +} + +void YangRtcpTWCC::set_media_ssrc(uint32_t ssrc) +{ + m_media_ssrc = ssrc; +} +void YangRtcpTWCC::set_base_sn(uint16_t sn) +{ + m_base_sn = sn; +} + +void YangRtcpTWCC::set_reference_time(uint32_t time) +{ + m_reference_time = time; +} + +void YangRtcpTWCC::set_feedback_count(uint8_t count) +{ + m_fb_pkt_count = count; +} + +void YangRtcpTWCC::add_packet_chuck(uint16_t chunk) +{ + m_encoded_chucks.push_back(chunk); +} + +void YangRtcpTWCC::add_recv_delta(uint16_t delta) +{ + m_pkt_deltas.push_back(delta); +} + +int32_t YangRtcpTWCC::recv_packet(uint16_t sn, int64_t ts) +{ + map::iterator it = m_recv_packets.find(sn); + if(it != m_recv_packets.end()) { + return yang_error_wrap(ERROR_RTC_RTCP, "TWCC dup seq: %d", sn); + } + + m_recv_packets[sn] = ts; + m_recv_sns.insert(sn); + + return Yang_Ok; +} + +bool YangRtcpTWCC::need_feedback() +{ + return m_recv_packets.size() > 0; +} + +int32_t YangRtcpTWCC::decode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT=15 | PT=205 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | base sequence number | packet status count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | reference time | fb pkt. count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | packet chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | recv delta | recv delta | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | recv delta | recv delta | zero padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + m_payload_len = (m_header.length + 1) * 4 - sizeof(YangRtcpHeader) - 4; + buffer->read_bytes((char *)m_payload, m_payload_len); + + return err; +} + +uint64_t YangRtcpTWCC::nb_bytes() +{ + return kMaxUDPDataSize; +} + +int64_t YangRtcpTWCC::calculate_delta_us(int64_t ts, int64_t last) +{ + int64_t divisor = kTwccFbReferenceTimeDivisor; + int64_t delta_us = (ts - last) % divisor; + + if (delta_us > (divisor >> 1)) + delta_us -= divisor; + + delta_us += (delta_us < 0) ? (-kTwccFbDeltaUnit / 2) : (kTwccFbDeltaUnit / 2); + delta_us /= kTwccFbDeltaUnit; + + return delta_us; +} + +bool YangRtcpTWCC::can_add_to_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk, int32_t delta_size) +{ + yang_info("can_add %d chunk->size %u delta_sizes %d %d %d %d %d %d %d %d %d %d %d %d %d %d all_same %d has_large_delta %d", + delta_size, chunk.size, chunk.delta_sizes[0], chunk.delta_sizes[1], chunk.delta_sizes[2], chunk.delta_sizes[3], + chunk.delta_sizes[4], chunk.delta_sizes[5], chunk.delta_sizes[6], chunk.delta_sizes[7], chunk.delta_sizes[8], + chunk.delta_sizes[9], chunk.delta_sizes[10], chunk.delta_sizes[11], chunk.delta_sizes[12], chunk.delta_sizes[13], + (int)chunk.all_same, (int)chunk.has_large_delta); + + if (chunk.size < kTwccFbTwoBitElements) { + return true; + } + + if (chunk.size < kTwccFbOneBitElements && !chunk.has_large_delta && delta_size != kTwccFbLargeRecvDeltaBytes) { + return true; + } + + if (chunk.size < kTwccFbMaxRunLength && chunk.all_same && chunk.delta_sizes[0] == delta_size) { + yang_info("< %d && all_same && delta_size[0] %d == %d", kTwccFbMaxRunLength, chunk.delta_sizes[0], delta_size); + return true; + } + + return false; +} + +void YangRtcpTWCC::add_to_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk, int32_t delta_size) +{ + if (chunk.size < kTwccFbMaxBitElements) { + chunk.delta_sizes[chunk.size] = delta_size; + } + + chunk.size += 1; + chunk.all_same = chunk.all_same && delta_size == chunk.delta_sizes[0]; + chunk.has_large_delta = chunk.has_large_delta || delta_size >= kTwccFbLargeRecvDeltaBytes; +} + +int32_t YangRtcpTWCC::encode_chunk_run_length(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk) +{ + if (!chunk.all_same || chunk.size > kTwccFbMaxRunLength) { + return yang_error_wrap(ERROR_RTC_RTCP, "invalid run all_same:%d, size:%d", chunk.all_same, chunk.size); + } + + uint16_t encoded_chunk = (chunk.delta_sizes[0] << 13) | chunk.size; + + m_encoded_chucks.push_back(encoded_chunk); + m_pkt_len += sizeof(encoded_chunk); + + return Yang_Ok; +} + +int32_t YangRtcpTWCC::encode_chunk_one_bit(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk) +{ + int32_t i = 0; + if (chunk.has_large_delta) { + return yang_error_wrap(ERROR_RTC_RTCP, "invalid large delta"); + } + + uint16_t encoded_chunk = 0x8000; + for (i = 0; i < chunk.size; ++i) { + encoded_chunk |= (chunk.delta_sizes[i] << (kTwccFbOneBitElements - 1 - i)); + } + + m_encoded_chucks.push_back(encoded_chunk); + m_pkt_len += sizeof(encoded_chunk); + + // 1 0 symbol_list + return Yang_Ok; +} + +int32_t YangRtcpTWCC::encode_chunk_two_bit(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk, size_t size, bool shift) +{ + uint32_t i = 0; + uint8_t delta_size = 0; + + uint16_t encoded_chunk = 0xc000; + // 1 1 symbol_list + for (i = 0; i < size; ++i) { + encoded_chunk |= (chunk.delta_sizes[i] << (2 * (kTwccFbTwoBitElements - 1 - i))); + } + m_encoded_chucks.push_back(encoded_chunk); + m_pkt_len += sizeof(encoded_chunk); + + if (shift) { + chunk.size -= size; + chunk.all_same = true; + chunk.has_large_delta = false; + for (i = 0; i < chunk.size; ++i) { + delta_size = chunk.delta_sizes[i + size]; + chunk.delta_sizes[i] = delta_size; + chunk.all_same = (chunk.all_same && delta_size == chunk.delta_sizes[0]); + chunk.has_large_delta = chunk.has_large_delta || delta_size == kTwccFbLargeRecvDeltaBytes; + } + } + + return Yang_Ok; +} + +void YangRtcpTWCC::reset_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk) +{ + chunk.size = 0; + + chunk.all_same = true; + chunk.has_large_delta = false; +} + +int32_t YangRtcpTWCC::encode_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk) +{ + int32_t err = Yang_Ok; + + if (can_add_to_chunk(chunk, 0) && can_add_to_chunk(chunk, 1) && can_add_to_chunk(chunk, 2)) { + return yang_error_wrap(ERROR_RTC_RTCP, "TWCC chunk"); + } + + if (chunk.all_same) { + if ((err = encode_chunk_run_length(chunk)) != Yang_Ok) { + return yang_error_wrap(err, "encode run"); + } + reset_chunk(chunk); + return err; + } + + if (chunk.size == kTwccFbOneBitElements) { + if ((err = encode_chunk_one_bit(chunk)) != Yang_Ok) { + return yang_error_wrap(err, "encode chunk"); + } + reset_chunk(chunk); + return err; + } + + if ((err = encode_chunk_two_bit(chunk, kTwccFbTwoBitElements, true)) != Yang_Ok) { + return yang_error_wrap(err, "encode chunk"); + } + + return err; +} + +int32_t YangRtcpTWCC::encode_remaining_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk) +{ + if (chunk.all_same) { + return encode_chunk_run_length(chunk); + } else if (chunk.size <= kTwccFbTwoBitElements) { + // FIXME, TRUE or FALSE + return encode_chunk_two_bit(chunk, chunk.size, false); + } + return encode_chunk_one_bit(chunk); +} + +int32_t YangRtcpTWCC::process_pkt_chunk(YangRtcpTWCC::SrsRtcpTWCCChunk& chunk, int32_t delta_size) +{ + int32_t err = Yang_Ok; + + size_t needed_chunk_size = chunk.size == 0 ? kTwccFbChunkBytes : 0; + + size_t might_occupied = m_pkt_len + needed_chunk_size + delta_size; + if (might_occupied > kRtcpPacketSize) { + return yang_error_wrap(ERROR_RTC_RTCP, "might_occupied %zu", might_occupied); + } + + if (can_add_to_chunk(chunk, delta_size)) { + //pkt_len += needed_chunk_size; + add_to_chunk(chunk, delta_size); + return err; + } + if ((err = encode_chunk(chunk)) != Yang_Ok) { + return yang_error_wrap(err, "encode chunk, delta_size %u", delta_size); + } + add_to_chunk(chunk, delta_size); + return err; +} + +int32_t YangRtcpTWCC::encode(YangBuffer *buffer) +{ + int32_t err = Yang_Ok; + + err = do_encode(buffer); + + if (err != Yang_Ok || m_next_base_sn == 0) { + clear(); + } + + return err; +} + +int32_t YangRtcpTWCC::do_encode(YangBuffer *buffer) +{ + /* + @doc: https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT=15 | PT=205 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | base sequence number | packet status count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | reference time | fb pkt. count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | packet chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | recv delta | recv delta | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | recv delta | recv delta | zero padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int32_t err = Yang_Ok; + + if(!buffer->require(nb_bytes())) { + return yang_error_wrap(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes()); + } + + m_pkt_len = kTwccFbPktHeaderSize; + + set::iterator it_sn = m_recv_sns.begin(); + if (!m_next_base_sn) { + m_base_sn = *it_sn; + } else { + m_base_sn = m_next_base_sn; + it_sn = m_recv_sns.find(m_base_sn); + } + + map::iterator it_ts = m_recv_packets.find(m_base_sn); + int64_t ts = it_ts->second; + + m_reference_time = (ts % kTwccFbReferenceTimeDivisor) / kTwccFbTimeMultiplier; + int64_t last_ts = (int64_t)(m_reference_time) * kTwccFbTimeMultiplier; + + uint16_t last_sn = m_base_sn; + uint16_t packet_count = 0; + + // encode chunk + YangRtcpTWCC::SrsRtcpTWCCChunk chunk; + for(; it_sn != m_recv_sns.end(); ++it_sn) { + // check whether exceed buffer len + // max recv_delta_size = 2 + if (m_pkt_len + 2 >= buffer->left()) { + break; + } + + uint16_t current_sn = *it_sn; + // calculate delta + it_ts = m_recv_packets.find(current_sn); + if (it_ts == m_recv_packets.end()) { + continue; + } + + packet_count++; + int64_t delta_us = calculate_delta_us(it_ts->second, last_ts); + int16_t delta = delta_us; + if(delta != delta_us) { + return yang_error_wrap(ERROR_RTC_RTCP, "twcc: delta:%lld, exceeds the 16bits", delta_us); + } + + if(current_sn > (last_sn + 1)) { + // lost packet + for(uint16_t lost_sn = last_sn + 1; lost_sn < current_sn; ++lost_sn) { + process_pkt_chunk(chunk, 0); + packet_count++; + } + } + + // FIXME 24-bit base receive delta not supported + int32_t recv_delta_size = (delta >= 0 && delta <= 0xff) ? 1 : 2; + if ((err = process_pkt_chunk(chunk, recv_delta_size)) != Yang_Ok) { + return yang_error_wrap(err, "delta_size %d, failed to append_recv_delta", recv_delta_size); + } + + m_pkt_deltas.push_back(delta); + last_ts += delta * kTwccFbDeltaUnit; + m_pkt_len += recv_delta_size; + last_sn = current_sn; + + m_recv_packets.erase(it_ts); + } + + m_next_base_sn = 0; + if (it_sn != m_recv_sns.end()) { + m_next_base_sn = *it_sn; + } + + if(0 < chunk.size) { + if((err = encode_remaining_chunk(chunk)) != Yang_Ok) { + return yang_error_wrap(err, "encode chunk"); + } + } + + // encode rtcp twcc packet + if((m_pkt_len % 4) == 0) { + m_header.length = m_pkt_len / 4; + } else { + m_header.length = (m_pkt_len + 4 - (m_pkt_len%4)) / 4; + } + m_header.length -= 1; + + if(Yang_Ok != (err = encode_header(buffer))) { + return yang_error_wrap(err, "encode header"); + } + buffer->write_4bytes(m_media_ssrc); + buffer->write_2bytes(m_base_sn); + buffer->write_2bytes(packet_count); + buffer->write_3bytes(m_reference_time); + buffer->write_1bytes(m_fb_pkt_count); + + for(vector::iterator it = m_encoded_chucks.begin(); it != m_encoded_chucks.end(); ++it) { + buffer->write_2bytes(*it); + } + for(vector::iterator it = m_pkt_deltas.begin(); it != m_pkt_deltas.end(); ++it) { + if(0 <= *it && 0xFF >= *it) { + // small delta + uint8_t delta = *it; + buffer->write_1bytes(delta); + } else { + // large or negative delta + buffer->write_2bytes(*it); + } + } + while((m_pkt_len % 4) != 0) { + buffer->write_1bytes(0); + m_pkt_len++; + } + + m_encoded_chucks.clear(); + m_pkt_deltas.clear(); + + return err; +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpTWCC.h b/libyangrtc2/src/yangrtp/YangRtcpTWCC.h new file mode 100644 index 0000000000000000000000000000000000000000..639e493ccab0bf27b8ec378b9a2307e5daa0ef6c --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpTWCC.h @@ -0,0 +1,115 @@ + +#ifndef SRC_YANGRTP_YANGRTCPTWCC_H_ +#define SRC_YANGRTP_YANGRTCPTWCC_H_ +#include +#include +#include +#include +#include + +// The Message format of TWCC, @see https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT=15 | PT=205 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | base sequence number | packet status count | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | reference time | fb pkt. count | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | packet chunk | packet chunk | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . . +// . . +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | packet chunk | recv delta | recv delta | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . . +// . . +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | recv delta | recv delta | zero padding | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +#define kTwccFbPktHeaderSize (4 + 8 + 8) +#define kTwccFbChunkBytes (2) +#define kTwccFbPktFormat (15) +#define kTwccFbPayloadType (205) +#define kTwccFbMaxPktStatusCount (0xffff) +#define kTwccFbDeltaUnit (250) // multiple of 250us +#define kTwccFbTimeMultiplier (kTwccFbDeltaUnit * (1 << 8)) // multiplicand multiplier/* 250us -> 64ms (1 << 8) */ +#define kTwccFbReferenceTimeDivisor ((1ll<<24) * kTwccFbTimeMultiplier) // dividend divisor + +#define kTwccFbMaxRunLength 0x1fff +#define kTwccFbOneBitElements 14 +#define kTwccFbTwoBitElements 7 +#define kTwccFbLargeRecvDeltaBytes 2 +#define kTwccFbMaxBitElements kTwccFbOneBitElements +class YangRtcpTWCC : public YangRtcpCommon +{ +private: + uint32_t m_media_ssrc; + uint16_t m_base_sn; + int32_t m_reference_time; + uint8_t m_fb_pkt_count; + std::vector m_encoded_chucks; + std::vector m_pkt_deltas; + + std::map m_recv_packets; + std::set m_recv_sns; + + struct SrsRtcpTWCCChunk { + uint8_t delta_sizes[kTwccFbMaxBitElements]; + uint16_t size; + bool all_same; + bool has_large_delta; + SrsRtcpTWCCChunk(); + }; + + int32_t m_pkt_len; + uint16_t m_next_base_sn; +private: + void clear(); + int64_t calculate_delta_us(int64_t ts, int64_t last); + int32_t process_pkt_chunk(SrsRtcpTWCCChunk& chunk, int32_t delta_size); + bool can_add_to_chunk(SrsRtcpTWCCChunk& chunk, int32_t delta_size); + void add_to_chunk(SrsRtcpTWCCChunk& chunk, int32_t delta_size); + int32_t encode_chunk(SrsRtcpTWCCChunk& chunk); + int32_t encode_chunk_run_length(SrsRtcpTWCCChunk& chunk); + int32_t encode_chunk_one_bit(SrsRtcpTWCCChunk& chunk); + int32_t encode_chunk_two_bit(SrsRtcpTWCCChunk& chunk, size_t size, bool shift); + void reset_chunk(SrsRtcpTWCCChunk& chunk); + int32_t encode_remaining_chunk(SrsRtcpTWCCChunk& chunk); +public: + YangRtcpTWCC(uint32_t sender_ssrc = 0); + virtual ~YangRtcpTWCC(); + + uint32_t get_media_ssrc() const; + uint16_t get_base_sn() const; + uint32_t get_reference_time() const; + uint8_t get_feedback_count() const; + std::vector get_packet_chucks() const; + std::vector get_recv_deltas() const; + + void set_media_ssrc(uint32_t ssrc); + void set_base_sn(uint16_t sn); + void set_reference_time(uint32_t time); + void set_feedback_count(uint8_t count); + void add_packet_chuck(uint16_t chuck); + void add_recv_delta(uint16_t delta); + + int32_t recv_packet(uint16_t sn, int64_t ts); + bool need_feedback(); + + +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +private: + int32_t do_encode(YangBuffer *buffer); +}; +#endif /* SRC_YANGRTP_YANGRTCPTWCC_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtcpXr.cpp b/libyangrtc2/src/yangrtp/YangRtcpXr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b20fe3733008403288dadec0b5f3746412695b7 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpXr.cpp @@ -0,0 +1,55 @@ +#include +#include + + + +YangRtcpXr::YangRtcpXr(uint32_t ssrc/*= 0*/) +{ + m_header.padding = 0; + m_header.type = YangRtcpType_xr; + m_header.rc = 0; + m_header.version = kRtcpVersion; + m_ssrc = ssrc; +} + +YangRtcpXr::~YangRtcpXr() +{ +} + +int32_t YangRtcpXr::decode(YangBuffer *buffer) +{ +/* + @doc: https://tools.ietf.org/html/rfc3611#section-2 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|reserved | PT=XR=207 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : report blocks : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + int32_t err = Yang_Ok; + m_data = buffer->head(); + m_nb_data = buffer->left(); + + if(Yang_Ok != (err = decode_header(buffer))) { + return yang_error_wrap(err, "decode header"); + } + + int32_t len = (m_header.length + 1) * 4 - 8; + buffer->skip(len); + return err; +} + +uint64_t YangRtcpXr::nb_bytes() +{ + return kRtcpPacketSize; +} + +int32_t YangRtcpXr::encode(YangBuffer *buffer) +{ + return yang_error_wrap(ERROR_RTC_RTCP, "not support"); +} diff --git a/libyangrtc2/src/yangrtp/YangRtcpXr.h b/libyangrtc2/src/yangrtp/YangRtcpXr.h new file mode 100644 index 0000000000000000000000000000000000000000..641ce50e1d1d6dd18733aff86e0c1c39a36281a2 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtcpXr.h @@ -0,0 +1,20 @@ + +#ifndef SRC_YANGRTP_YANGRTCPXR_H_ +#define SRC_YANGRTP_YANGRTCPXR_H_ + +#include + +class YangRtcpXr : public YangRtcpCommon +{ +public: + YangRtcpXr (uint32_t ssrc = 0); + virtual ~YangRtcpXr(); + + // interface ISrsCodec +public: + virtual int32_t decode(YangBuffer *buffer); + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer *buffer); +}; + +#endif /* SRC_YANGRTP_YANGRTCPXR_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtp.cpp b/libyangrtc2/src/yangrtp/YangRtp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53c32fef257e2162cfee33c8c3f1481ba684596e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtp.cpp @@ -0,0 +1,525 @@ +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +const YangExtensionInfo kExtensions[] = { + {kRtpExtensionTransportSequenceNumber, std::string("http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01")}, + {kRtpExtensionAudioLevel, kAudioLevelUri}, +}; +/* @see https://tools.ietf.org/html/rfc1889#section-5.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +uint32_t yang_rtp_fast_parse_ssrc(char* buf, int32_t size) +{ + if (size < 12) { + return 0; + } + + uint32_t value = 0; + char* pp = (char*)&value; + + char* p = buf + 8; + pp[3] = *p++; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + return value; +} +uint8_t yang_rtp_fast_parse_pt(char* buf, int32_t size) +{ + if (size < 12) { + return 0; + } + return buf[1] & 0x7f; +} +int32_t yang_rtp_fast_parse_twcc(char* buf, int32_t size, uint8_t twcc_id, uint16_t& twcc_sn) +{ + int32_t err = Yang_Ok; + + int32_t need_size = 12 /*rtp head fix len*/ + 4 /* extension header len*/ + 3 /* twcc extension len*/; + if(size < (need_size)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + + uint8_t first = buf[0]; + bool extension = (first & 0x10); + uint8_t cc = (first & 0x0F); + + if(!extension) { + return yang_error_wrap(ERROR_RTC_RTP, "no extension in rtp"); + } + + need_size += cc * 4; // csrc size + if(size < (need_size)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + buf += 12 + 4*cc; + + uint16_t value = *((uint16_t*)buf); + value = ntohs(value); + if(0xBEDE != value) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "no support this type(0x%02x) extension", value); + } + buf += 2; + + uint16_t extension_length = ntohs(*((uint16_t*)buf)); + buf += 2; + extension_length *= 4; + need_size += extension_length; // entension size + if(size < (need_size)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + + while(extension_length > 0) { + uint8_t v = buf[0]; + buf++; + extension_length--; + if(0 == v) { + continue; + } + + uint8_t id = (v & 0xF0) >>4; + uint8_t len = (v & 0x0F) + 1; + + if(id == twcc_id) { + twcc_sn = ntohs(*((uint16_t*)buf)); + return err; + } else { + buf += len; + extension_length -= len; + } + } + + + return err; +} + +// If value is newer than pre_value,return true; otherwise false +bool yang_seq_is_newer(uint16_t value, uint16_t pre_value) +{ + return yang_rtp_seq_distance(pre_value, value) > 0; +} + +bool yang_seq_is_rollback(uint16_t value, uint16_t pre_value) +{ + if(yang_seq_is_newer(value, pre_value)) { + return pre_value > value; + } + return false; +} + +// If value is newer then pre_value, return positive, otherwise negative. +int32_t yang_seq_distance(uint16_t value, uint16_t pre_value) +{ + return yang_rtp_seq_distance(pre_value, value); +} + +YangRtpExtensionTypes::YangRtpExtensionTypes() +{ + memset(m_ids, kRtpExtensionNone, sizeof(m_ids)); +} + +YangRtpExtensionTypes::~YangRtpExtensionTypes() +{ +} + +bool YangRtpExtensionTypes::register_by_uri(int32_t id, std::string uri) +{ + for (int32_t i = 0; i < (int)(sizeof(kExtensions)/sizeof(kExtensions[0])); ++i) { + if (kExtensions[i].uri == uri) { + return register_id(id, kExtensions[i].type, kExtensions[i].uri); + } + } + return false; +} + +bool YangRtpExtensionTypes::register_id(int32_t id, YangRtpExtensionType type, std::string uri) +{ + if (id < 1 || id > 255) { + return false; + } + + m_ids[type] = static_cast(id); + return true; +} + +YangRtpExtensionType YangRtpExtensionTypes::get_type(int32_t id) const +{ + for (int32_t type = kRtpExtensionNone + 1; type < kRtpExtensionNumberOfExtensions; ++type) { + if (m_ids[type] == id) { + return static_cast(type); + } + } + return kInvalidType; +} + +YangRtpExtensionTwcc::YangRtpExtensionTwcc() +{ + m_has_twcc = false; + m_id = 0; + m_sn = 0; +} + +YangRtpExtensionTwcc::~YangRtpExtensionTwcc() +{ +} + +int32_t YangRtpExtensionTwcc::decode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + // 0 1 2 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | ID | L=1 |transport wide sequence number | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + uint8_t v = buf->read_1bytes(); + + m_id = (v & 0xF0) >> 4; + uint8_t len = (v & 0x0F); + if(!m_id || len != 1) { + return yang_error_wrap(ERROR_RTC_RTP, "invalid twcc id=%d, len=%d", m_id, len); + } + + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + m_sn = buf->read_2bytes(); + + m_has_twcc = true; + return err; +} + +uint64_t YangRtpExtensionTwcc::nb_bytes() +{ + return 3; +} + +int32_t YangRtpExtensionTwcc::encode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + if(!buf->require(3)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3); + } + + uint8_t id_len = (m_id & 0x0F)<< 4| 0x01; + buf->write_1bytes(id_len); + buf->write_2bytes(m_sn); + + return err; +} + + +uint8_t YangRtpExtensionTwcc::get_id() +{ + return m_id; +} + +void YangRtpExtensionTwcc::set_id(uint8_t id) +{ + m_id = id; + m_has_twcc = true; +} + +uint16_t YangRtpExtensionTwcc::get_sn() +{ + return m_sn; +} + +void YangRtpExtensionTwcc::set_sn(uint16_t sn) +{ + m_sn = sn; + m_has_twcc = true; +} + +YangRtpExtensionOneByte::YangRtpExtensionOneByte() +{ + m_has_ext = false; + m_id = 0; + m_value = 0; +} + +YangRtpExtensionOneByte::~YangRtpExtensionOneByte() +{ +} + +void YangRtpExtensionOneByte::set_id(int32_t id) +{ + m_id = id; + m_has_ext = true; +} + +void YangRtpExtensionOneByte::set_value(uint8_t value) +{ + m_value = value; + m_has_ext = true; +} + +int32_t YangRtpExtensionOneByte::decode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + uint8_t v = buf->read_1bytes(); + + m_id = (v & 0xF0) >> 4; + uint8_t len = (v & 0x0F); + if(!m_id || len != 0) { + return yang_error_wrap(ERROR_RTC_RTP, "invalid rtp extension id=%d, len=%d", m_id, len); + } + + m_value = buf->read_1bytes(); + + m_has_ext = true; + return err; +} + +int32_t YangRtpExtensionOneByte::encode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + + uint8_t id_len = (m_id & 0x0F)<< 4 | 0x00; + buf->write_1bytes(id_len); + buf->write_1bytes(m_value); + + return err; +} + +YangRtpExtensions::YangRtpExtensions() +{ + m_types = NULL; + m_has_ext = false; + m_decode_twcc_extension = false; +} + +YangRtpExtensions::~YangRtpExtensions() +{ +} + +int32_t YangRtpExtensions::decode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + /* @see https://tools.ietf.org/html/rfc3550#section-5.3.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | defined by profile | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | header extension | + | .... | + */ + if (!buf->require(4)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires 4 bytes"); + } + uint16_t profile_id = buf->read_2bytes(); + uint16_t extension_length = buf->read_2bytes(); + + // @see: https://tools.ietf.org/html/rfc5285#section-4.2 + if (profile_id == 0xBEDE) { + YangBuffer xbuf(buf->head(), extension_length * 4); + buf->skip(extension_length * 4); + return decode_0xbede(&xbuf); + } else if (profile_id == 0x1000) { + buf->skip(extension_length * 4); + } else { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "fail to parse extension"); + } + return err; +} + +int32_t YangRtpExtensions::decode_0xbede(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + while (!buf->empty()) { + // The first byte maybe padding or id+len. + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + uint8_t v = *((uint8_t*)buf->head()); + + // Padding, ignore + if(v == 0) { + buf->skip(1); + continue; + } + + // 0 + // 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+ + // | ID | len | + // +-+-+-+-+-+-+-+-+ + // Note that 'len' is the header extension element length, which is the + // number of bytes - 1. + uint8_t id = (v & 0xF0) >> 4; + uint8_t len = (v & 0x0F) + 1; + + YangRtpExtensionType xtype = m_types? m_types->get_type(id) : kRtpExtensionNone; + if (xtype == kRtpExtensionTransportSequenceNumber) { + if (m_decode_twcc_extension) { + if ((err = m_twcc.decode(buf)) != Yang_Ok) { + return yang_error_wrap(err, "decode twcc extension"); + } + m_has_ext = true; + } else { + if (!buf->require(len+1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", len+1); + } + buf->skip(len + 1); + } + } else if (xtype == kRtpExtensionAudioLevel) { + if((err = m_audio_level.decode(buf)) != Yang_Ok) { + return yang_error_wrap(err, "decode audio level extension"); + } + m_has_ext = true; + } else { + buf->skip(1 + len); + } + } + + return err; +} + +uint64_t YangRtpExtensions::nb_bytes() +{ + int32_t size = 4 + (m_twcc.exists() ? m_twcc.nb_bytes() : 0); + size += (m_audio_level.exists() ? m_audio_level.nb_bytes() : 0); + // add padding + size += (size % 4 == 0) ? 0 : (4 - size % 4); + return size; +} + +int32_t YangRtpExtensions::encode(YangBuffer* buf) +{ + int32_t err = Yang_Ok; + + buf->write_2bytes(0xBEDE); + + // Write length. + int32_t len = 0; + + if (m_twcc.exists()) { + len += m_twcc.nb_bytes(); + } + + if (m_audio_level.exists()) { + len += m_audio_level.nb_bytes(); + } + + int32_t padding_count = (len % 4 == 0) ? 0 : (4 - len % 4); + len += padding_count; + + if (!buf->require(len)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", len); + } + + buf->write_2bytes(len / 4); + + // Write extensions. + if (m_twcc.exists()) { + if ((err = m_twcc.encode(buf)) != Yang_Ok) { + return yang_error_wrap(err, "encode twcc extension"); + } + } + + if (m_audio_level.exists()) { + if (Yang_Ok != (err = m_audio_level.encode(buf))) { + return yang_error_wrap(err, "encode audio level extension"); + } + } + + // add padding + if (padding_count) { + memset(buf->head(), 0, padding_count); + buf->skip(padding_count); + } + + return err; +} + +void YangRtpExtensions::set_types_(YangRtpExtensionTypes* types) +{ + m_types = types; +} + +int32_t YangRtpExtensions::get_twcc_sequence_number(uint16_t& twcc_sn) +{ + if (m_twcc.exists()) { + twcc_sn = m_twcc.get_sn(); + return Yang_Ok; + } + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "not find twcc sequence number"); +} + +int32_t YangRtpExtensions::set_twcc_sequence_number(uint8_t id, uint16_t sn) +{ + m_has_ext = true; + m_twcc.set_id(id); + m_twcc.set_sn(sn); + return Yang_Ok; +} + +int32_t YangRtpExtensions::get_audio_level(uint8_t& level) +{ + if(m_audio_level.exists()) { + level = m_audio_level.get_value(); + return Yang_Ok; + } + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "not find rtp extension audio level"); +} + +int32_t YangRtpExtensions::set_audio_level(int32_t id, uint8_t level) +{ + m_has_ext = true; + m_audio_level.set_id(id); + m_audio_level.set_value(level); + return Yang_Ok; +} +YangRtpPayloader::YangRtpPayloader(){ + m_payload = NULL; + m_size = 0; +} + YangRtpPayloader::~YangRtpPayloader(){ + +} +IYangRtpPayloader::IYangRtpPayloader() { +} + +IYangRtpPayloader::~IYangRtpPayloader() { +} + + + diff --git a/libyangrtc2/src/yangrtp/YangRtpBuffer.cpp b/libyangrtc2/src/yangrtp/YangRtpBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4d9d7e614726b965cf19a93093048e7fb438af2 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpBuffer.cpp @@ -0,0 +1,17 @@ +#include +#include +YangRtpBuffer::YangRtpBuffer(int pbuflen,int unitsize){ + m_bufLen=pbuflen;//role==Yang_Stream_Play?1500:20; + m_index=0; + m_buffer=new char[unitsize*m_bufLen]; + +} +YangRtpBuffer::~YangRtpBuffer(){ + yang_deleteA(m_buffer); +} +char* YangRtpBuffer::getBuffer(){ + m_index++; + if(m_index==m_bufLen) m_index=0; + return m_buffer+1500*m_index; +} + diff --git a/libyangrtc2/src/yangrtp/YangRtpBuffer.h b/libyangrtc2/src/yangrtp/YangRtpBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..d6b5fd41e979f35ec0cf0b3464f0b2c33bfe3d9c --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpBuffer.h @@ -0,0 +1,17 @@ +#ifndef SRC_YANGRTP_YANGRTPBUFFER_H_ +#define SRC_YANGRTP_YANGRTPBUFFER_H_ +#include +class YangRtpBuffer{ +public: + YangRtpBuffer(int pbuflen,int unitsize=1500); + ~YangRtpBuffer(); +public: + char* getBuffer(); +private: + char* m_buffer; + int32_t m_bufLen; + int32_t m_index; + +}; + +#endif /* SRC_YANGRTP_YANGRTPBUFFER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpFUAPayload.cpp b/libyangrtc2/src/yangrtp/YangRtpFUAPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a0800409955ed699ada64404ad988886cee0ce6 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpFUAPayload.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +YangRtpFUAPayload::YangRtpFUAPayload() { + m_start = m_end = false; + m_nri = m_nalu_type = (YangAvcNaluType) 0; +} + +YangRtpFUAPayload::~YangRtpFUAPayload() { + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + yang_delete(p); + } +} + +uint64_t YangRtpFUAPayload::nb_bytes() { + int32_t size = 2; + + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + size += p->nb; + } + + return size; +} + +int32_t YangRtpFUAPayload::encode(YangBuffer *buf) { + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_indicate = kFuA; + fu_indicate |= (m_nri & (~kNalTypeMask)); + buf->write_1bytes(fu_indicate); + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_header = m_nalu_type; + if (m_start) { + fu_header |= kStart; + } + if (m_end) { + fu_header |= kEnd; + } + buf->write_1bytes(fu_header); + + // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + + if (!buf->require(p->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + p->nb); + } + + buf->write_bytes(p->bytes, p->nb); + } + + return Yang_Ok; +} + +int32_t YangRtpFUAPayload::decode(YangBuffer *buf) { + + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t v = buf->read_1bytes(); + m_nri = YangAvcNaluType(v & (~kNalTypeMask)); + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + v = buf->read_1bytes(); + m_start = v & kStart; + m_end = v & kEnd; + m_nalu_type = YangAvcNaluType(v & kNalTypeMask); + + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + YangSample *sample = new YangSample(); + sample->bytes = buf->head(); + sample->nb = buf->left(); + buf->skip(sample->nb); + + m_nalus.push_back(sample); + + return Yang_Ok; +} + +IYangRtpPayloader* YangRtpFUAPayload::copy() { + YangRtpFUAPayload *cp = new YangRtpFUAPayload(); + + cp->m_nri = m_nri; + cp->m_start = m_start; + cp->m_end = m_end; + cp->m_nalu_type = m_nalu_type; + + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + cp->m_nalus.push_back(yang_sample_copy(p)); + } + + return cp; +} diff --git a/libyangrtc2/src/yangrtp/YangRtpFUAPayload.h b/libyangrtc2/src/yangrtp/YangRtpFUAPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..dd31fcfd7383ef46abff5e5a8189809cf4d00ec1 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpFUAPayload.h @@ -0,0 +1,29 @@ +#ifndef SRC_YANGRTP_YANGRTPFUAPAYLOAD_H_ +#define SRC_YANGRTP_YANGRTPFUAPAYLOAD_H_ +#include +// FU-A, for one NALU with multiple fragments. +// With more than one payload. +class YangRtpFUAPayload : public IYangRtpPayloader +{ +public: + // The NRI in NALU type. + YangAvcNaluType m_nri; + // The FUA header. + bool m_start; + bool m_end; + YangAvcNaluType m_nalu_type; + // The NALU samples, we manage the samples. + // @remark We only refer to the memory, user must free its bytes. + std::vector m_nalus; +public: + YangRtpFUAPayload(); + virtual ~YangRtpFUAPayload(); +// interface ISrsRtpPayloader +public: + uint64_t nb_bytes(); + int32_t encode(YangBuffer* buf); + int32_t decode(YangBuffer* buf); + IYangRtpPayloader* copy(); + int32_t nb_size(){return 0;}; +}; +#endif /* SRC_YANGRTP_YANGRTPFUAPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.cpp b/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7865b1522729ec16510aac68cbc0f56d3066c50 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +int32_t yang_decode_h264_fua2(YangBuffer* buf,Fua2H264DataCache* pkt){ + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t v = buf->read_1bytes(); + pkt->nri = YangAvcNaluType(v & (~kNalTypeMask)); + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + v = buf->read_1bytes(); + pkt->start = v & kStart; + pkt->end = v & kEnd; + pkt->nalu_type = YangAvcNaluType(v & kNalTypeMask); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + return Yang_Ok; +} + +int32_t yang_encode_h264_fua2(YangBuffer* buf,YangFua2H264Data* pkt){ + if (!buf->require(2 + pkt->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // Fast encoding. + char *p = buf->head(); + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_indicate = kFuA; + fu_indicate |= (pkt->nri & (~kNalTypeMask)); + *p++ = fu_indicate; + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_header = pkt->nalu_type; + if (pkt->start) { + fu_header |= kStart; + } + if (pkt->end) { + fu_header |= kEnd; + } + *p++ = fu_header; + + // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 + memcpy(p, pkt->payload, pkt->nb); + + // Consume bytes. + buf->skip(2 + pkt->nb); + + return Yang_Ok; +} +int32_t yang_decode_h265_fua2(YangBuffer* buf,Fua2H265DataCache* pkt){ + if (!buf->require(3)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "decode_h265_fua2 requires %d bytes", 3); + } + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t v = buf->read_1bytes(); + pkt->nri = YangHevcNaluType((v>>1) & 0x3f); // YangHevcNaluType(v & (~kNalTypeMask)); + v=buf->read_1bytes(); + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + v = buf->read_1bytes(); + pkt->start = v & kStart; + pkt->end = v & kEnd; + pkt->nalu_type = YangHevcNaluType(v & 0x3F); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "decode_h265_fua2 requires %d bytes", 1); + } + + return Yang_Ok; +} +int32_t yang_encode_h265_fua2(YangBuffer* buf,YangFua2H265Data* pkt){ + if (!buf->require(3 + pkt->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3 + pkt->nb); + } + + // Fast encoding. + char *p = buf->head(); + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + //uint8_t fu_indicate = 49 << 1; + //fu_indicate |= (pkt->nri & (~kNalTypeMask)); + //uint8_t nal_type = (pkt->nri >> 1) & 0x3F; + *p++=H265_kFuA<<1;//49<<1; + *p++=1; + //*p++ = nal_type|(1 << 7); + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_header = pkt->nalu_type; + if (pkt->start) { + fu_header |= kStart; + } + if (pkt->end) { + fu_header |= kEnd; + } + *p++ = fu_header; + + // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 + memcpy(p, pkt->payload, pkt->nb); + + // Consume bytes. + buf->skip(3 + pkt->nb); + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.h b/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.h new file mode 100644 index 0000000000000000000000000000000000000000..a9bfb6a2774b5f82184665b41082b27c7c539e3a --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpFUAPayload2.h @@ -0,0 +1,43 @@ +#ifndef SRC_YANGRTP_YANGRTPFUAPAYLOAD2_H_ +#define SRC_YANGRTP_YANGRTPFUAPAYLOAD2_H_ +#include +#include +struct Fua2H264DataCache{ + bool start; + bool end; + YangAvcNaluType nri; + YangAvcNaluType nalu_type; +}; +struct Fua2H265DataCache{ + bool start; + bool end; + YangHevcNaluType nri; + YangHevcNaluType nalu_type; +}; +struct YangFua2H264Data{ + // The FUA header. + bool start; + bool end; + YangAvcNaluType nri; + YangAvcNaluType nalu_type; + int32_t nb; + char* payload; +}; +struct YangFua2H265Data{ + // The FUA header. + bool start; + bool end; + YangHevcNaluType nri; + YangHevcNaluType nalu_type; + int32_t nb; + char* payload; +}; +int32_t yang_decode_h264_fua2(YangBuffer* buf,Fua2H264DataCache* pkt); +int32_t yang_decode_h265_fua2(YangBuffer* buf,Fua2H265DataCache* pkt); +// FU-A, for one NALU with multiple fragments. +// With only one payload. +int32_t yang_encode_h264_fua2(YangBuffer* buf,YangFua2H264Data* pkt); +int32_t yang_encode_h265_fua2(YangBuffer* buf,YangFua2H265Data* pkt); + + +#endif /* SRC_YANGRTP_YANGRTPFUAPAYLOAD2_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpHeader.cpp b/libyangrtc2/src/yangrtp/YangRtpHeader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99356bde56ef335c59b26bb57698620c12f88a7e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpHeader.cpp @@ -0,0 +1,324 @@ +#include +#include +#include +int32_t parse_extensions(YangBuffer *buf,YangRtpExtensions* ext) { + int32_t err = Yang_Ok; + + if (Yang_Ok != (err = ext->decode(buf))) { + return yang_error_wrap(err, "decode rtp extension"); + } + + return err; +} +int32_t yang_encode_rtpHeader(YangBuffer* buf,YangRtpHeader* header){ + int32_t err = Yang_Ok; + + // Encode the RTP fix header, 12bytes. + // @see https://tools.ietf.org/html/rfc1889#section-5.1 + // The version, padding, extension and cc, total 1 byte. + uint8_t v = 0x80 | header->cc; + if (header->padding_length > 0) { + v |= 0x20; + } + if (header->extensions&&header->extensions->exists()) { + v |= 0x10; + } + buf->write_1bytes(v); + + // The marker and payload type, total 1 byte. + v = header->payload_type; + if (header->marker) { + v |= kRtpMarker; + } + buf->write_1bytes(v); + + // The sequence number, 2 bytes. + buf->write_2bytes(header->sequence); + + // The timestamp, 4 bytes. + buf->write_4bytes(header->timestamp); + + // The SSRC, 4 bytes. + buf->write_4bytes(header->ssrc); + + // The CSRC list: 0 to 15 items, each is 4 bytes. + for (size_t i = 0; i < header->cc; ++i) { + buf->write_4bytes(header->csrc[i]); + } + + if (header->extensions&&header->extensions->exists()) { + if (Yang_Ok != (err = header->extensions->encode(buf))) { + return yang_error_wrap(err, "encode rtp extension"); + } + } + + return err; +} +int32_t yang_decode_rtpHeader(YangBuffer* buf,YangRtpHeader* header){ + int32_t err = Yang_Ok; + + if (!buf->require(kRtpHeaderFixedSize)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", + kRtpHeaderFixedSize); + } + + /* @see https://tools.ietf.org/html/rfc1889#section-5.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + uint8_t first = buf->read_1bytes(); + bool padding = (first & 0x20); + bool extension = (first & 0x10); + header->cc = (first & 0x0F); + + uint8_t second = buf->read_1bytes(); + header->marker = (second & 0x80); + header->payload_type = (second & 0x7F); + + header->sequence = buf->read_2bytes(); + header->timestamp = buf->read_4bytes(); + header->ssrc = buf->read_4bytes(); + + + + for (uint8_t i = 0; i < header->cc; ++i) { + header->csrc[i] = buf->read_4bytes(); + } + + if (extension) { + if(header->extensions==NULL) header->extensions=new YangRtpExtensions(); + if ((err = parse_extensions(buf,header->extensions)) != Yang_Ok) { + return yang_error_wrap(err, "fail to parse extension"); + } + } + + if (padding && !header->ignore_padding && !buf->empty()) { + header->padding_length = *(reinterpret_cast(buf->data() + buf->size() + - 1)); + if (!buf->require(header->padding_length)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes",header->padding_length); + } + } + + return err; +} +/** + +YangRtpHeader::YangRtpHeader() { + reset(); +} + +YangRtpHeader::~YangRtpHeader() { +} + +void YangRtpHeader::reset(){ + m_cc = 0; + m_marker = false; + m_payload_type = 0; + m_sequence = 0; + m_timestamp = 0; + m_ssrc = 0; + m_padding_length = 0; + m_ignore_padding = false; + memset(m_csrc, 0, sizeof(m_csrc)); +} +int32_t YangRtpHeader::decode(YangBuffer *buf) { + int32_t err = Yang_Ok; + + if (!buf->require(kRtpHeaderFixedSize)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", + kRtpHeaderFixedSize); + } +**/ + /* @see https://tools.ietf.org/html/rfc1889#section-5.1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +/** + uint8_t first = buf->read_1bytes(); + bool padding = (first & 0x20); + bool extension = (first & 0x10); + m_cc = (first & 0x0F); + + uint8_t second = buf->read_1bytes(); + m_marker = (second & 0x80); + m_payload_type = (second & 0x7F); + + m_sequence = buf->read_2bytes(); + m_timestamp = buf->read_4bytes(); + m_ssrc = buf->read_4bytes(); + + int32_t ext_bytes = nb_bytes() - kRtpHeaderFixedSize; + if (!buf->require(ext_bytes)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", + ext_bytes); + } + + for (uint8_t i = 0; i < m_cc; ++i) { + m_csrc[i] = buf->read_4bytes(); + } + + if (extension) { + if ((err = parse_extensions(buf)) != Yang_Ok) { + return yang_error_wrap(err, "fail to parse extension"); + } + } + + if (padding && !m_ignore_padding && !buf->empty()) { + m_padding_length = *(reinterpret_cast(buf->data() + buf->size() + - 1)); + if (!buf->require(m_padding_length)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes", m_padding_length); + } + } + + return err; +} + +int32_t YangRtpHeader::parse_extensions(YangBuffer *buf) { + int32_t err = Yang_Ok; + + if (Yang_Ok != (err = m_extensions.decode(buf))) { + return yang_error_wrap(err, "decode rtp extension"); + } + + return err; +} + +int32_t YangRtpHeader::encode(YangBuffer *buf) { + int32_t err = Yang_Ok; + + // Encode the RTP fix header, 12bytes. + // @see https://tools.ietf.org/html/rfc1889#section-5.1 + // The version, padding, extension and cc, total 1 byte. + uint8_t v = 0x80 | m_cc; + if (m_padding_length > 0) { + v |= 0x20; + } + if (m_extensions.exists()) { + v |= 0x10; + } + buf->write_1bytes(v); + + // The marker and payload type, total 1 byte. + v = m_payload_type; + if (m_marker) { + v |= kRtpMarker; + } + buf->write_1bytes(v); + + // The sequence number, 2 bytes. + buf->write_2bytes(m_sequence); + + // The timestamp, 4 bytes. + buf->write_4bytes(m_timestamp); + + // The SSRC, 4 bytes. + buf->write_4bytes(m_ssrc); + + // The CSRC list: 0 to 15 items, each is 4 bytes. + for (size_t i = 0; i < m_cc; ++i) { + buf->write_4bytes(m_csrc[i]); + } + + if (m_extensions.exists()) { + if (Yang_Ok != (err = m_extensions.encode(buf))) { + return yang_error_wrap(err, "encode rtp extension"); + } + } + + return err; +} +void YangRtpHeader::set_extensions(YangRtpExtensionTypes *extmap) { + if (extmap) { + m_extensions.set_types_(extmap); + } +} + +void YangRtpHeader::ignore_padding(bool v) { + m_ignore_padding = v; +} + +int32_t YangRtpHeader::get_twcc_sequence_number(uint16_t &twcc_sn) { + if (m_extensions.exists()) { + return m_extensions.get_twcc_sequence_number(twcc_sn); + } + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "no rtp extension"); +} + +int32_t YangRtpHeader::set_twcc_sequence_number(uint8_t id, uint16_t sn) { + return m_extensions.set_twcc_sequence_number(id, sn); +} + +uint64_t YangRtpHeader::nb_bytes() { + return kRtpHeaderFixedSize + m_cc * 4 + + (m_extensions.exists() ? m_extensions.nb_bytes() : 0); +} + +void YangRtpHeader::set_marker(bool v) { + m_marker = v; +} + +bool YangRtpHeader::get_marker() const { + return m_marker; +} + +void YangRtpHeader::set_payload_type(uint8_t v) { + m_payload_type = v; +} + +uint8_t YangRtpHeader::get_payload_type() const { + return m_payload_type; +} + +void YangRtpHeader::set_sequence(uint16_t v) { + m_sequence = v; +} + +uint16_t YangRtpHeader::get_sequence() const { + return m_sequence; +} + +void YangRtpHeader::set_timestamp(uint32_t v) { + m_timestamp = v; +} + +uint32_t YangRtpHeader::get_timestamp() const { + return m_timestamp; +} + +void YangRtpHeader::set_ssrc(uint32_t v) { + m_ssrc = v; +} + +void YangRtpHeader::set_padding(uint8_t v) { + m_padding_length = v; +} + +uint8_t YangRtpHeader::get_padding() const { + return m_padding_length; +} +**/ diff --git a/libyangrtc2/src/yangrtp/YangRtpHeader.h b/libyangrtc2/src/yangrtp/YangRtpHeader.h new file mode 100644 index 0000000000000000000000000000000000000000..dc354273c3c533f214c69dc0605ed4cdaac2cdd6 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpHeader.h @@ -0,0 +1,64 @@ +#ifndef SRC_YANGRTP_YANGRTPHEADER_H_ +#define SRC_YANGRTP_YANGRTPHEADER_H_ +#include +struct YangRtpHeader{ + uint8_t padding_length; + uint8_t cc; + bool marker; + uint8_t payload_type; + uint16_t sequence; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[15]; + YangRtpExtensions* extensions; + bool ignore_padding; +}; + +int32_t yang_encode_rtpHeader(YangBuffer* buf,YangRtpHeader* header); +int32_t yang_decode_rtpHeader(YangBuffer* buf,YangRtpHeader* header); +/** +// Note that the header sho;uld never extends from any class, for performance. +class YangRtpHeader //: public IYangCodec +{ +private: + uint8_t m_padding_length; + uint8_t m_cc; + bool m_marker; + uint8_t m_payload_type; + uint16_t m_sequence; + uint32_t m_timestamp; + uint32_t m_ssrc; + uint32_t m_csrc[15]; + YangRtpExtensions m_extensions; + bool m_ignore_padding; +public: + YangRtpHeader(); + virtual ~YangRtpHeader(); +public: + void reset(); + int32_t decode(YangBuffer* buf); +private: + int32_t parse_extensions(YangBuffer* buf); +public: + int32_t encode(YangBuffer* buf); + uint64_t nb_bytes(); +public: + void enable_twcc_decode() { m_extensions.enable_twcc_decode(); } // SrsRtpHeader::enable_twcc_decode + void set_marker(bool v); + bool get_marker() const; + void set_payload_type(uint8_t v); + uint8_t get_payload_type() const; + void set_sequence(uint16_t v); + uint16_t get_sequence() const; + void set_timestamp(uint32_t v); + uint32_t get_timestamp() const; + void set_ssrc(uint32_t v); + inline uint32_t get_ssrc() const { return m_ssrc; } // SrsRtpHeader::get_ssrc + void set_padding(uint8_t v); + uint8_t get_padding() const; + void set_extensions(YangRtpExtensionTypes* extmap); + void ignore_padding(bool v); + int32_t get_twcc_sequence_number(uint16_t& twcc_sn); + int32_t set_twcc_sequence_number(uint8_t id, uint16_t sn); +};**/ +#endif /* SRC_YANGRTP_YANGRTPHEADER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.cpp b/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d16a83a275c9f1f191fec7c5e141022033301a2 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include +YangNackOption::YangNackOption() +{ + max_req_count = 10; + max_alive_time = 1000 * YANG_UTIME_MILLISECONDS; + first_nack_interval = 10 * YANG_UTIME_MILLISECONDS; + nack_interval = 50 * YANG_UTIME_MILLISECONDS; + max_nack_interval = 500 * YANG_UTIME_MILLISECONDS; + min_nack_interval = 15 * YANG_UTIME_MILLISECONDS; + + nack_check_interval = 15 * YANG_UTIME_MILLISECONDS; + + //TODO: FIXME: audio and video using diff nack strategy + // video: + // max_alive_time = 1 * YANG_UTIME_SECONDS + // max_count = 15; + // nack_interval = 50 * YANG_UTIME_MILLISECONDS + // + // audio: + // DefaultRequestNackDelay = 30; //ms + // DefaultLostPacketLifeTime = 600; //ms + // FirstRequestInterval = 50;//ms +} + +YangRtpNackInfo::YangRtpNackInfo() +{ + generate_time_ = yang_get_system_time();//yang_update_system_time(); + pre_req_nack_time_ = 0; + req_nack_count_ = 0; +} + +YangRtpNackForReceiver::YangRtpNackForReceiver(YangRtpPlayNackBuffer* rtp, size_t queue_size) +{ + m_max_queue_size = queue_size; + m_rtp = rtp; + m_pre_check_time = 0; + m_rtt = 0; + + +} + +YangRtpNackForReceiver::~YangRtpNackForReceiver() +{ +} + +void YangRtpNackForReceiver::insert(uint16_t first, uint16_t last) +{ + for (uint16_t s = first; s != last; ++s) { + m_queue[s] = YangRtpNackInfo(); + } +} + +void YangRtpNackForReceiver::remove(uint16_t seq) +{ + m_queue.erase(seq); +} + +YangRtpNackInfo* YangRtpNackForReceiver::find(uint16_t seq) +{ + std::map::iterator iter = m_queue.find(seq); + + if (iter == m_queue.end()) { + return NULL; + } + + return &(iter->second); +} + +void YangRtpNackForReceiver::check_queue_size() +{ + if (m_queue.size() >= m_max_queue_size) { + m_rtp->notify_nack_list_full(); + m_queue.clear(); + } +} +bool YangRtpNackForReceiver::isEmpty(){ + return m_queue.empty(); +} +void YangRtpNackForReceiver::get_nack_seqs(YangRtcpNack& seqs, uint32_t& timeout_nacks) +{ + + int64_t now = yang_get_system_time(); + + //int64_t interval = now - m_pre_check_time; + + if (now - m_pre_check_time < m_opts.nack_check_interval) { + return; + } + m_pre_check_time = now; + + std::map::iterator iter = m_queue.begin(); + while (iter != m_queue.end()) { + const uint16_t& seq = iter->first; + YangRtpNackInfo& nack_info = iter->second; + + int32_t alive_time = now - nack_info.generate_time_; + if (alive_time > m_opts.max_alive_time || nack_info.req_nack_count_ > m_opts.max_req_count) { + ++timeout_nacks; + m_rtp->notify_drop_seq(seq); + m_queue.erase(iter++); + continue; + } + + // TODO:Statistics unorder packet. + if (now - nack_info.generate_time_ < m_opts.first_nack_interval) { + break; + } + + int64_t nack_interval = yang_max(m_opts.min_nack_interval, m_opts.nack_interval / 3); + if(m_opts.nack_interval < 50 * YANG_UTIME_MILLISECONDS){ + nack_interval = yang_max(m_opts.min_nack_interval, m_opts.nack_interval); + } + + if (now - nack_info.pre_req_nack_time_ >= nack_interval ) { + ++nack_info.req_nack_count_; + nack_info.pre_req_nack_time_ = now; + seqs.add_lost_sn(seq); + } + + ++iter; + } +} + +void YangRtpNackForReceiver::update_rtt(int32_t rtt) +{ + m_rtt = rtt * YANG_UTIME_MILLISECONDS; + + if (m_rtt > m_opts.nack_interval) { + m_opts.nack_interval = m_opts.nack_interval * 0.8 + m_rtt * 0.2; + } else { + m_opts.nack_interval = m_rtt; + } + + m_opts.nack_interval = yang_min(m_opts.nack_interval, m_opts.max_nack_interval); +} + diff --git a/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.h b/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.h new file mode 100644 index 0000000000000000000000000000000000000000..fccb0f1fa22cb7a50688ed0f72def8f428775a6e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpNackForReceiver.h @@ -0,0 +1,63 @@ +#ifndef SRC_YANGRTP_YANGRTPNACKFORRECEIVER_H_ +#define SRC_YANGRTP_YANGRTPNACKFORRECEIVER_H_ +#include +#include +#include +#include +#include + +struct YangNackOption +{ + int32_t max_req_count; + int64_t max_alive_time; + int64_t first_nack_interval; + int64_t nack_interval; + + int64_t max_nack_interval; + int64_t min_nack_interval; + int64_t nack_check_interval; + + YangNackOption(); +}; + +struct YangRtpNackInfo +{ + // Use to control the time of first nack req and the life of seq. + int64_t generate_time_; + // Use to control nack interval. + int64_t pre_req_nack_time_; + // Use to control nack times. + int32_t req_nack_count_; + + YangRtpNackInfo(); +}; + +class YangRtpNackForReceiver +{ +private: + // Nack queue, seq order, oldest to newest. + std::map m_queue; + // Max nack count. + size_t m_max_queue_size; + //YangRtpRingBuffer* m_rtp; + YangRtpPlayNackBuffer* m_rtp; + YangNackOption m_opts; +private: + int64_t m_pre_check_time; +private: + int32_t m_rtt; +public: + YangRtpNackForReceiver(YangRtpPlayNackBuffer* rtp, size_t queue_size); + virtual ~YangRtpNackForReceiver(); +public: + void insert(uint16_t first, uint16_t last); + void remove(uint16_t seq); + YangRtpNackInfo* find(uint16_t seq); + void check_queue_size(); + bool isEmpty(); +public: + void get_nack_seqs(YangRtcpNack& seqs, uint32_t& timeout_nacks); +public: + void update_rtt(int32_t rtt); +}; +#endif /* SRC_YANGRTP_YANGRTPNACKFORRECEIVER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpPacket.cpp b/libyangrtc2/src/yangrtp/YangRtpPacket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09b8f31b579a0b27231e627e470b382afca97554 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpPacket.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + + +YangRtpPacket::YangRtpPacket() { + memset(&m_header,0,sizeof(YangRtpHeader)); + m_payload_type = YangRtspPacketPayloadTypeUnknown; + m_actual_buffer_size = 0; + + m_nalu_type = YangAvcNaluTypeReserved; + m_frame_type = YangFrameTypeAudio; + m_cached_payload_size = 0; + + m_payload=NULL; + + m_nb=0; + + +} + +YangRtpPacket::~YangRtpPacket() { + + m_payload=NULL; + +} +void YangRtpPacket::reset(){ + //m_header.reset(); + yang_delete(m_header.extensions); + memset(&m_header,0,sizeof(YangRtpHeader)); + m_payload_type = YangRtspPacketPayloadTypeUnknown; + m_actual_buffer_size = 0; + + m_nalu_type = YangAvcNaluTypeReserved; + m_frame_type = YangFrameTypeAudio; + m_cached_payload_size = 0; + + m_payload=NULL; + m_nb=0; +} +char* YangRtpPacket::wrap(YangRtpBuffer* rtpb,char* data,int32_t nb){ + m_actual_buffer_size=nb; + + char* p=rtpb->getBuffer(); + memcpy(p,data,nb); + return p; +} + +void YangRtpPacket::set_padding(int32_t size) { + m_header.padding_length=size; + if (m_cached_payload_size) { + m_cached_payload_size += size - m_header.padding_length; + } +} + +void YangRtpPacket::add_padding(int32_t size) { + m_header.padding_length=m_header.padding_length + size; + if (m_cached_payload_size) { + m_cached_payload_size += size; + } +} + + +bool YangRtpPacket::is_audio() { + return m_frame_type == YangFrameTypeAudio; +} + +void YangRtpPacket::set_extension_types(YangRtpExtensionTypes *v) { + if( m_header.extensions) m_header.extensions->set_types_(v); +} + +int32_t YangRtpPacket::decode(YangBuffer *buf) { + int32_t err = Yang_Ok; + + if ((err = yang_decode_rtpHeader(buf,&m_header)) != Yang_Ok) { + return yang_error_wrap(err, "rtp header"); + } + + + uint8_t padding = m_header.padding_length; + if (!buf->require(padding)) { + return yang_error_wrap(err, "requires padding %d bytes", padding); + } + buf->set_size(buf->size() - padding); + m_payload=buf->head(); + m_nb=buf->left(); + m_payload_type = YangRtspPacketPayloadTypeRaw; + + + + return err; +} + + + + + diff --git a/libyangrtc2/src/yangrtp/YangRtpPacket.h b/libyangrtc2/src/yangrtp/YangRtpPacket.h new file mode 100644 index 0000000000000000000000000000000000000000..4ce34c5d39b61482cb25b8794b387be49020561e --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpPacket.h @@ -0,0 +1,64 @@ +#ifndef SRC_YANGRTP_YANGRTPPACKET_H_ +#define SRC_YANGRTP_YANGRTPPACKET_H_ +#include +#include +#include + +#include +#include + + + // 8 = audio +#define YangFrameTypeAudio 8 + // 9 = video +#define YangFrameTypeVideo 9 + // 18 = script data + + +class YangRtpPacket +{ +public: + YangRtpPacket(); + virtual ~YangRtpPacket(); +public: + YangRtpHeader m_header; + +public: + // The first byte as nalu type, for video decoder only. + int32_t m_actual_buffer_size; + int32_t m_nalu_type; + // The frame type, for RTMP bridger or SFU source. + int32_t m_frame_type; +// Fast cache for performance. + YangRtspPacketPayloadType m_payload_type; + + char* m_payload; + int32_t m_nb; + //bool m_is_keyframe; +private: + // The cached payload size for packet. + int32_t m_cached_payload_size; + + +public: + // virtual YangRtpPacket* copy(); + char* wrap(YangRtpBuffer* rtpb,char* data,int32_t nb); +public: + // Parse the TWCC extension, ignore by default. + void enable_twcc_decode() { if(m_header.extensions) m_header.extensions->enable_twcc_decode(); } // SrsRtpPacket::enable_twcc_decode + + // Set the padding of RTP packet. + void set_padding(int32_t size); + // Increase the padding of RTP packet. + void add_padding(int32_t size); + + // Whether the packet is Audio packet. + bool is_audio(); + // Set RTP header extensions for encoding or decoding header extension + void set_extension_types(YangRtpExtensionTypes* v); + int32_t decode(YangBuffer* buf); + void reset(); + +}; +int32_t yang_encode_rtppayload(YangRtpPacket* pkt,YangBuffer *buf); +#endif /* SRC_YANGRTP_YANGRTPPACKET_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.cpp b/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8014008d03ded3ba2c2510acb12d9b9202e2e1c --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.cpp @@ -0,0 +1,185 @@ +#include +#include +#include + +YangRtpPlayNackBuffer::YangRtpPlayNackBuffer(int32_t capacity) +{ + m_nn_seq_flip_backs = 0; + m_begin = m_end = 0; + m_capacity = (uint16_t)capacity; + m_contexttialized = false; + + m_queue = new int32_t[m_capacity]; + memset(m_queue, 0, sizeof(int32_t) * capacity); +} + +YangRtpPlayNackBuffer::~YangRtpPlayNackBuffer() +{ + + yang_deleteA(m_queue); +} + +bool YangRtpPlayNackBuffer::empty() +{ + return m_begin == m_end; +} + +int32_t YangRtpPlayNackBuffer::size() +{ + int32_t size = yang_rtp_seq_distance(m_begin, m_end); + //srs_assert(size >= 0); + return size; +} + +void YangRtpPlayNackBuffer::advance_to(uint16_t seq) +{ + m_begin = seq; +} + +void YangRtpPlayNackBuffer::set(uint16_t at, uint16_t pkt) +{ + + + m_queue[at % m_capacity] = pkt; +} + +void YangRtpPlayNackBuffer::remove(uint16_t at) +{ + m_queue[at % m_capacity] = -1; + // set(at, -1); +} + +uint32_t YangRtpPlayNackBuffer::get_extended_highest_sequence() +{ + return m_nn_seq_flip_backs * 65536 + m_end - 1; +} +bool YangRtpPlayNackBuffer::update(uint16_t seq){ + if (!m_contexttialized) { + m_contexttialized = true; + m_begin = seq; + m_end = seq + 1; + return true; + } + // Normal sequence, seq follows high_. + if (yang_rtp_seq_distance(m_end, seq) >= 0) { + //TODO: FIXME: if diff_upper > limit_max_size clear? + // int16_t diff_upper = yang_rtp_seq_distance(end, seq) + // notify_nack_list_full() + + + // When distance(seq,high_)>0 and seq0 and 1<65535. + // TODO: FIXME: The first flip may be dropped. + if (seq < m_end) { + ++m_nn_seq_flip_backs; + } + m_end = seq + 1; + // TODO: FIXME: check whether is neccessary? + // yang_rtp_seq_distance(begin, end) > max_size + // advance_to(), srs_rtp_seq_distance(begin, end) < max_size; + return true; + } + + // Out-of-order sequence, seq before low_. + if (yang_rtp_seq_distance(seq, m_begin) > 0) { + + m_begin = seq; + + // TODO: FIXME: Maybe should support startup drop. + return true; + // When startup, we may receive packets in chaos order. + // Because we don't know the ISN(initiazlie sequence number), the first packet + // we received maybe no the first packet client sent. + // @remark We only log a warning, because it seems ok for publisher. + //return false; + } + + return true; + +} +bool YangRtpPlayNackBuffer::update(uint16_t seq, uint16_t& nack_first, uint16_t& nack_last) +{ + if (!m_contexttialized) { + m_contexttialized = true; + m_begin = seq; + m_end = seq + 1; + return true; + } + + // Normal sequence, seq follows high_. + if (yang_rtp_seq_distance(m_end, seq) >= 0) { + //TODO: FIXME: if diff_upper > limit_max_size clear? + // int16_t diff_upper = yang_rtp_seq_distance(end, seq) + // notify_nack_list_full() + nack_first = m_end; + nack_last = seq; + + // When distance(seq,high_)>0 and seq0 and 1<65535. + // TODO: FIXME: The first flip may be dropped. + if (seq < m_end) { + ++m_nn_seq_flip_backs; + } + m_end = seq + 1; + // TODO: FIXME: check whether is neccessary? + // yang_rtp_seq_distance(begin, end) > max_size + // advance_to(), srs_rtp_seq_distance(begin, end) < max_size; + return true; + } + + // Out-of-order sequence, seq before low_. + if (yang_rtp_seq_distance(seq, m_begin) > 0) { + nack_first = seq; + nack_last = m_begin; + m_begin = seq; + + // TODO: FIXME: Maybe should support startup drop. + return true; + // When startup, we may receive packets in chaos order. + // Because we don't know the ISN(initiazlie sequence number), the first packet + // we received maybe no the first packet client sent. + // @remark We only log a warning, because it seems ok for publisher. + //return false; + } + + return true; +} + +int32_t YangRtpPlayNackBuffer::at(uint16_t seq) { + return m_queue[seq % m_capacity]; +} + +void YangRtpPlayNackBuffer::notify_nack_list_full() +{ + clear_all_histroy(); + + m_begin = m_end = 0; + m_contexttialized = false; +} + +void YangRtpPlayNackBuffer::notify_drop_seq(uint16_t seq) +{ + remove(seq); + advance_to(seq+1); +} + +void YangRtpPlayNackBuffer::clear_histroy(uint16_t seq) +{ + // TODO FIXME Did not consider loopback + for (uint16_t i = 0; i < m_capacity; i++) { + + if ( m_queue[i] < seq) { + + m_queue[i] = -1; + } + } +} + +void YangRtpPlayNackBuffer::clear_all_histroy() +{ + for (uint16_t i = 0; i < m_capacity; i++) { + + m_queue[i] = -1; + + } +} diff --git a/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.h b/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..2ac13e4d63c37700067307c448b0267d653da0e2 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpPlayNackBuffer.h @@ -0,0 +1,54 @@ +#ifndef SRC_YANGRTP_YANGRTPPLAYNACKBUFFER_H_ +#define SRC_YANGRTP_YANGRTPPLAYNACKBUFFER_H_ + +#include +class YangRtpPlayNackBuffer { +public: + YangRtpPlayNackBuffer(int32_t capacity); + virtual ~YangRtpPlayNackBuffer(); + +private: + // Capacity of the ring-buffer. + uint16_t m_capacity; + // Ring bufer. + int32_t* m_queue; + // Increase one when uint16 flip back, for get_extended_highest_sequence. + uint64_t m_nn_seq_flip_backs; + // Whether initialized, because we use uint16 so we can't use -1. + bool m_contexttialized; +public: + // The begin iterator for ring buffer. + // For example, when got 1 elems, the begin is 0. + uint16_t m_begin; + // The end iterator for ring buffer. + // For example, when got 1 elems, the end is 1. + uint16_t m_end; + +public: + // Whether the ring buffer is empty. + bool empty(); + // Get the count of elems in ring buffer. + int32_t size(); + // Move the low position of buffer to seq. + void advance_to(uint16_t seq); + // Free the packet at position. + void set(uint16_t at, uint16_t seq); + void remove(uint16_t at); + // The highest sequence number, calculate the flip back base. + uint32_t get_extended_highest_sequence(); + // Update the sequence, got the nack range by [first, last). + // @return If false, the seq is too old. + bool update(uint16_t seq, uint16_t& nack_first, uint16_t& nack_last); + bool update(uint16_t seq); + // Get the packet by seq. + int32_t at(uint16_t seq); +public: + // TODO: FIXME: Refine it? + void notify_nack_list_full(); + void notify_drop_seq(uint16_t seq); +public: + void clear_histroy(uint16_t seq); + void clear_all_histroy(); +}; + +#endif /* SRC_YANGRTP_YANGRTPPLAYNACKBUFFER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpRawNALUs.cpp b/libyangrtc2/src/yangrtp/YangRtpRawNALUs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37ef528e7e93ef02926ff054ad3cda76c85ff2e9 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRawNALUs.cpp @@ -0,0 +1,133 @@ + +#include +#include +YangRtpRawNALUs::YangRtpRawNALUs() { + m_cursor = 0; + m_nn_bytes = 0; +} + +YangRtpRawNALUs::~YangRtpRawNALUs() { + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + yang_delete(p); + } +} + +void YangRtpRawNALUs::push_back(YangSample *sample) { + if (sample->nb <= 0) { + return; + } + + if (!m_nalus.empty()) { + YangSample *p = new YangSample(); + p->bytes = (char*) "\0\0\1"; + p->nb = 3; + m_nn_bytes += 3; + m_nalus.push_back(p); + } + + m_nn_bytes += sample->nb; + m_nalus.push_back(sample); +} + +uint8_t YangRtpRawNALUs::skip_first_byte() { + // srs_assert (cursor >= 0 && nn_bytes > 0 && cursor < nn_bytes); + m_cursor++; + return uint8_t(m_nalus[0]->bytes[0]); +} + +int32_t YangRtpRawNALUs::read_samples(vector &samples, int32_t packet_size) { + if (m_cursor + packet_size < 0 || m_cursor + packet_size > m_nn_bytes) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "cursor=%d, max=%d, size=%d", m_cursor, m_nn_bytes, packet_size); + } + + int32_t pos = m_cursor; + m_cursor += packet_size; + int32_t left = packet_size; + + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; left > 0 && i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + + // Ignore previous consumed samples. + if (pos && pos - p->nb >= 0) { + pos -= p->nb; + continue; + } + + // Now, we are working at the sample. + int32_t nn = yang_min(left, p->nb - pos); + // srs_assert(nn > 0); + + YangSample *sample = new YangSample(); + samples.push_back(sample); + + sample->bytes = p->bytes + pos; + sample->nb = nn; + + left -= nn; + pos = 0; + } + + return Yang_Ok; +} + +uint64_t YangRtpRawNALUs::nb_bytes() { + int32_t size = 0; + + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + size += p->nb; + } + + return size; +} + +int32_t YangRtpRawNALUs::encode(YangBuffer *buf) { + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + + if (!buf->require(p->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + p->nb); + } + + buf->write_bytes(p->bytes, p->nb); + } + + return Yang_Ok; +} + +int32_t YangRtpRawNALUs::decode(YangBuffer *buf) { + if (buf->empty()) { + return Yang_Ok; + } + + YangSample *sample = new YangSample(); + sample->bytes = buf->head(); + sample->nb = buf->left(); + buf->skip(sample->nb); + + m_nalus.push_back(sample); + + return Yang_Ok; +} + +IYangRtpPayloader* YangRtpRawNALUs::copy() { + YangRtpRawNALUs *cp = new YangRtpRawNALUs(); + + cp->m_nn_bytes = m_nn_bytes; + cp->m_cursor = m_cursor; + + int32_t nn_nalus = (int) m_nalus.size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = m_nalus[i]; + cp->m_nalus.push_back(yang_sample_copy(p)); + } + + return cp; +} diff --git a/libyangrtc2/src/yangrtp/YangRtpRawNALUs.h b/libyangrtc2/src/yangrtp/YangRtpRawNALUs.h new file mode 100644 index 0000000000000000000000000000000000000000..09fa870806d4fe22bc5a579e73145329890a6f48 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRawNALUs.h @@ -0,0 +1,31 @@ +#ifndef SRC_YANGRTP_YANGRTPRAWNALUS_H_ +#define SRC_YANGRTP_YANGRTPRAWNALUS_H_ +#include + +// Multiple NALUs, automatically insert 001 between NALUs. +class YangRtpRawNALUs : public IYangRtpPayloader +{ +private: + // We will manage the samples, but the sample itself point32_t to the shared memory. + std::vector m_nalus; + int32_t m_nn_bytes; + int32_t m_cursor; +public: + YangRtpRawNALUs(); + virtual ~YangRtpRawNALUs(); +public: + void push_back(YangSample* sample); +public: + uint8_t skip_first_byte(); + // We will manage the returned samples, if user want to manage it, please copy it. + int32_t read_samples(std::vector& samples, int32_t packet_size); +// interface ISrsRtpPayloader +public: + virtual uint64_t nb_bytes(); + virtual int32_t encode(YangBuffer* buf); + virtual int32_t decode(YangBuffer* buf); + virtual IYangRtpPayloader* copy(); + int32_t nb_size(){return 0;}; +}; + +#endif /* SRC_YANGRTP_YANGRTPRAWNALUS_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpRawPayload.cpp b/libyangrtc2/src/yangrtp/YangRtpRawPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72da16920b445e3a49d88c8fb90687e4a56e855a --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRawPayload.cpp @@ -0,0 +1,26 @@ +#include +#include +int32_t yang_encode_h264_raw(YangBuffer* buf,YangRtpRawData* pkt){ + if (pkt->nb <= 0) { + return Yang_Ok; + } + + if (!buf->require(pkt->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes",pkt->nb); + } + + buf->write_bytes(pkt->payload, pkt->nb); + + return Yang_Ok; +} +int32_t yang_decode_h264_raw(YangBuffer* buf,YangRtpRawData* pkt){ + if (buf->empty()) { + return Yang_Ok; + } + + pkt->payload = buf->head(); + pkt->nb = buf->left(); + + return Yang_Ok; +} + diff --git a/libyangrtc2/src/yangrtp/YangRtpRawPayload.h b/libyangrtc2/src/yangrtp/YangRtpRawPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..32af13649fc5549a557dd7d8dd379dcb55593cd7 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRawPayload.h @@ -0,0 +1,13 @@ +#ifndef SRC_YANGRTP_YANGRTPRAWPAYLOAD_H_ +#define SRC_YANGRTP_YANGRTPRAWPAYLOAD_H_ +#include +struct YangRtpRawData{ + char* payload; + int32_t nb; +}; + +int32_t yang_encode_h264_raw(YangBuffer* buf,YangRtpRawData* pkt); +int32_t yang_decode_h264_raw(YangBuffer* buf,YangRtpRawData* pkt); + + +#endif /* SRC_YANGRTP_YANGRTPRAWPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpRingBuffer.cpp b/libyangrtc2/src/yangrtp/YangRtpRingBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccf232a24ee24a74ccfe47b850c8a99ca1043954 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRingBuffer.cpp @@ -0,0 +1,146 @@ +#include +#include + +YangRtpRingBuffer::YangRtpRingBuffer(int32_t capacity) +{ + m_nn_seq_flip_backs = 0; + m_begin = m_end = 0; + m_capacity = (uint16_t)capacity; + m_contexttialized = false; + + m_queue = new YangRtpPacket*[m_capacity]; + memset(m_queue, 0, sizeof(YangRtpPacket*) * capacity); +} + +YangRtpRingBuffer::~YangRtpRingBuffer() +{ + for (int32_t i = 0; i < m_capacity; ++i) { + YangRtpPacket* pkt = m_queue[i]; + yang_delete(pkt); + } + yang_deleteA(m_queue); +} + +bool YangRtpRingBuffer::empty() +{ + return m_begin == m_end; +} + +int32_t YangRtpRingBuffer::size() +{ + int32_t size = yang_rtp_seq_distance(m_begin, m_end); + //srs_assert(size >= 0); + return size; +} + +void YangRtpRingBuffer::advance_to(uint16_t seq) +{ + m_begin = seq; +} + +void YangRtpRingBuffer::set(uint16_t at, YangRtpPacket* pkt) +{ + YangRtpPacket* p = m_queue[at % m_capacity]; + yang_delete(p); + + m_queue[at % m_capacity] = pkt; +} + +void YangRtpRingBuffer::remove(uint16_t at) +{ + set(at, NULL); +} + +uint32_t YangRtpRingBuffer::get_extended_highest_sequence() +{ + return m_nn_seq_flip_backs * 65536 + m_end - 1; +} + +bool YangRtpRingBuffer::update(uint16_t seq, uint16_t& nack_first, uint16_t& nack_last) +{ + if (!m_contexttialized) { + m_contexttialized = true; + m_begin = seq; + m_end = seq + 1; + return true; + } + + // Normal sequence, seq follows high_. + if (yang_rtp_seq_distance(m_end, seq) >= 0) { + //TODO: FIXME: if diff_upper > limit_max_size clear? + // int16_t diff_upper = yang_rtp_seq_distance(end, seq) + // notify_nack_list_full() + nack_first = m_end; + nack_last = seq; + + // When distance(seq,high_)>0 and seq0 and 1<65535. + // TODO: FIXME: The first flip may be dropped. + if (seq < m_end) { + ++m_nn_seq_flip_backs; + } + m_end = seq + 1; + // TODO: FIXME: check whether is neccessary? + // yang_rtp_seq_distance(begin, end) > max_size + // advance_to(), srs_rtp_seq_distance(begin, end) < max_size; + return true; + } + + // Out-of-order sequence, seq before low_. + if (yang_rtp_seq_distance(seq, m_begin) > 0) { + nack_first = seq; + nack_last = m_begin; + m_begin = seq; + + // TODO: FIXME: Maybe should support startup drop. + return true; + // When startup, we may receive packets in chaos order. + // Because we don't know the ISN(initiazlie sequence number), the first packet + // we received maybe no the first packet client sent. + // @remark We only log a warning, because it seems ok for publisher. + //return false; + } + + return true; +} + +YangRtpPacket* YangRtpRingBuffer::at(uint16_t seq) { + return m_queue[seq % m_capacity]; +} + +void YangRtpRingBuffer::notify_nack_list_full() +{ + clear_all_histroy(); + + m_begin = m_end = 0; + m_contexttialized = false; +} + +void YangRtpRingBuffer::notify_drop_seq(uint16_t seq) +{ + remove(seq); + advance_to(seq+1); +} + +void YangRtpRingBuffer::clear_histroy(uint16_t seq) +{ + // TODO FIXME Did not consider loopback + for (uint16_t i = 0; i < m_capacity; i++) { + YangRtpPacket* p = m_queue[i]; + if (p && p->m_header.sequence < seq) { + yang_delete(p); + m_queue[i] = NULL; + } + } +} + +void YangRtpRingBuffer::clear_all_histroy() +{ + for (uint16_t i = 0; i < m_capacity; i++) { + YangRtpPacket* p = m_queue[i]; + if (p) { + yang_delete(p); + m_queue[i] = NULL; + } + } +} diff --git a/libyangrtc2/src/yangrtp/YangRtpRingBuffer.h b/libyangrtc2/src/yangrtp/YangRtpRingBuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..11e5ef8cd6e4edb358e5f1196f113f5c77b267df --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpRingBuffer.h @@ -0,0 +1,60 @@ +#ifndef SRC_YANGRTP_YANGRTPRINGBUFFER_H_ +#define SRC_YANGRTP_YANGRTPRINGBUFFER_H_ +#include +#include +// For UDP, the packets sequence may present as bellow: +// [seq1(done)|seq2|seq3 ... seq10|seq11(lost)|seq12|seq13] +// \___(head_sequence_) \ \___(highest_sequence_) +// \___(no received, in nack list) +// * seq1: The packet is done, we have already got and processed it. +// * seq2,seq3,...,seq10,seq12,seq13: Theses packets are in queue and wait to be processed. +// * seq10: This packet is lost or not received, we will put it in the nack list. +// We store the received packets in ring buffer. +class YangRtpRingBuffer +{ +public: + YangRtpRingBuffer(int32_t capacity); + virtual ~YangRtpRingBuffer(); +private: + // Capacity of the ring-buffer. + uint16_t m_capacity; + // Ring bufer. + YangRtpPacket** m_queue; + // Increase one when uint16 flip back, for get_extended_highest_sequence. + uint64_t m_nn_seq_flip_backs; + // Whether initialized, because we use uint16 so we can't use -1. + bool m_contexttialized; +public: + // The begin iterator for ring buffer. + // For example, when got 1 elems, the begin is 0. + uint16_t m_begin; + // The end iterator for ring buffer. + // For example, when got 1 elems, the end is 1. + uint16_t m_end; + +public: + // Whether the ring buffer is empty. + bool empty(); + // Get the count of elems in ring buffer. + int32_t size(); + // Move the low position of buffer to seq. + void advance_to(uint16_t seq); + // Free the packet at position. + void set(uint16_t at, YangRtpPacket* pkt); + void remove(uint16_t at); + // The highest sequence number, calculate the flip back base. + uint32_t get_extended_highest_sequence(); + // Update the sequence, got the nack range by [first, last). + // @return If false, the seq is too old. + bool update(uint16_t seq, uint16_t& nack_first, uint16_t& nack_last); + // Get the packet by seq. + YangRtpPacket* at(uint16_t seq); +public: + // TODO: FIXME: Refine it? + void notify_nack_list_full(); + void notify_drop_seq(uint16_t seq); +public: + void clear_histroy(uint16_t seq); + void clear_all_histroy(); +}; +#endif /* SRC_YANGRTP_YANGRTPRINGBUFFER_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.cpp b/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afff6f65e44ab695aeffda94c5a2a9990c193790 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.cpp @@ -0,0 +1,240 @@ +#include +#include +#include +#include +YangSample* yang_get_h264_stap_sps(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return NULL; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + if (!p || !p->nb) { + continue; + } + + YangAvcNaluType nalu_type = (YangAvcNaluType) (p->bytes[0] & kNalTypeMask); + if (nalu_type == YangAvcNaluTypeSPS) { + return p; + } + } + + return NULL; +} +YangSample* yang_get_h264_stap_pps(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return NULL; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + if (!p || !p->nb) { + continue; + } + + YangAvcNaluType nalu_type = (YangAvcNaluType) (p->bytes[0] & kNalTypeMask); + if (nalu_type == YangAvcNaluTypePPS) { + return p; + } + } + + return NULL; +} + +void yang_reset_h2645_stap(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + yang_delete(p); + } + data->nalus->clear(); +} +int32_t yang_decode_h264_stap(YangBuffer* buf,YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return yang_error_wrap(ERROR_RTC_RTP_MUXER, "decode stap nalu vector is null!"); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // STAP header, RTP payload format for aggregation packets + // @see https://tools.ietf.org/html/rfc6184#section-5.7 + uint8_t v = buf->read_1bytes(); + + // forbidden_zero_bit shoul be zero. + // @see https://tools.ietf.org/html/rfc6184#section-5.3 + uint8_t f = (v & 0x80); + if (f == 0x80) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "forbidden_zero_bit should be zero"); + } + + data->nri = YangAvcNaluType(v & (~kNalTypeMask)); + + // NALUs. + while (!buf->empty()) { + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + + int32_t size = buf->read_2bytes(); + if (!buf->require(size)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + size); + } + + YangSample *sample = new YangSample(); + sample->bytes = buf->head(); + sample->nb = size; + buf->skip(size); + + if(data->nalus) data->nalus->push_back(sample); + } + + return Yang_Ok; +} + +int32_t yang_encode_h264_stap(YangBuffer* buf,YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return yang_error_wrap(ERROR_RTC_RTP_MUXER, "stap nalu vector is null!"); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // STAP header, RTP payload format for aggregation packets + // @see https://tools.ietf.org/html/rfc6184#section-5.7 + uint8_t v = kStapA; + v |= (data->nri & (~kNalTypeMask)); + buf->write_1bytes(v); + + // NALUs. + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p =data->nalus->at(i); + + if (!buf->require(2 + p->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + 2 + p->nb); + } + + buf->write_2bytes(p->nb); + buf->write_bytes(p->bytes, p->nb); + } + + return Yang_Ok; +} +int32_t yang_decode_h265_stap(YangBuffer* buf,YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return yang_error_wrap(ERROR_RTC_RTP_MUXER, "decode stap nalu vector is null!"); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // STAP header, RTP payload format for aggregation packets + // @see https://tools.ietf.org/html/rfc6184#section-5.7 + uint8_t v = buf->read_1bytes(); + + // forbidden_zero_bit shoul be zero. + // @see https://tools.ietf.org/html/rfc6184#section-5.3 + //uint8_t f = (v & 0x80); + //if (f == 0x80) { + // return yang_error_wrap(ERROR_RTC_RTP_MUXER, "forbidden_zero_bit should be zero"); + //} + + data->nri = YANG_HEVC_NALU_TYPE(v);//YangAvcNaluType(v & (~kNalTypeMask)); + + // NALUs. + while (!buf->empty()) { + if (!buf->require(2)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2); + } + + int32_t size = buf->read_2bytes(); + if (!buf->require(size)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + size); + } + + YangSample *sample = new YangSample(); + sample->bytes = buf->head(); + sample->nb = size; + buf->skip(size); + + if(data->nalus) data->nalus->push_back(sample); + } + + return Yang_Ok; +} + +int32_t yang_encode_h265_stap(YangBuffer* buf,YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return yang_error_wrap(ERROR_RTC_RTP_MUXER, "stap nalu vector is null!"); + if (!buf->require(1)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // STAP header, RTP payload format for aggregation packets + // @see https://tools.ietf.org/html/rfc6184#section-5.7 + uint8_t v = H265_kStapA<<1; + //v |= (data->nri & (~kNalTypeMask)); + buf->write_1bytes(v); + + // NALUs. + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p =data->nalus->at(i); + + if (!buf->require(2 + p->nb)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "requires %d bytes", + 2 + p->nb); + } + + buf->write_2bytes(p->nb); + buf->write_bytes(p->bytes, p->nb); + } + + return Yang_Ok; +} +YangSample* yang_get_h265_stap_sps(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return NULL; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + if (!p || !p->nb) { + continue; + } + + YangHevcNaluType nalu_type = (YangHevcNaluType) YANG_HEVC_NALU_TYPE(p->bytes[0]); + if (nalu_type == YANG_NAL_UNIT_SPS) { + return p; + } + } + + return NULL; +} +YangSample* yang_get_h265_stap_pps(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return NULL; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + if (!p || !p->nb) { + continue; + } + + YangHevcNaluType nalu_type = (YangHevcNaluType) YANG_HEVC_NALU_TYPE(p->bytes[0]); + if (nalu_type == YANG_NAL_UNIT_PPS) { + return p; + } + } + + return NULL; +} +YangSample* yang_get_h265_stap_vps(YangRtpSTAPData* data){ + if(data==NULL||data->nalus==NULL) return NULL; + int32_t nn_nalus = (int) data->nalus->size(); + for (int32_t i = 0; i < nn_nalus; i++) { + YangSample *p = data->nalus->at(i); + if (!p || !p->nb) { + continue; + } + + YangHevcNaluType nalu_type = (YangHevcNaluType) YANG_HEVC_NALU_TYPE(p->bytes[0]); + if (nalu_type == YANG_NAL_UNIT_VPS) { + return p; + } + } + + return NULL; +} diff --git a/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.h b/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..909bf573fcde2aa7ea43b58226325a070b6517c5 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtpSTAPPayload.h @@ -0,0 +1,28 @@ +#ifndef SRC_YANGRTP_YANGRTPSTAPPAYLOAD_H_ +#define SRC_YANGRTP_YANGRTPSTAPPAYLOAD_H_ +#include + +// STAP-A, for multiple NALUs. +// FU-A, for one NALU with multiple fragments. +// With only one payload. +struct YangRtpSTAPData{ + int32_t nri; + int32_t nb; + char* payload; + // The NALU samples, we will manage the samples. + // @remark We only refer to the memory, user must free its bytes. + std::vector* nalus; +}; + +void yang_reset_h2645_stap(YangRtpSTAPData* data); +YangSample* yang_get_h264_stap_sps(YangRtpSTAPData* data); +YangSample* yang_get_h265_stap_sps(YangRtpSTAPData* data); +YangSample* yang_get_h264_stap_pps(YangRtpSTAPData* data); +YangSample* yang_get_h265_stap_pps(YangRtpSTAPData* data); +YangSample* yang_get_h265_stap_vps(YangRtpSTAPData* data); +int32_t yang_decode_h264_stap(YangBuffer* buf,YangRtpSTAPData* data); +int32_t yang_encode_h264_stap(YangBuffer* buf,YangRtpSTAPData* data); +int32_t yang_decode_h265_stap(YangBuffer* buf,YangRtpSTAPData* data); +int32_t yang_encode_h265_stap(YangBuffer* buf,YangRtpSTAPData* data); + +#endif /* SRC_YANGRTP_YANGRTPSTAPPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangRtxPayloadDes.cpp b/libyangrtc2/src/yangrtp/YangRtxPayloadDes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bd4306750f22fe5798f4c37090ba9ca3696b334 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtxPayloadDes.cpp @@ -0,0 +1,45 @@ + +#include +#include + + +YangRtxPayloadDes::YangRtxPayloadDes() +{ +} + +YangRtxPayloadDes::YangRtxPayloadDes(uint8_t pt, uint8_t apt):YangCodecPayload(pt, "rtx", 8000), apt_(apt) +{ +} + +YangRtxPayloadDes::~YangRtxPayloadDes() +{ +} + +YangRtxPayloadDes* YangRtxPayloadDes::copy() +{ + YangRtxPayloadDes* cp = new YangRtxPayloadDes(); + + cp->m_type = m_type; + cp->m_pt = m_pt; + cp->m_pt_of_publisher = m_pt_of_publisher; + cp->m_name = m_name; + cp->m_sample = m_sample; + cp->m_rtcp_fbs = m_rtcp_fbs; + cp->apt_ = apt_; + + return cp; +} + +YangMediaPayloadType YangRtxPayloadDes::generate_media_payload_type() +{ + YangMediaPayloadType media_payload_type(m_pt); + + media_payload_type.m_encoding_name = m_name; + media_payload_type.m_clock_rate = m_sample; + std::ostringstream format_specific_param; + format_specific_param << "fmtp:" << m_pt << " apt="<< apt_; + + media_payload_type.m_format_specific_param = format_specific_param.str(); + + return media_payload_type; +} diff --git a/libyangrtc2/src/yangrtp/YangRtxPayloadDes.h b/libyangrtc2/src/yangrtp/YangRtxPayloadDes.h new file mode 100644 index 0000000000000000000000000000000000000000..561881b378881ab81d134f1529eecfc62a9460f1 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangRtxPayloadDes.h @@ -0,0 +1,18 @@ +#ifndef SRC_YANGRTP_YANGRTXPAYLOADDES_H_ +#define SRC_YANGRTP_YANGRTXPAYLOADDES_H_ +#include +class YangRtxPayloadDes : public YangCodecPayload +{ +public: + uint8_t apt_; +public: + YangRtxPayloadDes(); + YangRtxPayloadDes(uint8_t pt, uint8_t apt); + virtual ~YangRtxPayloadDes(); + +public: + virtual YangRtxPayloadDes* copy(); + virtual YangMediaPayloadType generate_media_payload_type(); +}; + +#endif /* SRC_YANGRTP_YANGRTXPAYLOADDES_H_ */ diff --git a/libyangrtc2/src/yangrtp/YangVideoPayload.cpp b/libyangrtc2/src/yangrtp/YangVideoPayload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d35a21597657b7b23d8ae9e909995c0864c3ec3 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangVideoPayload.cpp @@ -0,0 +1,99 @@ +#include +#include +#include +#include +YangVideoPayload::YangVideoPayload() +{ + m_type = "video"; +} + +YangVideoPayload::YangVideoPayload(uint8_t pt, std::string encode_name, int32_t sample) + :YangCodecPayload(pt, encode_name, sample) +{ + m_type = "video"; + m_h264_param.profile_level_id = ""; + m_h264_param.packetization_mode = ""; + m_h264_param.level_asymmerty_allow = ""; +} + +YangVideoPayload::~YangVideoPayload() +{ +} + +YangVideoPayload* YangVideoPayload::copy() +{ + YangVideoPayload* cp = new YangVideoPayload(); + + cp->m_type = m_type; + cp->m_pt = m_pt; + cp->m_pt_of_publisher = m_pt_of_publisher; + cp->m_name = m_name; + cp->m_sample = m_sample; + cp->m_rtcp_fbs = m_rtcp_fbs; + cp->m_h264_param = m_h264_param; + + return cp; +} + + +YangMediaPayloadType YangVideoPayload::generate_media_payload_type() +{ + YangMediaPayloadType media_payload_type(m_pt); + + media_payload_type.m_encoding_name = m_name; + media_payload_type.m_clock_rate = m_sample; + media_payload_type.m_rtcp_fb = m_rtcp_fbs; + + std::ostringstream format_specific_param; + if (!m_h264_param.level_asymmerty_allow.empty()) { + format_specific_param << "level-asymmetry-allowed=" << m_h264_param.level_asymmerty_allow; + } + if (!m_h264_param.packetization_mode.empty()) { + format_specific_param << ";packetization-mode=" << m_h264_param.packetization_mode; + } + if (!m_h264_param.profile_level_id.empty()) { + format_specific_param << ";profile-level-id=" << m_h264_param.profile_level_id; + } + + media_payload_type.m_format_specific_param = format_specific_param.str(); + + return media_payload_type; +} + +int32_t YangVideoPayload::set_h264_param_desc(std::string fmtp) +{ + int32_t err = Yang_Ok; + + // For example: level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f + std::vector attributes = yang_splits(fmtp, ";"); + + for (size_t i = 0; i < attributes.size(); ++i) { + std::string attribute = attributes.at(i); + + std::vector kv = yang_splits(attribute, "="); + if (kv.size() != 2) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid h264 param=%s", attribute.c_str()); + } + + if (kv[0] == "profile-level-id") { + m_h264_param.profile_level_id = kv[1]; + } else if (kv[0] == "packetization-mode") { + // 6.3. Non-Interleaved Mode + // This mode is in use when the value of the OPTIONAL packetization-mode + // media type parameter is equal to 1. This mode SHOULD be supported. + // It is primarily intended for low-delay applications. Only single NAL + // unit packets, STAP-As, and FU-As MAY be used in this mode. STAP-Bs, + // MTAPs, and FU-Bs MUST NOT be used. The transmission order of NAL + // units MUST comply with the NAL unit decoding order. + // @see https://tools.ietf.org/html/rfc6184#section-6.3 + m_h264_param.packetization_mode = kv[1]; + } else if (kv[0] == "level-asymmetry-allowed") { + m_h264_param.level_asymmerty_allow = kv[1]; + } else { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid h264 param=%s", kv[0].c_str()); + } + } + + return err; +} + diff --git a/libyangrtc2/src/yangrtp/YangVideoPayload.h b/libyangrtc2/src/yangrtp/YangVideoPayload.h new file mode 100644 index 0000000000000000000000000000000000000000..9b5989fb54c24551369e8db153cd71fb3f55a1a5 --- /dev/null +++ b/libyangrtc2/src/yangrtp/YangVideoPayload.h @@ -0,0 +1,29 @@ +#ifndef SRC_YANGRTP_YANGVIDEOPAYLOAD_H_ +#define SRC_YANGRTP_YANGVIDEOPAYLOAD_H_ + +#include + +// TODO: FIXME: Rename it. +class YangVideoPayload : public YangCodecPayload +{ +public: + struct H264SpecificParameter + { + std::string profile_level_id; + std::string packetization_mode; + std::string level_asymmerty_allow; + }; + H264SpecificParameter m_h264_param; + +public: + YangVideoPayload(); + YangVideoPayload(uint8_t pt, std::string encode_name, int32_t sample); + virtual ~YangVideoPayload(); +public: + virtual YangVideoPayload* copy(); + virtual YangMediaPayloadType generate_media_payload_type(); +public: + int32_t set_h264_param_desc(std::string fmtp); +}; + +#endif /* SRC_YANGRTP_YANGVIDEOPAYLOAD_H_ */ diff --git a/libyangrtc2/src/yangsrt/YangSrtBase.cpp b/libyangrtc2/src/yangsrt/YangSrtBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd8f38bbf604f32049f8f0ddfeb75705ae5b2ceb --- /dev/null +++ b/libyangrtc2/src/yangsrt/YangSrtBase.cpp @@ -0,0 +1,412 @@ +/* + * YangSrtBase.cpp + * + * Created on: 2020年9月4日 + * Author: yang + */ +#include + +#ifdef _WIN32 +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x602 +#endif +#include +//#pragma comment(lib,"Ws2_32.lib") +#else +#include + +#include +#include +#endif +#include +#include +#include +#include "string.h" + +#include "yangutil/sys/YangLog.h" + +#define POLLING_TIME 1 /// Time in milliseconds between interrupt check +#define TS_UDP_LEN 188*7 + +using namespace std; + +#define HAVE_GETTIMEOFDAY 1 + +int64_t sls_gettime(void) //rturn micro-second + { +#ifndef _WIN32 + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t) tv.tv_sec * 1000000 + tv.tv_usec; +#else + FILETIME ft; + int64_t t; + GetSystemTimeAsFileTime(&ft); + t = (int64_t) ft.dwHighDateTime << 32 | ft.dwLowDateTime; + return t / 10 - 11644473600000000; // Jan 1, 1601 + + //return -1; +#endif +} +int64_t sls_gettime_ms(void) //rturn millisecond + { + return sls_gettime() / 1000; +} + +void YangSrtBase::loadLib() { + yang_srt_startup = (int32_t (*)(void)) m_lib.loadFunction("srt_startup"); + ; + yang_srt_setloglevel = (void (*)(int32_t ll)) m_lib.loadFunction( + "srt_setloglevel"); + + yang_srt_create_socket = (SRTSOCKET (*)(void)) m_lib.loadFunction( + "srt_create_socket"); + yang_srt_setsockopt = (int32_t (*)(SRTSOCKET u, int32_t level, SRT_SOCKOPT optname, + const void *optval, int32_t optlen)) m_lib.loadFunction( + "srt_setsockopt"); + yang_srt_setsockflag = (int32_t (*)(SRTSOCKET u, SRT_SOCKOPT opt, + const void *optval, int32_t optlen)) m_lib.loadFunction( + "srt_setsockflag"); + yang_srt_connect = (int32_t (*)(SRTSOCKET u, const struct sockaddr *name, + int32_t namelen)) m_lib.loadFunction("srt_connect"); + yang_srt_epoll_create = (int32_t (*)(void)) m_lib.loadFunction( + "srt_epoll_create"); + yang_srt_epoll_set = + (int32_t (*)(int32_t eid, int32_t flags)) m_lib.loadFunction( + "srt_epoll_set"); + yang_srt_epoll_add_usock = + (int32_t (*)(int32_t eid, SRTSOCKET u, const int32_t *events)) m_lib.loadFunction( + "srt_epoll_add_usock"); + yang_srt_epoll_remove_usock = + (int32_t (*)(int32_t eid, SRTSOCKET u)) m_lib.loadFunction( + "srt_epoll_remove_usock"); + yang_srt_epoll_release = (int32_t (*)(int32_t eid)) m_lib.loadFunction( + "srt_epoll_release"); + yang_srt_close = (int32_t (*)(SRTSOCKET u)) m_lib.loadFunction("srt_close"); + yang_srt_getsockstate = + (SRT_SOCKSTATUS (*)(SRTSOCKET u)) m_lib.loadFunction( + "srt_getsockstate"); + yang_srt_cleanup = (int32_t (*)(void)) m_lib.loadFunction("srt_cleanup"); + yang_srt_epoll_wait = (int32_t (*)(int32_t eid, SRTSOCKET *readfds, int32_t *rnum, + SRTSOCKET *writefds, int32_t *wnum, int64_t msTimeOut, SYSSOCKET *lrfds, + int32_t *lrnum, SYSSOCKET *lwfds, int32_t *lwnum)) m_lib.loadFunction( + "srt_epoll_wait"); + yang_srt_sendmsg = (int32_t (*)(SRTSOCKET u, const char *buf, int32_t len, + int32_t ttl/* = -1*/, int32_t inorder/* = false*/)) m_lib.loadFunction( + "srt_sendmsg"); + yang_srt_recvmsg = + (int32_t (*)(SRTSOCKET u, char *buf, int32_t len)) m_lib.loadFunction( + "srt_recvmsg"); + yang_srt_getlasterror = (int32_t (*)(int32_t *errno_loc)) m_lib.loadFunction( + "srt_getlasterror"); + yang_srt_getlasterror_str = (const char* (*)(void)) m_lib.loadFunction( + "srt_getlasterror_str"); +} + +void YangSrtBase::unloadLib() { //srt_cleanup + yang_srt_startup = NULL; + yang_srt_getsockstate = NULL; + yang_srt_setloglevel = NULL; + yang_srt_create_socket = NULL; + yang_srt_setsockopt = NULL; + yang_srt_setsockflag = NULL; + yang_srt_connect = NULL; + yang_srt_epoll_create = NULL; + yang_srt_epoll_set = NULL; + yang_srt_epoll_add_usock = NULL; + yang_srt_epoll_remove_usock = NULL; + yang_srt_epoll_release = NULL; + yang_srt_close = NULL; + yang_srt_cleanup = NULL; + yang_srt_epoll_wait = NULL; + yang_srt_sendmsg = NULL; + yang_srt_recvmsg = NULL; + yang_srt_getlasterror = NULL; + yang_srt_getlasterror_str = NULL; + +} +YangSrtBase::YangSrtBase() { + m_port = 9000; + m_sfd = -1; + m_eid = -1; + m_dataCount = 0; + m_beginTm = 0; + m_bitRate = 0; + m_errState = 0; + m_contextt = 0; + memset(m_server, 0, YangSrtBase_strlen); + unloadLib(); +} + +YangSrtBase::~YangSrtBase() { + closeSrt(); + yang_srt_cleanup(); + unloadLib(); + m_lib.unloadObject(); +} + +void YangSrtBase::closeSrt() { + if (!m_contextt) + return; + int32_t st = 0; + + if (m_eid > 0) { + st = yang_srt_epoll_remove_usock(m_eid, m_sfd); + yang_srt_epoll_release(m_eid); + + } + //srt_close + if (m_sfd > 0) { + st = yang_srt_close(m_sfd); + } + if (st == SRT_ERROR) { + yang_error("srt_close: %s", yang_srt_getlasterror_str()); + return; + } + m_sfd = 0; + //srt_cleanup(); + +} +int32_t YangSrtBase::getSrtSocketStatus() { + return yang_srt_getsockstate(m_sfd); +} +int32_t YangSrtBase::init(char *pserver, int32_t pport) { + if (m_contextt) + return Yang_Ok; +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(2, 2); //create 16bit data + if (WSAStartup(wVersionRequested, &wsaData) != 0) { + printf("Load WinSock Failed!"); + exit(1); + return ERROR_SOCKET; + } +#endif + + m_lib.loadObject("libsrt"); + loadLib(); + strcpy(m_server, pserver); + m_port = pport; + yang_srt_startup(); + yang_srt_setloglevel(srt_logging::LogLevel::debug); + + m_errState = Yang_Ok; + m_contextt = 1; + return Yang_Ok; +} +#ifdef _WIN32 +int32_t YangSrtBase::yang_inet_pton(int32_t af, const char *src, void *dst) { + struct sockaddr_storage ss; + int32_t ssSize = sizeof(ss); + char srcCopy[INET6_ADDRSTRLEN + 1]; + + ZeroMemory(&ss, sizeof(ss)); + + // work around non-const API + strncpy(srcCopy, src, INET6_ADDRSTRLEN + 1); + srcCopy[INET6_ADDRSTRLEN] = '\0'; + + if (WSAStringToAddressA(srcCopy, af, NULL, (struct sockaddr*) &ss, &ssSize) + != 0) { + return 0; + } + + switch (af) { + case AF_INET: { + *(struct in_addr*) dst = ((struct sockaddr_in*) &ss)->sin_addr; + return 1; + } + case AF_INET6: { + *(struct in6_addr*) dst = ((struct sockaddr_in6*) &ss)->sin6_addr; + return 1; + } + default: { + // No-Op + } + } + + return 0; +} +#endif +int32_t YangSrtBase::initConnect(char *streamid) { + m_sfd = yang_srt_create_socket(); + if (m_sfd == SRT_ERROR) { + yang_error("srt_socket: %s", yang_srt_getlasterror_str()); + return ERROR_SRT_SocketConnectCreate; + } + int32_t no = 0; //,m_is_write=1; + // srt_setsockflag(m_sfd, SRTO_SENDER, &m_is_write, sizeof m_is_write); +#ifdef _WIN32 + //int32_t mss = 1052; + //yang_srt_setsockopt(m_sfd, 0, SRTO_MSS, &mss, sizeof(int)); +#endif + yang_srt_setsockopt(m_sfd, 0, SRTO_SNDSYN, &no, sizeof no); // for async write + yang_srt_setsockopt(m_sfd, 0, SRTO_RCVSYN, &no, sizeof no); + if (yang_srt_setsockopt(m_sfd, 0, SRTO_STREAMID, streamid, strlen(streamid)) + < 0) { + yang_error( + "[%p]CSLSRelay::open, srt_setsockopt SRTO_STREAMID failure. err=%s.", + this, yang_srt_getlasterror_str()); + return ERROR_SRT_StreamIdSetFailure; + } + + // int32_t minversion = SRT_VERSION_FEAT_HSv5; + // srt_setsockflag(m_sfd, SRTO_MINVERSION, &minversion, sizeof minversion); + + // Require also non-live message mode. + int32_t file_mode = SRTT_LIVE; //SRTT_FILE; + // int32_t yes = 1; + yang_srt_setsockflag(m_sfd, SRTO_TRANSTYPE, &file_mode, sizeof file_mode); + // srt_setsockflag(m_sfd, SRTO_MESSAGEAPI, &yes, sizeof yes); + + addrinfo hints, *res; + char portstr[10] = { 0 }; + snprintf(portstr, sizeof(portstr), "%d", m_port); + memset(&hints, 0, sizeof(addrinfo)); + + hints.ai_socktype = SOCK_DGRAM; //SOCK_STREAM; + hints.ai_family = AF_INET; + struct sockaddr_in sa; + sa.sin_port = htons(m_port); + sa.sin_family = AF_INET; //AF_UNSPEC; + getaddrinfo(m_server, portstr, &hints, &res); +#ifdef _WIN32 + if (yang_inet_pton(AF_INET, (const char*) m_server, &sa.sin_addr) != 1) { + return ERROR_SRT_SocketConnect; + } +#else + if (inet_pton(AF_INET, (const char*) m_server, &sa.sin_addr) != 1) { + return ERROR_SRT_SocketConnect; + } +#endif + //srt_connect + int32_t st = yang_srt_connect(m_sfd, (struct sockaddr*) &sa, sizeof sa); + SRT_SOCKSTATUS status = yang_srt_getsockstate(m_sfd); + yang_info("srt connect status===%d", status); + if (st == SRT_ERROR) { + yang_error("srt_connect: %s", yang_srt_getlasterror_str()); + return ERROR_SRT_SocketConnect; + } +//#ifndef _WIN32 + m_eid = yang_srt_epoll_create(); + if (m_eid < 0) { + yang_error("work, srt_epoll_create failed."); + return ERROR_SRT_EpollCreateFailure; + // return CSLSSrt::libsrt_neterrno(); + } + //compatible with srt v1.4.0 when container is empty. + yang_srt_epoll_set(m_eid, SRT_EPOLL_ENABLE_EMPTY); + int32_t modes = SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR; + + int32_t ret = yang_srt_epoll_add_usock(m_eid, m_sfd, &modes); + if (ret < 0) { + yang_error( + "srt_add_to_epoll, srt_epoll_add_usock failed, m_eid=%d, fd=%d, modes=%d.", + m_eid, m_sfd, modes); + return ERROR_SRT_EpollSetFailure; //libsrt_neterrno(); + } +//#endif + return Yang_Ok; +} +int32_t YangSrtBase::connectServer() { + int32_t srtRet = 0; + for (int32_t i = 0; i < 500; i++) { + srtRet = getSrtSocketStatus(); + if (srtRet == SRTS_CONNECTED) { + return Yang_Ok; + } + yang_usleep(1000); + } + + srtRet += Yang_SRTS_SocketBase; + if (srtRet == Yang_SRTS_CONNECTING) srtRet = Yang_SRTS_NONSRTSERVER; + return yang_error_wrap(srtRet,"srt connect error"); + +} +int32_t YangSrtBase::receive(char *szData, int32_t *plen) { + if (yang_srt_getsockstate(m_sfd) != SRTS_CONNECTED) + return ERROR_SRT_NotInit; + //char szData[TS_UDP_LEN]; + *plen = 0; + int32_t ret = 0; +//#ifndef _WIN32 + SRTSOCKET read_socks[1]; + SRTSOCKET write_socks[1]; + + int32_t read_len = 1; + int32_t write_len = 0; + ret = yang_srt_epoll_wait(m_eid, read_socks, &read_len, write_socks, + &write_len, POLLING_TIME, 0, 0, 0, 0); + + if (ret < 2) { + //yang_error("srt_epoll failure, n=%s.", yang_srt_getlasterror_str()); + return Yang_Ok; //ERROR_SRT_EpollSelectFailure; + } + if (0 >= read_socks[0]) { + //yang_error("srt_reader failure, n=%s.", yang_srt_getlasterror_str()); + return Yang_Ok; //ERROR_SRT_ReadSocket; + } +//#endif + //read data + ret = yang_srt_recvmsg(m_sfd, szData, TS_UDP_LEN); + + // if(ret>0) printf("a%d,",*plen); + + if (ret == SRT_ERROR) { + // int32_t err_no = srt_getlasterror(NULL); + if (getSrtSocketStatus() == SRTS_CONNECTED) + return Yang_Ok; + yang_error("read_data_handler, srt_read failure, errno=%d...err=%s", + yang_srt_getlasterror(NULL), yang_srt_getlasterror_str()); + return ERROR_SRT_PullFailure; + } + *plen = ret; + //*len=ret; + //update invalid begin time + //m_invalid_begin_tm = sls_gettime(); + //printf("%d,",ret); + m_dataCount += ret; + int64_t cur_tm = sls_gettime_ms(); + int32_t d = cur_tm - m_beginTm; + if (d >= 500) { + m_bitRate = m_dataCount * 8 / d; + m_dataCount = 0; + m_beginTm = sls_gettime_ms(); + } + return Yang_Ok; + +} + +int32_t YangSrtBase::publish(char *message, int32_t len) { +//#ifndef _WIN32 + if (yang_srt_getsockstate(m_sfd) != SRTS_CONNECTED) + return ERROR_SRT_NotInit; + SRTSOCKET read_socks[1]; + SRTSOCKET write_socks[1]; + int32_t read_len = 0; + int32_t write_len = 1; + + int32_t ret = yang_srt_epoll_wait(m_eid, read_socks, &read_len, write_socks, + &write_len, POLLING_TIME, 0, 0, 0, 0); + if (0 > ret) { + //return ERROR_SRT_EpollSelectFailure; + return Yang_Ok; + } + if (0 >= write_socks[0]) { + //yang_error("srt_write failure, n=%s.", yang_srt_getlasterror_str()); + return Yang_Ok; //ERROR_SRT_WriteSocket; + } +//#endif + //write data + int32_t n = yang_srt_sendmsg(m_sfd, message, len, -1, 0); + if (n == SRT_ERROR) { + yang_error("srt_write failure, n=%d.", n); + + return ERROR_SRT_PushFailure; + + } + // m_sync_clock.wait(tm_ms); + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangsrt/YangTsBuffer.cpp b/libyangrtc2/src/yangsrt/YangTsBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..346ccece19220dba89e151c7742f329d4e9d8ebe --- /dev/null +++ b/libyangrtc2/src/yangsrt/YangTsBuffer.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include +YangTsBuffer::YangTsBuffer() + : _pos(0) +{ + curPos=0; +} + +YangTsBuffer::YangTsBuffer(int32_t size, char value) + : _pos(0) +{ + curPos=0; +} + +YangTsBuffer::~YangTsBuffer() +{ +} + +void YangTsBuffer::write_1byte(char val) +{ + _data[curPos++]=val; +} + +void YangTsBuffer::write_2bytes(int16_t val) +{ + char *p = (char *)&val; + + for (int32_t i = 1; i >= 0; --i) { + _data[curPos++]=p[i]; + + } +} + +void YangTsBuffer::write_3bytes(int32_t val) +{ + char *p = (char *)&val; + + for (int32_t i = 2; i >= 0; --i) { + _data[curPos++]=p[i]; + + } +} + +void YangTsBuffer::write_4bytes(int32_t val) +{ + char *p = (char *)&val; + + for (int32_t i = 3; i >= 0; --i) { + _data[curPos++]=p[i]; + } +} + +void YangTsBuffer::write_8bytes(int64_t val) +{ + char *p = (char *)&val; + + for (int32_t i = 7; i >= 0; --i) { + _data[curPos++]=p[i]; + } +} +void YangTsBuffer::writeBytes(uint8_t* bytes,int32_t size){ + memcpy(_data+curPos,bytes,size); + curPos+=size; +} + + +void YangTsBuffer::append( uint8_t* bytes, int32_t size) +{ + if (!bytes || size <= 0) + return; + memcpy(_data+curPos,bytes,size); + curPos+=size; +} + +char YangTsBuffer::read_1byte() +{ + assert(require(1)); + + char val = _data[_pos]; + _pos++; + + return val; +} + +int16_t YangTsBuffer::read_2bytes() +{ + assert(require(2)); + + int16_t val = 0; + char *p = (char *)&val; + + for (int32_t i = 1; i >= 0; --i) { + p[i] = _data[_pos]; + _pos++; + } + + return val; +} + +int32_t YangTsBuffer::read_3bytes() +{ + assert(require(3)); + + int32_t val = 0; + char *p = (char *)&val; + + for (int32_t i = 2; i >= 0; --i) { + p[i] = _data[_pos];//_data.at(0 + _pos); + _pos++; + } + + return val; +} + +int32_t YangTsBuffer::read_4bytes() +{ + assert(require(4)); + + int32_t val = 0; + char *p = (char *)&val; + + for (int32_t i = 3; i >= 0; --i) { + p[i] = _data[_pos]; + _pos++; + } + + return val; +} + +int64_t YangTsBuffer::read_8bytes() +{ + assert(require(8)); + + int64_t val = 0; + char *p = (char *)&val; + + for (int32_t i = 7; i >= 0; --i) { + p[i] = _data[_pos]; + _pos++; + } + + return val; +} +void YangTsBuffer::readBytes(uint8_t *p,int32_t len){ + memcpy(p,_data+_pos,len); + _pos += len; +} +std::string YangTsBuffer::read_string(int32_t len) +{ + assert(require(len)); + + std::string val((char*)_data + _pos, len); + _pos += len; + + return val; +} + +void YangTsBuffer::skip(int32_t size) +{ + _pos += size; +} + +bool YangTsBuffer::require(int32_t required_size) +{ + assert(required_size >= 0); + + return required_size <= curPos-_pos; +} + +bool YangTsBuffer::empty() +{ + return _pos >= curPos; +} + +int32_t YangTsBuffer::size() +{ + return curPos; +} + +int32_t YangTsBuffer::pos() +{ + return _pos; +} + +uint8_t *YangTsBuffer::data() +{ + return (size() == 0) ? nullptr : _data; +} + +void YangTsBuffer::clear() +{ + _pos = 0; + curPos=0; + +} + +void YangTsBuffer::set_data(int32_t pos, const uint8_t *data, int32_t len) +{ + if (!data) + return; + + if (pos + len > size()) { + return; + } + + for (int32_t i = 0; i < len; i++) { + _data[pos + i] = data[i]; + } +} + +std::string YangTsBuffer::to_string() +{ + return std::string(_data, _data+curPos); +} diff --git a/libyangrtc2/src/yangsrt/YangTsMuxer.cpp b/libyangrtc2/src/yangsrt/YangTsMuxer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c05753d7b3796637afa25cac68a4333f02a888dc --- /dev/null +++ b/libyangrtc2/src/yangsrt/YangTsMuxer.cpp @@ -0,0 +1,428 @@ +/* + * YangTsMux.cpp + * + * Created on: 2020年8月7日 + * Author: yang + */ + +#include +#include +#include + +#include +#include +static const uint16_t MPEGTS_NULL_PACKET_PID = 0x1FFF; +static const uint16_t MPEGTS_PAT_PID = 0x00; +static const uint16_t MPEGTS_PMT_PID = 0x100; +static const uint16_t MPEGTS_PCR_PID = 0x110; + + +YangTsMuxer::YangTsMuxer() { + m_pmt_pid = MPEGTS_PMT_PID; + m_stream_pid_map[STREAM_TYPE_VIDEO_H264]=Yang_H264_PID; + m_stream_pid_map[STREAM_TYPE_VIDEO_HEVC]=Yang_H265_PID; + m_stream_pid_map[STREAM_TYPE_AUDIO_AAC]=Yang_AAC_PID; + m_stream_pid_map[STREAM_TYPE_AUDIO_OPUS]=Yang_OPUS_PID; + m_stream_pid_map[STREAM_TYPE_PRIVATE_DATA]=Yang_PRIVATE_PID; + + + /**m_stream_pid_map.insert( + pair(STREAM_TYPE_VIDEO_H264, Yang_H264_PID)); + m_stream_pid_map.insert( + pair(STREAM_TYPE_VIDEO_HEVC, Yang_H265_PID)); + m_stream_pid_map.insert( + pair(STREAM_TYPE_AUDIO_AAC, Yang_AAC_PID)); + m_stream_pid_map.insert( + pair(STREAM_TYPE_AUDIO_OPUS, Yang_OPUS_PID)); + m_stream_pid_map.insert( + pair(STREAM_TYPE_PRIVATE_DATA, Yang_PRIVATE_PID));**/ + current_index = 0; + +} + +YangTsMuxer::~YangTsMuxer() { + +} + +void YangTsMuxer::create_pat(YangTsBuffer *sb, uint16_t pmt_pid, uint8_t cc) { + YangTsBuffer pat_sb; + TsHeader ts_header; + ts_header.sync_byte = 0x47; + ts_header.transport_error_indicator = 0; + ts_header.payload_unit_start_indicator = 1; + ts_header.transport_priority = 0; + ts_header.pid = MPEGTS_PAT_PID; + ts_header.transport_scrambling_control = 0; + ts_header.adaptation_field_control = + MpegTsAdaptationFieldType::payload_only; + ts_header.continuity_counter = cc; + + AdaptationFieldHeader adapt_field; + + PATHeader pat_header; + pat_header.table_id = 0x00; + pat_header.section_syntax_indicator = 1; + pat_header.b0 = 0; + pat_header.reserved0 = 0x3; + pat_header.transport_stream_id = 0; + pat_header.reserved1 = 0x3; + pat_header.version_number = 0; + pat_header.current_next_indicator = 1; + pat_header.section_number = 0x0; + pat_header.last_section_number = 0x0; + + //program_number + uint16_t program_number = 0x0001; + //program_map_PID + uint16_t program_map_PID = 0xe000 | (pmt_pid & 0x1fff); + + uint32_t section_length = 4 + 4 + 5; + pat_header.section_length = section_length & 0x3ff; + + ts_header.encode(&pat_sb); + adapt_field.encode(&pat_sb); + pat_header.encode(&pat_sb); + pat_sb.write_2bytes(program_number); + pat_sb.write_2bytes(program_map_PID); + + // crc32 + uint32_t crc_32 = crc32((uint8_t*) pat_sb.data() + 5, pat_sb.size() - 5); + pat_sb.write_4bytes(crc_32); + + int32_t suffLen = 188 - pat_sb.size(); + //uint8_t stuff[suffLen]; + uint8_t* stuff=new uint8_t[suffLen]; + YangAutoFreeA(uint8_t,stuff); + memset(stuff, 0xff, suffLen); + pat_sb.writeBytes(stuff, 188 - suffLen); + // memcpy() + //std::string stuff(188 - pat_sb.size(), 0xff); + //pat_sb.write_string(stuff); + + sb->append(pat_sb.data(), pat_sb.size()); +} + +void YangTsMuxer::create_pmt(YangTsBuffer *sb, uint8_t cc) { + YangTsBuffer pmt_sb; + TsHeader ts_header; + ts_header.sync_byte = 0x47; + ts_header.transport_error_indicator = 0; + ts_header.payload_unit_start_indicator = 1; + ts_header.transport_priority = 0; + ts_header.pid = m_pmt_pid; + ts_header.transport_scrambling_control = 0; + ts_header.adaptation_field_control = + MpegTsAdaptationFieldType::payload_only; + ts_header.continuity_counter = cc; + + AdaptationFieldHeader adapt_field; + + PMTHeader pmt_header; + pmt_header.table_id = 0x02; + pmt_header.section_syntax_indicator = 1; + pmt_header.b0 = 0; + pmt_header.reserved0 = 0x3; + pmt_header.section_length = 0; + pmt_header.program_number = 0x0001; + pmt_header.reserved1 = 0x3; + pmt_header.version_number = 0; + pmt_header.current_next_indicator = 1; + pmt_header.section_number = 0x00; + pmt_header.last_section_number = 0x00; + pmt_header.reserved2 = 0x7; + pmt_header.reserved3 = 0xf; + pmt_header.program_info_length = 0; + for (auto it = m_stream_pid_map.begin(); it != m_stream_pid_map.end(); + it++) { + pmt_header.infos.push_back( + std::shared_ptr( + new PMTElementInfo(it->first, it->second))); + if (it->first == MpegTsStream::AVC) { + pmt_header.PCR_PID = it->second; + } + } + + uint16_t section_length = pmt_header.size() - 3 + 4; + pmt_header.section_length = section_length & 0x3ff; + + ts_header.encode(&pmt_sb); + adapt_field.encode(&pmt_sb); + pmt_header.encode(&pmt_sb); + + // crc32 + uint32_t crc_32 = crc32((uint8_t*) pmt_sb.data() + 5, pmt_sb.size() - 5); + pmt_sb.write_4bytes(crc_32); + + int32_t suffLen = 188 - pmt_sb.size(); + //uint8_t stuff[suffLen]; + uint8_t* stuff=new uint8_t[suffLen]; + YangAutoFreeA(uint8_t,stuff); + memset(stuff, 0xff, suffLen); + pmt_sb.writeBytes(stuff, 188 - suffLen); + // std::string stuff(188 - pmt_sb.size(), 0xff); + // pmt_sb.write_string(stuff); + + sb->append(pmt_sb.data(), pmt_sb.size()); +} +void YangTsMuxer::create_pes(YangTsPes *frame, uint8_t *p, int32_t plen, + int32_t frametype, int64_t timestamp, YangTsStream pstreamType) { + YangTsBuffer packet; + PESHeader pes_header; + uint8_t streamType = STREAM_TYPE_VIDEO_H264; + if (pstreamType == TS_H264) { + streamType = PES_VIDEO_ID; //STREAM_TYPE_VIDEO_H264; + frame->pid = Yang_H264_PID; + frame->dts = timestamp; + frame->pts = frame->dts; + } + if (pstreamType == TS_H265) { + streamType = PES_VIDEO_ID; //STREAM_TYPE_VIDEO_H265; + frame->pid = Yang_H265_PID; + frame->dts = timestamp; + frame->pts = timestamp; + } + if (pstreamType == TS_AAC) { + streamType = PES_AUDIO_ID; //STREAM_TYPE_AUDIO_AAC; + frame->pid = Yang_AAC_PID; + frame->pts = frame->dts = timestamp; + } + if (pstreamType == TS_OPUS) { + streamType = PES_AUDIO_ID; //STREAM_TYPE_AUDIO_OPUS; + frame->pid = Yang_OPUS_PID; + frame->pts = frame->dts = timestamp; + } + if (pstreamType == TS_PRIVATE) { + streamType = STREAM_TYPE_PRIVATE_DATA; //STREAM_TYPE_AUDIO_OPUS; + frame->pid = Yang_PRIVATE_PID; + + } + + frame->stream_type = streamType; + + pes_header.packet_start_code = 0x000001; + pes_header.stream_id = frame->stream_type; + pes_header.marker_bits = 0x02; + pes_header.original_or_copy = 0x01; + + if (frame->pts != frame->dts) { + pes_header.pts_dts_flags = 0x03; + pes_header.header_data_length = 0x0A; + } else { + pes_header.pts_dts_flags = 0x2; + pes_header.header_data_length = 0x05; + } + + uint32_t pes_size = (pes_header.header_data_length + frame->len + 3); + //printf("\n*****************pes=====%d,",pes_size); + pes_header.pes_packet_length = pes_size > 0xffff ? 0 : pes_size; + pes_header.encode(&packet); + + if (pes_header.pts_dts_flags == 0x03) { + write_pts(&packet, 3, frame->pts); + write_pts(&packet, 1, frame->dts); + } else { + write_pts(&packet, 2, frame->pts); + } + memcpy(frame->data, packet.data(), packet.size()); + memcpy(frame->data + packet.size(), p, plen); + frame->len = plen + packet.size(); +} +void YangTsMuxer::create_ts(YangTsPes *frame, vector *sb) { + bool first = true; + // while (!frame->_data->empty()) { + while (frame->pos < frame->len) { + YangTsBuffer packet; + + TsHeader ts_header; + ts_header.pid = frame->pid; + ts_header.adaptation_field_control = + MpegTsAdaptationFieldType::payload_only; + ts_header.continuity_counter = get_cc(frame->stream_type); + + if (first) { + ts_header.payload_unit_start_indicator = 0x01; + if (frame->stream_type == STREAM_TYPE_VIDEO_H264 + || frame->stream_type == STREAM_TYPE_VIDEO_HEVC) { + ts_header.adaptation_field_control |= 0x02; + AdaptationFieldHeader adapt_field_header; + adapt_field_header.adaptation_field_length = 0x07; + adapt_field_header.random_access_indicator = 0x01; + adapt_field_header.pcr_flag = 0x01; + + ts_header.encode(&packet); + adapt_field_header.encode(&packet); + write_pcr(&packet, frame->dts); + } else { + ts_header.encode(&packet); + } + //pes handle + + first = false; + } else { + ts_header.encode(&packet); + } + // printf("\n********tsheader===%d\n",packet.size()); + uint32_t pos = packet.size(); + uint32_t body_size = 188 - pos; + uint8_t* bodys=new uint8_t[body_size]; + YangAutoFreeA(uint8_t,bodys); + memset(bodys,0,body_size); + packet.writeBytes(bodys, body_size); + // packet.write_string(std::string(body_size, 0)); + packet.skip(pos); + uint32_t in_size = frame->len - frame->pos; + if (body_size <= in_size) { // MpegTsAdaptationFieldType::payload_only or MpegTsAdaptationFieldType::payload_adaption_both for AVC +// packet.write_string(frame->_data->read_string(body_size)); + // std::string body_string = frame->_data->read_string(body_size); + packet.set_data(pos, frame->data + frame->pos, body_size); + frame->pos += body_size; + } else { + uint16_t stuff_size = body_size - in_size; + if (ts_header.adaptation_field_control + == MpegTsAdaptationFieldType::adaption_only + || ts_header.adaptation_field_control + == MpegTsAdaptationFieldType::payload_adaption_both) { + uint8_t *base = packet.data() + 5 + packet.data()[4]; + packet.set_data(base - packet.data() + stuff_size, base, + packet.data() + packet.pos() - base); + memset(base, 0xff, stuff_size); + packet.skip(stuff_size); + packet.data()[4] += stuff_size; + } else { + // adaptation_field_control |= 0x20 == MpegTsAdaptationFieldType::payload_adaption_both + packet.data()[3] |= 0x20; + packet.set_data(188 - 4 - stuff_size, packet.data() + 4, + packet.pos() - 4); + packet.skip(stuff_size); + packet.data()[4] = stuff_size - 1; + if (stuff_size >= 2) { + packet.data()[5] = 0; + memset(&(packet.data()[6]), 0xff, stuff_size - 2); + } + } +// packet.write_string(frame->_data->read_string(in_size)); + // std::string body_string = frame->_data->read_string(in_size); + //packet.set_data(packet.pos(), body_string.c_str(), body_string.length()); + packet.set_data(packet.pos(), frame->data + frame->pos, in_size); + frame->pos += in_size; + } + sb->push_back(packet); + // sb->append(packet.data(), packet.size()); + } +} + +void YangTsMuxer::create_pcr(YangTsBuffer *sb) { + uint64_t pcr = 0; + TsHeader ts_header; + ts_header.sync_byte = 0x47; + ts_header.transport_error_indicator = 0; + ts_header.payload_unit_start_indicator = 0; + ts_header.transport_priority = 0; + ts_header.pid = MPEGTS_PCR_PID; + ts_header.transport_scrambling_control = 0; + ts_header.adaptation_field_control = + MpegTsAdaptationFieldType::adaption_only; + ts_header.continuity_counter = 0; + + AdaptationFieldHeader adapt_field; + adapt_field.adaptation_field_length = 188 - 4 - 1; + adapt_field.discontinuity_indicator = 0; + adapt_field.random_access_indicator = 0; + adapt_field.elementary_stream_priority_indicator = 0; + adapt_field.pcr_flag = 1; + adapt_field.opcr_flag = 0; + adapt_field.splicing_point_flag = 0; + adapt_field.transport_private_data_flag = 0; + adapt_field.adaptation_field_extension_flag = 0; + + // char *p = sb->data(); + ts_header.encode(sb); + adapt_field.encode(sb); + write_pcr(sb, pcr); +} + +void YangTsMuxer::create_null(YangTsBuffer *sb) { + TsHeader ts_header; + ts_header.sync_byte = 0x47; + ts_header.transport_error_indicator = 0; + ts_header.payload_unit_start_indicator = 0; + ts_header.transport_priority = 0; + ts_header.pid = MPEGTS_NULL_PACKET_PID; + ts_header.transport_scrambling_control = 0; + ts_header.adaptation_field_control = + MpegTsAdaptationFieldType::payload_only; + ts_header.continuity_counter = 0; + ts_header.encode(sb); +} + +void YangTsMuxer::encode(uint8_t *p, int32_t plen, int32_t frametype, + int64_t timestamp, YangTsStream streamType, + vector *sb) { + if (should_create_pat()) { + encodePmtWithoutData(sb); + } + YangTsPes *frame = (YangTsPes*) malloc(sizeof(YangTsPes)); + memset(frame, 0, sizeof(YangTsPes)); + frame->data = (uint8_t*) malloc(plen + 20); + frame->len = plen; + create_pes(frame, p, plen, frametype, timestamp, streamType); + create_ts(frame, sb); + free(frame->data); + frame->data = nullptr; + free(frame); + frame = nullptr; +} +void YangTsMuxer::encodeWithPmt(uint8_t *p, int32_t plen, int32_t frametype, + int64_t timestamp, YangTsStream streamType, + vector *sb) { + encodePmtWithoutData(sb); + + YangTsPes *frame = (YangTsPes*) malloc(sizeof(YangTsPes)); + memset(frame, 0, sizeof(YangTsPes)); + frame->data = (uint8_t*) malloc(plen + 20); + frame->len = plen; + create_pes(frame, p, plen, frametype, timestamp, streamType); + create_ts(frame, sb); + free(frame->data); + frame->data = nullptr; + free(frame); + frame = nullptr; +} +//YangTsMuxer::current_index=0; +//void YangTsMuxer::encodePmt(vector *sb) { +// if (should_create_pat()) { +// encodePmtWithoutData(sb); +// } +//} +uint8_t YangTsMuxer::get_cc(uint32_t with_pid) { + if (_pid_cc_map.find(with_pid) != _pid_cc_map.end()) { + _pid_cc_map[with_pid] = (_pid_cc_map[with_pid] + 1) & 0x0F; + return _pid_cc_map[with_pid]; + } + + _pid_cc_map[with_pid] = 0; + return 0; +} +void YangTsMuxer::encodePmtWithoutData(vector *sb){ + current_index=0; + sb->push_back(YangTsBuffer()); + uint8_t pat_pmt_cc = get_cc(0); + create_pat(&sb->at(0), m_pmt_pid, pat_pmt_cc); + sb->push_back(YangTsBuffer()); + create_pmt(&sb->at(1), pat_pmt_cc); +} +bool YangTsMuxer::should_create_pat() { + bool ret = false; + + if (current_index % pat_interval == 0) { + if (current_index > 0) { + current_index = 0; + } + ret = true; + } + + current_index++; + + return ret; +} + diff --git a/libyangrtc2/src/yangsrt/YangTsPacket.cpp b/libyangrtc2/src/yangsrt/YangTsPacket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87ea70a492712327f21ea089bcefe46fed2d76f2 --- /dev/null +++ b/libyangrtc2/src/yangsrt/YangTsPacket.cpp @@ -0,0 +1,506 @@ +#include +#include +#include + +TsFrame::TsFrame(){ + _data.reset(new YangTsBuffer); + pts=dts=pcr=0; + stream_type=stream_id=0; + completed=false; + pid=0; + expected_pes_packet_length=0; + + +} + +TsFrame::TsFrame(uint8_t st){ + stream_type=st; + pts=dts=pcr=0; + stream_id=0; + completed=false; + pid=0; + expected_pes_packet_length=0; + _data.reset(new YangTsBuffer); +} + +bool TsFrame::empty() +{ + return _data->size() == 0; +} + +void TsFrame::reset() +{ + pid = 0; + completed = false; + expected_pes_packet_length = 0; + _data.reset(new YangTsBuffer); +} + +TsHeader::TsHeader() + : sync_byte(0x47) + , transport_error_indicator(0) + , payload_unit_start_indicator(0) + , transport_priority(0) + , pid(0) + , transport_scrambling_control(0) + , adaptation_field_control(0) + , continuity_counter(0) +{ +} + +TsHeader::~TsHeader() +{ +} + +void TsHeader::encode(YangTsBuffer *sb) +{ + sb->write_1byte(sync_byte); + + uint16_t b1b2 = pid & 0x1FFF; + b1b2 |= (transport_priority << 13) & 0x2000; + b1b2 |= (payload_unit_start_indicator << 14) & 0x4000; + b1b2 |= (transport_error_indicator << 15) & 0x8000; + sb->write_2bytes(b1b2); + + uint8_t b3 = continuity_counter & 0x0F; + b3 |= (adaptation_field_control << 4) & 0x30; + b3 |= (transport_scrambling_control << 6) & 0xC0; + sb->write_1byte(b3); +} + +void TsHeader::decode(YangTsBuffer *sb) +{ + sync_byte = sb->read_1byte(); + + uint16_t b1b2 = sb->read_2bytes(); + pid = b1b2 & 0x1FFF; + transport_error_indicator = (b1b2 >> 13) & 0x01; + payload_unit_start_indicator = (b1b2 >> 14) & 0x01; + transport_error_indicator = (b1b2 >> 15) & 0x01; + + uint8_t b3 = sb->read_1byte(); + continuity_counter = b3 & 0x0F; + adaptation_field_control = (b3 >> 4) & 0x03; + transport_scrambling_control = (b3 >> 6) & 0x03; +} + +PATHeader::PATHeader() + : table_id(0) + , section_syntax_indicator(0) + , b0(0) + , reserved0(0) + , section_length(0) + , transport_stream_id(0) + , reserved1(0) + , version_number(0) + , current_next_indicator(0) + , section_number(0) + , last_section_number(0) +{ + +} + +PATHeader::~PATHeader() +{ + +} + +void PATHeader::encode(YangTsBuffer *sb) +{ + sb->write_1byte(table_id); + + uint16_t b1b2 = section_length & 0x0FFF; + b1b2 |= (reserved0 << 12) & 0x3000; + b1b2 |= (b0 << 14) & 0x4000; + b1b2 |= (section_syntax_indicator << 15) & 0x8000; + sb->write_2bytes(b1b2); + + sb->write_2bytes(transport_stream_id); + + uint8_t b5 = current_next_indicator & 0x01; + b5 |= (version_number << 1) & 0x3E; + b5 |= (reserved1 << 6) & 0xC0; + sb->write_1byte(b5); + + sb->write_1byte(section_number); + sb->write_1byte(last_section_number); +} + +void PATHeader::decode(YangTsBuffer *sb) +{ + table_id = sb->read_1byte(); + + uint16_t b1b2 = sb->read_2bytes(); + section_syntax_indicator = (b1b2 >> 15) & 0x01; + b0 = (b1b2 >> 14) & 0x01; + section_length = b1b2 & 0x0FFF; + + transport_stream_id = sb->read_2bytes(); + + uint8_t b5 = sb->read_1byte(); + reserved1 = (b5 >> 6) & 0x03; + version_number = (b5 >> 1) & 0x1F; + current_next_indicator = b5 & 0x01; + + section_number = sb->read_1byte(); + + last_section_number = sb->read_1byte(); +} + +void PATHeader::print() +{ + std::cout << "----------PAT information----------" << std::endl; + std::cout << "table_id: " << std::to_string(table_id) << std::endl; + std::cout << "section_syntax_indicator: " << std::to_string(section_syntax_indicator) << std::endl; + std::cout << "b0: " << std::to_string(b0) << std::endl; + std::cout << "reserved0: " << std::to_string(reserved0) << std::endl; + std::cout << "section_length: " << std::to_string(section_length) << std::endl; + std::cout << "transport_stream_id: " << std::to_string(transport_stream_id) << std::endl; + std::cout << "reserved1: " << std::to_string(reserved1) << std::endl; + std::cout << "version_number: " << std::to_string(version_number) << std::endl; + std::cout << "current_next_indicator: " << std::to_string(current_next_indicator) << std::endl; + std::cout << "section_number: " << std::to_string(section_number) << std::endl; + std::cout << "last_section_number: " << std::to_string(last_section_number) << std::endl; + std::cout << std::endl; + std::flush(std::cout); +} + +PMTElementInfo::PMTElementInfo(uint8_t st, uint16_t pid) + : stream_type(st) + , reserved0(0x7) + , elementary_PID(pid) + , reserved1(0xf) + , ES_info_length(0) +{ + +} + +PMTElementInfo::PMTElementInfo() + : PMTElementInfo(0, 0) +{ + +} + +PMTElementInfo::~PMTElementInfo() +{ + +} + +void PMTElementInfo::encode(YangTsBuffer *sb) +{ + sb->write_1byte(stream_type); + + uint16_t b1b2 = elementary_PID & 0x1FFF; + b1b2 |= (reserved0 << 13) & 0xE000; + sb->write_2bytes(b1b2); + + int16_t b3b4 = ES_info_length & 0x0FFF; + b3b4 |= (reserved1 << 12) & 0xF000; + sb->write_2bytes(b3b4); + + if (ES_info_length > 0) { + // TODO: + } +} + +void PMTElementInfo::decode(YangTsBuffer *sb) +{ + stream_type = sb->read_1byte(); + + uint16_t b1b2 = sb->read_2bytes(); + reserved0 = (b1b2 >> 13) & 0x07; + elementary_PID = b1b2 & 0x1FFF; + + uint16_t b3b4 = sb->read_2bytes(); + reserved1 = (b3b4 >> 12) & 0xF; + ES_info_length = b3b4 & 0xFFF; + + if (ES_info_length > 0) { + ES_info = sb->read_string(ES_info_length); + } +} + +uint16_t PMTElementInfo::size() +{ + return 5 + ES_info_length; +} + +void PMTElementInfo::print() +{ + std::cout << "**********PMTElement information**********" << std::endl; + std::cout << "stream_type: " << std::to_string(stream_type) << std::endl; + std::cout << "reserved0: " << std::to_string(reserved0) << std::endl; + std::cout << "elementary_PID: " << std::to_string(elementary_PID) << std::endl; + std::cout << "reserved1: " << std::to_string(reserved1) << std::endl; + std::cout << "ES_info_length: " << std::to_string(ES_info_length) << std::endl; + std::cout << "ES_info: " << ES_info << std::endl; + std::flush(std::cout); +} + +PMTHeader::PMTHeader() + : table_id(0x02) + , section_syntax_indicator(0) + , b0(0) + , reserved0(0) + , section_length(0) + , program_number(0) + , reserved1(0) + , version_number(0) + , current_next_indicator(0) + , section_number(0) + , last_section_number(0) + , reserved2(0) + , PCR_PID(0) + , reserved3(0) + , program_info_length(0) +{ + +} + +PMTHeader::~PMTHeader() +{ + +} + +void PMTHeader::encode(YangTsBuffer *sb) +{ + sb->write_1byte(table_id); + + uint16_t b1b2 = section_length & 0xFFFF; + b1b2 |= (reserved0 << 12) & 0x3000; + b1b2 |= (b0 << 14) & 0x4000; + b1b2 |= (section_syntax_indicator << 15) & 0x8000; + sb->write_2bytes(b1b2); + + sb->write_2bytes(program_number); + + uint8_t b5 = current_next_indicator & 0x01; + b5 |= (version_number << 1) & 0x3E; + b5 |= (reserved1 << 6) & 0xC0; + sb->write_1byte(b5); + + sb->write_1byte(section_number); + sb->write_1byte(last_section_number); + + uint16_t b8b9 = PCR_PID & 0x1FFF; + b8b9 |= (reserved2 << 13) & 0xE000; + sb->write_2bytes(b8b9); + + uint16_t b10b11 = program_info_length & 0xFFF; + b10b11 |= (reserved3 << 12) & 0xF000; + sb->write_2bytes(b10b11); + + for (int32_t i = 0; i < (int)infos.size(); i++) { + infos[i]->encode(sb); + } +} + +void PMTHeader::decode(YangTsBuffer *sb) +{ + table_id = sb->read_1byte(); + + uint16_t b1b2 = sb->read_2bytes(); + section_syntax_indicator = (b1b2 >> 15) & 0x01; + b0 = (b1b2 >> 14) & 0x01; + reserved0 = (b1b2 >> 12) & 0x03; + section_length = b1b2 & 0xFFF; + + program_number = sb->read_2bytes(); + + uint8_t b5 = sb->read_1byte(); + reserved1 = (b5 >> 6) & 0x03; + version_number = (b5 >> 1) & 0x1F; + current_next_indicator = b5 & 0x01; + + section_number = sb->read_1byte(); + last_section_number = sb->read_1byte(); + + uint16_t b8b9 = sb->read_2bytes(); + reserved2 = (b8b9 >> 13) & 0x07; + PCR_PID = b8b9 & 0x1FFF; + + uint16_t b10b11 = sb->read_2bytes(); + reserved3 = (b10b11 >> 12) & 0xF; + program_info_length = b10b11 & 0xFFF; + + if (program_info_length > 0) { + sb->read_string(program_info_length); + } + + int32_t remain_bytes = section_length - 4 - 9 - program_info_length; + while (remain_bytes > 0) { + std::shared_ptr element_info(new PMTElementInfo); + element_info->decode(sb); + infos.push_back(element_info); + remain_bytes -= element_info->size(); + } +} + +uint16_t PMTHeader::size() +{ + uint16_t ret = 12; + for (int32_t i = 0; i < (int)infos.size(); i++) { + ret += infos[i]->size(); + } + + return ret; +} + +void PMTHeader::print() +{ + std::cout << "----------PMT information----------" << std::endl; + std::cout << "table_id: " << std::to_string(table_id) << std::endl; + std::cout << "section_syntax_indicator: " << std::to_string(section_syntax_indicator) << std::endl; + std::cout << "b0: " << std::to_string(b0) << std::endl; + std::cout << "reserved0: " << std::to_string(reserved0) << std::endl; + std::cout << "section_length: " << std::to_string(section_length) << std::endl; + std::cout << "program_number: " << std::to_string(program_number) << std::endl; + std::cout << "reserved1: " << std::to_string(reserved1) << std::endl; + std::cout << "version_number: " << std::to_string(version_number) << std::endl; + std::cout << "current_next_indicator: " << std::to_string(current_next_indicator) << std::endl; + std::cout << "section_number: " << std::to_string(section_number) << std::endl; + std::cout << "last_section_number: " << std::to_string(last_section_number) << std::endl; + std::cout << "reserved2: " << std::to_string(reserved2) << std::endl; + std::cout << "PCR_PID: " << std::to_string(PCR_PID) << std::endl; + std::cout << "reserved3: " << std::to_string(reserved3) << std::endl; + std::cout << "program_info_length: " << std::to_string(program_info_length) << std::endl; + for (int32_t i = 0; i < (int)infos.size(); i++) { + infos[i]->print(); + } + std::cout << std::endl; + std::flush(std::cout); +} + +AdaptationFieldHeader::AdaptationFieldHeader() + : adaptation_field_length(0) + , adaptation_field_extension_flag(0) + , transport_private_data_flag(0) + , splicing_point_flag(0) + , opcr_flag(0) + , pcr_flag(0) + , elementary_stream_priority_indicator(0) + , random_access_indicator(0) + , discontinuity_indicator(0) +{ + +} + +AdaptationFieldHeader::~AdaptationFieldHeader() +{ + +} + +void AdaptationFieldHeader::encode(YangTsBuffer *sb) +{ + sb->write_1byte(adaptation_field_length); + if (adaptation_field_length != 0) { + uint8_t val = adaptation_field_extension_flag & 0x01; + val |= (transport_private_data_flag << 1) & 0x02; + val |= (splicing_point_flag << 2) & 0x04; + val |= (opcr_flag << 3) & 0x08; + val |= (pcr_flag << 4) & 0x10; + val |= (elementary_stream_priority_indicator << 5) & 0x20; + val |= (random_access_indicator << 6) & 0x40; + val |= (discontinuity_indicator << 7) & 0x80; + sb->write_1byte(val); + } +} + +void AdaptationFieldHeader::decode(YangTsBuffer *sb) +{ + adaptation_field_length = sb->read_1byte(); + if (adaptation_field_length != 0) { + uint8_t val = sb->read_1byte(); + adaptation_field_extension_flag = val & 0x01; + transport_private_data_flag = (val >> 1) & 0x01; + splicing_point_flag = (val >> 2) & 0x01; + opcr_flag = (val >> 3) & 0x01; + pcr_flag = (val >> 4) & 0x01; + elementary_stream_priority_indicator = (val >> 5) & 0x01; + random_access_indicator = (val >> 6) & 0x01; + discontinuity_indicator = (val >> 7) & 0x01; + } +} + +PESHeader::PESHeader() + : packet_start_code(0x000001) + , stream_id(0) + , pes_packet_length(0) + , original_or_copy(0) + , copyright(0) + , data_alignment_indicator(0) + , pes_priority(0) + , pes_scrambling_control(0) + , marker_bits(0x02) + , pes_ext_flag(0) + , pes_crc_flag(0) + , add_copy_info_flag(0) + , dsm_trick_mode_flag(0) + , es_rate_flag(0) + , escr_flag(0) + , pts_dts_flags(0) + , header_data_length(0) +{ + +} + +PESHeader::~PESHeader() +{ + +} + +void PESHeader::encode(YangTsBuffer *sb) +{ + uint32_t b0b1b2b3 = (packet_start_code << 8) & 0xFFFFFF00; + b0b1b2b3 |= stream_id & 0xFF; + sb->write_4bytes(b0b1b2b3); + + sb->write_2bytes(pes_packet_length); + + uint8_t b6 = original_or_copy & 0x01; + b6 |= (copyright << 1) & 0x02; + b6 |= (data_alignment_indicator << 2) & 0x04; + b6 |= (pes_priority << 3) & 0x08; + b6 |= (pes_scrambling_control << 4) & 0x30; + b6 |= (marker_bits << 6) & 0xC0; + sb->write_1byte(b6); + + uint8_t b7 = pes_ext_flag & 0x01; + b7 |= (pes_crc_flag << 1) & 0x02; + b7 |= (add_copy_info_flag << 2) & 0x04; + b7 |= (dsm_trick_mode_flag << 3) & 0x08; + b7 |= (es_rate_flag << 4) & 0x10; + b7 |= (escr_flag << 5) & 0x20; + b7 |= (pts_dts_flags << 6) & 0xC0; + sb->write_1byte(b7); + + sb->write_1byte(header_data_length); +} + +void PESHeader::decode(YangTsBuffer *sb) +{ + uint32_t b0b1b2b3 = sb->read_4bytes(); + packet_start_code = (b0b1b2b3 >> 8) & 0x00FFFFFF; + stream_id = (b0b1b2b3) & 0xFF; + + pes_packet_length = sb->read_2bytes(); + + uint8_t b6 = sb->read_1byte(); + original_or_copy = b6 & 0x01; + copyright = (b6 >> 1) & 0x01; + data_alignment_indicator = (b6 >> 2) & 0x01; + pes_priority = (b6 >> 3) & 0x01; + pes_scrambling_control = (b6 >> 4) & 0x03; + marker_bits = (b6 >> 6) & 0x03; + + uint8_t b7 = sb->read_1byte(); + pes_ext_flag = b7 & 0x01; + pes_crc_flag = (b7 >> 1) & 0x01; + add_copy_info_flag = (b7 >> 2) & 0x01; + dsm_trick_mode_flag = (b7 >> 3) & 0x01; + es_rate_flag = (b7 >> 4) & 0x01; + escr_flag = (b7 >> 5) & 0x01; + pts_dts_flags = (b7 >> 6) & 0x03; + + header_data_length = sb->read_1byte(); +} diff --git a/libyangrtc2/src/yangsrt/YangTsdemux.cpp b/libyangrtc2/src/yangsrt/YangTsdemux.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e470f118933ecd3a318df4e08cf76430f209cfa --- /dev/null +++ b/libyangrtc2/src/yangsrt/YangTsdemux.cpp @@ -0,0 +1,603 @@ +/* + * YangTsdemux.cpp + * + * Created on: 2020年8月15日 + * Author: yang + */ + +#include +#include +#include "memory.h" +using namespace std; + +YangTsdemux::YangTsdemux():_data_total(0) +,_last_pid(0) +,_last_dts(0) +,_last_pts(0) { + + +} + +YangTsdemux::~YangTsdemux() { + +} + +int32_t YangTsdemux::decode_unit(uint8_t* data_p, ts_media_data_callback_I* callback) +{ + int32_t pos = 0; + int32_t npos = 0; + ts_header ts_header_info; + + ts_header_info._sync_byte = data_p[pos]; + pos++; + + ts_header_info._transport_error_indicator = (data_p[pos]&0x80)>>7; + ts_header_info._payload_unit_start_indicator = (data_p[pos]&0x40)>>6; + ts_header_info._transport_priority = (data_p[pos]&0x20)>>5; + ts_header_info._PID = ((data_p[pos]<<8)|data_p[pos+1])&0x1FFF; + pos += 2; + + ts_header_info._transport_scrambling_control = (data_p[pos]&0xC0)>>6; + ts_header_info._adaptation_field_control = (data_p[pos]&0x30)>>4; + ts_header_info._continuity_counter = (data_p[pos]&0x0F); + pos++; + npos = pos; + + adaptation_field* field_p = &(ts_header_info._adaptation_field_info); + //printf("%02x-%hd,",ts_header_info._adaptation_field_control,ts_header_info._PID); + // adaptation field + // 0x01 No adaptation_field, payload only + // 0x02 Adaptation_field only, no payload + // 0x03 Adaptation_field followed by payload + if( ts_header_info._adaptation_field_control == 2 + || ts_header_info._adaptation_field_control == 3 ){ + // adaptation_field() + field_p->_adaptation_field_length = data_p[pos]; + pos++; + + if( field_p->_adaptation_field_length > 0 ){ + field_p->_discontinuity_indicator = (data_p[pos]&0x80)>>7; + field_p->_random_access_indicator = (data_p[pos]&0x40)>>6; + field_p->_elementary_stream_priority_indicator = (data_p[pos]&0x20)>>5; + field_p->_PCR_flag = (data_p[pos]&0x10)>>4; + field_p->_OPCR_flag = (data_p[pos]&0x08)>>3; + field_p->_splicing_point_flag = (data_p[pos]&0x04)>>2; + field_p->_transport_private_data_flag = (data_p[pos]&0x02)>>1; + field_p->_adaptation_field_extension_flag = (data_p[pos]&0x01); + pos++; + + if( field_p->_PCR_flag == 1 ) { // PCR info + //program_clock_reference_base 33 uimsbf + //reserved 6 bslbf + //program_clock_reference_extension 9 uimsbf + pos += 6; + } + if( field_p->_OPCR_flag == 1 ) { + //original_program_clock_reference_base 33 uimsbf + //reserved 6 bslbf + //original_program_clock_reference_extension 9 uimsbf + pos += 6; + } + if( field_p->_splicing_point_flag == 1 ) { + //splice_countdown 8 tcimsbf + pos++; + } + if( field_p->_transport_private_data_flag == 1 ) { + //transport_private_data_length 8 uimsbf + field_p->_transport_private_data_length = data_p[pos]; + pos++; + memcpy(field_p->_private_data_byte, data_p + pos, field_p->_transport_private_data_length); + } + if( field_p->_adaptation_field_extension_flag == 1 ) { + //adaptation_field_extension_length 8 uimsbf + field_p->_adaptation_field_extension_length = data_p[pos]; + pos++; + //ltw_flag 1 bslbf + field_p->_ltw_flag = (data_p[pos]&0x80)>>7; + //piecewise_rate_flag 1 bslbf + field_p->_piecewise_rate_flag = (data_p[pos]&0x40)>>6; + //seamless_splice_flag 1 bslbf + field_p->_seamless_splice_flag = (data_p[pos]&0x20)>>5; + //reserved 5 bslbf + pos++; + if (field_p->_ltw_flag == 1) { + //ltw_valid_flag 1 bslbf + //ltw_offset 15 uimsbf + pos += 2; + } + if (field_p->_piecewise_rate_flag == 1) { + //reserved 2 bslbf + //piecewise_rate 22 uimsbf + pos += 3; + } + if (field_p->_seamless_splice_flag == 1) { + //splice_type 4 bslbf + //DTS_next_AU[32..30] 3 bslbf + //marker_bit 1 bslbf + //DTS_next_AU[29..15] 15 bslbf + //marker_bit 1 bslbf + //DTS_next_AU[14..0] 15 bslbf + //marker_bit 1 bslbf + pos += 5; + } + } + } + npos += sizeof(field_p->_adaptation_field_length) + field_p->_adaptation_field_length; + } + + if(ts_header_info._adaptation_field_control == 1 + || ts_header_info._adaptation_field_control == 3 ) { + // data_byte with placeholder + // payload parser + if(ts_header_info._PID == 0x00){ + // PAT // program association table + if(ts_header_info._payload_unit_start_indicator) { + pos++; + } + _pat._table_id = data_p[pos]; + pos++; + _pat._section_syntax_indicator = (data_p[pos]>>7)&0x01; + // skip 3 bits of 1 zero and 2 reserved + _pat._section_length = ((data_p[pos]<<8)|data_p[pos+1])&0x0FFF; + pos += 2; + _pat._transport_stream_id = (data_p[pos]<<8)|data_p[pos+1]; + pos += 2; + // reserved 2 bits + _pat._version_number = (data_p[pos]&0x3E)>>1; + _pat._current_next_indicator = data_p[pos]&0x01; + pos++; + _pat._section_number = data_p[pos]; + pos++; + _pat._last_section_number = data_p[pos]; + // assert(_pat._table_id == 0x00); + // assert((188 - npos) > (_pat._section_length+3)); // PAT = section_length + 3 + pos++; + _pat._pid_vec.clear(); + for (;pos+4 <= _pat._section_length-5-4+9 + npos;) { // 4:CRC, 5:follow section_length item rpos + 4(following unit length) section_length + 9(above field and unit_start_first_byte ) + PID_INFO pid_info; + //program_number 16 uimsbf + pid_info._program_number = data_p[pos]<<8|data_p[pos+1]; + pos += 2; +// reserved 3 bslbf + + if (pid_info._program_number == 0) { +// // network_PID 13 uimsbf + pid_info._network_id = (data_p[pos]<<8|data_p[pos+1])&0x1FFF; + //printf("#### network id:%d.\r\n", pid_info._network_id); + pos += 2; + } + else { +// // program_map_PID 13 uimsbf + pid_info._pid = (data_p[pos]<<8|data_p[pos+1])&0x1FFF; + //printf("#### pmt id:%d.\r\n", pid_info._pid); + pos += 2; + } + _pat._pid_vec.push_back(pid_info); + // network_PID and program_map_PID save to list + } +// CRC_32 use pat to calc crc32, eq + pos += 4; + }else if(ts_header_info._PID == 0x01){ + // CAT // conditional access table + }else if(ts_header_info._PID == 0x02){ + //TSDT // transport stream description table + }else if(ts_header_info._PID == 0x03){ + //IPMP // IPMP control information table + // 0x0004-0x000F Reserved + // 0x0010-0x1FFE May be assigned as network_PID, Program_map_PID, elementary_PID, or for other purposes + }else if(ts_header_info._PID == 0x11){ + // SDT // https://en.wikipedia.org/wiki/Service_Description_Table / https://en.wikipedia.org/wiki/MPEG_transport_stream + }else if(is_pmt(ts_header_info._PID)) { + if(ts_header_info._payload_unit_start_indicator) + pos++; + _pmt._table_id = data_p[pos]; + pos++; + _pmt._section_syntax_indicator = (data_p[pos]>>7)&0x01; + // skip 3 bits of 1 zero and 2 reserved + _pmt._section_length = ((data_p[pos]<<8)|data_p[pos+1])&0x0FFF; + pos += 2; + _pmt._program_number = (data_p[pos]<<8)|data_p[pos+1]; + pos += 2; + // reserved 2 bits + _pmt._version_number = (data_p[pos]&0x3E)>>1; + _pmt._current_next_indicator = data_p[pos]&0x01; + pos++; + _pmt._section_number = data_p[pos]; + pos++; + _pmt._last_section_number = data_p[pos]; + pos++; + // skip 3 bits for reserved 3 bslbf + _pmt._PCR_PID = ((data_p[pos]<<8)|data_p[pos+1])&0x1FFF; //PCR_PID 13 uimsbf + pos += 2; + + //reserved 4 bslbf + _pmt._program_info_length = ((data_p[pos]<<8)|data_p[pos+1])&0x0FFF;//program_info_length 12 uimsbf + pos += 2; + // assert(_pmt._table_id==0x02); // 0x02, // TS_program_map_section + memcpy(_pmt._dscr, data_p+pos, _pmt._program_info_length); +// for (i = 0; i < N; i++) { +// descriptor() +// } + pos += _pmt._program_info_length; + _pmt._stream_pid_vec.clear(); + _pmt._pid2steamtype.clear(); + + for (; pos + 5 <= _pmt._section_length + 4 - 4 + npos; ) { // pos(above field length) i+5(following unit length) section_length +3(PMT begin three bytes)+1(payload_unit_start_indicator) -4(crc32) + STREAM_PID_INFO pid_info; + pid_info._stream_type = data_p[pos];//stream_type 8 uimsbf 0x1B AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video + pos++; + //reserved 3 bslbf + pid_info._elementary_PID = ((data_p[pos]<<8)|data_p[pos+1])&0x1FFF; //elementary_PID 13 uimsbf + pos += 2; + //reserved 4 bslbf + pid_info._ES_info_length = ((data_p[pos]<<8)|data_p[pos+1])&0x0FFF; //ES_info_length 12 uimsbf + pos += 2; + if( pos + pid_info._ES_info_length > _pmt._section_length + 4 - 4 + npos ) + break; + int32_t absES_info_length = pos + pid_info._ES_info_length; + for (; pos< absES_info_length; ) { + //descriptor() + int32_t descriptor_tag = data_p[pos]; + (void)descriptor_tag; + pos++; + int32_t descriptor_length = data_p[pos]; + pos++; + memcpy(pid_info._dscr, data_p + pos, descriptor_length); + pos += descriptor_length; + } + // save program_number(stream num) elementary_PID(PES PID) stream_type(stream codec) + //printf("pmt pid:%d, streamtype:%d, pos:%d\r\n", pid_info._elementary_PID, pid_info._stream_type, pos); + _pmt._stream_pid_vec.push_back(pid_info); + _pmt._pid2steamtype.insert(std::make_pair((unsigned short)pid_info._elementary_PID, pid_info._stream_type)); + } + pos += 4;//CRC_32 + }else if(ts_header_info._PID == 0x0042){ + // USER + }else if(ts_header_info._PID == 0x1FFF){ + // Null packet + }else{//pes packet or pure data packet + //bool isFound = false; + //printf("%d,",_pmt._stream_pid_vec.size()); + for (size_t i = 0; i < _pmt._stream_pid_vec.size(); i++) { + if(ts_header_info._PID == _pmt._stream_pid_vec[i]._elementary_PID){ + //if(ts_header_info._PID == 225||ts_header_info._PID == 192){ + //isFound = true; + if(ts_header_info._payload_unit_start_indicator){ + uint8_t* ret_data_p = nullptr; + size_t ret_size = 0; + uint64_t dts = 0; + uint64_t pts = 0; + + //callback last media data in data buffer + on_callback(callback, _last_pid, _last_dts, _last_pts); + int32_t peslen=0; + int32_t ret = pes_parse(data_p+npos, npos, &ret_data_p, ret_size, dts, pts,&peslen); + // assert(ret <= 188); + if (ret > 188) { + return -1; + } + + _last_pts = pts; + _last_dts = (dts == 0) ? pts : dts; + if ((ret_data_p != nullptr) && (ret_size > 0)) { + insert_into_databuf(ret_data_p, ret_size, ts_header_info._PID); + if((peslen+npos)<=188) on_callback(callback, _last_pid, _last_dts, _last_pts); + + } + }else{ + insert_into_databuf(data_p + npos, 188-npos,ts_header_info._PID); + } + } + } + + } + } + + return 0; +} +int32_t YangTsdemux::decode(SRT_DATA_MSG_PTR data_ptr, ts_media_data_callback_I* callback) +{ + int32_t ret = -1; + std::string path; + + if (!data_ptr || (data_ptr->data_len() < 188) || (data_ptr->data_len()%188 != 0)) + { + return -1; + } + + uint32_t count = data_ptr->data_len()/188; + for (uint32_t index = 0; index < count; index++) + { + uint8_t* data = data_ptr->get_data() + 188*index; + if (data[0] != 0x47) { + continue; + } + ret = decode_unit(data, callback); + if (ret < 0) + { + break; + } + } + return ret; +} + +void YangTsdemux::insert_into_databuf(uint8_t* data_p, size_t data_size, unsigned short pid) { + _last_pid = pid; + _data_total += data_size; + int32_t key=pid; + _data_buffer_map.find(key); + std::map>::iterator iter1=_data_buffer_map.find(key); + if(iter1 ==_data_buffer_map.end()){ + _data_buffer_map.insert(pair>(key,vector())); + std::map>::iterator iter=_data_buffer_map.find(key); + iter->second.push_back(std::make_shared(data_p, data_size)); + }else{ + iter1->second.push_back(std::make_shared(data_p, data_size)); + } + +} + +void YangTsdemux::on_callback(ts_media_data_callback_I* callback, unsigned short pid, + uint64_t dts, uint64_t pts) { + + int32_t stream_type = pid;//0xe1;//iter->second; + std::map>::iterator iter=_data_buffer_map.find(stream_type); + vector* _data_buffer_vec=NULL; + if(iter ==_data_buffer_map.end()){ + _data_buffer_map.insert(pair>(stream_type,vector())); + return; + } + _data_buffer_vec=&iter->second; + if(_data_buffer_vec->size()==0){ + _data_buffer_vec=NULL; + return; + } + int32_t dataLen=0; + size_t index =0; + for ( index = 0; index < _data_buffer_vec->size(); index++) { + dataLen+=_data_buffer_vec->at(index)->data_len(); + } + if(dataLen>0){ + auto total_data_ptr = std::make_shared(dataLen); + size_t pos = 0; + for ( index = 0; index < _data_buffer_vec->size(); index++) { + memcpy(total_data_ptr->get_data() + pos, + _data_buffer_vec->at(index)->get_data(), + _data_buffer_vec->at(index)->data_len()); + pos += _data_buffer_vec->at(index)->data_len(); + } + _data_buffer_vec->clear(); + _data_buffer_vec=NULL; + callback->on_data_callback(total_data_ptr, stream_type, dts, pts); + }else{ + _data_buffer_vec->clear(); + _data_buffer_vec=NULL; + } + + return; +} + +bool YangTsdemux::is_pmt(unsigned short pid) { + //printf("%hd,",pid); + for (size_t index = 0; index < _pat._pid_vec.size(); index++) { + if (_pat._pid_vec[index]._program_number != 0) { + if (_pat._pid_vec[index]._pid == pid) { + return true; + } + } + } + return false; +} + + +int32_t YangTsdemux::pes_parse(uint8_t* p, size_t npos, + uint8_t** ret_pp, size_t& ret_size, + uint64_t& dts, uint64_t& pts,int32_t *pesLen) { + int32_t pos = 0; + // int32_t packet_start_code_prefix = (p[pos]<<16)|(p[pos+1]<<8)|p[pos+2]; //packet_start_code_prefix 24 bslbf + pos += 3; + int32_t stream_id = p[pos]; //stream_id 8 uimsbf + pos++; + + int32_t PES_packet_length = ((unsigned int)p[pos]<<8)|p[pos+1]; //PES_packet_length 16 uimsbf + + *pesLen=PES_packet_length; + (void)PES_packet_length; + + pos += 2; + // packet_start_code_prefix, npos, PES_packet_length, stream_id); + // assert(0x00000001 == packet_start_code_prefix); + if (stream_id != 188//program_stream_map 1011 1100 + && stream_id != 190//padding_stream 1011 1110 + && stream_id != 191//private_stream_2 1011 1111 + && stream_id != 240//ECM 1111 0000 + && stream_id != 241//EMM 1111 0001 + && stream_id != 255//program_stream_directory 1111 1111 + && stream_id != 242//DSMCC_stream 1111 0010 + && stream_id != 248//ITU-T Rec. H.222.1 type E stream 1111 1000 + ) + { + // assert(0x80 == p[pos]); + //skip 2bits//'10' 2 bslbf + int32_t PES_scrambling_control = (p[pos]&30)>>4; //PES_scrambling_control 2 bslbf + (void)PES_scrambling_control; + int32_t PES_priority = (p[pos]&0x08)>>3; //PES_priority 1 bslbf + (void)PES_priority; + int32_t data_alignment_indicator = (p[pos]&0x04)>>2;//data_alignment_indicator 1 bslbf + (void)data_alignment_indicator; + int32_t copyright = (p[pos]&0x02)>>1; //copyright 1 bslbf + (void)copyright; + int32_t original_or_copy = (p[pos]&0x01);//original_or_copy 1 bslbf + (void)original_or_copy; + pos++; + int32_t PTS_DTS_flags = (p[pos]&0xC0)>>6; //PTS_DTS_flags 2 bslbf + int32_t ESCR_flag = (p[pos]&0x20)>>5; // ESCR_flag 1 bslbf + int32_t ES_rate_flag = (p[pos]&0x10)>>4;//ES_rate_flag 1 bslbf + int32_t DSM_trick_mode_flag = (p[pos]&0x08)>>3;//DSM_trick_mode_flag 1 bslbf + int32_t additional_copy_info_flag = (p[pos]&0x04)>>2; //additional_copy_info_flag 1 bslbf + int32_t PES_CRC_flag = (p[pos]&0x02)>>1; //PES_CRC_flag 1 bslbf + int32_t PES_extension_flag = (p[pos]&0x01);//PES_extension_flag 1 bslbf + pos++; + int32_t PES_header_data_length = p[pos]; //PES_header_data_length 8 uimsbf + (void)PES_header_data_length; + pos++; + + if (PTS_DTS_flags == 2) { + // skip 4 bits '0010' 4 bslbf + // PTS [32..30] 3 bslbf + // marker_bit 1 bslbf + // PTS [29..15] 15 bslbf + // marker_bit 1 bslbf + // PTS [14..0] 15 bslbf + // marker_bit 1 bslbf + pts = (((p[pos]>>1)&0x07) << 30) | (p[pos+1]<<22) | (((p[pos+2]>>1)&0x7F)<<15) | (p[pos+3]<<7) | ((p[pos+4]>>1)&0x7F); + pos += 5; + } + if (PTS_DTS_flags == 3) { + // '0011' 4 bslbf + // PTS [32..30] 3 bslbf + // marker_bit 1 bslbf + //PTS [29..15] 15 bslbf + //marker_bit 1 bslbf + // PTS [14..0] 15 bslbf + // marker_bit 1 bslbf + pts = (((p[pos]>>1)&0x07) << 30) | (p[pos+1]<<22) | (((p[pos+2]>>1)&0x7F)<<15) | (p[pos+3]<<7) | ((p[pos+4]>>1)&0x7F); + pos += 5; + // '0001' 4 bslbf + // DTS [32..30] 3 bslbf + // marker_bit 1 bslbf + // DTS [29..15] 15 bslbf + // marker_bit 1 bslbf + // DTS [14..0] 15 bslbf + // marker_bit 1 bslbf + dts = (((p[pos]>>1)&0x07) << 30) | (p[pos+1]<<22) | (((p[pos+2]>>1)&0x7F)<<15) | (p[pos+3]<<7) | ((p[pos+4]>>1)&0x7F); + pos += 5; + } + if (ESCR_flag == 1) { + // reserved 2 bslbf + // ESCR_base[32..30] 3 bslbf + // marker_bit 1 bslbf + // ESCR_base[29..15] 15 bslbf + // marker_bit 1 bslbf + // ESCR_base[14..0] 15 bslbf + // marker_bit 1 bslbf + // ESCR_extension 9 uimsbf + // marker_bit 1 bslbf + uint64_t ESCR_base = ((((uint64_t)p[pos] >> 3) & 0x07) << 30) | (((uint64_t)p[pos] & 0x03) << 28) | ((uint64_t)p[pos + 1] << 20) | ((((uint64_t)p[pos + 2] >> 3) & 0x1F) << 15) | (((uint64_t)p[pos + 2] & 0x3) << 13) | ((uint64_t)p[pos + 3] << 5) | ((p[pos + 4] >> 3) & 0x1F); + int32_t ESCR_extension = ((p[pos + 4] & 0x03) << 7) | ((p[pos + 5] >> 1) & 0x7F); + (void)ESCR_base; + (void)ESCR_extension; + pos += 6; + } + if (ES_rate_flag == 1) { + // marker_bit 1 bslbf + // ES_rate 22 uimsbf + // marker_bit 1 bslbf + int32_t ES_rate = (p[pos]&0x7F)<<15 | (p[pos+1])<<7 | (p[pos+2]&0x7F)>>1; + (void)ES_rate; + pos += 3; + } + if (DSM_trick_mode_flag == 1) { // ignore + int32_t trick_mode_control = (p[pos]&0xE0)>>5;//trick_mode_control 3 uimsbf + if ( trick_mode_control == 0/*fast_forward*/ ) { + // field_id 2 bslbf + // intra_slice_refresh 1 bslbf + // frequency_truncation 2 bslbf + } + else if ( trick_mode_control == 1/*slow_motion*/ ) { + //rep_cntrl 5 uimsbf + } + else if ( trick_mode_control == 2/*freeze_frame*/ ) { + // field_id 2 uimsbf + // reserved 3 bslbf + } + else if ( trick_mode_control == 3/*fast_reverse*/ ) { + // field_id 2 bslbf + // intra_slice_refresh 1 bslbf + // frequency_truncation 2 bslbf + }else if ( trick_mode_control == 4/*slow_reverse*/ ) { + // rep_cntrl 5 uimsbf + } + else{ + //reserved 5 bslbf + } + pos++; + } + if ( additional_copy_info_flag == 1) { // ignore + // marker_bit 1 bslbf + // additional_copy_info 7 bslbf + pos++; + } + if ( PES_CRC_flag == 1) { // ignore + // previous_PES_packet_CRC 16 bslbf + pos += 2; + } + if ( PES_extension_flag == 1) { // ignore + int32_t PES_private_data_flag = (p[pos]&0x80)>>7;// PES_private_data_flag 1 bslbf + int32_t pack_header_field_flag = (p[pos]&0x40)>>6;// pack_header_field_flag 1 bslbf + int32_t program_packet_sequence_counter_flag = (p[pos]&0x20)>>5;// program_packet_sequence_counter_flag 1 bslbf + int32_t P_STD_buffer_flag = (p[pos]&0x10)>>4; // P-STD_buffer_flag 1 bslbf + // reserved 3 bslbf + int32_t PES_extension_flag_2 = (p[pos]&0x01);// PES_extension_flag_2 1 bslbf + pos++; + + if ( PES_private_data_flag == 1) { + // PES_private_data 128 bslbf + pos += 16; + } + if (pack_header_field_flag == 1) { + // pack_field_length 8 uimsbf + // pack_header() + } + if (program_packet_sequence_counter_flag == 1) { + // marker_bit 1 bslbf + // program_packet_sequence_counter 7 uimsbf + // marker_bit 1 bslbf + // MPEG1_MPEG2_identifier 1 bslbf + // original_stuff_length 6 uimsbf + pos += 2; + } + if ( P_STD_buffer_flag == 1) { + // '01' 2 bslbf + // P-STD_buffer_scale 1 bslbf + // P-STD_buffer_size 13 uimsbf + pos += 2; + } + if ( PES_extension_flag_2 == 1) { + // marker_bit 1 bslbf + int32_t PES_extension_field_length = (p[pos]&0x7F);// PES_extension_field_length 7 uimsbf + pos++; + for (int32_t i = 0; i < PES_extension_field_length; i++) { + // reserved 8 bslbf + pos++; + } + } + } + + + *ret_pp = p+pos; + ret_size = 188-(npos+pos); + // ret_size, p[pos], p[pos+1], p[pos+2], p[pos+3], p[pos+4], p[pos+5], + // dts, dts/90, pts, pts/90); + } + else if ( stream_id == 188//program_stream_map 1011 1100 BC + || stream_id == 191//private_stream_2 1011 1111 BF + || stream_id == 240//ECM 1111 0000 F0 + || stream_id == 241//EMM 1111 0001 F1 + || stream_id == 255//program_stream_directory 1111 1111 FF + || stream_id == 242//DSMCC_stream 1111 0010 F2 + || stream_id == 248//ITU-T Rec. H.222.1 type E stream 1111 1000 F8 + ) { + + *ret_pp = p+pos; + ret_size = 188-(npos+pos); + + } + else if ( stream_id == 190//padding_stream 1011 1110 + ) { + *ret_pp = p+pos; + ret_size = 188-(npos+pos); + } + + return pos; +} diff --git a/libyangrtc2/src/yangsrt/common.cpp b/libyangrtc2/src/yangsrt/common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e16fee268505fcbfe63e13ae2dae0896f0a6ab6 --- /dev/null +++ b/libyangrtc2/src/yangsrt/common.cpp @@ -0,0 +1,62 @@ +#include + + #include + +void write_pcr(YangTsBuffer *sb, uint64_t pcr) { + sb->write_1byte((char)(pcr >> 25)); + sb->write_1byte((char)(pcr >> 17)); + sb->write_1byte((char)(pcr >> 9)); + sb->write_1byte((char)(pcr >> 1)); + sb->write_1byte((char)(pcr << 7 | 0x7e)); + sb->write_1byte(0); +} + +void write_pts(YangTsBuffer *sb, uint32_t fb, uint64_t pts) { + uint32_t val; + + val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; + sb->write_1byte((char)val); + + val = (((pts >> 15) & 0x7fff) << 1) | 1; + sb->write_2bytes((int16_t)val); + + val = (((pts) & 0x7fff) << 1) | 1; + sb->write_2bytes((int16_t)val); +} + +uint64_t read_pts(YangTsBuffer *sb) { + uint64_t pts = 0; + uint32_t val = 0; + val = sb->read_1byte(); + pts |= ((val >> 1) & 0x07) << 30; + + val = sb->read_2bytes(); + pts |= ((val >> 1) & 0x7fff) << 15; + + val = sb->read_2bytes(); + pts |= ((val >> 1) & 0x7fff); + + return pts; +} + +uint64_t read_pcr(YangTsBuffer *sb) { + uint64_t pcr = 0; + uint64_t val = sb->read_1byte(); + pcr |= (val << 25) & 0x1FE000000; + + val = sb->read_1byte(); + pcr |= (val << 17) & 0x1FE0000; + + val = sb->read_1byte(); + pcr |= (val << 9) & 0x1FE00; + + val = sb->read_1byte(); + pcr |= (val << 1) & 0x1FE; + + val = sb->read_1byte(); + pcr |= ((val >> 7) & 0x01); + + sb->read_1byte(); + + return pcr; +} diff --git a/libyangrtc2/src/yangsrt/crc.cpp b/libyangrtc2/src/yangsrt/crc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25807f82f7c37a72d6effb75caa7ea6b5b3d3618 --- /dev/null +++ b/libyangrtc2/src/yangsrt/crc.cpp @@ -0,0 +1,13 @@ +#include + +// @see http://www.stmc.edu.hk/~vincent/ffmpeg_0.4.9-pre1/libavformat/mpegtsenc.c +uint32_t crc32(const uint8_t *data, int32_t len) +{ + int32_t i; + uint32_t crc = 0xffffffff; + + for (i = 0; i> 24) ^ *data++) & 0xff]; + + return crc; +} diff --git a/libyangrtc2/src/yangsrt/srt_data.cpp b/libyangrtc2/src/yangsrt/srt_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b04f4f1ead2419cfd2bb4d7a6c630c783927fbd --- /dev/null +++ b/libyangrtc2/src/yangsrt/srt_data.cpp @@ -0,0 +1,45 @@ +#include +#include +SRT_DATA_MSG::SRT_DATA_MSG():_msg_type(SRT_MSG_DATA_TYPE) + ,_len(0) + ,_data_p(nullptr) + //,_key_path(path) +{ + +} + + +SRT_DATA_MSG::SRT_DATA_MSG(uint32_t len):_msg_type(SRT_MSG_DATA_TYPE) + ,_len(len) + //,_key_path(path) +{ + _data_p = new uint8_t[len]; + memset(_data_p, 0, len); +} + +SRT_DATA_MSG::SRT_DATA_MSG(uint8_t* data_p, uint32_t len):_msg_type(SRT_MSG_DATA_TYPE) + ,_len(len) + +{ + _data_p = new uint8_t[len]; + memcpy(_data_p, data_p, len); +} + +SRT_DATA_MSG::~SRT_DATA_MSG() { + if (_data_p && (_len > 0)) { + delete _data_p; + } +} + +uint32_t SRT_DATA_MSG::msg_type() { + return _msg_type; +} + + +uint32_t SRT_DATA_MSG::data_len() { + return _len; +} + +uint8_t* SRT_DATA_MSG::get_data() { + return _data_p; +} diff --git a/libyangrtc2/src/yangstream/YangAudioStreamCapture.cpp b/libyangrtc2/src/yangstream/YangAudioStreamCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28775bcb67e13538eb79a3e3c6dce2211c5433db --- /dev/null +++ b/libyangrtc2/src/yangstream/YangAudioStreamCapture.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +YangAudioStreamCapture::YangAudioStreamCapture() { + m_audioBufs = new uint8_t[1024 * 8]; + m_audioBuffer = m_audioBufs + 20; + m_audioHeaderLen = 1; + atime = 0; + atime1 = 0; + perSt = 0; + m_unitAudioTime=960; + m_src = NULL; + m_srcLen = 0; + m_transType = 0; + m_frametype=1; + m_audioLen=0; + m_audioType=Yang_AED_AAC; +} + +YangAudioStreamCapture::~YangAudioStreamCapture() { + m_audioBuffer = NULL; + delete[] m_audioBufs; + m_audioBufs = NULL; + + m_src = NULL; +} +void YangAudioStreamCapture::init(int32_t ptranstype, int32_t sample, int32_t channel, + YangAudioEncDecType audioType) { + m_transType = ptranstype; + m_audioType=audioType; + if(audioType == Yang_AED_OPUS){ + perSt=channel==1?320:960; + m_unitAudioTime=(channel==1)?320:960; + + }else if (audioType == Yang_AED_MP3){ + perSt = 1152 * 1000 / sample; + }else if (audioType == Yang_AED_AAC) { + m_audioHeaderLen = 2; + m_audioBuffer[0] = 0xaf; + m_audioBuffer[1] = 0x01; + perSt = 1024 * 1000 / sample; + } else { + m_audioHeaderLen = 1; + m_audioBuffer[0] = 0xbe; + + if (audioType != Yang_AED_MP3) { + int32_t sam = 320; + perSt = sam * 1000 / 16000; + } + } +} + +void YangAudioStreamCapture::setFrametype(int32_t frametype){ + m_frametype=frametype; +} +void YangAudioStreamCapture::setAudioData(YangFrame* audioFrame) { + + if (m_transType == Yang_Webrtc) { + m_src = audioFrame->payload; + m_srcLen = audioFrame->nb; + m_audioLen = audioFrame->nb; + + } else { + memcpy(m_audioBuffer + m_audioHeaderLen, audioFrame->payload, audioFrame->nb); + m_audioLen=audioFrame->nb + m_audioHeaderLen; + + } + if(m_audioType == Yang_AED_OPUS){ + if(m_transType == Yang_Webrtc){ + atime+=m_unitAudioTime; + }else{ + atime+=perSt; + } + }else{ + atime1 += perSt; //10240*t_frames/441; + atime = (int64_t) atime1; + } + +} +void YangAudioStreamCapture::setAudioMetaData(uint8_t* p,int32_t plen){ + if (m_transType == Yang_Webrtc) { + m_src = p; + m_srcLen = plen; + m_audioLen = plen; + + } else { + memcpy(m_audioBuffer + m_audioHeaderLen, p, plen); + m_audioLen=plen + m_audioHeaderLen; + } +} +uint8_t* YangAudioStreamCapture::getAudioData() { + return m_transType == Yang_Webrtc ? m_src : m_audioBuffer; +} +int64_t YangAudioStreamCapture::getRtmpTimestamp() { + return atime; +} +int64_t YangAudioStreamCapture::getTsTimestamp() { + return atime * 90; +} + +int64_t YangAudioStreamCapture::getTimestamp() { + return m_transType==Yang_Srt ? atime*90 : atime; +} +int32_t YangAudioStreamCapture::getAudioLen(){ + return m_audioLen; +} +int32_t YangAudioStreamCapture::getFrametype(){ + return m_frametype; +} +YangAudioEncDecType YangAudioStreamCapture::getAudioType(){ + return m_audioType; +} diff --git a/libyangrtc2/src/yangstream/YangStreamCapture.cpp b/libyangrtc2/src/yangstream/YangStreamCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff7ea6ec279f443e36b4ac2759eb5422db79f12e --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamCapture.cpp @@ -0,0 +1,77 @@ +/* + * YangStreamCapture.cpp + * + * Created on: 2021年10月2日 + * Author: yang + */ + +#include + +YangStreamCapture::YangStreamCapture() { + + +} + +YangStreamCapture::~YangStreamCapture() { + +} + + + +uint8_t* YangStreamCapture::getVideoData(){ + return m_video.getVideoData(); +} +int32_t YangStreamCapture::getVideoLen(){ + return m_video.getVideoLen(); +} +int32_t YangStreamCapture::getVideoFrametype(){ + return m_video.getFrametype(); +} +int64_t YangStreamCapture::getVideoTimestamp(){ + return m_video.getTimestamp(); +} + + +uint8_t* YangStreamCapture::getAudioData(){ + return m_audio.getAudioData(); +} +int32_t YangStreamCapture::getAudioLen(){ + return m_audio.getAudioLen(); +} +int64_t YangStreamCapture::getAudioTimestamp(){ + return m_audio.getTimestamp(); +} +YangAudioEncDecType YangStreamCapture::getAudioType(){ + return m_audio.getAudioType(); +} + + +void YangStreamCapture::initVideo(int32_t transtype){ + m_video.init(transtype); +} +void YangStreamCapture::setVideoData(YangFrame* videoFrame,YangVideoEncDecType videoType){ + m_video.setVideoData(videoFrame,videoType); +} +void YangStreamCapture::setVideoMeta(uint8_t* p,int32_t plen,YangVideoEncDecType videoType){ + m_video.setVideoMeta(p,plen,videoType); +} +void YangStreamCapture::setVideoFrametype(int32_t frametype){ + m_video.setFrametype(frametype); +} +void YangStreamCapture::setMetaTimestamp(int64_t timestamp){ + m_video.setMetaTimestamp(timestamp); +} + +void YangStreamCapture::setAudioData(YangFrame* audioFrame){ + m_audio.setAudioData(audioFrame); +} +void YangStreamCapture::setAudioMetaData(uint8_t* p,int32_t plen){ + m_audio.setAudioMetaData(p,plen); +} +void YangStreamCapture::setAudioFrametype(int32_t frametype){ + m_audio.setFrametype(frametype); +} + +void YangStreamCapture::initAudio(int32_t transType,int32_t sample,int32_t channel,YangAudioEncDecType audioType){ + m_audio.init(transType,sample,channel,audioType); +} diff --git a/libyangrtc2/src/yangstream/YangStreamFactory.cpp b/libyangrtc2/src/yangstream/YangStreamFactory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de8d6515eb800df9c982fc83327b6f509a47d6f7 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamFactory.cpp @@ -0,0 +1,20 @@ +#include +#include "YangStreamRtmp.h" +#include "YangStreamSrt.h" +#include "YangStreamRtc.h" +YangStreamFactory::YangStreamFactory() { + + +} + +YangStreamFactory::~YangStreamFactory() { + +} +YangStreamHandle* YangStreamFactory::createStreamHandle(int32_t transType,int32_t puid,YangContext* pcontext){ + if(transType==Yang_Rtmp) return new YangStreamRtmp(puid,pcontext); + if(transType==Yang_Srt) return new YangStreamSrt(puid,pcontext); + + return new YangStreamRtc(puid,pcontext); + +} + diff --git a/libyangrtc2/src/yangstream/YangStreamHandle.cpp b/libyangrtc2/src/yangstream/YangStreamHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9641a5ba26adc387fc16da2d2a04d2e7b6227a9 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamHandle.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include "yangutil/sys/YangLog.h" +YangStreamHandle::YangStreamHandle(int32_t puid,YangContext* pcontext) { + m_context=pcontext; + m_streamInit = 0; + m_audioStream=0; + m_videoStream=0; + m_uid=puid; + m_data=NULL; + m_netState = 1; +} + +YangStreamHandle::~YangStreamHandle() { + m_data=NULL; + m_context=NULL; + +} +void YangStreamHandle::init(YangStreamConfig* pconf){ + m_conf.serverIp=pconf->serverIp; + m_conf.localIp=pconf->localIp; + m_conf.app=pconf->app; + m_conf.stream=pconf->stream; + m_conf.serverPort=pconf->serverPort; + m_conf.localPort=pconf->localPort; + m_conf.uid=pconf->uid; + m_conf.streamOptType=pconf->streamOptType; +} +int32_t YangStreamHandle::connectServer(){ + if(isconnected()) return Yang_Ok; + m_netState=connectMediaServer(); + return m_netState; +} +int32_t YangStreamHandle::disConnectServer(){ + m_netState=1; + return disConnectMediaServer(); +} +void YangStreamHandle::setReceiveCallback(YangReceiveCallback *pdata){ + m_data=pdata; +} diff --git a/libyangrtc2/src/yangstream/YangStreamManager.cpp b/libyangrtc2/src/yangstream/YangStreamManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c54f3f71084778db89b24cae84c17e9e309c436 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamManager.cpp @@ -0,0 +1,121 @@ +/* + * YangStreamManager.cpp + * + * Created on: 2021年10月2日 + * Author: yang + */ + +#include +#include +YangStreamManager::YangStreamManager() { + m_playBuffers=NULL; + m_playBuffer=NULL; + m_sendPli=NULL; + m_mediaConfig_dec=NULL; + m_mediaConfig_render=NULL; + m_rtcMsg=NULL; + m_rtcMsgMap=NULL; + + m_audioClock=0; + m_videoClock=0; +} + +YangStreamManager::~YangStreamManager() { + yang_delete(m_playBuffer); + if(m_playBuffers){ + for(size_t i=0;isize();i++){ + yang_delete(m_playBuffers->at(i)); + } + m_playBuffers->clear(); + } + m_sendPli=NULL; + m_mediaConfig_dec=NULL; + m_mediaConfig_render=NULL; + if(m_rtcMsgMap){ + m_rtcMsgMap->clear(); + yang_delete(m_rtcMsgMap); + } +} +int32_t YangStreamManager::getAudioClock(){ + return m_audioClock; +} + +void YangStreamManager::sendRequest(int32_t puid, YangRtcMessageType msg) { + if(puid>0&&m_rtcMsgMap){ + map::iterator iter=m_rtcMsgMap->find(puid); + if(iter!=m_rtcMsgMap->end()){ + yang_trace("\nuser(%d)..send pli....",puid); + iter->second->notify(puid, msg); + } + }else if(m_rtcMsg) { + yang_trace("\n..send pli...."); + m_rtcMsg->notify(puid, msg); + } +} + + int32_t YangStreamManager::getVideoClock(){ + return m_videoClock; + } +void YangStreamManager::setSendRequestCallback(YangSendRequestCallback* pli){ + m_sendPli=pli; +} + void YangStreamManager::setDecoderMediaConfigCallback(YangMediaConfigCallback* dec){ + m_mediaConfig_dec=dec; + } + void YangStreamManager::setRenderMediaConfigCallback(YangMediaConfigCallback* render){ + m_mediaConfig_render=render; + } +void YangStreamManager::setMediaConfig(int32_t puid,YangAudioParam* audio,YangVideoParam* video){ + if(m_mediaConfig_dec) m_mediaConfig_dec->setMediaConfig(puid,audio,video); + if(m_mediaConfig_render) m_mediaConfig_render->setMediaConfig(puid,audio,video); + size_t i=0; + if(audio){ + if(m_playBuffer) m_playBuffer->setAudioClock(audio->audioClock); + if(m_playBuffers){ + for(i=0;isize();i++){ + m_playBuffers->at(i)->setAudioClock(audio->audioClock); + } + } + m_audioClock=audio->audioClock; + } + if(video){ + if(m_playBuffer) m_playBuffer->setVideoClock(video->videoClock); + if(m_playBuffers){ + for(i=0;isize();i++){ + m_playBuffers->at(i)->setVideoClock(video->videoClock); + } + } + m_videoClock=video->videoClock; + } +} + void YangStreamManager::sendRequest(int32_t puid,uint32_t ssrc,YangRequestType req){ + if(m_sendPli) m_sendPli->sendRequest(puid,ssrc,req); + } +int YangStreamManager::getIndex(int puid){ + if(m_playBuffers){ + for(size_t i=0;isize();i++){ + if(m_playBuffers->at(i)->m_uid==puid) return i; + } + } + return -1; +} + +YangSynBuffer* YangStreamManager::getSynBuffer(int puid){ + int ind=getIndex(puid); + if(ind==-1) return NULL; + return m_playBuffers->at(ind); +} + +void YangStreamManager::setRtcMessageNotify(int puid,YangRtcMessageNotify *rtcmsg) { + + if(puid>0){ + if(m_rtcMsgMap==NULL) m_rtcMsgMap=new map(); + map::iterator iter=m_rtcMsgMap->find(puid); + if(iter==m_rtcMsgMap->end()){ + (*m_rtcMsgMap)[puid]=rtcmsg; + } + }else{ + m_rtcMsg=rtcmsg; + + } +} diff --git a/libyangrtc2/src/yangstream/YangStreamPlay.cpp b/libyangrtc2/src/yangstream/YangStreamPlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..173de1608003f3f8257d5ae017ac0d5696570e3d --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamPlay.cpp @@ -0,0 +1,18 @@ +/* + * YangStreamRender.cpp + * + * Created on: 2021年10月2日 + * Author: yang + */ + +#include + +YangStreamPlay::YangStreamPlay() { + + +} + +YangStreamPlay::~YangStreamPlay() { + +} + diff --git a/libyangrtc2/src/yangstream/YangStreamPlay.h b/libyangrtc2/src/yangstream/YangStreamPlay.h new file mode 100644 index 0000000000000000000000000000000000000000..d9512558ac7884b6daec755e0af2120011e90db3 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamPlay.h @@ -0,0 +1,17 @@ +/* + * YangStreamRender.h + * + * Created on: 2021年10月2日 + * Author: yang + */ + +#ifndef SRC_YANGSTREAM_YANGSTREAMPLAY_H_ +#define SRC_YANGSTREAM_YANGSTREAMPLAY_H_ + +class YangStreamPlay { +public: + YangStreamPlay(); + virtual ~YangStreamPlay(); +}; + +#endif /* SRC_YANGSTREAM_YANGSTREAMPLAY_H_ */ diff --git a/libyangrtc2/src/yangstream/YangStreamRtc.cpp b/libyangrtc2/src/yangstream/YangStreamRtc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96f1527540f4e2e66d3dbd3fc3ce5ef18f6b464b --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamRtc.cpp @@ -0,0 +1,59 @@ +#include "YangStreamRtc.h" + +#include +#include +#include "yangutil/yang_unistd.h" +YangStreamRtc::YangStreamRtc(int32_t puid,YangContext* pcontext) :YangStreamHandle(puid,pcontext) { + m_rtc = YangRtcHandle::createRtcHandle(pcontext); + + +} + +YangStreamRtc::~YangStreamRtc() { + yang_delete(m_rtc); + +} +int32_t YangStreamRtc::isconnected(){ + if(m_rtc==NULL) return 0; + return m_rtc->getState(); +} +int32_t YangStreamRtc::getConnectState(){ + + return m_rtc->getState()?Yang_Ok:ERROR_SOCKET; +} +int32_t YangStreamRtc::disConnectMediaServer(){ + + return m_rtc->disconnectServer(); +} +int32_t YangStreamRtc::connectMediaServer() { + if(isconnected()) return Yang_Ok; + + m_rtc->setReceiveCallback(m_data); + m_rtc->init(&m_conf); + + return reconnect(); +} + + + +int32_t YangStreamRtc::publishAudioData(YangStreamCapture *audioFrame) { + if(m_rtc) return m_rtc->publishAudio(audioFrame); + return Yang_Ok; +} + +int32_t YangStreamRtc::publishVideoData(YangStreamCapture* videoFrame) { + if(m_rtc) return m_rtc->publishVideo(videoFrame); + return Yang_Ok; +} + +int32_t YangStreamRtc::reconnect() { + + return m_rtc->connectRtcServer(); +} + + +int32_t YangStreamRtc::receiveData(int32_t *plen) { + + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangstream/YangStreamRtc.h b/libyangrtc2/src/yangstream/YangStreamRtc.h new file mode 100644 index 0000000000000000000000000000000000000000..08078843a2c784dec47b4955a48d20960a524bd4 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamRtc.h @@ -0,0 +1,27 @@ +#ifndef SRC_YANGSTREAM_SRC_YANGSTREAMRTC_H_ +#define SRC_YANGSTREAM_SRC_YANGSTREAMRTC_H_ +#include +#include +class YangStreamRtc :public YangStreamHandle{ +public: + YangStreamRtc(int32_t puid,YangContext* pcontext); + virtual ~YangStreamRtc(); + int32_t disConnectMediaServer(); + int32_t connectMediaServer(); + int32_t receiveData(int32_t *plen); + int32_t getConnectState(); + int32_t isconnected(); + + //void setRemoteMediaParamCallback(YangMediaConfigCallback* remoteCb); + //void setSendRequestCallback(YangSendRequestCallback *cb); +public: + + int32_t reconnect(); + int32_t publishVideoData(YangStreamCapture* videoFrame); + int32_t publishAudioData(YangStreamCapture* audioFrame); +private: + YangRtcHandle *m_rtc; + +}; + +#endif /* SRC_YANGSTREAM_SRC_YANGSTREAMRTC_H_ */ diff --git a/libyangrtc2/src/yangstream/YangStreamRtmp.cpp b/libyangrtc2/src/yangstream/YangStreamRtmp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71c2147cf36b1450609439f8eb43a15afc0ae739 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamRtmp.cpp @@ -0,0 +1,131 @@ + +#include "YangStreamRtmp.h" +#include +#include "yangutil/yang_unistd.h" +YangStreamRtmp::YangStreamRtmp(int32_t puid,YangContext* pcontext) :YangStreamHandle(puid,pcontext) { + rtmp = NULL; + rtmpRet = 0; + memset(&pac_a, 0, sizeof(pac_a)); + memset(&pac, 0, sizeof(pac)); + m_buf = NULL; + m_bufLen = 0; + memset(&m_audioFrame,0,sizeof(YangFrame)); + memset(&m_videoFrame,0,sizeof(YangFrame)); + +} +int32_t YangStreamRtmp::isconnected(){ + if(rtmp&&rtmp->r) + return rtmp->r->m_bConnected; + else + return 0; +} + +YangStreamRtmp::~YangStreamRtmp() { + pac.m_body=NULL; + pac_a.m_body=NULL; + yang_delete(rtmp); + yang_deleteA(m_buf); +} +int32_t YangStreamRtmp::getConnectState(){ + if(rtmp&&rtmp->r->m_bConnected) return Yang_Ok; + return ERROR_SOCKET; +} +int32_t YangStreamRtmp::disConnectMediaServer(){ + rtmp->RTMP_Close(); + return Yang_Ok; +} +int32_t YangStreamRtmp::connectMediaServer() { + if(isconnected()) return Yang_Ok; + if (rtmp == NULL) + rtmp = new YangRtmpBase(); + if(m_conf.streamOptType){ + pac.m_packetType = RTMP_PACKET_TYPE_VIDEO; + pac_a.m_packetType = RTMP_PACKET_TYPE_AUDIO; + } + rtmp->initRTMP((char*)m_conf.serverIp.c_str(),(char*) m_conf.app.c_str(), m_conf.serverPort); + return reconnect(); +} + +int32_t YangStreamRtmp::publishAudioData(YangStreamCapture* audioFrame) { + + pac_a.m_nBodySize = audioFrame->getAudioLen(); + pac_a.m_headerType = RTMP_PACKET_SIZE_LARGE; + pac_a.m_nTimeStamp = audioFrame->getAudioTimestamp(); + pac_a.m_nChannel = 0x04; + pac_a.m_nInfoField2 = rtmp->r->m_stream_id; + pac_a.m_body=(char*)audioFrame->getAudioData(); + rtmpRet = rtmp->sendPacket(&pac_a, 0); + if(!rtmpRet) m_netState=ERROR_SOCKET; + return m_netState; +} + +int32_t YangStreamRtmp::publishVideoData(YangStreamCapture* videoFrame) { + //int32_t ret = Yang_Ok; + pac.m_nBodySize = videoFrame->getVideoLen(); + pac.m_headerType = RTMP_PACKET_SIZE_LARGE; + pac.m_body=(char*)videoFrame->getVideoData(); + pac.m_nChannel = 0x04; + pac.m_nTimeStamp = videoFrame->getVideoTimestamp(); //(unsigned int)videoTimestamp; + pac.m_nInfoField2 = rtmp->r->m_stream_id; + rtmpRet = rtmp->sendPacket(&pac, 0); + if(!rtmpRet) m_netState=ERROR_SOCKET; + return m_netState; +} + +int32_t YangStreamRtmp::reconnect() { + int32_t ret = rtmp->connectRtmpServer( m_conf.streamOptType, (char*)m_conf.serverIp.c_str(), (char*)m_conf.app.c_str(), m_conf.serverPort); + if (ret) { + rtmp->RTMP_Close(); + return ret; + } + return rtmp->HandleStream((char*)m_conf.stream.c_str(), m_conf.streamOptType, m_uid); +} + + +int32_t YangStreamRtmp::receiveData(int32_t *plen) { + if(!rtmp||!rtmp->r->m_bConnected) return 1; + if (!m_buf) + m_buf = new char[1024 * 64]; + char *buf = m_buf + 30; + if (!rtmp->yangReadPacket(&pac, buf)) { + return 1; + } + //while (!RTMPPacket_IsReady(&pac)&&rtmp->yangReadPacket(&pac, buf)) { + // yang_usleep(1); + //} + if (RTMPPacket_IsReady(&pac)) { + uint8_t *temp = NULL; + if ((pac.m_packetType == RTMP_PACKET_TYPE_AUDIO + || pac.m_packetType == RTMP_PACKET_TYPE_VIDEO)) { + temp = (uint8_t*) pac.m_body; + if (temp) { + + if (pac.m_packetType == RTMP_PACKET_TYPE_AUDIO) { + m_audioFrame.payload=temp; + m_audioFrame.uid=m_uid; + m_audioFrame.nb=pac.m_nBodySize; + if(m_data) m_data->receiveAudio(&m_audioFrame); + *plen = pac.m_nBodySize; + } else { + m_videoFrame.timestamp = pac.m_nTimeStamp; + m_videoFrame.payload=temp; + m_videoFrame.uid=m_uid; + m_videoFrame.nb=pac.m_nBodySize; + if(m_data) m_data->receiveVideo(&m_videoFrame); + *plen = pac.m_nBodySize; + } + } + + } else { + rtmp->clientPacket(&pac); + } + + memset(m_buf, 0, + pac.m_nBodySize < RTMP_MAX_BODY_SIZE ? + pac.m_nBodySize + 36 : RTMP_MAX_BODY_SIZE); + memset(&pac, 0, sizeof(RTMPPacket)); + pac.m_body = NULL; + + } + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangstream/YangStreamRtmp.h b/libyangrtc2/src/yangstream/YangStreamRtmp.h new file mode 100644 index 0000000000000000000000000000000000000000..451bc8579b79bd7c1771bb4058547807e3d83626 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamRtmp.h @@ -0,0 +1,36 @@ + +#ifndef YANGSTREAM_SRC_YANGSTREAMRTMP_H_ +#define YANGSTREAM_SRC_YANGSTREAMRTMP_H_ +#include "stdint.h" +#include +#include +class YangStreamRtmp :public YangStreamHandle{ +public: + YangStreamRtmp(int32_t puid,YangContext* pcontext); + virtual ~YangStreamRtmp(); + int32_t disConnectMediaServer(); + int32_t connectMediaServer(); + int32_t receiveData(int32_t *plen); + int32_t getConnectState(); + int32_t isconnected(); + + //void setRemoteMediaParamCallback(YangMediaConfigCallback* remoteCb); + //void setSendRequestCallback(YangSendRequestCallback *cb); + public: + int32_t sendPmt(); + int32_t reconnect(); + int32_t publishVideoData(YangStreamCapture* videoFrame); + int32_t publishAudioData(YangStreamCapture* audioFrame); + private: + YangRtmpBase *rtmp; + int32_t rtmpRet; + char* m_buf; + int32_t m_bufLen; + RTMPPacket pac; + RTMPPacket pac_a; + + YangFrame m_audioFrame; + YangFrame m_videoFrame; +}; + +#endif /* YANGSTREAM_SRC_YANGSTREAMRTMP_H_ */ diff --git a/libyangrtc2/src/yangstream/YangStreamSrt.cpp b/libyangrtc2/src/yangstream/YangStreamSrt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5cb5ee37871f9a9976de2e2f89170b0471141816 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamSrt.cpp @@ -0,0 +1,182 @@ + +#include "YangStreamSrt.h" +#include + +#include "yangutil/sys/YangLog.h" +#define YangSrtUnitSize 1316 +YangStreamSrt::YangStreamSrt(int32_t puid,YangContext* pcontext):YangStreamHandle(puid,pcontext) { + m_bufLen = 0; + m_buffer = NULL; + m_bufReceiveLen = 0, m_bufRemainLen = 0; + m_srt = NULL; + memset(&m_audioFrame,0,sizeof(YangFrame)); + memset(&m_videoFrame,0,sizeof(YangFrame)); +} + +YangStreamSrt::~YangStreamSrt() { + if (m_buffer) + delete[] m_buffer; + m_buffer = NULL; +} + +int32_t YangStreamSrt::isconnected(){ + if(m_srt) + return m_srt->getSrtSocketStatus()==SRTS_CONNECTED; + else + return 0; +} + + +int32_t YangStreamSrt::getConnectState(){ + int32_t ret=m_srt->getSrtSocketStatus(); + if(ret==SRTS_CONNECTED) + return Yang_Ok; + else + return Yang_SRTS_SocketBase+ret; + //return ERROR_SOCKET; +} +int32_t YangStreamSrt::reconnect() { + m_bufLen=0; + char url[1024]={0}; + sprintf(url,"%s.sls.com/%s/%s",m_conf.streamOptType?"uplive":"live",m_conf.app.c_str(),m_conf.stream.c_str()); + int32_t ret=m_srt->initConnect(url); + if(ret) return ret; + return m_srt->connectServer(); + +} + + + +int32_t YangStreamSrt::connectMediaServer(){ + if(isconnected()) return Yang_Ok; + if(!m_buffer) m_buffer=new char[Yang_Srt_CacheSize]; + if(m_srt==NULL) m_srt=new YangSrtBase(); + if(!m_srt->m_contextt){ + m_bufLen=0; + char s[512]={0}; + sprintf(s,"%s.sls.com/%s/%s",m_conf.streamOptType==Yang_Stream_Publish?"uplive":"live",m_conf.app.c_str(),m_conf.stream.c_str()); + m_conf.url=s; + m_srt->init((char*)m_conf.serverIp.c_str(),m_conf.serverPort); + } + int32_t ret=m_srt->initConnect((char*)m_conf.url.c_str()); + if(ret) return ret; + return m_srt->connectServer(); + +} + +int32_t YangStreamSrt::disConnectMediaServer(){ + m_srt->closeSrt(); + m_netState=1; + return Yang_Ok; +} + + +int32_t YangStreamSrt::publishAudioData(YangStreamCapture* audioFrame) { + vector sb ; + m_ts.encode(audioFrame->getAudioData(), audioFrame->getAudioLen(), 1, audioFrame->getAudioTimestamp(), audioFrame->getAudioType() == 0 ? TS_AAC : TS_OPUS, &sb); + int32_t ret=Yang_Ok; + for (size_t i = 0; i < sb.size(); i++) { + memcpy(m_buffer+m_bufLen,sb.at(i).data(),188); + m_bufLen+=188; + if(m_bufLen==YangSrtUnitSize){ + ret=m_srt->publish((char*) m_buffer, YangSrtUnitSize); + m_bufLen=0; + } + + if (ret){ + yang_error("publish audio error..%d",ret); + m_netState=ret; + return ret; + } + + } + return Yang_Ok; +} + + +int32_t YangStreamSrt::publishVideoData(YangStreamCapture* videoFrame) { + int32_t ret=Yang_Ok; + vector sb; + m_ts.encode(videoFrame->getVideoData(), videoFrame->getVideoLen(), videoFrame->getVideoFrametype(), videoFrame->getVideoTimestamp(), TS_H264, &sb); + for (size_t i = 0; i < sb.size(); i++) { + memcpy(m_buffer+m_bufLen,sb.at(i).data(),188); + m_bufLen+=188; + if(m_bufLen==YangSrtUnitSize){ + ret=m_srt->publish((char*) m_buffer, YangSrtUnitSize); + m_bufLen=0; + } + if (ret) { + return ret; + m_netState=ret; + } + } + return Yang_Ok; +} + + +void YangStreamSrt::on_data_callback(SRT_DATA_MSG_PTR data_ptr, + uint32_t media_type, uint64_t dts, uint64_t pts) { + uint8_t *temp = data_ptr->get_data(); + int32_t len = data_ptr->data_len(); + + if ((media_type == Yang_H264_PID || media_type == Yang_H265_PID) + && m_videoStream) { + //int64_t t_timestamp = dts; + m_videoFrame.timestamp=dts; + m_videoFrame.uid=m_uid; + m_videoFrame.payload=temp; + m_videoFrame.nb=len; + if (m_data) m_data->receiveVideo(&m_videoFrame); + } else if (media_type == Yang_AAC_PID && m_audioStream) { + m_audioFrame.uid=m_uid; + m_audioFrame.nb=len; + m_audioFrame.payload=temp; + if (m_data) m_data->receiveAudio(&m_audioFrame); + } else if (media_type == Yang_OPUS_PID && m_audioStream) { + m_audioFrame.uid=m_uid; + m_audioFrame.nb=len; + m_audioFrame.payload=temp; + if (m_data) m_data->receiveAudio(&m_audioFrame); + } + temp = NULL; +} + +int32_t YangStreamSrt::receiveData(int32_t *plen) { + + if (!m_srt) + return Yang_Ok; + m_bufReceiveLen = 0; + if (m_srt->receive(m_buffer + m_bufRemainLen, &m_bufReceiveLen)) + return ERROR_SRT_PushFailure; + m_bufLen = m_bufReceiveLen + m_bufRemainLen; + if (m_bufLen < YangSrtUnitLen) { + m_bufRemainLen = m_bufLen; + return Yang_Ok; + } + m_bufRemainLen = m_bufLen % YangSrtUnitLen; + *plen = m_bufLen; + auto input_ptr = std::make_shared((uint8_t*) m_buffer, + m_bufLen - m_bufRemainLen); + demux.decode(input_ptr, this); + if (m_bufRemainLen > 0) + memcpy(m_buffer, m_buffer + (m_bufLen - m_bufRemainLen), + m_bufRemainLen); + return Yang_Ok; +} + + +int32_t YangStreamSrt::sendPmt(){ + vector sb; + m_ts.encodePmtWithoutData(&sb); + int32_t ret=Yang_Ok; + for (size_t i = 0; i < sb.size(); i++) { + ret=m_srt->publish((char*) sb.at(i).data(), 188); + if (ret){ + yang_error("publish audio error..%d",i); + return ret; + } + + } + sb.clear(); + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangstream/YangStreamSrt.h b/libyangrtc2/src/yangstream/YangStreamSrt.h new file mode 100644 index 0000000000000000000000000000000000000000..8abd74500d1cc0c6f27f4d9acf99d29cd6916fb7 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangStreamSrt.h @@ -0,0 +1,37 @@ + +#ifndef YANGSTREAM_SRC_YANGSTREAMSRT_H_ +#define YANGSTREAM_SRC_YANGSTREAMSRT_H_ +#include +#include "yangsrt/YangSrtBase.h" +#include "yangsrt/YangTsMuxer.h" +#include "yangsrt/YangTsdemux.h" +class YangStreamSrt :public YangStreamHandle,public ts_media_data_callback_I { +public: + YangStreamSrt(int32_t puid,YangContext* pcontext); + virtual ~YangStreamSrt(); + int32_t disConnectMediaServer(); + int32_t connectMediaServer(); + int32_t receiveData(int32_t *plen); + void on_data_callback(SRT_DATA_MSG_PTR data_ptr, + uint32_t media_type, uint64_t dts, uint64_t pts); + + +public: + int32_t isconnected(); + int32_t getConnectState(); + int32_t sendPmt(); + int32_t reconnect(); + int32_t publishVideoData(YangStreamCapture* videoFrame); + int32_t publishAudioData(YangStreamCapture* audioFrame); +private: + YangTsdemux demux; + YangSrtBase *m_srt; + YangTsMuxer m_ts; + char *m_buffer; + int32_t m_bufLen; + int32_t m_bufReceiveLen,m_bufRemainLen; + YangFrame m_audioFrame; + YangFrame m_videoFrame; +}; + +#endif /* YANGSTREAM_SRC_YANGSTREAMSRT_H_ */ diff --git a/libyangrtc2/src/yangstream/YangSynBuffer.cpp b/libyangrtc2/src/yangstream/YangSynBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fd2e268a1f97bc1bc3e2f43c2c013c7d032f237 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangSynBuffer.cpp @@ -0,0 +1,268 @@ +#include +#include +#include +#include +#include + + +YangSynBuffer::YangSynBuffer() { + m_transtype = Yang_Webrtc; + if (m_transtype == Yang_Webrtc) { + m_videoClock = 90000; + m_audioClock = 48000; + } else if (m_transtype == Yang_Rtmp) { + m_videoClock = 1000; + m_audioClock = 1000; + } + + m_videoCacheTime=Yang_Video_Cache_time; + + resetAudioClock(); + resetVideoClock(); + + + m_baseClock = 0; + + m_paused = 0; + m_uid = 0; + m_width = 0; + m_height = 0; + + m_synType = YANG_SYNC_AUDIO_MASTER; + m_maxAudioMinus = Yang_Max_Audio_Intervaltime; + m_maxVideoMinus = Yang_Max_Video_Intervaltime; + m_videoBuffer = NULL; + m_audioBuffer = NULL; +} + +YangSynBuffer::~YangSynBuffer() { + m_videoBuffer = NULL; + m_audioBuffer = NULL; +} +void YangSynBuffer::resetVideoClock(){ + m_videoBase = 0; + m_videoTime = 0; + m_videoMinus = 0; + m_pre_videoTime = 0; + + m_video_startClock=0; + m_videoNegativeCount=0; + m_videoTimeoutCount=0; + + m_isFirstVideo=false; + m_video_time_state=0; + +} +void YangSynBuffer::resetAudioClock(){ + m_audioBase = 0; + m_audioTime = 0; + m_audioMinus = 0; + m_pre_audioTime = 0; + m_lostAudioCount=0; + m_audio_startClock = 0; + m_audioNegativeCount=0; + m_audioTimeoutCount=0; + m_audioDelay=0; + m_isFirstAudio=false; +} +void YangSynBuffer::setAudioClock(int paudioclock){ + if(paudioclock<=0) return; + m_audioClock = paudioclock; +} +void YangSynBuffer::setVideoClock(int pvideoclock){ + if(pvideoclock<=0) return; + m_videoClock = pvideoclock; + +} + +void YangSynBuffer::setVideoCacheTime(int pctime){ + m_videoCacheTime=pctime; +} +void YangSynBuffer::setInVideoBuffer(YangVideoBuffer *pbuf) { + m_videoBuffer = pbuf; +} +void YangSynBuffer::setInAudioBuffer(YangAudioPlayBuffer *pbuf) { + m_audioBuffer = pbuf; +} +void YangSynBuffer::setTranstype(int transtype) { + m_transtype = transtype; + + if (m_transtype == Yang_Webrtc) { + m_videoClock = 90000; + m_audioClock = 48000; + } else if (m_transtype == Yang_Rtmp) { + m_videoClock = 1000; + m_audioClock = 1000; + } +} +uint8_t* YangSynBuffer::getVideoRef(YangFrame *pframe) { + if (!m_videoBuffer || !m_videoBuffer->size()) + return NULL; + uint8_t *tmp = NULL; + int err=0; + + + if ((err=playVideoFrame(m_videoBuffer->getCurVideoFrame()))==Yang_Ok) { + + tmp = m_videoBuffer->getVideoRef(pframe); + m_width = m_videoBuffer->m_width; + m_height = m_videoBuffer->m_height; + return tmp; + }else if(err==-1){ + tmp = m_videoBuffer->getVideoRef(pframe); + m_width = m_videoBuffer->m_width; + m_height = m_videoBuffer->m_height; + return NULL; + } + + return tmp; +} + +uint8_t* YangSynBuffer::getAudioRef(YangFrame *audioFrame) { + if (!m_audioBuffer || !m_audioBuffer->size()) + return NULL; + + //return m_audioBuffer->getAudios(audioFrame); + + int err=0; + if ((err=playAudioFrame(m_audioBuffer->getNextTimestamp()))==Yang_Ok){ + + return m_audioBuffer->getAudios(audioFrame); + } + if(err==-1){ + m_audioBuffer->getAudios(audioFrame); + + return getAudioRef(audioFrame); + } + + return NULL; + +} + +int32_t YangSynBuffer::getAudioSize() { + if (m_audioBuffer) + return m_audioBuffer->size(); + return 0; +} +int32_t YangSynBuffer::getVideoSize() { + if (m_videoBuffer) + return m_videoBuffer->size(); + return 0; +} + +int YangSynBuffer::playAudioFrame(int64_t pts) { + + if (m_audioBase == 0) { + if(!m_isFirstAudio){ + //clear cache + yang_reindex(m_audioBuffer); + m_isFirstAudio=true; + return false; + } + updateAudioBaseTimestamp(pts); + } + + if(m_transtype == Yang_Webrtc){ + //get relative time + m_audioTime = (pts - m_audioBase) * 1000 / m_audioClock; + }else{ + m_audioTime = (pts - m_audioBase); + } + + m_audioMinus = m_audioTime +Yang_Audio_Cache_time- (yang_get_milli_tick() - m_audio_startClock); + + m_pre_audioTime = m_audioTime; + + if(m_audioMinus<0) { + m_audioNegativeCount++; + if(m_audioNegativeCount>10){ + updateAudioBaseTimestamp(pts); + m_audioNegativeCount=0; + } + return -1; + } + if(m_audioMinus <= m_maxAudioMinus) { + if(m_audioTime>Yang_Audio_Base_Update_Interval) { + //int delay=m_videoTime- (yang_get_milli_tick() - m_video_startClock); + + if(m_lostAudioCount>5){ + YangFrame frame; + memset(&frame,0,sizeof(YangFrame)); + + m_audioBuffer->getAudios(&frame); + m_audioBuffer->getAudios(&frame); + m_lostAudioCount=0; + } + if(m_audioBuffer->size()>2) m_lostAudioCount++; + updateAudioBaseTimestamp(pts); + + } + return Yang_Ok; + } + m_audioTimeoutCount++; + if(m_audioTimeoutCount>10){ + m_audioTimeoutCount=0; + updateAudioBaseTimestamp(pts); + } + return 1; +} + +int YangSynBuffer::playVideoFrame(YangFrame* frame) { + // if(!m_audio_startClock) return false; + if(m_videoBase==0) { + if(!m_isFirstVideo){ + //clear cache + yang_reindex(m_videoBuffer); + m_isFirstVideo=true; + return false; + } + + updateVideoBaseTimestamp(frame->timestamp); + } + if(!m_video_time_state&&frame->frametype==YANG_Frametype_I){ + + updateVideoBaseTimestamp(frame->timestamp); + m_video_time_state=1; + } + + if (m_transtype == Yang_Webrtc) + m_videoTime = (frame->timestamp - m_videoBase) * 1000 / m_videoClock; + else + m_videoTime = frame->timestamp - m_videoBase; + + m_videoMinus = m_videoTime+m_videoCacheTime - (yang_get_milli_tick() - m_video_startClock); + + if(m_videoMinus<0) { + m_videoNegativeCount++; + if(m_videoNegativeCount>6){ + updateVideoBaseTimestamp(frame->timestamp); + m_videoNegativeCount=0; + } + return -1; + } + if(m_videoMinus <= m_maxVideoMinus) { + if(frame->frametype==YANG_Frametype_I) updateVideoBaseTimestamp(frame->timestamp); + return Yang_Ok; + } + m_videoTimeoutCount++; + if(m_videoTimeoutCount>6){ + m_videoTimeoutCount=0; + updateVideoBaseTimestamp(frame->timestamp); + } + + return 1; + +} + +void YangSynBuffer::updateVideoBaseTimestamp(int64_t pts){ + m_videoBase = pts; + m_video_startClock=yang_get_milli_tick(); +} +void YangSynBuffer::updateAudioBaseTimestamp(int64_t pts){ + m_audioBase=pts; + m_audio_startClock = yang_get_milli_tick(); +} +void YangSynBuffer::setClock() { + m_audio_startClock = yang_get_milli_tick(); +} + diff --git a/libyangrtc2/src/yangstream/YangVideoStreamCapture.cpp b/libyangrtc2/src/yangstream/YangVideoStreamCapture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51fe67113a631dbf52065a7f77cca42d1d9529f9 --- /dev/null +++ b/libyangrtc2/src/yangstream/YangVideoStreamCapture.cpp @@ -0,0 +1,157 @@ + +#include +#include +#include +#include +YangVideoStreamCapture::YangVideoStreamCapture() { + + m_videoBufs = NULL; + m_videoBuffer = NULL; + videoTimestamp = 0, baseTimestamp = 0; + curVideotimestamp = 0; + preTimestamp = 0; + + m_src=NULL; + + m_transType=0; + m_videoLen=0; + m_frametype=1; + m_metaTime=0; + + m_spsppsConf=NULL; + +} + +YangVideoStreamCapture::~YangVideoStreamCapture() { + m_videoBuffer = NULL; + yang_deleteA(m_videoBufs); + if(m_spsppsConf){ + yang_deleteA(m_spsppsConf->sps); + yang_deleteA(m_spsppsConf->pps); + yang_delete(m_spsppsConf); + } + + + +} + +void YangVideoStreamCapture::init(int32_t transtype) { + m_transType=transtype; + if(m_transType!=Yang_Webrtc){ + if(m_videoBufs==NULL) m_videoBufs = new uint8_t[1024 * 1024]; + m_videoBuffer = m_videoBufs + 20; + m_videoBuffer[1] = 0x01; + m_videoBuffer[2] = 0x00; + m_videoBuffer[3] = 0x00; + m_videoBuffer[4] = 0x00; + } +} +void YangVideoStreamCapture::initEncType(YangVideoEncDecType videoType, + int32_t frametype) { + if (frametype == 1) { + m_videoBuffer[0] = (videoType == Yang_VED_265 ? 0x1c : 0x17); + + } else { + m_videoBuffer[0] = (videoType == Yang_VED_265 ? 0x2c : 0x27); + } + m_videoBuffer[1] = 0x01; + m_videoBuffer[2] = 0x00; + m_videoBuffer[3] = 0x00; + m_videoBuffer[4] = 0x00; +} +void YangVideoStreamCapture::initSpspps(uint8_t *buf){ + + if(m_spsppsConf==NULL){ + m_spsppsConf=new YangSpsppsConf(); + int32_t spsLen = *(buf + 12) + 1; + uint8_t *sps = buf + 13; + int32_t ppsLen = *(sps + spsLen + 1) + 1; + uint8_t *pps = buf + 13 + spsLen + 2; + //spsLen++; + //ppsLen++; + m_spsppsConf->sps=new uint8_t[spsLen]; + m_spsppsConf->pps=new uint8_t[ppsLen]; + m_spsppsConf->spsLen=spsLen; + m_spsppsConf->ppsLen=ppsLen; + memcpy(m_spsppsConf->sps,sps,spsLen); + memcpy(m_spsppsConf->pps,pps,ppsLen); + + } + +} +void YangVideoStreamCapture::setVideoData(YangFrame* videoFrame, YangVideoEncDecType videoType) { + if(m_transType==Yang_Webrtc){ + + m_src=videoFrame->payload; + m_videoLen = videoFrame->nb; + + }else{ + initEncType(videoType, videoFrame->frametype); + yang_put_be32((char*) m_videoBuffer + 5, videoFrame->nb); + memcpy(m_videoBuffer + 9, videoFrame->payload, videoFrame->nb); + m_videoLen= videoFrame->nb + 9; + + } + + if (preTimestamp == 0) { + baseTimestamp = videoTimestamp; + curVideotimestamp = 0; + + } else { + if (videoTimestamp <= preTimestamp) + return; + + curVideotimestamp = videoTimestamp - baseTimestamp; + } + preTimestamp = videoTimestamp; + m_frametype=videoFrame->frametype; + //return m_videoBuffer; +} +void YangVideoStreamCapture::setVideoMeta(uint8_t *p, int32_t plen, YangVideoEncDecType videoType) { + + if(m_transType==Yang_Webrtc){ + m_src=p; + m_videoLen= plen; + initSpspps(p); + }else{ + memcpy(m_videoBuffer, p, plen); + m_videoLen= plen; + } +} +void YangVideoStreamCapture::setMetaTimestamp(int64_t timestamp){ + m_metaTime=timestamp; +} +void YangVideoStreamCapture::setFrametype(int32_t frametype){ + m_frametype=frametype; +} + +YangSpsppsConf* YangVideoStreamCapture::getSpsppsConf(){ + return m_spsppsConf; +} + +int32_t YangVideoStreamCapture::getFrametype(){ + return m_frametype; +} +int32_t YangVideoStreamCapture::getVideoLen(){ + return m_videoLen; +} + +int64_t YangVideoStreamCapture::getRtmpTimestamp() { + return curVideotimestamp / 1000; +} +int64_t YangVideoStreamCapture::getTimestamp(){ + if(m_transType==0){ + return curVideotimestamp / 1000; + } + return curVideotimestamp * 9 / 100; +} +int64_t YangVideoStreamCapture::getMetaTimestamp(){ + return m_metaTime; +} +int64_t YangVideoStreamCapture::getTsTimestamp() { + return curVideotimestamp * 9 / 100; +} +uint8_t* YangVideoStreamCapture::getVideoData() { + + return m_transType==Yang_Webrtc?m_src:m_videoBuffer; +} diff --git a/libyangrtc2/src/yangutil/YangAmf.cpp b/libyangrtc2/src/yangutil/YangAmf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec33e6428b188e07fee9112f6a766293a7436810 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangAmf.cpp @@ -0,0 +1,1273 @@ +#include "yangutil/sys/YangAmf.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "yangutil/sys/YangLog.h" +enum Yang_LogLevel { + Yang_LOGCRIT = 0, + Yang_LOGERROR, + Yang_LOGWARNING, + Yang_LOGINFO, + Yang_LOGDEBUG, + Yang_LOGDEBUG2, + Yang_LOGALL +}; +void Yang_Logs1(int32_t level, const char *format, ...) { + if (level > Yang_LOGERROR) + return; + char str[2048] = ""; + va_list args; + va_start(args, format); + vsnprintf(str, 2048 - 1, format, args); + va_end(args); +} +#ifdef _WIN32 +/* Windows is little endian only */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN +#define __FLOAT_WORD_ORDER __BYTE_ORDER + +typedef uint8_t uint8_t; + +#else /* !_WIN32 */ + +#include + +#if defined(BYTE_ORDER) && !defined(__BYTE_ORDER) +#define __BYTE_ORDER BYTE_ORDER +#endif + +#if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN) +#define __BIG_ENDIAN BIG_ENDIAN +#endif + +#if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#endif + +#endif /* !_WIN32 */ + +/* define default endianness */ +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN 1234 +#endif + +#ifndef __BIG_ENDIAN +#define __BIG_ENDIAN 4321 +#endif + +#ifndef __BYTE_ORDER +#warning "Byte order not defined on your system, assuming little endian!" +#define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* ok, we assume to have the same float word order and byte order if float word order is not defined */ +#ifndef __FLOAT_WORD_ORDER +#warning "Float word order not defined, assuming the same as byte order!" +#define __FLOAT_WORD_ORDER __BYTE_ORDER +#endif + +#if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER) +#error "Undefined byte or float word order!" +#endif + +#if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN +#error "Unknown/unsupported float word order!" +#endif + +#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN +#error "Unknown/unsupported byte order!" +#endif + +static const AMFObjectProperty AMFProp_Invalid = { { 0, 0 }, AMF_INVALID }; +static const AMFObject AMFObj_Invalid = { 0, 0 }; +static const AVal AV_empty = { 0, 0 }; + +/* Data is Big-Endian */ +unsigned short AMF_DecodeInt16(const char *data) { + uint8_t *c = (uint8_t*) data; + unsigned short val; + val = (c[0] << 8) | c[1]; + return val; +} + +uint32_t AMF_DecodeInt24(const char *data) { + uint8_t *c = (uint8_t*) data; + uint32_t val; + val = (c[0] << 16) | (c[1] << 8) | c[2]; + return val; +} + +uint32_t AMF_DecodeInt32(const char *data) { + uint8_t *c = (uint8_t*) data; + uint32_t val; + val = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; + return val; +} + +void AMF_DecodeString(const char *data, AVal *bv) { + bv->av_len = AMF_DecodeInt16(data); + bv->av_val = (bv->av_len > 0) ? (char*) data + 2 : NULL; +} + +void AMF_DecodeLongString(const char *data, AVal *bv) { + bv->av_len = AMF_DecodeInt32(data); + bv->av_val = (bv->av_len > 0) ? (char*) data + 4 : NULL; +} + +double AMF_DecodeNumber(const char *data) { + double dVal; +#if __FLOAT_WORD_ORDER == __BYTE_ORDER +#if __BYTE_ORDER == __BIG_ENDIAN + memcpy(&dVal, data, 8); +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t *ci, *co; + ci = (uint8_t*) data; + co = (uint8_t*) &dVal; + co[0] = ci[7]; + co[1] = ci[6]; + co[2] = ci[5]; + co[3] = ci[4]; + co[4] = ci[3]; + co[5] = ci[2]; + co[6] = ci[1]; + co[7] = ci[0]; +#endif +#else +#if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */ + uint8_t *ci, *co; + ci = (uint8_t *)data; + co = (uint8_t *)&dVal; + co[0] = ci[3]; + co[1] = ci[2]; + co[2] = ci[1]; + co[3] = ci[0]; + co[4] = ci[7]; + co[5] = ci[6]; + co[6] = ci[5]; + co[7] = ci[4]; +#else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */ + uint8_t *ci, *co; + ci = (uint8_t *)data; + co = (uint8_t *)&dVal; + co[0] = ci[4]; + co[1] = ci[5]; + co[2] = ci[6]; + co[3] = ci[7]; + co[4] = ci[0]; + co[5] = ci[1]; + co[6] = ci[2]; + co[7] = ci[3]; +#endif +#endif + return dVal; +} + +int32_t AMF_DecodeBoolean(const char *data) { + return *data != 0; +} + +char* +AMF_EncodeInt16(char *output, char *outend, short nVal) { + if (output + 2 > outend) + return NULL; + + output[1] = nVal & 0xff; + output[0] = nVal >> 8; + return output + 2; +} + +char* +AMF_EncodeInt24(char *output, char *outend, int32_t nVal) { + if (output + 3 > outend) + return NULL; + + output[2] = nVal & 0xff; + output[1] = nVal >> 8; + output[0] = nVal >> 16; + return output + 3; +} + +char* +AMF_EncodeInt32(char *output, char *outend, int32_t nVal) { + if (output + 4 > outend) + return NULL; + + output[3] = nVal & 0xff; + output[2] = nVal >> 8; + output[1] = nVal >> 16; + output[0] = nVal >> 24; + return output + 4; +} + +char* +AMF_EncodeString(char *output, char *outend, const AVal *bv) { + if ((bv->av_len < 65536 && output + 1 + 2 + bv->av_len > outend) + || output + 1 + 4 + bv->av_len > outend) + return NULL; + + if (bv->av_len < 65536) { + *output++ = AMF_STRING; + + output = AMF_EncodeInt16(output, outend, bv->av_len); + } else { + *output++ = AMF_LONG_STRING; + + output = AMF_EncodeInt32(output, outend, bv->av_len); + } + memcpy(output, bv->av_val, bv->av_len); + output += bv->av_len; + + return output; +} + +char* +AMF_EncodeNumber(char *output, char *outend, double dVal) { + if (output + 1 + 8 > outend) + return NULL; + + *output++ = AMF_NUMBER; /* type: Number */ + +#if __FLOAT_WORD_ORDER == __BYTE_ORDER +#if __BYTE_ORDER == __BIG_ENDIAN + memcpy(output, &dVal, 8); +#elif __BYTE_ORDER == __LITTLE_ENDIAN + { + uint8_t *ci, *co; + ci = (uint8_t*) &dVal; + co = (uint8_t*) output; + co[0] = ci[7]; + co[1] = ci[6]; + co[2] = ci[5]; + co[3] = ci[4]; + co[4] = ci[3]; + co[5] = ci[2]; + co[6] = ci[1]; + co[7] = ci[0]; + } +#endif +#else +#if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */ + { + uint8_t *ci, *co; + ci = (uint8_t *)&dVal; + co = (uint8_t *)output; + co[0] = ci[3]; + co[1] = ci[2]; + co[2] = ci[1]; + co[3] = ci[0]; + co[4] = ci[7]; + co[5] = ci[6]; + co[6] = ci[5]; + co[7] = ci[4]; + } +#else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */ + { + uint8_t *ci, *co; + ci = (uint8_t *)&dVal; + co = (uint8_t *)output; + co[0] = ci[4]; + co[1] = ci[5]; + co[2] = ci[6]; + co[3] = ci[7]; + co[4] = ci[0]; + co[5] = ci[1]; + co[6] = ci[2]; + co[7] = ci[3]; + } +#endif +#endif + + return output + 8; +} + +char* +AMF_EncodeBoolean(char *output, char *outend, int32_t bVal) { + if (output + 2 > outend) + return NULL; + + *output++ = AMF_BOOLEAN; + + *output++ = bVal ? 0x01 : 0x00; + + return output; +} + +char* +AMF_EncodeNamedString(char *output, char *outend, const AVal *strName, + const AVal *strValue) { + if (output + 2 + strName->av_len > outend) + return NULL; + output = AMF_EncodeInt16(output, outend, strName->av_len); + + memcpy(output, strName->av_val, strName->av_len); + output += strName->av_len; + + return AMF_EncodeString(output, outend, strValue); +} + +char* +AMF_EncodeNamedNumber(char *output, char *outend, const AVal *strName, + double dVal) { + if (output + 2 + strName->av_len > outend) + return NULL; + output = AMF_EncodeInt16(output, outend, strName->av_len); + + memcpy(output, strName->av_val, strName->av_len); + output += strName->av_len; + + return AMF_EncodeNumber(output, outend, dVal); +} + +char* +AMF_EncodeNamedBoolean(char *output, char *outend, const AVal *strName, + int32_t bVal) { + if (output + 2 + strName->av_len > outend) + return NULL; + output = AMF_EncodeInt16(output, outend, strName->av_len); + + memcpy(output, strName->av_val, strName->av_len); + output += strName->av_len; + + return AMF_EncodeBoolean(output, outend, bVal); +} + +void AMFProp_GetName(AMFObjectProperty *prop, AVal *name) { + *name = prop->p_name; +} + +void AMFProp_SetName(AMFObjectProperty *prop, AVal *name) { + prop->p_name = *name; +} + +AMFDataType AMFProp_GetType(AMFObjectProperty *prop) { + return prop->p_type; +} + +double AMFProp_GetNumber(AMFObjectProperty *prop) { + return prop->p_vu.p_number; +} + +int32_t AMFProp_GetBoolean(AMFObjectProperty *prop) { + return prop->p_vu.p_number != 0; +} + +void AMFProp_GetString(AMFObjectProperty *prop, AVal *str) { + if (prop->p_type == AMF_STRING) + *str = prop->p_vu.p_aval; + else + *str = AV_empty; +} + +void AMFProp_GetObject(AMFObjectProperty *prop, AMFObject *obj) { + if (prop->p_type == AMF_OBJECT) + *obj = prop->p_vu.p_object; + else + *obj = AMFObj_Invalid; +} + +int32_t AMFProp_IsValid(AMFObjectProperty *prop) { + return prop->p_type != AMF_INVALID; +} + +char* +AMFProp_Encode(AMFObjectProperty *prop, char *pBuffer, char *pBufEnd) { + if (prop->p_type == AMF_INVALID) + return NULL; + + if (prop->p_type != AMF_NULL + && pBuffer + prop->p_name.av_len + 2 + 1 >= pBufEnd) + return NULL; + + if (prop->p_type != AMF_NULL && prop->p_name.av_len) { + *pBuffer++ = prop->p_name.av_len >> 8; + *pBuffer++ = prop->p_name.av_len & 0xff; + memcpy(pBuffer, prop->p_name.av_val, prop->p_name.av_len); + pBuffer += prop->p_name.av_len; + } + + switch (prop->p_type) { + case AMF_NUMBER: + pBuffer = AMF_EncodeNumber(pBuffer, pBufEnd, prop->p_vu.p_number); + break; + + case AMF_BOOLEAN: + pBuffer = AMF_EncodeBoolean(pBuffer, pBufEnd, prop->p_vu.p_number != 0); + break; + + case AMF_STRING: + pBuffer = AMF_EncodeString(pBuffer, pBufEnd, &prop->p_vu.p_aval); + break; + + case AMF_NULL: + if (pBuffer + 1 >= pBufEnd) + return NULL; + *pBuffer++ = AMF_NULL; + break; + + case AMF_OBJECT: + pBuffer = AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd); + break; + + case AMF_ECMA_ARRAY: + pBuffer = AMF_EncodeEcmaArray(&prop->p_vu.p_object, pBuffer, pBufEnd); + break; + + case AMF_STRICT_ARRAY: + pBuffer = AMF_EncodeArray(&prop->p_vu.p_object, pBuffer, pBufEnd); + break; + + default: + Yang_Logs1(Yang_LOGERROR, "%s, invalid type. %d", __FUNCTION__, + prop->p_type); + pBuffer = NULL; + }; + + return pBuffer; +} + +#define AMF3_INTEGER_MAX 268435455 +#define AMF3_INTEGER_MIN -268435456 + +int32_t AMF3ReadInteger(const char *data, int32_t *valp) { + int32_t i = 0; + int32_t val = 0; + + while (i <= 2) { /* handle first 3 bytes */ + if (data[i] & 0x80) { /* byte used */ + val <<= 7; /* shift up */ + val |= (data[i] & 0x7f); /* add bits */ + i++; + } else { + break; + } + } + + if (i > 2) { /* use 4th byte, all 8bits */ + val <<= 8; + val |= data[3]; + + /* range check */ + if (val > AMF3_INTEGER_MAX) + val -= (1 << 29); + } else { /* use 7bits of last unparsed byte (0xxxxxxx) */ + val <<= 7; + val |= data[i]; + } + + *valp = val; + + return i > 2 ? 4 : i + 1; +} + +int32_t AMF3ReadString(const char *data, AVal *str) { + int32_t ref = 0; + int32_t len; + assert(str != 0); + + len = AMF3ReadInteger(data, &ref); + data += len; + + if ((ref & 0x1) == 0) { /* reference: 0xxx */ + uint32_t refIndex = (ref >> 1); + Yang_Logs1(Yang_LOGDEBUG, + "%s, string reference, index: %d, not supported, ignoring!", + __FUNCTION__, refIndex); + str->av_val = NULL; + str->av_len = 0; + return len; + } else { + uint32_t nSize = (ref >> 1); + + str->av_val = (char*) data; + str->av_len = nSize; + + return len + nSize; + } + return len; +} + +int32_t AMF3Prop_Decode(AMFObjectProperty *prop, const char *pBuffer, int32_t nSize, + int32_t bDecodeName) { + int32_t nOriginalSize = nSize; + AMF3DataType type; + + prop->p_name.av_len = 0; + prop->p_name.av_val = NULL; + + if (nSize == 0 || !pBuffer) { + Yang_Logs1(Yang_LOGDEBUG, "empty buffer/no buffer pointer!"); + return -1; + } + + /* decode name */ + if (bDecodeName) { + AVal name; + int32_t nRes = AMF3ReadString(pBuffer, &name); + + if (name.av_len <= 0) + return nRes; + + nSize -= nRes; + if (nSize <= 0) + return -1; + prop->p_name = name; + pBuffer += nRes; + } + + /* decode */ + type = (AMF3DataType) *pBuffer++; + nSize--; + + switch (type) { + case AMF3_UNDEFINED: + case AMF3_NULL: + prop->p_type = AMF_NULL; + break; + case AMF3_FALSE: + prop->p_type = AMF_BOOLEAN; + prop->p_vu.p_number = 0.0; + break; + case AMF3_TRUE: + prop->p_type = AMF_BOOLEAN; + prop->p_vu.p_number = 1.0; + break; + case AMF3_INTEGER: { + int32_t res = 0; + int32_t len = AMF3ReadInteger(pBuffer, &res); + prop->p_vu.p_number = (double) res; + prop->p_type = AMF_NUMBER; + nSize -= len; + break; + } + case AMF3_DOUBLE: + if (nSize < 8) + return -1; + prop->p_vu.p_number = AMF_DecodeNumber(pBuffer); + prop->p_type = AMF_NUMBER; + nSize -= 8; + break; + case AMF3_STRING: + case AMF3_XML_DOC: + case AMF3_XML: { + int32_t len = AMF3ReadString(pBuffer, &prop->p_vu.p_aval); + prop->p_type = AMF_STRING; + nSize -= len; + break; + } + case AMF3_DATE: { + int32_t res = 0; + int32_t len = AMF3ReadInteger(pBuffer, &res); + + nSize -= len; + pBuffer += len; + + if ((res & 0x1) == 0) { /* reference */ + uint32_t nIndex = (res >> 1); + Yang_Logs1(Yang_LOGDEBUG, "AMF3_DATE reference: %d, not supported!", + nIndex); + } else { + if (nSize < 8) + return -1; + + prop->p_vu.p_number = AMF_DecodeNumber(pBuffer); + nSize -= 8; + prop->p_type = AMF_NUMBER; + } + break; + } + case AMF3_OBJECT: { + int32_t nRes = AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); + if (nRes == -1) + return -1; + nSize -= nRes; + prop->p_type = AMF_OBJECT; + break; + } + case AMF3_ARRAY: + case AMF3_BYTE_ARRAY: + default: + Yang_Logs1(Yang_LOGDEBUG, + "%s - AMF3 unknown/unsupported datatype 0x%02x, @%p", + __FUNCTION__, (uint8_t) (*pBuffer), pBuffer); + return -1; + } + if (nSize < 0) + return -1; + + return nOriginalSize - nSize; +} + +int32_t AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int32_t nSize, + int32_t bDecodeName) { + int32_t nOriginalSize = nSize; + int32_t nRes; + + prop->p_name.av_len = 0; + prop->p_name.av_val = NULL; + + if (nSize == 0 || !pBuffer) { + Yang_Logs1(Yang_LOGDEBUG, "%s: Empty buffer/no buffer pointer!", + __FUNCTION__); + return -1; + } + + if (bDecodeName && nSize < 4) { /* at least name (length + at least 1 byte) and 1 byte of data */ + Yang_Logs1(Yang_LOGDEBUG, + "%s: Not enough data for decoding with name, less than 4 bytes!", + __FUNCTION__); + return -1; + } + + if (bDecodeName) { + unsigned short nNameSize = AMF_DecodeInt16(pBuffer); + if (nNameSize > nSize - 2) { + Yang_Logs1(Yang_LOGDEBUG, + "%s: Name size out of range: namesize (%d) > len (%d) - 2", + __FUNCTION__, nNameSize, nSize); + return -1; + } + + AMF_DecodeString(pBuffer, &prop->p_name); + nSize -= 2 + nNameSize; + pBuffer += 2 + nNameSize; + } + + if (nSize == 0) { + return -1; + } + + nSize--; + + prop->p_type = (AMFDataType) (*pBuffer++); + switch (prop->p_type) { + case AMF_NUMBER: + if (nSize < 8) + return -1; + prop->p_vu.p_number = AMF_DecodeNumber(pBuffer); + nSize -= 8; + break; + case AMF_BOOLEAN: + if (nSize < 1) + return -1; + prop->p_vu.p_number = (double) AMF_DecodeBoolean(pBuffer); + nSize--; + break; + case AMF_STRING: { + unsigned short nStringSize = AMF_DecodeInt16(pBuffer); + + if (nSize < (long) nStringSize + 2) + return -1; + AMF_DecodeString(pBuffer, &prop->p_vu.p_aval); + nSize -= (2 + nStringSize); + break; + } + case AMF_OBJECT: { + int32_t nRes = AMF_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); + if (nRes == -1) + return -1; + nSize -= nRes; + break; + } + case AMF_MOVIECLIP: { + Yang_Logs1(Yang_LOGERROR, "AMF_MOVIECLIP reserved!"); + return -1; + break; + } + case AMF_NULL: + case AMF_UNDEFINED: + case AMF_UNSUPPORTED: + prop->p_type = AMF_NULL; + break; + case AMF_REFERENCE: { + Yang_Logs1(Yang_LOGERROR, "AMF_REFERENCE not supported!"); + return -1; + break; + } + case AMF_ECMA_ARRAY: { + nSize -= 4; + + /* next comes the rest, mixed array has a final 0x000009 mark and names, so its an object */ + + nRes = AMF_Decode(&prop->p_vu.p_object, pBuffer + 4, nSize, TRUE); + //printf("\n%d....................AMF_ECMA_ARRAY\n",nRes); + if (nRes == -1) + return -1; + nSize -= nRes; + break; + } + case AMF_OBJECT_END: { + return -1; + break; + } + case AMF_STRICT_ARRAY: { + uint32_t nArrayLen = AMF_DecodeInt32(pBuffer); + nSize -= 4; + + nRes = AMF_DecodeArray(&prop->p_vu.p_object, pBuffer + 4, nSize, + nArrayLen, FALSE); + if (nRes == -1) + return -1; + nSize -= nRes; + break; + } + case AMF_DATE: { + Yang_Logs1(Yang_LOGDEBUG, "AMF_DATE"); + + if (nSize < 10) + return -1; + + prop->p_vu.p_number = AMF_DecodeNumber(pBuffer); + prop->p_UTCoffset = AMF_DecodeInt16(pBuffer + 8); + + nSize -= 10; + break; + } + case AMF_LONG_STRING: + case AMF_XML_DOC: { + uint32_t nStringSize = AMF_DecodeInt32(pBuffer); + if (nSize < (long) nStringSize + 4) + return -1; + AMF_DecodeLongString(pBuffer, &prop->p_vu.p_aval); + nSize -= (4 + nStringSize); + if (prop->p_type == AMF_LONG_STRING) + prop->p_type = AMF_STRING; + break; + } + case AMF_RECORDSET: { + Yang_Logs1(Yang_LOGERROR, "AMF_RECORDSET reserved!"); + return -1; + break; + } + case AMF_TYPED_OBJECT: { + Yang_Logs1(Yang_LOGERROR, "AMF_TYPED_OBJECT not supported!"); + return -1; + break; + } + case AMF_AVMPLUS: { + int32_t nRes = AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); + if (nRes == -1) + return -1; + nSize -= nRes; + prop->p_type = AMF_OBJECT; + break; + } + default: + Yang_Logs1(Yang_LOGDEBUG, "%s - unknown datatype 0x%02x, @%p", + __FUNCTION__, prop->p_type, pBuffer - 1); + return -1; + } + + return nOriginalSize - nSize; +} + +void AMFProp_Dump(AMFObjectProperty *prop) { + char strRes[256]; + char str[256]; + AVal name; + + if (prop->p_type == AMF_INVALID) { + Yang_Logs1(Yang_LOGDEBUG, "Property: INVALID"); + return; + } + + if (prop->p_type == AMF_NULL) { + Yang_Logs1(Yang_LOGDEBUG, "Property: NULL"); + return; + } + + if (prop->p_name.av_len) { + name = prop->p_name; + } else { + name.av_val = (char*)"no-name."; + name.av_len = sizeof("no-name.") - 1; + } + if (name.av_len > 18) + name.av_len = 18; + + snprintf(strRes, 255, "Name: %18.*s, ", name.av_len, name.av_val); + + if (prop->p_type == AMF_OBJECT) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sOBJECT>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } else if (prop->p_type == AMF_ECMA_ARRAY) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sECMA_ARRAY>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } else if (prop->p_type == AMF_STRICT_ARRAY) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sSTRICT_ARRAY>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } + + switch (prop->p_type) { + case AMF_NUMBER: + snprintf(str, 255, "NUMBER:\t%.2f", prop->p_vu.p_number); + break; + case AMF_BOOLEAN: + snprintf(str, 255, "BOOLEAN:\t%s", + prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE"); + break; + case AMF_STRING: + snprintf(str, 255, "STRING:\t%.*s", prop->p_vu.p_aval.av_len, + prop->p_vu.p_aval.av_val); + break; + case AMF_DATE: + snprintf(str, 255, "DATE:\ttimestamp: %.2f, UTC offset: %d", + prop->p_vu.p_number, prop->p_UTCoffset); + break; + default: + snprintf(str, 255, "INVALID TYPE 0x%02x", (uint8_t) prop->p_type); + } + + Yang_Logs1(Yang_LOGDEBUG, "Property: <%s%s>", strRes, str); +} +void AMFProp_Dump1(AMFObjectProperty *prop) { + char strRes[256]; + char str[256]; + AVal name; + + if (prop->p_type == AMF_INVALID) { + Yang_Logs1(Yang_LOGDEBUG, "Property: INVALID"); + return; + } + + if (prop->p_type == AMF_NULL) { + Yang_Logs1(Yang_LOGDEBUG, "Property: NULL"); + return; + } + + if (prop->p_name.av_len) { + name = prop->p_name; + } else { + name.av_val =(char*) "no-name."; + name.av_len = sizeof("no-name.") - 1; + } + if (name.av_len > 18) + name.av_len = 18; + + snprintf(strRes, 255, "Name: %18.*s, ", name.av_len, name.av_val); + + if (prop->p_type == AMF_OBJECT) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sOBJECT>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } else if (prop->p_type == AMF_ECMA_ARRAY) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sECMA_ARRAY>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } else if (prop->p_type == AMF_STRICT_ARRAY) { + Yang_Logs1(Yang_LOGDEBUG, "Property: <%sSTRICT_ARRAY>", strRes); + AMF_Dump(&prop->p_vu.p_object); + return; + } + + switch (prop->p_type) { + case AMF_NUMBER: + snprintf(str, 255, "NUMBER:\t%.2f", prop->p_vu.p_number); + break; + case AMF_BOOLEAN: + snprintf(str, 255, "BOOLEAN:\t%s", + prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE"); + break; + case AMF_STRING: + snprintf(str, 255, "STRING:\t%.*s", prop->p_vu.p_aval.av_len, + prop->p_vu.p_aval.av_val); + break; + case AMF_DATE: + snprintf(str, 255, "DATE:\ttimestamp: %.2f, UTC offset: %d", + prop->p_vu.p_number, prop->p_UTCoffset); + break; + default: + snprintf(str, 255, "INVALID TYPE 0x%02x", (uint8_t) prop->p_type); + } + + Yang_Logs1(Yang_LOGERROR, "Property: <%s%s>", strRes, str); +} +void AMFProp_Reset(AMFObjectProperty *prop) { + if (prop->p_type == AMF_OBJECT || prop->p_type == AMF_ECMA_ARRAY + || prop->p_type == AMF_STRICT_ARRAY) + AMF_Reset(&prop->p_vu.p_object); + else { + prop->p_vu.p_aval.av_len = 0; + prop->p_vu.p_aval.av_val = NULL; + } + prop->p_type = AMF_INVALID; +} + +/* AMFObject */ + +char* +AMF_Encode(AMFObject *obj, char *pBuffer, char *pBufEnd) { + int32_t i; + + if (pBuffer + 4 >= pBufEnd) + return NULL; + + *pBuffer++ = AMF_OBJECT; + + for (i = 0; i < obj->o_num; i++) { + char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); + if (res == NULL) { + Yang_Logs1(Yang_LOGERROR, + "AMF_Encode - failed to encode property in index %d", i); + break; + } else { + pBuffer = res; + } + } + + if (pBuffer + 3 >= pBufEnd) + return NULL; /* no room for the end marker */ + + pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END); + + return pBuffer; +} + +char* +AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd) { + int32_t i; + + if (pBuffer + 4 >= pBufEnd) + return NULL; + + *pBuffer++ = AMF_ECMA_ARRAY; + + pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num); + + for (i = 0; i < obj->o_num; i++) { + char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); + if (res == NULL) { + Yang_Logs1(Yang_LOGERROR, + "AMF_Encode - failed to encode property in index %d", i); + break; + } else { + pBuffer = res; + } + } + + if (pBuffer + 3 >= pBufEnd) + return NULL; /* no room for the end marker */ + + pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END); + + return pBuffer; +} + +char* +AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd) { + int32_t i; + + if (pBuffer + 4 >= pBufEnd) + return NULL; + + *pBuffer++ = AMF_STRICT_ARRAY; + + pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num); + + for (i = 0; i < obj->o_num; i++) { + char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); + if (res == NULL) { + Yang_Logs1(Yang_LOGERROR, + "AMF_Encode - failed to encode property in index %d", i); + break; + } else { + pBuffer = res; + } + } + + //if (pBuffer + 3 >= pBufEnd) + // return NULL; /* no room for the end marker */ + + //pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END); + + return pBuffer; +} + +int32_t AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int32_t nSize, + int32_t nArrayLen, int32_t bDecodeName) { + int32_t nOriginalSize = nSize; + int32_t bError = FALSE; + + obj->o_num = 0; + obj->o_props = NULL; + while (nArrayLen > 0) { + AMFObjectProperty prop; + int32_t nRes; + nArrayLen--; + + if (nSize <= 0) { + bError = TRUE; + break; + } + nRes = AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName); + if (nRes == -1) { + bError = TRUE; + break; + } else { + nSize -= nRes; + pBuffer += nRes; + AMF_AddProp(obj, &prop); + } + } + if (bError) + return -1; + + return nOriginalSize - nSize; +} + +int32_t AMF3_Decode(AMFObject *obj, const char *pBuffer, int32_t nSize, int32_t bAMFData) { + int32_t nOriginalSize = nSize; + int32_t ref; + int32_t len; + + obj->o_num = 0; + obj->o_props = NULL; + if (bAMFData) { + if (*pBuffer != AMF3_OBJECT) + Yang_Logs1(Yang_LOGERROR, + "AMF3 Object encapsulated in AMF stream does not start with AMF3_OBJECT!"); + pBuffer++; + nSize--; + } + + ref = 0; + len = AMF3ReadInteger(pBuffer, &ref); + pBuffer += len; + nSize -= len; + + if ((ref & 1) == 0) { /* object reference, 0xxx */ + uint32_t objectIndex = (ref >> 1); + + Yang_Logs1(Yang_LOGDEBUG, "Object reference, index: %d", objectIndex); + } else /* object instance */ + { + int32_t classRef = (ref >> 1); + + AMF3ClassDef cd = { { 0, 0 } }; + AMFObjectProperty prop; + + if ((classRef & 0x1) == 0) { /* class reference */ + uint32_t classIndex = (classRef >> 1); + Yang_Logs1(Yang_LOGDEBUG, "Class reference: %d", classIndex); + } else { + int32_t classExtRef = (classRef >> 1); + int32_t i, cdnum; + + cd.cd_externalizable = (classExtRef & 0x1) == 1; + cd.cd_dynamic = ((classExtRef >> 1) & 0x1) == 1; + + cdnum = classExtRef >> 2; + + /* class name */ + + len = AMF3ReadString(pBuffer, &cd.cd_name); + nSize -= len; + pBuffer += len; + + /*std::string str = className; */ + + Yang_Logs1(Yang_LOGDEBUG, + "Class name: %s, externalizable: %d, dynamic: %d, classMembers: %d", + cd.cd_name.av_val, cd.cd_externalizable, cd.cd_dynamic, + cd.cd_num); + + for (i = 0; i < cdnum; i++) { + AVal memberName; + if (nSize <= 0) { + + return nOriginalSize; + } + len = AMF3ReadString(pBuffer, &memberName); + Yang_Logs1(Yang_LOGDEBUG, "Member: %s", memberName.av_val); + AMF3CD_AddProp(&cd, &memberName); + nSize -= len; + pBuffer += len; + } + } + + /* add as referencable object */ + + if (cd.cd_externalizable) { + int32_t nRes; + AVal name = AVC("DEFAULT_ATTRIBUTE"); + + Yang_Logs1(Yang_LOGDEBUG, "Externalizable, TODO check"); + + nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE); + if (nRes == -1) + Yang_Logs1(Yang_LOGDEBUG, "%s, failed to decode AMF3 property!", + __FUNCTION__); + else { + nSize -= nRes; + pBuffer += nRes; + } + + AMFProp_SetName(&prop, &name); + AMF_AddProp(obj, &prop); + } else { + int32_t nRes, i; + for (i = 0; i < cd.cd_num; i++) /* non-dynamic */ + { + if (nSize <= 0) + goto invalid; + nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE); + if (nRes == -1) + Yang_Logs1(Yang_LOGDEBUG, + "%s, failed to decode AMF3 property!", + __FUNCTION__); + + AMFProp_SetName(&prop, AMF3CD_GetProp(&cd, i)); + AMF_AddProp(obj, &prop); + + pBuffer += nRes; + nSize -= nRes; + } + if (cd.cd_dynamic) { + int32_t len = 0; + + do { + if (nSize <= 0) + goto invalid; + nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, TRUE); + AMF_AddProp(obj, &prop); + + pBuffer += nRes; + nSize -= nRes; + + len = prop.p_name.av_len; + } while (len > 0); + } + } + Yang_Logs1(Yang_LOGDEBUG, "class object!"); + } + invalid: Yang_Logs1(Yang_LOGDEBUG, "%s, invalid class encoding!", + __FUNCTION__); + + return nOriginalSize - nSize; +} + +int32_t AMF_Decode(AMFObject *obj, const char *pBuffer, int32_t nSize,int32_t bDecodeName) { + int32_t nOriginalSize = nSize; + int32_t bError = FALSE; /* if there is an error while decoding - try to at least find the end mark AMF_OBJECT_END */ + + obj->o_num = 0; + obj->o_props = NULL; + while (nSize > 0) { + AMFObjectProperty prop; + int32_t nRes; + + if (nSize >= 3 && AMF_DecodeInt24(pBuffer) == AMF_OBJECT_END) { + nSize -= 3; + bError = FALSE; + break; + } + + if (bError) { + Yang_Logs1(Yang_LOGERROR, + "DECODING ERROR, IGNORING BYTES UNTIL NEXT KNOWN PATTERN!"); + nSize--; + pBuffer++; + continue; + } + + nRes = AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName); + //printf("\nnRes====================%d\n",nRes); + if (nRes == -1) { + bError = TRUE; + break; + } else { + nSize -= nRes; + if (nSize < 0) { + bError = TRUE; + break; + } + pBuffer += nRes; + AMF_AddProp(obj, &prop); + } + } + + if (bError) + return -1; + + return nOriginalSize - nSize; +} + +void AMF_AddProp(AMFObject *obj, const AMFObjectProperty *prop) { + if (!(obj->o_num & 0x0f)) + obj->o_props = (struct AMFObjectProperty*) realloc(obj->o_props, + (obj->o_num + 16) * sizeof(AMFObjectProperty)); + memcpy(&obj->o_props[obj->o_num++], prop, sizeof(AMFObjectProperty)); +} + +int32_t AMF_CountProp(AMFObject *obj) { + return obj->o_num; +} + +AMFObjectProperty* +AMF_GetProp(AMFObject *obj, const AVal *name, int32_t nIndex) { + if (nIndex >= 0) { + if (nIndex < obj->o_num) + return &obj->o_props[nIndex]; + } else { + int32_t n; + for (n = 0; n < obj->o_num; n++) { + if (AVMATCH(&obj->o_props[n].p_name, name)) + return &obj->o_props[n]; + } + } + + return (AMFObjectProperty*) &AMFProp_Invalid; +} + +void AMF_Dump(AMFObject *obj) { + int32_t n; + Yang_Logs1(Yang_LOGDEBUG, "(object begin)"); + for (n = 0; n < obj->o_num; n++) { + AMFProp_Dump(&obj->o_props[n]); + } + Yang_Logs1(Yang_LOGDEBUG, "(object end)"); +} +void AMF_Dump1(AMFObject *obj) { + int32_t n; + Yang_Logs1(Yang_LOGERROR, "(object begin)"); + for (n = 0; n < obj->o_num; n++) { + AMFProp_Dump1(&obj->o_props[n]); + } + Yang_Logs1(Yang_LOGERROR, "(object end)"); +} +void AMF_Reset(AMFObject *obj) { + int32_t n; + for (n = 0; n < obj->o_num; n++) { + AMFProp_Reset(&obj->o_props[n]); + } + free(obj->o_props); + obj->o_props = NULL; + obj->o_num = 0; +} + +/* AMF3ClassDefinition */ + +void AMF3CD_AddProp(AMF3ClassDef *cd, AVal *prop) { + if (!(cd->cd_num & 0x0f)) + cd->cd_props = (AVal*) realloc(cd->cd_props, + (cd->cd_num + 16) * sizeof(AVal)); + cd->cd_props[cd->cd_num++] = *prop; +} + +AVal* +AMF3CD_GetProp(AMF3ClassDef *cd, int32_t nIndex) { + if (nIndex >= cd->cd_num) + return (AVal*) &AV_empty; + return &cd->cd_props[nIndex]; +} + diff --git a/libyangrtc2/src/yangutil/YangAvinfo.cpp b/libyangrtc2/src/yangutil/YangAvinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d4efd7780e234ef8c312064f407792403802aca --- /dev/null +++ b/libyangrtc2/src/yangutil/YangAvinfo.cpp @@ -0,0 +1,157 @@ +/* + * YangAvinfo.cpp + * + * Created on: 2021年10月2日 + * Author: yang + */ +#include +#include +#include +#include +#include +#include + +class YangInitContext { +public: + YangInitContext() { + } + + ~YangInitContext() { + } + + void initVideo(YangVideoInfo *video) { + video->width = 1280; + video->height = 720; + video->outWidth = 1280; + video->outHeight = 720; + video->rate = 2048; + video->frame = 10; + + video->bitDepth = 8; + + video->videoCacheNum = 10; + video->evideoCacheNum = 10; + video->videoPlayCacheNum = 5; + + video->videoCaptureFormat = YangYuy2; + video->videoEncoderFormat = YangI420; + video->videoDecoderFormat = YangI420; + + video->videoEncoderType = 0; + video->videoDecoderType = 0; + video->videoEncHwType = 0; + video->videoDecHwType = 0; + video->vIndex = 0; + } + void initAudio(YangAudioInfo *audio) { + audio->sample = 48000; + audio->frameSize = 960; + audio->channel = 2; + audio->bitrate = 128; + audio->usingMono = 0; + audio->hasAec = 0; + audio->echoPath = 10; + audio->aecBufferFrames = 0; + audio->hasAudioHeader = 0; + audio->audioEncoderType = 3; + audio->audioDecoderType = 3; + audio->audioPlayType = 0; + audio->audioCacheNum = 10; + audio->audioCacheSize = 10; + audio->audioPlayCacheNum = 10; + + audio->aIndex = -1; + audio->aSubIndex = 0; + //aSubIndex + + } + void initSys(YangSysInfo *sys) { + + sys->transType = 2; + sys->isMultCamera = 0; + sys->usingDataServer = 0; + + sys->rtmpPort = 1935; + sys->srtPort = 8080; + sys->rtcPort = 1985; + sys->rtcLocalPort = 16000; + sys->httpPort = 8080; + sys->dataPort = 9999; + sys->hasLogFile = 0; + sys->logLevel = 1; + sys->logLevel = 1; + sys->cameraCount = 3; + strcpy(sys->cameraIndexs, "1"); + strcpy(sys->rtmpServerIP, "127.0.0.1"); + strcpy(sys->srtServerIP, "127.0.0.1"); + strcpy(sys->rtcServerIP, "127.0.0.1"); + strcpy(sys->httpServerIP, "127.0.0.1"); + strcpy(sys->dataServerIP, "127.0.0.1"); + } + void initEnc(YangVideoEncInfo *enc) { + enc->preset = 3; + enc->level_idc = 31; + enc->profile = 0; + enc->keyint_max = 30; + enc->enc_threads = 4; + enc->gop=60; + enc->createMeta=true; + + } + void initRtc(YangRtcInfo *rtc) { + rtc->sendTwcc = 0; + rtc->mixAvqueue = 1; + rtc->audioQueueCount = 5; + rtc->videoQueueCount = 5; + } +}; + +YangContext::YangContext() { + init(); + m_certificate=NULL; +} + +YangContext::~YangContext() { + yang_closeLogFile(); + yang_delete(m_certificate); +} +void YangContext::init(char *filename) { + YangIni ini; + ini.init(filename); + ini.initAudio(&audio); + ini.initVideo(&video); + ini.initSys(&sys); + ini.initEnc(&enc); + ini.initRtc(&rtc); + initExt(&ini); +} + +void YangContext::init() { + memset(&video, 0, sizeof(YangVideoInfo)); + memset(&audio, 0, sizeof(YangAudioInfo)); + memset(&sys, 0, sizeof(YangSysInfo)); + memset(&enc, 0, sizeof(YangVideoEncInfo)); + memset(&rtc, 0, sizeof(YangRtcInfo)); + YangInitContext ini; + + ini.initAudio(&audio); + ini.initVideo(&video); + ini.initSys(&sys); + ini.initEnc(&enc); + ini.initRtc(&rtc); + initExt(); +} + +YangCertificate* YangContext::getCertificate(){ + if(m_certificate==NULL){ + m_certificate=new YangCertificateImpl(); + if(m_certificate->init()) yang_error("certificate init error!"); + } + return m_certificate; +} +void YangContext::initExt() { + +} +void YangContext::initExt(void *filename) { + +} diff --git a/libyangrtc2/src/yangutil/YangAvtype.cpp b/libyangrtc2/src/yangutil/YangAvtype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb58363ccd5fbeb801dd4a462dab324c136cf9ea --- /dev/null +++ b/libyangrtc2/src/yangutil/YangAvtype.cpp @@ -0,0 +1,99 @@ +#include +#include +#include + +#include +void yang_frame_copy_nobuffer(YangFrame *src, YangFrame *dst) { + if (!src || !dst) return; + dst->mediaType = src->mediaType; + dst->uid = src->uid; + dst->frametype = src->frametype; + dst->nb = src->nb; + dst->timestamp = src->timestamp; +} +void yang_frame_copy(YangFrame *src, YangFrame *dst) { + if (!src || !dst) return; + dst->mediaType = src->mediaType; + dst->uid = src->uid; + dst->frametype = src->frametype; + dst->nb = src->nb; + dst->timestamp = src->timestamp; + dst->payload = src->payload; +} +void yang_frame_copy_buffer(YangFrame *src, YangFrame *dst) { + if (!src || !dst) return; + dst->mediaType = src->mediaType; + dst->uid = src->uid; + dst->frametype = src->frametype; + dst->nb = src->nb; + dst->timestamp = src->timestamp; + if (src->payload && dst->payload) + memcpy(dst->payload, src->payload, src->nb); +} +/** + void yang_frame_init(YangFrame* dst){ + if(!dst) return; + dst->mediaType=0; + dst->uid=0; + dst->frametype=0; + dst->nb=0; + dst->timestamp=0; + dst->payload=NULL; + + + }**/ + +/** +YangSample::YangSample() { + m_size = 0; + m_bytes = NULL; + +} + +YangSample::YangSample(char *b, int32_t s) { + m_size = s; + m_bytes = b; + +} + +YangSample::~YangSample() { +} + +YangSample* YangSample::copy() { + YangSample *p = new YangSample(); + p->m_bytes = m_bytes; + p->m_size = m_size; + + return p; +} +**/ +YangBufferManager::YangBufferManager() { + m_curindex = 0; + m_size = 0; + m_unitsize = 0; + m_cache = NULL; +} +YangBufferManager::YangBufferManager(int32_t num, int32_t unitsize) { + m_curindex = 0; + m_size = 0; + m_unitsize = 0; + m_cache = NULL; + init(num, unitsize); +} +YangBufferManager::~YangBufferManager() { + yang_deleteA(m_cache); +} + +void YangBufferManager::init(int32_t num, int32_t unitsize) { + m_size = num; + m_unitsize = unitsize; + if (m_cache == NULL) + m_cache = new uint8_t[m_unitsize * m_size]; +} +uint8_t* YangBufferManager::getBuffer() { + if (!m_cache) + return NULL; + if (m_curindex >= m_size) + m_curindex = 0; + return m_cache + m_unitsize * m_curindex++; +} diff --git a/libyangrtc2/src/yangutil/YangEndian.cpp b/libyangrtc2/src/yangutil/YangEndian.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bb902c16b4d1512d436d2b94d0f645905b85f2e --- /dev/null +++ b/libyangrtc2/src/yangutil/YangEndian.cpp @@ -0,0 +1,78 @@ +/* + * YangCommon.cpp + * + * Created on: 2019年7月20日 + * Author: yang + */ + +#include +#include +#include +#include + + +char * yang_put_amf_string( char *c, const char *str ) +{ + unsigned short len = strlen( str ); + c=yang_put_be16( c, len ); + memcpy(c,str,len); + return c+len; +} +char * yang_put_amf_double( char *c, double d ) +{ + *c++ = 0; /* type: Number */ + { + uint8_t *ci, *co; + ci = (uint8_t *)&d; + co = (uint8_t *)c; + co[0] = ci[7]; + co[1] = ci[6]; + co[2] = ci[5]; + co[3] = ci[4]; + co[4] = ci[3]; + co[5] = ci[2]; + co[6] = ci[1]; + co[7] = ci[0]; + } + return c+8; +} +char * yang_put_byte( char *output, uint8_t nVal ) +{ + output[0] = nVal; + return output+1; +} +char * yang_put_be16(char *output, unsigned short nVal ) +{ + output[1] = nVal & 0xff; + output[0] = nVal >> 8; + return output+2; +} +char * yang_put_be24(char *output,uint32_t nVal ) +{ + output[2] = nVal & 0xff; + output[1] = nVal >> 8; + output[0] = nVal >> 16; + return output+3; +} +char * yang_put_be32(char *output, uint32_t nVal ) +{ + output[3] = nVal & 0xff; + output[2] = nVal >> 8; + output[1] = nVal >> 16; + output[0] = nVal >> 24; + return output+4; +} +char * yang_put_be64( char *output, unsigned long nVal ) +{ + output=yang_put_be32( output, nVal >> 32 ); + output=yang_put_be32( output, nVal ); + return output; +} + +uint32_t yang_get_be32(uint8_t *output) { + return output[3]|output[2]<<8|output[1]<<16|output[0]<<24; +} + +uint16_t yang_get_be16(uint8_t *output) { + return output[1]|output[0]<<8; +} diff --git a/libyangrtc2/src/yangutil/YangFile.cpp b/libyangrtc2/src/yangutil/YangFile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33a2f12f350340ce743d70c9581b5afe03bbb11c --- /dev/null +++ b/libyangrtc2/src/yangutil/YangFile.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _MSC_VER +#include +#endif + +YangFile::YangFile() { + + +} + +YangFile::~YangFile() { + +} + +int32_t YangFile::hasPath(const char* path){ + // _waccess(path,0); +#ifndef _MSC_VER + if( access(path, F_OK)!=0) return 1; + if( access(path, W_OK)!=0) return 2; +#endif + return 0; +} + +int32_t YangFile::createPath(const char* path){ + + #ifdef _WIN32 + #ifdef _MSC_VER + return _mkdir(path); + #else + return mkdir(path); + #endif + #else + mode_t mode=0755; + return mkdir(path,mode); + #endif + +} +int32_t YangFile::getCurpath(char* path){ +#ifdef _MSC_VER + if(_getcwd(path, 255)) return Yang_Ok; +#else + if(getcwd(path, 255)) return Yang_Ok; +#endif + return 1; +} + + +int32_t yang_getCurpath(char* path){ +#ifdef _MSC_VER + if(_getcwd(path, 255)) return Yang_Ok; +#else + if(getcwd(path, 255)) return Yang_Ok; +#endif + return 1; +} +int32_t yang_getLibpath(char* path){ + +char tmp[255]; +memset(tmp,0,sizeof(tmp)); +#ifdef _MSC_VER + if(_getcwd(tmp, 255)) { + +#else + if(getcwd(tmp, 255)) { +#endif + sprintf(path,"%s/lib",tmp); + return Yang_Ok; + } + return 1; +} + + int32_t yang_getCaFile(char* pem,char* key){ + char tmp[200]; + memset(tmp,0,sizeof(tmp)); +#ifdef _MSC_VER + if(_getcwd(tmp, 200)) { + +#else + if(getcwd(tmp, 200)) { +#endif + sprintf(pem,"%s/lib/client.pem",tmp); + sprintf(key,"%s/lib/client.key",tmp); + return Yang_Ok; + } + return 1; + } + +/** +int32_t createDirectory(std::string path) +{ + int32_t len = path.length(); + char tmpDirPath[256] = { 0 }; + for (int32_t i = 0; i < len; i++) + { + tmpDirPath[i] = path[i]; + if (tmpDirPath[i] == '\\' || tmpDirPath[i] == '/') + { + if (_access(tmpDirPath, 0) == -1) + { + int32_t ret = _mkdir(tmpDirPath); + if (ret == -1) return ret; + } + } + } + return 0; +} +**/ diff --git a/libyangrtc2/src/yangutil/YangHttp.cpp b/libyangrtc2/src/yangutil/YangHttp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d749f54a155437167f1972ad26be6aa801a31852 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangHttp.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +using namespace std; + +void YangHttp::loadLib(){ + + yang_curl_global_init=(CURLcode (*)(long flags))m_lib.loadFunction("curl_global_init"); + yang_curl_easy_init=(CURL* (*)(void))m_lib.loadFunction("curl_easy_init"); + yang_curl_easy_setopt=(CURLcode (*)(CURL *curl, CURLoption option, ...))m_lib.loadFunction("curl_easy_setopt"); + yang_curl_slist_append=(struct curl_slist* (*)(struct curl_slist *, + const char *))m_lib.loadFunction("curl_slist_append"); + yang_curl_easy_perform=(CURLcode (*)(CURL *curl))m_lib.loadFunction("curl_easy_perform"); + yang_curl_easy_cleanup=(void (*)(CURL *curl))m_lib.loadFunction("curl_easy_cleanup"); + yang_curl_global_cleanup=(void (*)(void))m_lib.loadFunction("curl_global_cleanup"); +} +void YangHttp::unloadLib(){ + yang_curl_global_init=NULL; + yang_curl_easy_init=NULL; + yang_curl_easy_setopt=NULL; + yang_curl_slist_append=NULL; + yang_curl_easy_perform=NULL; + yang_curl_easy_cleanup=NULL; + yang_curl_global_cleanup=NULL; +} + +YangHttp::YangHttp() +{ + unloadLib(); + m_lib.loadObject("libcurl"); + loadLib(); +} +YangHttp::~YangHttp() +{ + unloadLib(); + m_lib.unloadObject(); +} +size_t YangHttp::WriteFunction(void* input, size_t uSize, size_t uCount, void* avg) +{ + size_t uLen = uSize * uCount; + string* pStr = (string*)(avg); + pStr->append((char*)(input), uLen); + return uLen; +} +void string_replace(std::string& strBig, const std::string& strsrc, const std::string& strdst) +{ + std::string::size_type pos = 0; + std::string::size_type srclen = strsrc.size(); + std::string::size_type dstlen = strdst.size(); + + while ((pos = strBig.find(strsrc, pos)) != std::string::npos) + { + strBig.replace(pos, srclen, strdst); + pos += dstlen; + } +} +int32_t YangHttp::queryPost(char* purl1, string psdp,string &outsdp) +{ + + CURL* curl = NULL; + CURLcode code; + code = yang_curl_global_init(CURL_GLOBAL_DEFAULT); + if (code != CURLE_OK) yang_error(" http global init error"); + curl = yang_curl_easy_init(); + if (curl == NULL) yang_error(" http easy init error"); + + + + yang_curl_easy_setopt(curl, CURLOPT_URL, purl1); + yang_curl_easy_setopt(curl, CURLOPT_POST, 1); + yang_curl_easy_setopt(curl, CURLOPT_POSTFIELDS, psdp.c_str()); + yang_curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, psdp.length()); + + yang_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteFunction); + yang_curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outsdp); + + + + curl_slist* pHeaders = NULL; + pHeaders = yang_curl_slist_append(pHeaders, "Content-Type:application/json;charset=UTF-8"); + yang_curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaders); + yang_curl_easy_setopt(curl, CURLOPT_POST, 1); + code = yang_curl_easy_perform(curl); + if (code != CURLE_OK) { + //string err = "curl_easy_perform() Err...code=="+ to_string((int)code); + printf("curl_easy_perform() Err...code==%d",(int)code); + return 1; + } + + + yang_curl_easy_cleanup(curl); + yang_curl_global_cleanup(); + + return Yang_Ok; + +} + +int32_t YangHttp::querySslPost(char* purl, std::string psdp,std::string &outsdp){ + CURL* curl = NULL; + CURLcode code; + code = yang_curl_global_init(CURL_GLOBAL_DEFAULT); + if (code != CURLE_OK) yang_error(" http global init error"); + curl = yang_curl_easy_init(); + if (curl == NULL) yang_error(" http easy init error"); + + yang_curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + + yang_curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + char cerpath[255]={0}; + char privatekey[255]={0}; + + yang_getCaFile(cerpath,privatekey); + yang_curl_easy_setopt(curl, CURLOPT_CAINFO, cerpath); + yang_curl_easy_setopt(curl, CURLOPT_URL, purl); // + yang_curl_easy_setopt(curl, CURLOPT_POST, 1); + yang_curl_easy_setopt(curl, CURLOPT_POSTFIELDS, psdp.c_str()); + yang_curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, psdp.length()); + + yang_curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteFunction); + yang_curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outsdp); + + curl_slist* pHeaders = NULL; + + pHeaders = yang_curl_slist_append(pHeaders, "Content-Type:application/json;charset=UTF-8"); + yang_curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaders); + yang_curl_easy_setopt(curl, CURLOPT_POST, 1); + code = yang_curl_easy_perform(curl); + if (code != CURLE_OK) { + //string err = "curl_easy_perform() Err...code=="+ to_string((int)code); + return yang_error_wrap(code,"curl_easy_perform() Err...code==%d",(int)code); + //return 1; + } + + + yang_curl_easy_cleanup(curl); + yang_curl_global_cleanup(); + + return Yang_Ok; +} diff --git a/libyangrtc2/src/yangutil/YangIniImpl.cpp b/libyangrtc2/src/yangutil/YangIniImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06e5984571e49779c6cdd3daa022b1968bf26f87 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangIniImpl.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif +#define SECTION_MAX_LEN 256 +#define STRVALUE_MAX_LEN 256 +#define LINE_CONTENT_MAX_LEN 256 +#define FILEPATH_MAX 80 + + +YangIni::YangIni() { + m_file = NULL; +} + +YangIni::~YangIni() { + yang_free(m_file); +} +void YangIni::init(const char *p_filename) { + if(!p_filename) return; + char file1[300]; + memset(file1, 0, 300); + char file_path_getcwd[255]; + memset(file_path_getcwd, 0, 255); +#ifdef _MSC_VER + if(_getcwd(file_path_getcwd, 255)){ +#else + if(getcwd(file_path_getcwd, 255)){ +#endif + sprintf(file1, "%s/%s", file_path_getcwd, p_filename); + int32_t len = strlen(file1) + 1; + m_file = (char*) malloc(len); + memset(m_file, 0, len); + strcpy(m_file, file1); + } + +} + +void yangTrim(char *ps, int32_t len) { + for (int32_t i = 0; i < len; i++) + if (*(ps + i) == 0x0a || *(ps + i) == 0x0d) + *(ps + i) = 0x00; +} +int32_t YangIni::IniReadValue(const char *section, const char *key, char *val) { + FILE *fp; + int32_t i = 0; + int32_t lineContentLen = 0; + int32_t position = 0; + int32_t ret = 1; + char lineContent[LINE_CONTENT_MAX_LEN]; + bool bFoundSection = false; + bool bFoundKey = false; + fp = fopen(m_file, "r"); + if (fp == NULL) { + printf("%s: Opent file %s failed.\n", __FILE__, m_file); + return -1; + } + int32_t stLen=0; + while (feof(fp) == 0) { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + if(!fgets(lineContent, LINE_CONTENT_MAX_LEN, fp)) continue; + if ((lineContent[0] == ';') || (lineContent[0] == '\0') + || (lineContent[0] == '\r') || (lineContent[0] == '\n')) { + continue; + } + + //check section + if (strncmp(lineContent, section, strlen(section)) == 0) { + bFoundSection = true; + //printf("Found section = %s\n", lineContent); + while (feof(fp) == 0) { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + if(!fgets(lineContent, LINE_CONTENT_MAX_LEN, fp)) continue; + //check key + if (strncmp(lineContent, key, strlen(key)) == 0) { + bFoundKey = true; + lineContentLen = strlen(lineContent); + //find value + for (i = strlen(key); i < lineContentLen; i++) { + if (lineContent[i] == '=') { + position = i + 1; + break; + } + } + if (i >= lineContentLen) + break; + + stLen=strlen((char*)(lineContent + position)); + strncpy(val, lineContent + position,stLen); + lineContentLen = strlen(val); + for (i = 0; i < lineContentLen; i++) { + if ((lineContent[i] == '\0') || (lineContent[i] == '\r') + || (lineContent[i] == '\n')) { + val[i] = '\0'; + break; + } + } + } else if (lineContent[0] == '[') { + break; + } + } + break; + } + } + if (!bFoundSection) { + ret = -1; + } + else if (!bFoundKey) { + ret = -1; + } + fclose(fp); + yangTrim(val, strlen(val)); + return ret; +} + +int32_t YangIni::readStringValue(const char *section, const char *key, + char *val, const char *p_defaultStr) { + char sect[SECTION_MAX_LEN]; + //printf("section = %s, key = %s, file = %s\n", section, key, file); + if (section == NULL || key == NULL || val == NULL || m_file == NULL) { + printf("%s: input parameter(s) is NULL!\n", __func__); + strcpy(val, p_defaultStr); + return -1; + } + + memset(sect, 0, SECTION_MAX_LEN); + sprintf(sect, "[%s]", section); + int32_t ret = IniReadValue(sect, key, val); + if (ret == -1) + strcpy(val, p_defaultStr); + return ret; +} + +int32_t YangIni::readStringValue1(const char *section, const char *key, + char *val) { + char sect[SECTION_MAX_LEN]; + if (section == NULL || key == NULL || val == NULL || m_file == NULL) { + printf("%s: input parameter(s) is NULL!\n", __func__); + return -1; + } + + memset(sect, 0, SECTION_MAX_LEN); + sprintf(sect, "[%s]", section); + return IniReadValue(sect, key, val); +} + +int32_t YangIni::readIntValue(const char *section, const char *key, + int32_t p_defaultInt) { + char strValue[STRVALUE_MAX_LEN]; + memset(strValue, '\0', STRVALUE_MAX_LEN); + if (readStringValue1(section, key, strValue) != 1) { + return p_defaultInt; + } + return (atoi(strValue)); +} + + +void YangIni::initVideo(YangVideoInfo* video){ + memset(video,0,sizeof(YangVideoInfo)); + video->width = readIntValue("video", "width", 1280); + video->height = readIntValue("video", "height", 720); + video->outWidth = readIntValue("video", "outWidth", 1280); + video->outHeight = readIntValue("video", "outHeight", 720); + video->rate = readIntValue("video", "rate", 2048); + video->frame = readIntValue("video", "frame", 10); + + video->bitDepth = readIntValue("video", "bitDepth", 8); + + video->videoCacheNum = readIntValue("video", "videoCacheNum", 50); + video->evideoCacheNum = readIntValue("video", "evideoCacheNum", 50); + video->videoPlayCacheNum = readIntValue("video", "videoPlayCacheNum", 5); + + video->videoCaptureFormat = (YangYuvType)readIntValue("video", "videoCaptureFormat", YangYuy2); + video->videoEncoderFormat = (YangYuvType)readIntValue("video", "videoEncoderFormat", YangI420); + video->videoDecoderFormat = (YangYuvType)readIntValue("video", "videoDecoderFormat", YangI420); + + video->videoEncoderType = readIntValue("video", "videoEncoderType", 0); + video->videoDecoderType = readIntValue("video", "videoDecoderType", 0); + video->videoEncHwType = readIntValue("video", "videoEncHwType", 0); + video->videoDecHwType = readIntValue("video", "videoDecHwType", 0); + video->vIndex = readIntValue("video", "vIndex", 0); + + +} + void YangIni::initAudio(YangAudioInfo* audio){ + memset(audio,0,sizeof(YangAudioInfo)); + audio->sample=readIntValue("audio", "sample", 44100); + audio->frameSize=readIntValue("audio", "frameSize", 1024); + audio->channel=readIntValue("audio", "channel", 2); + audio->bitrate = readIntValue("audio", "bitrate", 128); + audio->usingMono=readIntValue("audio", "usingMono", 0); + audio->hasAec = readIntValue("audio", "hasAec", 0); + audio->echoPath = readIntValue("audio", "echoPath", 10); + audio->aecBufferFrames=readIntValue("audio", "aecBufferFrames", 0); + audio->hasAudioHeader = readIntValue("audio", "hasAudioHeader", 0); + audio->audioEncoderType = readIntValue("audio", "audioEncoderType", 0); + audio->audioDecoderType = readIntValue("audio", "audioDecoderType", 0); + audio->audioPlayType = readIntValue("audio", "audioPlayType", 0); + audio->audioCacheNum = readIntValue("audio", "audioCacheNum", 100); + audio->audioCacheSize = readIntValue("audio", "audioCacheSize", 100); + audio->audioPlayCacheNum = readIntValue("audio", "audioPlayCacheNum", 10); + + audio->aIndex = readIntValue("audio", "aIndex", 0); + audio->aSubIndex = readIntValue("audio", "aSubIndex", 0); + //aSubIndex + if(audio->usingMono){ + if(audio->audioEncoderType<2) audio->audioEncoderType=2; + if(audio->audioDecoderType<2)audio->audioDecoderType=2; + audio->channel=1; + audio->sample=16000; + audio->frameSize=320; + } + } + void YangIni::initSys(YangSysInfo *sys){ + memset(sys,0,sizeof(YangSysInfo)); + + sys->transType = readIntValue("sys", "transType", 0); + sys->isMultCamera = readIntValue("sys", "isMultCamera", 0); + sys->usingDataServer = readIntValue("sys", "usingDataServer", 0); + + sys->rtmpPort = readIntValue("sys", "rtmpPort", 1935); + sys->srtPort = readIntValue("sys", "srtPort", 8080); + sys->rtcPort = readIntValue("sys", "rtcPort", 1985); + sys->rtcLocalPort = readIntValue("sys", "rtcLocalPort", 16000); + sys->httpPort = readIntValue("sys", "httpPort", 8080); + sys->dataPort = readIntValue("sys", "dataPort", 9999); + sys->hasLogFile=readIntValue("sys", "hasLogFile", 0); + sys->logLevel = readIntValue("sys", "logLevel", 1); + sys->logLevel = readIntValue("sys", "logLevel", 1); + sys->cameraCount = readIntValue("sys", "cameraCount", 3); + readStringValue("sys", "cameraIndexs", sys->cameraIndexs, "1"); + readStringValue("sys", "rtmpServerIP", sys->rtmpServerIP, "127.0.0.1"); + readStringValue("sys", "srtServerIP", sys->srtServerIP, "127.0.0.1"); + readStringValue("sys", "rtcServerIP", sys->rtcServerIP, "127.0.0.1"); + readStringValue("sys", "httpServerIP", sys->httpServerIP, "127.0.0.1"); + readStringValue("sys", "dataServerIP", sys->dataServerIP, "127.0.0.1"); + } + + void YangIni::initEnc(YangVideoEncInfo *enc){ + memset(enc,0,sizeof(YangVideoEncInfo)); + enc->preset = readIntValue("enc", "preset", 3); + enc->level_idc = readIntValue("enc", "level_idc", 31); + enc->profile = readIntValue("enc", "profile", 0); + enc->keyint_max = readIntValue("enc", "keyint_max", 30); + enc->enc_threads = readIntValue("enc", "enc_threads", 4); + enc->createMeta = readIntValue("enc", "createMeta", 1)==0?false:true; + enc->gop = readIntValue("enc", "gop", 30); + + } + + void YangIni::initRtc(YangRtcInfo *rtc){ + memset(rtc,0,sizeof(YangRtcInfo)); + rtc->sendTwcc = readIntValue("rtc", "sendTwcc", 0); + rtc->mixAvqueue = readIntValue("rtc", "mixAvqueue", 1); + rtc->audioQueueCount = readIntValue("rtc", "audioQueueCount", 5); + rtc->videoQueueCount = readIntValue("rtc", "videoQueueCount", 5); + + } + + diff --git a/libyangrtc2/src/yangutil/YangJson.cpp b/libyangrtc2/src/yangutil/YangJson.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6dd33ed3bae316418007f01426a5fcb24997efd3 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangJson.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +void yang_gen_jsonstr(vector &jsons,string &outstr){ + /** + outstr="{"; + char msg[1024]; + memset(msg,0,sizeof(msg)); + for(size_t i=0;i &jsons){ + Json::Reader reader; + Json::Value root; + if(!reader.parse(jsonstr, root)){ + return yang_error_wrap(1,"parse json fail"); + } + int size = root.size(); + /** for (int i=0; i +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _WIN32 +#include +#include +#ifdef _MSC_VER +#include +#endif +#else + #include +#endif + + + +YangLoadLib::YangLoadLib(){ + m_handle=NULL; +} +YangLoadLib::~YangLoadLib(){ + unloadObject(); +} +void* YangLoadLib::loadSysObject(const char *sofile) +{ + +#ifdef _WIN32 + // LPCSTR + m_handle = LoadLibraryA(sofile); +#else + m_handle = dlopen(sofile, RTLD_NOW|RTLD_LOCAL); +#endif + + if (m_handle == 0) { + yang_error("Failed loading %s: %s", sofile, (char *) dlerror()); + } + return (m_handle); +} +#define LENTH 200 +void* YangLoadLib::loadObject(const char *sofile) +{ + + + char file1[LENTH+50]; + char file_path_getcwd[LENTH]; + memset(file1, 0, LENTH+50); + memset(file_path_getcwd, 0, LENTH); + if(yang_getLibpath(file_path_getcwd)!=Yang_Ok){ + yang_error( "Failed loading shared obj %s: %s,getcwd error!", sofile, (char *) dlerror()); + return NULL; + } + +#ifdef _WIN32 + sprintf(file1, "%s/%s.dll", file_path_getcwd, sofile); + m_handle = LoadLibraryA(file1); +#else + sprintf(file1, "%s/%s.so", file_path_getcwd, sofile); + m_handle = dlopen(file1, RTLD_NOW|RTLD_LOCAL); +#endif + + if (m_handle == 0) { + + yang_error( "Failed loading shared obj %s: %s", sofile, (char *) dlerror()); + } + return (m_handle); +} +#ifdef _WIN32 +char *YangLoadLib::dlerror(){ + return (char*)"loadlib error"; +} +#endif + +void* YangLoadLib::loadFunction( const char *name) +{ + +#ifdef _WIN32 + void *symbol = (void *) GetProcAddress(m_handle, name); +#else + void *symbol = dlsym(m_handle, name); +#endif + + if (symbol == NULL) { + yang_error("Failed loading function %s: %s", name, (const char *) dlerror()); + } + return (symbol); +} + +void YangLoadLib::unloadObject() +{ + if (m_handle) { +#ifdef _WIN32 + FreeLibrary( m_handle); +#else + dlclose(m_handle);; +#endif + m_handle=NULL; + + } +} + +//#endif + diff --git a/libyangrtc2/src/yangutil/YangLog.cpp b/libyangrtc2/src/yangutil/YangLog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2fdc7399424b5d72b3678f047582cfab2041836 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangLog.cpp @@ -0,0 +1,188 @@ +#include "yangutil/sys/YangLog.h" + +#include +#include +#include +#include +#include +#include +#include +//#include + +#ifdef _WIN32 +#include +#ifdef _MSC_VER +#include +#endif +#else +#include +#endif + +class YangLogFile { +public: + //std::mutex m_lock; + FILE *fmsg = NULL; + YangLogFile() { + fmsg = NULL; + } + ; + ~YangLogFile() { + if (fmsg) + fclose(fmsg); + fmsg = NULL; + } + ; + void writeFileData(char *p, int32_t plen) { + //if(!fmsg) return; + //m_lock.lock(); + fwrite(p, plen, 1, fmsg); + fflush(fmsg); + //m_lock.unlock(); + } + //; + +}; + +YangLogFile *g_yangLogFile = NULL; + + + +static char const *YANG_LOG_LEVEL_NAME[] = { "FATAL", "ERROR", "WARNING", + "INFO", "DEBUG", "TRACE" }; + +YangCLog::YangCLog() { + //neednl = 0; + +} + +YangCLog::~YangCLog() { + +} + +void YangCLog::setLogFile(int32_t isSetLogFile) { + if (!g_yangLogFile) + g_yangLogFile = new YangLogFile(); + if (m_hasLogFile) + return; + m_hasLogFile = isSetLogFile; + if (isSetLogFile) { + char file1[300]; + memset(file1, 0, 300); + char file_path_getcwd[255]; + memset(file_path_getcwd, 0, 255); +#ifdef _MSC_VER + if (_getcwd(file_path_getcwd, 255)) { +#else + if (getcwd(file_path_getcwd, 255)) { +#endif + + sprintf(file1, "%s/yang_log.log", file_path_getcwd); + g_yangLogFile->fmsg = fopen(file1, "wb+"); + + } + + } +} +void YangCLog::closeLogFile() { + if (g_yangLogFile) + delete g_yangLogFile; + g_yangLogFile = NULL; +} + +void YangCLog::log(int32_t level, const char *fmt, ...) { + if (level > logLevel) + return; + char buf[4096]; + memset(buf, 0, 4096); + //int32_t len=0; + va_list args; + va_start(args, fmt); + //int32_t len = + vsnprintf(buf, 4095, fmt, args); + va_end(args); + + if (m_hasLogFile) { + if (!g_yangLogFile) + g_yangLogFile = new YangLogFile(); + } + struct tm* ntm=NULL; + if(level==YANG_LOG_ERROR){ + time_t t_now=time(NULL); + ntm=localtime(&t_now); + printf("[%02d:%02d:%02d] Yang %s: %s\n",ntm->tm_hour,ntm->tm_min,ntm->tm_sec,YANG_LOG_LEVEL_NAME[level], buf); + + }else{ + printf("Yang %s: %s\n",YANG_LOG_LEVEL_NAME[level], buf); + } + + if (m_hasLogFile) { + + char sf[4196]; + memset(sf, 0, 4196); + int32_t sfLen=0; + if(level==YANG_LOG_ERROR&&ntm) + sfLen = sprintf(sf, "[%02d:%02d:%02d] Yang %s: %s\n",ntm->tm_hour,ntm->tm_min,ntm->tm_sec, YANG_LOG_LEVEL_NAME[level], buf); + else + sfLen = sprintf(sf, "Yang %s: %s\n", YANG_LOG_LEVEL_NAME[level], buf); + if (g_yangLogFile->fmsg) + g_yangLogFile->writeFileData(sf, sfLen); + } + ntm=NULL; + +} +int32_t yang_error_wrap(int32_t errcode, const char *fmt, ...) { + char buf[4096]; + memset(buf, 0, 4096); + va_list args; + va_start(args, fmt); + vsnprintf(buf, 4095, fmt, args); + va_end(args); + + time_t t_now=time(NULL); + struct tm* ntm=localtime(&t_now); + + printf("Yang Error(%d): %s\n", errcode, + buf); + + if (YangCLog::m_hasLogFile) { + if (!g_yangLogFile) + g_yangLogFile = new YangLogFile(); + char sf[4196]; + memset(sf, 0, 4196); + int32_t sfLen = sprintf(sf, "[%02d:%02d:%02d] Yang Error(%d): %s\n",ntm->tm_hour,ntm->tm_min,ntm->tm_sec, errcode, buf); + if (g_yangLogFile->fmsg) + g_yangLogFile->writeFileData(sf, sfLen); + } + ntm=NULL; + return errcode; +} + +void YangCLog::logf(int32_t level, const char *fmt, ...) { + if (level > logLevel) + return; + char buf[4096]; + memset(buf, 0, 4096); + int32_t len = 0; + va_list args; + va_start(args, fmt); + len = vsnprintf(buf, 4095, fmt, args); + va_end(args); + + printf(buf); + + if (m_hasLogFile) { + if (!g_yangLogFile) + g_yangLogFile = new YangLogFile(); + if (g_yangLogFile->fmsg) + g_yangLogFile->writeFileData(buf, len); + } + +} +int32_t YangCLog::logLevel = YANG_LOG_ERROR; +int32_t YangCLog::m_hasLogFile = 0; +void YangCLog::setLogLevel(int32_t plevel) { + logLevel = plevel; + if (logLevel > YANG_LOG_TRACE) + logLevel = YANG_LOG_TRACE; +} + diff --git a/libyangrtc2/src/yangutil/YangSRtp.cpp b/libyangrtc2/src/yangutil/YangSRtp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..609c13d02165a30abc539597090c17884c74566d --- /dev/null +++ b/libyangrtc2/src/yangutil/YangSRtp.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#ifdef _WIN32 +#include + +#define bzero(a, b) memset(a, 0, b) +#else +#include +#endif +YangSRtp::YangSRtp() +{ + m_recvCtx = NULL; + m_sendCtx = NULL; +} + +YangSRtp::~YangSRtp() +{ + if (m_recvCtx) { + srtp_dealloc(m_recvCtx); + } + + if (m_sendCtx) { + srtp_dealloc(m_sendCtx); + } +} + +int32_t YangSRtp::init(char* recv_key,int precvkeylen, char* send_key,int psendkeylen) +{ + int32_t err = Yang_Ok; + srtp_policy_t policy; + + bzero(&policy, sizeof(policy)); + + // TODO: Maybe we can use SRTP-GCM in future. + // @see https://bugs.chromium.org/p/chromium/issues/detail?id=713701 + // @see https://groups.google.com/forum/#!topic/discuss-webrtc/PvCbWSetVAQ + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); + + policy.ssrc.value = 0; + // TODO: adjust window_size + policy.window_size = 8192; + policy.allow_repeat_tx = 1; + policy.next = NULL; + srtp_err_status_t r0 = srtp_err_status_ok; + + //init send context + policy.ssrc.type = ssrc_any_outbound; + uint8_t *skey = new uint8_t[psendkeylen]; + YangAutoFreeA(uint8_t, skey); + memcpy(skey, send_key, psendkeylen); + policy.key = skey; + + if ((r0 = srtp_create(&m_sendCtx, &policy)) != srtp_err_status_ok) { + return yang_error_wrap(ERROR_RTC_SRTP_INIT, "srtp create send r0=%u", r0); + } + + // init recv context + policy.ssrc.type = ssrc_any_inbound; + uint8_t *rkey = new uint8_t[precvkeylen]; + YangAutoFreeA(uint8_t, rkey); + memcpy(rkey, recv_key, precvkeylen); + policy.key = rkey; + + + if ((r0 = srtp_create(&m_recvCtx, &policy)) != srtp_err_status_ok) { + return yang_error_wrap(ERROR_RTC_SRTP_INIT, "srtp create recv r0=%u", r0); + } + + + return err; +} + +int32_t YangSRtp::enc_rtp(void* packet, int* nb_cipher) +{ + int32_t err = Yang_Ok; + + // If DTLS/SRTP is not ready, fail. + if (!m_sendCtx) { + return yang_error_wrap(ERROR_RTC_SRTP_PROTECT, "not ready"); + } + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_protect(m_sendCtx, packet, nb_cipher)) != srtp_err_status_ok) { + return yang_error_wrap(ERROR_RTC_SRTP_PROTECT, "rtp protect r0=%u", r0); + } + + return err; +} + +int32_t YangSRtp::enc_rtcp(void* packet, int* nb_cipher) +{ + int32_t err = Yang_Ok; + + // If DTLS/SRTP is not ready, fail. + if (!m_sendCtx) { + return yang_error_wrap(ERROR_RTC_SRTP_PROTECT, "not ready"); + } + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_protect_rtcp(m_sendCtx, packet, nb_cipher)) != srtp_err_status_ok) { + return yang_error_wrap(ERROR_RTC_SRTP_PROTECT, "rtcp protect r0=%u", r0); + } + + return err; +} + +int32_t YangSRtp::dec_rtp(void* packet, int* nb_plaintext) +{ + int32_t err = Yang_Ok; + + // If DTLS/SRTP is not ready, fail. + if (!m_recvCtx) { + return yang_error_wrap(ERROR_RTC_SRTP_UNPROTECT, "not ready"); + } + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_unprotect(m_recvCtx, packet, nb_plaintext)) != srtp_err_status_ok) { + if(r0==srtp_err_status_replay_fail) return r0; + return yang_error_wrap(ERROR_RTC_SRTP_UNPROTECT, "rtp unprotect r0=%u", r0); + } + + return err; +} + +int32_t YangSRtp::dec_rtcp(void* packet, int* nb_plaintext) +{ + int32_t err = Yang_Ok; + + // If DTLS/SRTP is not ready, fail. + if (!m_recvCtx) { + return yang_error_wrap(ERROR_RTC_SRTP_UNPROTECT, "not ready"); + } + + srtp_err_status_t r0 = srtp_err_status_ok; + if ((r0 = srtp_unprotect_rtcp(m_recvCtx, packet, nb_plaintext)) != srtp_err_status_ok) { + return yang_error_wrap(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect r0=%u", r0); + } + + return err; +} + diff --git a/libyangrtc2/src/yangutil/YangSocket.cpp b/libyangrtc2/src/yangutil/YangSocket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8d231d4fbd02e0f25bf31a5ca5e9ea48331ed90 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangSocket.cpp @@ -0,0 +1,239 @@ +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include + +using namespace std; +void yang_getIp( std::string domain, std::string& ip) +{ +#ifdef _WIN32 + WORD wVersionRequested = MAKEWORD(2, 2); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); +#endif + struct hostent *host = gethostbyname(domain.c_str()); + if (host == NULL){ + ip=domain; + #ifdef _WIN32 + WSACleanup(); +#endif + return; + } + for (int i = 0; host->h_addr_list[i]; i++) + { + ip=inet_ntoa(*(struct in_addr*)host->h_addr_list[i]); + break; + } + #ifdef _WIN32 + WSACleanup(); +#endif + //ip=domain; +} + + +#ifdef _WIN32 +void SplitString2Int( const string& src, string delimit, vector& vecRet) +{ + string null_subst = "0"; + if( src.empty() || src == "" || delimit.empty() || delimit == "" ) + return; + + uint32_t deli_len = delimit.size(); + uint32_t nIndex = 0; + uint32_t last_search_position = 0; + while( ( nIndex = src.find( delimit, last_search_position ) ) != -1 ) + { + if( nIndex == last_search_position ) + { + int32_t nValue = atoi( null_subst.c_str() ); + vecRet.push_back( nValue ); + } + else + { + int32_t nValue = atoi( src.substr( last_search_position, nIndex - last_search_position ).c_str() ); + vecRet.push_back( nValue ); + } + last_search_position = nIndex + deli_len; + } + + string last_one = src.substr( last_search_position ); + if ( last_one.empty() ) + { + int32_t nValue = atoi( null_subst.c_str() ); + vecRet.push_back( nValue ); + } + else + { + int32_t nValue = atoi( last_one.c_str() ); + vecRet.push_back( nValue ); + } +} + +std::string yang_getLocalInfo(void){ + string localIP = ""; + + WORD wVersionRequested = MAKEWORD(2, 2); + WSADATA wsaData; + if (WSAStartup(wVersionRequested, &wsaData) != 0) + return ""; + char local[255] = {0}; + gethostname(local, sizeof(local)); + hostent* ph = gethostbyname(local); + if (ph == NULL) + return ""; + + for(int32_t i=0;;i++) + { + localIP = inet_ntoa(*(IN_ADDR*)ph->h_addr_list[i]); + std::vector vecRet; + SplitString2Int( localIP, ".", vecRet ); + if(vecRet[0] == 127 && vecRet[1] == 0 && vecRet[2] == 0) //获得192.168.0.X最后一位 + continue; + if(ph->h_addr_list[i]+ph->h_length >= ph->h_name) break; + break; + } + //in_addr addr; + //memcpy(&addr, ph->h_addr_list[0], sizeof(in_addr)); // 这里仅获取第一个ip + //localIP.assign(inet_ntoa(addr)); + WSACleanup(); + + return localIP; + + } +#else +std::string yang_getLocalInfo(void) +{ + int32_t fd; + int32_t interfaceNum = 0; + struct ifreq buf[16]; + struct ifconf ifc; + struct ifreq ifrcopy; + char mac[16] = {0}; + char ip[32] = {0}; + char broadAddr[32] = {0}; + char subnetMask[32] = {0}; + + + string res="127.0.0.1"; + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + yang_error("socket error"); + + close(fd); + return res; + } + + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = (caddr_t)buf; + if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) + { + interfaceNum = ifc.ifc_len / sizeof(struct ifreq); + while (interfaceNum-- > 0) + { + //ignore the interface that not up or not runing + ifrcopy = buf[interfaceNum]; + if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy)) + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + + close(fd); + return res; + } + + //get the mac of this interface + if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum]))) + { + memset(mac, 0, sizeof(mac)); + snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x", + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[0], + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[1], + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[2], + + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[3], + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[4], + (uint8_t)buf[interfaceNum].ifr_hwaddr.sa_data[5]); + + } + else + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + close(fd); + return res; + } + + //get the IP of this interface + + if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum])) + { + string s=(char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_addr))->sin_addr); + if(s!="127.0.0.1") res=s; + snprintf(ip, sizeof(ip), "%s", + (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_addr))->sin_addr)); + + } + else + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + close(fd); + return res; + } + + //get the broad address of this interface + + if (!ioctl(fd, SIOCGIFBRDADDR, &buf[interfaceNum])) + { + snprintf(broadAddr, sizeof(broadAddr), "%s", + (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_broadaddr))->sin_addr)); + + } + else + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + close(fd); + return res; + } + + //get the subnet mask of this interface + if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum])) + { + snprintf(subnetMask, sizeof(subnetMask), "%s", + (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_netmask))->sin_addr)); + + } + else + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + close(fd); + return res; + + } + } + } + else + { + yang_error("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__); + close(fd); + return res; + } + + close(fd); + + return res; +} +#endif diff --git a/libyangrtc2/src/yangutil/YangSsl.cpp b/libyangrtc2/src/yangutil/YangSsl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3de27d60bed1071a5f2059a39cd9701bce469788 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangSsl.cpp @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#define yang_assert(expression) assert(expression) +int32_t hmac_encode(const std::string& algo, const char* key, const int& key_length, + const char* input, const int32_t input_length, char* output, unsigned int& output_length) +{ + int32_t err = Yang_Ok; + + const EVP_MD* engine = NULL; + if (algo == "sha512") { + engine = EVP_sha512(); + } else if(algo == "sha256") { + engine = EVP_sha256(); + } else if(algo == "sha1") { + engine = EVP_sha1(); + } else if(algo == "md5") { + engine = EVP_md5(); + } else if(algo == "sha224") { + engine = EVP_sha224(); + } else if(algo == "sha384") { + engine = EVP_sha384(); + } else { + yang_error( "ERROR_RTC_STUN unknown algo=%s", algo.c_str()); + return 1; + } + + HMAC_CTX* ctx = HMAC_CTX_new(); + if (ctx == NULL) { + return yang_error_wrap(ERROR_SSL, "hmac init faied"); + } + + if (HMAC_Init_ex(ctx, key, key_length, engine, NULL) < 0) { + HMAC_CTX_free(ctx); + return yang_error_wrap(ERROR_SSL, "hmac init faied"); + } + + if (HMAC_Update(ctx, (const uint8_t*)input, input_length) < 0) { + HMAC_CTX_free(ctx); + return yang_error_wrap(ERROR_SSL, "hmac update faied"); + } + + if (HMAC_Final(ctx, (uint8_t*)output, &output_length) < 0) { + HMAC_CTX_free(ctx); + return yang_error_wrap(ERROR_SSL, "hmac final faied"); + } + + HMAC_CTX_free(ctx); + + return err; +} + + + +YangCertificateImpl::YangCertificateImpl() { + ecdsa_mode = true; + dtls_cert = NULL; + dtls_pkey = NULL; + eckey = NULL; +} + +YangCertificateImpl::~YangCertificateImpl() { + if (eckey) { + EC_KEY_free(eckey); + } + + if (dtls_pkey) { + EVP_PKEY_free(dtls_pkey); + } + + if (dtls_cert) { + X509_free(dtls_cert); + } +} + +int32_t YangCertificateImpl::init() { + int32_t err = Yang_Ok; + + // Initialize once. + if (dtls_cert) { + return err; + } + +#if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x + OpenSSL_add_ssl_algorithms(); +#else + +#endif + + // Initialize SRTP first. + if(srtp_init()) + yang_error("srtp init fail..................."); + else + yang_trace("\nsrtp init success!...................\n"); + + ecdsa_mode = 1; //_srs_config->get_rtc_server_ecdsa(); + dtls_pkey = EVP_PKEY_new(); + //yang_assert(dtls_pkey); + if (!ecdsa_mode) { // By RSA + RSA *rsa = RSA_new(); + if(rsa==NULL) return yang_error_wrap(ERROR_SSL,"Certificate rsa create fail"); + + // Initialize the big-number for private key. + BIGNUM *exponent = BN_new(); + if(exponent==NULL) return yang_error_wrap(ERROR_SSL,"Certificate BIGNUM create fail"); + BN_set_word(exponent, RSA_F4); + int32_t key_bits = 1024; + RSA_generate_key_ex(rsa, key_bits, exponent, NULL); + if(EVP_PKEY_set1_RSA(dtls_pkey, rsa) != 1) yang_error("EVP_PKEY_set1_RSA error"); + + RSA_free(rsa); + BN_free(exponent); + } + if (ecdsa_mode) { // By ECDSA, https://stackoverflow.com/a/6006898 + eckey = EC_KEY_new(); + yang_assert(eckey); + EC_GROUP *ecgroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + yang_assert(ecgroup); +#if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x + // For openssl 1.0, we must set the group parameters, so that cert is ok. + // @see https://github.com/monero-project/monero/blob/master/contrib/epee/src/net_ssl.cpp#L225 + EC_GROUP_set_asn1_flag(ecgroup, OPENSSL_EC_NAMED_CURVE); +#endif + + if(EC_KEY_set_group(eckey, ecgroup) != 1) return yang_error_wrap(ERROR_SSL,"EC_KEY_set_group error"); + if(EC_KEY_generate_key(eckey) != 1) return yang_error_wrap(ERROR_SSL,"EC_KEY_generate_key error"); + if(EVP_PKEY_set1_EC_KEY(dtls_pkey, eckey) != 1) return yang_error_wrap(ERROR_SSL,"EVP_PKEY_set1_EC_KEY error"); + + EC_GROUP_free(ecgroup); + } + + // Create certificate, from previous generated pkey. + // TODO: Support ECDSA certificate. + dtls_cert = X509_new(); + yang_assert(dtls_cert); + if (true) { + X509_NAME *subject = X509_NAME_new(); + yang_assert(subject); + + int32_t serial = (int) yang_random(); + ASN1_INTEGER_set(X509_get_serialNumber(dtls_cert), serial); + + const std::string &aor = "yangrtc";//RTMP_SIG_SRS_DOMAIN; + X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC, + (uint8_t*) aor.data(), aor.size(), -1, 0); + + X509_set_issuer_name(dtls_cert, subject); + X509_set_subject_name(dtls_cert, subject); + + int32_t expire_day = 365; + const long cert_duration = 60 * 60 * 24 * expire_day; + + X509_gmtime_adj(X509_get_notBefore(dtls_cert), 0); + X509_gmtime_adj(X509_get_notAfter(dtls_cert), cert_duration); + + X509_set_version(dtls_cert, 2); + if(X509_set_pubkey(dtls_cert, dtls_pkey) != 1) yang_error("EVP_PKEY_set1_EC_KEY error"); + if(X509_sign(dtls_cert, dtls_pkey, EVP_sha1()) == 0) yang_error("EVP_PKEY_set1_EC_KEY error"); + + X509_NAME_free(subject); + } + + // Show DTLS fingerprint + if (true) { + char fp[100] = { 0 }; + char *p = fp; + uint8_t md[EVP_MAX_MD_SIZE]; + uint32_t n = 0; + + // TODO: FIXME: Unused variable. + /*int32_t r = */X509_digest(dtls_cert, EVP_sha256(), md, &n); + + for (uint32_t i = 0; i < n; i++, ++p) { + sprintf(p, "%02X", md[i]); + p += 2; + + if (i < (n - 1)) { + *p = ':'; + } else { + *p = '\0'; + } + } + + fingerprint.assign(fp, strlen(fp)); + //yang_trace("fingerprint=%s", fingerprint.c_str()); + } + + return err; +} + +X509* YangCertificateImpl::get_cert() { + return dtls_cert; +} + +EVP_PKEY* YangCertificateImpl::get_public_key() { + return dtls_pkey; +} + +EC_KEY* YangCertificateImpl::get_ecdsa_key() { + return eckey; +} + +std::string YangCertificateImpl::get_fingerprint() { + return fingerprint; +} + +bool YangCertificateImpl::is_ecdsa() { + return ecdsa_mode; +} diff --git a/libyangrtc2/src/yangutil/YangSsrc.cpp b/libyangrtc2/src/yangutil/YangSsrc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93781a80de5a45f88bf487a64109dad5c584a527 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangSsrc.cpp @@ -0,0 +1,160 @@ +#ifndef _WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +uint64_t __crc32_reflect(uint64_t data, int32_t width) +{ + uint64_t res = data & 0x01; + + for (int32_t i = 0; i < (int)width - 1; i++) { + data >>= 1; + res = (res << 1) | (data & 0x01); + } + + return res; +} +void __crc32_make_table(uint32_t t[256], uint32_t poly, bool reflect_in) +{ + int32_t width = 32; // 32bits checksum. + uint64_t msb_mask = (uint32_t)(0x01 << (width - 1)); + uint64_t mask = (uint32_t)(((msb_mask - 1) << 1) | 1); + + int32_t tbl_idx_width = 8; // table index size. + int32_t tbl_width = 0x01 << tbl_idx_width; // table size: 256 + + for (int32_t i = 0; i < (int)tbl_width; i++) { + uint64_t reg = uint64_t(i); + + if (reflect_in) { + reg = __crc32_reflect(reg, tbl_idx_width); + } + + reg = reg << (width - tbl_idx_width); + for (int32_t j = 0; j < tbl_idx_width; j++) { + if ((reg&msb_mask) != 0) { + reg = (reg << 1) ^ poly; + } else { + reg = reg << 1; + } + } + + if (reflect_in) { + reg = __crc32_reflect(reg, width); + } + + t[i] = (uint32_t)(reg & mask); + } +} + +// @see pycrc table_driven at https://github.com/winlinvip/pycrc/blob/master/pycrc/algorithms.py#L207 +uint32_t __crc32_table_driven(uint32_t* t, const void* buf, int32_t size, uint32_t previous, bool reflect_in, uint32_t xor_in, bool reflect_out, uint32_t xor_out) +{ + int32_t width = 32; // 32bits checksum. + uint64_t msb_mask = (uint32_t)(0x01 << (width - 1)); + uint64_t mask = (uint32_t)(((msb_mask - 1) << 1) | 1); + + int32_t tbl_idx_width = 8; // table index size. + + uint8_t* p = (uint8_t*)buf; + uint64_t reg = 0; + + if (!reflect_in) { + reg = xor_in; + + for (int32_t i = 0; i < (int)size; i++) { + uint8_t tblidx = (uint8_t)((reg >> (width - tbl_idx_width)) ^ p[i]); + reg = t[tblidx] ^ (reg << tbl_idx_width); + } + } else { + reg = previous ^ __crc32_reflect(xor_in, width); + + for (int32_t i = 0; i < (int)size; i++) { + uint8_t tblidx = (uint8_t)(reg ^ p[i]); + reg = t[tblidx] ^ (reg >> tbl_idx_width); + } + + reg = __crc32_reflect(reg, width); + } + + if (reflect_out) { + reg = __crc32_reflect(reg, width); + } + + reg ^= xor_out; + return (uint32_t)(reg & mask); +} + +// @see pycrc https://github.com/winlinvip/pycrc/blob/master/pycrc/algorithms.py#L207 +// IEEETable is the table for the IEEE polynomial. +static uint32_t __crc32_IEEE_table[256]; +static bool __crc32_IEEE_table_initialized = false; +uint32_t yang_crc32_ieee(const void* buf, int32_t size, uint32_t previous) +{ + // @see golang IEEE of hash/crc32/crc32.go + // IEEE is by far and away the most common CRC-32 polynomial. + // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ... + // @remark The poly of CRC32 IEEE is 0x04C11DB7, its reverse is 0xEDB88320, + // please read https://en.wikipedia.org/wiki/Cyclic_redundancy_check + uint32_t poly = 0x04C11DB7; + + bool reflect_in = true; + uint32_t xor_in = 0xffffffff; + bool reflect_out = true; + uint32_t xor_out = 0xffffffff; + + if (!__crc32_IEEE_table_initialized) { + __crc32_make_table(__crc32_IEEE_table, poly, reflect_in); + __crc32_IEEE_table_initialized = true; + } + + return __crc32_table_driven(__crc32_IEEE_table, buf, size, previous, reflect_in, xor_in, reflect_out, xor_out); +} + + +YangRtcSSRCGenerator* YangRtcSSRCGenerator::_instance = NULL; + +YangRtcSSRCGenerator::YangRtcSSRCGenerator() +{ + ssrc_num = 0; +} + +YangRtcSSRCGenerator::~YangRtcSSRCGenerator() +{ +} + +YangRtcSSRCGenerator* YangRtcSSRCGenerator::instance() +{ + if (!_instance) { + _instance = new YangRtcSSRCGenerator(); + } + return _instance; +} + +uint32_t YangRtcSSRCGenerator::generate_ssrc() +{ + if (!ssrc_num) { + + + #ifdef _MSC_VER + ssrc_num = ::GetCurrentProcessId() * 10000 + ::GetCurrentProcessId() * 100 + ::GetCurrentProcessId(); + #else + ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid(); + #endif + + } + + return ++ssrc_num; +} + diff --git a/libyangrtc2/src/yangutil/YangString.cpp b/libyangrtc2/src/yangutil/YangString.cpp new file mode 100644 index 0000000000000000000000000000000000000000..414b374e5ee30da7877103e5e6ca82a843521a30 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangString.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#define srandom srand +#define random rand +#endif +#include +#ifdef _MSC_VER +#include +#endif + + void skip_first_spaces(std::string& str) +{ + while (! str.empty() && str[0] == ' ') { + str.erase(0, 1); + } +} + + vector yang_split_first(string s, char ch) { + int32_t len = 0; + vector ret; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == ch) { + ret.push_back(s.substr(0, i)); + ret.push_back(s.substr(i+1, s.length()-1)); + return ret; + } + else { + len++; + } + } + + return ret; + } + +vector yang_split(string s, char ch) { + size_t start = 0; + int32_t len = 0; + vector ret; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == ch) { + ret.push_back(s.substr(start, len)); + start = i + 1; + len = 0; + } + else { + len++; + } + } + if (start < s.length()) + ret.push_back(s.substr(start, len)); + return ret; +} + +std::vector yang_splits(const std::string& str, const std::string& delim) +{ + std::vector ret; + size_t pre_pos = 0; + std::string tmp; + size_t pos = 0; + do { + pos = str.find(delim, pre_pos); + tmp = str.substr(pre_pos, pos - pre_pos); + ret.push_back(tmp); + pre_pos = pos + delim.size(); + } while (pos != std::string::npos); + + return ret; +} + +long yang_random() { + static bool _random_contexttialized = false; + if (!_random_contexttialized) { + _random_contexttialized = true; +#ifdef _MSC_VER + ::srandom((unsigned long) (yang_update_system_time() | (GetCurrentProcessId() << 13))); +#else + ::srandom((unsigned long) (yang_update_system_time() | (getpid() << 13))); +#endif + + + } + + return random(); +} +std::string yang_int2str(int64_t value) { + + char tmp[22]; + snprintf(tmp, 22, "%" PRId64, value); + return string(tmp); +} +std::string yang_random_str(int32_t len) { + static string random_table = + "01234567890123456789012345678901234567890123456789abcdefghijklmnopqrstuvwxyz"; + string ret; + ret.reserve(len); + for (int32_t i = 0; i < len; ++i) { + ret.append(1, random_table[yang_random() % random_table.size()]); + } + + return ret; +} +void yang_replace(std::string& strBig, const std::string& strsrc, const std::string& strdst) +{ + std::string::size_type pos = 0; + std::string::size_type srclen = strsrc.size(); + std::string::size_type dstlen = strdst.size(); + + while ((pos = strBig.find(strsrc, pos)) != std::string::npos) + { + strBig.replace(pos, srclen, strdst); + pos += dstlen; + } +} + + diff --git a/libyangrtc2/src/yangutil/YangSysMessageHandle.cpp b/libyangrtc2/src/yangutil/YangSysMessageHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68c5178dce23059b6d491703bba605d1b2850731 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangSysMessageHandle.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include +#include "yangutil/sys/YangLog.h" + +void yang_post_message(int32_t st, int32_t uid, YangSysMessageI *mhandle,void* user) { + if (YangSysMessageHandle::m_instance) + YangSysMessageHandle::m_instance->putMessage(mhandle, st, uid, 0,user); +} +void yang_post_state_message(int32_t st, int32_t uid, int32_t handleState,YangSysMessageI *mhandle) { + if (YangSysMessageHandle::m_instance) + YangSysMessageHandle::m_instance->putMessage(mhandle, st, uid, + handleState); +} +void yang_post_userMessage(int32_t st, int32_t uid,YangSysMessageI *mhandle,void* user){ + if (YangSysMessageHandle::m_instance) + YangSysMessageHandle::m_instance->putMessage(mhandle, st, uid, 0); +} +YangSysMessageHandle::YangSysMessageHandle() { + m_loop = 0; + m_isStart = 0; + //m_lock = PTHREAD_MUTEX_INITIALIZER; + //m_cond_mess = PTHREAD_COND_INITIALIZER; + pthread_mutex_init(&m_lock, NULL); + pthread_cond_init(&m_cond_mess, NULL); + m_waitState=0; + m_receive=NULL; + if (m_instance == NULL) + m_instance = this; +} + +YangSysMessageHandle::~YangSysMessageHandle() { + + if (m_isStart) { + stop(); + while (m_isStart) { + yang_usleep(1000); + } + } + m_instance = NULL; + pthread_mutex_destroy(&m_lock); + pthread_cond_destroy(&m_cond_mess); + +} +YangSysMessageHandle *YangSysMessageHandle::m_instance = NULL; +void YangSysMessageHandle::run() { + m_isStart = 1; + startLoop(); + //startLoop(); + m_isStart = 0; +} +void YangSysMessageHandle::stop() { + stopLoop(); + +} +void YangSysMessageHandle::stopLoop() { + m_loop = 0; + //pthread_mutex_unlock(&m_lock); + if(m_waitState){ + pthread_mutex_lock(&m_lock); + pthread_cond_signal(&m_cond_mess); + pthread_mutex_unlock(&m_lock); + + } +} + +void YangSysMessageHandle::putMessage(YangSysMessageI *handle, int32_t pst, + int32_t puid, int32_t handleState,void* user) { + if(!m_loop) return; + + YangSysMessage* mes=new YangSysMessage(); + + mes->uid = puid; + mes->messageId = pst; + mes->handleState = handleState; + mes->handle = handle; + mes->user=user; + + m_sysMessages.push_back(mes); + mes=NULL; + + if(m_waitState){ + pthread_mutex_lock(&m_lock); + + pthread_cond_signal(&m_cond_mess); + pthread_mutex_unlock(&m_lock); + } +} + +void YangSysMessageHandle::startLoop() { + m_loop = 1; + + pthread_mutex_unlock(&m_lock); + pthread_mutex_lock(&m_lock); + + while (m_loop) { + + m_waitState=1; + pthread_cond_wait(&m_cond_mess, &m_lock); + m_waitState=0; + + while (m_sysMessages.size()>0) { + handleMessage(m_sysMessages.front()); + m_sysMessages.front()->handle = NULL; + delete m_sysMessages.front(); + m_sysMessages.front() = NULL; + m_sysMessages.erase(m_sysMessages.begin()); + } + + } + pthread_mutex_unlock(&m_lock); +} + diff --git a/libyangrtc2/src/yangutil/YangThread.cpp b/libyangrtc2/src/yangutil/YangThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b835c63909ba97791e113a5980323a45b63f051 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangThread.cpp @@ -0,0 +1,64 @@ + + +#include "yangutil/sys/YangThread.h" +#include "yangutil/sys/YangLog.h" + +YangThread::YangThread(){ +#ifndef _MSC_VER + + m_thread=0; +#endif +} +YangThread::~YangThread(){ + +} + +int32_t YangThread::start() +{ + if (pthread_create( &m_thread, 0, &YangThread::go, this)) + { + yang_error("YangThread::start could not start thread"); + return -1; + } + + return 0; +} + +void* YangThread::go(void* obj) +{ + reinterpret_cast(obj)->run(); + return NULL; +} + +void* YangThread::join() +{ + void* ret; + pthread_join(m_thread, &ret); + return ret; +} + +pthread_t YangThread::getThread() +{ + return m_thread; +} + +int32_t YangThread::detach() +{ + return pthread_detach(m_thread); +} + +int32_t YangThread::equals(YangThread* t) +{ + return pthread_equal(m_thread, t->getThread()); +} + +void YangThread::exitThread(void* value_ptr) +{ + pthread_exit(value_ptr); +} + +int32_t YangThread::cancel() +{ + return pthread_cancel(m_thread); +} + diff --git a/libyangrtc2/src/yangutil/YangTime.cpp b/libyangrtc2/src/yangutil/YangTime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99b281fef972d7e549984a4158a6a3baef883f36 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangTime.cpp @@ -0,0 +1,171 @@ +#include +#include +#ifdef _MSC_VER +#define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */ +#define HECTONANOSEC_PER_SEC 10000000ull + union yang_gettimeofday_type { + unsigned long long ns100; //time since 1 Jan 1601 in 100ns units + FILETIME ft; + } ; +int gettimeofday(struct timeval *tp, void *tzp) +{ + yang_gettimeofday_type t_now; + GetSystemTimeAsFileTime(&t_now.ft); + //100 nano-seconds since 1-1-1970 + t_now.ns100 -= FILETIME_1970; + tp->tv_sec=t_now.ns100 / HECTONANOSEC_PER_SEC; + tp->tv_usec=(t_now.ns100 % HECTONANOSEC_PER_SEC)/10; + + return (0); +} + +#endif +int64_t YangSystime::system_time_us_cache = 0; +int64_t YangSystime::system_time_startup_time = 0; +#ifdef _MSC_VER +int64_t YangSystime::dff = 0; +LARGE_INTEGER YangSystime::large_interger; +#endif + +#define Yang_TIME_RESOLUTION_US 300*1000 +void YangSystime::update_system_time() { //milli weimiao +#ifdef _MSC_VER + if(dff==0){ + QueryPerformanceFrequency(&large_interger); + dff = large_interger.QuadPart; + } + if(system_time_startup_time==0){ + QueryPerformanceCounter(&large_interger); + system_time_startup_time=large_interger.QuadPart; + } + + +#else + if(system_time_startup_time==0) system_time_startup_time = yang_get_micro_time(); +#endif + + +} + +int64_t YangSystime::get_system_micro_time(){ + if(system_time_startup_time==0) update_system_time(); +#ifdef _MSC_VER + + QueryPerformanceCounter(&large_interger); + system_time_us_cache = (large_interger.QuadPart-system_time_startup_time)*1000000/dff; + return system_time_us_cache; +#else + return yang_get_micro_time()-system_time_startup_time; + + +#endif +} + +int64_t YangSystime::get_system_milli_time(){ + if(system_time_startup_time==0) update_system_time(); +#ifdef _MSC_VER + + QueryPerformanceCounter(&large_interger); + return (large_interger.QuadPart-system_time_startup_time)*1000/dff; + +#else + return get_system_micro_time()/1000; +#endif +} + +YangSystime::YangSystime(){ + +} + +YangSystime::~YangSystime(){ + +} + +uint64_t YangNtp::kMagicNtpFractionalUnit = 1ULL << 32; + +YangNtp::YangNtp() +{ + m_system_ms = 0; + m_ntp = 0; + m_ntp_second = 0; + m_ntp_fractions = 0; +} + +YangNtp::~YangNtp() +{ + +} + +YangNtp YangNtp::from_time_ms(uint64_t ms) +{ + YangNtp srs_ntp; + srs_ntp.m_system_ms = ms; + srs_ntp.m_ntp_second = ms / 1000; + srs_ntp.m_ntp_fractions = (static_cast(ms % 1000 / 1000.0)) * kMagicNtpFractionalUnit; + srs_ntp.m_ntp = (static_cast(srs_ntp.m_ntp_second) << 32) | srs_ntp.m_ntp_fractions; + return srs_ntp; +} + +YangNtp YangNtp::to_time_ms(uint64_t ntp) +{ + YangNtp srs_ntp; + srs_ntp.m_ntp = ntp; + srs_ntp.m_ntp_second = (ntp & 0xFFFFFFFF00000000ULL) >> 32; + srs_ntp.m_ntp_fractions = (ntp & 0x00000000FFFFFFFFULL); + srs_ntp.m_system_ms = (static_cast(srs_ntp.m_ntp_second) * 1000) + + (static_cast(static_cast(srs_ntp.m_ntp_fractions) * 1000.0) / kMagicNtpFractionalUnit); + return srs_ntp; +} + + + + +#ifdef _MSC_VER +//haomiao +int64_t yang_get_milli_tick() { + return YangSystime::get_system_milli_time(); + +} + +#else +//haomiao +/**int64_t yang_get_milli_tick() { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); + + +} +//weimiao +int64_t yang_get_micro_tick() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_sec * 1000000 + ts.tv_nsec/1000); +}**/ +//haomiao + +//namiao +int64_t yang_get_nano_tick(){ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_sec * 1000000000 + ts.tv_nsec); +} +#endif + +//haomiao +int64_t yang_get_milli_time() { + struct timeval time; + gettimeofday(&time, 0); + // long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + return (time.tv_sec * 1000) + (time.tv_usec / 1000); + + +} +//weimiao +int64_t yang_get_micro_time() { + struct timeval time; + gettimeofday(&time, 0); + return time.tv_sec * 1000000 + time.tv_usec ; +} + diff --git a/libyangrtc2/src/yangutil/YangTimer.cpp b/libyangrtc2/src/yangutil/YangTimer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7d7e13f55c881edf463ec29036ba3f25c9af419 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangTimer.cpp @@ -0,0 +1,212 @@ +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include +#include +#include +#include + +#if !Yang_Using_Phtread +#ifdef _WIN32 +#pragma comment(lib,"Winmm.lib") +void CALLBACK YangTimer::TimeEvent(PVOID user, BOOLEAN TimerOrWaitFired2) +{ + YangTimer* timer=(YangTimer*)user; + if(timer->m_task) timer->m_task->doTask(timer->m_taskId); + return; +} + +void YangTimer::startWindowsEventTime(int pwaitTime,DWORD_PTR duser) +{ + m_hTimerQueue = CreateTimerQueue(); + if(m_hTimerQueue!=NULL){ + if (!CreateTimerQueueTimer(&m_hTimerQueueTimer, m_hTimerQueue, TimeEvent, this, 0, pwaitTime, WT_EXECUTEDEFAULT)) + { + m_hTimerQueue = NULL; + m_hTimerQueueTimer = NULL; + } + } + + + return; +} +#else +#include +#include +#include + +#endif + +#endif + +YangTimer::YangTimer() { + m_loop = 0; + m_isStart = 0; + m_waitState = 0; + m_waitTime = 100; +#if Yang_Using_Phtread + pthread_mutex_init(&m_lock,NULL); + pthread_cond_init(&m_cond_mess,NULL); + //m_lock = PTHREAD_MUTEX_INITIALIZER; + //m_cond_mess = PTHREAD_COND_INITIALIZER; +#else +#ifdef _WIN32 + m_hTimerQueue=NULL; + m_hTimerQueueTimer=NULL; + m_winEvent=CreateEvent(NULL,TRUE,FALSE,NULL); +#else + m_timerfd = timerfd_create(CLOCK_REALTIME, 0); + m_efd = -1; +#endif + +#endif + m_task = NULL; + m_taskId = 0; +} + +YangTimer::~YangTimer() { + + if (m_isStart) { + stop(); + while (m_isStart) + yang_usleep(1000); + } + m_task = NULL; +#if Yang_Using_Phtread + pthread_mutex_destroy(&m_lock); + pthread_cond_destroy(&m_cond_mess); +#endif +} +void YangTimer::setTaskId(int32_t ptaskId) { + m_taskId = ptaskId; +} +void YangTimer::setTask(YangTimerTask *ptask) { + m_task = ptask; +} +void YangTimer::setTimelen(int32_t ptimelen) { + m_waitTime = ptimelen; +} +void YangTimer::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangTimer::stop() { + stopLoop(); + +} +void YangTimer::stopLoop() { + m_loop = 0; +#if Yang_Using_Phtread + if(m_waitState){ + pthread_mutex_lock(&m_lock); + pthread_cond_signal(&m_cond_mess); + pthread_mutex_unlock(&m_lock); + + } +#else +#ifdef _WIN32 + if (m_hTimerQueueTimer != NULL) + DeleteTimerQueueTimer(m_hTimerQueue, m_hTimerQueueTimer, INVALID_HANDLE_VALUE); + if (m_hTimerQueue != NULL) + DeleteTimerQueueEx(m_hTimerQueue, INVALID_HANDLE_VALUE); + + m_hTimerQueueTimer = NULL; + m_hTimerQueue = NULL; + SetEvent(m_winEvent); +#else + if (m_isStart) { + struct epoll_event tev; + tev.events = EPOLLIN | EPOLLET; + tev.data.fd = m_timerfd; + epoll_ctl(m_efd, EPOLL_CTL_DEL, m_timerfd, &tev); + close(m_efd); + m_efd = -1; + + } + close(m_timerfd); + m_timerfd = -1; + +#endif +#endif +} + +void YangTimer::startLoop() { + m_loop = 1; + //pthread_mutex_unlock(&m_lock); +#if Yang_Using_Phtread + struct timespec outtime; + struct timeval now; + pthread_mutex_lock(&m_lock); + while (m_loop) { + gettimeofday(&now, NULL); + + long nsec = now.tv_usec * 1000 + (m_waitTime % 1000) * 1000000; + outtime.tv_sec=now.tv_sec + nsec / 1000000000 + m_waitTime / 1000; + outtime.tv_nsec=nsec % 1000000000; + + m_waitState=1; + + pthread_cond_timedwait(&m_cond_mess, &m_lock,&outtime); + m_waitState=0; + if(m_task) m_task->doTask(m_taskId); + } + pthread_mutex_unlock(&m_lock); +#else +#ifdef _WIN32 + + startWindowsEventTime(m_waitTime,(DWORD_PTR)this); + if(WaitForSingleObject(m_winEvent,INFINITE) !=WAIT_OBJECT_0) + { + yang_error("YangTimer WaitForSingleObject fail"); + } + + CloseHandle(m_winEvent); + m_winEvent=NULL; +#else + struct itimerspec itimer; + itimer.it_value.tv_sec = m_waitTime / 1000; + itimer.it_value.tv_nsec = (m_waitTime % 1000) * 1000 * 1000; + itimer.it_interval.tv_sec = m_waitTime / 1000; + itimer.it_interval.tv_nsec = (m_waitTime % 1000) * 1000 * 1000; + int ret = timerfd_settime(m_timerfd, TFD_TIMER_ABSTIME, &itimer, NULL); + if (ret == -1) { + yang_error("timerfd_settime"); + } + + int opts; + opts = fcntl(m_timerfd, F_GETFL); + if (opts < 0) { + yang_error("fcntl(sock,GETFL)"); + exit(1); + } + opts = opts | O_NONBLOCK; + if (fcntl(m_timerfd, F_SETFL, opts) < 0) { + yang_error("fcntl(sock,SETFL,opts)"); + exit(1); + } + m_efd = epoll_create(1); + struct epoll_event tev; + tev.events = EPOLLIN | EPOLLET; + tev.data.fd = m_timerfd; + epoll_ctl(m_efd, EPOLL_CTL_ADD, m_timerfd, &tev); + struct epoll_event ev[1]; + while (m_loop) { + int nev = epoll_wait(m_efd, ev, 1, 0); + + if (nev > 0 && (ev[0].events & EPOLLIN)) { + uint64_t res; + int bytes = read(m_timerfd, &res, sizeof(res)); + + if (m_task) + m_task->doTask(m_taskId); + } + } + +#endif +#endif + +} diff --git a/libyangrtc2/src/yangutil/YangUrl.cpp b/libyangrtc2/src/yangutil/YangUrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6081e86a54107a277e5c5453eb469e46f1e5624 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangUrl.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include + + +//webrtc://host[:port]/app/stream +int32_t yang_srs_url_parse(char* url,YangUrlData* data) { + + + char *p = strstr(url, "://"); + if (!p) { + yang_error("Srs Webrt URL: No :// in url!"); + return 1; + } + int32_t len = (int) (p - url); + if (len == 4 && memcmp(url, "rtmp", 4) == 0) { + data->netType = Yang_Rtmp; + data->port=1935; + } else if (len == 6 && memcmp(url, "webrtc", 6) == 0) { + data->netType = Yang_Webrtc; + data->port=1985; + } else { + return 1; + } + p += 3; + if (*p == 0) { + yang_warn("No hostname in URL!"); + return 1; + } + + char *end = p + strlen(p); + char *col = strchr(p, ':'); + //schar *ques = strchr(p, '?'); + char *slash = strchr(p, '/'); + int32_t hostlen; + if (slash) + hostlen = slash - p; + else + hostlen = end - p; + if (col && col - p < hostlen) + hostlen = col - p; + + if (hostlen < 256) { + yang_getIp(std::string(p, hostlen),data->server); + + } else { + yang_warn("Hostname exceeds 255 characters!"); + } + + p += hostlen; + + if (*p == ':') { + uint32_t p2; + p++; + p2 = atoi(p); + if (p2 > 65535) { + yang_warn("Invalid port number!"); + } else { + data->port = p2; + } + } + + if (!slash) { + yang_warn("No application or playpath in URL!"); + return 0; + } + p = slash + 1; + //parse app + char *slash2, *slash3 = NULL, *slash4 = NULL; + int32_t applen, appnamelen; + + slash2 = strchr(p, '/'); + if (slash2) + slash3 = strchr(slash2 + 1, '/'); + if (slash3) + slash4 = strchr(slash3 + 1, '/'); + + applen = end - p; /* ondemand, pass all parameters as app */ + appnamelen = applen; /* ondemand length */ + if (slash4) + appnamelen = slash4 - p; + else if (slash3) + appnamelen = slash3 - p; + else if (slash2) + appnamelen = slash2 - p; + + applen = appnamelen; + data->app = std::string(p, applen); + p += appnamelen; + + //parse streamName + if (*p == '/') + p++; + + if (end - p) { + data->stream = std::string(p, end - p); + } + + return Yang_Ok; +} + + +//http://host:port/path ws://host:port/path wss://host:port/path +int32_t yang_ws_url_parse(char* url,YangUrlData* data) { + + + char *p = strstr(url, "://"); + if (!p) { + yang_error("Ws Webrt URL: No :// in url!"); + return 1; + } + int32_t len = (int) (p - url); + + if (len == 2 && memcmp(url, "ws", 2) == 0) { + data->netType = Yang_Websocket_Ws; + data->port=8088; + }else if (len == 3 && memcmp(url, "wss", 3) == 0) { + data->netType = Yang_Websocket_Wss; + data->port=8089; + }else if (len == 4 && memcmp(url, "http", 4) == 0) { + data->netType = Yang_Websocket_Http; + data->port=8088; + } else if (len == 5 && memcmp(url, "https", 5) == 0) { + data->netType = Yang_Websocket_Https; + data->port=8089; + } else { + return 1; + } + p += 3; + if (*p == 0) { + yang_warn("No hostname in URL!"); + return 1; + } + + char *end = p + strlen(p); + char *col = strchr(p, ':'); + //schar *ques = strchr(p, '?'); + char *slash = strchr(p, '/'); + int32_t hostlen; + if (slash) + hostlen = slash - p; + else + hostlen = end - p; + if (col && col - p < hostlen) + hostlen = col - p; + + if (hostlen < 256) { + data->server = std::string(p, hostlen); + + } else { + yang_warn("Hostname exceeds 255 characters!"); + } + + p += hostlen; + + if (*p == ':') { + uint32_t p2; + p++; + p2 = atoi(p); + if (p2 > 65535) { + yang_warn("Invalid port number!"); + } else { + data->port = p2; + } + } + + if (!slash) { + yang_warn("No application or playpath in URL!"); + return 0; + } + p = slash + 1; + //parse app + char *slash2, *slash3 = NULL, *slash4 = NULL; + int32_t applen, appnamelen; + + slash2 = strchr(p, '/'); + if (slash2) + slash3 = strchr(slash2 + 1, '/'); + if (slash3) + slash4 = strchr(slash3 + 1, '/'); + + applen = end - p; /* ondemand, pass all parameters as app */ + appnamelen = applen; /* ondemand length */ + if (slash4) + appnamelen = slash4 - p; + else if (slash3) + appnamelen = slash3 - p; + else if (slash2) + appnamelen = slash2 - p; + + applen = appnamelen; + data->app = std::string(p, applen); + + + return Yang_Ok; +} + + + + diff --git a/libyangrtc2/src/yangutil/YangWebsocket.cpp b/libyangrtc2/src/yangutil/YangWebsocket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63efce2b38063be6b3e7dc734dbacf1e503ede6f --- /dev/null +++ b/libyangrtc2/src/yangutil/YangWebsocket.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + + + +YangWebsocket::YangWebsocket() { + m_receiveCallback=NULL; + m_isStart=0; +} + +YangWebsocket::~YangWebsocket() { + +} + +void YangWebsocket::setReceiveCallback(YangWebsocketCallback* pcallback){ + m_receiveCallback=pcallback; +} +YangWebsocketCallback* YangWebsocket::getReceiveCallback(){ + return m_receiveCallback; +} + + + +void YangWebsocket::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangWebsocket::stop() { + + stopLoop(); + +} + + + diff --git a/libyangrtc2/src/yangutil/YangWebsocketImpl.cpp b/libyangrtc2/src/yangutil/YangWebsocketImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f078b58236655cb5ba81a183179f442cecf62468 --- /dev/null +++ b/libyangrtc2/src/yangutil/YangWebsocketImpl.cpp @@ -0,0 +1,235 @@ + +#include +#include +#include +#include "YangWebsocketImpl.h" + +#if HaveWebsockets +YangWebsocket* YangWebsocket::getWebsocket(){ + return new YangWebsocketImpl(); +} +int yang_websocket_callback(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { + YangWebsocketImpl *obj = (struct YangWebsocketImpl*) user; + + if(obj==NULL) return 0; + + switch (reason) { + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + { + yang_error("Connected to server fail!\n"); + if(in){ + yang_error("fail reason==%s",(uint8_t*)in); + } + break; + } + case LWS_CALLBACK_CLIENT_ESTABLISHED: // 连接到服务器后的回调 + yang_info("Connected to server ok!\n"); + break; + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + yang_info("Connected to http server ok!\n"); + break; + case LWS_CALLBACK_CLIENT_RECEIVE: // 接收到服务器数据后的回调,数据为in,其长度为len + { + yang_trace("Rx: %s\n", (char* ) in); + /** + YangWebsocketData pdata; + pdata.payload=(uint8_t*)in; + pdata.nb=len; + yang_trace("\nresponse(%d)==%s",len,(uint8_t*)in); + if(obj->getReceiveCallback()) obj->getReceiveCallback()->receive(&pdata); + **/ + break; + } + + case LWS_CALLBACK_CLIENT_WRITEABLE: // 当此客户端可以发送数据时的回调 + { + yang_trace("\n*****LWS_CALLBACK_CLIENT_WRITEABLE "); + if(obj->m_messages.size()>=0) break; + + uint8_t buf[2048]; + + for (size_t i=0;im_messages.size();i++) { + + memset(buf,0,2048); + YangWebsocketData* data=obj->m_messages.front(); + // char *msg = (char*) buf+LWS_PRE; + + memcpy(buf+LWS_PRE,data->payload,data->nb); + yang_trace("\nsend data(%d)=%s",data->nb,buf+LWS_PRE); + obj->yang_lws_write(wsi, buf+LWS_PRE, data->nb,LWS_WRITE_TEXT); + //memcpy(buf,data->payload,data->nb); + //obj->yang_lws_write(wsi, buf, data->nb, LWS_WRITE_HTTP); + + delete data; + obj->m_messages.erase(obj->m_messages.begin()); + } + break; + } + + + + } + return Yang_Ok; +} +YangWebsocketImpl::YangWebsocketImpl() { + m_context = NULL; + m_wsi=NULL; + m_loop=0; + m_ssl=false; + m_lib.loadObject("libwebsockets"); + loadLib(); +} + +YangWebsocketImpl::~YangWebsocketImpl() { + disconnectServer(); +} + +void YangWebsocketImpl::loadLib(){ + yang_lws_set_log_level=(void (*)(int level, lws_log_emit_t log_emit_function))m_lib.loadFunction("lws_set_log_level"); + yang_lws_create_context=(struct lws_context * (*)(const struct lws_context_creation_info *info))m_lib.loadFunction("lws_create_context"); + yang_lws_write=(int (*)(struct lws *wsi, unsigned char *buf, size_t len, enum lws_write_protocol protocol))m_lib.loadFunction("lws_write"); + yang_lws_client_connect_via_info=(struct lws* (*)(const struct lws_client_connect_info *ccinfo))m_lib.loadFunction("lws_client_connect_via_info"); + yang_lws_context_destroy=(void (*)(struct lws_context *context))m_lib.loadFunction("lws_context_destroy"); + yang_lws_service=(int (*)(struct lws_context *context, int timeout_ms))m_lib.loadFunction("lws_service"); + yang_lws_callback_on_writable=(int (*)(struct lws *wsi))m_lib.loadFunction("lws_callback_on_writable"); + yang_lws_http_client_read=(int (*)(struct lws *wsi, char **buf, int *len))m_lib.loadFunction("lws_http_client_read"); + yang_lws_add_http_header_by_token=(int (*)(struct lws *wsi, enum lws_token_indexes token, + const unsigned char *value, int length, + unsigned char **p, unsigned char *end))m_lib.loadFunction("lws_add_http_header_by_token"); + yang_lws_client_http_body_pending=(void (*)(struct lws *wsi, int something_left_to_send))m_lib.loadFunction("lws_client_http_body_pending"); +} + +void YangWebsocketImpl::unloadLib(){ + yang_lws_set_log_level=NULL; + yang_lws_create_context=NULL; + yang_lws_write=NULL; + yang_lws_client_connect_via_info=NULL; + yang_lws_context_destroy=NULL; + yang_lws_service=NULL; + yang_lws_callback_on_writable=NULL; + yang_lws_http_client_read=NULL; + yang_lws_add_http_header_by_token=NULL; + yang_lws_client_http_body_pending=NULL; +} +int YangWebsocketImpl::init() { + //bool ssl = protocol == "wss" ? true : false; //确认是否进行SSL加密 + yang_lws_set_log_level(7, NULL); + + + memset(&info, 0, sizeof(info)); + /** const struct lws_protocols protocols[] = { + {"ws",yang_websocket_callback,0,2048 + }, + + {NULL, NULL, 0, 0}};**/ + static const struct lws_protocols protocols[] = { + { + "ws-client", + yang_websocket_callback, + 0, 4096, 0, NULL, 0 + }, + LWS_PROTOCOL_LIST_TERM + }; + + info.protocols = protocols; //设置处理协议 + info.port = CONTEXT_PORT_NO_LISTEN; //作为ws客户端,无需绑定端口 + //ws和wss的初始化配置不同 + info.options = m_ssl ? LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT : 0; //如果是wss,需要做全局SSL初始化 + //info.options |= LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; + info.gid = (gid_t)-1; + info.uid = (uid_t)-1; + + char cerpath[255]={0}; + char privatekey[255]={0}; + + yang_getCaFile(cerpath,privatekey); + + info.client_ssl_cert_filepath=cerpath; + info.client_ssl_private_key_filepath=privatekey; + info.client_ssl_private_key_password="yangrtc"; + //info.client_ssl_ca_filepath=cerpath; + m_context = yang_lws_create_context(&info); //创建连接上下文 + if (m_context == NULL) { + yang_error("create context error\n"); + return 1; + } + + memset(&conn_info, 0, sizeof(struct lws_client_connect_info)); + char addr_port[256] = { 0 }; + sprintf(addr_port, "%s:%u", m_urlData.server.c_str(), m_urlData.port & 65535 ); + //初始化连接信息 + conn_info.context = m_context; //设置上下文 + conn_info.address = m_urlData.server.c_str(); //设置目标主机IP + conn_info.port = m_urlData.port; //设置目标主机服务端口 + conn_info.path = "./";//m_urlData.app.c_str(); //设置目标主机服务PATH + conn_info.host = m_urlData.server.c_str();//addr_port; //设置目标主机IP + conn_info.origin = m_urlData.server.c_str();//addr_port; //设置目标主机IP + //conn_info.pwsi = &m_wsi; //设置wsi句柄 + conn_info.userdata =(void*)this;//NULL; //userdata 指针会传递给callback的user参数,一般用作自定义变量传入 + conn_info.protocol = protocols[0].name; + //conn_info.ietf_version_or_minus_one=-1; + + + //conn_info.method="POST"; + //ws/wss需要不同的配置 + int usessl= LCCSCF_USE_SSL | + LCCSCF_ALLOW_SELFSIGNED | + LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; + //LCCSCF_ALLOW_INSECURE) + conn_info.ssl_connection = m_ssl ? usessl: 0; + m_wsi = yang_lws_client_connect_via_info(&conn_info); + + if(m_wsi==NULL){ + return yang_error_wrap(1,"lws_client_connect_via_info error!"); + } + //yang_trace("\ninit ws sucess!"); + // lws_client_connect_via_info(&ci); //使连接信息生效 + + return Yang_Ok; +} +int YangWebsocketImpl::connectServer(std::string url) { + + if(yang_ws_url_parse((char*)url.c_str(),&m_urlData)) return 1; + yang_trace("\nserver==%s,port==%d,path==%s",m_urlData.server.c_str(),m_urlData.port,m_urlData.app.c_str()); + m_ssl=(m_urlData.netType==Yang_Websocket_Wss||m_urlData.netType==Yang_Websocket_Https); + int err=Yang_Ok; + if((err=init())==Yang_Ok) { + start(); + }else{ + return yang_error_wrap(err,"websocket init error!"); + } + return err; +} +int YangWebsocketImpl::disconnectServer() { + stop(); + yang_stop_thread(this); +// yang_delete(m_wsi); + if(m_context) yang_lws_context_destroy(m_context); + m_context=NULL; + return Yang_Ok; +} + +int YangWebsocketImpl::sendData(uint8_t *p, int nb) { + m_messages.push_back(new YangWebsocketData()); + memcpy(m_messages.back()->payload,p,nb); + m_messages.back()->nb=nb; + yang_lws_callback_on_writable(m_wsi); +// yang_trace("\nsend data len==%d",nb); + return Yang_Ok; +} + +void YangWebsocketImpl::startLoop() { + m_loop=1; + + while (m_loop) { + + yang_lws_service(m_context, 500); + //yang_lws_callback_on_writable(m_wsi); + } + +} +void YangWebsocketImpl::stopLoop() { + m_loop=0; +} +#endif diff --git a/libyangrtc2/src/yangutil/YangWebsocketImpl.h b/libyangrtc2/src/yangutil/YangWebsocketImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..d2562f0501887f5831893c987f464e004771575c --- /dev/null +++ b/libyangrtc2/src/yangutil/YangWebsocketImpl.h @@ -0,0 +1,54 @@ +#ifndef SRC_YANGUTIL_YANGWEBSOCKETIMPL_H_ +#define SRC_YANGUTIL_YANGWEBSOCKETIMPL_H_ +#include +#include +#include +#include +#if HaveWebsockets +class YangWebsocketImpl :public YangWebsocket{ +public: + YangWebsocketImpl(); + virtual ~YangWebsocketImpl(); + int init(); + int connectServer(std::string url); + int disconnectServer(); + + int sendData(uint8_t* p,int nb); + + + std::vector m_messages; + void (*yang_lws_set_log_level)(int level, lws_log_emit_t log_emit_function); + int (*yang_lws_write)(struct lws *wsi, unsigned char *buf, size_t len, enum lws_write_protocol protocol); + int (*yang_lws_callback_on_writable)(struct lws *wsi); + int (*yang_lws_http_client_read)(struct lws *wsi, char **buf, int *len); + int (*yang_lws_add_http_header_by_token)(struct lws *wsi, enum lws_token_indexes token, + const unsigned char *value, int length, + unsigned char **p, unsigned char *end); + void (*yang_lws_client_http_body_pending)(struct lws *wsi, int something_left_to_send); +protected: + + void startLoop(); + void stopLoop(); + + +private: + int m_loop; + bool m_ssl; + struct lws_context *m_context; + struct lws *m_wsi; + struct lws_context_creation_info info; + struct lws_client_connect_info conn_info; +private: + YangLoadLib m_lib; + void loadLib(); + void unloadLib(); + struct lws_context* (*yang_lws_create_context)(const struct lws_context_creation_info *info); + + struct lws* (*yang_lws_client_connect_via_info)(const struct lws_client_connect_info *ccinfo); + void (*yang_lws_context_destroy)(struct lws_context *context); + int (*yang_lws_service)(struct lws_context *context, int timeout_ms); + +}; + +#endif +#endif /* SRC_YANGUTIL_YANGWEBSOCKETIMPL_H_ */ diff --git a/libyangrtc2/src/yangutil/YangWindowsMouse.cpp b/libyangrtc2/src/yangutil/YangWindowsMouse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..098bb6e9a7fe23e7e6da352c2986f51609f54a8e --- /dev/null +++ b/libyangrtc2/src/yangutil/YangWindowsMouse.cpp @@ -0,0 +1,156 @@ + +#include +#ifdef _WIN32 + +YangWindowsMouse::YangWindowsMouse() +{ + +} + +YangWindowsMouse::~YangWindowsMouse() +{ + +} + +void YangWindowsMouse::moveTo(int x, int y) +{ + p.x = x; + p.y = y; + SetCursorPos(x, y); +} + + +void YangWindowsMouse::relativeMove(int cx, int cy) +{ + GetCursorPos(&p); + p.x += cx; + p.y += cy; + SetCursorPos(p.x, p.y); +} + + +void YangWindowsMouse::setPos() +{ + GetCursorPos(&p); +} + + +void YangWindowsMouse::restorePos() +{ + SetCursorPos(p.x, p.y); +} + + +void YangWindowsMouse::lockMouse() +{ + POINT pt; + RECT rt; + + GetCursorPos(&pt); + rt.left = rt.right = pt.x; + rt.top = rt.bottom = pt.y; + rt.right++; + rt.bottom++; + ClipCursor(&rt); +} + + +void YangWindowsMouse::unlockMouse() +{ + ClipCursor(NULL); +} + + +void YangWindowsMouse::leftBClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::leftbDClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, p.x, p.y, 0, 0); + mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::leftBDown() +{ + setPos(); + mouse_event(MOUSEEVENTF_LEFTDOWN, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::leftBUp() +{ + setPos(); + mouse_event(MOUSEEVENTF_LEFTUP, p.x, p.y, 0, 0); +} + +//middle +void YangWindowsMouse::middleBClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::middleBDbClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP, p.x, p.y, 0, 0); + mouse_event(MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::middleBDown() +{ + setPos(); + mouse_event(MOUSEEVENTF_MIDDLEDOWN, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::middleBUp() +{ + setPos(); + mouse_event(MOUSEEVENTF_MIDDLEUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::middleBRoll(int x,int y,int ch) +{ + setPos(); + mouse_event(MOUSEEVENTF_WHEEL, x, y, ch, 0); +} + +void YangWindowsMouse::rightBClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::rightBDbClick() +{ + setPos(); + mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.x, p.y, 0, 0); + mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::rightBDown() +{ + setPos(); + mouse_event(MOUSEEVENTF_RIGHTDOWN, p.x, p.y, 0, 0); +} + + +void YangWindowsMouse::rightBUp() +{ + setPos(); + mouse_event(MOUSEEVENTF_RIGHTUP, p.x, p.y, 0, 0); +} + +#endif diff --git a/libyangrtc2/src/yangutil/buffer/YangAudioBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangAudioBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..542d9da5abf51da43ee8003c858aeff9c3f96f7b --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangAudioBuffer.cpp @@ -0,0 +1,52 @@ +#include "yangutil/buffer/YangAudioBuffer.h" + +#include +#include "stdio.h" + + + +YangAudioBuffer::YangAudioBuffer(int32_t pcacheNum) +{ + resetIndex(); + m_cache_num=pcacheNum; + m_bufLen=0; +} + +void YangAudioBuffer::reset(){ + resetIndex(); +} + +YangAudioBuffer::~YangAudioBuffer(void) +{ + +} + +void YangAudioBuffer::putAudio(YangFrame* pframe) +{ + if(m_bufLen==0){ + m_bufLen=pframe->nb; + initFrames(m_cache_num,pframe->nb); + } + putFrame(pframe); + +} + +int32_t YangAudioBuffer::getAudio(YangFrame* pframe) +{ + if(size()>0){ + getFrame(pframe); + return 0; + }else + return 1; +} + + +uint8_t *YangAudioBuffer::getAudioRef(YangFrame* pframe) +{ + if(size()>0){ + return getFrameRef(pframe); + }else{ + return NULL; + } +} + diff --git a/libyangrtc2/src/yangutil/buffer/YangAudioEncoderBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangAudioEncoderBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b2bf5cec6ceb44edb6594718a30f3d2153b87dd --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangAudioEncoderBuffer.cpp @@ -0,0 +1,42 @@ +#include "yangutil/buffer/YangAudioEncoderBuffer.h" + +#include "malloc.h" +#include "string.h" + +YangAudioEncoderBuffer::YangAudioEncoderBuffer(int32_t paudioCacheNum) +{ + resetIndex(); + m_cache_num=paudioCacheNum; + initFrames(m_cache_num,1024); + +} + +YangAudioEncoderBuffer::~YangAudioEncoderBuffer() +{ + +} + + +void YangAudioEncoderBuffer::reset(){ + resetIndex(); +} + +void YangAudioEncoderBuffer::putAudio(YangFrame* audioFrame){ + putPlayAudio(audioFrame); +} + +void YangAudioEncoderBuffer::getAudio(YangFrame* audioFrame){ + getPlayAudio(audioFrame); +} +uint8_t* YangAudioEncoderBuffer::getAudioRef(YangFrame* frame){ + return getFrameRef(frame); +} +void YangAudioEncoderBuffer::putPlayAudio(YangFrame* audioFrame){ + putFrame(audioFrame); +} + +void YangAudioEncoderBuffer::getPlayAudio(YangFrame* audioFrame){ + getFrame(audioFrame); +} + + diff --git a/libyangrtc2/src/yangutil/buffer/YangAudioPlayBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangAudioPlayBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..297e30e9e16fbae784965d79e16fe977f801a9b0 --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangAudioPlayBuffer.cpp @@ -0,0 +1,53 @@ +#include "yangutil/buffer/YangAudioPlayBuffer.h" + +#include +#include "stdio.h" + + +YangAudioPlayBuffer::YangAudioPlayBuffer() { + resetIndex(); + m_cache_num = 50; + m_bufLen=0; + +} + +void YangAudioPlayBuffer::reset() { + resetIndex(); +} + +YangAudioPlayBuffer::~YangAudioPlayBuffer(void) { + +} + +void YangAudioPlayBuffer::putAudio(YangFrame* pframe) { + if(m_bufLen==0){ + m_bufLen = pframe->nb; + initFrames(m_cache_num,pframe->nb); + + } + + putFrame(pframe); +} + +void YangAudioPlayBuffer::getAudio(YangFrame* pframe) { + + getFrame(pframe); +} + +uint8_t* YangAudioPlayBuffer::getAudios(YangFrame* pframe) { + if (size() < 1) + return NULL; + return getFrameRef(pframe); + +} +int32_t YangAudioPlayBuffer::getFrameTimestamp(int64_t *ptimestamp) { + + YangFrame* f=getCurFrameRef(); + if(f) *ptimestamp=f->timestamp; + return Yang_Ok; +} +int64_t YangAudioPlayBuffer::getNextTimestamp(){ + return getNextFrameTimestamp(); +} + + diff --git a/libyangrtc2/src/yangutil/buffer/YangBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..537367f8e33795683c2026c6bcce8a1897de35a2 --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangBuffer.cpp @@ -0,0 +1,362 @@ +#include + + +YangBuffer::YangBuffer(char* b, int32_t nn) +{ + p = bytes = b; + nb_bytes = nn; +} +YangBuffer::YangBuffer() +{ + p = bytes = NULL; + nb_bytes = 0; +} +YangBuffer::~YangBuffer() +{ +} +void YangBuffer::init(char* b, int32_t nn) +{ + p = bytes = b; + nb_bytes = nn; +} +YangBuffer* YangBuffer::copy() +{ + YangBuffer* cp = new YangBuffer(bytes, nb_bytes); + cp->p = p; + return cp; +} + +char* YangBuffer::data() +{ + return bytes; +} + +char* YangBuffer::head() +{ + return p; +} + +int32_t YangBuffer::size() +{ + return nb_bytes; +} + +void YangBuffer::set_size(int32_t v) +{ + nb_bytes = v; +} + +int32_t YangBuffer::pos() +{ + return (int)(p - bytes); +} + +int32_t YangBuffer::left() +{ + return nb_bytes - (int)(p - bytes); +} + +bool YangBuffer::empty() +{ + return !bytes || (p >= bytes + nb_bytes); +} + +bool YangBuffer::require(int32_t required_size) +{ + if (required_size < 0) { + return false; + } + + return required_size <= nb_bytes - (p - bytes); +} + +void YangBuffer::skip(int32_t size) +{ + + p += size; +} + +char YangBuffer::read_1bytes() +{ + // //srs_assert(require(1)); + //require(1); + return (char)*p++; +} + +int16_t YangBuffer::read_2bytes() +{ + // //srs_assert(require(2)); + + int16_t value; + char* pp = (char*)&value; + pp[1] = *p++; + pp[0] = *p++; + + return value; +} + +int16_t YangBuffer::read_le2bytes() +{ + ////srs_assert(require(2)); + + int16_t value; + char* pp = (char*)&value; + pp[0] = *p++; + pp[1] = *p++; + + return value; +} + +int32_t YangBuffer::read_3bytes() +{ + // //srs_assert(require(3)); + + int32_t value = 0x00; + char* pp = (char*)&value; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + + return value; +} + +int32_t YangBuffer::read_le3bytes() +{ + ////srs_assert(require(3)); + + int32_t value = 0x00; + char* pp = (char*)&value; + pp[0] = *p++; + pp[1] = *p++; + pp[2] = *p++; + + return value; +} + +int32_t YangBuffer::read_4bytes() +{ + ////srs_assert(require(4)); + + int32_t value; + char* pp = (char*)&value; + pp[3] = *p++; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + + return value; +} + +int32_t YangBuffer::read_le4bytes() +{ + ////srs_assert(require(4)); + + int32_t value; + char* pp = (char*)&value; + pp[0] = *p++; + pp[1] = *p++; + pp[2] = *p++; + pp[3] = *p++; + + return value; +} + +int64_t YangBuffer::read_8bytes() +{ + // //srs_assert(require(8)); + + int64_t value; + char* pp = (char*)&value; + pp[7] = *p++; + pp[6] = *p++; + pp[5] = *p++; + pp[4] = *p++; + pp[3] = *p++; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + + return value; +} + +int64_t YangBuffer::read_le8bytes() +{ + ////srs_assert(require(8)); + + int64_t value; + char* pp = (char*)&value; + pp[0] = *p++; + pp[1] = *p++; + pp[2] = *p++; + pp[3] = *p++; + pp[4] = *p++; + pp[5] = *p++; + pp[6] = *p++; + pp[7] = *p++; + + return value; +} + +string YangBuffer::read_string(int32_t len) +{ + ////srs_assert(require(len)); + + std::string value; + value.append(p, len); + + p += len; + + return value; +} + +void YangBuffer::read_bytes(char* data, int32_t size) +{ + //srs_assert(require(size)); + + memcpy(data, p, size); + + p += size; +} + +void YangBuffer::write_1bytes(char value) +{ + //srs_assert(require(1)); + + *p++ = value; +} + +void YangBuffer::write_2bytes(int16_t value) +{ + //srs_assert(require(2)); + + char* pp = (char*)&value; + *p++ = pp[1]; + *p++ = pp[0]; +} + +void YangBuffer::write_le2bytes(int16_t value) +{ + //srs_assert(require(2)); + + char* pp = (char*)&value; + *p++ = pp[0]; + *p++ = pp[1]; +} + +void YangBuffer::write_4bytes(int32_t value) +{ + //srs_assert(require(4)); + + char* pp = (char*)&value; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; +} + +void YangBuffer::write_le4bytes(int32_t value) +{ + //srs_assert(require(4)); + + char* pp = (char*)&value; + *p++ = pp[0]; + *p++ = pp[1]; + *p++ = pp[2]; + *p++ = pp[3]; +} + +void YangBuffer::write_3bytes(int32_t value) +{ + //srs_assert(require(3)); + + char* pp = (char*)&value; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; +} + +void YangBuffer::write_le3bytes(int32_t value) +{ + //srs_assert(require(3)); + + char* pp = (char*)&value; + *p++ = pp[0]; + *p++ = pp[1]; + *p++ = pp[2]; +} + +void YangBuffer::write_8bytes(int64_t value) +{ + //srs_assert(require(8)); + + char* pp = (char*)&value; + *p++ = pp[7]; + *p++ = pp[6]; + *p++ = pp[5]; + *p++ = pp[4]; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; +} + +void YangBuffer::write_le8bytes(int64_t value) +{ + //srs_assert(require(8)); + + char* pp = (char*)&value; + *p++ = pp[0]; + *p++ = pp[1]; + *p++ = pp[2]; + *p++ = pp[3]; + *p++ = pp[4]; + *p++ = pp[5]; + *p++ = pp[6]; + *p++ = pp[7]; +} + +void YangBuffer::write_string(string value) +{ + //srs_assert(require((int)value.length())); + + memcpy(p, value.data(), value.length()); + p += value.length(); +} + +void YangBuffer::write_bytes(char* data, int32_t size) +{ + //srs_assert(require(size)); + + memcpy(p, data, size); + p += size; +} + +YangBitBuffer::YangBitBuffer(YangBuffer* b) +{ + cb = 0; + cb_left = 0; + stream = b; +} + +YangBitBuffer::~YangBitBuffer() +{ +} + +bool YangBitBuffer::empty() { + if (cb_left) { + return false; + } + return stream->empty(); +} + +char YangBitBuffer::read_bit() { + if (!cb_left) { + //srs_assert(!stream->empty()); + cb = stream->read_1bytes(); + cb_left = 8; + } + + char v = (cb >> (cb_left - 1)) & 0x01; + cb_left--; + return v; +} diff --git a/libyangrtc2/src/yangutil/buffer/YangMediaBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangMediaBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03604d0ab5d541a6c7fb82a77768b25a61ee49a0 --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangMediaBuffer.cpp @@ -0,0 +1,115 @@ +/* + * + * + * Created on: 2020年8月8日 + * Author: yang + */ +#include +#include +#include +#include +#define Yang_MediaBuffer_Minus Yang_MediaBuffer_Maxsize-100 +YangMediaBuffer::YangMediaBuffer() { + resetIndex(); + m_cache_num = 5; + m_mediaType = 1; + m_uid = -1; + m_frames = NULL; + m_bufferManager = NULL; + //m_lock = PTHREAD_MUTEX_INITIALIZER; + //pthread_mutex_init(&m_lock,NULL); +} + + +YangMediaBuffer::~YangMediaBuffer() { + if (m_frames) { + for (int32_t i = 0; i < m_cache_num; i++) { + yang_delete(m_frames[i]); + } + yang_deleteA(m_frames); + } + yang_delete(m_bufferManager); +} + +void YangMediaBuffer::resetIndex() { + m_putIndex = 0; + m_getIndex = 0; + m_nextIndex=0; + m_putSize=0; + m_getSize=0; + m_ret=0; + //m_size = 0; +} +int32_t YangMediaBuffer::size(){ + m_ret=m_putSize-m_getSize; + if(m_ret<0){ + m_ret=0; + checkSize(); + } + return m_ret; +} +void YangMediaBuffer::checkSize(){ + if(m_getSize>m_putSize){ + + if(m_getSize>Yang_MediaBuffer_Minus&&m_putSizepayload = m_bufferManager->getBuffer(); + } + } +} +void YangMediaBuffer::putFrame(YangFrame *pframe) { + if (!pframe||size()>=m_cache_num) return; + if (m_putIndex >= m_cache_num||m_putIndex<0) m_putIndex = 0; + yang_frame_copy_buffer(pframe, m_frames[m_putIndex++]); + m_putSize++; + if(m_putSize>Yang_MediaBuffer_Maxsize){ + m_putSize-=Yang_MediaBuffer_Minus; + } + //setSize(1); +} +void YangMediaBuffer::getFrame(YangFrame *pframe) { + if (!pframe||!size()) return; + if (m_getIndex >= m_cache_num||m_getIndex<0) m_getIndex = 0; + yang_frame_copy_buffer(m_frames[m_getIndex++], pframe); + m_getSize++; + checkSize(); + //setSize(0); +} +uint8_t* YangMediaBuffer::getFrameRef(YangFrame *pframe) { + if (!size()||!pframe) return NULL; + if (m_getIndex >= m_cache_num||m_getIndex<0) m_getIndex = 0; + yang_frame_copy_nobuffer(m_frames[m_getIndex], pframe); + uint8_t *p = m_frames[m_getIndex]->payload; + m_getIndex++; + m_getSize++; + checkSize(); + //setSize(0); + return p; + +} +YangFrame* YangMediaBuffer::getCurFrameRef() { + if(!size()) return NULL; + m_nextIndex=m_getIndex; + if(m_nextIndex>=m_cache_num) m_nextIndex=0; + return m_frames[m_nextIndex]; +} + +int64_t YangMediaBuffer::getNextFrameTimestamp(){ + if(!size()) return 0; + m_nextIndex=m_getIndex; + if(m_nextIndex>=m_cache_num) m_nextIndex=0; + return m_frames[m_nextIndex]->timestamp; + +} + diff --git a/libyangrtc2/src/yangutil/buffer/YangVideoBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangVideoBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f1ac9debdec6503c75a19738aeb5b0eb80d97af --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangVideoBuffer.cpp @@ -0,0 +1,75 @@ +#include + +#include + + +YangVideoBuffer::~YangVideoBuffer(void) +{ + +} + +YangVideoBuffer::YangVideoBuffer(int32_t pBitDepthLen) +{ + reset(); + m_bitDepthLen=pBitDepthLen; + m_frames=0; + m_cache_num = 30; + m_width=0; + m_height=0; + m_length=0; + +} + + +YangVideoBuffer::YangVideoBuffer(int32_t pwid,int32_t phei,YangYuvType ptype,int32_t pBitDepthLen){ + reset(); + m_bitDepthLen=pBitDepthLen; + init(pwid,phei,ptype); + +} +void YangVideoBuffer::init(int32_t pwid,int32_t phei,YangYuvType ptype){ + reset(); + m_width=pwid; + m_height=phei; + m_length=m_width*m_height*3*m_bitDepthLen/2; + if(ptype==YangYuy2) m_length=m_width*m_height*2*m_bitDepthLen; + if(ptype==YangRgb) m_length=m_width*m_height*3*m_bitDepthLen; + if(ptype==YangArgb||ptype==YangBgra) m_length=m_width*m_height*4*m_bitDepthLen; + m_cache_num=30; + initFrames(m_cache_num,m_length); + + m_frames=0; + +} + +void YangVideoBuffer::reset() { + resetIndex(); +} + + +void YangVideoBuffer::putVideo(YangFrame* pframe){ + putFrame(pframe); +} + +void YangVideoBuffer::getVideo(YangFrame* pframe){ + + getFrame(pframe); +} +uint8_t * YangVideoBuffer::getVideoRef(YangFrame* pframe){ + return getFrameRef(pframe); + +} + +int64_t YangVideoBuffer::getTimestamp(int64_t *ptimestamp){ + + YangFrame* f=getCurFrameRef(); + if(f) *ptimestamp=f->timestamp; + return 0; +} + +int64_t YangVideoBuffer::getNextTimestamp(){ + return getNextFrameTimestamp(); +} +YangFrame* YangVideoBuffer::getCurVideoFrame(){ + return getCurFrameRef(); +} diff --git a/libyangrtc2/src/yangutil/buffer/YangVideoDecoderBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangVideoDecoderBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbda9a799aa33100bba8c9701d98cd4f69b2f186 --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangVideoDecoderBuffer.cpp @@ -0,0 +1,27 @@ +//#include "stdafx.h" +#include "yangutil/buffer/YangVideoDecoderBuffer.h" + +#include +#include "memory.h" + + + + +YangVideoDecoderBuffer::YangVideoDecoderBuffer(int num) { + resetIndex(); + m_cache_num = num; + initFrames(m_cache_num,YANG_VIDEO_ENCODE_BUFFER_LEN); +} + +YangVideoDecoderBuffer::~YangVideoDecoderBuffer(void) { + +} + +void YangVideoDecoderBuffer::getEVideo(YangFrame* pframe) { + getFrame(pframe); +} + +void YangVideoDecoderBuffer::putEVideo(YangFrame* pframe) { + putFrame(pframe); +} + diff --git a/libyangrtc2/src/yangutil/buffer/YangVideoEncoderBuffer.cpp b/libyangrtc2/src/yangutil/buffer/YangVideoEncoderBuffer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ea953662d915125c95745f10c3c2b6af6277a70 --- /dev/null +++ b/libyangrtc2/src/yangutil/buffer/YangVideoEncoderBuffer.cpp @@ -0,0 +1,32 @@ + +#include "yangutil/buffer/YangVideoEncoderBuffer.h" + +#include +#include "string.h" + +YangVideoEncoderBuffer::YangVideoEncoderBuffer(int pcachenum) +{ + resetIndex(); + m_cache_num=pcachenum; + initFrames(m_cache_num,YANG_VIDEO_ENCODE_BUFFER_LEN); + +} + +YangVideoEncoderBuffer::~YangVideoEncoderBuffer(void) +{ + +} + + +void YangVideoEncoderBuffer::getEVideo(YangFrame* pframe){ + + getFrame(pframe); +} +uint8_t * YangVideoEncoderBuffer::getEVideoRef(YangFrame* frame){ + return getFrameRef(frame); + +} +void YangVideoEncoderBuffer::putEVideo(YangFrame* pframe){ + putFrame(pframe); +} + diff --git a/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.cpp b/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8b500309b6d4f21466c03e1b5ba9b4ece51254f --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.cpp @@ -0,0 +1,455 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +YangH264RecvTrack::YangH264RecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque) { + + + + m_key_frame_ts = -1; + m_lost_sn = 0; + m_header_sn = 0; + m_hasRequestKeyframe = false; + + m_hasReceiveStap=-1; + + memset(m_cache_video_pkts, 0, s_cache_size*sizeof(YangRtcPacketCache)); + m_video_buffer=new char[YANG_VIDEO_ENCODE_BUFFER_LEN]; + memset(m_video_buffer,0,YANG_VIDEO_ENCODE_BUFFER_LEN); + + memset(&m_stapData,0,sizeof(YangRtpSTAPData)); + m_stapData.nalus=new std::vector(); + + m_recvcb=NULL; + m_uid=uid; + m_session=session; + m_track_desc=track_desc; + + memset(&m_videoFrame,0,sizeof(YangFrame)); +} + + +YangH264RecvTrack::~YangH264RecvTrack() { + + yang_deleteA(m_video_buffer); + yang_reset_h2645_stap(&m_stapData); + yang_delete(m_stapData.nalus); +} + + +void YangH264RecvTrack::setReceiveCallback(YangReceiveCallback *cbk) { + m_recvcb = cbk; +} +int32_t YangH264RecvTrack::packet_video(const uint16_t start, + const uint16_t end) { + int32_t err = Yang_Ok; + uint16_t cnt = end - start + 1; + YangRtcPacketCache *header = &m_cache_video_pkts[cache_index(start)]; + int64_t timestamp = header->ts; + char* p=m_video_buffer; + if (is_keyframe(header)) { + *p++=0x17; // type(4 bits): key frame; code(4bits): avc + m_key_frame_ts = -1; + } else { + *p++=0x27;// type(4 bits): inter frame; code(4bits): avc + } + *p++=0x01; + *p++=0x00; + *p++=0x00; + *p++=0x00; + + int32_t nalu_len = 0; + for (uint16_t i = 0; i < cnt; ++i) { + uint16_t index = cache_index((start + i)); + YangRtcPacketCache *pkt = &m_cache_video_pkts[index]; + m_cache_video_pkts[index].in_use = false; + + if(pkt->nalu_type==kFuA){ + if (pkt->nb > 0) { + if (pkt->fua2.start) { + nalu_len = pkt->nb + 1; + p+=4; + *p++=pkt->fua2.nri | pkt->fua2.nalu_type; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + } else { + nalu_len += pkt->nb; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + if (pkt->fua2.end) { + //write nalu_len back + yang_put_be32(p-(4 + nalu_len),nalu_len); + } + } + pkt->fua2.start = pkt->fua2.end = false; + pkt->fua2.nri = pkt->fua2.nalu_type = (YangAvcNaluType) 0; + continue; + } + } + + if (pkt->nalu_type==kStapA) { + + if(m_hasReceiveStap>-1&&m_hasReceiveStap==pkt->sn){ + m_hasReceiveStap=-1; + continue; + }else{ + YangBuffer stap_buf(pkt->payload,pkt->nb); + yang_reset_h2645_stap(&m_stapData); + yang_decode_h264_stap(&stap_buf,&m_stapData); + //m_stap.decode(&stap_buf); + + for (int32_t j = 0; j < (int) m_stapData.nalus->size(); ++j) { + YangSample *sample = m_stapData.nalus->at(j); + if (sample->nb > 0) { + yang_put_be32(p,sample->nb); + p+=4; + memcpy(p,sample->bytes, sample->nb); + p+=sample->nb; + } + } + yang_reset_h2645_stap(&m_stapData); + continue; + } + + } + if(pkt->payload){ + + if (pkt->nb> 0) { + yang_put_be32(p,pkt->nb); + p+=4; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + + pkt->payload=NULL; + + continue; + } + } + memset(&m_cache_video_pkts[i],0,sizeof(struct YangRtcPacketCache)); + } + + if ((err = put_frame_video(m_video_buffer, timestamp, p-m_video_buffer)) != Yang_Ok) { + yang_warn("fail to pack video frame"); + } + + m_header_sn = end + 1; + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_header_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + err = packet_video(m_header_sn, tail_sn); + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = sn; + } + + return err; +} + +int32_t YangH264RecvTrack::packet_video_key_frame(YangRtpPacket *pkt) { + int32_t err = Yang_Ok; + uint16_t index = cache_index(pkt->m_header.sequence); + + if (pkt->m_nalu_type == kStapA) { + YangBuffer stap_buf(pkt->m_payload, pkt->m_nb); + yang_reset_h2645_stap(&m_stapData); + yang_decode_h264_stap(&stap_buf, &m_stapData); + YangSample *sps = yang_get_h264_stap_sps(&m_stapData); //m_stap.get_sps(); + YangSample *pps = yang_get_h264_stap_pps(&m_stapData); //m_stap.get_pps(); + if (NULL == sps || NULL == pps) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "no sps or pps in stap-a rtp. sps: %p, pps:%p", sps, pps); + } else { + int32_t metaLen=0; + yang_getConfig_Meta_H264(sps,pps,(uint8_t*)m_video_buffer,&metaLen); + + m_hasReceiveStap = pkt->m_header.sequence; + yang_reset_h2645_stap(&m_stapData); + if(metaLen>0){ + if ((err = put_frame_video(m_video_buffer, 0, metaLen)) + != Yang_Ok) { + return err; + } + } + + } + } + if (-1 == m_key_frame_ts) { + m_key_frame_ts = pkt->m_header.timestamp; + m_header_sn = pkt->m_header.sequence; + m_lost_sn = m_header_sn + 1; + // Received key frame and clean cache of old p frame pkts + clear_cached_video(); + //yang_trace("set ts=%lld, header=%hu, lost=%hu", key_frame_ts_, header_sn_, lost_sn_); + } else if (m_key_frame_ts != pkt->m_header.timestamp) { + //new key frame, clean cache + + m_key_frame_ts = pkt->m_header.timestamp; + m_header_sn = pkt->m_header.sequence; + m_lost_sn = m_header_sn + 1; + clear_cached_video(); + + } + + + m_cache_video_pkts[index].in_use = true; + copy(pkt,&m_cache_video_pkts[index]); + + int32_t sn = m_lost_sn; + uint16_t tail_sn = 0; + if (yang_rtp_seq_distance(m_header_sn, pkt->m_header.sequence) < 0) { + // When receive previous pkt in the same frame, update header sn; + m_header_sn = pkt->m_header.sequence; + sn = find_next_lost_sn(m_header_sn, tail_sn); + } else if (m_lost_sn == pkt->m_header.sequence) { + sn = find_next_lost_sn(m_lost_sn, tail_sn); + } + + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + if ((err = packet_video(m_header_sn, tail_sn)) != Yang_Ok) { + err = yang_error_wrap(err, "fail to packet key frame"); + } + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = (uint16_t) sn; + } + + return err; +} + +void YangH264RecvTrack::clear_cached_video() { + for (size_t i = 0; i < s_cache_size; i++) { + if (m_cache_video_pkts[i].in_use) { + memset(&m_cache_video_pkts[i],0,sizeof(struct YangRtcPacketCache)); + } + } +} + + + +int32_t YangH264RecvTrack::put_frame_video(char *p, int64_t timestamp, + int32_t nb) { + + m_videoFrame.uid = m_uid; + m_videoFrame.payload = (uint8_t*) p; + m_videoFrame.nb = nb; + m_videoFrame.timestamp = timestamp; + if (m_recvcb) m_recvcb->receiveVideo(&m_videoFrame); + + + return Yang_Ok; +} + +bool YangH264RecvTrack::check_frame_complete(const uint16_t start, + const uint16_t end) { + uint16_t cnt = (end - start + 1); + uint16_t fu_s_c = 0; + uint16_t fu_e_c = 0; + for (uint16_t i = 0; i < cnt; ++i) { + int32_t index = cache_index((start + i)); + YangRtcPacketCache *pkt = &m_cache_video_pkts[index]; + if (pkt->nalu_type == kFuA) { + if (pkt->fua2.start) { + ++fu_s_c; + } + + if (pkt->fua2.end) { + ++fu_e_c; + } + } + } + + return fu_s_c == fu_e_c; +} + +int32_t YangH264RecvTrack::find_next_lost_sn(uint16_t current_sn, + uint16_t &end_sn) { + uint32_t last_ts = m_cache_video_pkts[cache_index(m_header_sn)].ts; + for (int32_t i = 0; i < s_cache_size; ++i) { + uint16_t lost_sn = current_sn + i; + int32_t index = cache_index(lost_sn); + + if (!m_cache_video_pkts[index].in_use) { + return lost_sn; + } + //check time first, avoid two small frame mixed case decode fail + if (last_ts != m_cache_video_pkts[index].ts) { + end_sn = lost_sn - 1; + return -1; + } + + if (m_cache_video_pkts[index].end) { + end_sn = lost_sn; + return -1; + } + } + + yang_error("the cache is mess. the packet count of video frame is more than %u", + s_cache_size); + return -2; +} + +bool YangH264RecvTrack::is_keyframe(YangRtpPacket *pkt) { + // It's normal H264 video rtp packet + if (pkt->m_nalu_type == kStapA) { + + YangAvcNaluType nalu_type = (YangAvcNaluType) ((*(pkt->m_payload+3)) + & kNalTypeMask); + if (nalu_type == YangAvcNaluTypeSPS + || nalu_type == YangAvcNaluTypePPS) { + return true; + } + } else if (pkt->m_nalu_type == kFuA) { + uint8_t v = (uint8_t)(*(pkt->m_payload+1)); + if (YangAvcNaluTypeIDR == YangAvcNaluType(v & kNalTypeMask)) + return true; + + } else { + if ((pkt->m_nalu_type == YangAvcNaluTypeIDR) + || (pkt->m_nalu_type == YangAvcNaluTypeSPS) + || (pkt->m_nalu_type == YangAvcNaluTypePPS)) { + return true; + } + } + return false; +} + +bool YangH264RecvTrack::is_keyframe(YangRtcPacketCache *pkt) { + // It's normal H264 video rtp packet + if (pkt->nalu_type == kStapA) { + + YangAvcNaluType nalu_type = (YangAvcNaluType) ((*(pkt->payload+3)) + & kNalTypeMask); + if (nalu_type == YangAvcNaluTypeSPS + || nalu_type == YangAvcNaluTypePPS) { + return true; + } + } else if (pkt->nalu_type == kFuA) { + uint8_t v = (uint8_t)(*pkt->payload); + if (YangAvcNaluTypeIDR == YangAvcNaluType(v & kNalTypeMask)) return true; + + } else { + if ((pkt->nalu_type == YangAvcNaluTypeIDR) + || (pkt->nalu_type == YangAvcNaluTypeSPS) + || (pkt->nalu_type == YangAvcNaluTypePPS)) { + return true; + } + } + return false; +} + +int32_t YangH264RecvTrack::on_rtp(YangRtpPacket *src) { + int32_t err = Yang_Ok; + if (!m_hasRequestKeyframe) { + m_session->send_rtcp_fb_pli(m_track_desc->ssrc_); + + } + src->m_nalu_type = YangAvcNaluType((uint8_t) (src->m_payload[0] & kNalTypeMask)); + + if (is_keyframe(src)) { + m_hasRequestKeyframe = true; + return packet_video_key_frame(src); + } + +// if(src->m_nalu_type<=YangAvcNaluTypeCodedSliceExt){ +// if(src->m_header.marker) { +// packet_video_Raw(src); +// return Yang_Ok; +// } +// +// } + // store in cache + + int32_t index = cache_index(src->m_header.sequence); + m_cache_video_pkts[index].in_use = true; + copy(src,&m_cache_video_pkts[index]); + + + // check whether to recovery lost packet and can construct a video frame + if (m_lost_sn == src->m_header.sequence) { + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_lost_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + if ((err = packet_video(m_header_sn, tail_sn)) != Yang_Ok) { + err = yang_error_wrap(err, "fail to pack video frame"); + } + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "video cache is overflow"); + } else { + m_lost_sn = (uint16_t) sn; + } + } + + return err; +} + + + +void YangH264RecvTrack::copy(YangRtpPacket *src, YangRtcPacketCache *pkt) { + pkt->sn = src->m_header.sequence; + pkt->end = src->m_header.marker; + + // For performance issue, do not copy the unused field. + + pkt->ts = src->m_header.timestamp; + pkt->nalu_type = src->m_nalu_type; + + pkt->payload = src->m_payload; + pkt->nb = src->m_nb; + + if (pkt->nalu_type == kFuA) { + m_buf.init(src->m_payload, src->m_nb); + yang_decode_h264_fua2(&m_buf,&pkt->fua2); + pkt->payload = m_buf.head(); + pkt->nb = m_buf.left(); + } +} + + +int32_t YangH264RecvTrack::packet_video_Raw(YangRtpPacket* pkt){ + int err=Yang_Ok; + char* p=m_video_buffer; + int64_t timestamp=pkt->m_header.timestamp; + *p++=0x27;// type(4 bits): inter frame; code(4bits): avc + *p++=0x01; + *p++=0x00; + *p++=0x00; + *p++=0x00; + yang_put_be32(p,pkt->m_nb); + p+=4; + memcpy(p,pkt->m_payload,pkt->m_nb); + p+=pkt->m_nb; + if ((err = put_frame_video(m_video_buffer, timestamp, p-m_video_buffer)) != Yang_Ok) { + yang_warn("fail to pack video frame"); + } + + m_header_sn = pkt->m_header.sequence + 1; + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_header_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + err = packet_video(m_header_sn, tail_sn); + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = sn; + } + + return err; +} diff --git a/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.h b/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..da9fbf68a55ee6ae1250351fe4439b10f812e830 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH264RecvTrack.h @@ -0,0 +1,66 @@ +#ifndef SRC_YANGWEBRTC_YangH264RecvTrack_H_ +#define SRC_YANGWEBRTC_YangH264RecvTrack_H_ +#include +#include + + + + +class YangH264RecvTrack{ +public: + YangH264RecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *stream_descs, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque); + virtual ~YangH264RecvTrack(); + bool m_hasRequestKeyframe; +public: + int32_t on_rtp(YangRtpPacket *pkt); + void setReceiveCallback(YangReceiveCallback *cbk); +private: + uint16_t m_header_sn; + uint16_t m_lost_sn; + int32_t m_hasReceiveStap; + int64_t m_key_frame_ts; + + YangRtpSTAPData m_stapData; + YangBuffer m_buf; + YangFrame m_videoFrame; + char* m_video_buffer; + YangReceiveCallback *m_recvcb; + int32_t m_uid; + YangRtcSessionI *m_session; + YangRtcTrack *m_track_desc; + +private: + int32_t put_frame_video(char *p, int64_t timestamp, int32_t nb); + int32_t put_frame_mixvideo(char *p, int64_t timestamp, int32_t nb); + + const static uint16_t s_cache_size = 1024; + struct YangRtcPacketCache { + bool in_use; + bool end; + uint16_t sn; + uint32_t ts; + int32_t nalu_type; + int32_t nb; + Fua2H264DataCache fua2; + char *payload; + }; + YangRtcPacketCache m_cache_video_pkts[1024]; + void clear_cached_video(); + inline uint16_t cache_index(uint16_t current_sn) { + //return current_sn % s_cache_size; + return current_sn&1023; + } + + bool check_frame_complete(const uint16_t start, const uint16_t end); + int32_t find_next_lost_sn(uint16_t current_sn, uint16_t &end_sn); + int32_t packet_video_Raw(YangRtpPacket* pkt); + int32_t packet_video(const uint16_t start, const uint16_t end); + int32_t packet_video_key_frame(YangRtpPacket *pkt); + + bool is_keyframe(YangRtpPacket* pkt); + bool is_keyframe(YangRtcPacketCache* pkt); + void copy(YangRtpPacket* src,YangRtcPacketCache* pkt); +}; +#endif /* SRC_YANGWEBRTC_YANGRTCVIDEORECVTRACK_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.cpp b/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5883e21075b0edbc4b131f4604ecf988b6a8877c --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.cpp @@ -0,0 +1,264 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +YangH264RtpEncode::YangH264RtpEncode() { + m_videoSsrc = 0; + m_videoSeq = 0; + m_audioSeq = 0; + m_audioSsrc = 0; + m_rtpBuffer = NULL; + m_session = NULL; + m_videoBuf = new char[kRtpPacketSize]; + memset(&m_stapData,0,sizeof(YangRtpSTAPData)); + m_stapData.nalus=new std::vector(); +} + +YangH264RtpEncode::~YangH264RtpEncode() { + m_session = NULL; + yang_deleteA(m_videoBuf); + yang_reset_h2645_stap(&m_stapData); + yang_delete(m_stapData.nalus); +} +void YangH264RtpEncode::init(YangRtpBuffer *rtpBuffer, + YangRtcSessionI *psession) { + m_rtpBuffer = rtpBuffer; + m_session = psession; +} +int32_t YangH264RtpEncode::on_audio(YangStreamCapture *audioFrame) { + int err = 0; + m_audioRawPacket.reset(); + m_audioRawPacket.m_header.payload_type=kAudioPayloadType; + m_audioRawPacket.m_header.ssrc=m_audioSsrc; + m_audioRawPacket.m_frame_type = YangFrameTypeAudio; + m_audioRawPacket.m_header.marker=true; + + m_audioRawPacket.m_header.sequence=m_audioSeq++; + m_audioRawPacket.m_header.timestamp=audioFrame->getAudioTimestamp(); + m_audioRawPacket.m_header.padding_length=0; + m_audioRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + + m_audioRawData.payload = m_videoBuf; + m_audioRawData.nb = audioFrame->getAudioLen(); + memcpy(m_audioRawData.payload, audioFrame->getAudioData(), m_audioRawData.nb); + if ((err = encodeAudio(&m_audioRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + return err; +} +int32_t YangH264RtpEncode::on_h264_video(YangStreamCapture *videoFrame) { + int32_t err = Yang_Ok; + + if (videoFrame->getVideoLen() <= kRtpMaxPayloadSize) { + if ((err = package_single_nalu(videoFrame)) != Yang_Ok) { + return yang_error_wrap(err, "package single nalu"); + } + } else { + if ((err = package_fu_a(videoFrame, kRtpMaxPayloadSize)) != Yang_Ok) { + return yang_error_wrap(err, "package fu-a"); + } + } + + return err; +} + +int32_t YangH264RtpEncode::package_single_nalu(YangStreamCapture *videoFrame) { + int32_t err = Yang_Ok; + + m_videoRawPacket.reset(); + m_videoRawPacket.m_header.payload_type=kVideoPayloadType; + m_videoRawPacket.m_header.ssrc=m_videoSsrc; + m_videoRawPacket.m_frame_type = YangFrameTypeVideo; + m_videoRawPacket.m_header.sequence=m_videoSeq++; + m_videoRawPacket.m_header.timestamp=videoFrame->getVideoTimestamp(); + m_videoRawPacket.m_header.marker=true; + m_videoRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + //memset(&m_raw_video,0,sizeof(YangRtpRawPayload)); + m_videoRawData.payload = m_videoBuf; + m_videoRawData.nb = videoFrame->getVideoLen(); + memcpy(m_videoRawData.payload, videoFrame->getVideoData(), m_videoRawData.nb); + if ((err = encodeVideo(&m_videoRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + return err; +} +int32_t YangH264RtpEncode::package_single_nalu(char *p, int32_t plen, + int64_t timestamp) { + + int32_t err = Yang_Ok; + m_videoRawPacket.reset(); + m_videoRawPacket.m_header.payload_type=kVideoPayloadType; + m_videoRawPacket.m_header.ssrc=m_videoSsrc; + m_videoRawPacket.m_frame_type = YangFrameTypeVideo; + m_videoRawPacket.m_header.sequence=m_videoSeq++; + m_videoRawPacket.m_header.timestamp=timestamp; + + + m_videoRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + m_videoRawData.payload = m_videoBuf; + m_videoRawData.nb = plen; + memcpy(m_videoRawData.payload, p, plen); + if ((err = encodeVideo(&m_videoRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + return err; +} +int32_t YangH264RtpEncode::package_fu_a(YangStreamCapture *videoFrame, + int32_t fu_payload_size) { + int32_t err = Yang_Ok; + int32_t plen = videoFrame->getVideoLen(); + uint8_t *pdata = videoFrame->getVideoData(); + char *p = (char*) pdata + 1; + int32_t nb_left = plen - 1; + uint8_t header = pdata[0]; + uint8_t nal_type = header & kNalTypeMask; + + int32_t num_of_packet = ((plen - 1) % fu_payload_size==0)?0:1 + (plen - 1) / fu_payload_size; + for (int32_t i = 0; i < num_of_packet; ++i) { + int32_t packet_size = yang_min(nb_left, fu_payload_size); + m_videoFuaPacket.reset(); + m_videoFuaPacket.m_header.payload_type=kVideoPayloadType; + m_videoFuaPacket.m_header.ssrc=m_videoSsrc; + m_videoFuaPacket.m_frame_type = YangFrameTypeVideo; + m_videoFuaPacket.m_header.sequence=m_videoSeq++; + m_videoFuaPacket.m_header.timestamp=videoFrame->getVideoTimestamp(); + m_videoFuaPacket.m_header.marker=bool(i == num_of_packet - 1); + + + m_videoFuaPacket.m_payload_type = YangRtspPacketPayloadTypeFUA2; + + memset(&m_videoFua2Data,0,sizeof(YangFua2H264Data)); + m_videoFua2Data.nri = (YangAvcNaluType) header; + m_videoFua2Data.nalu_type = (YangAvcNaluType) nal_type; + m_videoFua2Data.start = bool(i == 0); + m_videoFua2Data.end = bool(i == (num_of_packet - 1)); + + m_videoFua2Data.payload = m_videoBuf; + m_videoFua2Data.nb = packet_size; + memcpy(m_videoFua2Data.payload, p, packet_size); + + p += packet_size; + nb_left -= packet_size; + + if ((err = encodeVideo(&m_videoFuaPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + } + + return err; +} +int32_t YangH264RtpEncode::encodeVideo(YangRtpPacket *pkt) { + int err = 0; + m_buf.init(m_rtpBuffer->getBuffer(), kRtpPacketSize); + + if ((err = yang_encode_rtpHeader(&m_buf,&pkt->m_header)) != Yang_Ok) { + return yang_error_wrap(err, "rtp header(%d) encode packet fail", + pkt->m_payload_type); + } + if (pkt->m_payload_type == YangRtspPacketPayloadTypeRaw) { + err=yang_encode_h264_raw(&m_buf,&m_videoRawData); + } else if (pkt->m_payload_type == YangRtspPacketPayloadTypeFUA2) { + err = yang_encode_h264_fua2(&m_buf,&m_videoFua2Data); + + } else if (pkt->m_payload_type == YangRtspPacketPayloadTypeSTAP) { + err = yang_encode_h264_stap(&m_buf,&m_stapData); + yang_reset_h2645_stap(&m_stapData); + } + + if (err != Yang_Ok) { + return yang_error_wrap(err, "rtp payload(%d) encode packet fail", pkt->m_payload_type); + } + if (pkt->m_header.padding_length > 0) { + uint8_t padding = pkt->m_header.padding_length; + if (!m_buf.require(padding)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes", padding); + } + memset(m_buf.head(), padding, padding); + m_buf.skip(padding); + } + + if (m_session) + return m_session->send_avpacket(pkt, &m_buf); + return err; +} +int32_t YangH264RtpEncode::encodeAudio(YangRtpPacket *pkt) { + int err = 0; + m_buf.init(m_rtpBuffer->getBuffer(), kRtpPacketSize); + + + if ((err = yang_encode_rtpHeader(&m_buf,&pkt->m_header)) != Yang_Ok) { + return yang_error_wrap(err, "rtp header(%d) encode packet fail", + pkt->m_payload_type); + } + err=yang_encode_h264_raw(&m_buf,&m_audioRawData); + if (err != Yang_Ok) { + return yang_error_wrap(err, "rtp payload(%d) encode packet fail", + pkt->m_payload_type); + } + if (pkt->m_header.padding_length > 0) { + uint8_t padding = pkt->m_header.padding_length; + if (!m_buf.require(padding)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes", padding); + } + memset(m_buf.head(), padding, padding); + m_buf.skip(padding); + } + + if (m_session) + return m_session->send_avpacket(pkt, &m_buf); + return err; +} +int32_t YangH264RtpEncode::package_stap_a(YangStreamCapture *videoFrame) { + int err = Yang_Ok; +// uint8_t *buf = videoFrame->getVideoData(); +// int32_t spsLen = *(buf + 12) + 1; +// uint8_t *sps = buf + 13; +// int32_t ppsLen = *(sps + spsLen + 1) + 1; +// uint8_t *pps = buf + 13 + spsLen + 2; + m_videoStapPacket.reset(); + m_videoStapPacket.m_header.payload_type=kVideoPayloadType; + m_videoStapPacket.m_header.ssrc=m_videoSsrc; + m_videoStapPacket.m_frame_type = YangFrameTypeVideo; + m_videoStapPacket.m_nalu_type = (YangAvcNaluType) kStapA; + m_videoStapPacket.m_header.marker=false; + m_videoStapPacket.m_header.sequence=m_videoSeq++; + m_videoStapPacket.m_header.timestamp=0; + + + m_videoStapPacket.m_payload_type = YangRtspPacketPayloadTypeSTAP; + + yang_reset_h2645_stap(&m_stapData); + + YangSample *sps_sample = new YangSample(); + YangSample *pps_sample = new YangSample(); + yang_decodeMetaH264(videoFrame->getVideoData(),videoFrame->getVideoLen(),sps_sample,pps_sample); + uint8_t header = (uint8_t)sps_sample->bytes[0]; + + m_stapData.nri = (YangAvcNaluType) header; + + // YangSample *vps_sample = new YangSample(); + // vps_sample->m_bytes = (char*) vps; + // vps_sample->m_size = vpsLen; + // m_stap.nalus.push_back(vps_sample); + + if(m_stapData.nalus) m_stapData.nalus->push_back(sps_sample); + if(m_stapData.nalus) m_stapData.nalus->push_back(pps_sample); + + + if ((err = encodeVideo(&m_videoStapPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + return err; + +} + diff --git a/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.h b/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.h new file mode 100644 index 0000000000000000000000000000000000000000..5a1c93006c8a1a9d8c96729a225a5d258946e836 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH264RtpEncode.h @@ -0,0 +1,44 @@ +#ifndef SRC_YANGRTP_YANGRTPPACKETWRAP_H_ +#define SRC_YANGRTP_YANGRTPPACKETWRAP_H_ +#include +#include +#include +#include +#include +#include +#include + +class YangH264RtpEncode { +public: + YangH264RtpEncode(); + virtual ~YangH264RtpEncode(); + void init(YangRtpBuffer* rtpBuffer,YangRtcSessionI* psession); + int32_t on_h264_video(YangStreamCapture* videoFrame); + int32_t on_audio(YangStreamCapture* audioFrame); + int32_t package_single_nalu(char* p,int32_t plen, int64_t timestamp); + int32_t package_single_nalu(YangStreamCapture* videoFrame); + int32_t package_fu_a(YangStreamCapture* videoFrame,int32_t fu_payload_size); + int32_t package_stap_a(YangStreamCapture* videoFrame); +public: + uint32_t m_videoSsrc; + uint32_t m_audioSsrc; + uint16_t m_videoSeq; + uint16_t m_audioSeq; +private: + YangRtpBuffer* m_rtpBuffer; + YangRtcSessionI* m_session; + YangFua2H264Data m_videoFua2Data; + YangRtpRawData m_videoRawData; + YangRtpRawData m_audioRawData; + YangRtpSTAPData m_stapData; + YangBuffer m_buf; + + char* m_videoBuf; + YangRtpPacket m_videoFuaPacket; + YangRtpPacket m_videoRawPacket; + YangRtpPacket m_videoStapPacket; + YangRtpPacket m_audioRawPacket; + int32_t encodeVideo(YangRtpPacket *pkt); + int32_t encodeAudio(YangRtpPacket *pkt); +}; +#endif /* SRC_YANGRTP_YANGRTPPACKETWRAP_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.cpp b/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e61fb9faeaa7c5b3b4c0059f3e4607cfb81768b --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.cpp @@ -0,0 +1,457 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +YangH265RecvTrack::YangH265RecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque) { + + m_recvcb=NULL; + + m_key_frame_ts = -1; + m_lost_sn = 0; + m_header_sn = 0; + m_hasRequestKeyframe = false; + + m_hasReceiveStap=-1; + + memset(m_cache_video_pkts, 0, s_cache_size*sizeof(YangRtcPacketCache)); + m_video_buffer=new char[YANG_VIDEO_ENCODE_BUFFER_LEN]; + memset(m_video_buffer,0,YANG_VIDEO_ENCODE_BUFFER_LEN); + + memset(&m_stapData,0,sizeof(YangRtpSTAPData)); + m_stapData.nalus=new std::vector(); + + m_recvcb=NULL; + m_uid=uid; + m_session=session; + m_track_desc=track_desc; + + memset(&m_videoFrame,0,sizeof(YangFrame)); +} + + +YangH265RecvTrack::~YangH265RecvTrack() { + + yang_deleteA(m_video_buffer); + yang_reset_h2645_stap(&m_stapData); + yang_delete(m_stapData.nalus); +} + + +void YangH265RecvTrack::setReceiveCallback(YangReceiveCallback *cbk) { + m_recvcb = cbk; +} +int32_t YangH265RecvTrack::packet_video(const uint16_t start, + const uint16_t end) { + int32_t err = Yang_Ok; + uint16_t cnt = end - start + 1; + YangRtcPacketCache *header = &m_cache_video_pkts[cache_index(start)]; + int64_t timestamp = header->ts; + char* p=m_video_buffer; + if (is_keyframe(header)) { + *p++=0x1c; // type(4 bits): key frame; code(4bits): avc + m_key_frame_ts = -1; + } else { + *p++=0x2c;// type(4 bits): inter frame; code(4bits): avc + } + *p++=0x01; + *p++=0x00; + *p++=0x00; + *p++=0x00; + + int32_t nalu_len = 0; + for (uint16_t i = 0; i < cnt; ++i) { + uint16_t index = cache_index((start + i)); + YangRtcPacketCache *pkt = &m_cache_video_pkts[index]; + m_cache_video_pkts[index].in_use = false; + + if(pkt->nalu_type==H265_kFuA){ + if (pkt->nb > 0) { + if (pkt->fua2.start) { + nalu_len = pkt->nb + 1; + p+=4; + //*p++=pkt->fua2.nri | pkt->fua2.nalu_type; + *p++=pkt->fua2.nalu_type <<1; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + } else { + nalu_len += pkt->nb; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + if (pkt->fua2.end) { + //write nalu_len back + yang_put_be32(p-(4 + nalu_len),nalu_len); + } + } + pkt->fua2.start = pkt->fua2.end = false; + pkt->fua2.nri = pkt->fua2.nalu_type = (YangHevcNaluType) 0; + continue; + } + } + + if (pkt->nalu_type==H265_kStapA) { + + if(m_hasReceiveStap>-1&&m_hasReceiveStap==pkt->sn){ + m_hasReceiveStap=-1; + continue; + }else{ + YangBuffer stap_buf(pkt->payload,pkt->nb); + yang_reset_h2645_stap(&m_stapData); + yang_decode_h265_stap(&stap_buf,&m_stapData); + //m_stap.decode(&stap_buf); + + for (int32_t j = 0; j < (int) m_stapData.nalus->size(); ++j) { + YangSample *sample = m_stapData.nalus->at(j); + if (sample->nb > 0) { + yang_put_be32(p,sample->nb); + p+=4; + memcpy(p,sample->bytes, sample->nb); + p+=sample->nb; + } + } + yang_reset_h2645_stap(&m_stapData); + continue; + } + + } + if(pkt->payload){ + + if (pkt->nb> 0) { + yang_put_be32(p,pkt->nb); + p+=4; + memcpy(p,pkt->payload,pkt->nb); + p+=pkt->nb; + + pkt->payload=NULL; + + continue; + } + } + memset(&m_cache_video_pkts[i],0,sizeof(struct YangRtcPacketCache)); + } + + if ((err = put_frame_video(m_video_buffer, timestamp, p-m_video_buffer)) != Yang_Ok) { + yang_warn("fail to pack video frame"); + } + + m_header_sn = end + 1; + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_header_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + err = packet_video(m_header_sn, tail_sn); + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = sn; + } + + return err; +} + +int32_t YangH265RecvTrack::packet_video_key_frame(YangRtpPacket *pkt) { + int32_t err = Yang_Ok; + uint16_t index = cache_index(pkt->m_header.sequence); + + if (pkt->m_nalu_type==H265_kStapA) { + YangBuffer stap_buf(pkt->m_payload, pkt->m_nb); + yang_reset_h2645_stap(&m_stapData); + yang_decode_h265_stap(&stap_buf,&m_stapData); + YangSample *vps = yang_get_h265_stap_vps(&m_stapData); + YangSample *sps = yang_get_h265_stap_sps(&m_stapData);//m_stap.get_sps(); + YangSample *pps = yang_get_h265_stap_pps(&m_stapData);//m_stap.get_pps(); + if (NULL==vps||NULL == sps || NULL == pps) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "no vps or sps or pps in stap-a rtp.vps:%p, sps: %p, pps:%p", vps,sps, pps); + } else { + int32_t metaLen=0; + yang_getConfig_Meta_H265(vps,sps,pps,(uint8_t*)m_video_buffer,&metaLen); + m_hasReceiveStap = pkt->m_header.sequence; + yang_reset_h2645_stap(&m_stapData); + if(metaLen>0){ + if ((err = put_frame_video(m_video_buffer, 0, metaLen)) + != Yang_Ok) { + return err; + } + } + + } + } + if (-1 == m_key_frame_ts) { + m_key_frame_ts = pkt->m_header.timestamp; + m_header_sn = pkt->m_header.sequence; + m_lost_sn = m_header_sn + 1; + // Received key frame and clean cache of old p frame pkts + clear_cached_video(); + //yang_trace("set ts=%lld, header=%hu, lost=%hu", key_frame_ts_, header_sn_, lost_sn_); + } else if (m_key_frame_ts != pkt->m_header.timestamp) { + //new key frame, clean cache + + m_key_frame_ts = pkt->m_header.timestamp; + m_header_sn = pkt->m_header.sequence; + m_lost_sn = m_header_sn + 1; + clear_cached_video(); + + } + + + m_cache_video_pkts[index].in_use = true; + copy(pkt,&m_cache_video_pkts[index]); + + int32_t sn = m_lost_sn; + uint16_t tail_sn = 0; + if (yang_rtp_seq_distance(m_header_sn, pkt->m_header.sequence) < 0) { + // When receive previous pkt in the same frame, update header sn; + m_header_sn = pkt->m_header.sequence; + sn = find_next_lost_sn(m_header_sn, tail_sn); + } else if (m_lost_sn == pkt->m_header.sequence) { + sn = find_next_lost_sn(m_lost_sn, tail_sn); + } + + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + if ((err = packet_video(m_header_sn, tail_sn)) != Yang_Ok) { + err = yang_error_wrap(err, "fail to packet key frame"); + } + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = (uint16_t) sn; + } + + return err; +} + +void YangH265RecvTrack::clear_cached_video() { + for (size_t i = 0; i < s_cache_size; i++) { + if (m_cache_video_pkts[i].in_use) { + memset(&m_cache_video_pkts[i],0,sizeof(struct YangRtcPacketCache)); + } + } +} + + +int32_t YangH265RecvTrack::put_frame_video(char *p, int64_t timestamp, + int32_t nb) { + + m_videoFrame.uid = m_uid; + m_videoFrame.payload = (uint8_t*) p; + m_videoFrame.nb = nb; + m_videoFrame.timestamp = timestamp; + + if (m_recvcb) m_recvcb->receiveVideo(&m_videoFrame); + + + return Yang_Ok; +} + +bool YangH265RecvTrack::check_frame_complete(const uint16_t start, + const uint16_t end) { + uint16_t cnt = (end - start + 1); + uint16_t fu_s_c = 0; + uint16_t fu_e_c = 0; + for (uint16_t i = 0; i < cnt; ++i) { + int32_t index = cache_index((start + i)); + YangRtcPacketCache *pkt = &m_cache_video_pkts[index]; + if (pkt->nalu_type == H265_kFuA) { + if (pkt->fua2.start) { + ++fu_s_c; + } + + if (pkt->fua2.end) { + ++fu_e_c; + } + } + } + + return fu_s_c == fu_e_c; +} + +int32_t YangH265RecvTrack::find_next_lost_sn(uint16_t current_sn, + uint16_t &end_sn) { + uint32_t last_ts = m_cache_video_pkts[cache_index(m_header_sn)].ts; + for (int32_t i = 0; i < s_cache_size; ++i) { + uint16_t lost_sn = current_sn + i; + int32_t index = cache_index(lost_sn); + + if (!m_cache_video_pkts[index].in_use) { + return lost_sn; + } + //check time first, avoid two small frame mixed case decode fail + if (last_ts != m_cache_video_pkts[index].ts) { + end_sn = lost_sn - 1; + return -1; + } + + if (m_cache_video_pkts[index].end) { + end_sn = lost_sn; + return -1; + } + } + + yang_error("the cache is mess. the packet count of video frame is more than %u", + s_cache_size); + return -2; +} + +bool YangH265RecvTrack::is_keyframe(YangRtpPacket *pkt) { + // It's normal H264 video rtp packet + if (pkt->m_nalu_type == H265_kStapA) { + + YangHevcNaluType nalu_type = (YangHevcNaluType) (YANG_HEVC_NALU_TYPE(*(pkt->m_payload+3))); + if (nalu_type == YANG_NAL_UNIT_VPS + || nalu_type == YANG_NAL_UNIT_SPS||nalu_type == YANG_NAL_UNIT_VPS) { + return true; + } + } else if (pkt->m_nalu_type == H265_kFuA) { + YangHevcNaluType v = (YangHevcNaluType)(YANG_HEVC_NALU_TYPE((uint8_t)(*(pkt->m_payload+2)))); + + if (v >= YANG_NAL_UNIT_CODED_SLICE_BLA&&v<= YANG_NAL_UNIT_CODED_SLICE_CRA) + return true; + + } else { //32 + if ((pkt->m_nalu_type == YANG_NAL_UNIT_VPS) + || (pkt->m_nalu_type == YANG_NAL_UNIT_SPS) + || (pkt->m_nalu_type == YANG_NAL_UNIT_PPS)) { + return true; + } + } + return false; +} + +bool YangH265RecvTrack::is_keyframe(YangRtcPacketCache *pkt) { + // It's normal H264 video rtp packet + if (pkt->nalu_type == H265_kStapA) { + + YangHevcNaluType nalu_type = (YangHevcNaluType) (YANG_HEVC_NALU_TYPE(*(pkt->payload+3))); + if (nalu_type == YANG_NAL_UNIT_VPS + || nalu_type == YANG_NAL_UNIT_SPS||nalu_type == YANG_NAL_UNIT_VPS) { + return true; + } + } else if (pkt->nalu_type == H265_kFuA) { + uint8_t v = (uint8_t)(*pkt->payload); + if (YangAvcNaluTypeIDR == YangAvcNaluType(v & kNalTypeMask)) return true; + + } else { + if ((pkt->nalu_type == YANG_NAL_UNIT_VPS) + || (pkt->nalu_type == YANG_NAL_UNIT_SPS) + || (pkt->nalu_type == YANG_NAL_UNIT_PPS)) { + return true; + } + } + return false; +} + +int32_t YangH265RecvTrack::on_rtp(YangRtpPacket *src) { + int32_t err = Yang_Ok; + if (!m_hasRequestKeyframe) { + m_session->send_rtcp_fb_pli(m_track_desc->ssrc_); + + } + src->m_nalu_type = YANG_HEVC_NALU_TYPE(src->m_payload[0]); + //yang_trace("%d,",src->m_nalu_type); + + if (is_keyframe(src)) { + m_hasRequestKeyframe = true; + return packet_video_key_frame(src); + } + +// if(src->m_nalu_type<=YangAvcNaluTypeCodedSliceExt){ +// if(src->m_header.marker) { +// packet_video_Raw(src); +// return Yang_Ok; +// } + + // } + // store in cache + + int32_t index = cache_index(src->m_header.sequence); + m_cache_video_pkts[index].in_use = true; + copy(src,&m_cache_video_pkts[index]); + + + // check whether to recovery lost packet and can construct a video frame + if (m_lost_sn == src->m_header.sequence) { + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_lost_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + if ((err = packet_video(m_header_sn, tail_sn)) != Yang_Ok) { + err = yang_error_wrap(err, "fail to pack video frame"); + } + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "video cache is overflow"); + } else { + m_lost_sn = (uint16_t) sn; + } + } + + return err; +} + + + +void YangH265RecvTrack::copy(YangRtpPacket *src, YangRtcPacketCache *pkt) { + pkt->sn = src->m_header.sequence; + pkt->end = src->m_header.marker; + + // For performance issue, do not copy the unused field. + + pkt->ts = src->m_header.timestamp; + pkt->nalu_type = src->m_nalu_type; + + pkt->payload = src->m_payload; + pkt->nb = src->m_nb; + + if (pkt->nalu_type == H265_kFuA) { + m_buf.init(src->m_payload, src->m_nb); + yang_decode_h265_fua2(&m_buf,&pkt->fua2); + pkt->payload = m_buf.head(); + pkt->nb = m_buf.left(); + } +} + + + +int32_t YangH265RecvTrack::packet_video_Raw(YangRtpPacket* pkt){ + int err=Yang_Ok; + char* p=m_video_buffer; + int64_t timestamp=pkt->m_header.timestamp; + *p++=0x2c;// type(4 bits): inter frame; code(4bits): avc + *p++=0x01; + *p++=0x00; + *p++=0x00; + *p++=0x00; + yang_put_be32(p,pkt->m_nb); + p+=4; + memcpy(p,pkt->m_payload,pkt->m_nb); + p+=pkt->m_nb; + if ((err = put_frame_video(m_video_buffer, timestamp, p-m_video_buffer)) != Yang_Ok) { + yang_warn("fail to pack video frame"); + } + + m_header_sn = pkt->m_header.sequence + 1; + uint16_t tail_sn = 0; + int32_t sn = find_next_lost_sn(m_header_sn, tail_sn); + if (-1 == sn) { + if (check_frame_complete(m_header_sn, tail_sn)) { + err = packet_video(m_header_sn, tail_sn); + } + } else if (-2 == sn) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, "video cache is overflow"); + } else { + m_lost_sn = sn; + } + + return err; +} diff --git a/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.h b/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..549488861e20af94a76eb6c848c65268749e00a0 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH265RecvTrack.h @@ -0,0 +1,66 @@ +#ifndef SRC_YANGWEBRTC_YangH265RecvTrack_H_ +#define SRC_YANGWEBRTC_YangH265RecvTrack_H_ +#include +#include +#include + + + +class YangH265RecvTrack{ +public: + YangH265RecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *stream_descs, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque); + virtual ~YangH265RecvTrack(); + +public: + int32_t on_rtp(YangRtpPacket *pkt); + void setReceiveCallback(YangReceiveCallback *cbk); + bool m_hasRequestKeyframe; +private: + uint16_t m_header_sn; + uint16_t m_lost_sn; + int32_t m_hasReceiveStap; + int64_t m_key_frame_ts; + + YangRtpSTAPData m_stapData; + YangBuffer m_buf; + YangFrame m_videoFrame; + char* m_video_buffer; + YangReceiveCallback *m_recvcb; + int32_t m_uid; + YangRtcSessionI *m_session; + YangRtcTrack *m_track_desc; +private: + int32_t put_frame_video(char *p, int64_t timestamp, int32_t nb); + int32_t put_frame_mixvideo(char *p, int64_t timestamp, int32_t nb); + + const static uint16_t s_cache_size = 1024; + struct YangRtcPacketCache { + bool in_use; + bool end; + uint16_t sn; + uint32_t ts; + int32_t nalu_type; + int32_t nb; + Fua2H265DataCache fua2; + char *payload; + }; + YangRtcPacketCache m_cache_video_pkts[1024]; + void clear_cached_video(); + inline uint16_t cache_index(uint16_t current_sn) { + //return current_sn % s_cache_size; + return current_sn&1023; + } + + bool check_frame_complete(const uint16_t start, const uint16_t end); + int32_t find_next_lost_sn(uint16_t current_sn, uint16_t &end_sn); + int32_t packet_video_Raw(YangRtpPacket* pkt); + int32_t packet_video(const uint16_t start, const uint16_t end); + int32_t packet_video_key_frame(YangRtpPacket *pkt); + + bool is_keyframe(YangRtpPacket* pkt); + bool is_keyframe(YangRtcPacketCache* pkt); + void copy(YangRtpPacket* src,YangRtcPacketCache* pkt); +}; +#endif /* SRC_YANGWEBRTC_YANGRTCVIDEORECVTRACK_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.cpp b/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ca4f40084cbeee9d05e7dbf294f1a2f6e2706e7 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.cpp @@ -0,0 +1,262 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if Yang_H265_Encoding +YangH265RtpEncode::YangH265RtpEncode() { + m_videoSsrc = 0; + m_videoSeq = 0; + m_audioSeq = 0; + m_audioSsrc = 0; + m_rtpBuffer = NULL; + m_session = NULL; + m_videoBuf = new char[kRtpPacketSize]; + memset(&m_stapData,0,sizeof(YangRtpSTAPData)); + m_stapData.nalus=new std::vector(); +} + +YangH265RtpEncode::~YangH265RtpEncode() { + m_session = NULL; + yang_deleteA(m_videoBuf); + yang_reset_h2645_stap(&m_stapData); + yang_delete(m_stapData.nalus); +} +void YangH265RtpEncode::init(YangRtpBuffer *rtpBuffer, + YangRtcSessionI *psession) { + m_rtpBuffer = rtpBuffer; + m_session = psession; +} +int32_t YangH265RtpEncode::on_audio(YangStreamCapture *audioFrame) { + int err = 0; + m_audioRawPacket.reset(); + m_audioRawPacket.m_header.payload_type=kAudioPayloadType; + m_audioRawPacket.m_header.ssrc=m_audioSsrc; + m_audioRawPacket.m_frame_type = YangFrameTypeAudio; + m_audioRawPacket.m_header.marker=true; + + m_audioRawPacket.m_header.sequence=m_audioSeq++; + m_audioRawPacket.m_header.timestamp=audioFrame->getAudioTimestamp(); + m_audioRawPacket.m_header.padding_length=0; + m_audioRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + + m_audioRawData.payload = m_videoBuf; + m_audioRawData.nb = audioFrame->getAudioLen(); + memcpy(m_audioRawData.payload, audioFrame->getAudioData(), m_audioRawData.nb); + if ((err = encodeAudio(&m_audioRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + return err; +} +int32_t YangH265RtpEncode::on_h265_video(YangStreamCapture *videoFrame) { + int32_t err = Yang_Ok; + + if (videoFrame->getVideoLen() <= kRtpMaxPayloadSize) { + if ((err = package_single_nalu(videoFrame)) != Yang_Ok) { + return yang_error_wrap(err, "package single nalu"); + } + } else { + if ((err = package_fu_a(videoFrame, kRtpMaxPayloadSize)) != Yang_Ok) { + return yang_error_wrap(err, "package fu-a"); + } + } + + return err; +} + +int32_t YangH265RtpEncode::package_single_nalu(YangStreamCapture *videoFrame) { + int32_t err = Yang_Ok; + + m_videoRawPacket.reset(); + m_videoRawPacket.m_header.payload_type=kVideoPayloadType; + m_videoRawPacket.m_header.ssrc=m_videoSsrc; + m_videoRawPacket.m_frame_type = YangFrameTypeVideo; + m_videoRawPacket.m_header.sequence=m_videoSeq++; + m_videoRawPacket.m_header.timestamp=videoFrame->getVideoTimestamp(); + m_videoRawPacket.m_header.marker=true; + m_videoRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + //memset(&m_raw_video,0,sizeof(YangRtpRawPayload)); + m_videoRawData.payload = m_videoBuf; + m_videoRawData.nb = videoFrame->getVideoLen(); + memcpy(m_videoRawData.payload, videoFrame->getVideoData(), m_videoRawData.nb); + if ((err = encodeVideo(&m_videoRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + return err; +} +int32_t YangH265RtpEncode::package_single_nalu(char *p, int32_t plen, + int64_t timestamp) { + + int32_t err = Yang_Ok; + m_videoRawPacket.reset(); + m_videoRawPacket.m_header.payload_type=kVideoPayloadType; + m_videoRawPacket.m_header.ssrc=m_videoSsrc; + m_videoRawPacket.m_frame_type = YangFrameTypeVideo; + m_videoRawPacket.m_header.sequence=m_videoSeq++; + m_videoRawPacket.m_header.timestamp=timestamp; + + + m_videoRawPacket.m_payload_type = YangRtspPacketPayloadTypeRaw; + m_videoRawData.payload = m_videoBuf; + m_videoRawData.nb = plen; + memcpy(m_videoRawData.payload, p, plen); + if ((err = encodeVideo(&m_videoRawPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + return err; +} +int32_t YangH265RtpEncode::package_fu_a(YangStreamCapture *videoFrame, + int32_t fu_payload_size) { + int32_t err = Yang_Ok; + int32_t plen = videoFrame->getVideoLen(); + uint8_t *pdata = videoFrame->getVideoData(); + char *p = (char*) pdata + 1; + int32_t nb_left = plen - 1; + uint8_t header = pdata[0]; + uint8_t nal_type = YANG_HEVC_NALU_TYPE(header); + + int32_t num_of_packet = ((plen - 1) % fu_payload_size==0)?0:1 + (plen - 1) / fu_payload_size; + for (int32_t i = 0; i < num_of_packet; ++i) { + int32_t packet_size = yang_min(nb_left, fu_payload_size); + m_videoFuaPacket.reset(); + m_videoFuaPacket.m_header.payload_type=kVideoPayloadType; + m_videoFuaPacket.m_header.ssrc=m_videoSsrc; + m_videoFuaPacket.m_frame_type = YangFrameTypeVideo; + m_videoFuaPacket.m_header.sequence=m_videoSeq++; + m_videoFuaPacket.m_header.timestamp=videoFrame->getVideoTimestamp(); + m_videoFuaPacket.m_header.marker=bool(i == num_of_packet - 1); + + + m_videoFuaPacket.m_payload_type = YangRtspPacketPayloadTypeFUA2; + + memset(&m_videoFua2Data,0,sizeof(YangFua2H265Data)); + m_videoFua2Data.nri = (YangHevcNaluType) header; + m_videoFua2Data.nalu_type = (YangHevcNaluType) nal_type; + m_videoFua2Data.start = bool(i == 0); + m_videoFua2Data.end = bool(i == (num_of_packet - 1)); + + m_videoFua2Data.payload = m_videoBuf; + m_videoFua2Data.nb = packet_size; + memcpy(m_videoFua2Data.payload, p, packet_size); + + p += packet_size; + nb_left -= packet_size; + + if ((err = encodeVideo(&m_videoFuaPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + + } + + return err; +} +int32_t YangH265RtpEncode::encodeVideo(YangRtpPacket *pkt) { + int err = 0; + m_buf.init(m_rtpBuffer->getBuffer(), kRtpPacketSize); + + if ((err = yang_encode_rtpHeader(&m_buf,&pkt->m_header)) != Yang_Ok) { + return yang_error_wrap(err, "rtp header(%d) encode packet fail", + pkt->m_payload_type); + } + if (pkt->m_payload_type == YangRtspPacketPayloadTypeRaw) { + err=yang_encode_h264_raw(&m_buf,&m_videoRawData); + } else if (pkt->m_payload_type == YangRtspPacketPayloadTypeFUA2) { + err = yang_encode_h265_fua2(&m_buf,&m_videoFua2Data); + + } else if (pkt->m_payload_type == YangRtspPacketPayloadTypeSTAP) { + err = yang_encode_h265_stap(&m_buf,&m_stapData); + yang_reset_h2645_stap(&m_stapData); + } + + if (err != Yang_Ok) { + return yang_error_wrap(err, "rtp payload(%d) encode packet fail", pkt->m_payload_type); + } + if (pkt->m_header.padding_length > 0) { + uint8_t padding = pkt->m_header.padding_length; + if (!m_buf.require(padding)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes", padding); + } + memset(m_buf.head(), padding, padding); + m_buf.skip(padding); + } + + if (m_session) + return m_session->send_avpacket(pkt, &m_buf); + return err; +} +int32_t YangH265RtpEncode::encodeAudio(YangRtpPacket *pkt) { + int err = 0; + m_buf.init(m_rtpBuffer->getBuffer(), kRtpPacketSize); + + + if ((err = yang_encode_rtpHeader(&m_buf,&pkt->m_header)) != Yang_Ok) { + return yang_error_wrap(err, "rtp header(%d) encode packet fail", + pkt->m_payload_type); + } + err=yang_encode_h264_raw(&m_buf,&m_audioRawData); + if (err != Yang_Ok) { + return yang_error_wrap(err, "rtp payload(%d) encode packet fail", + pkt->m_payload_type); + } + if (pkt->m_header.padding_length > 0) { + uint8_t padding = pkt->m_header.padding_length; + if (!m_buf.require(padding)) { + return yang_error_wrap(ERROR_RTC_RTP_MUXER, + "padding requires %d bytes", padding); + } + memset(m_buf.head(), padding, padding); + m_buf.skip(padding); + } + + if (m_session) + return m_session->send_avpacket(pkt, &m_buf); + return err; +} +int32_t YangH265RtpEncode::package_stap_a(YangStreamCapture *videoFrame) { + int err = Yang_Ok; + //uint8_t *buf = videoFrame->getVideoData(); +// int32_t vpsLen = *(buf + 12) + 1; +// uint8_t *vps; +// int32_t spsLen = *(buf + 12) + 1; +// uint8_t *sps = buf + 13; +// int32_t ppsLen = *(sps + spsLen + 1) + 1; +// uint8_t *pps = buf + 13 + spsLen + 2; + m_videoStapPacket.reset(); + m_videoStapPacket.m_header.payload_type=kVideoPayloadType; + m_videoStapPacket.m_header.ssrc=m_videoSsrc; + m_videoStapPacket.m_frame_type = YangFrameTypeVideo; + m_videoStapPacket.m_nalu_type = (YangAvcNaluType) kStapA; + m_videoStapPacket.m_header.marker=false; + m_videoStapPacket.m_header.sequence=m_videoSeq++; + m_videoStapPacket.m_header.timestamp=0; + + + m_videoStapPacket.m_payload_type = YangRtspPacketPayloadTypeSTAP; + + YangSample *vps_sample = new YangSample(); + YangSample *sps_sample = new YangSample(); + YangSample *pps_sample = new YangSample(); + yang_decodeMetaH265(videoFrame->getVideoData(),videoFrame->getVideoLen(),vps_sample,sps_sample,pps_sample); + yang_reset_h2645_stap(&m_stapData); + uint8_t header = (uint8_t)sps_sample->bytes[0]; + m_stapData.nri = header; + if(m_stapData.nalus) m_stapData.nalus->push_back(vps_sample); + if(m_stapData.nalus) m_stapData.nalus->push_back(sps_sample); + if(m_stapData.nalus) m_stapData.nalus->push_back(pps_sample); + + + if ((err = encodeVideo(&m_videoStapPacket)) != Yang_Ok) { + return yang_error_wrap(err, "encode packet"); + } + return err; + +} +#endif diff --git a/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.h b/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.h new file mode 100644 index 0000000000000000000000000000000000000000..79e4b64570a92d173359b0c5d006cf9af30b991c --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangH265RtpEncode.h @@ -0,0 +1,46 @@ +#ifndef SRC_YANGRTP_YangH265RtpEncode_H_ +#define SRC_YANGRTP_YangH265RtpEncode_H_ +#if Yang_H265_Encoding +#include +#include +#include +#include +#include +#include +#include + +class YangH265RtpEncode { +public: + YangH265RtpEncode(); + virtual ~YangH265RtpEncode(); + void init(YangRtpBuffer* rtpBuffer,YangRtcSessionI* psession); + int32_t on_h265_video(YangStreamCapture* videoFrame); + int32_t on_audio(YangStreamCapture* audioFrame); + int32_t package_single_nalu(char* p,int32_t plen, int64_t timestamp); + int32_t package_single_nalu(YangStreamCapture* videoFrame); + int32_t package_fu_a(YangStreamCapture* videoFrame,int32_t fu_payload_size); + int32_t package_stap_a(YangStreamCapture* videoFrame); +public: + uint32_t m_videoSsrc; + uint32_t m_audioSsrc; + uint16_t m_videoSeq; + uint16_t m_audioSeq; +private: + YangRtpBuffer* m_rtpBuffer; + YangRtcSessionI* m_session; + YangFua2H265Data m_videoFua2Data; + YangRtpRawData m_videoRawData; + YangRtpRawData m_audioRawData; + YangRtpSTAPData m_stapData; + YangBuffer m_buf; + + char* m_videoBuf; + YangRtpPacket m_videoFuaPacket; + YangRtpPacket m_videoRawPacket; + YangRtpPacket m_videoStapPacket; + YangRtpPacket m_audioRawPacket; + int32_t encodeVideo(YangRtpPacket *pkt); + int32_t encodeAudio(YangRtpPacket *pkt); +}; +#endif +#endif /* SRC_YANGRTP_YANGRTPPACKETWRAP_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangLocalH264Sdp.h b/libyangrtc2/src/yangwebrtc/YangLocalH264Sdp.h new file mode 100644 index 0000000000000000000000000000000000000000..a1fb8733a44ad4e5c0754a0339f25c80a573ca80 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangLocalH264Sdp.h @@ -0,0 +1,43 @@ +#ifndef SRC_YANGWEBRTC_YANGLOCALH264SDP_H_ +#define SRC_YANGWEBRTC_YANGLOCALH264SDP_H_ + +const char* local_h264_sdp_str="o=Yangwebrtc 93937470806864 2 IN IP4 0.0.0.0\n"\ + "s=YangPlaySession\nt=0 0\na=ice-lite\na=group:BUNDLE 0 1\n"\ + "a=msid-semantic: WMS live/livestream\nm=audio 9 UDP/TLS/RTP/SAVPF 111\n"\ + "c=IN IP4 0.0.0.0\n"\ + "a=ice-ufrag:7nlf8226\n"\ + "a=ice-pwd:86971b13h9723f8oc0z72h82a42x6184\n"\ + "a=fingerprint:sha-256 A0:8B:98:29:DE:2E:16:0C:60:C6:D0:09:1C:A4:E9:3F:7C:06:98:53:03:A3:6F:0E:67:2B:9A:9D:F0:4F:A3:D6\n"\ + "a=setup:passive\na=mid:0\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n"\ + "a=sendonly\n"\ + "a=rtcp-mux\na=rtcp-rsize\n"\ + "a=rtpmap:111 opus/48000/2\n"\ + "a=rtcp-fb:111 transport-cc\n"\ + "a=fmtp:111 minptime=10;useinbandfec=1\n"\ + "a=ssrc:144706935 cname:5hcuv2i7jtwg6bj1\n"\ + "a=ssrc:144706935 msid:- 79ac70ad-c572-4017-86a1-330d56089c70\n"\ + "a=ssrc:144706935 mslabel:-\n"\ + "a=ssrc:144706935 label:79ac70ad-c572-4017-86a1-330d56089c70\n"\ + "a=candidate:0 1 udp 2130706431 127.0.0.1 8000 typ host generation 0\n"\ + "m=video 9 UDP/TLS/RTP/SAVPF 125 114\nc=IN IP4 0.0.0.0\na=ice-ufrag:7nlf8226\n"\ + "a=ice-pwd:86971b13h9723f8oc0z72h82a42x6184\n"\ + "a=fingerprint:sha-256 A0:8B:98:29:DE:2E:16:0C:60:C6:D0:09:1C:A4:E9:3F:7C:06:98:53:03:A3:6F:0E:67:2B:9A:9D:F0:4F:A3:D6\n"\ + "a=setup:passive\n"\ + "a=mid:1\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n"\ + "a=sendonly\n"\ + "a=rtcp-mux\n"\ + "a=rtcp-rsize\n"\ + "a=rtpmap:125 H264/90000\n"\ + "a=rtcp-fb:125 transport-cc\n"\ + "a=rtcp-fb:125 nack\n"\ + "a=rtcp-fb:125 nack pli\n"\ + "a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\n"\ + "a=rtpmap:114 red/90000\na=ssrc:144706936 cname:5hcuv2i7jtwg6bj1\n"\ + "a=ssrc:144706936 msid:- 549dbfe5-fd12-4c5f-9182-d513f6defce5\n"\ + "a=ssrc:144706936 mslabel:-\n"\ + "a=ssrc:144706936 label:549dbfe5-fd12-4c5f-9182-d513f6defce5\n"\ + "a=candidate:0 1 udp 2130706431 127.0.0.1 8000 typ host generation 0"; + + + +#endif /* SRC_YANGWEBRTC_YANGLOCALH264SDP_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangLocalH265Sdp.h b/libyangrtc2/src/yangwebrtc/YangLocalH265Sdp.h new file mode 100644 index 0000000000000000000000000000000000000000..713c97cf5e725dccd2559537cf74de16c22aa914 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangLocalH265Sdp.h @@ -0,0 +1,44 @@ +#ifndef SRC_YANGWEBRTC_YANGLOCALH265SDP_H_ +#define SRC_YANGWEBRTC_YANGLOCALH265SDP_H_ + + +const char* local_h265_sdp_str="o=yangwebrtc 93937470806864 2 IN IP4 0.0.0.0\n"\ + "s=yangPlaySession\nt=0 0\na=ice-lite\na=group:BUNDLE 0 1\n"\ + "a=msid-semantic: WMS live/livestream\nm=audio 9 UDP/TLS/RTP/SAVPF 111\n"\ + "c=IN IP4 0.0.0.0\n"\ + "a=ice-ufrag:7nlf8226\n"\ + "a=ice-pwd:86971b13h9723f8oc0z72h82a42x6184\n"\ + "a=fingerprint:sha-256 A0:8B:98:29:DE:2E:16:0C:60:C6:D0:09:1C:A4:E9:3F:7C:06:98:53:03:A3:6F:0E:67:2B:9A:9D:F0:4F:A3:D6\n"\ + "a=setup:passive\na=mid:0\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n"\ + "a=sendonly\n"\ + "a=rtcp-mux\na=rtcp-rsize\n"\ + "a=rtpmap:111 opus/48000/2\n"\ + "a=rtcp-fb:111 transport-cc\n"\ + "a=fmtp:111 minptime=10;useinbandfec=1\n"\ + "a=ssrc:144706935 cname:5hcuv2i7jtwg6bj1\n"\ + "a=ssrc:144706935 msid:- 79ac70ad-c572-4017-86a1-330d56089c70\n"\ + "a=ssrc:144706935 mslabel:-\n"\ + "a=ssrc:144706935 label:79ac70ad-c572-4017-86a1-330d56089c70\n"\ + "a=candidate:0 1 udp 2130706431 127.0.0.1 8000 typ host generation 0\n"\ + "m=video 9 UDP/TLS/RTP/SAVPF 126 114\nc=IN IP4 0.0.0.0\na=ice-ufrag:7nlf8226\n"\ + "a=ice-pwd:86971b13h9723f8oc0z72h82a42x6184\n"\ + "a=fingerprint:sha-256 A0:8B:98:29:DE:2E:16:0C:60:C6:D0:09:1C:A4:E9:3F:7C:06:98:53:03:A3:6F:0E:67:2B:9A:9D:F0:4F:A3:D6\n"\ + "a=setup:passive\n"\ + "a=mid:1\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n"\ + "a=sendonly\n"\ + "a=rtcp-mux\n"\ + "a=rtcp-rsize\n"\ + "a=rtpmap:126 H265/90000\n"\ + "a=rtcp-fb:126 transport-cc\n"\ + "a=rtcp-fb:126 nack\n"\ + "a=rtcp-fb:126 nack pli\n"\ + "a=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\n"\ + "a=rtpmap:114 red/90000\na=ssrc:144706936 cname:5hcuv2i7jtwg6bj1\n"\ + "a=ssrc:144706936 msid:- 549dbfe5-fd12-4c5f-9182-d513f6defce5\n"\ + "a=ssrc:144706936 mslabel:-\n"\ + "a=ssrc:144706936 label:549dbfe5-fd12-4c5f-9182-d513f6defce5\n"\ + "a=candidate:0 1 udp 2130706431 127.0.0.1 8000 typ host generation 0"; + + + +#endif /* SRC_YANGWEBRTC_YANGLOCALH265SDP_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangMediaDesc.cpp b/libyangrtc2/src/yangwebrtc/YangMediaDesc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee8db8e99c8b571d03ca6fd12f06f359dc11494f --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangMediaDesc.cpp @@ -0,0 +1,537 @@ +#include +#include +#include +#include +#include +#define kCRLF "\r\n" +#define FETCH(is,word) \ +if (!(is >> word)) {\ + return Yang_Fetch_Failed;\ +}\ + +#define FETCH_WITH_DELIM(is,word,delim) \ +if (!getline(is,word,delim)) {\ + return Yang_Fetch_Failed_WithDelim;\ +}\ + +using namespace std; +YangSessionInfo::YangSessionInfo() +{ +} + +YangSessionInfo::~YangSessionInfo() +{ +} + +int32_t YangSessionInfo::parse_attribute(const std::string& attribute, const std::string& value) +{ + int32_t err = Yang_Ok; + + if (attribute == "ice-ufrag") { + m_ice_ufrag = value; + } else if (attribute == "ice-pwd") { + m_ice_pwd = value; + } else if (attribute == "ice-options") { + m_ice_options = value; + } else if (attribute == "fingerprint") { + std::istringstream is(value); + FETCH(is, m_fingerprint_algo); + FETCH(is, m_fingerprint); + } else if (attribute == "setup") { + // @see: https://tools.ietf.org/html/rfc4145#section-4 + m_setup = value; + } else { + // yang_trace("ignore attribute=%s, value=%s", attribute.c_str(), value.c_str()); + } + + return err; +} + +int32_t YangSessionInfo::encode(std::stringstream& os) +{ + int32_t err = Yang_Ok; + + if (!m_ice_ufrag.empty()) { + os << "a=ice-ufrag:" << m_ice_ufrag << kCRLF; + } + + if (!m_ice_pwd.empty()) { + os << "a=ice-pwd:" << m_ice_pwd << kCRLF; + } + + // For ICE-lite, we never set the trickle. + if (!m_ice_options.empty()) { + os << "a=ice-options:" << m_ice_options << kCRLF; + } + + if (!m_fingerprint_algo.empty() && ! m_fingerprint.empty()) { + os << "a=fingerprint:" << m_fingerprint_algo << " " << m_fingerprint << kCRLF; + } + + if (!m_setup.empty()) { + os << "a=setup:" << m_setup << kCRLF; + } + + return err; +} + +bool YangSessionInfo::operator=(const YangSessionInfo& rhs) +{ + return m_ice_ufrag == rhs.m_ice_ufrag && + m_ice_pwd == rhs.m_ice_pwd && + m_ice_options == rhs.m_ice_options && + m_fingerprint_algo == rhs.m_fingerprint_algo && + m_fingerprint == rhs.m_fingerprint && + m_setup == rhs.m_setup; +} + + +YangMediaDesc::YangMediaDesc(const std::string& type) +{ + m_type = type; + + m_port = 0; + m_rtcp_mux = false; + m_rtcp_rsize = false; + + m_sendrecv = false; + m_recvonly = false; + m_sendonly = false; + m_inactive = false; +} + +YangMediaDesc::~YangMediaDesc() +{ +} + +YangMediaPayloadType* YangMediaDesc::find_media_with_payload_type(int32_t payload_type) +{ + for (size_t i = 0; i < m_payload_types.size(); ++i) { + if (m_payload_types[i].m_payload_type == payload_type) { + return &m_payload_types[i]; + } + } + + return NULL; +} +bool YangMediaDesc::find_encoding_name(const std::string& encoding_name) const{ + + std::string lower_name(encoding_name), upper_name(encoding_name); + transform(encoding_name.begin(), encoding_name.end(), lower_name.begin(), ::tolower); + transform(encoding_name.begin(), encoding_name.end(), upper_name.begin(), ::toupper); + + for (size_t i = 0; i < m_payload_types.size(); ++i) { + if (m_payload_types[i].m_encoding_name == std::string(lower_name.c_str()) || + m_payload_types[i].m_encoding_name == std::string(upper_name.c_str())) { + return true; + } + } + + return false; +} +vector YangMediaDesc::find_media_with_encoding_name(const std::string& encoding_name) const +{ + std::vector payloads; + + std::string lower_name(encoding_name), upper_name(encoding_name); + transform(encoding_name.begin(), encoding_name.end(), lower_name.begin(), ::tolower); + transform(encoding_name.begin(), encoding_name.end(), upper_name.begin(), ::toupper); + + for (size_t i = 0; i < m_payload_types.size(); ++i) { + if (m_payload_types[i].m_encoding_name == std::string(lower_name.c_str()) || + m_payload_types[i].m_encoding_name == std::string(upper_name.c_str())) { + payloads.push_back(m_payload_types[i]); + } + } + + return payloads; +} + +int32_t YangMediaDesc::update_msid(string id) +{ + int32_t err = Yang_Ok; + + for(vector::iterator it = m_ssrc_infos.begin(); it != m_ssrc_infos.end(); ++it) { + YangSSRCInfo& info = *it; + + info.m_msid = id; + info.m_mslabel = id; + } + + return err; +} + +int32_t YangMediaDesc::parse_line(const std::string& line) +{ + int32_t err = Yang_Ok; + std::string content = line.substr(2); + + switch (line[0]) { + case 'a': { + return parse_attribute(content); + } + case 'c': { + // TODO: process c-line + break; + } + default: { + yang_trace("ignore media line=%s", line.c_str()); + break; + } + } + + return err; +} + +int32_t YangMediaDesc::encode(std::stringstream& os) +{ + int32_t err = Yang_Ok; + + os << "m=" << m_type << " " << m_port << " " << m_protos; + for (std::vector::iterator iter = m_payload_types.begin(); iter != m_payload_types.end(); ++iter) { + os << " " << iter->m_payload_type; + } + + os << kCRLF; + + // TODO:nettype and address type + os << "c=IN IP4 0.0.0.0" << kCRLF; + + if ((err = m_session_info.encode(os)) != Yang_Ok) { + return printf("encode session info failed"); + } + + os << "a=mid:" << m_mid << kCRLF; + if (!m_msid.empty()) { + os << "a=msid:" << m_msid; + + if (!m_msid_tracker.empty()) { + os << " " << m_msid_tracker; + } + + os << kCRLF; + } + + for(map::iterator it = m_extmaps.begin(); it != m_extmaps.end(); ++it) { + os << "a=extmap:"<< it->first<< " "<< it->second<< kCRLF; + } + if (m_sendonly) { + os << "a=sendonly" << kCRLF; + } + if (m_recvonly) { + os << "a=recvonly" << kCRLF; + } + if (m_sendrecv) { + os << "a=sendrecv" << kCRLF; + } + if (m_inactive) { + os << "a=inactive" << kCRLF; + } + + if (m_rtcp_mux) { + os << "a=rtcp-mux" << kCRLF; + } + + if (m_rtcp_rsize) { + os << "a=rtcp-rsize" << kCRLF; + } + + for (std::vector::iterator iter = m_payload_types.begin(); iter != m_payload_types.end(); ++iter) { + if ((err = iter->encode(os)) != Yang_Ok) { + return printf("encode media payload failed"); + } + } + + for (std::vector::iterator iter = m_ssrc_infos.begin(); iter != m_ssrc_infos.end(); ++iter) { + YangSSRCInfo& ssrc_info = *iter; + + if ((err = ssrc_info.encode(os)) != Yang_Ok) { + return printf("encode ssrc failed"); + } + } + + int32_t foundation = 0; + int32_t component_id = 1; /* RTP */ + for (std::vector::iterator iter = m_candidates.begin(); iter != m_candidates.end(); ++iter) { + // @see: https://tools.ietf.org/html/draft-ietf-ice-rfc5245bis-00#section-4.2 + uint32_t priority = (1<<24)*(126) + (1<<8)*(65535) + (1)*(256 - component_id); + + // @see: https://tools.ietf.org/id/draft-ietf-mmusic-ice-sip-sdp-14.html#rfc.section.5.1 + os << "a=candidate:" << foundation++ << " " + << component_id << " udp " << priority << " " + << iter->ip_ << " " << iter->port_ + << " typ " << iter->type_ + << " generation 0" << kCRLF; + + yang_trace("local SDP candidate line=%s", os.str().c_str()); + } + + return err; +} + +int32_t YangMediaDesc::parse_attribute(const std::string& content) +{ + int32_t err = Yang_Ok; + std::string attribute = ""; + std::string value = ""; + size_t pos = content.find_first_of(":"); + + if (pos != std::string::npos) { + attribute = content.substr(0, pos); + value = content.substr(pos + 1); + } else { + attribute = content; + } + + if (attribute == "extmap") { + return parse_attr_extmap(value); + } else if (attribute == "rtpmap") { + return parse_attr_rtpmap(value); + } else if (attribute == "rtcp") { + return parse_attr_rtcp(value); + } else if (attribute == "rtcp-fb") { + return parse_attr_rtcp_fb(value); + } else if (attribute == "fmtp") { + return parse_attr_fmtp(value); + } else if (attribute == "mid") { + return parse_attr_mid(value); + } else if (attribute == "msid") { + return parse_attr_msid(value); + } else if (attribute == "ssrc") { + return parse_attr_ssrc(value); + } else if (attribute == "ssrc-group") { + return parse_attr_ssrc_group(value); + } else if (attribute == "rtcp-mux") { + m_rtcp_mux = true; + } else if (attribute == "rtcp-rsize") { + m_rtcp_rsize = true; + } else if (attribute == "recvonly") { + m_recvonly = true; + } else if (attribute == "sendonly") { + m_sendonly = true; + } else if (attribute == "sendrecv") { + m_sendrecv = true; + } else if (attribute == "inactive") { + m_inactive = true; + } else { + return m_session_info.parse_attribute(attribute, value); + } + + return err; +} +int32_t YangMediaDesc::parse_attr_extmap(const std::string& value) +{ + int32_t err = Yang_Ok; + std::istringstream is(value); + int32_t id = 0; + FETCH(is, id); + if(m_extmaps.end() != m_extmaps.find(id)) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "duplicate ext id: %d", id); + } + string ext; + FETCH(is, ext); + m_extmaps[id] = ext; + return err; +} + +int32_t YangMediaDesc::parse_attr_rtpmap(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#page-25 + // a=rtpmap: / [/] + + std::istringstream is(value); + + int32_t payload_type = 0; + FETCH(is, payload_type); + + YangMediaPayloadType* payload = find_media_with_payload_type(payload_type); + if (payload == NULL) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "can not find payload %d when pase rtpmap", payload_type); + } + + std::string word; + FETCH(is, word); + + std::vector vec = yang_splits(word, "/"); + if (vec.size() < 2) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid rtpmap line=%s", value.c_str()); + } + + payload->m_encoding_name = vec[0]; + payload->m_clock_rate = atoi(vec[1].c_str()); + + if (vec.size() == 3) { + payload->m_encoding_param = vec[2]; + } + + return err; +} + +int32_t YangMediaDesc::parse_attr_rtcp(const std::string& value) +{ + int32_t err = Yang_Ok; + + // TODO:parse rtcp attribute + + return err; +} + +int32_t YangMediaDesc::parse_attr_rtcp_fb(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc5104#section-7.1 + + std::istringstream is(value); + + int32_t payload_type = 0; + FETCH(is, payload_type); + + YangMediaPayloadType* payload = find_media_with_payload_type(payload_type); + if (payload == NULL) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "can not find payload %d when pase rtcp-fb", payload_type); + } + + std::string rtcp_fb = is.str().substr(is.tellg()); + skip_first_spaces(rtcp_fb); + + payload->m_rtcp_fb.push_back(rtcp_fb); + + return err; +} + +int32_t YangMediaDesc::parse_attr_fmtp(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#page-30 + // a=fmtp: + + std::istringstream is(value); + + int32_t payload_type = 0; + FETCH(is, payload_type); + + YangMediaPayloadType* payload = find_media_with_payload_type(payload_type); + if (payload == NULL) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "can not find payload %d when pase fmtp", payload_type); + } + + std::string word; + FETCH(is, word); + + payload->m_format_specific_param = word; + + return err; +} + +int32_t YangMediaDesc::parse_attr_mid(const std::string& value) +{ + // @see: https://tools.ietf.org/html/rfc3388#section-3 + int32_t err = Yang_Ok; + std::istringstream is(value); + // mid_ means m-line id + FETCH(is, m_mid); + yang_trace("mid=%s", m_mid.c_str()); + return err; +} + +int32_t YangMediaDesc::parse_attr_msid(const std::string& value) +{ + // @see: https://tools.ietf.org/id/draft-ietf-mmusic-msid-08.html#rfc.section.2 + // TODO: msid and msid_tracker + int32_t err = Yang_Ok; + std::istringstream is(value); + // msid_ means media stream id + FETCH(is, m_msid); + is >> m_msid_tracker; + return err; +} + +int32_t YangMediaDesc::parse_attr_ssrc(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc5576#section-4.1 + + std::istringstream is(value); + + uint32_t ssrc = 0; + FETCH(is, ssrc); + + std::string ssrc_attr = ""; + FETCH_WITH_DELIM(is, ssrc_attr, ':'); + skip_first_spaces(ssrc_attr); + + std::string ssrc_value = is.str().substr(is.tellg()); + skip_first_spaces(ssrc_value); + + YangSSRCInfo& ssrc_info = fetch_or_create_ssrc_info(ssrc); + + if (ssrc_attr == "cname") { + // @see: https://tools.ietf.org/html/rfc5576#section-6.1 + ssrc_info.m_cname = ssrc_value; + ssrc_info.m_ssrc = ssrc; + } else if (ssrc_attr == "msid") { + // @see: https://tools.ietf.org/html/draft-alvestrand-mmusic-msid-00#section-2 + std::vector vec = yang_splits(ssrc_value, " "); + if (vec.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid ssrc line=%s", value.c_str()); + } + + ssrc_info.m_msid = vec[0]; + if (vec.size() > 1) { + ssrc_info.m_msid_tracker = vec[1]; + } + } else if (ssrc_attr == "mslabel") { + ssrc_info.m_mslabel = ssrc_value; + } else if (ssrc_attr == "label") { + ssrc_info.m_label = ssrc_value; + } + + return err; +} + +int32_t YangMediaDesc::parse_attr_ssrc_group(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc5576#section-4.2 + // a=ssrc-group: ... + + std::istringstream is(value); + + std::string semantics; + FETCH(is, semantics); + + std::string ssrc_ids = is.str().substr(is.tellg()); + skip_first_spaces(ssrc_ids); + + std::vector vec = yang_splits(ssrc_ids, " "); + if (vec.size() == 0) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid ssrc-group line=%s", value.c_str()); + } + + std::vector ssrcs; + for (size_t i = 0; i < vec.size(); ++i) { + std::istringstream in_stream(vec[i]); + uint32_t ssrc = 0; + in_stream >> ssrc; + ssrcs.push_back(ssrc); + } + m_ssrc_groups.push_back(YangSSRCGroup(semantics, ssrcs)); + + return err; +} + +YangSSRCInfo& YangMediaDesc::fetch_or_create_ssrc_info(uint32_t ssrc) +{ + for (size_t i = 0; i < m_ssrc_infos.size(); ++i) { + if (m_ssrc_infos[i].m_ssrc == ssrc) { + return m_ssrc_infos[i]; + } + } + + YangSSRCInfo ssrc_info; + ssrc_info.m_ssrc = ssrc; + m_ssrc_infos.push_back(ssrc_info); + + return m_ssrc_infos.back(); +} diff --git a/libyangrtc2/src/yangwebrtc/YangMediaDesc.h b/libyangrtc2/src/yangwebrtc/YangMediaDesc.h new file mode 100644 index 0000000000000000000000000000000000000000..4f1a148ab5ee90e195584fcc73e7f83720257813 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangMediaDesc.h @@ -0,0 +1,90 @@ +#ifndef SRC_YANGWEBRTC_YANGMEDIADESC_H_ +#define SRC_YANGWEBRTC_YANGMEDIADESC_H_ +#include +#include +#include + + +#define Yang_Fetch_Failed 200 +#define Yang_Fetch_Failed_WithDelim 200 +struct YangCandidate +{ + std::string ip_; + int32_t port_; + std::string type_; +}; + +class YangSessionInfo +{ +public: + YangSessionInfo(); + virtual ~YangSessionInfo(); + + int32_t parse_attribute(const std::string& attribute, const std::string& value); + int32_t encode(std::stringstream& os); + + bool operator=(const YangSessionInfo& rhs); +public: + std::string m_ice_ufrag; + std::string m_ice_pwd; + std::string m_ice_options; + std::string m_fingerprint_algo; + std::string m_fingerprint; + std::string m_setup; +}; + +class YangMediaDesc +{ +public: + YangMediaDesc(const std::string& type); + virtual ~YangMediaDesc(); +public: + int32_t parse_line(const std::string& line); + int32_t encode(std::stringstream& os); + YangMediaPayloadType* find_media_with_payload_type(int32_t payload_type); + std::vector find_media_with_encoding_name(const std::string& encoding_name) const; + + const std::map& get_extmaps() const { return m_extmaps; } + int32_t update_msid(std::string id); + bool find_encoding_name(const std::string& encoding_name) const; + bool is_audio() const { return m_type == "audio"; } + bool is_video() const { return m_type == "video"; } +private: + int32_t parse_attribute(const std::string& content); + int32_t parse_attr_rtpmap(const std::string& value); + int32_t parse_attr_rtcp(const std::string& value); + int32_t parse_attr_rtcp_fb(const std::string& value); + int32_t parse_attr_fmtp(const std::string& value); + int32_t parse_attr_mid(const std::string& value); + int32_t parse_attr_msid(const std::string& value); + int32_t parse_attr_ssrc(const std::string& value); + int32_t parse_attr_ssrc_group(const std::string& value); + int32_t parse_attr_extmap(const std::string& value); +private: + YangSSRCInfo& fetch_or_create_ssrc_info(uint32_t ssrc); + +public: + YangSessionInfo m_session_info; + std::string m_type; + int32_t m_port; + + bool m_rtcp_mux; + bool m_rtcp_rsize; + + bool m_sendonly; + bool m_recvonly; + bool m_sendrecv; + bool m_inactive; + + std::string m_mid; + std::string m_msid; + std::string m_msid_tracker; + std::string m_protos; + std::vector m_payload_types; + + std::vector m_candidates; + std::vector m_ssrc_groups; + std::vector m_ssrc_infos; + std::map m_extmaps; +}; +#endif /* SRC_YANGWEBRTC_YANGMEDIADESC_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRecvTrack.cpp b/libyangrtc2/src/yangwebrtc/YangRecvTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f0ee1c6f2311e6785ce1d4222715ddedb24fabb --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRecvTrack.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +YangRecvTrack::YangRecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *ptrack_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque, bool is_audio) { + m_uid = uid; + m_session = session; + m_track_desc = ptrack_desc->copy(); + m_rtpBuffer = rtpBuffer; + + if (is_audio) { + m_rtp_queue = new YangRtpPlayNackBuffer(100); + m_nack_receiver = new YangRtpNackForReceiver(m_rtp_queue, 100 * 2 / 3); + } else { + m_rtp_queue = new YangRtpPlayNackBuffer(1000); + m_nack_receiver = new YangRtpNackForReceiver(m_rtp_queue, 1000 * 2 / 3); + } + m_last_sender_report_rtp_time = 0; + m_last_sender_report_rtp_time1 = 0; + + m_last_sender_report_sys_time = 0; + //m_recvcb = NULL; + //m_mixQueue = pmixque; + m_conf = conf; + //m_usingMixav = m_conf->context->rtc.mixAvqueue; + m_last_seq=0; + memset(&m_audioFrame,0,sizeof(YangFrame)); + //memset(&m_videoFrame,0,sizeof(YangFrame)); +} + +YangRecvTrack::~YangRecvTrack() { + yang_delete(m_rtp_queue); + yang_delete(m_nack_receiver); + yang_delete(m_track_desc); + //m_recvcb = NULL; +} + +bool YangRecvTrack::has_ssrc(uint32_t ssrc) { + return m_track_desc->has_ssrc(ssrc); +} + +uint32_t YangRecvTrack::get_ssrc() { + return m_track_desc->ssrc_; +} + +void YangRecvTrack::update_rtt(int32_t rtt) { + m_nack_receiver->update_rtt(rtt); +} + +void YangRecvTrack::update_send_report_time(const YangNtp &ntp, + uint32_t rtp_time) { + m_last_sender_report_ntp1 = m_last_sender_report_ntp; + m_last_sender_report_rtp_time1 = m_last_sender_report_rtp_time; + + m_last_sender_report_ntp = ntp; + m_last_sender_report_rtp_time = rtp_time; + + m_last_sender_report_sys_time = yang_update_system_time(); +} + +int64_t YangRecvTrack::cal_avsync_time(uint32_t rtp_time) { + // Have no recv at least 2 sender reports, can't calculate sync time. + // TODO: FIXME: use the sample rate from sdp. + return (int64_t) rtp_time; + if (m_last_sender_report_rtp_time1 <= 0) { + return -1; + } + + // WebRTC using sender report to sync audio/video timestamp, because audio video have different timebase, + // typical audio opus is 48000Hz, video is 90000Hz. + // We using two sender report point to calculate avsync timestamp(clock time) with any given rtp timestamp. + // For example, there are two history sender report of audio as below. + // sender_report1: rtp_time1 = 10000, ntp_time1 = 40000 + // sender_report : rtp_time = 10960, ntp_time = 40020 + // (rtp_time - rtp_time1) / (ntp_time - ntp_time1) = 960 / 20 = 48, + // Now we can calcualte ntp time(ntp_x) of any given rtp timestamp(rtp_x), + // (rtp_x - rtp_time) / (ntp_x - ntp_time) = 48 => ntp_x = (rtp_x - rtp_time) / 48 + ntp_time; + double sys_time_elapsed = + static_cast(m_last_sender_report_ntp.m_system_ms) + - static_cast(m_last_sender_report_ntp1.m_system_ms); + + // Check sys_time_elapsed is equal to zero. + if (fpclassify(sys_time_elapsed) == FP_ZERO) { + return -1; + } + + double rtp_time_elpased = static_cast(m_last_sender_report_rtp_time) + - static_cast(m_last_sender_report_rtp_time1); + int rate = round(rtp_time_elpased / sys_time_elapsed); + + if (rate <= 0) { + return -1; + } + + double delta = round((rtp_time - m_last_sender_report_rtp_time) / rate); + + int64_t avsync_time = delta + m_last_sender_report_ntp.m_system_ms; + + return avsync_time; +} +int32_t YangRecvTrack::send_rtcp_rr() { + int32_t err = Yang_Ok; + + uint32_t ssrc = m_track_desc->ssrc_; + const uint64_t &last_time = m_last_sender_report_sys_time; + //printf("last_%ld",m_last_sender_report_sys_time); + if ((err = m_session->send_rtcp_rr(ssrc, m_rtp_queue, last_time, + m_last_sender_report_ntp)) != Yang_Ok) { + return yang_error_wrap(err, "ssrc=%u, last_time=%lld", ssrc, last_time); + } + + return err; +} + +int32_t YangRecvTrack::send_rtcp_xr_rrtr() { + int32_t err = Yang_Ok; + + if ((err = m_session->send_rtcp_xr_rrtr(m_track_desc->ssrc_)) != Yang_Ok) { + return yang_error_wrap(err, "ssrc=%u", m_track_desc->ssrc_); + } + + return err; +} +std::string YangRecvTrack::get_track_id() { + return m_track_desc->id_; +} + +int32_t YangRecvTrack::on_nack(YangRtpPacket *pkt) { + int32_t err = Yang_Ok; + + uint16_t seq = pkt->m_header.sequence; + + + YangRtpNackInfo *nack_info = m_nack_receiver->find(seq); + if (nack_info) { + // seq had been received. + //yang_trace("\nreceive seq===%hu", seq); + m_nack_receiver->remove(seq); + return err; + } + + // insert check nack list + uint16_t nack_first = 0, nack_last = 0; + m_rtp_queue->update(seq, nack_first, nack_last); + if (yang_rtp_seq_distance(nack_first, nack_last) > 0) { + //yang_trace("\nNACK: update seq=%u, nack range [%u, %u]", seq, nack_first, nack_last); + m_nack_receiver->insert(nack_first, nack_last); + m_nack_receiver->check_queue_size(); + + } + + // insert into video_queue and audio_queue + m_rtp_queue->set(seq, pkt->m_header.sequence); + if (!m_nack_receiver->isEmpty()) { + uint32_t timeout_nacks = 0; + do_check_send_nacks(timeout_nacks); + } + + return err; +} + +int32_t YangRecvTrack::do_check_send_nacks(uint32_t &timeout_nacks) { + uint32_t sent_nacks = 0; + return m_session->check_send_nacks(m_nack_receiver, m_track_desc->ssrc_, + sent_nacks, timeout_nacks); + +} diff --git a/libyangrtc2/src/yangwebrtc/YangRecvTrack.h b/libyangrtc2/src/yangwebrtc/YangRecvTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..bc323d72768a2b5733ad0b4767ca81145324aef9 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRecvTrack.h @@ -0,0 +1,74 @@ +#ifndef SRC_YANGWEBRTC_YANGRECVTRACK_H_ +#define SRC_YANGWEBRTC_YANGRECVTRACK_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class YangRecvTrack { +protected: + YangRtcTrack *m_track_desc; +public: + YangRtcSessionI *m_session; + //YangRtpRingBuffer *m_rtp_queue; + YangRtpPlayNackBuffer* m_rtp_queue; + YangRtpNackForReceiver *m_nack_receiver; + +protected: + // send report ntp and received time. + int32_t m_uid; + uint16_t m_last_seq; + // Latest sender report ntp and rtp time. + YangNtp m_last_sender_report_ntp; + int64_t m_last_sender_report_rtp_time; + + // Prev sender report ntp and rtp time. + YangNtp m_last_sender_report_ntp1; + int64_t m_last_sender_report_rtp_time1; + //YangNtp m_last_sender_report_ntp; + uint64_t m_last_sender_report_sys_time; + + YangRtpBuffer *m_rtpBuffer; + YangRtcContext *m_conf; + YangFrame m_audioFrame; + //YangFrame m_videoFrame; + //bool m_usingMixav; +public: + YangRecvTrack(int32_t uid, YangRtcContext *pcontext, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque, bool is_audio); + virtual ~YangRecvTrack(); + + virtual void setReceiveCallback(YangReceiveCallback *cbk)=0; +public: + + bool has_ssrc(uint32_t ssrc); + uint32_t get_ssrc(); + void update_rtt(int32_t rtt); + void update_send_report_time(const YangNtp &ntp, uint32_t rtp_time); + int64_t cal_avsync_time(uint32_t rtp_time); + int32_t send_rtcp_rr(); + int32_t send_rtcp_xr_rrtr(); + std::string get_track_id(); +public: + // Note that we can set the pkt to NULL to avoid copy, for example, if the NACK cache the pkt and + // set to NULL, nack nerver copy it but set the pkt to NULL. + int32_t on_nack(YangRtpPacket *ppkt); +public: + virtual int32_t on_rtp(YangRtpPacket *pkt) = 0; + virtual int32_t check_send_nacks() = 0; +protected: + virtual int32_t do_check_send_nacks(uint32_t &timeout_nacks); + void on_audio_data(YangMessage *msg); + void on_video_data(YangMessage *msg); + //YangReceiveCallback *m_recvcb; + //YangMixQueue *m_mixQueue; +}; +#endif /* SRC_YANGWEBRTC_YANGRECVTRACK_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.cpp b/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24be69c968135389d041765ad1c2a87c15b4d31e --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +YangRtcAudioRecvTrack::YangRtcAudioRecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque) : + YangRecvTrack(uid, conf, session, track_desc, rtpBuffer, pmixque, true) { + //m_audioCacheSize = 3; + m_aduioBuffer = NULL; + //if (conf->context->rtc.mixAvqueue == 0) { + // m_aduioBuffer = new YangRtpBuffer(m_audioCacheSize + 1, 5 * 512); + //} +} + +YangRtcAudioRecvTrack::~YangRtcAudioRecvTrack() { + //for (std::map::iterator it = m_audioMap.begin(); + // it != m_audioMap.end(); ++it) { + // yang_delete(it->second); + //} + //if (!m_audioMap.empty()) + // m_audioMap.clear(); + yang_delete(m_aduioBuffer); +} +void YangRtcAudioRecvTrack::setReceiveCallback(YangReceiveCallback *cbk) { + m_recvcb = cbk; +} +/** +int32_t YangRtcAudioRecvTrack::on_mixrtp(YangFrame *pkt) { + YangMessage *prt = new YangMessage(); + //YangRtpRawPayload *payload =dynamic_cast(pkt->payload()); + prt->mediaType = 0; + prt->nb = pkt->size(); + prt->timestamp = pkt-; + prt->payload = pkt->m_payload; + m_mixQueue->push(prt); + YangMessage *msg = m_mixQueue->pop(); + if (msg == NULL) + return Yang_Ok; + if (msg->mediaType) { + on_video_data(msg); + + } else { + on_audio_data(msg); + } + return Yang_Ok; +} + +YangRtpPacket* YangRtcAudioRecvTrack::get_audiortp(YangRtpPacket *src){ + if (m_audioMap.find(src->get_avsync_time()) != m_audioMap.end()) { + return NULL; + } + + YangFrame *rtpkt = src->copy(); + //YangRtpRawPayload *tpayload1 =dynamic_cast(rtpkt->payload()); + + char *tmp = src->m_payload; + src->m_payload = m_aduioBuffer->getBuffer(); + memcpy(src->m_payload, tmp, src->size()); + + m_audioMap[rtpkt->get_avsync_time()] = rtpkt; + + + if (m_audioMap.size() <= m_audioCacheSize) return NULL; + + map::iterator iter=m_audioMap.begin(); + YangRtpPacket* apkt=iter->second; + m_audioMap.erase(iter); + + return apkt; +}**/ +int32_t YangRtcAudioRecvTrack::on_rtp(YangRtpPacket *ppkt) { + int32_t err = Yang_Ok; + //if(m_usingMixav) return on_mixrtp(ppkt); + //YangRtpPacket *pkt = get_audiortp(ppkt); + + if (ppkt->m_payload){ + m_audioFrame.uid = m_uid; + m_audioFrame.payload = (uint8_t*) ppkt->m_payload; + m_audioFrame.nb = ppkt->m_nb; + m_audioFrame.timestamp = ppkt->m_header.timestamp; + + if (m_recvcb) m_recvcb->receiveAudio(&m_audioFrame); + } + + return err; +} + +int32_t YangRtcAudioRecvTrack::check_send_nacks() { + int32_t err = Yang_Ok; + uint32_t timeout_nacks = 0; + if ((err = do_check_send_nacks(timeout_nacks)) != Yang_Ok) { + return yang_error_wrap(err, "audio"); + } + + return err; +} + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.h b/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..bd79e26760b0e4adbd44238c3b828f7b9cb53680 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcAudioRecvTrack.h @@ -0,0 +1,27 @@ +#ifndef SRC_YANGWEBRTC_YANGRTCAUDIORECVTRACK_H_ +#define SRC_YANGWEBRTC_YANGRTCAUDIORECVTRACK_H_ +#include +#include +class YangRtcAudioRecvTrack: public YangRecvTrack +{ +public: + YangRtcAudioRecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque); + virtual ~YangRtcAudioRecvTrack(); + + +public: + int32_t on_rtp(YangRtpPacket *pkt); + int32_t on_mixrtp(YangRtpPacket *pkt); + YangRtpPacket *get_audiortp(YangRtpPacket *pkt); + int32_t check_send_nacks(); + void setReceiveCallback(YangReceiveCallback *cbk); + //size_t m_audioCacheSize; +private: + //map m_audioMap; + YangRtpBuffer *m_aduioBuffer; + YangReceiveCallback *m_recvcb; +}; + +#endif /* SRC_YANGWEBRTC_YANGRTCAUDIORECVTRACK_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcContext.cpp b/libyangrtc2/src/yangwebrtc/YangRtcContext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e99fc5469c7f150fb916f645a8976a3186ad34b9 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcContext.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +YangRtcContext::YangRtcContext() { + remote_audio = NULL; + remote_video = NULL; + + + + source = NULL; + streamConf = NULL; + context = NULL; + codec_="H264"; + + audioSsrc=YangRtcSSRCGenerator::instance()->generate_ssrc(); + videoSsrc=YangRtcSSRCGenerator::instance()->generate_ssrc(); + yang_trace("\naudiossrc===%u,videossrc==%u..........",audioSsrc,videoSsrc); + local_sdp=new YangSdp(); + remote_sdp=new YangSdp(); + state=0; +} +YangRtcContext::~YangRtcContext() { + + streamConf = NULL; + context = NULL; + yang_delete(local_sdp); + yang_delete(remote_sdp); + yang_delete(remote_audio); + yang_delete(remote_video); + yang_delete(source); +} +YangRtcTrack::YangRtcTrack() { + ssrc_ = 0; + fec_ssrc_ = 0; + rtx_ssrc_ = 0; +} +YangRtcTrack::~YangRtcTrack() { + +} + +YangRtcTrack* YangRtcTrack::copy() { + YangRtcTrack *cp = new YangRtcTrack(); + + cp->type_ = type_; + cp->id_ = id_; + cp->ssrc_ = ssrc_; + cp->fec_ssrc_ = fec_ssrc_; + cp->rtx_ssrc_ = rtx_ssrc_; + cp->extmaps_ = extmaps_; + return cp; +} +int32_t YangRtcTrack::get_rtp_extension_id(std::string uri) { + for (std::map::iterator it = extmaps_.begin(); + it != extmaps_.end(); ++it) { + if (uri == it->second) { + return it->first; + } + } + + return 0; +} +bool YangRtcTrack::has_ssrc(uint32_t ssrc) { + + if (ssrc == ssrc_ || ssrc == rtx_ssrc_ || ssrc == fec_ssrc_) { + return true; + } + + return false; +} + +void YangRtcTrack::add_rtp_extension_desc(int32_t id, std::string uri) { + extmaps_[id] = uri; +} + +void YangRtcTrack::del_rtp_extension_desc(std::string uri) { + for (std::map::iterator it = extmaps_.begin(); + it != extmaps_.end(); ++it) { + if (uri == it->second) { + extmaps_.erase(it++); + break; + } + } +} +void YangRtcTrack::set_rtx_ssrc(uint32_t ssrc) { + rtx_ssrc_ = ssrc; +} + +void YangRtcTrack::set_fec_ssrc(uint32_t ssrc) { + fec_ssrc_ = ssrc; +} + +void YangRtcTrack::set_mid(std::string mid) { + mid_ = mid; +} + +YangRtcSourceDescription::YangRtcSourceDescription() { + audio_track_desc_ = NULL; +} + +YangRtcSourceDescription::~YangRtcSourceDescription() { + yang_delete(audio_track_desc_); + + for (int32_t i = 0; i < (int) video_track_descs_.size(); ++i) { + yang_delete(video_track_descs_.at(i)); + } + video_track_descs_.clear(); +} + +YangRtcSourceDescription* YangRtcSourceDescription::copy() { + YangRtcSourceDescription *stream_desc = new YangRtcSourceDescription(); + + if (audio_track_desc_) { + stream_desc->audio_track_desc_ = audio_track_desc_->copy(); + } + + for (int32_t i = 0; i < (int) video_track_descs_.size(); ++i) { + stream_desc->video_track_descs_.push_back( + video_track_descs_.at(i)->copy()); + } + + return stream_desc; +} + +YangRtcTrack* YangRtcSourceDescription::find_track_description_by_ssrc( + uint32_t ssrc) { + if (audio_track_desc_ && audio_track_desc_->ssrc_ == ssrc) { + return audio_track_desc_; + } + + for (int32_t i = 0; i < (int) video_track_descs_.size(); ++i) { + if (video_track_descs_.at(i)->ssrc_ == ssrc) { + return video_track_descs_.at(i); + } + } + + return NULL; +} + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcContext.h b/libyangrtc2/src/yangwebrtc/YangRtcContext.h new file mode 100644 index 0000000000000000000000000000000000000000..af91d8a5192096df4f01c692ad28c928f7368ae6 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcContext.h @@ -0,0 +1,129 @@ +#ifndef SRC_YANGWEBRTC_YANGRTCCONTEXT_H_ +#define SRC_YANGWEBRTC_YANGRTCCONTEXT_H_ +#include +#include + +#include +#include +class YangSdp; +class YangRtcSourceDescription; + +class YangRtcContext{ +public: + YangRtcContext(); + ~YangRtcContext(); + std::string codec_; + + YangAudioParam* remote_audio; + YangVideoParam* remote_video; + YangSdp* local_sdp; + YangSdp* remote_sdp; + + uint32_t audioSsrc; + uint32_t videoSsrc; + int32_t state; + + YangRtcSourceDescription* source; + YangStreamConfig* streamConf; + YangContext* context; +}; +class YangRtcTrack{ +public: + YangRtcTrack(); + ~YangRtcTrack(); + std::string type_; + // track_id + std::string id_; + uint32_t ssrc_; + uint32_t rtx_ssrc_; + uint32_t fec_ssrc_; + std::string mid_; + // msid_: track stream id + std::string msid_; + std::map extmaps_; +public: + YangRtcTrack* copy(); + void add_rtp_extension_desc(int32_t id, std::string uri); + void del_rtp_extension_desc(std::string uri); + int32_t get_rtp_extension_id(std::string uri); + bool has_ssrc(uint32_t ssrc); + void set_rtx_ssrc(uint32_t ssrc); + void set_fec_ssrc(uint32_t ssrc); + void set_mid(std::string mid); +}; +class YangRtcSourceDescription +{ +public: + // the id for this stream; + std::string id_; + + YangRtcTrack* audio_track_desc_; + std::vector video_track_descs_; +public: + YangRtcSourceDescription(); + virtual ~YangRtcSourceDescription(); + +public: + YangRtcSourceDescription* copy(); + YangRtcTrack* find_track_description_by_ssrc(uint32_t ssrc); +}; + +/** +class YangRtcTrackDescription +{ +public: + // type: audio, video + std::string type_; + // track_id + std::string id_; + // ssrc is the primary ssrc for this track, + // if sdp has ssrc-group, it is the first ssrc of the ssrc-group + uint32_t ssrc_; + // rtx ssrc is the second ssrc of "FEC" src-group, + // if no rtx ssrc, rtx_ssrc_ = 0. + uint32_t fec_ssrc_; + // rtx ssrc is the second ssrc of "FID" src-group, + // if no rtx ssrc, rtx_ssrc_ = 0. + uint32_t rtx_ssrc_; + // key: rtp header extension id, value: rtp header extension uri. + std::map extmaps_; + // Whether this track active. default: active. + bool is_active_; + // direction + std::string direction_; + // mid is used in BOUNDLE + std::string mid_; + // msid_: track stream id + std::string msid_; + + // meida payload, such as opus, h264. + YangCodecPayload* media_; + YangCodecPayload* red_; + YangCodecPayload* rtx_; + YangCodecPayload* ulpfec_; +public: + YangRtcTrackDescription(); + virtual ~YangRtcTrackDescription(); +public: + // whether or not the track has ssrc. + // for example: + // we need check track has the ssrc in the ssrc_group, then add ssrc_group to the track, + bool has_ssrc(uint32_t ssrc); +public: + void add_rtp_extension_desc(int32_t id, std::string uri); + void del_rtp_extension_desc(std::string uri); + void set_direction(std::string direction); + void set_codec_payload(YangCodecPayload* payload); + // auxiliary paylod include red, rtx, ulpfec. + void create_auxiliary_payload(const std::vector payload_types); + void set_rtx_ssrc(uint32_t ssrc); + void set_fec_ssrc(uint32_t ssrc); + void set_mid(std::string mid); + int32_t get_rtp_extension_id(std::string uri); +public: + YangRtcTrackDescription* copy(); +}; + + +**/ +#endif /* SRC_YANGWEBRTC_YANGRTCCONTEXT_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcDtls.cpp b/libyangrtc2/src/yangwebrtc/YangRtcDtls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83e7618285975cf5399b168febcdbdc447f7ffa3 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcDtls.cpp @@ -0,0 +1,479 @@ +#include + + +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +#include +#endif +#include + +#ifdef _WIN32 +#include + +#define bzero(a, b) memset(a, 0, b) +#else +#include +#endif +int32_t yang_verify_callback(int32_t preverify_ok, X509_STORE_CTX *ctx) { + // Always OK, we don't check the certificate of client, + // because we allow client self-sign certificate. + + return 1; +} +void ssl_on_info(const SSL* dtls, int32_t where, int32_t ret) +{ + YangRtcDtls* dtls_impl = (YangRtcDtls*)SSL_get_ex_data(dtls, 0); + const char* method; + int32_t w = where& ~SSL_ST_MASK; + if (w & SSL_ST_CONNECT) { + method = "SSL_connect"; + } else if (w & SSL_ST_ACCEPT) { + method = "SSL_accept"; + } else { + method = "undefined"; + } + + int32_t r1 = SSL_get_error(dtls, ret); + if (where & SSL_CB_LOOP) { + + } else if (where & SSL_CB_ALERT) { + method = (where & SSL_CB_READ) ? "read":"write"; + + // @see https://www.openssl.org/docs/man1.0.2/man3/SSL_alert_type_string_long.html + string alert_type = SSL_alert_type_string_long(ret); + string alert_desc = SSL_alert_desc_string(ret); + // Notify the DTLS to handle the ALERT message, which maybe means media connection disconnect. + dtls_impl->on_dtls_alert(alert_type, alert_desc); + } +} +uint32_t dtls_timer_cb(SSL *dtls, uint32_t previous_us) { + YangRtcDtls *dtls_impl = (YangRtcDtls*) SSL_get_ex_data(dtls, 0); + if(!dtls_impl) return yang_error_wrap(ERROR_RTC_DTLS,"YangRtcDtls is null"); + + // Double the timeout. Note that it can be 0. + uint32_t timeout_us = previous_us * 2; + + // If previous_us is 0, for example, the HelloVerifyRequest, we should response it ASAP. + // When got ServerHello, we should reset the timer. + if (previous_us == 0 || dtls_impl->should_reset_timer()) { + timeout_us = 50 * 1000; // in us + } + // Never exceed the max timeout. + timeout_us = yang_min(timeout_us, 30 * 1000 * 1000); // in us + return timeout_us; +} + +YangRtcDtls::YangRtcDtls(YangContext* pcontext) { + m_context=pcontext; + m_sslctx = NULL; + m_ssl = NULL; + m_bioIn = NULL; + m_bioOut = NULL; + m_version = YangDtlsVersionAuto; + m_cer=NULL; + reset_timer_=false; + m_udp=NULL; + m_handshake_done=false; + m_isStart=0; + m_loop=0; + m_state=YangDtlsStateInit; + m_srtp = NULL; +} + +YangRtcDtls::~YangRtcDtls() { + + if (m_sslctx) { + SSL_CTX_free(m_sslctx); + m_sslctx = NULL; + } + + if (m_ssl) { + // this function will free bio_in and bio_out + SSL_free(m_ssl); + m_ssl = NULL; + } + + if(m_srtp ){ + delete m_srtp; + m_srtp = NULL; + } + m_cer=NULL; + m_udp=NULL; + m_context=NULL; +} +YangSRtp* YangRtcDtls::getSrtp(){ + return m_srtp; +} +int32_t YangRtcDtls::init(YangSendUdpData* pudp) { + + m_udp=pudp; + + m_cer=dynamic_cast(m_context->getCertificate()); + + string role = "actpass"; + m_sslctx = yang_build_dtls_ctx(m_version, role); + + if ((m_ssl = SSL_new(m_sslctx)) == NULL) { + printf("\nERROR_OpenSslCreateSSL, SSL_new dtls"); + return 1; + } + + SSL_set_ex_data(m_ssl, 0, this); + SSL_set_info_callback(m_ssl, ssl_on_info); + SSL_set_options(m_ssl, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(m_ssl, kRtpPacketSize); + SSL_set_connect_state(m_ssl);//SSL_set_accept_state(dtls); + SSL_set_max_send_fragment(m_ssl, kRtpPacketSize); +#if OPENSSL_VERSION_NUMBER >= 0x1010102fL // 1.1.1b + DTLS_set_timer_cb(m_ssl, dtls_timer_cb); +#endif + + if ((m_bioIn = BIO_new(BIO_s_mem())) == NULL) { + printf("\nERROR_OpenSslBIONew, BIO_new in"); + return 1; + } + + if ((m_bioOut = BIO_new(BIO_s_mem())) == NULL) { + BIO_free(m_bioIn); + printf("\nERROR_OpenSslBIONew, BIO_new out"); + return 1; + } + + SSL_set_bio(m_ssl, m_bioIn, m_bioOut); + m_srtp = new YangSRtp(); + + return Yang_Ok; +} +bool YangRtcDtls::should_reset_timer() { + bool v = reset_timer_; + reset_timer_ = false; + return v; +} + +int32_t YangRtcDtls::sendDtlsAlert(){ + + int32_t r0 = SSL_shutdown(m_ssl); + int32_t r1 = SSL_get_error(m_ssl, r0); + // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2. + if (r0 < 0 && (r1 != SSL_ERROR_NONE && r1 != SSL_ERROR_WANT_READ + && r1 != SSL_ERROR_WANT_WRITE)) { + printf("\nERROR_RTC_DTLS, handshake r0=%d, r1=%d\n", r0, r1); + return 1; + } + + uint8_t *data = NULL; + int32_t size = BIO_get_mem_data(m_bioOut, (char** )&data); + if(size>0&&m_udp) m_udp->sendData((char*)data,size); + + return Yang_Ok; +} +int32_t YangRtcDtls::on_dtls_alert(std::string type, std::string desc){ + yang_info("dtls alert ..type==%s,desc==%s",type.c_str(),desc.c_str()); + return Yang_Ok; +} +int32_t YangRtcDtls::decodeHandshake(char *data, int32_t nb_data) { + + int32_t r0 = 0; + + if ((r0 = BIO_reset(m_bioIn)) != 1) { + yang_error("ERROR_OpenSslBIOReset, BIO_in reset r0=%d", r0); + return 1; + } + if ((r0 = BIO_reset(m_bioOut)) != 1) { + yang_error("ERROR_OpenSslBIOReset, BIO_out reset r0=%d", r0); + return 1; + } + + // Trace the detail of DTLS packet. + + if ((r0 = BIO_write(m_bioIn, data, nb_data)) <= 0) { + + printf("\nERROR_OpenSslBIOWrite, BIO_write r0=%d", r0); + return 1; + } + + int32_t err = 0; + if((err=this->doHandshake()!=Yang_Ok)){ + return 1; + } + + for (int32_t i = 0; i < 1024 && BIO_ctrl_pending(m_bioIn) > 0; i++) { + char buf[8092]; + int32_t r0 = SSL_read(m_ssl, buf, sizeof(buf)); + int32_t r1 = SSL_get_error(m_ssl, r0); + if (r0 <= 0) { + + if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE) { + break; + } + + uint8_t *data = NULL; + int32_t size = BIO_get_mem_data(m_bioOut, (char** )&data); + if(size>0&&m_udp) m_udp->sendData((char*)data,size); + continue; + } + + + } + + return Yang_Ok; +} +int32_t YangRtcDtls::startHandShake(){ + if(doHandshake()) return 1; + start(); + return Yang_Ok; +} + +int32_t YangRtcDtls::doHandshake() { + if (m_handshake_done) { + return 0; + } + + int32_t r0 = SSL_do_handshake(m_ssl); + int32_t r1 = SSL_get_error(m_ssl, r0); + + // Fatal SSL error, for example, no available suite when peer is DTLS 1.0 while we are DTLS 1.2. + if (r0 < 0 && (r1 != SSL_ERROR_NONE && r1 != SSL_ERROR_WANT_READ + && r1 != SSL_ERROR_WANT_WRITE)) { + yang_trace("\nERROR_RTC_DTLS, handshake r0=%d, r1=%d\n", r0, r1); + return 1; + } + + if (r1 == SSL_ERROR_NONE) { + m_handshake_done = true; + yang_trace("\n******************dtls handshake is sucess....................\n"); + } + uint8_t *data = NULL; + int32_t size = BIO_get_mem_data(m_bioOut, (char** )&data); + + filter_data(data, size); + + if(size>0&&m_udp) m_udp->sendData((char*)data,size); + + if(m_handshake_done){ + on_handshake_done(); + + } + + return Yang_Ok; +} +int32_t YangRtcDtls::filter_data(uint8_t* data, int32_t size) +{ + int32_t err = Yang_Ok; + + if (m_state==YangDtlsStateInit&&size > 14 && data[0] == 22 && data[13] == 1) { + m_state=YangDtlsStateClientHello; + return err; + } + + if (m_state==1&&size > 14 && data[0] == 22 && data[13] == 11) { + m_state=YangDtlsStateClientCertificate; + reset_timer_ = true; + yang_trace("\nDTLS: Reset the timer for ServerHello"); + return err; + } + + return err; +} +const int32_t SRTP_MASTER_KEY_KEY_LEN = 16; +const int32_t SRTP_MASTER_KEY_SALT_LEN = 14; +int32_t YangRtcDtls::get_srtp_key(char* recv_key, int *precvkeylen,char* send_key,int *psendkeylen){ + int32_t err = Yang_Ok; + + uint8_t material[SRTP_MASTER_KEY_LEN * 2] = {0}; // client(SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN) + server + static const string dtls_srtp_lable = "EXTRACTOR-dtls_srtp"; + if (!SSL_export_keying_material(m_ssl, material, sizeof(material), dtls_srtp_lable.c_str(), dtls_srtp_lable.size(), NULL, 0, 0)) { + return yang_error_wrap(ERROR_RTC_SRTP_INIT, "SSL export key r0=%lu", ERR_get_error()); + } + + size_t offset = 0; + + + memcpy(send_key,material,SRTP_MASTER_KEY_KEY_LEN); + offset += SRTP_MASTER_KEY_KEY_LEN; + + memcpy(recv_key,material+offset,SRTP_MASTER_KEY_KEY_LEN); + offset += SRTP_MASTER_KEY_KEY_LEN; + + memcpy(send_key+SRTP_MASTER_KEY_KEY_LEN,material+offset,SRTP_MASTER_KEY_SALT_LEN); + offset += SRTP_MASTER_KEY_SALT_LEN; + + memcpy(recv_key+SRTP_MASTER_KEY_KEY_LEN,material+offset,SRTP_MASTER_KEY_SALT_LEN); + + + *precvkeylen=SRTP_MASTER_KEY_KEY_LEN+SRTP_MASTER_KEY_SALT_LEN; + *psendkeylen=SRTP_MASTER_KEY_KEY_LEN+SRTP_MASTER_KEY_SALT_LEN; + return err; + +} + +YangDtlsState YangRtcDtls::getDtlsState(){ + return m_state; +} + +int32_t YangRtcDtls::on_handshake_done() +{ + int32_t err = Yang_Ok; + + // Ignore if done. + if (m_state == YangDtlsStateClientDone) { + return err; + } + + // Change to done state. + m_state = YangDtlsStateClientDone; + // When handshake done, stop the ARQ. + stop(); + char send_key[50]; + char recv_key[50]; + int sendKeyLen=30; + int recvKeyLen=30; + if ((err = get_srtp_key(recv_key, &recvKeyLen,send_key,&sendKeyLen)) != Yang_Ok) { + return err; + } + + if ((err = m_srtp->init(recv_key,recvKeyLen, send_key,sendKeyLen)) != Yang_Ok) { + return yang_error_wrap(err, "srtp init"); + } + + return err; +} + +void YangRtcDtls::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangRtcDtls::stop() { + stopLoop(); + +} +void YangRtcDtls::stopLoop() { + m_loop = 0; + +} +#define YANG_UTIME_MILLISECONDS 1000 +int32_t YangRtcDtls::startLoop() +{ + int32_t err = Yang_Ok; + const int32_t max_loop = 512; + int32_t arq_count = 0; + int32_t arq_max_retry = 12 * 2; + for (int32_t i = 0; arq_count < arq_max_retry && i < max_loop; i++) { + if (m_handshake_done) { + return err; + } + + // For DTLS client ARQ, the state should be specified. + if (m_state != YangDtlsStateClientHello && m_state != YangDtlsStateClientCertificate) { + return err; + } + + // If there is a timeout in progress, it sets *out to the time remaining + // and returns one. Otherwise, it returns zero. + int32_t r0 = 0; timeval to = {0}; + if ((r0 = DTLSv1_get_timeout(m_ssl, &to)) == 0) { + // No timeout, for example?, wait for a default 50ms. + yang_usleep(50 * YANG_UTIME_MILLISECONDS); + continue; + } + int64_t timeout = to.tv_sec + to.tv_usec; + + + if (timeout > 0) { + timeout = yang_min(100 * YANG_UTIME_MILLISECONDS, timeout); + timeout = yang_max(50 * YANG_UTIME_MILLISECONDS, timeout); + yang_usleep((unsigned int)timeout); + continue; + } + + r0 = BIO_reset(m_bioOut); int32_t r1 = SSL_get_error(m_ssl, r0); + if (r0 != 1) { + return yang_error_wrap(ERROR_OpenSslBIOReset,"OpenSslBIORese BIO_reset r0=%d, r1=%d", r0, r1); + } + + r0 = DTLSv1_handle_timeout(m_ssl); r1 = SSL_get_error(m_ssl, r0); + if (r0 == 0) { + continue; // No timeout had expired. + } + if (r0 != 1) { + return yang_error_wrap(ERROR_RTC_DTLS,"dtls error ARQ r0=%d, r1=%d", r0, r1); + + } + + + uint8_t* data = NULL; + int32_t size = BIO_get_mem_data(m_bioOut, (char**)&data); + arq_count++; + if (size > 0 && (err = m_udp->sendData((char*)data, size)) != Yang_Ok) { + return yang_error_wrap(ERROR_RTC_DTLS,"error dtls send size=%u", size); + } + } + + return err; +} + + +SSL_CTX* YangRtcDtls::yang_build_dtls_ctx(YangDtlsVersion version, std::string role) { + SSL_CTX *dtls_ctx; +#if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2 + m_sslctx = SSL_CTX_new(DTLSv1_method()); +#else + if (version == YangDtlsVersion1_2) { + if (role == "active") { + dtls_ctx = SSL_CTX_new(DTLS_client_method()); + } else { + dtls_ctx = SSL_CTX_new(DTLS_server_method()); + } + } else { + // YangDtlsVersionAuto, use version-flexible DTLS methods + dtls_ctx = SSL_CTX_new(DTLS_method()); + } +#endif + + if (m_cer->is_ecdsa()) { // By ECDSA, https://stackoverflow.com/a/6006898 +#if OPENSSL_VERSION_NUMBER >= 0x10002000L // v1.0.2 + // For ECDSA, we could set the curves list. + // @see https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set1_curves_list.html + SSL_CTX_set1_curves_list(dtls_ctx, "P-521:P-384:P-256"); +#endif + + // For openssl <1.1, we must set the ECDH manually. + // @see https://stackoverrun.com/cn/q/10791887 +#if OPENSSL_VERSION_NUMBER < 0x10100000L // v1.1.x + #if OPENSSL_VERSION_NUMBER < 0x10002000L // v1.0.2 + SSL_CTX_set_tmp_ecdh(m_sslctx, _srs_rtc_dtls_certificate->get_ecdsa_key()); + #else + SSL_CTX_set_ecdh_auto(m_sslctx, 1); + #endif +#endif + } + + // Setup DTLS context. + if (true) { + //yang_assert(SSL_CTX_set_cipher_list(dtls_ctx, "ALL") == 1); + if(SSL_CTX_set_cipher_list(dtls_ctx, "ALL") != 1) yang_error("SSL_CTX_set_cipher_list error"); + //yang_assert(SSL_CTX_use_certificate(dtls_ctx,m_cer->get_cert()) == 1); + if(SSL_CTX_use_certificate(dtls_ctx,m_cer->get_cert()) != 1) yang_error("SSL_CTX_use_certificate error"); + //yang_assert(SSL_CTX_use_PrivateKey(dtls_ctx, m_cer->get_public_key()) == 1); + if(SSL_CTX_use_PrivateKey(dtls_ctx, m_cer->get_public_key()) != 1) yang_error("SSL_CTX_use_PrivateKey error"); + + + SSL_CTX_set_verify(dtls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, + yang_verify_callback); + SSL_CTX_set_verify_depth(dtls_ctx, 4); + SSL_CTX_set_read_ahead(dtls_ctx, 1); + //yang_assert(SSL_CTX_set_tlsext_use_srtp(dtls_ctx, "SRTP_AES128_CM_SHA1_80") == 0); + if(SSL_CTX_set_tlsext_use_srtp(dtls_ctx, "SRTP_AES128_CM_SHA1_80") != 0) yang_error("SSL_CTX_set_tlsext_use_srtp error"); + } + + return dtls_ctx; +} + + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcDtls.h b/libyangrtc2/src/yangwebrtc/YangRtcDtls.h new file mode 100644 index 0000000000000000000000000000000000000000..789ea2003ce10d94dd78f5e750b438e7b17013ab --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcDtls.h @@ -0,0 +1,83 @@ +#ifndef YANGWEBRTC_YANGRTCDTLS_H_ +#define YANGWEBRTC_YANGRTCDTLS_H_ + +#include + +#include +#include +#include +#include + +#include +#include +#include +using namespace std; + +enum YangDtlsRole { + YangDtlsRoleClient, + YangDtlsRoleServer +}; +enum YangDtlsState { + YangDtlsStateInit, // Start. + YangDtlsStateClientHello, // Should start ARQ thread. + YangDtlsStateServerHello, // We are in the first ARQ state. + YangDtlsStateClientCertificate, // Should start ARQ thread again. + YangDtlsStateServerDone, // We are in the second ARQ state. + YangDtlsStateClientDone, // Done. +}; + +enum YangDtlsVersion { + YangDtlsVersionAuto = -1, + YangDtlsVersion1_0, + YangDtlsVersion1_2 +}; +class YangSendUdpData{ +public: + YangSendUdpData(){}; + virtual ~YangSendUdpData(){}; + virtual int32_t sendData(char* p,int32_t plen)=0; +}; +class YangRtcDtls :public YangThread{ +public: + YangRtcDtls(YangContext* pcontext); + virtual ~YangRtcDtls(); + int32_t init(YangSendUdpData* pudp); + int32_t doHandshake(); + int32_t startHandShake(); + int32_t decodeHandshake(char* p,int32_t len); + int32_t sendDtlsAlert(); + int32_t filter_data(uint8_t* data, int32_t size); + bool should_reset_timer(); + int32_t on_dtls_alert(std::string type, std::string desc); + int32_t get_srtp_key(char* recv_key, int *precvkeylen,char* send_key,int *psendkeylen); + YangSRtp* getSrtp(); + YangDtlsState getDtlsState(); + int32_t m_isStart; + int32_t m_loop; + void stop(); +protected: + void run(); + int32_t startLoop(); + void stopLoop(); + + int32_t on_handshake_done(); +protected: + YangContext* m_context; + YangCertificateImpl *m_cer; + YangSRtp* m_srtp; + YangDtlsState m_state; + SSL_CTX* m_sslctx; + bool reset_timer_; + YangSendUdpData* m_udp; + SSL* m_ssl; + BIO* m_bioIn; + BIO* m_bioOut; + YangDtlsVersion m_version; + + bool m_handshake_done; + SSL_CTX* yang_build_dtls_ctx(YangDtlsVersion version, std::string role); +}; + + + +#endif /* YANGWEBRTC_YANGRTCDTLS_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.cpp b/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c6c52f5ddca4b0af6c576f7a00c5f2fb018ce00 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.cpp @@ -0,0 +1,448 @@ +#include +#include +#include "YangRtcSdp.h" +#include +#include +#include +#include +using namespace std; +YangRtcPlayStream::YangRtcPlayStream(YangRtcSessionI *psession) { + m_session = psession; + m_request_keyframe = false; + m_nn_simulate_nack_drop = 0; + m_nack_enabled = true; + + m_pt_to_drop = 0; + m_twcc_enabled = false; + m_twcc_id = 0; + m_twcc_fb_count = 0; + m_last_time_send_twcc = 0; + m_conf = NULL; + m_rtpBuffer = NULL; +} + +YangRtcPlayStream::~YangRtcPlayStream() { + + for (int32_t i = 0; i < (int) m_video_tracks.size(); ++i) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + yang_delete(track); + } + m_video_tracks.clear(); + + for (int32_t i = 0; i < (int) m_audio_tracks.size(); ++i) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + yang_delete(track); + } + m_audio_tracks.clear(); + + m_conf = NULL; + m_session = NULL; +} + +int32_t YangRtcPlayStream::initialize(YangRtcContext *conf, + YangRtcSourceDescription *stream_desc, YangReceiveCallback *cbk, + YangRtpBuffer *rtpBuffer) { + int32_t err = Yang_Ok; + m_conf = conf; + m_rtpBuffer = rtpBuffer; + m_mixQueue.setAudioSize(conf->context->rtc.audioQueueCount); + m_mixQueue.setVideoSize(conf->context->rtc.videoQueueCount); + if (stream_desc->audio_track_desc_) { + m_audio_tracks.push_back( + new YangRtcAudioRecvTrack(conf->streamConf->uid, conf, + m_session, stream_desc->audio_track_desc_, rtpBuffer, + &m_mixQueue)); + + } + + for (int32_t i = 0; i < (int) stream_desc->video_track_descs_.size(); ++i) { + YangRtcTrack *desc = stream_desc->video_track_descs_.at(i); + m_video_tracks.push_back( + new YangVideoRecvTrack(conf->streamConf->uid, conf, + m_session, desc, rtpBuffer, &m_mixQueue)); + } + + int32_t twcc_id = -1; + uint32_t media_ssrc = 0; + // because audio_track_desc have not twcc id, for example, h5demo + // fetch twcc_id from video track description, + for (int32_t i = 0; i < (int) stream_desc->video_track_descs_.size(); ++i) { + YangRtcTrack *desc = stream_desc->video_track_descs_.at(i); + twcc_id = desc->get_rtp_extension_id(kTWCCExt); + + media_ssrc = desc->ssrc_; + break; + } + if (twcc_id > 0) { + m_twcc_id = twcc_id; + m_extension_types.register_by_uri(m_twcc_id, kTWCCExt); + m_rtcp_twcc.set_media_ssrc(media_ssrc); + } + + m_nack_enabled = true; + m_pt_to_drop = 0; + m_twcc_enabled = true; + + // No TWCC when negotiate, disable it. + if (twcc_id <= 0) { + m_twcc_enabled = false; + } + + yang_trace("RTC publisher nack=%d, pt-drop=%u, twcc=%u/%d", m_nack_enabled, + m_pt_to_drop, m_twcc_enabled, twcc_id); + + // Setup tracks. + for (int32_t i = 0; i < (int) m_audio_tracks.size(); i++) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + track->setReceiveCallback(cbk); + } + + for (int32_t i = 0; i < (int) m_video_tracks.size(); i++) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + track->setReceiveCallback(cbk); + } + return err; +} + +int32_t YangRtcPlayStream::send_rtcp_rr() { + int32_t err = Yang_Ok; + + for (int32_t i = 0; i < (int) m_video_tracks.size(); ++i) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + if ((err = track->send_rtcp_rr()) != Yang_Ok) { + return yang_error_wrap(err, "track=%s", + track->get_track_id().c_str()); + } + } + + for (int32_t i = 0; i < (int) m_audio_tracks.size(); ++i) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + if ((err = track->send_rtcp_rr()) != Yang_Ok) { + return yang_error_wrap(err, "track=%s", + track->get_track_id().c_str()); + } + } + + return err; +} + +int32_t YangRtcPlayStream::send_rtcp_xr_rrtr() { + int32_t err = Yang_Ok; + + for (int32_t i = 0; i < (int) m_video_tracks.size(); ++i) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + if ((err = track->send_rtcp_xr_rrtr()) != Yang_Ok) { + return yang_error_wrap(err, "track=%s", + track->get_track_id().c_str()); + } + } + + for (int32_t i = 0; i < (int) m_audio_tracks.size(); ++i) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + if ((err = track->send_rtcp_xr_rrtr()) != Yang_Ok) { + return yang_error_wrap(err, "track=%s", + track->get_track_id().c_str()); + } + } + + return err; +} + +int32_t YangRtcPlayStream::on_twcc(uint16_t sn) { + int32_t err = Yang_Ok; + + int64_t now = yang_get_system_time(); + err = m_rtcp_twcc.recv_packet(sn, now); + + return err; +} + +int32_t YangRtcPlayStream::on_rtp(char *data, int32_t nb_data) { + int32_t err = Yang_Ok; + /** + if (m_twcc_id) { + // We must parse the TWCC from RTP header before SRTP unprotect, because: + // 1. Client may send some padding packets with invalid SequenceNumber, which causes the SRTP fail. + // 2. Server may send multiple duplicated NACK to client, and got more than one ARQ packet, which also fail SRTP. + // so, we must parse the header before SRTP unprotect(which may fail and drop packet). + + uint16_t twcc_sn = 0; + if ((err = yang_rtp_fast_parse_twcc(data, nb_data, m_twcc_id, twcc_sn))== Yang_Ok) { + printf("twcc_%hu,",twcc_sn); + if((err = on_twcc(twcc_sn)) != Yang_Ok) { + return yang_error_wrap(err, "on twcc"); + } + } + } + **/ + + char *plaintext = data; + int32_t nb_plaintext = nb_data; + if ((err = m_session->get_srtp()->dec_rtp(plaintext, &nb_plaintext))!= Yang_Ok) { + if(err==srtp_err_status_replay_fail) return Yang_Ok; + YangBuffer b(data, nb_data); YangRtpHeader h; memset(&h,0,sizeof(YangRtpHeader));h.ignore_padding=true; + //int r0 = h.decode(&b); // Ignore any error for header decoding. + yang_decode_rtpHeader(&b,&h); + return yang_error_wrap(err, "marker=%u, pt=%u, seq=%u, ts=%u, ssrc=%u, pad=%u, payload=%uB", h.marker, h.payload_type, + h.sequence, h.timestamp, h.ssrc, h.padding_length, nb_data - b.pos()); + } + + m_rtp.reset(); + m_buf.init(m_rtp.wrap(m_rtpBuffer, plaintext, nb_plaintext), nb_plaintext); + + m_rtp.set_extension_types(&m_extension_types); + m_rtp.m_header.ignore_padding=false; + + if ((err = m_rtp.decode(&m_buf)) != Yang_Ok) { + return yang_error_wrap(err, "decode rtp packet"); + } + + uint32_t ssrc = m_rtp.m_header.ssrc; + YangRtcAudioRecvTrack *audio_track = get_audio_track(ssrc); + YangVideoRecvTrack *video_track = get_video_track(ssrc); + + if (audio_track) { + m_rtp.m_frame_type = YangFrameTypeAudio; + if ((err = audio_track->on_rtp(&m_rtp)) != Yang_Ok) { + return yang_error_wrap(err, "on audio"); + } + } else if (video_track) { + m_rtp.m_frame_type = YangFrameTypeVideo; + if ((err = video_track->on_rtp(&m_rtp)) != Yang_Ok) { + return yang_error_wrap(err, "on video"); + } + } else { + return yang_error_wrap(ERROR_RTC_RTP, "unknown ssrc=%u", ssrc); + } + + // For NACK to handle packet. + + if (audio_track) { + if ((err = audio_track->on_nack(&m_rtp)) != Yang_Ok) { + return yang_error_wrap(err, "on nack"); + } + } else if (video_track) { + if ((err = video_track->on_nack(&m_rtp)) != Yang_Ok) { + return yang_error_wrap(err, "on nack"); + } + } + return err; +} + + + + + +int32_t YangRtcPlayStream::check_send_nacks() { + int32_t err = Yang_Ok; + + //if (!m_nack_enabled) { + // return err; + //} + + for (int32_t i = 0; i < (int) m_video_tracks.size(); ++i) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + if ((err = track->check_send_nacks()) != Yang_Ok) { + return yang_error_wrap(err, "video track=%s", + track->get_track_id().c_str()); + } + } + + for (int32_t i = 0; i < (int) m_audio_tracks.size(); ++i) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + if ((err = track->check_send_nacks()) != Yang_Ok) { + return yang_error_wrap(err, "audio track=%s", + track->get_track_id().c_str()); + } + } + + return err; + +} +YangVideoRecvTrack* YangRtcPlayStream::get_video_track(uint32_t ssrc) { + for (int32_t i = 0; i < (int) m_video_tracks.size(); ++i) { + YangVideoRecvTrack *track = m_video_tracks.at(i); + if (track->has_ssrc(ssrc)) { + return track; + } + } + + return NULL; +} + +YangRtcAudioRecvTrack* YangRtcPlayStream::get_audio_track(uint32_t ssrc) { + for (int32_t i = 0; i < (int) m_audio_tracks.size(); ++i) { + YangRtcAudioRecvTrack *track = m_audio_tracks.at(i); + if (track->has_ssrc(ssrc)) { + return track; + } + } + + return NULL; +} + + +int32_t YangRtcPlayStream::send_periodic_twcc() { + int32_t err = Yang_Ok; + m_last_time_send_twcc = yang_get_system_time(); + + if (!m_rtcp_twcc.need_feedback()) { + return err; + } + + // limit the max count=1024 to avoid dead loop. + for (int32_t i = 0; i < 1024 && m_rtcp_twcc.need_feedback(); ++i) { + char pkt[kMaxUDPDataSize]; + YangBuffer *buffer = new YangBuffer(pkt, sizeof(pkt)); + YangAutoFree(YangBuffer, buffer); + + m_rtcp_twcc.set_feedback_count(m_twcc_fb_count); + m_twcc_fb_count++; + + if ((err = m_rtcp_twcc.encode(buffer)) != Yang_Ok) { + return yang_error_wrap(err, "encode, count=%u", m_twcc_fb_count); + } + + if ((err = m_session->send_rtcp(pkt, buffer->pos())) != Yang_Ok) { + return yang_error_wrap(err, "send twcc, count=%u", m_twcc_fb_count); + } + } + return err; +} + +int32_t YangRtcPlayStream::on_rtcp(YangRtcpCommon *rtcp) { + if (YangRtcpType_sr == rtcp->type()) { + YangRtcpSR *sr = dynamic_cast(rtcp); + return on_rtcp_sr(sr); + } else if (YangRtcpType_xr == rtcp->type()) { + YangRtcpXr *xr = dynamic_cast(rtcp); + return on_rtcp_xr(xr); + } else if (YangRtcpType_sdes == rtcp->type()) { + //ignore RTCP SDES + return Yang_Ok; + } else if (YangRtcpType_bye == rtcp->type()) { + // TODO: FIXME: process rtcp bye. + return Yang_Ok; + } else { + return yang_error_wrap(ERROR_RTC_RTCP_CHECK, "unknown rtcp type=%u", + rtcp->type()); + } +} + +int32_t YangRtcPlayStream::on_rtcp_sr(YangRtcpSR *rtcp) { + int32_t err = Yang_Ok; + YangNtp yang_ntp = YangNtp::to_time_ms(rtcp->get_ntp()); + //yang_trace("\nrtcp sr.....%ld",rtcp->get_ntp()); + // yang_debug("sender report, ssrc_of_sender=%u, rtp_time=%u, sender_packet_count=%u, sender_octec_count=%u", + // rtcp->get_ssrc(), rtcp->get_rtp_ts(), rtcp->get_rtp_send_packets(), rtcp->get_rtp_send_bytes()); + + update_send_report_time(rtcp->get_ssrc(), yang_ntp, rtcp->get_rtp_ts()); + + return err; +} + +int32_t YangRtcPlayStream::on_rtcp_xr(YangRtcpXr *rtcp) { + int32_t err = Yang_Ok; + + /* + @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|reserved | PT=XR=207 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : report blocks : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + YangBuffer stream(rtcp->data(), rtcp->size()); + /*uint8_t first = */stream.read_1bytes(); + uint8_t pt = stream.read_1bytes(); + if (pt != kXR) + return yang_error_wrap(ERROR_RTC_RTCP_CHECK, "invalid XR packet"); + //srs_assert(pt == kXR); + uint16_t length = (stream.read_2bytes() + 1) * 4; + /*uint32_t ssrc = */stream.read_4bytes(); + + if (length > rtcp->size()) { + return yang_error_wrap(ERROR_RTC_RTCP_CHECK, + "invalid XR packet, length=%u, nb_buf=%d", length, rtcp->size()); + } + + while (stream.pos() + 4 < length) { + uint8_t bt = stream.read_1bytes(); + stream.skip(1); + uint16_t block_length = (stream.read_2bytes() + 1) * 4; + + if (stream.pos() + block_length - 4 > rtcp->size()) { + return yang_error_wrap(ERROR_RTC_RTCP_CHECK, + "invalid XR packet block, block_length=%u, nb_buf=%d", + block_length, rtcp->size()); + } + + if (bt == 5) { + for (int32_t i = 4; i < block_length; i += 12) { + uint32_t ssrc = stream.read_4bytes(); + uint32_t lrr = stream.read_4bytes(); + uint32_t dlrr = stream.read_4bytes(); + + YangNtp cur_ntp = YangNtp::from_time_ms( + yang_update_system_time() / 1000); + uint32_t compact_ntp = (cur_ntp.m_ntp_second << 16) + | (cur_ntp.m_ntp_fractions >> 16); + + int32_t rtt_ntp = compact_ntp - lrr - dlrr; + int32_t rtt = ((rtt_ntp * 1000) >> 16) + + ((rtt_ntp >> 16) * 1000); + yang_trace("ssrc=%u, compact_ntp=%u, lrr=%u, dlrr=%u, rtt=%d", + ssrc, compact_ntp, lrr, dlrr, rtt); + + update_rtt(ssrc, rtt); + } + } + } + + return err; +} + + + +void YangRtcPlayStream::simulate_nack_drop(int32_t nn) { + m_nn_simulate_nack_drop = nn; +} + +void YangRtcPlayStream::simulate_drop_packet(YangRtpHeader *h, + int32_t nn_bytes) { + + m_nn_simulate_nack_drop--; +} + +void YangRtcPlayStream::update_rtt(uint32_t ssrc, int32_t rtt) { + YangVideoRecvTrack *video_track = get_video_track(ssrc); + if (video_track) { + return video_track->update_rtt(rtt); + } + + YangRtcAudioRecvTrack *audio_track = get_audio_track(ssrc); + if (audio_track) { + return audio_track->update_rtt(rtt); + } +} + +void YangRtcPlayStream::update_send_report_time(uint32_t ssrc, + const YangNtp &ntp, uint32_t rtp_time) { + YangVideoRecvTrack *video_track = get_video_track(ssrc); + if (video_track) { + return video_track->update_send_report_time(ntp, rtp_time); + } + + YangRtcAudioRecvTrack *audio_track = get_audio_track(ssrc); + if (audio_track) { + return audio_track->update_send_report_time(ntp, rtp_time); + } +} + + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.h b/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.h new file mode 100644 index 0000000000000000000000000000000000000000..cb174285950d6b3d871b7905ebdc4793b11a37b5 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcPlayStream.h @@ -0,0 +1,84 @@ + +#ifndef YANGWEBRTC_YANGRTCPLAYSTREAM_H_ +#define YANGWEBRTC_YANGRTCPLAYSTREAM_H_ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +using namespace std; +class YangRtcTrack; +class YangRtcSourceDescription; + +class YangRtcPlayStream{ +public: + YangRtcPlayStream(YangRtcSessionI *psession); + virtual ~YangRtcPlayStream(); + + int32_t initialize(YangRtcContext *conf, + YangRtcSourceDescription *stream_desc, YangReceiveCallback *cbk, + YangRtpBuffer *rtpBuffer); + int32_t send_rtcp_rr(); + int32_t send_rtcp_xr_rrtr(); + int32_t check_send_nacks(); + int32_t send_periodic_twcc(); + //void request_keyframe(uint32_t ssrc); + + + int32_t on_rtp(char *data, int32_t nb_data); + int32_t on_rtcp(YangRtcpCommon *rtcp); +private: + int32_t on_rtcp_sr(YangRtcpSR *rtcp); + int32_t on_rtcp_xr(YangRtcpXr *rtcp); + int32_t on_twcc(uint16_t sn); + void update_rtt(uint32_t ssrc, int32_t rtt); + void update_send_report_time(uint32_t ssrc, const YangNtp &ntp, + uint32_t rtp_time); + void simulate_nack_drop(int32_t nn); + void simulate_drop_packet(YangRtpHeader *h, int32_t nn_bytes); + +private: + YangRtcContext *m_conf; + YangRtcSessionI *m_session; + uint16_t m_pt_to_drop; + YangRtpBuffer *m_rtpBuffer; + YangMixQueue m_mixQueue; + YangRtpPacket m_rtp; + YangBuffer m_buf; + + bool m_twcc_enabled; + int32_t m_twcc_id; + int64_t m_last_time_send_twcc; + uint8_t m_twcc_fb_count; + YangRtcpTWCC m_rtcp_twcc; + + bool m_nack_enabled; + + YangRtpExtensionTypes m_extension_types; + + int32_t m_nn_simulate_nack_drop; + bool m_request_keyframe; + std::vector m_audio_tracks; + std::vector m_video_tracks; + YangRtcAudioRecvTrack* get_audio_track(uint32_t ssrc); + YangVideoRecvTrack* get_video_track(uint32_t ssrc); + +}; + +#endif /* YANGWEBRTC_YANGRTCPLAYSTREAM_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.cpp b/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a45bdb6c21d4ce2d6f201d5925475ac3dc60a68c --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.cpp @@ -0,0 +1,186 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include "YangRtcSdp.h" +YangRtcPublishStream::YangRtcPublishStream(YangRtcSessionI *s) { + m_session = s; + m_mw_msgs = 0; + m_realtime = true; + m_nack_enabled = false; + + m_audio_queue = NULL; + m_video_queue = NULL; + m_audioSsrc = 0; + m_videoSsrc = 0; + +} + +YangRtcPublishStream::~YangRtcPublishStream() { + yang_delete(m_audio_queue); + yang_delete(m_video_queue); +} + +int32_t YangRtcPublishStream::init(uint32_t audioSsrc, uint32_t videoSsrc) { + int32_t err = Yang_Ok; + if (m_audio_queue == NULL) + m_audio_queue = new YangPublishNackBuffer(100); + if (m_video_queue == NULL) + m_video_queue = new YangPublishNackBuffer(1000); + m_audioSsrc = audioSsrc; + m_videoSsrc = videoSsrc; + m_nack_enabled = true; + + return err; +} + +int32_t YangRtcPublishStream::cache_nack(YangRtpPacket *pkt,char* p,int plen) { + int32_t err = Yang_Ok; + uint16_t seq = pkt->m_header.sequence; + if (pkt->is_audio()) + m_audio_queue->set(seq, p,plen); + else + m_video_queue->set(seq, p,plen); + + return err; +} + +int32_t YangRtcPublishStream::on_rtcp(YangRtcpCommon *rtcp) { + yang_trace("\npublish rtcp size==%d,nb==%" PRId64,rtcp->size(),rtcp->nb_bytes()); + if (YangRtcpType_rr == rtcp->type()) { + YangRtcpRR *rr = dynamic_cast(rtcp); + return on_rtcp_rr(rr); + } else if (YangRtcpType_rtpfb == rtcp->type()) { + //currently rtpfb of nack will be handle by player. TWCC will be handled by YangRtcRtcpI + YangRtcpNack *nack = dynamic_cast(rtcp); + return on_rtcp_nack(nack); + } else if (YangRtcpType_psfb == rtcp->type()) { + YangRtcpPsfbCommon *psfb = dynamic_cast(rtcp); + return on_rtcp_ps_feedback(psfb); + } else if (YangRtcpType_xr == rtcp->type()) { + YangRtcpXr *xr = dynamic_cast(rtcp); + return on_rtcp_xr(xr); + } else if (YangRtcpType_bye == rtcp->type()) { + // TODO: FIXME: process rtcp bye. + return Yang_Ok; + } else { + return yang_error_wrap(ERROR_RTC_RTCP_CHECK, "unknown rtcp type=%u", + rtcp->type()); + } +} + +int32_t YangRtcPublishStream::on_rtcp_rr(YangRtcpRR *rtcp) { + int32_t err = Yang_Ok; + + // TODO: FIXME: Implements it. + + return err; +} + +int32_t YangRtcPublishStream::on_rtcp_xr(YangRtcpXr *rtcp) { + int32_t err = Yang_Ok; + + // TODO: FIXME: Implements it. + + return err; +} + +int32_t YangRtcPublishStream::on_rtcp_nack(YangRtcpNack *rtcp) { + int32_t err = Yang_Ok; + YangPublishNackBuffer *que = NULL; + uint32_t ssrc = rtcp->get_media_ssrc(); + vector seqs = rtcp->get_lost_sns(); + if (ssrc == m_audioSsrc) + que = m_audio_queue; + if (ssrc == m_videoSsrc) + que = m_video_queue; + yang_trace("\npublish find lost ssrc=%hu:",ssrc); + if (!ssrc) + return yang_error_wrap(err, "track response nack ssrc=%u", ssrc);; + if (que&&(err = on_recv_nack(que, seqs)) != Yang_Ok) { + return yang_error_wrap(err, "track response nack. ssrc=%u", ssrc); + } + return err; +} + +int32_t YangRtcPublishStream::on_recv_nack(YangPublishNackBuffer *que, + const vector &lost_seqs) { + int32_t err = Yang_Ok; + + for (int32_t i = 0; i < (int) lost_seqs.size(); ++i) { + uint16_t seq = lost_seqs.at(i); + YangPublishBuffer *pkt = fetch_rtp_packet(que, seq); + if (pkt == NULL) { + continue; + } + yang_trace("\nsendlostsn=%hu,",seq); + if ((err = m_session->send_nackpacket(pkt->payload,pkt->nb)) != Yang_Ok) { + return yang_error_wrap(err, "raw send"); + } + } + + return err; +} + +YangPublishBuffer* YangRtcPublishStream::fetch_rtp_packet(YangPublishNackBuffer *que, + uint16_t seq) { + YangPublishBuffer *pkt = que->at(seq); + + if (pkt == NULL) { + return pkt; + } + + // For NACK, it sequence must match exactly, or it cause SRTP fail. + // Return packet only when sequence is equal. + if (pkt->seq == seq) { + return pkt; + } + return NULL; +} +int32_t YangRtcPublishStream::on_rtcp_ps_feedback(YangRtcpPsfbCommon *rtcp) { + int32_t err = Yang_Ok; + + uint8_t fmt = rtcp->get_rc(); + switch (fmt) { + case kPLI: { + uint32_t ssrc = m_videoSsrc; //get_video_publish_ssrc(rtcp->get_media_ssrc()); + if (ssrc) { + do_request_keyframe(ssrc); + } + break; + } + case kSLI: { + yang_info("sli"); + break; + } + case kRPSI: { + yang_info("rpsi"); + break; + } + case kAFB: { + yang_info("afb"); + break; + } + default: { + return yang_error_wrap(ERROR_RTC_RTCP, + "unknown payload specific feedback=%u", fmt); + } + } + + return err; +} + + +int32_t YangRtcPublishStream::do_request_keyframe(uint32_t ssrc) { + int32_t err = Yang_Ok; + + m_session->do_request_keyframe(ssrc); + + return err; +} + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.h b/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.h new file mode 100644 index 0000000000000000000000000000000000000000..0e101126f8e37c77154c868f99b10a779ed5efa7 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcPublishStream.h @@ -0,0 +1,56 @@ +#ifndef YANGWEBRTC_YANGRTCPUBLISHSTREAM_H_ +#define YANGWEBRTC_YANGRTCPUBLISHSTREAM_H_ +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include + +class YangRtcPublishStream +{ +private: + YangRtcSessionI* m_session; +private: + uint32_t m_audioSsrc; + uint32_t m_videoSsrc; + + +private: + // For merged-write messages. + int32_t m_mw_msgs; + bool m_realtime; + // Whether enabled nack. + bool m_nack_enabled; + + YangPublishNackBuffer* m_audio_queue; + YangPublishNackBuffer* m_video_queue; + + +public: + YangRtcPublishStream(YangRtcSessionI* s); + virtual ~YangRtcPublishStream(); +public: + int32_t init(uint32_t audioSsrc,uint32_t videoSsrc); +public: + int32_t on_rtcp(YangRtcpCommon* rtcp); + int32_t on_recv_nack(YangPublishNackBuffer* que,const std::vector& lost_seqs); + int32_t cache_nack(YangRtpPacket* pkt,char* p,int plen); +private: + YangPublishBuffer* fetch_rtp_packet(YangPublishNackBuffer* que,uint16_t seq); + int32_t on_rtcp_xr(YangRtcpXr* rtcp); + int32_t on_rtcp_nack(YangRtcpNack* rtcp); + int32_t on_rtcp_ps_feedback(YangRtcpPsfbCommon* rtcp); + int32_t on_rtcp_rr(YangRtcpRR* rtcp); + +public: + int32_t do_request_keyframe(uint32_t ssrc); +}; +#endif /* YANGWEBRTC_YANGRTCPUBLISHSTREAM_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcSdp.cpp b/libyangrtc2/src/yangwebrtc/YangRtcSdp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc3b642e9605f7af4f6f9012f27a101f1d7b68b1 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcSdp.cpp @@ -0,0 +1,650 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +const std::string kCRLF = "\r\n"; + +#define FETCH(is,word) \ +if (!(is >> word)) {\ + return Yang_Fetch_Failed;\ +}\ + +#define FETCH_WITH_DELIM(is,word,delim) \ +if (!getline(is,word,delim)) {\ + return Yang_Fetch_Failed_WithDelim;\ +}\ + + + + + +int32_t srs_parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_param) +{ + int32_t err = Yang_Ok; + std::vector vec = yang_splits(fmtp, ";"); + for (size_t i = 0; i < vec.size(); ++i) { + std::vector kv = yang_splits(vec[i], "="); + if (kv.size() == 2) { + if (kv[0] == "profile-level-id") { + h264_param.profile_level_id = kv[1]; + } else if (kv[0] == "packetization-mode") { + // 6.3. Non-Interleaved Mode + // This mode is in use when the value of the OPTIONAL packetization-mode + // media type parameter is equal to 1. This mode SHOULD be supported. + // It is primarily intended for low-delay applications. Only single NAL + // unit packets, STAP-As, and FU-As MAY be used in this mode. STAP-Bs, + // MTAPs, and FU-Bs MUST NOT be used. The transmission order of NAL + // units MUST comply with the NAL unit decoding order. + // @see https://tools.ietf.org/html/rfc6184#section-6.3 + h264_param.packetization_mode = kv[1]; + } else if (kv[0] == "level-asymmetry-allowed") { + h264_param.level_asymmerty_allow = kv[1]; + } else { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid h264 param=%s", kv[0].c_str()); + } + } else { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid h264 param=%s", vec[i].c_str()); + } + } + + return err; +} + + + + +YangSdpHandle::YangSdpHandle() { + m_cer=NULL; +} + +YangSdpHandle::~YangSdpHandle() { + m_cer=NULL; +} +void YangSdpHandle::init(YangCertificateImpl* pcer){ + m_cer=pcer; +} +int32_t YangSdpHandle::genLocalSdp(int32_t localport,YangRtcContext* pconf, char *sdp,YangStreamOptType role) { + //char s[1024 * 10] = { 0 }; + /**FILE *f = NULL; + char file_path_getcwd[210]={0}; + getcwd(file_path_getcwd, 210); + char path[255]={0}; + + if(role==Yang_Stream_Play) + sprintf(path,"%s/lib/local_play.sdp",file_path_getcwd ); + else + sprintf(path,"%s/lib/local_publish.sdp",file_path_getcwd); + + f=fopen(path, "rb"); + + int32_t fileLen = fread(s, 1024 * 10, 1, f); + fclose(f); + f = NULL;**/ + + //printf("\n******************************gensdp localport==%d\n",localport); + string ss; + if(pconf->context->video.videoEncoderType==Yang_VED_264){ + ss=local_h264_sdp_str; + } +#if Yang_H265_Encoding + if(pconf->context->video.videoEncoderType==Yang_VED_265){ + ss=local_h265_sdp_str; + } +#endif + yang_replace(ss,"5hcuv2i7jtwg6bj1",yang_random_str(16)); + string msaid=yang_random_str(8)+"-"+yang_random_str(4)+"-"+yang_random_str(4)+"-"+yang_random_str(4)+"-"+yang_random_str(12); + yang_replace(ss,"79ac70ad-c572-4017-86a1-330d56089c70",msaid); + + yang_replace(ss,"144706935",to_string(pconf->audioSsrc)); + string msvid=yang_random_str(8)+"-"+yang_random_str(4)+"-"+yang_random_str(4)+"-"+yang_random_str(4)+"-"+yang_random_str(12); + yang_replace(ss,"549dbfe5-fd12-4c5f-9182-d513f6defce5",msvid); + yang_replace(ss,"144706936",to_string(pconf->videoSsrc)); + yang_replace(ss,"127.0.0.1 8000",pconf->streamConf->serverIp+" "+to_string(localport)); + if(pconf->context&&pconf->context->audio.audioEncoderType==Yang_AED_OPUS){ + char str1[64]={0}; + sprintf(str1,"opus/%d/%d",pconf->context->audio.sample,pconf->context->audio.channel); + yang_replace(ss,"opus/48000/2",str1); + } + if(role==Yang_Stream_Play) + yang_replace(ss,"a=sendonly\n","a=recvonly\n"); + + + //,sample_sdp; + pconf->local_sdp->parse(ss); + //local_sdp.parse(s); + + pconf->local_sdp->set_ice_ufrag(yang_random_str(4)); + pconf->local_sdp->set_ice_pwd(yang_random_str(32)); + pconf->local_sdp->set_fingerprint_algo("sha-256"); + pconf->local_sdp->set_fingerprint(m_cer->get_fingerprint()); + pconf->local_sdp->m_session_negotiate = pconf->local_sdp->m_session_config; + pconf->local_sdp->m_session_negotiate.m_dtls_role = "actpass"; //"passive","active"; + pconf->local_sdp->set_dtls_role(pconf->local_sdp->m_session_negotiate.m_dtls_role); + + + generate_local_sdp(pconf, 1, role); + stringstream os; + int32_t err = 0; + if ((err = pconf->local_sdp->encode(os)) != Yang_Ok) { + printf("\nencode sdp error==%d", err); + return 1; + } + + std::string local_sdp_str = os.str(); + // Filter the \r\n to \\r\\n for JSON. + //local_sdp_str = srs_string_replace(local_sdp_str.c_str(), "\r\n", "\\r\\n"); + yang_replace(local_sdp_str,"\r\n", "\\r\\n"); + memcpy(sdp, local_sdp_str.c_str(), local_sdp_str.length()); + + return Yang_Ok; + +} + + +int32_t YangSdpHandle::generate_local_sdp(YangRtcContext* pconf, bool unified_plan, int32_t role) { + int32_t err = Yang_Ok; + + pconf->local_sdp->m_version = "0"; + + pconf->local_sdp->m_username = "YangRtc"; + pconf->local_sdp->m_session_id = yang_int2str(((int64_t) this)); + pconf->local_sdp->m_session_version = "2"; + pconf->local_sdp->m_nettype = "IN"; + pconf->local_sdp->m_addrtype = "IP4"; + pconf->local_sdp->m_unicast_address = "0.0.0.0"; + + + pconf->local_sdp->m_session_name = "YangRtcSession"; + + pconf->local_sdp->m_msid_semantic = "WMS"; + std::string stream_id = pconf->streamConf->app + "/" + pconf->streamConf->stream; + pconf->local_sdp->m_msids.push_back(stream_id); + + pconf->local_sdp->m_group_policy = "BUNDLE"; + + //std::string cname = srs_random_str(16); + YangMediaDesc *audio_media_desc = pconf->local_sdp->find_media_descs("audio");//new SrsMediaDesc("audio");// + audio_media_desc->m_port = 9; + audio_media_desc->m_protos = "UDP/TLS/RTP/SAVPF"; + audio_media_desc->m_rtcp_mux = true; + audio_media_desc->m_rtcp_rsize = true; + std::vector payloads =audio_media_desc->find_media_with_encoding_name("opus"); + + YangMediaDesc *video_media_desc =pconf->local_sdp->find_media_descs("video"); //SrsMediaDesc("video"); + video_media_desc->m_port = 9; + video_media_desc->m_protos = "UDP/TLS/RTP/SAVPF"; + video_media_desc->m_rtcp_mux = true; + video_media_desc->m_rtcp_rsize = true; + + //sendrecv + if (role==0) { + audio_media_desc->m_recvonly = true; + video_media_desc->m_recvonly = true; + } else if(role==1) { + audio_media_desc->m_sendonly = true; + video_media_desc->m_sendonly = true; + }else if(role==2){ + audio_media_desc->m_sendrecv=true; + video_media_desc->m_sendrecv = true; + } + + + + + + return err; +} + + +YangSdp::YangSdp() +{ + m_in_media_session = false; + + m_start_time = 0; + m_end_time = 0; +} + +YangSdp::~YangSdp() +{ +} + +int32_t YangSdp::parse(const std::string& sdp_str) +{ + int32_t err = Yang_Ok; + //printf("\nsdp===%s\n",sdp_str.c_str()); + // All webrtc SrsSdp annotated example + // @see: https://tools.ietf.org/html/draft-ietf-rtcweb-SrsSdp-11 + // Sdp example + // session info + // v= + // o= + // s= + // t= + // media description + // m= + // a= + // ... + // media description + // m= + // a= + // ... + std::istringstream is(sdp_str); + std::string line; + while (getline(is, line)) { + //yang_trace("%s", line.c_str()); + if (line.size() < 2 || line[1] != '=') { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid sdp line=%s", line.c_str()); + } + if (!line.empty() && line[line.size()-1] == '\r') { + line.erase(line.size()-1, 1); + } + + if ((err = parse_line(line)) != Yang_Ok) { + return printf("parse sdp line failed"); + } + } + + // The msid/tracker/mslabel is optional for SSRC, so we copy it when it's empty. + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc& media_desc = *iter; + + for (size_t i = 0; i < media_desc.m_ssrc_infos.size(); ++i) { + YangSSRCInfo& ssrc_info = media_desc.m_ssrc_infos.at(i); + + if (ssrc_info.m_msid.empty()) { + ssrc_info.m_msid = media_desc.m_msid; + } + + if (ssrc_info.m_msid_tracker.empty()) { + ssrc_info.m_msid_tracker = media_desc.m_msid_tracker; + } + + if (ssrc_info.m_mslabel.empty()) { + ssrc_info.m_mslabel = media_desc.m_msid; + } + + if (ssrc_info.m_label.empty()) { + ssrc_info.m_label = media_desc.m_msid_tracker; + } + } + } + + return err; +} + +int32_t YangSdp::encode(std::stringstream& os) +{ + int32_t err = Yang_Ok; + + os << "v=" << m_version << kCRLF; + os << "o=" << m_username << " " << m_session_id << " " << m_session_version << " " << m_nettype << " " << m_addrtype << " " << m_unicast_address << kCRLF; + os << "s=" << m_session_name << kCRLF; + os << "t=" << m_start_time << " " << m_end_time << kCRLF; + // ice-lite is a minimal version of the ICE specification, intended for servers running on a public IP address. + os << "a=ice-lite" << kCRLF; + + if (!m_groups.empty()) { + os << "a=group:" << m_group_policy; + for (std::vector::iterator iter = m_groups.begin(); iter != m_groups.end(); ++iter) { + os << " " << *iter; + } + os << kCRLF; + } + + os << "a=msid-semantic: " << m_msid_semantic; + for (std::vector::iterator iter = m_msids.begin(); iter != m_msids.end(); ++iter) { + os << " " << *iter; + } + os << kCRLF; + + if ((err = m_session_info.encode(os)) != Yang_Ok) { + return printf("encode session info failed"); + } + + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + if ((err = (*iter).encode(os)) != Yang_Ok) { + return printf("encode media description failed"); + } + } + + return err; +} + +YangMediaDesc* YangSdp::find_media_descs(const std::string& type) +{ + // std::vector descs; + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + + if (desc->m_type == type) { + return desc;//descs.push_back(desc); + } + } + + return NULL; +} + +void YangSdp::set_ice_ufrag(const std::string& ufrag) +{ + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_session_info.m_ice_ufrag = ufrag; + } +} + +void YangSdp::set_ice_pwd(const std::string& pwd) +{ + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_session_info.m_ice_pwd = pwd; + } +} + +void YangSdp::set_dtls_role(const std::string& dtls_role) +{ + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_session_info.m_setup = dtls_role; + } +} + +void YangSdp::set_fingerprint_algo(const std::string& algo) +{ + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_session_info.m_fingerprint_algo = algo; + } +} + +void YangSdp::set_fingerprint(const std::string& fingerprint) +{ + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_session_info.m_fingerprint = fingerprint; + } +} + +void YangSdp::add_candidate(const std::string& ip, const int& port, const std::string& type) +{ + // @see: https://tools.ietf.org/id/draft-ietf-mmusic-ice-sip-sdp-14.html#rfc.section.5.1 + YangCandidate candidate; + candidate.ip_ = ip; + candidate.port_ = port; + candidate.type_ = type; + + for (std::vector::iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + YangMediaDesc* desc = &(*iter); + desc->m_candidates.push_back(candidate); + } +} + +std::string YangSdp::get_ice_ufrag() const +{ + // Becaues we use BUNDLE, so we can choose the first element. + for (std::vector::const_iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + const YangMediaDesc* desc = &(*iter); + return desc->m_session_info.m_ice_ufrag; + } + + return ""; +} + +std::string YangSdp::get_ice_pwd() const +{ + // Becaues we use BUNDLE, so we can choose the first element. + for (std::vector::const_iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + const YangMediaDesc* desc = &(*iter); + return desc->m_session_info.m_ice_pwd; + } + + return ""; +} + +std::string YangSdp::get_dtls_role() const +{ + // Becaues we use BUNDLE, so we can choose the first element. + for (std::vector::const_iterator iter = m_media_descs.begin(); iter != m_media_descs.end(); ++iter) { + const YangMediaDesc* desc = &(*iter); + return desc->m_session_info.m_setup; + } + + return ""; +} + +int32_t YangSdp::parse_line(const std::string& line) +{ + int32_t err = Yang_Ok; + + std::string content = line.substr(2); + + switch (line[0]) { + case 'o': { + return parse_origin(content); + } + case 'v': { + return parse_version(content); + } + case 's': { + return parse_session_name(content); + } + case 't': { + return parse_timing(content); + } + case 'a': { + if (m_in_media_session) { + return m_media_descs.back().parse_line(line); + } + return parse_attribute(content); + } + case 'm': { + return parse_media_description(content); + } + case 'c': { + + break; + } + default: { + yang_trace("ignore sdp line=%s", line.c_str()); + break; + } + } + + return err; +} + +int32_t YangSdp::parse_origin(const std::string& content) +{ + int32_t err = Yang_Ok; + + // @see: https://tools.ietf.org/html/rfc4566#section-5.2 + // o= + // eg. o=- 9164462281920464688 2 IN IP4 127.0.0.1 + std::istringstream is(content); + + FETCH(is, m_username); + FETCH(is, m_session_id); + FETCH(is, m_session_version); + FETCH(is, m_nettype); + FETCH(is, m_addrtype); + FETCH(is, m_unicast_address); + + return err; +} + +int32_t YangSdp::parse_version(const std::string& content) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#section-5.1 + + std::istringstream is(content); + + FETCH(is, m_version); + + return err; +} + +int32_t YangSdp::parse_session_name(const std::string& content) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#section-5.3 + // s= + + m_session_name = content; + + return err; +} + +int32_t YangSdp::parse_timing(const std::string& content) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#section-5.9 + // t= + + std::istringstream is(content); + + FETCH(is, m_start_time); + FETCH(is, m_end_time); + + return err; +} + +int32_t YangSdp::parse_attribute(const std::string& content) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc4566#section-5.13 + // a= + // a=: + + std::string attribute = ""; + std::string value = ""; + size_t pos = content.find_first_of(":"); + + if (pos != std::string::npos) { + attribute = content.substr(0, pos); + value = content.substr(pos + 1); + } + + if (attribute == "group") { + return parse_attr_group(value); + } else if (attribute == "msid-semantic") { + std::istringstream is(value); + FETCH(is, m_msid_semantic); + + std::string msid; + while (is >> msid) { + m_msids.push_back(msid); + } + } else { + return m_session_info.parse_attribute(attribute, value); + } + + return err; +} + +int32_t YangSdp::parse_attr_group(const std::string& value) +{ + int32_t err = Yang_Ok; + // @see: https://tools.ietf.org/html/rfc5888#section-5 + + std::istringstream is(value); + + FETCH(is, m_group_policy); + + std::string word; + while (is >> word) { + m_groups.push_back(word); + } + + return err; +} + +int32_t YangSdp::parse_media_description(const std::string& content) +{ + int32_t err = Yang_Ok; + + // @see: https://tools.ietf.org/html/rfc4566#section-5.14 + // m= ... + // m= / ... + std::istringstream is(content); + + std::string media; + FETCH(is, media); + + int32_t port; + FETCH(is, port); + + std::string proto; + FETCH(is, proto); + + m_media_descs.push_back(YangMediaDesc(media)); + m_media_descs.back().m_protos = proto; + m_media_descs.back().m_port = port; + + int32_t fmt; + while (is >> fmt) { + m_media_descs.back().m_payload_types.push_back(YangMediaPayloadType(fmt)); + } + + if (!m_in_media_session) { + m_in_media_session = true; + } + + return err; +} + +bool YangSdp::is_unified() const +{ + // TODO: FIXME: Maybe we should consider other situations. + return m_media_descs.size() > 2; +} + +int32_t YangSdp::update_msid(string id) +{ + int32_t err = Yang_Ok; + + m_msids.clear(); + m_msids.push_back(id); + + for (vector::iterator it = m_media_descs.begin(); it != m_media_descs.end(); ++it) { + YangMediaDesc& desc = *it; + + if ((err = desc.update_msid(id)) != Yang_Ok) { + printf("desc %s update msid %s", desc.m_mid.c_str(), id.c_str()); + return err; + } + } + + return err; +} + + + + + + + + + + + + + + + + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcSdp.h b/libyangrtc2/src/yangwebrtc/YangRtcSdp.h new file mode 100644 index 0000000000000000000000000000000000000000..8a99cabd3bbebf48349ae4ff2dd22f219fc36d38 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcSdp.h @@ -0,0 +1,118 @@ +#ifndef YangSdp_H__ +#define YangSdp_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +const std::string kTWCCExt = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"; + +class YangSessionConfig +{ +public: + std::string m_dtls_role; + std::string m_dtls_version; +}; + + + +struct H264SpecificParam +{ + std::string profile_level_id; + std::string packetization_mode; + std::string level_asymmerty_allow; +}; + +class YangSdp +{ +public: + YangSdp(); + virtual ~YangSdp(); +public: + int32_t parse(const std::string& sdp_str); + int32_t encode(std::stringstream& os); +public: + YangMediaDesc* find_media_descs(const std::string& type); +public: + void set_ice_ufrag(const std::string& ufrag); + void set_ice_pwd(const std::string& pwd); + void set_dtls_role(const std::string& dtls_role); + void set_fingerprint_algo(const std::string& algo); + void set_fingerprint(const std::string& fingerprint); + void add_candidate(const std::string& ip, const int& port, const std::string& type); + + std::string get_ice_ufrag() const; + std::string get_ice_pwd() const; + std::string get_dtls_role() const; + +private: + int32_t parse_line(const std::string& line); +private: + int32_t parse_origin(const std::string& content); + int32_t parse_version(const std::string& content); + int32_t parse_session_name(const std::string& content); + int32_t parse_timing(const std::string& content); + int32_t parse_attribute(const std::string& content); + int32_t parse_media_description(const std::string& content); + int32_t parse_attr_group(const std::string& content); +private: + bool m_in_media_session; +public: + // version + std::string m_version; + + // origin + std::string m_username; + std::string m_session_id; + std::string m_session_version; + std::string m_nettype; + std::string m_addrtype; + std::string m_unicast_address; + + // session_name + std::string m_session_name; + + // timing + int64_t m_start_time; + int64_t m_end_time; + + YangSessionInfo m_session_info; + YangSessionConfig m_session_config; + YangSessionConfig m_session_negotiate; + + std::vector m_groups; + std::string m_group_policy; + + std::string m_msid_semantic; + std::vector m_msids; + + // m-line, media sessions + std::vector m_media_descs; + + bool is_unified() const; + // TODO: FIXME: will be fixed when use single pc. + int32_t update_msid(std::string id); +}; + + + + +class YangSdpHandle { +public: + YangSdpHandle(); + virtual ~YangSdpHandle(); + //role0: play 1:publish 2:play&publish + int32_t genLocalSdp(int32_t localport,YangRtcContext* conf, char *sdp,YangStreamOptType role); + void init(YangCertificateImpl* pcer); + +private: + YangCertificateImpl* m_cer; + int32_t generate_local_sdp(YangRtcContext* pconf, bool unified_plan,int32_t role); + int32_t generate_publish_local_sdp(YangStreamConfig* req, YangSdp& local_sdp, bool unified_plan); +}; +#endif diff --git a/libyangrtc2/src/yangwebrtc/YangRtcSession.cpp b/libyangrtc2/src/yangwebrtc/YangRtcSession.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42aac5356f5d9c747e03b235c89225702d3df380 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcSession.cpp @@ -0,0 +1,552 @@ +#include +#include + + +#include +#include + +#include +#include +#include + +#include +/** +bool yang_is_rtp_or_rtcp(const uint8_t *data, size_t len) { + return (len >= 12 && (data[0] & 0xC0) == 0x80); +} +// For STUN packet, 0x00 is binding request, 0x01 is binding success response. + + +// For RTCP, PT is [128, 223] (or without marker [0, 95]). +// Literally, RTCP starts from 64 not 0, so PT is [192, 223] (or without marker [64, 95]). +// @note For RTP, the PT is [96, 127], or [224, 255] with marker. +bool yang_is_rtcp(const uint8_t *data, size_t len) { + return (len >= 12) && (data[0] & 0x80) && (data[1] >= 192 && data[1] <= 223); +} +**/ +bool yang_is_stun(const uint8_t *data, size_t size) { + return size > 0 && (data[0] == 0 || data[0] == 1); +} +// change_cipher_spec(20), alert(21), handshake(22), application_data(23) +// @see https://tools.ietf.org/html/rfc2246#section-6.2.1 +bool yang_is_dtls(const uint8_t *data, size_t len) { + return (len >= 13 && (data[0] > 19 && data[0] < 64)); +} + +YangRtcSession::YangRtcSession(YangRtcContext* pconf) { + m_context=pconf; + m_dtls = NULL; + m_srtp = NULL; + + m_codec=(YangVideoEncDecType)m_context->context->video.videoEncoderType; + isSendDtls = 0; + twcc_id_ = 1; + //nack_enabled_ = 0; + m_play = NULL; + m_publish = NULL; + m_h264Encoder=NULL; + + if(m_codec==Yang_VED_264){ + m_h264Encoder=new YangH264RtpEncode(); + } +#if Yang_H265_Encoding + m_h265Encoder=NULL; + if(m_codec==Yang_VED_265){ + m_h265Encoder=new YangH265RtpEncode(); + } +#endif + // m_20ms = new YangTimer(); + // m_20ms->setTaskId(20); + // m_20ms->setTimelen(20); + // m_20ms->setTask(this); + + m_1s = new YangTimer(); + m_1s->setTaskId(1); + m_1s->setTask(this); + m_1s->setTimelen(1000); + + m_100ms = new YangTimer(); + m_100ms->setTaskId(100); + m_100ms->setTimelen(100); + m_100ms->setTask(this); + + m_udp = NULL; + m_startRecv = 0; + + m_stunBuffer = new char[1024]; + m_stunBufferLen = 0; + + m_isSendStun = 0; + + m_rtpBuffer=NULL; + m_activeState=true; +} + +YangRtcSession::~YangRtcSession() { + m_activeState=false; + //yang_stop(m_20ms); + yang_stop(m_1s); + yang_stop(m_100ms); + + // yang_delete(m_20ms); + yang_delete(m_1s); + yang_delete(m_100ms); + + yang_delete(m_publish); + yang_delete(m_play); + yang_delete(m_dtls); + + yang_deleteA(m_stunBuffer); + yang_delete(m_rtpBuffer); + yang_delete(m_h264Encoder); +#if Yang_H265_Encoding + yang_delete(m_h265Encoder); +#endif + m_udp = NULL; + m_srtp = NULL; + m_context=NULL; + + +} + +void YangRtcSession::setSsrc(uint32_t audioSsrc,uint32_t videoSsrc){ + if(m_h264Encoder){ + m_h264Encoder->m_audioSsrc=audioSsrc; + m_h264Encoder->m_videoSsrc=videoSsrc; + } +#if Yang_H265_Encoding + if(m_h265Encoder){ + m_h265Encoder->m_audioSsrc=audioSsrc; + m_h265Encoder->m_videoSsrc=videoSsrc; + } +#endif + +} + +int32_t YangRtcSession::init(YangSendUdpData *pudp, YangReceiveCallback *cbk, YangStreamOptType role) { + m_udp = pudp; + + + if (m_dtls == NULL) { + m_dtls = new YangRtcDtls(m_context->context); + m_dtls->init(pudp); + + } + m_srtp = m_dtls->getSrtp(); + if(m_rtpBuffer==NULL) m_rtpBuffer=new YangRtpBuffer(1500); + if(role==Yang_Stream_Publish){ + if(m_h264Encoder){ + m_h264Encoder->init(m_rtpBuffer,this); + } +#if Yang_H265_Encoding + if(m_h265Encoder){ + m_h265Encoder->init(m_rtpBuffer,this); + } +#endif + } + if (role == Yang_Stream_Play) { + if (m_play == NULL){ + m_play = new YangRtcPlayStream(this); + m_play->initialize(m_context,m_context->source, cbk,m_rtpBuffer); + + //m_play->m_twcc_enabled + } + } else { + if (m_publish == NULL){ + m_publish = new YangRtcPublishStream(this); + m_publish->init(m_context->audioSsrc,m_context->videoSsrc); + } + } + return Yang_Ok; +} +void YangRtcSession::startStunTimer() { + if (m_1s) + m_1s->start(); + m_isSendStun = 1; +} +void YangRtcSession::startTimers() { + // if (m_20ms&&!m_20ms->m_isStart) m_20ms->start(); + if (m_context->context&&m_context->context->rtc.sendTwcc&&m_100ms&&!m_100ms->m_isStart) m_100ms->start(); +} +void YangRtcSession::setStunBuffer(char *p, int32_t plen) { + memcpy(m_stunBuffer, p, plen); + m_stunBufferLen = plen; +} +int32_t YangRtcSession::on_rtcp(char *data, int32_t nb_data) { + int32_t err = Yang_Ok; + + int32_t nb_unprotected_buf = nb_data; + if ((err = m_srtp->dec_rtcp(data, &nb_unprotected_buf)) != Yang_Ok) { + return yang_error_wrap(err, "rtcp unprotect"); + } + + char *unprotected_buf = data; + YangBuffer *buffer = new YangBuffer(unprotected_buf, nb_unprotected_buf); + YangAutoFree(YangBuffer, buffer); + + YangRtcpCompound rtcp_compound; + if (Yang_Ok != (err = rtcp_compound.decode(buffer))) { + return yang_error_wrap(err, "decode rtcp plaintext=%u", + nb_unprotected_buf); + } + + YangRtcpCommon *rtcp = NULL; + while (NULL != (rtcp = rtcp_compound.get_next_rtcp())) { + err = dispatch_rtcp(rtcp); + YangAutoFree(YangRtcpCommon, rtcp); + + if (Yang_Ok != err) { + return yang_error_wrap(err, + "cipher=%u, plaintext=%u, rtcp=(%u,%u,%u,%u)", nb_data, + nb_unprotected_buf, rtcp->size(), rtcp->get_rc(), + rtcp->type(), rtcp->get_ssrc(), rtcp->size()); + } + } + + return err; + +} + +void YangRtcSession::receive(char *data, int32_t size) { + + if(!m_activeState) return; + bool is_rtp_or_rtcp = (size >= 12 && (data[0] & 0xC0) == 0x80); + bool is_rtcp = (size >= 12) && (data[0] & 0x80) && (data[1] >= 192 && data[1] <= 223); + + + if (is_rtp_or_rtcp&&!is_rtcp) { + m_startRecv = 1; + if (m_play) m_play->on_rtp(data, size); + return; + + } + if (is_rtp_or_rtcp && is_rtcp) { + on_rtcp(data, size); + return; + } + + if (!is_rtp_or_rtcp && yang_is_stun((uint8_t*)data,size)) { + + YangStunPacket ping; + int32_t err = 0; + if ((err = ping.decode(data, size)) != Yang_Ok) { + yang_error("decode stun packet failed"); + return; + } + + if (!isSendDtls) { + if (m_dtls->startHandShake()) { + yang_error("dtls start handshake failed!"); + } + + isSendDtls = 1; + } + return; + } + if (size >= 13 && yang_is_dtls((uint8_t*)data,size)) { + + if (m_dtls) { + if (m_dtls->decodeHandshake(data, size) == Yang_Ok) { + + if(m_dtls->getDtlsState()==YangDtlsStateClientDone) { + startTimers(); + m_context->state=1; + + if(m_context&&m_context->context) + m_context->context->streams.sendRequest(m_context->streamConf->uid,0,Yang_Req_Connected); + } + } + } + + } +} + + +int32_t YangRtcSession::send_video_meta(YangStreamCapture* p) +{ + + if(m_h264Encoder) return m_h264Encoder->package_stap_a(p); +#if Yang_H265_Encoding + if(m_h265Encoder) return m_h265Encoder->package_stap_a(p); +#endif + return Yang_Ok; +} + +int32_t YangRtcSession::publishVideo(YangStreamCapture* p) { + + if(p->getVideoFrametype()==YANG_Frametype_Spspps) return send_video_meta(p); + if(m_h264Encoder) return m_h264Encoder->on_h264_video(p); +#if Yang_H265_Encoding + if(m_h265Encoder) return m_h265Encoder->on_h265_video(p); +#endif + return Yang_Ok; + +} + +int32_t YangRtcSession::publishAudio(YangStreamCapture *p) { + + if(m_h264Encoder) return m_h264Encoder->on_audio(p); +#if Yang_H265_Encoding + if(m_h265Encoder) return m_h265Encoder->on_audio(p); +#endif + //return m_h264Encoder.on_audio(p); + return Yang_Ok; + +} + +void YangRtcSession::disconnect() { + if(m_dtls) m_dtls->sendDtlsAlert(); +} + +YangSRtp* YangRtcSession::get_srtp() { + return m_dtls->getSrtp(); +} + +void YangRtcSession::doTask(int32_t taskId) { + if (m_isSendStun && taskId == 1) { + if (m_udp && m_stunBuffer && m_stunBufferLen > 0){ + m_udp->sendData(m_stunBuffer, m_stunBufferLen); + } + + } + if (!m_startRecv) + return; + if (m_play) { + //int32_t err=0; + // if (taskId == 20) { + // m_play->check_send_nacks(); + //} + if (taskId == 1) { + + if (m_play->send_rtcp_rr()) + yang_error("RTCP Error:RR err "); + if (m_play->send_rtcp_xr_rrtr()) + yang_error("RTCP Error:XR err "); + } + if (taskId == 100) { + if (m_play->send_periodic_twcc()) + yang_error("RTCP Error:send twcc err "); + //if(m_play->request_keyframe(this->m_videoSsrc)) yang_error("RTCP Error:request keyframe err "); + } + } +} + +int32_t YangRtcSession::send_rtcp(char *data, int32_t nb_data) { + int32_t err = Yang_Ok; + int32_t nb_buf = nb_data; + if ((err = m_srtp->enc_rtcp(data, &nb_buf)) != Yang_Ok) { + return yang_error_wrap(err, "protect rtcp"); + } + + if ((err = m_udp->sendData(data, nb_buf)) != Yang_Ok) { + return yang_error_wrap(err, "send"); + } + + return err; +} +int32_t YangRtcSession::send_avpacket(YangRtpPacket *pkt,YangBuffer* pbuf) { + int32_t err = Yang_Ok; + int32_t nn_encrypt = pbuf->pos(); + if(m_publish) m_publish->cache_nack(pkt,pbuf->data(),nn_encrypt); + if ((err = m_srtp->enc_rtp(pbuf->data(), &nn_encrypt)) != Yang_Ok) { + return yang_error_wrap(err, "srtp protect"); + } + + return m_udp->sendData(pbuf->data(), nn_encrypt); +} + +int32_t YangRtcSession::send_nackpacket(char* data,int32_t nb){ + int32_t err = Yang_Ok; + int32_t nn_encrypt = nb; + + if ((err = m_srtp->enc_rtp(data, &nn_encrypt)) != Yang_Ok) { + return yang_error_wrap(err, "srtp protect"); + } + return m_udp->sendData(data, nb); +} +int32_t YangRtcSession::send_rtcp_fb_pli(uint32_t ssrc) { + int32_t err = Yang_Ok; + char buf[kRtpPacketSize]; + YangBuffer stream(buf, sizeof(buf)); + stream.write_1bytes(0x81); + stream.write_1bytes(kPsFb); + stream.write_2bytes(2); + stream.write_4bytes(ssrc); + stream.write_4bytes(ssrc); + + int32_t nb_protected_buf = stream.pos(); + if ((err = m_srtp->enc_rtcp(stream.data(), &nb_protected_buf)) + != Yang_Ok) { + return yang_error_wrap(err, "protect rtcp psfb pli"); + } + + return m_udp->sendData(stream.data(), nb_protected_buf); +} + +int32_t YangRtcSession::check_send_nacks(YangRtpNackForReceiver *nack, uint32_t ssrc, + uint32_t &sent_nacks, uint32_t &timeout_nacks) { + + YangRtcpNack rtcpNack(ssrc); + rtcpNack.set_media_ssrc(ssrc); + nack->get_nack_seqs(rtcpNack, timeout_nacks); + + if (rtcpNack.empty()) { + return Yang_Ok; + } + + char buf[kRtcpPacketSize]; + YangBuffer stream(buf, sizeof(buf)); + + + rtcpNack.encode(&stream); + int32_t nb_protected_buf = stream.pos(); + m_srtp->enc_rtcp(stream.data(), &nb_protected_buf); + m_udp->sendData(stream.data(), nb_protected_buf); + + return Yang_Ok; +} +int32_t YangRtcSession::dispatch_rtcp(YangRtcpCommon *rtcp) { + int32_t err = Yang_Ok; + + // For TWCC packet. + if (YangRtcpType_rtpfb == rtcp->type() && 15 == rtcp->get_rc()) { + return on_rtcp_feedback_twcc(rtcp->data(), rtcp->size()); + } + + // For REMB packet. + if (YangRtcpType_psfb == rtcp->type()) { + YangRtcpPsfbCommon *psfb = dynamic_cast(rtcp); + if (15 == psfb->get_rc()) { + return on_rtcp_feedback_remb(psfb); + } + } + + // Ignore special packet. + if (YangRtcpType_rr == rtcp->type()) { + YangRtcpRR *rr = dynamic_cast(rtcp); + if (rr->get_rb_ssrc() == 0) { //for native client + return err; + } + } + + + if (m_publish && Yang_Ok != (err = m_publish->on_rtcp(rtcp))) { + return yang_error_wrap(err, "handle rtcp"); + } + if (m_play && Yang_Ok != (err = m_play->on_rtcp(rtcp))) { + return yang_error_wrap(err, "handle rtcp"); + } + + return err; +} + +int32_t YangRtcSession::on_rtcp_feedback_twcc(char *data, int32_t nb_data) { + return Yang_Ok; +} + +int32_t YangRtcSession::on_rtcp_feedback_remb(YangRtcpPsfbCommon *rtcp) { + //ignore REMB + return Yang_Ok; +} +void YangRtcSession::do_request_keyframe(uint32_t ssrc){ + if(m_context&&m_context->context) + m_context->context->streams.sendRequest(m_context->streamConf->uid,ssrc,Yang_Req_Sendkeyframe); + +} +int32_t YangRtcSession::send_rtcp_rr(uint32_t ssrc, YangRtpPlayNackBuffer *rtp_queue, + const uint64_t &last_send_systime, const YangNtp &last_send_ntp) { + int32_t err = Yang_Ok; + // @see https://tools.ietf.org/html/rfc3550#section-6.4.2 + char buf[kRtpPacketSize]; + YangBuffer stream(buf, sizeof(buf)); + stream.write_1bytes(0x81); + stream.write_1bytes(kRR); + stream.write_2bytes(7); + stream.write_4bytes(ssrc); // TODO: FIXME: Should be 1? + + uint8_t fraction_lost = 0; + uint32_t cumulative_number_of_packets_lost = 0 & 0x7FFFFF; + uint32_t extended_highest_sequence = + rtp_queue->get_extended_highest_sequence(); + uint32_t interarrival_jitter = 0; + + uint32_t rr_lsr = 0; + uint32_t rr_dlsr = 0; + + if (last_send_systime > 0) { + rr_lsr = (last_send_ntp.m_ntp_second << 16) + | (last_send_ntp.m_ntp_fractions >> 16); + uint32_t dlsr = (yang_update_system_time() - last_send_systime) / 1000; + rr_dlsr = ((dlsr / 1000) << 16) | ((dlsr % 1000) * 65536 / 1000); + } + + stream.write_4bytes(ssrc); + stream.write_1bytes(fraction_lost); + stream.write_3bytes(cumulative_number_of_packets_lost); + stream.write_4bytes(extended_highest_sequence); + stream.write_4bytes(interarrival_jitter); + stream.write_4bytes(rr_lsr); + stream.write_4bytes(rr_dlsr); + + + int32_t nb_protected_buf = stream.pos(); + if ((err = m_srtp->enc_rtcp(stream.data(), &nb_protected_buf)) + != Yang_Ok) { + return yang_error_wrap(err, "protect rtcp rr"); + } + + return m_udp->sendData(stream.data(), nb_protected_buf); +} + +int32_t YangRtcSession::send_rtcp_xr_rrtr(uint32_t ssrc) { + int32_t err = Yang_Ok; + + /* + @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|reserved | PT=XR=207 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : report blocks : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-4.4 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | BT=4 | reserved | block length = 2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NTP timestamp, most significant word | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NTP timestamp, least significant word | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + int64_t now = yang_update_system_time(); + YangNtp cur_ntp = YangNtp::from_time_ms(now / 1000); + + char buf[kRtpPacketSize]; + YangBuffer stream(buf, sizeof(buf)); + stream.write_1bytes(0x80); + stream.write_1bytes(kXR); + stream.write_2bytes(4); + stream.write_4bytes(ssrc); + stream.write_1bytes(4); + stream.write_1bytes(0); + stream.write_2bytes(2); + stream.write_4bytes(cur_ntp.m_ntp_second); + stream.write_4bytes(cur_ntp.m_ntp_fractions); + + int32_t nb_protected_buf = stream.pos(); + if ((err = m_srtp->enc_rtcp(stream.data(), &nb_protected_buf)) + != Yang_Ok) { + return yang_error_wrap(err, "protect rtcp xr"); + } + + return m_udp->sendData(stream.data(), nb_protected_buf); +} + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcSession.h b/libyangrtc2/src/yangwebrtc/YangRtcSession.h new file mode 100644 index 0000000000000000000000000000000000000000..3d456547f08259c9c77ff7aab685547b474264ff --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcSession.h @@ -0,0 +1,100 @@ + + + + + + +#ifndef YANGWEBRTC_YANGRTCSESSION_H_ +#define YANGWEBRTC_YANGRTCSESSION_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "YangRtcSdp.h" +#include "YangRtcPlayStream.h" + +#include "YangRtcPublishStream.h" +class YangRtcSession :public YangTimerTask,public YangRtcSessionI{ +public: + YangRtcSession(YangRtcContext* pconf); + virtual ~YangRtcSession(); + + int32_t init(YangSendUdpData *pudp,YangReceiveCallback *cbk,YangStreamOptType role); + void receive(char *data, int32_t nb_data); + int32_t on_rtcp(char *data, int32_t nb_data); + void startStunTimer(); + void setStunBuffer(char* p,int32_t plen); + + + int32_t send_nackpacket(char* data,int32_t nb); + int32_t check_send_nacks(YangRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks, uint32_t& timeout_nacks); + int32_t send_rtcp_rr(uint32_t ssrc, YangRtpPlayNackBuffer* rtp_queue, const uint64_t& last_send_systime, const YangNtp& last_send_ntp); + int32_t send_rtcp_xr_rrtr(uint32_t ssrc); + int32_t send_rtcp(char *data, int32_t nb_data); + int32_t send_rtcp_fb_pli(uint32_t ssrc); + void do_request_keyframe(uint32_t ssrc); + YangSRtp* get_srtp(); + void doTask(int32_t taskId); + + int32_t publishVideo(YangStreamCapture* videoFrame); + int32_t publishAudio(YangStreamCapture* audioFrame); + + void disconnect(); + int32_t send_video_meta(YangStreamCapture* videoFrame); + void setSsrc(uint32_t audioSsrc,uint32_t videoSsrc); +public: + + YangRtcPlayStream* m_play; + YangRtcPublishStream* m_publish; + + +private: + YangRtcDtls *m_dtls; + YangSRtp* m_srtp; + YangSendUdpData *m_udp; + YangRtcContext *m_context; + + YangRtpBuffer* m_rtpBuffer; + //YangTimer* m_20ms; + YangTimer* m_1s; + YangTimer* m_100ms; + YangH264RtpEncode *m_h264Encoder; +#if Yang_H265_Encoding + YangH265RtpEncode *m_h265Encoder; +#endif + char *m_stunBuffer; + int32_t m_stunBufferLen; + + YangRtpExtensionTypes extension_types_; + + int32_t isSendDtls; + + int32_t m_startRecv; + int32_t twcc_id_; + + int32_t m_isSendStun; + bool m_activeState; + + + YangRtpPacket m_pushPacket; + YangVideoEncDecType m_codec; + +private: + void startTimers(); + int32_t dispatch_rtcp(YangRtcpCommon* rtcp); + int32_t on_rtcp_feedback_twcc(char* data, int32_t nb_data); + int32_t on_rtcp_feedback_remb(YangRtcpPsfbCommon *rtcp); + + //std::vector get_track_desc(std::string type, std::string media_name); + int32_t send_avpacket(YangRtpPacket* pkt,YangBuffer* pbuf); +}; + +#endif /* YANGWEBRTC_YANGRTCSESSION_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcSessionI.h b/libyangrtc2/src/yangwebrtc/YangRtcSessionI.h new file mode 100644 index 0000000000000000000000000000000000000000..e840e840a9d26d464da8fc8a752d3ff6407825b1 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcSessionI.h @@ -0,0 +1,24 @@ +#ifndef SRC_YANGWEBRTC_YANGRTCSESSIONI_H_ +#define SRC_YANGWEBRTC_YANGRTCSESSIONI_H_ +#include +#include +#include +class YangRtcSessionI { +public: + YangRtcSessionI(){}; + virtual ~YangRtcSessionI(){}; + virtual int32_t check_send_nacks(YangRtpNackForReceiver* nack, uint32_t ssrc, uint32_t& sent_nacks, uint32_t& timeout_nacks)=0; + virtual int32_t send_rtcp_rr(uint32_t ssrc, YangRtpPlayNackBuffer* rtp_queue, const uint64_t& last_send_systime, const YangNtp& last_send_ntp)=0; + virtual int32_t send_rtcp_xr_rrtr(uint32_t ssrc)=0; + virtual int32_t send_rtcp(char *data, int32_t nb_data)=0; + //virtual int32_t send_packet(YangRtpPacket* pkt)=0; + virtual int32_t send_nackpacket(char* data,int32_t nb)=0; + virtual int32_t send_avpacket(YangRtpPacket* pkt,YangBuffer* pbuf)=0; + virtual int32_t send_rtcp_fb_pli(uint32_t ssrc)=0; + virtual void do_request_keyframe(uint32_t ssrc)=0; + virtual YangSRtp* get_srtp()=0; +}; + + + +#endif /* SRC_YANGWEBRTC_YANGRTCSESSIONI_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangRtcStun.cpp b/libyangrtc2/src/yangwebrtc/YangRtcStun.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a539b13670ee5bb539027853d90b0e91301d2eb6 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcStun.cpp @@ -0,0 +1,353 @@ +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; +YangStunPacket::YangStunPacket() +{ + m_message_type = 0; + m_local_ufrag = ""; + m_remote_ufrag = ""; + m_use_candidate = false; + m_ice_controlled = false; + m_ice_controlling = false; + m_mapped_port = 0; + m_mapped_address = 0; +} + +YangStunPacket::~YangStunPacket() +{ +} + +bool YangStunPacket::is_binding_request() const +{ + return m_message_type == BindingRequest; +} + +bool YangStunPacket::is_binding_response() const +{ + return m_message_type == BindingResponse; +} + +uint16_t YangStunPacket::get_message_type() const +{ + return m_message_type; +} + +std::string YangStunPacket::get_username() const +{ + return m_username; +} + +std::string YangStunPacket::get_local_ufrag() const +{ + return m_local_ufrag; +} + +std::string YangStunPacket::get_remote_ufrag() const +{ + return m_remote_ufrag; +} + +std::string YangStunPacket::get_transcation_id() const +{ + return m_transcation_id; +} + +uint32_t YangStunPacket::get_mapped_address() const +{ + return m_mapped_address; +} + +uint16_t YangStunPacket::get_mapped_port() const +{ + return m_mapped_port; +} + +bool YangStunPacket::get_ice_controlled() const +{ + return m_ice_controlled; +} + +bool YangStunPacket::get_ice_controlling() const +{ + return m_ice_controlling; +} + +bool YangStunPacket::get_use_candidate() const +{ + return m_use_candidate; +} + +void YangStunPacket::set_message_type(const uint16_t& m) +{ + m_message_type = m; +} + +void YangStunPacket::set_local_ufrag(const std::string& u) +{ + m_local_ufrag = u; +} + +void YangStunPacket::set_remote_ufrag(const std::string& u) +{ + m_remote_ufrag = u; +} + +void YangStunPacket::set_transcation_id(const std::string& t) +{ + m_transcation_id = t; +} + +void YangStunPacket::set_mapped_address(const uint32_t& addr) +{ + m_mapped_address = addr; +} + +void YangStunPacket::set_mapped_port(const uint32_t& port) +{ + m_mapped_port = port; +} + +int32_t YangStunPacket::decode(const char* buf, const int32_t nb_buf) +{ + int32_t err = Yang_Ok; + + YangBuffer* stream = new YangBuffer(const_cast(buf), nb_buf); + YangAutoFree(YangBuffer, stream); + + if (stream->left() < 20) { + return yang_error_wrap(ERROR_RTC_STUN, "ERROR_RTC_STUN invalid stun packet, size=%d", stream->size()); + } + + m_message_type = stream->read_2bytes(); + uint16_t message_len = stream->read_2bytes(); + string magic_cookie = stream->read_string(4); + m_transcation_id = stream->read_string(12); + + if (nb_buf != 20 + message_len) { + return yang_error_wrap(ERROR_RTC_STUN, "ERROR_RTC_STUN invalid stun packet, message_len=%d, nb_buf=%d", message_len, nb_buf); + } + + while (stream->left() >= 4) { + uint16_t type = stream->read_2bytes(); + uint16_t len = stream->read_2bytes(); + + if (stream->left() < len) { + return yang_error_wrap(ERROR_RTC_STUN, "invalid stun packet"); + } + + string val = stream->read_string(len); + // padding + if (len % 4 != 0) { + stream->read_string(4 - (len % 4)); + } + + switch (type) { + case Username: { + m_username = val; + size_t p = val.find(":"); + if (p != string::npos) { + m_local_ufrag = val.substr(0, p); + m_remote_ufrag = val.substr(p + 1); + // yang_trace("stun packet local_ufrag=%s, remote_ufrag=%s", local_ufrag.c_str(), remote_ufrag.c_str()); + } + break; + } + + case UseCandidate: { + m_use_candidate = true; + yang_trace("stun use-candidate"); + break; + } + + // @see: https://tools.ietf.org/html/draft-ietf-ice-rfc5245bis-00#section-5.1.2 + // One agent full, one lite: The full agent MUST take the controlling + // role, and the lite agent MUST take the controlled role. The full + // agent will form check lists, run the ICE state machines, and + // generate connectivity checks. + case IceControlled: { + m_ice_controlled = true; + yang_trace("stun ice-controlled"); + break; + } + + case IceControlling: { + m_ice_controlling = true; + yang_trace("stun ice-controlling"); + break; + } + + default: { + // yang_trace("stun type=%u, no process", type); + break; + } + } + } + + return err; +} + +int32_t YangStunPacket::encode(const string& pwd, YangBuffer* stream) +{ + if (is_binding_response()) { + return encode_binding_response(pwd, stream); + } + + yang_error("ERROR_RTC_STUN unknown stun type=%d", get_message_type()); + return 1; +} + +// FIXME: make this function easy to read +int32_t YangStunPacket::encode_binding_response(const string& pwd, YangBuffer* stream) +{ + int32_t err = Yang_Ok; + + string property_username = encode_username(); + string mapped_address = encode_mapped_address(); + + stream->write_2bytes(BindingResponse); + stream->write_2bytes(property_username.size() + mapped_address.size()); + stream->write_4bytes(kStunMagicCookie); + stream->write_string(m_transcation_id); + stream->write_string(property_username); + stream->write_string(mapped_address); + + stream->data()[2] = ((stream->pos() - 20 + 20 + 4) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20 + 20 + 4) & 0x000000FF); + + char hmac_buf[20] = {0}; + uint32_t hmac_buf_len = 0; + if ((err = hmac_encode("sha1", pwd.c_str(), pwd.size(), stream->data(), stream->pos(), hmac_buf, hmac_buf_len)) != Yang_Ok) { + return yang_error_wrap(err, "hmac encode failed"); + } + + string hmac = encode_hmac(hmac_buf, hmac_buf_len); + + stream->write_string(hmac); + stream->data()[2] = ((stream->pos() - 20 + 8) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20 + 8) & 0x000000FF); + + uint32_t crc32 = yang_crc32_ieee(stream->data(), stream->pos(), 0) ^ 0x5354554E; + + string fingerprint = encode_fingerprint(crc32); + + stream->write_string(fingerprint); + + stream->data()[2] = ((stream->pos() - 20) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20) & 0x000000FF); + + return err; +} +int32_t YangStunPacket::encode_binding_request(const string& pwd, YangBuffer* stream) +{ + int32_t err = Yang_Ok; + + string property_username = encode_username(); + string mapped_address = encode_mapped_address(); + + stream->write_2bytes(BindingRequest); + stream->write_2bytes(property_username.size() + mapped_address.size()); + stream->write_4bytes(kStunMagicCookie); + stream->write_string(m_transcation_id); + stream->write_string(property_username); + stream->write_string(mapped_address); + + stream->data()[2] = ((stream->pos() - 20 + 20 + 4) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20 + 20 + 4) & 0x000000FF); + + char hmac_buf[20] = {0}; + uint32_t hmac_buf_len = 0; + if ((err = hmac_encode("sha1", pwd.c_str(), pwd.size(), stream->data(), stream->pos(), hmac_buf, hmac_buf_len)) != Yang_Ok) { + return yang_error_wrap(err, "hmac encode failed"); + } + + string hmac = encode_hmac(hmac_buf, hmac_buf_len); + + stream->write_string(hmac); + stream->data()[2] = ((stream->pos() - 20 + 8) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20 + 8) & 0x000000FF); + + uint32_t crc32 = yang_crc32_ieee(stream->data(), stream->pos(), 0) ^ 0x5354554E; + + string fingerprint = encode_fingerprint(crc32); + + stream->write_string(fingerprint); + + stream->data()[2] = ((stream->pos() - 20) & 0x0000FF00) >> 8; + stream->data()[3] = ((stream->pos() - 20) & 0x000000FF); + + return err; +} +string YangStunPacket::encode_username() +{ + char buf[1460]; + YangBuffer* stream = new YangBuffer(buf, sizeof(buf)); + YangAutoFree(YangBuffer, stream); + + string username = m_remote_ufrag + ":" + m_local_ufrag; + + stream->write_2bytes(Username); + stream->write_2bytes(username.size()); + stream->write_string(username); + + if (stream->pos() % 4 != 0) { + static char padding[4] = {0}; + stream->write_bytes(padding, 4 - (stream->pos() % 4)); + } + + return string(stream->data(), stream->pos()); +} + +string YangStunPacket::encode_mapped_address() +{ + char buf[1460]; + YangBuffer* stream = new YangBuffer(buf, sizeof(buf)); + YangAutoFree(YangBuffer, stream); + + stream->write_2bytes(XorMappedAddress); + stream->write_2bytes(8); + stream->write_1bytes(0); // ignore this bytes + stream->write_1bytes(1); // ipv4 family + stream->write_2bytes(m_mapped_port ^ (kStunMagicCookie >> 16)); + stream->write_4bytes(m_mapped_address ^ kStunMagicCookie); + + return string(stream->data(), stream->pos()); +} + +string encode_hmac(char* hmac_buf, const int32_t hmac_buf_len) +{ + char buf[1460]; + YangBuffer* stream = new YangBuffer(buf, sizeof(buf)); + YangAutoFree(YangBuffer, stream); + + stream->write_2bytes(MessageIntegrity); + stream->write_2bytes(hmac_buf_len); + stream->write_bytes(hmac_buf, hmac_buf_len); + + return string(stream->data(), stream->pos()); +} + +string encode_fingerprint(uint32_t crc32) +{ + char buf[1460]; + YangBuffer* stream = new YangBuffer(buf, sizeof(buf)); + YangAutoFree(YangBuffer, stream); + + stream->write_2bytes(Fingerprint); + stream->write_2bytes(4); + stream->write_4bytes(crc32); + + return string(stream->data(), stream->pos()); +} + diff --git a/libyangrtc2/src/yangwebrtc/YangRtcStun.h b/libyangrtc2/src/yangwebrtc/YangRtcStun.h new file mode 100644 index 0000000000000000000000000000000000000000..e64d61d2e97fcccd66e70c36b68853a1731acd4f --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangRtcStun.h @@ -0,0 +1,105 @@ +#ifndef YangStunPacket_H__ +#define YangStunPacket_H__ + + +#include +#include +#include +#include +#include +#include +/** + +**/ +// @see: https://tools.ietf.org/html/rfc5389 +// The magic cookie field MUST contain the fixed value 0x2112A442 in network byte order +const uint32_t kStunMagicCookie = 0x2112A442; + +enum YangStunMessageType +{ + // see @ https://tools.ietf.org/html/rfc3489#section-11.1 + BindingRequest = 0x0001, + BindingResponse = 0x0101, + BindingErrorResponse = 0x0111, + SharedSecretRequest = 0x0002, + SharedSecretResponse = 0x0102, + SharedSecretErrorResponse = 0x0112, +}; + +enum YangStunMessageAttribute +{ + // see @ https://tools.ietf.org/html/rfc3489#section-11.2 + MappedAddress = 0x0001, + ResponseAddress = 0x0002, + ChangeRequest = 0x0003, + SourceAddress = 0x0004, + ChangedAddress = 0x0005, + Username = 0x0006, + Password = 0x0007, + MessageIntegrity = 0x0008, + ErrorCode = 0x0009, + UnknownAttributes = 0x000A, + ReflectedFrom = 0x000B, + + // see @ https://tools.ietf.org/html/rfc5389#section-18.2 + Realm = 0x0014, + Nonce = 0x0015, + XorMappedAddress = 0x0020, + Software = 0x8022, + AlternateServer = 0x8023, + Fingerprint = 0x8028, + + Priority = 0x0024, + UseCandidate = 0x0025, + IceControlled = 0x8029, + IceControlling = 0x802A, +}; + +class YangStunPacket +{ +public: + YangStunPacket(); + virtual ~YangStunPacket(); + + +public: + bool is_binding_request() const; + bool is_binding_response() const; + uint16_t get_message_type() const; + std::string get_username() const; + std::string get_local_ufrag() const; + std::string get_remote_ufrag() const; + std::string get_transcation_id() const; + uint32_t get_mapped_address() const; + uint16_t get_mapped_port() const; + bool get_ice_controlled() const; + bool get_ice_controlling() const; + bool get_use_candidate() const; + void set_message_type(const uint16_t& m); + void set_local_ufrag(const std::string& u); + void set_remote_ufrag(const std::string& u); + void set_transcation_id(const std::string& t); + void set_mapped_address(const uint32_t& addr); + void set_mapped_port(const uint32_t& port); + int32_t decode(const char* buf, const int32_t nb_buf); + int32_t encode(const std::string& pwd, YangBuffer* stream); + int32_t encode_binding_request(const std::string& pwd, YangBuffer* stream); +private: + int32_t encode_binding_response(const std::string& pwd, YangBuffer* stream); + std::string encode_username(); + std::string encode_mapped_address(); +private: + uint16_t m_message_type; + std::string m_username; + std::string m_local_ufrag; + std::string m_remote_ufrag; + std::string m_transcation_id; + uint32_t m_mapped_address; + uint16_t m_mapped_port; + bool m_use_candidate; + bool m_ice_controlled; + bool m_ice_controlling; + +}; + +#endif diff --git a/libyangrtc2/src/yangwebrtc/YangSSRCInfo.cpp b/libyangrtc2/src/yangwebrtc/YangSSRCInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c97796a23392db1650744c0f90ad237e7875a55c --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangSSRCInfo.cpp @@ -0,0 +1,83 @@ + +#include +#include +#include +#define kCRLF "\r\n" +YangSSRCInfo::YangSSRCInfo() +{ + m_ssrc = 0; +} + +YangSSRCInfo::YangSSRCInfo(uint32_t ssrc, std::string cname, std::string stream_id, std::string track_id) +{ + m_ssrc = ssrc; + m_cname = cname; + m_msid = stream_id; + m_msid_tracker = track_id; + m_mslabel = m_msid; + m_label = m_msid_tracker; +} + +YangSSRCInfo::~YangSSRCInfo() +{ +} + +int32_t YangSSRCInfo::encode(std::stringstream& os) +{ + int32_t err = Yang_Ok; + + if (m_ssrc == 0) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid ssrc"); + } + + os << "a=ssrc:" << m_ssrc << " cname:" << m_cname << kCRLF; + if (!m_msid.empty()) { + os << "a=ssrc:" << m_ssrc << " msid:" << m_msid; + if (!m_msid_tracker.empty()) { + os << " " << m_msid_tracker; + } + os << kCRLF; + } + if (!m_mslabel.empty()) { + os << "a=ssrc:" << m_ssrc << " mslabel:" << m_mslabel << kCRLF; + } + if (!m_label.empty()) { + os << "a=ssrc:" << m_ssrc << " label:" << m_label << kCRLF; + } + + return err; +} + +YangSSRCGroup::YangSSRCGroup() +{ +} + +YangSSRCGroup::~YangSSRCGroup() +{ +} + +YangSSRCGroup::YangSSRCGroup(const std::string& semantic, const std::vector& ssrcs) +{ + m_semantic = semantic; + m_ssrcs = ssrcs; +} + +int32_t YangSSRCGroup::encode(std::ostringstream& os) +{ + int32_t err = Yang_Ok; + + if (m_semantic.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid semantics"); + } + + if (m_ssrcs.size() == 0) { + return yang_error_wrap(ERROR_RTC_SDP_DECODE, "invalid ssrcs"); + } + + os << "a=ssrc-group:" << m_semantic; + for (int32_t i = 0; i < (int)m_ssrcs.size(); i++) { + os << " " << m_ssrcs[i]; + } + + return err; +} diff --git a/libyangrtc2/src/yangwebrtc/YangSSRCInfo.h b/libyangrtc2/src/yangwebrtc/YangSSRCInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..836bc41b102ae9c3bf200763a4970cc21038027d --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangSSRCInfo.h @@ -0,0 +1,37 @@ +#ifndef SRC_YANGWEBRTC_YANGSSRCINFO_H_ +#define SRC_YANGWEBRTC_YANGSSRCINFO_H_ +#include +#include +#include +class YangSSRCInfo +{ +public: + YangSSRCInfo(); + YangSSRCInfo(uint32_t ssrc, std::string cname, std::string stream_id, std::string track_id); + virtual ~YangSSRCInfo(); +public: + int32_t encode(std::stringstream& os); +public: + uint32_t m_ssrc; + std::string m_cname; + std::string m_msid; + std::string m_msid_tracker; + std::string m_mslabel; + std::string m_label; +}; + +class YangSSRCGroup +{ +public: + YangSSRCGroup(); + YangSSRCGroup(const std::string& usage, const std::vector& ssrcs); + virtual ~YangSSRCGroup(); +public: + int32_t encode(std::ostringstream& os); +public: + // e.g FIX, FEC, SIM. + std::string m_semantic; + // SSRCs of this type. + std::vector m_ssrcs; +}; +#endif /* SRC_YANGWEBRTC_YANGSSRCINFO_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.cpp b/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2b33dbe0a04af9c6ab8408c70f1c2c13b6dc4f8 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.cpp @@ -0,0 +1,620 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#define be32toh ntohl +#endif + +#include +#include "YangRtcStun.h" + +YangRtcHandle::YangRtcHandle(){ + m_recvcb=NULL; + m_conf=NULL; +} + +YangRtcHandle::~YangRtcHandle(){ + m_recvcb=NULL; + m_conf=NULL; +} + +void YangRtcHandle::setReceiveCallback(YangReceiveCallback* cbk){ + m_recvcb=cbk; +} +YangRtcHandle* YangRtcHandle::createRtcHandle(YangContext* pcontext){ + return new YangSrsRtcHandleImpl(pcontext); +} +YangSrsRtcHandleImpl::YangSrsRtcHandleImpl(YangContext* pcontext) { + m_context.context=pcontext; + m_session = NULL; + m_udp=NULL; + m_http=NULL; + m_isInit=0; +} + +YangSrsRtcHandleImpl::~YangSrsRtcHandleImpl() { + if(m_context.state) disconnectServer(); + + yang_delete(m_session); + if(m_udp) m_udp->stop(); + yang_stop_thread(m_udp); + yang_delete(m_udp); + yang_delete(m_http); + +} +int32_t YangSrsRtcHandleImpl::disconnectServer(){ + if(m_session){ + + yang_trace("\n*******************webrtc disconnect *********\n"); + + if(m_context.state) m_session->disconnect(); + m_context.state=0; + yang_delete(m_session); + + yang_stop(m_udp); + yang_stop_thread(m_udp); + + m_isInit=0; + + + } + return Yang_Ok; +} +int32_t YangSrsRtcHandleImpl::getState(){ + return m_context.state; +} + +int32_t YangSrsRtcHandleImpl::publishVideo(YangStreamCapture* p){ + if(m_session) return m_session->publishVideo(p); + return Yang_Ok; +} +int32_t YangSrsRtcHandleImpl::publishAudio(YangStreamCapture* p){ + if(m_session) return m_session->publishAudio(p); + return Yang_Ok; +} + + +void YangSrsRtcHandleImpl::init(YangStreamConfig* pconf) { + + if(m_isInit==0){ + if(m_context.streamConf==NULL) m_context.streamConf=pconf; + m_http=new YangSrsSdp(); + + + m_context.streamConf->localIp=yang_getLocalInfo(); + + if(m_udp==NULL) m_udp=new YangUdpHandle(); + if (m_session == NULL) m_session = new YangRtcSession(&m_context); + + m_sdpHandle.init(dynamic_cast(m_context.context->getCertificate())); + m_isInit=1; + } + +} +int32_t YangSrsRtcHandleImpl::connectRtcServer(){ + init(NULL); + static int32_t glocalport=m_context.streamConf->localPort; + int err=Yang_Ok; + if ((err=doHandleSignal(glocalport,m_http,m_context.streamConf->streamOptType)) == Yang_Ok) { + m_udp->init(m_session,(char*)m_context.streamConf->serverIp.c_str(),glocalport); + + m_session->init(m_udp,m_recvcb,m_context.streamConf->streamOptType); + m_udp->start(); + + } + glocalport++; + return err; +} + + +int32_t YangSrsRtcHandleImpl::doHandleSignal(int32_t localport,YangSrsSdp* url, YangStreamOptType role) { + int32_t err = Yang_Ok; + char *srsSdp = new char[1024 * 12]; + char *tsdp = new char[1024 * 10]; + + memset(srsSdp, 0, 1024 * 12); + memset(tsdp, 0, 1024 * 10); + + m_sdpHandle.genLocalSdp(localport,&m_context, tsdp,role); + m_session->setSsrc(m_context.audioSsrc,m_context.videoSsrc); + + char qt = '"'; + const char* roleStr=role==Yang_Stream_Play?"play":"publish"; + sprintf(srsSdp, + "{%capi%c:%chttp://%s:%d/rtc/v1/%s/%c,%cstreamurl%c:%cwebrtc://%s:%d/%s/%s%c,%cclientip%c:null,%csdp%c:%c%s%c}", + qt, qt, qt, m_context.streamConf->serverIp.c_str(), m_context.streamConf->serverPort,roleStr ,qt, qt, qt, qt, m_context.streamConf->serverIp.c_str(), + m_context.streamConf->serverPort, m_context.streamConf->app.c_str(), m_context.streamConf->stream.c_str(), qt, qt, qt, qt, qt, qt, tsdp, qt); + + string tusdp(srsSdp); + char apiurl[256] = { 0 }; + sprintf(apiurl, "http://%s:%d/rtc/v1/%s/", m_context.streamConf->serverIp.c_str(), m_context.streamConf->serverPort,roleStr); + err=url->querySrs(apiurl, tusdp); + + if (err == Yang_Ok) { + char s[1024] = { 0 }; + YangBuffer sb(s, 1024); + //if(role==Yang_Stream_Play) yang_trace("\nSdp:%s",url->m_srs.sdp.c_str()); + createStunPacket(&url->m_srs, &sb,role); + m_session->setStunBuffer( sb.data(), sb.pos()); + + } + + yang_deleteA(srsSdp); + yang_deleteA(tsdp); + + return err; +} + +int32_t YangSrsRtcHandleImpl::createStunPacket(SrsSdpResponseType *prt, YangBuffer *stream,YangStreamOptType role) { + YangStunPacket packet; + + m_context.remote_sdp->parse(prt->sdp); + string tid = yang_random_str(12); + uint32_t addr = be32toh(inet_addr(m_context.streamConf->localIp.c_str())); + vector sv = yang_split(prt->sessionid, ':'); + packet.set_message_type(BindingRequest); + + packet.set_local_ufrag(sv[1]); + packet.set_remote_ufrag(sv[0]); + packet.set_transcation_id(tid); + packet.set_mapped_address(addr); + packet.set_mapped_port(m_context.streamConf->localPort); + if(role==Yang_Stream_Play) + packet.encode_binding_request(m_context.remote_sdp->get_ice_pwd(),stream); + else + packet.encode_binding_request(m_context.remote_sdp->get_ice_pwd(),stream); + + if(role==Yang_Stream_Play) handlePlaySdp(); + + return Yang_Ok; +} +extern int32_t srs_parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_param); +bool srs_sdp_has_h264_profile(const YangMediaPayloadType &payload_type, + const string &profile) { + int32_t err = Yang_Ok; + + if (payload_type.m_format_specific_param.empty()) { + return false; + } + + H264SpecificParam h264_param; + if ((err = srs_parse_h264_fmtp(payload_type.m_format_specific_param, + h264_param)) != Yang_Ok) { + //srs_error_reset(err); + return false; + } + + if (h264_param.profile_level_id == profile) { + return true; + } + + return false; +} + +// For example, 42001f 42e01f, see https://blog.csdn.net/epubcn/article/details/102802108 +bool yang_sdp_has_h264_profile(const YangSdp *sdp, const string &profile) { + for (size_t i = 0; i < sdp->m_media_descs.size(); ++i) { + const YangMediaDesc &desc =sdp->m_media_descs[i]; + if (!desc.is_video()) { + continue; + } + + std::vector payloads = + desc.find_media_with_encoding_name("H264"); + if (payloads.empty()) { + continue; + } + + for (std::vector::iterator it = payloads.begin(); + it != payloads.end(); ++it) { + const YangMediaPayloadType &payload_type = *it; + if (srs_sdp_has_h264_profile(payload_type, profile)) { + return true; + } + } + } + + return false; +} + + + +int32_t YangSrsRtcHandleImpl::handlePlaySdp() { + int32_t err = Yang_Ok; + if(m_context.remote_audio==NULL) m_context.remote_audio=new YangAudioParam(); + if(m_context.remote_video==NULL) m_context.remote_video=new YangVideoParam(); + if(m_context.source==NULL) m_context.source=new YangRtcSourceDescription(); + YangRtcSourceDescription *stream_desc=m_context.source; + if (!stream_desc) { + return yang_error_wrap(ERROR_RTC_SDP_EXCHANGE,"stream description is NULL"); + } + bool nack_enabled = true; + bool twcc_enabled = true; + // TODO: FIME: Should check packetization-mode=1 also. + bool has_42e01f = yang_sdp_has_h264_profile(m_context.remote_sdp, "42e01f"); + + for (int32_t i = 0; i < (int) m_context.remote_sdp->m_media_descs.size(); ++i) { + const YangMediaDesc &remote_media_desc = m_context.remote_sdp->m_media_descs.at(i); + + YangRtcTrack *track_desc = new YangRtcTrack(); + YangAutoFree(YangRtcTrack, track_desc); + + //track_desc->set_direction("recvonly"); + track_desc->set_mid(remote_media_desc.m_mid); + // Whether feature enabled in remote extmap. + int32_t remote_twcc_id = 0; + if (true) { + map extmaps = remote_media_desc.get_extmaps(); + for (map::iterator it = extmaps.begin(); + it != extmaps.end(); ++it) { + if (it->second == kTWCCExt) { + remote_twcc_id = it->first; + break; + } + } + } + + if (twcc_enabled && remote_twcc_id) { + track_desc->add_rtp_extension_desc(remote_twcc_id, kTWCCExt); + } + //printf("\nremote media_descs_ type========================%s",remote_media_desc.is_audio()?"audio":"video"); + if (remote_media_desc.is_audio()) { + // TODO: check opus format specific param + std::vector payloads = + remote_media_desc.find_media_with_encoding_name("opus"); + if (payloads.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_EXCHANGE, + "no valid found opus payload type"); + } + + for (int32_t j = 0; j < (int) payloads.size(); j++) { + const YangMediaPayloadType &payload = payloads.at(j); + //payload. + // if the payload is opus, and the encoding_param_ is channel + YangAudioPayload *audio_payload = new YangAudioPayload( + payload.m_payload_type, payload.m_encoding_name, + payload.m_clock_rate, + ::atol(payload.m_encoding_param.c_str())); + audio_payload->set_opus_param_desc( + payload.m_format_specific_param); + m_context.remote_audio->encode=Yang_AED_OPUS; + m_context.remote_audio->sample=payload.m_clock_rate; + m_context.remote_audio->channel=atoi(payload.m_encoding_param.c_str()); + m_context.remote_audio->audioClock=payload.m_clock_rate; + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.m_rtcp_fb.size(); ++k) { + const string &rtcp_fb = payload.m_rtcp_fb.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + audio_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + audio_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + } + + track_desc->type_ = "audio"; + //printf("\naudio ssrc===%u,",track_desc->ssrc_); + //track_desc->set_codec_payload((YangCodecPayload*) audio_payload); + // Only choose one match opus codec. + break; + } + } else if (remote_media_desc.is_video() && m_context.codec_ == "av1") { + std::vector payloads = + remote_media_desc.find_media_with_encoding_name("AV1X"); + if (payloads.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_EXCHANGE, + "no found valid AV1 payload type"); + } + + for (int32_t j = 0; j < (int) payloads.size(); j++) { + const YangMediaPayloadType &payload = payloads.at(j); + + // Generate video payload for av1. + YangVideoPayload *video_payload = new YangVideoPayload( + payload.m_payload_type, payload.m_encoding_name, + payload.m_clock_rate); + + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.m_rtcp_fb.size(); ++k) { + const string &rtcp_fb = payload.m_rtcp_fb.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + } + + track_desc->type_ = "video"; + //track_desc->set_codec_payload((YangCodecPayload*) video_payload); + break; + } + } else if (remote_media_desc.is_video()&&remote_media_desc.find_encoding_name("H264")) { + std::vector payloads = + remote_media_desc.find_media_with_encoding_name("H264"); + if (payloads.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_EXCHANGE, + "no found valid H.264 payload type"); + } + + std::deque backup_payloads; + for (int32_t j = 0; j < (int) payloads.size(); j++) { + const YangMediaPayloadType &payload = payloads.at(j); + + if (payload.m_format_specific_param.empty()) { + backup_payloads.push_front(payload); + continue; + } + H264SpecificParam h264_param; + if ((err = srs_parse_h264_fmtp(payload.m_format_specific_param, + h264_param)) != Yang_Ok) { + // srs_error_reset(err); + continue; + } + + // If not exists 42e01f, we pick up any profile such as 42001f. + bool profile_matched = (!has_42e01f + || h264_param.profile_level_id == "42e01f"); + + // Try to pick the "best match" H.264 payload type. + if (profile_matched && h264_param.packetization_mode == "1" + && h264_param.level_asymmerty_allow == "1") { + // if the playload is opus, and the encoding_param_ is channel + YangVideoPayload *video_payload = new YangVideoPayload( + payload.m_payload_type, payload.m_encoding_name, + payload.m_clock_rate); + video_payload->set_h264_param_desc( + payload.m_format_specific_param); + m_context.remote_video->encode=Yang_VED_264; + m_context.remote_video->videoClock=payload.m_clock_rate; + //m_conf.audio->channel=atoi(payload.encoding_param_.c_str()); + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.m_rtcp_fb.size(); ++k) { + const string &rtcp_fb = payload.m_rtcp_fb.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + } + m_context.codec_ = "h264"; + track_desc->type_ = "video"; + + //track_desc->set_codec_payload((YangCodecPayload*) video_payload); + // Only choose first match H.264 payload type. + break; + } + + backup_payloads.push_back(payload); + } + + // Try my best to pick at least one media payload type. + /**if (!track_desc->media_ && !backup_payloads.empty()) { + const YangMediaPayloadType &payload = backup_payloads.front(); + + // if the playload is opus, and the encoding_param_ is channel + YangVideoPayload *video_payload = new YangVideoPayload( + payload.payload_type_, payload.encoding_name_, + payload.clock_rate_); + + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.rtcp_fb_.size(); ++k) { + const string &rtcp_fb = payload.rtcp_fb_.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + video_payload->rtcp_fbs_.push_back(rtcp_fb); + } + } + + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + video_payload->rtcp_fbs_.push_back(rtcp_fb); + } + } + } + + //track_desc->set_codec_payload((YangCodecPayload*) video_payload); + //yang_trace("choose backup H.264 payload type=%d", payload.payload_type_); + }**/ + + // TODO: FIXME: Support RRTR? + //local_media_desc.payload_types_.back().rtcp_fb_.push_back("rrtr"); + }else if (remote_media_desc.is_video()&&remote_media_desc.find_encoding_name("H265")) { + std::vector payloads = + remote_media_desc.find_media_with_encoding_name("H265"); + if (payloads.empty()) { + return yang_error_wrap(ERROR_RTC_SDP_EXCHANGE, + "no found valid H.265 payload type"); + } + + std::deque backup_payloads; + for (int32_t j = 0; j < (int) payloads.size(); j++) { + const YangMediaPayloadType &payload = payloads.at(j); + + if (payload.m_format_specific_param.empty()) { + backup_payloads.push_front(payload); + continue; + } + H264SpecificParam h264_param; + if ((err = srs_parse_h264_fmtp(payload.m_format_specific_param, + h264_param)) != Yang_Ok) { + // srs_error_reset(err); + continue; + } + + // If not exists 42e01f, we pick up any profile such as 42001f. + bool profile_matched = (!has_42e01f + || h264_param.profile_level_id == "42e01f"); + + // Try to pick the "best match" H.264 payload type. + if (profile_matched && h264_param.packetization_mode == "1" + && h264_param.level_asymmerty_allow == "1") { + // if the playload is opus, and the encoding_param_ is channel + YangVideoPayload *video_payload = new YangVideoPayload( + payload.m_payload_type, payload.m_encoding_name, + payload.m_clock_rate); + video_payload->set_h264_param_desc( + payload.m_format_specific_param); + m_context.remote_video->encode=Yang_VED_265; + m_context.remote_video->videoClock=payload.m_clock_rate; + //m_conf.audio->channel=atoi(payload.encoding_param_.c_str()); + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.m_rtcp_fb.size(); ++k) { + const string &rtcp_fb = payload.m_rtcp_fb.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + video_payload->m_rtcp_fbs.push_back(rtcp_fb); + } + } + } + + m_context.codec_ = "h265"; + + track_desc->type_ = "video"; + + //track_desc->set_codec_payload((YangCodecPayload*) video_payload); + // Only choose first match H.264 payload type. + break; + } + + backup_payloads.push_back(payload); + } + + // Try my best to pick at least one media payload type. + /**if (!track_desc->media_ && !backup_payloads.empty()) { + const YangMediaPayloadType &payload = backup_payloads.front(); + + // if the playload is opus, and the encoding_param_ is channel + YangVideoPayload *video_payload = new YangVideoPayload( + payload.payload_type_, payload.encoding_name_, + payload.clock_rate_); + + // TODO: FIXME: Only support some transport algorithms. + for (int32_t k = 0; k < (int) payload.rtcp_fb_.size(); ++k) { + const string &rtcp_fb = payload.rtcp_fb_.at(k); + + if (nack_enabled) { + if (rtcp_fb == "nack" || rtcp_fb == "nack pli") { + video_payload->rtcp_fbs_.push_back(rtcp_fb); + } + } + + if (twcc_enabled && remote_twcc_id) { + if (rtcp_fb == "transport-cc") { + video_payload->rtcp_fbs_.push_back(rtcp_fb); + } + } + } + + //track_desc->set_codec_payload((YangCodecPayload*) video_payload); + //yang_trace("choose backup H.264 payload type=%d", payload.payload_type_); + }**/ + + // TODO: FIXME: Support RRTR? + //local_media_desc.payload_types_.back().rtcp_fb_.push_back("rrtr"); + } + + // TODO: FIXME: use one parse payload from sdp. + + //track_desc->create_auxiliary_payload(remote_media_desc.find_media_with_encoding_name("red")); + //track_desc->create_auxiliary_payload(remote_media_desc.find_media_with_encoding_name("rtx")); + //track_desc->create_auxiliary_payload(remote_media_desc.find_media_with_encoding_name("ulpfec")); + + std::string track_id; + bool hasTrack=false; + for (int32_t j = 0; j < (int) remote_media_desc.m_ssrc_infos.size(); ++j) { + const YangSSRCInfo &ssrc_info = remote_media_desc.m_ssrc_infos.at(j); + + // ssrc have same track id, will be description in the same track description. + if (track_id != ssrc_info.m_msid_tracker) { + YangRtcTrack *track_desc_copy = track_desc->copy(); + track_desc_copy->ssrc_ = ssrc_info.m_ssrc; + track_desc_copy->id_ = ssrc_info.m_msid_tracker; + track_desc_copy->msid_ = ssrc_info.m_msid; + + if (remote_media_desc.is_audio() + && !stream_desc->audio_track_desc_) { + stream_desc->audio_track_desc_ = track_desc_copy; + } else if (remote_media_desc.is_video()) { + stream_desc->video_track_descs_.push_back(track_desc_copy); + } + hasTrack=true; + } + track_id = ssrc_info.m_msid_tracker; + + } + //rtmp to rtc no msid + if(!hasTrack){ + if( remote_media_desc.m_ssrc_infos.size()>0){ + const YangSSRCInfo &ssrc_info1 = remote_media_desc.m_ssrc_infos.at(0); + YangRtcTrack *track_desc_copy = track_desc->copy(); + track_desc_copy->ssrc_ = ssrc_info1.m_ssrc; + track_desc_copy->id_ = ssrc_info1.m_msid_tracker; + track_desc_copy->msid_ = ssrc_info1.m_msid; + if (remote_media_desc.is_audio() + && !stream_desc->audio_track_desc_) { + stream_desc->audio_track_desc_ = track_desc_copy; + } else if (remote_media_desc.is_video()&&stream_desc->video_track_descs_.size()==0) { + stream_desc->video_track_descs_.push_back(track_desc_copy); + } + } + + } + + + // set track fec_ssrc and rtx_ssrc + for (int32_t j = 0; j < (int) remote_media_desc.m_ssrc_groups.size(); ++j) { + const YangSSRCGroup &ssrc_group = remote_media_desc.m_ssrc_groups.at( + j); + + YangRtcTrack *track_desc = + stream_desc->find_track_description_by_ssrc( + ssrc_group.m_ssrcs[0]); + if (!track_desc) { + continue; + } + + if (ssrc_group.m_semantic == "FID") { + track_desc->set_rtx_ssrc(ssrc_group.m_ssrcs[1]); + } else if (ssrc_group.m_semantic == "FEC") { + track_desc->set_fec_ssrc(ssrc_group.m_ssrcs[1]); + } + } + } + + if(m_context.context){ + m_context.context->streams.setMediaConfig(m_context.streamConf->uid, m_context.remote_audio,m_context.remote_video); + } + return err; +} + diff --git a/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.h b/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..c2b5d4198afa0a4e70445f8e23396e90ad85b876 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangSrsRtcHandleImpl.h @@ -0,0 +1,46 @@ + +#ifndef YANGRTP_YangRtcHandleImpl_H_ +#define YANGRTP_YangRtcHandleImpl_H_ + +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +class YangSrsRtcHandleImpl:public YangRtcHandle +{ +public: + YangSrsRtcHandleImpl(YangContext* pcontext); + ~YangSrsRtcHandleImpl(); +public: + void init(YangStreamConfig* pconf); + + int32_t connectRtcServer(); + int32_t disconnectServer(); + + int32_t publishVideo(YangStreamCapture* videoFrame); + int32_t publishAudio(YangStreamCapture* audioFrame); + int32_t getState(); + + +private: + YangSrsSdp* m_http;//url_publish; + YangUdpHandle* m_udp; + YangRtcSession *m_session; + YangSdpHandle m_sdpHandle; + + + YangRtcContext m_context; + int32_t m_isInit; + + +private: + int32_t handlePlaySdp(); + int32_t createStunPacket(SrsSdpResponseType* prt,YangBuffer *stream,YangStreamOptType role); + int32_t doHandleSignal(int32_t localport,YangSrsSdp* url,YangStreamOptType role); +}; +#endif diff --git a/libyangrtc2/src/yangwebrtc/YangSrsSdp.cpp b/libyangrtc2/src/yangwebrtc/YangSrsSdp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3be176796cb0ba50c8dbc6bfb4a2ed9cbe8cb0c --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangSrsSdp.cpp @@ -0,0 +1,52 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +using namespace std; + + + + +YangSrsSdp::YangSrsSdp() +{ + +} +YangSrsSdp::~YangSrsSdp() +{ + +} + + +int32_t YangSrsSdp::querySrs(char* purl, string psdp) +{ + string sBuffer; + m_http.queryPost(purl, psdp, sBuffer); + yang_replace(sBuffer, "{", ""); + yang_replace(sBuffer, "}", ""); + yang_replace(sBuffer, "\\r\\n", "\r\n"); + vector sb=yang_split(sBuffer, ','); + for (int32_t i = 0; i < (int)sb.size(); i++) { + vector sb1 = yang_split_first(sb.at(i), ':'); + string key = sb1.at(0); + string value = sb1.at(1); + yang_replace(key, "\"", ""); + yang_replace(value, "\"", ""); + if (key.find("code") != key.npos) m_srs.retcode = value; + if (key.find("server") != key.npos) m_srs.serverIp = value; + if (key.find("sdp") != key.npos) { + m_srs.sdp = value; + } + if (key.find("sessionid") != key.npos) m_srs.sessionid = value; + + } + if(m_srs.retcode!="0") return 1; + return Yang_Ok; + +} diff --git a/libyangrtc2/src/yangwebrtc/YangUdpHandle.cpp b/libyangrtc2/src/yangwebrtc/YangUdpHandle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..664eebc354d95f4aa0083931d14637cfd905f363 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangUdpHandle.cpp @@ -0,0 +1,130 @@ +#include +#include +#include + +#include +#include +#include + + + + + +YangUdpHandle::YangUdpHandle() { + m_lclPort = 8100; + m_serverfd = -1; + m_loop = 0; + m_serverPort = 8000; + m_isStart = 0; + m_session = NULL; +} + +YangUdpHandle::~YangUdpHandle() { + stop(); + m_session = NULL; + while (m_isStart) + yang_usleep(1000); +} +void YangUdpHandle::init(YangRtcSession *psession, char *pserverIp, + int32_t plocalPort) { + m_session = psession; + m_serverIp = pserverIp; + m_lclPort = plocalPort; + +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(2, 2); + WSAStartup(wVersionRequested, &wsaData); +#endif + m_lcl_addr.sin_family = AF_INET; + m_lcl_addr.sin_port = htons(m_lclPort); + // lcl_addr.sin_addr.s_addr=inet_addr(ip); + m_lcl_addr.sin_addr.s_addr = INADDR_ANY; + m_serverfd = socket(AF_INET, SOCK_DGRAM, 0); + + m_remote_addr.sin_family = AF_INET; + m_remote_addr.sin_port = htons(m_serverPort); + m_remote_addr.sin_addr.s_addr = inet_addr(m_serverIp.c_str()); + +} + +void YangUdpHandle::run() { + m_isStart = 1; + startLoop(); + m_isStart = 0; +} +void YangUdpHandle::stop() { + m_loop = 0; + closeUdp(); + +} +int32_t YangUdpHandle::sendUdp(const char *data, int32_t len) { + + int32_t n = 0; + n = sendto(m_serverfd, data, len, 0, (sockaddr*) &m_remote_addr, + sizeof(sockaddr)); + + return n > 0 ? 0 : 1; +} +int32_t YangUdpHandle::sendData(char *p, int32_t plen) { + return sendUdp(p, plen); +} + +void YangUdpHandle::startLoop() { +#ifdef _WIN32 + int32_t timeout=200; + setsockopt(m_serverfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout)); +#else + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 200000; // 200 ms + setsockopt(m_serverfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &tv, sizeof(struct timeval)); +#endif + + printf("\n udp server is starting..localPort==%d",m_lclPort); + +#ifdef _WIN32 + if (bind(m_serverfd, (struct sockaddr*) &m_lcl_addr, sizeof(struct sockaddr_in)) < 0) { +#else + if (bind(m_serverfd, (struct sockaddr*) &m_lcl_addr, + sizeof(struct sockaddr_in)) < 0) { +#endif + + perror("Udp server bind error"); + exit(1); + } + char buffer[2048] = { 0 }; + m_loop = 1; + + int32_t len = 0; + if (m_session) + m_session->startStunTimer(); + + while (m_loop) { + struct sockaddr_in src; + socklen_t src_len = sizeof(src); + memset(&src, 0, sizeof(src)); + memset(buffer, 0, 2048); + if ((len = recvfrom(m_serverfd, buffer, 2048, 0, (sockaddr*) &src, + &src_len)) > 0) { + if (m_session) + m_session->receive(buffer, len); + } + } + + closeUdp(); + +} + +void YangUdpHandle::closeUdp() { + if (m_serverfd>-1) { +#ifdef _WIN32 + closesocket(m_serverfd); +#else + close(m_serverfd); +#endif + m_serverfd = -1; + } + +} diff --git a/libyangrtc2/src/yangwebrtc/YangUdpHandle.h b/libyangrtc2/src/yangwebrtc/YangUdpHandle.h new file mode 100644 index 0000000000000000000000000000000000000000..588747fdacd43faf1bd623fffbe0773f9d84b178 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangUdpHandle.h @@ -0,0 +1,47 @@ +#ifndef YANGWEBRTC_YANGUDPHANDLE_H_ +#define YANGWEBRTC_YANGUDPHANDLE_H_ +#include +#include +#include +#ifdef _WIN32 +#include +#include +//#define SOCKADDR_IN +#define socklen_t int +#else +#include +#include +#include +#include +#endif +#include "YangRtcSession.h" + +using namespace std; +class YangUdpHandle:public YangThread ,public YangSendUdpData{ +public: + YangUdpHandle(); + virtual ~YangUdpHandle(); + + void init(YangRtcSession* psession,char* pserverIp,int32_t plocalPort); + int32_t sendUdp(const char *data, int32_t len); + void setSockSrv(const char *ip, int32_t port); + int32_t sendData(char* p,int32_t plen); + void closeUdp(); + int32_t m_isStart; + void stop(); +protected: + void run(); + void startLoop(); + void receive(char* data,int32_t plen); + + YangRtcSession *m_session; + int32_t m_serverfd; + int32_t m_lclPort; + + string m_serverIp; + int32_t m_serverPort; + int32_t m_loop; + struct sockaddr_in m_lcl_addr,m_remote_addr; +}; + +#endif /* YANGWEBRTC_YANGUDPHANDLE_H_ */ diff --git a/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.cpp b/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff3f70b87e37cfd576cc1778e7249afde5dfce29 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +YangVideoRecvTrack::YangVideoRecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *track_desc, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque) : + YangRecvTrack(uid, conf, session, track_desc, rtpBuffer, pmixque, false) { + + if(conf&&conf->context&&conf->streamConf) + conf->context->streams.setRtcMessageNotify(conf->streamConf->uid,this); + m_h264Track=NULL; + m_h265Track=NULL; + + if(conf->codec_=="h264") m_h264Track=new YangH264RecvTrack(uid, conf, session, track_desc, rtpBuffer, pmixque); + if(conf->codec_=="h265") m_h265Track=new YangH265RecvTrack(uid, conf, session, track_desc, rtpBuffer, pmixque); +} + + +YangVideoRecvTrack::~YangVideoRecvTrack() { + yang_delete(m_h264Track); + yang_delete(m_h265Track); +} + + + +void YangVideoRecvTrack::setReceiveCallback(YangReceiveCallback *cbk) { + if(m_h264Track) m_h264Track->setReceiveCallback(cbk); + if(m_h265Track) m_h265Track->setReceiveCallback(cbk); +} +int32_t YangVideoRecvTrack::on_rtp(YangRtpPacket *src) { + int32_t err = Yang_Ok; + if(m_h264Track) m_h264Track->on_rtp(src); + if(m_h265Track) m_h265Track->on_rtp(src); + return err; +} + +int32_t YangVideoRecvTrack::check_send_nacks() { + int32_t err = Yang_Ok; + + uint32_t timeout_nacks = 0; + + if ((err = do_check_send_nacks(timeout_nacks)) != Yang_Ok) { + return yang_error_wrap(err, "video"); + } + + if (timeout_nacks == 0) { + return err; + } + + return err; +} + + +int32_t YangVideoRecvTrack::notify(int puid,YangRtcMessageType mess){ + + if(mess==YangRTC_Decoder_Input) { + if(m_h264Track) m_h264Track->m_hasRequestKeyframe=false; + if(m_h265Track) m_h265Track->m_hasRequestKeyframe=false; + return m_session->send_rtcp_fb_pli(m_track_desc->ssrc_); + } + + return Yang_Ok; +} + diff --git a/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.h b/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..b21ba4ff98fceae26ac8aea180809a79cb172370 --- /dev/null +++ b/libyangrtc2/src/yangwebrtc/YangVideoRecvTrack.h @@ -0,0 +1,27 @@ +#ifndef SRC_YANGWEBRTC_YANGRTCVIDEORECVTRACK1_H_ +#define SRC_YANGWEBRTC_YANGRTCVIDEORECVTRACK1_H_ +#include +#include +#include +#include + + + + +class YangVideoRecvTrack: public YangRecvTrack ,public YangRtcMessageNotify{ +public: + YangVideoRecvTrack(int32_t uid, YangRtcContext *conf, + YangRtcSessionI *session, YangRtcTrack *stream_descs, + YangRtpBuffer *rtpBuffer, YangMixQueue *pmixque); + virtual ~YangVideoRecvTrack(); + +public: + int32_t on_rtp(YangRtpPacket *pkt); + int32_t check_send_nacks(); + int32_t notify(int puid,YangRtcMessageType mess); + void setReceiveCallback(YangReceiveCallback *cbk); +private: + YangH264RecvTrack* m_h264Track; + YangH265RecvTrack* m_h265Track; +}; +#endif /* SRC_YANGWEBRTC_YANGRTCVIDEORECVTRACK_H_ */ diff --git a/libyangrtc2/yangrtc2.pro b/libyangrtc2/yangrtc2.pro new file mode 100644 index 0000000000000000000000000000000000000000..7ff782d40e6b56d439e943fc1e2e23ceca1fb61b --- /dev/null +++ b/libyangrtc2/yangrtc2.pro @@ -0,0 +1,392 @@ +CONFIG -= qt + +TEMPLATE = lib +CONFIG += staticlib + +CONFIG += c++14 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += __STDC_FORMAT_MACROS +HOME_BASE=../ +INCLUDEPATH += $$HOME_BASE/include +INCLUDEPATH += $$HOME_BASE/thirdparty/include +INCLUDEPATH += $$HOME_BASE/thirdparty/user_include +INCLUDEPATH += $$HOME_BASE/thirdparty/user_include/ffmpeg +INCLUDEPATH += $$HOME_BASE/libyangrtc2/src +#vr on +INCLUDEPATH += $$HOME_BASE/ext/include_ext +INCLUDEPATH += $$HOME_BASE/ext/thirdparty_ext/include +unix{ + CONFIG(debug, debug|release) { + DESTDIR += $$HOME_BASE/bin/lib_debug + }else{ + + DESTDIR += $$HOME_BASE/bin/lib_release + } +} +win32{ + DEFINES += _AMD64_ + INCLUDEPATH += $$HOME_BASE\thirdparty\include\win + CONFIG(debug, debug|release) { + DESTDIR += $$HOME_BASE\bin\lib_win_debug + }else{ + DESTDIR += $$HOME_BASE\bin\lib_win_release + } + + msvc{ + QMAKE_CFLAGS += /utf-8 + QMAKE_CXXFLAGS += /utf-8 + # QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8 + DEFINES +=HAVE_STRUCT_TIMESPEC + DEFINES +=WIN32_LEAN_AND_MEAN + INCLUDEPATH += $$HOME_BASE\thirdparty\include\win\include + } + +} +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + src/yangaudiodev/YangAudioCapture.cpp \ + src/yangaudiodev/YangAudioCaptureData.cpp \ + src/yangaudiodev/YangAudioCaptureHandle.cpp \ + src/yangaudiodev/YangAudioPlay.cpp \ + src/yangaudiodev/YangAudioRenderData.cpp \ + src/yangaudiodev/linux/YangAlsaDeviceHandle.cpp \ + src/yangaudiodev/linux/YangAlsaHandle.cpp \ + src/yangaudiodev/linux/YangAudioCaptureImpl.cpp \ + src/yangaudiodev/linux/YangAudioPlayAlsa.cpp \ + src/yangaudiodev/win/YangRecAudioCaptureHandle.cpp \ + src/yangaudiodev/win/YangWinAudioApi.cpp \ + src/yangaudiodev/win/YangWinAudioApiAec.cpp \ + src/yangaudiodev/win/YangWinAudioApiCapture.cpp \ + src/yangaudiodev/win/YangWinAudioApiDevice.cpp \ + src/yangaudiodev/win/YangWinAudioApiRender.cpp \ + src/yangaudiodev/win/YangWinAudioCapture.cpp \ + src/yangaudiodev/win/YangWinAudioCaptureHandle.cpp \ + src/yangaudiodev/win/YangWinRecordAudioCapture.cpp \ + src/yangavutil/YangAecBase.cpp \ + src/yangavutil/YangAecSpeex.cpp \ + src/yangavutil/YangAudioFactory.cpp \ + src/yangavutil/YangAudioMix.cpp \ + src/yangavutil/YangAudioUtil.cpp \ + src/yangavutil/YangConvert.cpp \ + src/yangavutil/YangImageConvert.cpp \ + src/yangavutil/YangMakeWave.cpp \ + src/yangavutil/YangMeta.cpp \ + src/yangavutil/YangNalu.cpp \ + src/yangavutil/YangPicUtilFfmpeg.cpp \ + src/yangavutil/YangPreProcess.cpp \ + src/yangavutil/YangPreProcessSpeex.cpp \ + src/yangavutil/YangResample.cpp \ + src/yangavutil/YangSwResample.cpp \ + src/yangavutil/YangVideoEncoderMeta.cpp \ + src/yangavutil/YangYuvConvert.cpp \ + src/yangavutil/YangYuvUtil.cpp \ + src/yangcapture/YangAudioDeviceQuery.cpp \ + src/yangcapture/YangCaptureFactory.cpp \ + src/yangcapture/YangDXGIManager.cpp \ + src/yangcapture/YangScreenCaptureImpl.cpp \ + src/yangcapture/YangScreenShare.cpp \ + src/yangcapture/YangVideoCapture.cpp \ + src/yangcapture/YangVideoCaptureHandle.cpp \ + src/yangcapture/YangVideoCaptureImpl.cpp \ + src/yangcapture/YangVideoDeviceQuery.cpp \ + src/yangcapture/win/YangVideoSrc.cpp \ + src/yangcapture/win/YangWinVideoCapture.cpp \ + src/yangcapture/win/YangWinVideoCaptureHandle.cpp \ + src/yangdecoder/YangAudioDecoder.cpp \ + src/yangdecoder/YangAudioDecoderAac.cpp \ + src/yangdecoder/YangAudioDecoderHandle.cpp \ + src/yangdecoder/YangAudioDecoderHandles.cpp \ + src/yangdecoder/YangAudioDecoderOpus.cpp \ + src/yangdecoder/YangAudioDecoderSpeex.cpp \ + src/yangdecoder/YangDecoderFactory.cpp \ + src/yangdecoder/YangH2645VideoDecoderFfmpeg.cpp \ + src/yangdecoder/YangH264DecoderSoft.cpp \ + src/yangdecoder/YangH264Header.cpp \ + src/yangdecoder/YangHeaderParseFfmpeg.cpp \ + src/yangdecoder/YangVideoDecoderHandle.cpp \ + src/yangdecoder/YangVideoDecoderHandles.cpp \ + src/yangdecoder/YangVideoDecoderIntel.cpp \ + src/yangencoder/YangAudioEncoder.cpp \ + src/yangencoder/YangAudioEncoderAac.cpp \ + src/yangencoder/YangAudioEncoderHandle.cpp \ + src/yangencoder/YangAudioEncoderHandleCb.cpp \ + src/yangencoder/YangAudioEncoderMeta.cpp \ + src/yangencoder/YangAudioEncoderMp3.cpp \ + src/yangencoder/YangAudioEncoderOpus.cpp \ + src/yangencoder/YangAudioEncoderSpeex.cpp \ + src/yangencoder/YangEncoderFactory.cpp \ + src/yangencoder/YangFfmpegEncoderMeta.cpp \ + src/yangencoder/YangH264EncHeader.cpp \ + src/yangencoder/YangH264EncoderIntel.cpp \ + src/yangencoder/YangH264EncoderMeta.cpp \ + src/yangencoder/YangH264EncoderSoft.cpp \ + src/yangencoder/YangH265EncoderMeta.cpp \ + src/yangencoder/YangH265EncoderSoft.cpp \ + src/yangencoder/YangVideoEncoder.cpp \ + src/yangencoder/YangVideoEncoderFfmpeg.cpp \ + src/yangencoder/YangVideoEncoderHandle.cpp \ + src/yangplayer/YangPlayFactory.cpp \ + src/yangplayer/YangPlayReceive.cpp \ + src/yangplayer/YangPlayerBase.cpp \ + src/yangplayer/YangPlayerDecoder.cpp \ + src/yangplayer/YangPlayerHandleImpl.cpp \ + src/yangplayer/YangPlayerPlay.cpp \ + src/yangplayer/YangRtcReceive.cpp \ + src/yangpush/YangPushCapture.cpp \ + src/yangpush/YangPushEncoder.cpp \ + src/yangpush/YangPushFactory.cpp \ + src/yangpush/YangPushHandleImpl.cpp \ + src/yangpush/YangPushMessageHandle.cpp \ + src/yangpush/YangPushPublish.cpp \ + src/yangpush/YangRtcPublish.cpp \ + src/yangpush/YangSendVideoImpl.cpp \ + src/yangrecord/YangFlvWrite.cpp \ + src/yangrecord/YangMp4File.cpp \ + src/yangrecord/YangMp4FileApp.cpp \ + src/yangrecord/YangRecEncoder.cpp \ + src/yangrecord/YangRecord.cpp \ + src/yangrecord/YangRecordApp.cpp \ + src/yangrecord/YangRecordCapture.cpp \ + src/yangrecord/YangRecordHandle.cpp \ + src/yangrecord/YangRecordMp4.cpp \ + src/yangrtmp/YangInvokeBuffer.cpp \ + src/yangrtmp/YangRtmpBase.cpp \ + src/yangrtp/YangAudioPayload.cpp \ + src/yangrtp/YangCodecPayload.cpp \ + src/yangrtp/YangMediaPayloadType.cpp \ + src/yangrtp/YangMixQueue.cpp \ + src/yangrtp/YangPublishNackBuffer.cpp \ + src/yangrtp/YangRedPayload.cpp \ + src/yangrtp/YangRtcpApp.cpp \ + src/yangrtp/YangRtcpCommon.cpp \ + src/yangrtp/YangRtcpCompound.cpp \ + src/yangrtp/YangRtcpNack.cpp \ + src/yangrtp/YangRtcpPli.cpp \ + src/yangrtp/YangRtcpPsfbCommon.cpp \ + src/yangrtp/YangRtcpRR.cpp \ + src/yangrtp/YangRtcpRpsi.cpp \ + src/yangrtp/YangRtcpSR.cpp \ + src/yangrtp/YangRtcpSli.cpp \ + src/yangrtp/YangRtcpTWCC.cpp \ + src/yangrtp/YangRtcpXr.cpp \ + src/yangrtp/YangRtp.cpp \ + src/yangrtp/YangRtpBuffer.cpp \ + src/yangrtp/YangRtpFUAPayload.cpp \ + src/yangrtp/YangRtpFUAPayload2.cpp \ + src/yangrtp/YangRtpHeader.cpp \ + src/yangrtp/YangRtpNackForReceiver.cpp \ + src/yangrtp/YangRtpPacket.cpp \ + src/yangrtp/YangRtpPlayNackBuffer.cpp \ + src/yangrtp/YangRtpRawNALUs.cpp \ + src/yangrtp/YangRtpRawPayload.cpp \ + src/yangrtp/YangRtpRingBuffer.cpp \ + src/yangrtp/YangRtpSTAPPayload.cpp \ + src/yangrtp/YangRtxPayloadDes.cpp \ + src/yangrtp/YangVideoPayload.cpp \ + src/yangsrt/YangSrtBase.cpp \ + src/yangsrt/YangTsBuffer.cpp \ + src/yangsrt/YangTsMuxer.cpp \ + src/yangsrt/YangTsPacket.cpp \ + src/yangsrt/YangTsdemux.cpp \ + src/yangsrt/common.cpp \ + src/yangsrt/crc.cpp \ + src/yangsrt/srt_data.cpp \ + src/yangstream/YangAudioStreamCapture.cpp \ + src/yangstream/YangStreamCapture.cpp \ + src/yangstream/YangStreamFactory.cpp \ + src/yangstream/YangStreamHandle.cpp \ + src/yangstream/YangStreamManager.cpp \ + src/yangstream/YangStreamPlay.cpp \ + src/yangstream/YangStreamRtc.cpp \ + src/yangstream/YangStreamRtmp.cpp \ + src/yangstream/YangStreamSrt.cpp \ + src/yangstream/YangSynBuffer.cpp \ + src/yangstream/YangVideoStreamCapture.cpp \ + src/yangutil/YangAmf.cpp \ + src/yangutil/YangAvinfo.cpp \ + src/yangutil/YangAvtype.cpp \ + src/yangutil/YangEndian.cpp \ + src/yangutil/YangFile.cpp \ + src/yangutil/YangHttp.cpp \ + src/yangutil/YangIniImpl.cpp \ + src/yangutil/YangJson.cpp \ + src/yangutil/YangLoadLib.cpp \ + src/yangutil/YangLog.cpp \ + src/yangutil/YangSRtp.cpp \ + src/yangutil/YangSocket.cpp \ + src/yangutil/YangSsl.cpp \ + src/yangutil/YangSsrc.cpp \ + src/yangutil/YangString.cpp \ + src/yangutil/YangSysMessageHandle.cpp \ + src/yangutil/YangThread.cpp \ + src/yangutil/YangTime.cpp \ + src/yangutil/YangTimer.cpp \ + src/yangutil/YangUrl.cpp \ + src/yangutil/YangWebsocket.cpp \ + src/yangutil/YangWebsocketImpl.cpp \ + src/yangutil/YangWindowsMouse.cpp \ + src/yangutil/buffer/YangAudioBuffer.cpp \ + src/yangutil/buffer/YangAudioEncoderBuffer.cpp \ + src/yangutil/buffer/YangAudioPlayBuffer.cpp \ + src/yangutil/buffer/YangBuffer.cpp \ + src/yangutil/buffer/YangMediaBuffer.cpp \ + src/yangutil/buffer/YangVideoBuffer.cpp \ + src/yangutil/buffer/YangVideoDecoderBuffer.cpp \ + src/yangutil/buffer/YangVideoEncoderBuffer.cpp \ + src/yangwebrtc/YangH264RecvTrack.cpp \ + src/yangwebrtc/YangH264RtpEncode.cpp \ + src/yangwebrtc/YangH265RecvTrack.cpp \ + src/yangwebrtc/YangH265RtpEncode.cpp \ + src/yangwebrtc/YangMediaDesc.cpp \ + src/yangwebrtc/YangRecvTrack.cpp \ + src/yangwebrtc/YangRtcAudioRecvTrack.cpp \ + src/yangwebrtc/YangRtcContext.cpp \ + src/yangwebrtc/YangRtcDtls.cpp \ + src/yangwebrtc/YangRtcPlayStream.cpp \ + src/yangwebrtc/YangRtcPublishStream.cpp \ + src/yangwebrtc/YangRtcSdp.cpp \ + src/yangwebrtc/YangRtcSession.cpp \ + src/yangwebrtc/YangRtcStun.cpp \ + src/yangwebrtc/YangSSRCInfo.cpp \ + src/yangwebrtc/YangSrsRtcHandleImpl.cpp \ + src/yangwebrtc/YangSrsSdp.cpp \ + src/yangwebrtc/YangUdpHandle.cpp \ + src/yangwebrtc/YangVideoRecvTrack.cpp + + +HEADERS += \ + src/yangaudiodev/YangAudioCaptureHandle.h \ + src/yangaudiodev/YangCaptureCallback.h \ + src/yangaudiodev/linux/YangAlsaDeviceHandle.h \ + src/yangaudiodev/linux/YangAlsaHandle.h \ + src/yangaudiodev/linux/YangAudioCaptureImpl.h \ + src/yangaudiodev/linux/YangAudioPlayAlsa.h \ + src/yangaudiodev/win/YangAudioApiCapture.h \ + src/yangaudiodev/win/YangRecAudioCaptureHandle.h \ + src/yangaudiodev/win/YangWinAudioApi.h \ + src/yangaudiodev/win/YangWinAudioApiAec.h \ + src/yangaudiodev/win/YangWinAudioApiCapture.h \ + src/yangaudiodev/win/YangWinAudioApiDevice.h \ + src/yangaudiodev/win/YangWinAudioApiRender.h \ + src/yangaudiodev/win/YangWinAudioCapture.h \ + src/yangaudiodev/win/YangWinAudioCaptureHandle.h \ + src/yangaudiodev/win/YangWinAudioDevice.h \ + src/yangaudiodev/win/YangWinRecordAudioCapture.h \ + src/yangavutil/YangAecSpeex.h \ + src/yangavutil/YangImageConvert.h \ + src/yangavutil/YangPreProcessSpeex.h \ + src/yangcapture/YangDXGIManager.h \ + src/yangcapture/YangScreenCaptureImpl.h \ + src/yangcapture/YangScreenShare.h \ + src/yangcapture/YangVideoCaptureHandle.h \ + src/yangcapture/YangVideoCaptureImpl.h \ + src/yangcapture/YangVideoDeviceQuery.h \ + src/yangcapture/win/YangVideoSrc.h \ + src/yangcapture/win/YangWinVideoCapture.h \ + src/yangcapture/win/YangWinVideoCaptureHandle.h \ + src/yangdecoder/YangAudioDecoderAac.h \ + src/yangdecoder/YangAudioDecoderOpus.h \ + src/yangdecoder/YangAudioDecoderSpeex.h \ + src/yangdecoder/YangH2645VideoDecoderFfmpeg.h \ + src/yangdecoder/YangH264Dec.h \ + src/yangdecoder/YangH264DecoderSoft.h \ + src/yangdecoder/YangH264DecoderSoftFactory.h \ + src/yangdecoder/YangH264Header.h \ + src/yangdecoder/YangH264Header1.h \ + src/yangdecoder/YangHeaderParseFfmpeg.h \ + src/yangdecoder/YangVideoDecoderIntel.h \ + src/yangencoder/YangAudioEncoderAac.h \ + src/yangencoder/YangAudioEncoderMp3.h \ + src/yangencoder/YangAudioEncoderOpus.h \ + src/yangencoder/YangAudioEncoderSpeex.h \ + src/yangencoder/YangFfmpegEncoderMeta.h \ + src/yangencoder/YangH264EncHeader.h \ + src/yangencoder/YangH264EncoderIntel.h \ + src/yangencoder/YangH264EncoderIntel1.h \ + src/yangencoder/YangH264EncoderMeta.h \ + src/yangencoder/YangH264EncoderSoft.h \ + src/yangencoder/YangH265EncoderMeta.h \ + src/yangencoder/YangH265EncoderSoft.h \ + src/yangencoder/YangVideoEncoderFfmpeg.h \ + src/yangencoder/lame.h \ + src/yangplayer/YangPlayerHandleImpl.h \ + src/yangplayer/YangRtcReceive.h \ + src/yangpush/YangPushEncoder.h \ + src/yangpush/YangPushHandleImpl.h \ + src/yangpush/YangPushMessageHandle.h \ + src/yangpush/YangSendVideoImpl.h \ + src/yangrecord/YangRecordHandle.h \ + src/yangrtmp/YangRtmpBase1.h \ + src/yangrtp/YangAudioPayload.h \ + src/yangrtp/YangCodecPayload.h \ + src/yangrtp/YangMediaPayloadType.h \ + src/yangrtp/YangMixQueue.h \ + src/yangrtp/YangPublishNackBuffer.h \ + src/yangrtp/YangRedPayload.h \ + src/yangrtp/YangRtcp.h \ + src/yangrtp/YangRtcpApp.h \ + src/yangrtp/YangRtcpCommon.h \ + src/yangrtp/YangRtcpCompound.h \ + src/yangrtp/YangRtcpNack.h \ + src/yangrtp/YangRtcpPli.h \ + src/yangrtp/YangRtcpPsfbCommon.h \ + src/yangrtp/YangRtcpRR.h \ + src/yangrtp/YangRtcpRpsi.h \ + src/yangrtp/YangRtcpSR.h \ + src/yangrtp/YangRtcpSli.h \ + src/yangrtp/YangRtcpTWCC.h \ + src/yangrtp/YangRtcpXr.h \ + src/yangrtp/YangRtpBuffer.h \ + src/yangrtp/YangRtpFUAPayload.h \ + src/yangrtp/YangRtpFUAPayload2.h \ + src/yangrtp/YangRtpHeader.h \ + src/yangrtp/YangRtpNackForReceiver.h \ + src/yangrtp/YangRtpPacket.h \ + src/yangrtp/YangRtpPlayNackBuffer.h \ + src/yangrtp/YangRtpRawNALUs.h \ + src/yangrtp/YangRtpRawPayload.h \ + src/yangrtp/YangRtpRingBuffer.h \ + src/yangrtp/YangRtpSTAPPayload.h \ + src/yangrtp/YangRtxPayloadDes.h \ + src/yangrtp/YangVideoPayload.h \ + src/yangstream/YangStreamPlay.h \ + src/yangstream/YangStreamRtc.h \ + src/yangstream/YangStreamRtmp.h \ + src/yangstream/YangStreamSrt.h \ + src/yangutil/YangWebsocketImpl.h \ + src/yangwebrtc/YangH264RecvTrack.h \ + src/yangwebrtc/YangH264RtpEncode.h \ + src/yangwebrtc/YangH265RecvTrack.h \ + src/yangwebrtc/YangH265RtpEncode.h \ + src/yangwebrtc/YangLocalH264Sdp.h \ + src/yangwebrtc/YangLocalH265Sdp.h \ + src/yangwebrtc/YangMediaDesc.h \ + src/yangwebrtc/YangRecvTrack.h \ + src/yangwebrtc/YangRtcAudioRecvTrack.h \ + src/yangwebrtc/YangRtcContext.h \ + src/yangwebrtc/YangRtcDtls.h \ + src/yangwebrtc/YangRtcPlayStream.h \ + src/yangwebrtc/YangRtcPublishStream.h \ + src/yangwebrtc/YangRtcSdp.h \ + src/yangwebrtc/YangRtcSession.h \ + src/yangwebrtc/YangRtcSessionI.h \ + src/yangwebrtc/YangRtcStun.h \ + src/yangwebrtc/YangSSRCInfo.h \ + src/yangwebrtc/YangSrsRtcHandleImpl.h \ + src/yangwebrtc/YangUdpHandle.h \ + src/yangwebrtc/YangVideoRecvTrack.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target diff --git a/thirdparty/include/curl/.gitignore b/thirdparty/include/curl/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..555795fae21de037455ff25af019027ccf8bcf41 --- /dev/null +++ b/thirdparty/include/curl/.gitignore @@ -0,0 +1,3 @@ +curlver.h.dist +stamp-h2 +stamp-h3 diff --git a/thirdparty/include/curl/Makefile.am b/thirdparty/include/curl/Makefile.am new file mode 100755 index 0000000000000000000000000000000000000000..e77273717de9d7818dcb8c7dcd68210af993c194 --- /dev/null +++ b/thirdparty/include/curl/Makefile.am @@ -0,0 +1,39 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h options.h + +pkgincludedir= $(includedir)/curl + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +if CURLDEBUG +# for debug builds, we scan the sources on all regular make invokes +all-local: checksrc +endif diff --git a/thirdparty/include/curl/curl.h b/thirdparty/include/curl/curl.h new file mode 100755 index 0000000000000000000000000000000000000000..97de8c88ae00d5fd9b985842ff3f5240ae14de40 --- /dev/null +++ b/thirdparty/include/curl/curl.h @@ -0,0 +1,3066 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define CURL_WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ + !defined(__SYMBIAN32__) +#define CURL_WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || defined(AMIGA) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +typedef enum { + CURLPX_OK, + CURLPX_BAD_ADDRESS_TYPE, + CURLPX_BAD_VERSION, + CURLPX_CLOSED, + CURLPX_GSSAPI, + CURLPX_GSSAPI_PERMSG, + CURLPX_GSSAPI_PROTECTION, + CURLPX_IDENTD, + CURLPX_IDENTD_DIFFER, + CURLPX_LONG_HOSTNAME, + CURLPX_LONG_PASSWD, + CURLPX_LONG_USER, + CURLPX_NO_AUTH, + CURLPX_RECV_ADDRESS, + CURLPX_RECV_AUTH, + CURLPX_RECV_CONNECT, + CURLPX_RECV_REQACK, + CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + CURLPX_REPLY_COMMAND_NOT_SUPPORTED, + CURLPX_REPLY_CONNECTION_REFUSED, + CURLPX_REPLY_GENERAL_SERVER_FAILURE, + CURLPX_REPLY_HOST_UNREACHABLE, + CURLPX_REPLY_NETWORK_UNREACHABLE, + CURLPX_REPLY_NOT_ALLOWED, + CURLPX_REPLY_TTL_EXPIRED, + CURLPX_REPLY_UNASSIGNED, + CURLPX_REQUEST_FAILED, + CURLPX_RESOLVE_HOST, + CURLPX_SEND_AUTH, + CURLPX_SEND_CONNECT, + CURLPX_SEND_REQUEST, + CURLPX_UNKNOWN_FAIL, + CURLPX_UNKNOWN_MODE, + CURLPX_USER_REJECTED, + CURLPX_LAST /* never use */ +} CURLproxycode; + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. */ +#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3) + +/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. */ +#define CURLSSLOPT_NATIVE_CA (1<<4) + +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + + +struct curl_hstsentry { + char *name; + size_t namelen; + unsigned int includeSubDomains:1; + char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */ +}; + +struct curl_index { + size_t index; /* the provided entry's "index" or count */ + size_t total; /* total number of entries to save */ +}; + +typedef enum { + CURLSTS_OK, + CURLSTS_DONE, + CURLSTS_FAIL +} CURLSTScode; + +typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy, + struct curl_hstsentry *e, + void *userp); +typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, + struct curl_hstsentry *e, + struct curl_index *i, + void *userp); + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +#define CURLHSTS_ENABLE (long)(1<<0) +#define CURLHSTS_READONLYFILE (long)(1<<1) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_MQTT (1<<28) +#define CURLPROTO_GOPHERS (1<<29) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 +#define CURLOPTTYPE_BLOB 40000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu + +/* CURLOPT aliases that make no run-time difference */ + +/* 'char *' argument to a string with a trailing zero */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40), + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57), +#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72), + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129), + + CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130), + CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182), + + /* set the SSH knownhost file name to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210), + + /* Set the name servers to use for DNS resolution */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorisation identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290), + + /* the private SSL-certificate as a "blob" */ + CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291), + CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292), + CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293), + CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294), + CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295), + + /* Issuer certificate for proxy */ + CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296), + CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297), + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html + */ + CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), + + /* HSTS bitmask */ + CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299), + /* HSTS file name */ + CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300), + + /* HSTS read callback */ + CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301), + CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302), + + /* HSTS write callback */ + CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), + CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + + /* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback. + Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */ + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a null-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime curl_mime; /* Mime context. */ +typedef struct curl_mimepart curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + CURLFORM_NOTHING, /********* the first one is unused ************/ + CURLFORM_COPYNAME, + CURLFORM_PTRNAME, + CURLFORM_NAMELENGTH, + CURLFORM_COPYCONTENTS, + CURLFORM_PTRCONTENTS, + CURLFORM_CONTENTSLENGTH, + CURLFORM_FILECONTENT, + CURLFORM_ARRAY, + CURLFORM_OBSOLETE, + CURLFORM_FILE, + + CURLFORM_BUFFER, + CURLFORM_BUFFERPTR, + CURLFORM_BUFFERLENGTH, + + CURLFORM_CONTENTTYPE, + CURLFORM_CONTENTHEADER, + CURLFORM_FILENAME, + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM, + CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +struct curl_ssl_backend { + curl_sslbackend id; + const char *name; +}; +typedef struct curl_ssl_backend curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, + CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, + + CURLINFO_LASTONE = 60 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_SIXTH, + CURLVERSION_SEVENTH, + CURLVERSION_EIGHTH, + CURLVERSION_NINTH, + CURLVERSION_TENTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_TENTH + +struct curl_version_info_data { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + const char *cainfo; /* the built-in default CURLOPT_CAINFO, might + be NULL */ + const char *capath; /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ +}; +typedef struct curl_version_info_data curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ +#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" +#include "options.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* CURLINC_CURL_H */ diff --git a/thirdparty/include/curl/curlver.h b/thirdparty/include/curl/curlver.h new file mode 100755 index 0000000000000000000000000000000000000000..75fa93ca752447e502e5c91a655bc9b2bb333564 --- /dev/null +++ b/thirdparty/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.77.0-DEV" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 77 +#define LIBCURL_VERSION_PATCH 0 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074d00 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "[unreleased]" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/thirdparty/include/curl/easy.h b/thirdparty/include/curl/easy.h new file mode 100755 index 0000000000000000000000000000000000000000..2dbfb26b5b7f4e398ec32215a1bf8455d81d1914 --- /dev/null +++ b/thirdparty/include/curl/easy.h @@ -0,0 +1,123 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Flag bits in the curl_blob struct: */ +#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */ +#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */ + +struct curl_blob { + void *data; + size_t len; + unsigned int flags; /* bit 0 is defined, the rest are reserved and should be + left zeroes */ +}; + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/curl/mprintf.h b/thirdparty/include/curl/mprintf.h new file mode 100755 index 0000000000000000000000000000000000000000..3549552dba63062f8904770055a5ed781517c48f --- /dev/null +++ b/thirdparty/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/thirdparty/include/curl/multi.h b/thirdparty/include/curl/multi.h new file mode 100755 index 0000000000000000000000000000000000000000..37f9829b3b3191182d46bd5fa847c7fedb39524e --- /dev/null +++ b/thirdparty/include/curl/multi.h @@ -0,0 +1,456 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a null-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +typedef enum { + /* This is the socket callback function pointer */ + CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), + + /* This is the timer callback function pointer */ + CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7), + + /* maximum number of requests in a pipeline */ + CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10), + + /* a list of site names(+port) that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11), + + /* a list of server types that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13), + + /* This is the server push callback function pointer */ + CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. + * + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 +#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */ + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/thirdparty/include/curl/options.h b/thirdparty/include/curl/options.h new file mode 100755 index 0000000000000000000000000000000000000000..14373b551c795024a133ec43097d3aa5e53417d2 --- /dev/null +++ b/thirdparty/include/curl/options.h @@ -0,0 +1,68 @@ +#ifndef CURLINC_OPTIONS_H +#define CURLINC_OPTIONS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + CURLOT_LONG, /* long (a range of values) */ + CURLOT_VALUES, /* (a defined set or bitmask) */ + CURLOT_OFF_T, /* curl_off_t (a range of values) */ + CURLOT_OBJECT, /* pointer (void *) */ + CURLOT_STRING, /* (char * to zero terminated buffer) */ + CURLOT_SLIST, /* (struct curl_slist *) */ + CURLOT_CBPTR, /* (void * passed as-is to a callback) */ + CURLOT_BLOB, /* blob (struct curl_blob *) */ + CURLOT_FUNCTION /* function pointer */ +} curl_easytype; + +/* Flag bits */ + +/* "alias" means it is provided for old programs to remain functional, + we prefer another name */ +#define CURLOT_FLAG_ALIAS (1<<0) + +/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size + to use for curl_easy_setopt() for the given id */ +struct curl_easyoption { + const char *name; + CURLoption id; + curl_easytype type; + unsigned int flags; +}; + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_name(const char *name); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_id (CURLoption id); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_next(const struct curl_easyoption *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif +#endif /* CURLINC_OPTIONS_H */ diff --git a/thirdparty/include/curl/stdcheaders.h b/thirdparty/include/curl/stdcheaders.h new file mode 100755 index 0000000000000000000000000000000000000000..60596c7568e2d8710d4f7ae9072deca8d7800f39 --- /dev/null +++ b/thirdparty/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/thirdparty/include/curl/system.h b/thirdparty/include/curl/system.h new file mode 100755 index 0000000000000000000000000000000000000000..faf8fcf84fcc48a94c1f13f4ba58089880fe9e94 --- /dev/null +++ b/thirdparty/include/curl/system.h @@ -0,0 +1,504 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# if defined(__e2k__) /* MCST eLbrus C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define CURLINC_OFF_T_C_HLPR2(x) x +# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/thirdparty/include/curl/typecheck-gcc.h b/thirdparty/include/curl/typecheck-gcc.h new file mode 100755 index 0000000000000000000000000000000000000000..34d0267ed95ad568630691f1eebdd824f3038b83 --- /dev/null +++ b/thirdparty/include/curl/typecheck-gcc.h @@ -0,0 +1,705 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(curlcheck_long_option(_curl_opt)) \ + if(!curlcheck_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(_curl_opt)) \ + if(!curlcheck_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(_curl_opt)) \ + if(!curlcheck_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(curlcheck_write_cb_option(_curl_opt)) \ + if(!curlcheck_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(_curl_opt)) \ + if(!curlcheck_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(curlcheck_cb_data_option(_curl_opt)) \ + if(!curlcheck_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(_curl_opt)) \ + if(!curlcheck_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(_curl_opt)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(curlcheck_string_info(_curl_info)) \ + if(!curlcheck_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(_curl_info)) \ + if(!curlcheck_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(_curl_info)) \ + if(!curlcheck_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(curlcheck_certinfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ + }) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +CURLWARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +CURLWARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +CURLWARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +CURLWARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +CURLWARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +CURLWARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB)) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_HSTS || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_ISSUERCERT || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_AWS_SIGV4 || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + (option) == CURLOPT_SSL_EC_CURVES || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_HSTSREADDATA || \ + (option) == CURLOPT_HSTSWRITEDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \ + (info) != CURLINFO_PRIVATE) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), _curl_read_callback1) || \ + curlcheck_cb_compatible((expr), _curl_read_callback2) || \ + curlcheck_cb_compatible((expr), _curl_read_callback3) || \ + curlcheck_cb_compatible((expr), _curl_read_callback4) || \ + curlcheck_cb_compatible((expr), _curl_read_callback5) || \ + curlcheck_cb_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), _curl_write_callback1) || \ + curlcheck_cb_compatible((expr), _curl_write_callback2) || \ + curlcheck_cb_compatible((expr), _curl_write_callback3) || \ + curlcheck_cb_compatible((expr), _curl_write_callback4) || \ + curlcheck_cb_compatible((expr), _curl_write_callback5) || \ + curlcheck_cb_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback1) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback1) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback2) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback3) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback4) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback5) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback6) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback7) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback1) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback2) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback3) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback1) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/thirdparty/include/curl/urlapi.h b/thirdparty/include/curl/urlapi.h new file mode 100755 index 0000000000000000000000000000000000000000..7343cb659ecb9b03d63c3253e1fe7d1565257ac7 --- /dev/null +++ b/thirdparty/include/curl/urlapi.h @@ -0,0 +1,125 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/thirdparty/include/faac.h b/thirdparty/include/faac.h new file mode 100755 index 0000000000000000000000000000000000000000..688c2653fbb77988a8df0ce628ef08922da08629 --- /dev/null +++ b/thirdparty/include/faac.h @@ -0,0 +1,101 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: faac.h,v 1.38 2012/03/01 18:34:17 knik Exp $ + */ + +#ifndef _FAAC_H_ +#define _FAAC_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#if !defined(FAACAPI) && defined(__GNUC__) && (__GNUC__ >= 4) +# if defined(_WIN32) +# define FAACAPI __stdcall __declspec(dllexport) +# else +# define FAACAPI __attribute__((visibility("default"))) +# endif +#endif +#ifndef FAACAPI +# define FAACAPI +#endif + +#pragma pack(push, 1) + +typedef struct { + void *ptr; + char *name; +} +psymodellist_t; + +#include "faaccfg.h" + + +typedef void *faacEncHandle; + +#ifndef HAVE_INT32_T +typedef signed int int32_t; +#endif + +/* + Allows an application to get FAAC version info. This is intended + purely for informative purposes. + + Returns FAAC_CFG_VERSION. +*/ +int FAACAPI faacEncGetVersion(char **faac_id_string, + char **faac_copyright_string); + + +faacEncConfigurationPtr FAACAPI + faacEncGetCurrentConfiguration(faacEncHandle hEncoder); + + +int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder, + faacEncConfigurationPtr config); + + +faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, + unsigned int numChannels, + unsigned long *inputSamples, + unsigned long *maxOutputBytes + ); + +int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, unsigned char **ppBuffer, + unsigned long *pSizeOfDecoderSpecificInfo); + + +int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput, + unsigned char *outputBuffer, + unsigned int bufferSize); + + +int FAACAPI faacEncClose(faacEncHandle hEncoder); + + + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _FAAC_H_ */ diff --git a/thirdparty/include/faaccfg.h b/thirdparty/include/faaccfg.h new file mode 100755 index 0000000000000000000000000000000000000000..242389793a82f64010eb976835414db7575043b5 --- /dev/null +++ b/thirdparty/include/faaccfg.h @@ -0,0 +1,134 @@ +/* + * FAAC - Freeware Advanced Audio Coder + * Copyright (C) 2001 Menno Bakker + * + * This library 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. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: faaccfg.h,v 1.3 2004/07/04 12:12:05 corrados Exp $ + */ + +#ifndef _FAACCFG_H_ +#define _FAACCFG_H_ + +#define FAAC_CFG_VERSION 105 + +/* MPEG ID's */ +#define MPEG2 1 +#define MPEG4 0 + +/* AAC object types */ +#define MAIN 1 +#define LOW 2 +#define SSR 3 +#define LTP 4 + +/* Input Formats */ +#define FAAC_INPUT_NULL 0 +#define FAAC_INPUT_16BIT 1 +#define FAAC_INPUT_24BIT 2 +#define FAAC_INPUT_32BIT 3 +#define FAAC_INPUT_FLOAT 4 + +#define SHORTCTL_NORMAL 0 +#define SHORTCTL_NOSHORT 1 +#define SHORTCTL_NOLONG 2 + +enum stream_format +{ + RAW_STREAM = 0, + ADTS_STREAM = 1, +}; + +enum {JOINT_NONE = 0, JOINT_MS, JOINT_IS}; + +#pragma pack(push, 1) +typedef struct faacEncConfiguration +{ + /* config version */ + int version; + + /* library version */ + char *name; + + /* copyright string */ + char *copyright; + + /* MPEG version, 2 or 4 */ + unsigned int mpegVersion; + + /* AAC object type */ + unsigned int aacObjectType; + + union { + /* Joint coding mode */ + unsigned int jointmode; + /* compatibility alias */ + unsigned int allowMidside; + }; + + /* Use one of the channels as LFE channel */ + unsigned int useLfe; + + /* Use Temporal Noise Shaping */ + unsigned int useTns; + + /* bitrate / channel of AAC file */ + unsigned long bitRate; + + /* AAC file frequency bandwidth */ + unsigned int bandWidth; + + /* Quantizer quality */ + unsigned long quantqual; + + /* Bitstream output format (0 = Raw; 1 = ADTS) */ + unsigned int outputFormat; + + /* psychoacoustic model list */ + psymodellist_t *psymodellist; + + /* selected index in psymodellist */ + unsigned int psymodelidx; + + /* + PCM Sample Input Format + 0 FAAC_INPUT_NULL invalid, signifies a misconfigured config + 1 FAAC_INPUT_16BIT native endian 16bit + 2 FAAC_INPUT_24BIT native endian 24bit in 24 bits (not implemented) + 3 FAAC_INPUT_32BIT native endian 24bit in 32 bits (DEFAULT) + 4 FAAC_INPUT_FLOAT 32bit floating point + */ + unsigned int inputFormat; + + /* block type enforcing (SHORTCTL_NORMAL/SHORTCTL_NOSHORT/SHORTCTL_NOLONG) */ + int shortctl; + + /* + Channel Remapping + + Default 0, 1, 2, 3 ... 63 (64 is MAX_CHANNELS in coder.h) + + WAVE 4.0 2, 0, 1, 3 + WAVE 5.0 2, 0, 1, 3, 4 + WAVE 5.1 2, 0, 1, 4, 5, 3 + AIFF 5.1 2, 0, 3, 1, 4, 5 + */ + int channel_map[64]; + int pnslevel; +} faacEncConfiguration, *faacEncConfigurationPtr; + +#pragma pack(pop) + +#endif /* _FAACCFG_H_ */ diff --git a/thirdparty/include/faad.h b/thirdparty/include/faad.h new file mode 100755 index 0000000000000000000000000000000000000000..72f4072803c494453aafc3d357994d02aa7568b8 --- /dev/null +++ b/thirdparty/include/faad.h @@ -0,0 +1,35 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** 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 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: faad.h,v 1.51 2007/11/01 12:33:29 menno Exp $ +**/ + +/* warn people for update */ +#pragma message("please update faad2 include filename and function names!") + +/* Backwards compatible link */ +#include "neaacdec.h" diff --git a/thirdparty/include/json/allocator.h b/thirdparty/include/json/allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..0f5c224b9d72f74ccb590e9cbd2b3f85ec187faf --- /dev/null +++ b/thirdparty/include/json/allocator.h @@ -0,0 +1,89 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_ALLOCATOR_H_INCLUDED +#define JSON_ALLOCATOR_H_INCLUDED + +#include +#include + +#pragma pack(push, 8) + +namespace Json { +template class SecureAllocator { +public: + // Type definitions + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + /** + * Allocate memory for N items using the standard allocator. + */ + pointer allocate(size_type n) { + // allocate using "global operator new" + return static_cast(::operator new(n * sizeof(T))); + } + + /** + * Release memory which was allocated for N items at pointer P. + * + * The memory block is filled with zeroes before being released. + * The pointer argument is tagged as "volatile" to prevent the + * compiler optimizing out this critical step. + */ + void deallocate(volatile pointer p, size_type n) { + std::memset(p, 0, n * sizeof(T)); + // free using "global operator delete" + ::operator delete(p); + } + + /** + * Construct an item in-place at pointer P. + */ + template void construct(pointer p, Args&&... args) { + // construct using "placement new" and "perfect forwarding" + ::new (static_cast(p)) T(std::forward(args)...); + } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + pointer address(reference x) const { return std::addressof(x); } + + const_pointer address(const_reference x) const { return std::addressof(x); } + + /** + * Destroy an item in-place at pointer P. + */ + void destroy(pointer p) { + // destroy using "explicit destructor" + p->~T(); + } + + // Boilerplate + SecureAllocator() {} + template SecureAllocator(const SecureAllocator&) {} + template struct rebind { using other = SecureAllocator; }; +}; + +template +bool operator==(const SecureAllocator&, const SecureAllocator&) { + return true; +} + +template +bool operator!=(const SecureAllocator&, const SecureAllocator&) { + return false; +} + +} // namespace Json + +#pragma pack(pop) + +#endif // JSON_ALLOCATOR_H_INCLUDED diff --git a/thirdparty/include/json/assertions.h b/thirdparty/include/json/assertions.h new file mode 100644 index 0000000000000000000000000000000000000000..666fa7f542ccef943baa133f3bbf9e8b19845104 --- /dev/null +++ b/thirdparty/include/json/assertions.h @@ -0,0 +1,61 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_ASSERTIONS_H_INCLUDED +#define JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +#define JSON_ASSERT(condition) \ + do { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } while (0) + +#define JSON_FAIL_MESSAGE(message) \ + do { \ + OStringStream oss; \ + oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } while (0) + +#else // JSON_USE_EXCEPTION + +#define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +#define JSON_FAIL_MESSAGE(message) \ + { \ + OStringStream oss; \ + oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + do { \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } \ + } while (0) + +#endif // JSON_ASSERTIONS_H_INCLUDED diff --git a/thirdparty/include/json/config.h b/thirdparty/include/json/config.h new file mode 100644 index 0000000000000000000000000000000000000000..6359273a2228f822b1e9634a9221cc82f18bd491 --- /dev/null +++ b/thirdparty/include/json/config.h @@ -0,0 +1,150 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include +#include +#include +#include +#include +#include +#include + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +// Temporary, tracked for removal with issue #982. +#ifndef JSON_USE_NULLREF +#define JSON_USE_NULLREF 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +// Export macros for DLL visibility +#if defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#elif defined(__GNUC__) || defined(__clang__) +#define JSON_API __attribute__((visibility("default"))) +#endif // if defined(_MSC_VER) + +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_DLL_BUILD + +#if !defined(JSON_API) +#define JSON_API +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#error \ + "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +// As recommended at +// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 +extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...); +#define jsoncpp_snprintf msvc_pre1900_c99_snprintf +#else +#define jsoncpp_snprintf std::snprintf +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. +// C++11 should be used directly in JSONCPP. +#define JSONCPP_OVERRIDE override + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates + // MSVC) +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif // __clang__ || __GNUC__ || _MSC_VER + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "allocator.h" +#include "version.h" + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +using Int = int; +using UInt = unsigned int; +#if defined(JSON_NO_INT64) +using LargestInt = int; +using LargestUInt = unsigned int; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +using Int64 = __int64; +using UInt64 = unsigned __int64; +#else // if defined(_MSC_VER) // Other platforms, use long long +using Int64 = int64_t; +using UInt64 = uint64_t; +#endif // if defined(_MSC_VER) +using LargestInt = Int64; +using LargestUInt = UInt64; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) + +template +using Allocator = + typename std::conditional, + std::allocator>::type; +using String = std::basic_string, Allocator>; +using IStringStream = + std::basic_istringstream; +using OStringStream = + std::basic_ostringstream; +using IStream = std::istream; +using OStream = std::ostream; +} // namespace Json + +// Legacy names (formerly macros). +using JSONCPP_STRING = Json::String; +using JSONCPP_ISTRINGSTREAM = Json::IStringStream; +using JSONCPP_OSTRINGSTREAM = Json::OStringStream; +using JSONCPP_ISTREAM = Json::IStream; +using JSONCPP_OSTREAM = Json::OStream; + +#endif // JSON_CONFIG_H_INCLUDED diff --git a/thirdparty/include/json/forwards.h b/thirdparty/include/json/forwards.h new file mode 100644 index 0000000000000000000000000000000000000000..affe33a7f9ec662ede90eef7dd200da89aa7dede --- /dev/null +++ b/thirdparty/include/json/forwards.h @@ -0,0 +1,43 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class StreamWriter; +class StreamWriterBuilder; +class Writer; +class FastWriter; +class StyledWriter; +class StyledStreamWriter; + +// reader.h +class Reader; +class CharReader; +class CharReaderBuilder; + +// json_features.h +class Features; + +// value.h +using ArrayIndex = unsigned int; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED diff --git a/thirdparty/include/json/json.h b/thirdparty/include/json/json.h new file mode 100644 index 0000000000000000000000000000000000000000..5c776a1609e6111bd156195956837cc762410ee2 --- /dev/null +++ b/thirdparty/include/json/json.h @@ -0,0 +1,15 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_JSON_H_INCLUDED +#define JSON_JSON_H_INCLUDED + +#include "config.h" +#include "json_features.h" +#include "reader.h" +#include "value.h" +#include "writer.h" + +#endif // JSON_JSON_H_INCLUDED diff --git a/thirdparty/include/json/json_features.h b/thirdparty/include/json/json_features.h new file mode 100644 index 0000000000000000000000000000000000000000..7c7e9f5de15e259eba132de8efa5d80b78f9f92c --- /dev/null +++ b/thirdparty/include/json/json_features.h @@ -0,0 +1,61 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FEATURES_H_INCLUDED +#define JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_{true}; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_{false}; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_{false}; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_{false}; +}; + +} // namespace Json + +#pragma pack(pop) + +#endif // JSON_FEATURES_H_INCLUDED diff --git a/thirdparty/include/json/reader.h b/thirdparty/include/json/reader.h new file mode 100644 index 0000000000000000000000000000000000000000..9175466089e33b384e64d0615a24b6a3e62fb87b --- /dev/null +++ b/thirdparty/include/json/reader.h @@ -0,0 +1,403 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_READER_H_INCLUDED +#define JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Unserialize a JSON document into a + * Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ + +class JSONCPP_DEPRECATED( + "Use CharReader and CharReaderBuilder instead.") JSON_API Reader { +public: + using Char = char; + using Location = const Char*; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + */ + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + + /** \brief Constructs a Reader allowing all features for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set for parsing. + */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * + * \param document UTF-8 encoded string containing the document + * to read. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool parse(const std::string& document, Value& root, + bool collectComments = true); + + /** \brief Read a Value from a JSON + * document. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded + * string of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string + * of the document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(IStream& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + String getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. + */ + String getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured errors encountered while parsing. + * + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate multiple + * errors. This can occur if the parser recovers from a non-fatal parse + * error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + + /** \brief Add a semantic error message. + * + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the Value + * offset exceeds the document size. + */ + bool pushError(const Value& value, const String& message); + + /** \brief Add a semantic error message with extra context. + * + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const String& message, const Value& extra); + + /** \brief Return whether there are any errors. + * + * \return \c true if there are no errors to report \c false if errors have + * occurred. + */ + bool good() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + String message_; + Location extra_; + }; + + using Errors = std::deque; + + bool readToken(Token& token); + void skipSpaces(); + bool match(const Char* pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, String& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static bool containsNewLine(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); + + using Nodes = std::stack; + Nodes nodes_; + Errors errors_; + String document_; + Location begin_{}; + Location end_{}; + Location current_{}; + Location lastValueEnd_{}; + Value* lastValue_{}; + String commentsBefore_; + Features features_; + bool collectComments_{}; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() = default; + /** \brief Read a Value from a JSON + * document. The document must be a UTF-8 encoded string containing the + * document to read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string + * of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + * document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it was + * successfully parsed. + * \param[out] errs Formatted error messages (if not NULL) a user + * friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; + + class JSON_API Factory { + public: + virtual ~Factory() = default; + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + * + * Usage: + * \code + * using namespace Json; + * CharReaderBuilder builder; + * builder["collectComments"] = false; + * Value value; + * String errs; + * bool ok = parseFromStream(builder, std::cin, &value, &errs); + * \endcode + */ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + * These are case-sensitive. + * Available settings (case-sensitive): + * - `"collectComments": false or true` + * - true to collect comment and allow writing them back during + * serialization, false to discard comments. This parameter is ignored + * if allowComments is false. + * - `"allowComments": false or true` + * - true if comments are allowed. + * - `"allowTrailingCommas": false or true` + * - true if trailing commas in objects and arrays are allowed. + * - `"strictRoot": false or true` + * - true if root must be either an array or an object value + * - `"allowDroppedNullPlaceholders": false or true` + * - true if dropped null placeholders are allowed. (See + * StreamWriterBuilder.) + * - `"allowNumericKeys": false or true` + * - true if numeric object keys are allowed. + * - `"allowSingleQuotes": false or true` + * - true if '' are allowed for strings (both keys and values) + * - `"stackLimit": integer` + * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an + * exception. + * - This is a security issue (seg-faults caused by deeply nested JSON), so + * the default is low. + * - `"failIfExtra": false or true` + * - If true, `parse()` returns false when extra non-whitespace trails the + * JSON value in the input string. + * - `"rejectDupKeys": false or true` + * - If true, `parse()` returns false when a key is duplicated within an + * object. + * - `"allowSpecialFloats": false or true` + * - If true, special float values (NaNs and infinities) are allowed and + * their values are lossfree restorable. + * + * You can examine 'settings_` yourself to see the defaults. You can also + * write and read them just like any JSON Value. + * \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + ~CharReaderBuilder() override; + + CharReader* newCharReader() const override; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](const String& key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root, + String* errs); + +/** \brief Read from 'sin' into 'root'. + * + * Always keep comments from the input JSON. + * + * This can be used to read a file into a particular sub-object. + * For example: + * \code + * Json::Value root; + * cin >> root["dir"]["file"]; + * cout << root; + * \endcode + * Result: + * \verbatim + * { + * "dir": { + * "file": { + * // The input stream JSON would be nested here. + * } + * } + * } + * \endverbatim + * \throw std::exception on parse error. + * \see Json::operator<<() + */ +JSON_API IStream& operator>>(IStream&, Value&); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_READER_H_INCLUDED diff --git a/thirdparty/include/json/value.h b/thirdparty/include/json/value.h new file mode 100644 index 0000000000000000000000000000000000000000..df1eba6acb2fe92b838c128a22d904dd17d63316 --- /dev/null +++ b/thirdparty/include/json/value.h @@ -0,0 +1,935 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_H_INCLUDED +#define JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) && _MSC_VER == 1800 +#define JSONCPP_NORETURN __declspec(noreturn) +#else +#define JSONCPP_NORETURN [[noreturn]] +#endif +#endif + +// Support for '= delete' with template declarations was a late addition +// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2 +// even though these declare themselves to be c++11 compilers. +#if !defined(JSONCPP_TEMPLATE_DELETE) +#if defined(__clang__) && defined(__apple_build_version__) +#if __apple_build_version__ <= 8000042 +#define JSONCPP_TEMPLATE_DELETE +#endif +#elif defined(__clang__) +#if __clang_major__ == 3 && __clang_minor__ <= 8 +#define JSONCPP_TEMPLATE_DELETE +#endif +#endif +#if !defined(JSONCPP_TEMPLATE_DELETE) +#define JSONCPP_TEMPLATE_DELETE = delete +#endif +#endif + +#include +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +#if JSON_USE_EXCEPTION +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(String msg); + ~Exception() noexcept override; + char const* what() const noexcept override; + +protected: + String msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(String const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(String const& msg); +}; +#endif + +/// used internally +JSONCPP_NORETURN void throwRuntimeError(String const& msg); +/// used internally +JSONCPP_NORETURN void throwLogicError(String const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignment takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of member keys of an object using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; + +public: + using Members = std::vector; + using iterator = ValueIterator; + using const_iterator = ValueConstIterator; + using UInt = Json::UInt; + using Int = Json::Int; +#if defined(JSON_HAS_INT64) + using UInt64 = Json::UInt64; + using Int64 = Json::Int64; +#endif // defined(JSON_HAS_INT64) + using LargestInt = Json::LargestInt; + using LargestUInt = Json::LargestUInt; + using ArrayIndex = Json::ArrayIndex; + + // Required for boost integration, e. g. BOOST_TEST + using value_type = std::string; + +#if JSON_USE_NULLREF + // Binary compatibility kludges, do not use. + static const Value& null; + static const Value& nullRef; +#endif + + // null and nullRef are deprecated, use this instead. + static Value const& nullSingleton(); + + /// Minimum signed integer value that can be stored in a Json::Value. + static constexpr LargestInt minLargestInt = + LargestInt(~(LargestUInt(-1) / 2)); + /// Maximum signed integer value that can be stored in a Json::Value. + static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); + /// Maximum unsigned integer value that can be stored in a Json::Value. + static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); + + /// Minimum signed int value that can be stored in a Json::Value. + static constexpr Int minInt = Int(~(UInt(-1) / 2)); + /// Maximum signed int value that can be stored in a Json::Value. + static constexpr Int maxInt = Int(UInt(-1) / 2); + /// Maximum unsigned int value that can be stored in a Json::Value. + static constexpr UInt maxUInt = UInt(-1); + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static constexpr UInt64 maxUInt64 = UInt64(-1); +#endif // defined(JSON_HAS_INT64) + /// Default precision for real value for string representation. + static constexpr UInt defaultRealPrecision = 17; + // The constant is hard-coded because some compiler have trouble + // converting Value::maxUInt64 to a double correctly (AIX/xlC). + // Assumes that UInt64 is a 64 bits integer. + static constexpr double maxUInt64AsDouble = 18446744073709551615.0; +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else +private: +#endif +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); + CZString(CZString&& other); + ~CZString(); + CZString& operator=(const CZString& other); + CZString& operator=(CZString&& other); + + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + // const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: + typedef std::map ObjectValues; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** + * \brief Create a default Value of the given type. + * + * This is a very useful constructor. + * To create an empty array, pass arrayValue. + * To create an empty object, pass objectValue. + * Another Value can then be set to this one by assignment. + * This is useful since clear() and resize() will not alter types. + * + * Examples: + * \code + * Json::Value null_value; // null + * Json::Value arr_value(Json::arrayValue); // [] + * Json::Value obj_value(Json::objectValue); // {} + * \endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** + * \brief Constructs a value from a static string. + * + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to + * this constructor. + * + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, which might be + * computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const String& value); + Value(bool value); + Value(std::nullptr_t ptr) = delete; + Value(const Value& other); + Value(Value&& other); + ~Value(); + + /// \note Overwrite existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(const Value& other); + Value& operator=(Value&& other); + + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + /// copy everything. + void copy(const Value& other); + /// copy values but leave comments and source offsets in place. + void copyPayload(const Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! +#if JSONCPP_USING_SECURE_MEMORY + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString +#endif + String asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString(char const** begin, char const** end) const; + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + /// The `as` and `is` member function templates and specializations. + template T as() const JSONCPP_TEMPLATE_DELETE; + template bool is() const JSONCPP_TEMPLATE_DELETE; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return !isNull() + explicit operator bool() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to newSize elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex newSize); + + //@{ + /// Access an array element (zero based index). If the array contains less + /// than index element, then null value are inserted in the array so that + /// its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + Value& operator[](int index); + //@} + + //@{ + /// Access an array element (zero based index). + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + const Value& operator[](int index) const; + //@} + + /// If the array contains at least index+1 elements, returns the element + /// value, otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + Value& append(Value&& value); + + /// \brief Insert value in array at specific index + bool insert(ArrayIndex index, const Value& newValue); + bool insert(ArrayIndex index, Value&& newValue); + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const String& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const String& key) const; + /** \brief Access an object value by name, create a null member if it does not + * exist. + * + * If the object has no entry for that name, then the member name used to + * store the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value get(const char* begin, const char* end, + const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const String& key, const Value& defaultValue) const; + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + void removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + void removeMember(const String& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + * + * Update 'removed' iff removed. + * \param key may contain embedded nulls. + * \return true iff removed (no exceptions) + */ + bool removeMember(String const& key, Value* removed); + /// Same as removeMember(String const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + * + * O(n) expensive operations. + * Update 'removed' iff removed. + * \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const String& key) const; + /// Same as isMember(String const& key)const + bool isMember(const char* begin, const char* end) const; + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(String const&) instead.") + void setComment(const char* comment, CommentPlacement placement) { + setComment(String(comment, strlen(comment)), placement); + } + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement) { + setComment(String(comment, len), placement); + } + /// Comments must be //... or /* ... */ + void setComment(String comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + String getComment(CommentPlacement placement) const; + + String toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(ptrdiff_t start); + void setOffsetLimit(ptrdiff_t limit); + ptrdiff_t getOffsetStart() const; + ptrdiff_t getOffsetLimit() const; + +private: + void setType(ValueType v) { + bits_.value_type_ = static_cast(v); + } + bool isAllocated() const { return bits_.allocated_; } + void setIsAllocated(bool v) { bits_.allocated_ = v; } + + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // if allocated_, ptr to { unsigned, char[] }. + ObjectValues* map_; + } value_; + + struct { + // Really a ValueType, but types should agree for bitfield packing. + unsigned int value_type_ : 8; + // Unless allocated_, string_ must be null-terminated. + unsigned int allocated_ : 1; + } bits_; + + class Comments { + public: + Comments() = default; + Comments(const Comments& that); + Comments(Comments&& that); + Comments& operator=(const Comments& that); + Comments& operator=(Comments&& that); + bool has(CommentPlacement slot) const; + String get(CommentPlacement slot) const; + void set(CommentPlacement slot, String comment); + + private: + using Array = std::array; + std::unique_ptr ptr_; + }; + Comments comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + ptrdiff_t start_; + ptrdiff_t limit_; +}; + +template <> inline bool Value::as() const { return asBool(); } +template <> inline bool Value::is() const { return isBool(); } + +template <> inline Int Value::as() const { return asInt(); } +template <> inline bool Value::is() const { return isInt(); } + +template <> inline UInt Value::as() const { return asUInt(); } +template <> inline bool Value::is() const { return isUInt(); } + +#if defined(JSON_HAS_INT64) +template <> inline Int64 Value::as() const { return asInt64(); } +template <> inline bool Value::is() const { return isInt64(); } + +template <> inline UInt64 Value::as() const { return asUInt64(); } +template <> inline bool Value::is() const { return isUInt64(); } +#endif + +template <> inline double Value::as() const { return asDouble(); } +template <> inline bool Value::is() const { return isDouble(); } + +template <> inline String Value::as() const { return asString(); } +template <> inline bool Value::is() const { return isString(); } + +/// These `as` specializations are type conversions, and do not have a +/// corresponding `is`. +template <> inline float Value::as() const { return asFloat(); } +template <> inline const char* Value::as() const { + return asCString(); +} + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(String key); + +private: + enum Kind { kindNone = 0, kindIndex, kindKey }; + String key_; + ArrayIndex index_{}; + Kind kind_{kindNone}; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provided as parameter + */ +class JSON_API Path { +public: + Path(const String& path, const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + using InArgs = std::vector; + using Args = std::vector; + + void makePath(const String& path, const InArgs& in); + void addPathInArg(const String& path, const InArgs& in, + InArgs::const_iterator& itInArg, PathArgument::Kind kind); + static void invalidPath(const String& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + using iterator_category = std::bidirectional_iterator_tag; + using size_t = unsigned int; + using difference_type = int; + using SelfType = ValueIteratorBase; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + String name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + /*! Internal utility functions to assist with implementing + * other iterator functions. The const and non-const versions + * of the "deref" protected methods expose the protected + * current_ member variable in a way that can often be + * optimized away by the compiler. + */ + const Value& deref() const; + Value& deref(); + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_{true}; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + using value_type = const Value; + // typedef unsigned int size_t; + // typedef int difference_type; + using reference = const Value&; + using pointer = const Value*; + using SelfType = ValueConstIterator; + + ValueConstIterator(); + ValueConstIterator(ValueIterator const& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + using value_type = Value; + using size_t = unsigned int; + using difference_type = int; + using reference = Value&; + using pointer = Value*; + using SelfType = ValueIterator; + + ValueIterator(); + explicit ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + /*! The return value of non-const iterators can be + * changed, so the these functions are not const + * because the returned references/pointers can be used + * to change state of the base class. + */ + reference operator*() { return deref(); } + pointer operator->() { return &deref(); } +}; + +inline void swap(Value& a, Value& b) { a.swap(b); } + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_H_INCLUDED diff --git a/thirdparty/include/json/version.h b/thirdparty/include/json/version.h new file mode 100644 index 0000000000000000000000000000000000000000..5b9783d9656b38570c29a5ede1776714b273db7b --- /dev/null +++ b/thirdparty/include/json/version.h @@ -0,0 +1,28 @@ +#ifndef JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED + +// Note: version must be updated in three places when doing a release. This +// annoying process ensures that amalgamate, CMake, and meson all report the +// correct version. +// 1. /meson.build +// 2. /include/json/version.h +// 3. /CMakeLists.txt +// IMPORTANT: also update the SOVERSION!! + +#define JSONCPP_VERSION_STRING "1.9.4" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 9 +#define JSONCPP_VERSION_PATCH 3 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) + +#ifdef JSONCPP_USING_SECURE_MEMORY +#undef JSONCPP_USING_SECURE_MEMORY +#endif +#define JSONCPP_USING_SECURE_MEMORY 0 +// If non-zero, the library zeroes any memory that it has allocated before +// it frees its memory. + +#endif // JSON_VERSION_H_INCLUDED diff --git a/thirdparty/include/json/writer.h b/thirdparty/include/json/writer.h new file mode 100644 index 0000000000000000000000000000000000000000..fb0852a0ca83bab3a725bfbd8480c37e56a59c83 --- /dev/null +++ b/thirdparty/include/json/writer.h @@ -0,0 +1,367 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +class Value; + +/** + * + * Usage: + * \code + * using namespace Json; + * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) + * { std::unique_ptr const writer( factory.newStreamWriter()); + * writer->write(value, &std::cout); + * std::cout << std::endl; // add lf and flush + * } + * \endcode + */ +class JSON_API StreamWriter { +protected: + OStream* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + * Do not take ownership of sout, but maintain a reference during function. + * \pre sout != NULL + * \return zero on success (For now, we always return zero, so check the + * stream instead.) \throw std::exception possibly, depending on + * configuration + */ + virtual int write(Value const& root, OStream* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +String JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); + +/** \brief Build a StreamWriter implementation. + +* Usage: +* \code +* using namespace Json; +* Value value = ...; +* StreamWriterBuilder builder; +* builder["commentStyle"] = "None"; +* builder["indentation"] = " "; // or whatever you like +* std::unique_ptr writer( +* builder.newStreamWriter()); +* writer->write(value, &std::cout); +* std::cout << std::endl; // add lf and flush +* \endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + * Available settings (case-sensitive): + * - "commentStyle": "None" or "All" + * - "indentation": "". + * - Setting this to an empty string also omits newline characters. + * - "enableYAMLCompatibility": false or true + * - slightly change the whitespace around colons + * - "dropNullPlaceholders": false or true + * - Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + * - "useSpecialFloats": false or true + * - If true, outputs non-finite floating point values in the following way: + * NaN values as "NaN", positive infinity as "Infinity", and negative + * infinity as "-Infinity". + * - "precision": int + * - Number of precision digits for formatting of real values. + * - "precisionType": "significant"(default) or "decimal" + * - Type of precision for formatting of real values. + + * You can examine 'settings_` yourself + * to see the defaults. You can also write and read them just like any + * JSON Value. + * \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + ~StreamWriterBuilder() override; + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + StreamWriter* newStreamWriter() const override; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](const String& key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { +public: + virtual ~Writer(); + + virtual String write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be useful to support feature such as RPC where bandwidth is limited. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter + : public Writer { +public: + FastWriter(); + ~FastWriter() override = default; + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + String write(const Value& root) override; + +private: + void writeValue(const Value& value); + + String document_; + bool yamlCompatibilityEnabled_{false}; + bool dropNullPlaceholders_{false}; + bool omitEndingLineFeed_{false}; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledWriter : public Writer { +public: + StyledWriter(); + ~StyledWriter() override = default; + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + String write(const Value& root) override; + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); + void writeIndent(); + void writeWithIndent(const String& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); + + using ChildValues = std::vector; + + ChildValues childValues_; + String document_; + String indentString_; + unsigned int rightMargin_{74}; + unsigned int indentSize_{3}; + bool addChildValues_{false}; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledStreamWriter { +public: + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(String indentation = "\t"); + ~StyledStreamWriter() = default; + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(OStream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); + void writeIndent(); + void writeWithIndent(const String& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); + + using ChildValues = std::vector; + + ChildValues childValues_; + OStream* document_; + String indentString_; + unsigned int rightMargin_{74}; + String indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(JSON_HAS_INT64) +String JSON_API valueToString(Int value); +String JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +String JSON_API valueToString(LargestInt value); +String JSON_API valueToString(LargestUInt value); +String JSON_API valueToString( + double value, unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +String JSON_API valueToString(bool value); +String JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API OStream& operator<<(OStream&, const Value& root); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED diff --git a/thirdparty/include/libwebsockets.h b/thirdparty/include/libwebsockets.h new file mode 100755 index 0000000000000000000000000000000000000000..759f3d61f6fed06a8a870cd2b313fddf1f1bdbcc --- /dev/null +++ b/thirdparty/include/libwebsockets.h @@ -0,0 +1,684 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** @file */ + +#ifndef LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C +#define LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C + +#ifdef __cplusplus +#include +#include + +extern "C" { +#else +#include +#endif + +#include +#include + +#include "lws_config.h" + +#if defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS) +#define OPENSSL_USE_DEPRECATED +#endif + +/* place for one-shot opaque forward references */ + +typedef struct lws_context * lws_ctx_t; +struct lws_sequencer; +struct lws_dsh; + +/* + * CARE: everything using cmake defines needs to be below here + */ + +#define LWS_US_PER_SEC ((lws_usec_t)1000000) +#define LWS_MS_PER_SEC ((lws_usec_t)1000) +#define LWS_US_PER_MS ((lws_usec_t)1000) +#define LWS_NS_PER_US ((lws_usec_t)1000) + +#define LWS_KI (1024) +#define LWS_MI (LWS_KI * 1024) +#define LWS_GI (LWS_MI * 1024) +#define LWS_TI ((uint64_t)LWS_GI * 1024) +#define LWS_PI ((uint64_t)LWS_TI * 1024) + +#define LWS_US_TO_MS(x) ((x + (LWS_US_PER_MS / 2)) / LWS_US_PER_MS) + +#if defined(LWS_HAS_INTPTR_T) +#include +#define lws_intptr_t intptr_t +#else +typedef unsigned long long lws_intptr_t; +#endif + +#if defined(WIN32) || defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include +#ifndef _WIN32_WCE +#include +#else +#define _O_RDONLY 0x0000 +#define O_RDONLY _O_RDONLY +#endif + +typedef int uid_t; +typedef int gid_t; +typedef unsigned short sa_family_t; +#if !defined(LWS_HAVE_SUSECONDS_T) +typedef unsigned int useconds_t; +typedef int suseconds_t; +#endif + +#define LWS_INLINE __inline +#define LWS_VISIBLE +#define LWS_WARN_UNUSED_RESULT +#define LWS_WARN_DEPRECATED +#define LWS_FORMAT(string_index) + +#if !defined(LWS_EXTERN) && defined(LWS_BUILDING_SHARED) +#ifdef LWS_DLL +#ifdef LWS_INTERNAL +#define LWS_EXTERN extern __declspec(dllexport) +#else +#define LWS_EXTERN extern __declspec(dllimport) +#endif +#endif +#endif + +#if !defined(LWS_INTERNAL) && !defined(LWS_EXTERN) +#define LWS_EXTERN +#define LWS_VISIBLE +#endif + +#if !defined(LWS_EXTERN) +#define LWS_EXTERN +#endif + +#define LWS_INVALID_FILE INVALID_HANDLE_VALUE +#define LWS_SOCK_INVALID (INVALID_SOCKET) +#define LWS_O_RDONLY _O_RDONLY +#define LWS_O_WRONLY _O_WRONLY +#define LWS_O_CREAT _O_CREAT +#define LWS_O_TRUNC _O_TRUNC + +#ifndef __func__ +#define __func__ __FUNCTION__ +#endif + +#else /* NOT WIN32 */ +#include +#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) +#include +#endif + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__) +#include +#include +#endif + +#define LWS_INLINE inline +#define LWS_O_RDONLY O_RDONLY +#define LWS_O_WRONLY O_WRONLY +#define LWS_O_CREAT O_CREAT +#define LWS_O_TRUNC O_TRUNC + +#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_TA) && !defined(LWS_PLAT_FREERTOS) +#include +#include +#define LWS_INVALID_FILE -1 +#define LWS_SOCK_INVALID (-1) +#else +#define getdtablesize() (30) +#if defined(LWS_PLAT_FREERTOS) +#define LWS_INVALID_FILE NULL +#define LWS_SOCK_INVALID (-1) +#else +#define LWS_INVALID_FILE NULL +#define LWS_SOCK_INVALID (-1) +#endif +#endif + +#if defined(__FreeBSD__) +#include +#endif +#if defined(__GNUC__) + +/* warn_unused_result attribute only supported by GCC 3.4 or later */ +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define LWS_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define LWS_WARN_UNUSED_RESULT +#endif + +#if defined(LWS_BUILDING_SHARED) +/* this is only set when we're building lws itself shared */ +#define LWS_VISIBLE __attribute__((visibility("default"))) +#define LWS_EXTERN extern + +#else /* not shared */ +#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) +#define LWS_VISIBLE +#define LWS_EXTERN extern +#else +/* + * If we explicitly say hidden here, symbols exist as T but + * cannot be imported at link-time. + */ +#define LWS_VISIBLE +#define LWS_EXTERN +#endif + +#endif /* not shared */ + +#define LWS_WARN_DEPRECATED __attribute__ ((deprecated)) +#define LWS_FORMAT(string_index) __attribute__ ((format(printf, string_index, string_index+1))) +#else /* not GNUC */ + +#define LWS_VISIBLE +#define LWS_WARN_UNUSED_RESULT +#define LWS_WARN_DEPRECATED +#define LWS_FORMAT(string_index) +#if !defined(LWS_EXTERN) +#define LWS_EXTERN extern +#endif +#endif + + +#if defined(__ANDROID__) +#include +#include +#endif +#endif + +#ifdef _WIN32 +#define random rand +#else +#if !defined(LWS_PLAT_OPTEE) +#include +#include +#endif +#endif + +#if defined(LWS_WITH_LIBUV_INTERNAL) +#include + +#ifdef LWS_HAVE_UV_VERSION_H +#include +#endif + +#ifdef LWS_HAVE_NEW_UV_VERSION_H +#include +#endif +#endif + +#if defined(LWS_WITH_TLS) + +#ifdef USE_WOLFSSL +#ifdef USE_OLD_CYASSL +#ifdef _WIN32 +/* + * Include user-controlled settings for windows from + * /IDE/WIN/user_settings.h + */ +#include +#include +#else +#include +#endif +#include +#include + +#else +#ifdef _WIN32 +/* + * Include user-controlled settings for windows from + * /IDE/WIN/user_settings.h + */ +#include +#include +#else +#include +#endif +#include +#include +#endif /* not USE_OLD_CYASSL */ +#else +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_PLAT_FREERTOS) +/* this filepath is passed to us but without quotes or <> */ +#if !defined(LWS_AMAZON_RTOS) +/* AMAZON RTOS has its own setting via MTK_MBEDTLS_CONFIG_FILE */ +#undef MBEDTLS_CONFIG_FILE +#define MBEDTLS_CONFIG_FILE +#endif +#endif +#if defined(LWS_WITH_TLS) +#include +#include +#include + +#if !defined(MBEDTLS_PRIVATE) +#define MBEDTLS_PRIVATE(_q) _q +#endif + +#endif +#else +#include +#if !defined(LWS_WITH_MBEDTLS) +#include +#endif +#endif +#endif /* not USE_WOLFSSL */ +#endif + +/* + * Helpers for pthread mutex in user code... if lws is built for + * multiple service threads, these resolve to pthread mutex + * operations. In the case LWS_MAX_SMP is 1 (the default), they + * are all NOPs and no pthread type or api is referenced. + */ + +#if LWS_MAX_SMP > 1 + +#include + +#define lws_pthread_mutex(name) pthread_mutex_t name; + +static LWS_INLINE void +lws_pthread_mutex_init(pthread_mutex_t *lock) +{ + pthread_mutex_init(lock, NULL); +} + +static LWS_INLINE void +lws_pthread_mutex_destroy(pthread_mutex_t *lock) +{ + pthread_mutex_destroy(lock); +} + +static LWS_INLINE void +lws_pthread_mutex_lock(pthread_mutex_t *lock) +{ + pthread_mutex_lock(lock); +} + +static LWS_INLINE void +lws_pthread_mutex_unlock(pthread_mutex_t *lock) +{ + pthread_mutex_unlock(lock); +} + +#else +#define lws_pthread_mutex(name) +#define lws_pthread_mutex_init(_a) +#define lws_pthread_mutex_destroy(_a) +#define lws_pthread_mutex_lock(_a) +#define lws_pthread_mutex_unlock(_a) +#endif + + +#define CONTEXT_PORT_NO_LISTEN -1 +#define CONTEXT_PORT_NO_LISTEN_SERVER -2 + +#include + + +#include + +#ifndef lws_container_of +#define lws_container_of(P,T,M) ((T *)((char *)(P) - offsetof(T, M))) +#endif +#define LWS_ALIGN_TO(x, bou) x += ((bou) - ((x) % (bou))) % (bou) + +struct lws; + +/* api change list for user code to test against */ + +#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_ARG + +/* the struct lws_protocols has the id field present */ +#define LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD + +/* you can call lws_get_peer_write_allowance */ +#define LWS_FEATURE_PROTOCOLS_HAS_PEER_WRITE_ALLOWANCE + +/* extra parameter introduced in 917f43ab821 */ +#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_LEN + +/* File operations stuff exists */ +#define LWS_FEATURE_FOPS + + +#if defined(_WIN32) +#if !defined(LWS_WIN32_HANDLE_TYPES) +typedef SOCKET lws_sockfd_type; +typedef HANDLE lws_filefd_type; +#endif + + +#define lws_pollfd pollfd +#define LWS_POLLHUP (POLLHUP) +#define LWS_POLLIN (POLLRDNORM | POLLRDBAND) +#define LWS_POLLOUT (POLLWRNORM) + +#else + + +#if defined(LWS_PLAT_FREERTOS) +#include +#else +typedef int lws_sockfd_type; +typedef int lws_filefd_type; +#endif + +#if defined(LWS_PLAT_OPTEE) +#include +struct timeval { + time_t tv_sec; + unsigned int tv_usec; +}; +#if defined(LWS_WITH_NETWORK) +// #include +#define lws_pollfd pollfd + +struct timezone; + +int gettimeofday(struct timeval *tv, struct timezone *tz); + + /* Internet address. */ + struct in_addr { + uint32_t s_addr; /* address in network byte order */ + }; + +typedef unsigned short sa_family_t; +typedef unsigned short in_port_t; +typedef uint32_t socklen_t; + +#include + +#if !defined(TEE_SE_READER_NAME_MAX) + struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; + }; +#endif + +ssize_t recv(int sockfd, void *buf, size_t len, int flags); +ssize_t send(int sockfd, const void *buf, size_t len, int flags); +ssize_t read(int fd, void *buf, size_t count); +int getsockopt(int sockfd, int level, int optname, + void *optval, socklen_t *optlen); + int setsockopt(int sockfd, int level, int optname, + const void *optval, socklen_t optlen); +int connect(int sockfd, const struct sockaddr *addr, + socklen_t addrlen); + +extern int errno; + +uint16_t ntohs(uint16_t netshort); +uint16_t htons(uint16_t hostshort); + +int bind(int sockfd, const struct sockaddr *addr, + socklen_t addrlen); + + +#define MSG_NOSIGNAL 0x4000 +#define EAGAIN 11 +#define EINTR 4 +#define EWOULDBLOCK EAGAIN +#define EADDRINUSE 98 +#define INADDR_ANY 0 +#define AF_INET 2 +#define SHUT_WR 1 +#define AF_UNSPEC 0 +#define PF_UNSPEC 0 +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +# define AI_PASSIVE 0x0001 +#define IPPROTO_UDP 17 +#define SOL_SOCKET 1 +#define SO_SNDBUF 7 +#define EISCONN 106 +#define EALREADY 114 +#define EINPROGRESS 115 +int shutdown(int sockfd, int how); +int close(int fd); +int atoi(const char *nptr); +long long atoll(const char *nptr); + +int socket(int domain, int type, int protocol); + int getaddrinfo(const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res); + + void freeaddrinfo(struct addrinfo *res); + +#if !defined(TEE_SE_READER_NAME_MAX) +struct lws_pollfd +{ + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ +}; +#endif + +int poll(struct pollfd *fds, int nfds, int timeout); + +#define LWS_POLLHUP (0x18) +#define LWS_POLLIN (1) +#define LWS_POLLOUT (4) +#else +struct lws_pollfd; +struct sockaddr_in; +#endif +#else +#define lws_pollfd pollfd +#define LWS_POLLHUP (POLLHUP | POLLERR) +#define LWS_POLLIN (POLLIN) +#define LWS_POLLOUT (POLLOUT) +#endif +#endif + + +#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__) +/* ... */ +#define ssize_t SSIZE_T +#endif + +#if defined(WIN32) && defined(LWS_HAVE__STAT32I64) +#include +#include +#endif + +#if defined(LWS_HAVE_STDINT_H) +#include +#else +#if defined(WIN32) || defined(_WIN32) +/* !!! >:-[ */ +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +#else +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +#endif +#endif + +typedef int64_t lws_usec_t; +typedef unsigned long long lws_filepos_t; +typedef long long lws_fileofs_t; +typedef uint32_t lws_fop_flags_t; + +#define lws_concat_temp(_t, _l) (_t + sizeof(_t) - _l) +#define lws_concat_used(_t, _l) (sizeof(_t) - _l) + +/** struct lws_pollargs - argument structure for all external poll related calls + * passed in via 'in' */ +struct lws_pollargs { + lws_sockfd_type fd; /**< applicable socket descriptor */ + int events; /**< the new event mask */ + int prev_events; /**< the previous event mask */ +}; + +struct lws_extension; /* needed even with ws exts disabled for create context */ +struct lws_token_limits; +struct lws_protocols; +struct lws_context; +struct lws_tokens; +struct lws_vhost; +struct lws; + +#include +#include + +#include +#include +#include +#if defined(LWS_WITH_SYS_SMD) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(LWS_WITH_CONMON) +#include +#endif + +#if defined(LWS_ROLE_MQTT) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(LWS_WITH_FILE_OPS) +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(LWS_PLAT_FREERTOS) +#include + +#include +#endif +#include + +#if defined(LWS_WITH_TLS) + +#include + +#if defined(LWS_WITH_MBEDTLS) +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/libwebsockets/abstract/abstract.h b/thirdparty/include/libwebsockets/abstract/abstract.h new file mode 100755 index 0000000000000000000000000000000000000000..c312a1f5a790c49c322a57df5550966728255333 --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/abstract.h @@ -0,0 +1,138 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/* + * These are used to optionally pass an array of index = C string, binary array, + * or ulong tokens to the abstract transport or protocol. For example if it's + * raw socket transport, then the DNS address to connect to and the port are + * passed using these when the client created and bound to the transport. + */ + +typedef struct lws_token_map { + union { + const char *value; + uint8_t *bvalue; + unsigned long lvalue; + } u; + short name_index; /* 0 here indicates end of array */ + short length_or_zero; +} lws_token_map_t; + +/* + * The indvidual protocols and transports define their own name_index-es which + * are meaningful to them. Define index 0 globally as the end of an array of + * them, and provide bases so user protocol and transport ones don't overlap. + */ + +enum { + LTMI_END_OF_ARRAY, + + LTMI_PROTOCOL_BASE = 2048, + + LTMI_TRANSPORT_BASE = 4096 +}; + +struct lws_abs_transport; +struct lws_abs_protocol; +typedef struct lws_abs lws_abs_t; + +LWS_VISIBLE LWS_EXTERN const lws_token_map_t * +lws_abs_get_token(const lws_token_map_t *token_map, short name_index); + +/* + * the combination of a protocol, transport, and token maps for each + */ + +typedef void lws_abs_transport_inst_t; +typedef void lws_abs_protocol_inst_t; + +/** + * lws_abstract_alloc() - allocate and configure an lws_abs_t + * + * \param vhost: the struct lws_vhost to bind to + * \param user: opaque user pointer + * \param abstract_path: "protocol.transport" names + * \param ap_tokens: tokens for protocol options + * \param at_tokens: tokens for transport + * \param seq: optional sequencer we should bind to, or NULL + * \param opaque_user_data: data given in sequencer callback, if any + * + * Returns an allocated lws_abs_t pointer set up with the other arguments. + * + * Doesn't create a connection instance, just allocates the lws_abs_t and + * sets it up with the arguments. + * + * Returns NULL is there's any problem. + */ +LWS_VISIBLE LWS_EXTERN lws_abs_t * +lws_abstract_alloc(struct lws_vhost *vhost, void *user, + const char *abstract_path, const lws_token_map_t *ap_tokens, + const lws_token_map_t *at_tokens, struct lws_sequencer *seq, + void *opaque_user_data); + +/** + * lws_abstract_free() - free an allocated lws_abs_t + * + * \param pabs: pointer to the lws_abs_t * to free + * + * Frees and sets the pointer to NULL. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_abstract_free(lws_abs_t **pabs); + +/** + * lws_abs_bind_and_create_instance - use an abstract protocol and transport + * + * \param abs: the lws_abs_t describing the combination desired + * + * This instantiates an abstract protocol and abstract transport bound together. + * A single heap allocation is made for the combination and the protocol and + * transport creation ops are called on it. The ap_tokens and at_tokens + * are consulted by the creation ops to decide the details of the protocol and + * transport for the instance. + */ +LWS_VISIBLE LWS_EXTERN lws_abs_t * +lws_abs_bind_and_create_instance(const lws_abs_t *ai); + +/** + * lws_abs_destroy_instance() - destroys an instance + * + * \param ai: pointer to the ai pointer to destroy + * + * This is for destroying an instance created by + * lws_abs_bind_and_create_instance() above. + * + * Calls the protocol and transport destroy operations on the instance, then + * frees the combined allocation in one step. The pointer ai is set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_abs_destroy_instance(lws_abs_t **ai); + +/* + * bring in all the protocols and transports definitions + */ + +#include +#include diff --git a/thirdparty/include/libwebsockets/abstract/protocols.h b/thirdparty/include/libwebsockets/abstract/protocols.h new file mode 100755 index 0000000000000000000000000000000000000000..77900203d5f7659bc51ca2be437d35a778c2fdd7 --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/protocols.h @@ -0,0 +1,88 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/* + * Information about how this protocol handles multiple use of connections. + * + * .flags of 0 indicates each connection must start with a fresh transport. + * + * Flags can be used to indicate the protocol itself supports different + * kinds of multiple use. However the actual use or not of these may depend on + * negotiation with the remote peer. + * + * LWS_AP_FLAG_PIPELINE_TRANSACTIONS: other instances can be queued on one + * with an existing connection and get a + * chance to "hot take over" the existing + * transport in turn, like h1 keepalive + * pipelining + * + * LWS_AP_FLAG_MUXABLE_STREAM: an existing connection can absorb more child + * connections and mux them as separate child + * streams ongoing, like h2 + */ + +enum { + LWS_AP_FLAG_PIPELINE_TRANSACTIONS = (1 << 0), + LWS_AP_FLAG_MUXABLE_STREAM = (1 << 1), +}; + +typedef struct lws_abs_protocol { + const char *name; + int alloc; + int flags; + + int (*create)(const struct lws_abs *ai); + void (*destroy)(lws_abs_protocol_inst_t **d); + int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2); + + /* events the transport invokes (handled by abstract protocol) */ + + int (*accept)(lws_abs_protocol_inst_t *d); + int (*rx)(lws_abs_protocol_inst_t *d, const uint8_t *b, size_t l); + int (*writeable)(lws_abs_protocol_inst_t *d, size_t budget); + int (*closed)(lws_abs_protocol_inst_t *d); + int (*heartbeat)(lws_abs_protocol_inst_t *d); + + /* as parent, we get a notification a new child / queue entry + * bound to us... this is the parent lws_abs_t as arg */ + int (*child_bind)(lws_abs_t *abs); +} lws_abs_protocol_t; + +/** + * lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops + * + * \param name: the name of the abstract protocol + * + * Returns a pointer to the named protocol ops struct if available, otherwise + * NULL. + */ +LWS_VISIBLE LWS_EXTERN const lws_abs_protocol_t * +lws_abs_protocol_get_by_name(const char *name); + +/* + * bring in public api pieces from protocols + */ + +#include + diff --git a/thirdparty/include/libwebsockets/abstract/protocols/smtp.h b/thirdparty/include/libwebsockets/abstract/protocols/smtp.h new file mode 100755 index 0000000000000000000000000000000000000000..90b69c6e839b3fdb9b66a0884f969e37ab08c6ba --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/protocols/smtp.h @@ -0,0 +1,115 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup smtp SMTP related functions + * ##SMTP related functions + * \ingroup lwsapi + * + * These apis let you communicate with a local SMTP server to send email from + * lws. It handles all the SMTP sequencing and protocol actions. + * + * Your system should have postfix, sendmail or another MTA listening on port + * 25 and able to send email using the "mail" commandline app. Usually distro + * MTAs are configured for this by default. + * + * You can either use the abstract protocol layer directly, or instead use the + * provided smtp sequencer... this takes care of creating the protocol + * connections, and provides and email queue and retry management. + */ +//@{ + +#if defined(LWS_WITH_SMTP) + +enum { + LTMI_PSMTP_V_HELO = LTMI_PROTOCOL_BASE, /* u.value */ + + LTMI_PSMTP_V_LWS_SMTP_EMAIL_T, /* u.value */ +}; + +enum { + LWS_SMTP_DISPOSITION_SENT, + LWS_SMTP_DISPOSITION_FAILED, + LWS_SMTP_DISPOSITION_FAILED_DESTROY +}; + +typedef struct lws_smtp_sequencer_args { + const char helo[32]; + struct lws_vhost *vhost; + time_t retry_interval; + time_t delivery_timeout; + size_t email_queue_max; + size_t max_content_size; +} lws_smtp_sequencer_args_t; + +typedef struct lws_smtp_sequencer lws_smtp_sequencer_t; +typedef struct lws_smtp_email lws_smtp_email_t; + +LWS_VISIBLE LWS_EXTERN lws_smtp_sequencer_t * +lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args); + +LWS_VISIBLE LWS_EXTERN void +lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s); + +typedef int (*lws_smtp_cb_t)(void *e, void *d, int disp, const void *b, size_t l); +typedef struct lws_smtp_email lws_smtp_email_t; + +/** + * lws_smtpc_add_email() - Allocates and queues an email object + * + * \param s: smtp sequencer to queue on + * \param payload: the email payload string, with headers and terminating . + * \param payload_len: size in bytes of the payload string + * \param sender: the sender name and email + * \param recipient: the recipient name and email + * \param data: opaque user data returned in the done callback + * \param done: callback called when the email send succeeded or failed + * + * Allocates an email object and copies the payload, sender and recipient into + * it and initializes it. Returns NULL if OOM, otherwise the allocated email + * object. + * + * Because it copies the arguments into an allocated buffer, the original + * arguments can be safely destroyed after calling this. + * + * The done() callback must free the email object. It doesn't have to free any + * individual members. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload, + size_t payload_len, const char *sender, + const char *recipient, void *data, lws_smtp_cb_t done); + +/** + * lws_smtpc_free_email() - Add email to the list of ones being sent + * + * \param e: email to queue for sending on \p c + * + * Adds an email to the linked-list of emails to send + */ +LWS_VISIBLE LWS_EXTERN int +lws_smtpc_free_email(lws_smtp_email_t *e); + + +#endif +//@} diff --git a/thirdparty/include/libwebsockets/abstract/transports.h b/thirdparty/include/libwebsockets/abstract/transports.h new file mode 100755 index 0000000000000000000000000000000000000000..e9d7aa5686f37430a32834bad9ae69d03c80a5d7 --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/transports.h @@ -0,0 +1,65 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/* + * Abstract transport ops + */ + +typedef struct lws_abs_transport { + const char *name; + int alloc; + + int (*create)(lws_abs_t *abs); + void (*destroy)(lws_abs_transport_inst_t **d); + + /* check if the transport settings for these connections are the same */ + int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2); + + /* events the abstract protocol invokes (handled by transport) */ + + int (*tx)(lws_abs_transport_inst_t *d, uint8_t *buf, size_t len); + int (*client_conn)(const lws_abs_t *abs); + int (*close)(lws_abs_transport_inst_t *d); + int (*ask_for_writeable)(lws_abs_transport_inst_t *d); + int (*set_timeout)(lws_abs_transport_inst_t *d, int reason, int secs); + int (*state)(lws_abs_transport_inst_t *d); +} lws_abs_transport_t; + +/** + * lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops + * + * \param name: the name of the abstract protocol + * + * Returns a pointer to the named protocol ops struct if available, otherwise + * NULL. + */ +LWS_VISIBLE LWS_EXTERN const lws_abs_transport_t * +lws_abs_transport_get_by_name(const char *name); + +/* + * bring in public api pieces from transports + */ + +#include +#include diff --git a/thirdparty/include/libwebsockets/abstract/transports/raw-skt.h b/thirdparty/include/libwebsockets/abstract/transports/raw-skt.h new file mode 100755 index 0000000000000000000000000000000000000000..beff9a3facbab299bfa84550417d5b8c939d5fa0 --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/transports/raw-skt.h @@ -0,0 +1,29 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +enum { + LTMI_PEER_V_DNS_ADDRESS = LTMI_TRANSPORT_BASE, /* u.value */ + LTMI_PEER_LV_PORT, /* u.lvalue */ + LTMI_PEER_LV_TLS_FLAGS, /* u.lvalue */ +}; diff --git a/thirdparty/include/libwebsockets/abstract/transports/unit-test.h b/thirdparty/include/libwebsockets/abstract/transports/unit-test.h new file mode 100755 index 0000000000000000000000000000000000000000..2213f29a76b8dfcf5c9f567f90bee602c9fe8da8 --- /dev/null +++ b/thirdparty/include/libwebsockets/abstract/transports/unit-test.h @@ -0,0 +1,81 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + * + * This is an abstract transport useful for unit testing abstract protocols. + * + * Instead of passing data anywhere, you give the transport a list of packets + * to deliver and packets you expect back from the abstract protocol it's + * bound to. + */ + +enum { + LWS_AUT_EXPECT_TEST_END = (1 << 0), + LWS_AUT_EXPECT_LOCAL_CLOSE = (1 << 1), + LWS_AUT_EXPECT_DO_REMOTE_CLOSE = (1 << 2), + LWS_AUT_EXPECT_TX /* expect this as tx from protocol */ = (1 << 3), + LWS_AUT_EXPECT_RX /* present this as rx to protocol */ = (1 << 4), + LWS_AUT_EXPECT_SHOULD_FAIL = (1 << 5), + LWS_AUT_EXPECT_SHOULD_TIMEOUT = (1 << 6), +}; + +typedef enum { + LPE_CONTINUE, + LPE_SUCCEEDED, + LPE_FAILED, + LPE_FAILED_UNEXPECTED_TIMEOUT, + LPE_FAILED_UNEXPECTED_PASS, + LPE_FAILED_UNEXPECTED_CLOSE, + LPE_SKIPPED, + LPE_CLOSING +} lws_unit_test_packet_disposition; + +typedef int (*lws_unit_test_packet_test_cb)(const void *cb_user, int disposition); +typedef int (*lws_unit_test_packet_cb)(lws_abs_t *instance); + +/* each step in the unit test */ + +typedef struct lws_unit_test_packet { + void *buffer; + lws_unit_test_packet_cb pre; + size_t len; + + uint32_t flags; +} lws_unit_test_packet_t; + +/* each unit test */ + +typedef struct lws_unit_test { + const char * name; /* NULL indicates end of test array */ + lws_unit_test_packet_t * expect_array; + int max_secs; +} lws_unit_test_t; + +enum { + LTMI_PEER_V_EXPECT_TEST = LTMI_TRANSPORT_BASE, /* u.value */ + LTMI_PEER_V_EXPECT_RESULT_CB, /* u.value */ + LTMI_PEER_V_EXPECT_RESULT_CB_ARG, /* u.value */ +}; + +LWS_VISIBLE LWS_EXTERN const char * +lws_unit_test_result_name(int in); + diff --git a/thirdparty/include/libwebsockets/lws-adopt.h b/thirdparty/include/libwebsockets/lws-adopt.h new file mode 100755 index 0000000000000000000000000000000000000000..94a1818d28c7326ef0031c1a57197ef42f8cb0c9 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-adopt.h @@ -0,0 +1,271 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup sock-adopt Socket adoption helpers + * ##Socket adoption helpers + * + * When integrating with an external app with its own event loop, these can + * be used to accept connections from someone else's listening socket. + * + * When using lws own event loop, these are not needed. + */ +///@{ + +/** + * lws_adopt_socket() - adopt foreign socket as if listen socket accepted it + * for the default vhost of context. + * + * \param context: lws context + * \param accept_fd: fd of already-accepted socket to adopt + * + * Either returns new wsi bound to accept_fd, or closes accept_fd and + * returns NULL, having cleaned up any new wsi pieces. + * + * LWS adopts the socket in http serving mode, it's ready to accept an upgrade + * to ws or just serve http. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd); +/** + * lws_adopt_socket_vhost() - adopt foreign socket as if listen socket accepted + * it for vhost + * + * \param vh: lws vhost + * \param accept_fd: fd of already-accepted socket to adopt + * + * Either returns new wsi bound to accept_fd, or closes accept_fd and + * returns NULL, having cleaned up any new wsi pieces. + * + * LWS adopts the socket in http serving mode, it's ready to accept an upgrade + * to ws or just serve http. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd); + +typedef enum { + LWS_ADOPT_RAW_FILE_DESC = 0, /* convenience constant */ + LWS_ADOPT_HTTP = 1, /* flag: absent implies RAW */ + LWS_ADOPT_SOCKET = 2, /* flag: absent implies file */ + LWS_ADOPT_ALLOW_SSL = 4, /* flag: use tls */ + LWS_ADOPT_FLAG_UDP = 16, /* flag: socket is UDP */ + LWS_ADOPT_FLAG_RAW_PROXY = 32, /* flag: raw proxy */ + + LWS_ADOPT_RAW_SOCKET_UDP = LWS_ADOPT_SOCKET | LWS_ADOPT_FLAG_UDP, +} lws_adoption_type; + +typedef union { + lws_sockfd_type sockfd; + lws_filefd_type filefd; +} lws_sock_file_fd_type; + +#if defined(LWS_ESP_PLATFORM) +#include +#endif + +typedef union { +#if defined(LWS_WITH_IPV6) + struct sockaddr_in6 sa6; +#else +#if defined(LWS_ESP_PLATFORM) + uint8_t _pad_sa6[28]; +#endif +#endif + struct sockaddr_in sa4; +} lws_sockaddr46; + +#define sa46_sockaddr(_sa46) ((struct sockaddr *)(_sa46)) + +#if defined(LWS_WITH_IPV6) +#define sa46_socklen(_sa46) (socklen_t)((_sa46)->sa4.sin_family == AF_INET ? \ + sizeof(struct sockaddr_in) : \ + sizeof(struct sockaddr_in6)) +#define sa46_sockport(_sa46, _sp) { if ((_sa46)->sa4.sin_family == AF_INET) \ + (_sa46)->sa4.sin_port = (_sp); else \ + (_sa46)->sa6.sin6_port = (_sp); } +#define sa46_address(_sa46) ((uint8_t *)((_sa46)->sa4.sin_family == AF_INET ? \ + &_sa46->sa4.sin_addr : &_sa46->sa6.sin6_addr )) +#else +#define sa46_socklen(_sa46) (socklen_t)sizeof(struct sockaddr_in) +#define sa46_sockport(_sa46, _sp) (_sa46)->sa4.sin_port = (_sp) +#define sa46_address(_sa46) (uint8_t *)&_sa46->sa4.sin_addr +#endif + +#define sa46_address_len(_sa46) ((_sa46)->sa4.sin_family == AF_INET ? 4 : 16) + +#if defined(LWS_WITH_UDP) +struct lws_udp { + lws_sockaddr46 sa46; + lws_sockaddr46 sa46_pending; + uint8_t connected:1; +}; +#endif + +/** +* lws_adopt_descriptor_vhost() - adopt foreign socket or file descriptor +* if socket descriptor, should already have been accepted from listen socket +* +* \param vh: lws vhost +* \param type: OR-ed combinations of lws_adoption_type flags +* \param fd: union with either .sockfd or .filefd set +* \param vh_prot_name: NULL or vh protocol name to bind raw connection to +* \param parent: NULL or struct lws to attach new_wsi to as a child +* +* Either returns new wsi bound to accept_fd, or closes accept_fd and +* returns NULL, having cleaned up any new wsi pieces. +* +* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's +* ready to accept an upgrade to ws or just serve http. +* +* parent may be NULL, if given it should be an existing wsi that will become the +* parent of the new wsi created by this call. +*/ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type, + lws_sock_file_fd_type fd, const char *vh_prot_name, + struct lws *parent); + +typedef struct lws_adopt_desc { + struct lws_vhost *vh; /**< vhost the wsi should belong to */ + lws_adoption_type type; /**< OR-ed combinations of lws_adoption_type flags */ + lws_sock_file_fd_type fd; /**< union with either .sockfd or .filefd set */ + const char *vh_prot_name; /**< NULL or vh protocol name to bind raw connection to */ + struct lws *parent; /**< NULL or struct lws to attach new_wsi to as a child */ + void *opaque; /**< opaque pointer to set on created wsi */ + const char *fi_wsi_name; /**< NULL, or Fault Injection inheritence filter for wsi=string/ context faults */ +} lws_adopt_desc_t; + +/** +* lws_adopt_descriptor_vhost_via_info() - adopt foreign socket or file descriptor +* if socket descriptor, should already have been accepted from listen socket +* +* \param info: the struct containing the parameters +* +* - vh: lws vhost +* - type: OR-ed combinations of lws_adoption_type flags +* - fd: union with either .sockfd or .filefd set +* - vh_prot_name: NULL or vh protocol name to bind raw connection to +* - parent: NULL or struct lws to attach new_wsi to as a child +* - opaque: opaque pointer to set on created wsi +* +* Either returns new wsi bound to accept_fd, or closes accept_fd and +* returns NULL, having cleaned up any new wsi pieces. +* +* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's +* ready to accept an upgrade to ws or just serve http. +* +* parent may be NULL, if given it should be an existing wsi that will become the +* parent of the new wsi created by this call. +*/ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info); + +/** + * lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it + * for the default vhost of context. + * \param context: lws context + * \param accept_fd: fd of already-accepted socket to adopt + * \param readbuf: NULL or pointer to data that must be drained before reading from + * accept_fd + * \param len: The length of the data held at \p readbuf + * + * Either returns new wsi bound to accept_fd, or closes accept_fd and + * returns NULL, having cleaned up any new wsi pieces. + * + * LWS adopts the socket in http serving mode, it's ready to accept an upgrade + * to ws or just serve http. + * + * If your external code did not already read from the socket, you can use + * lws_adopt_socket() instead. + * + * This api is guaranteed to use the data at \p readbuf first, before reading from + * the socket. + * + * \p readbuf is limited to the size of the ah rx buf, currently 2048 bytes. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd, + const char *readbuf, size_t len); +/** + * lws_adopt_socket_vhost_readbuf() - adopt foreign socket and first rx as if listen socket + * accepted it for vhost. + * \param vhost: lws vhost + * \param accept_fd: fd of already-accepted socket to adopt + * \param readbuf: NULL or pointer to data that must be drained before reading from accept_fd + * \param len: The length of the data held at \p readbuf + * + * Either returns new wsi bound to accept_fd, or closes accept_fd and + * returns NULL, having cleaned up any new wsi pieces. + * + * LWS adopts the socket in http serving mode, it's ready to accept an upgrade + * to ws or just serve http. + * + * If your external code did not already read from the socket, you can use + * lws_adopt_socket() instead. + * + * This api is guaranteed to use the data at \p readbuf first, before reading from + * the socket. + * + * \p readbuf is limited to the size of the ah rx buf, currently 2048 bytes. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, + lws_sockfd_type accept_fd, const char *readbuf, + size_t len); + +#define LWS_CAUDP_BIND (1 << 0) +#define LWS_CAUDP_BROADCAST (1 << 1) +#define LWS_CAUDP_PF_PACKET (1 << 2) + +#if defined(LWS_WITH_UDP) +/** + * lws_create_adopt_udp() - create, bind and adopt a UDP socket + * + * \param vhost: lws vhost + * \param ads: NULL or address to do dns lookup on + * \param port: UDP port to bind to, -1 means unbound + * \param flags: 0 or LWS_CAUDP_NO_BIND + * \param protocol_name: Name of protocol on vhost to bind wsi to + * \param ifname: NULL, for network interface name to bind socket to + * \param parent_wsi: NULL or parent wsi new wsi will be a child of + * \param opaque: set created wsi opaque ptr to this + * \param retry_policy: NULL for vhost default policy else wsi specific policy + * \param fi_wsi_name: NULL, or string to inherit Fault Injection rules in + * form "wsi=string/rule". "wsi/rule" faults will be + * automatically applied as well. It's done at creation + * time so the rules can, eg, inject faults related to + * creation. + * + * Either returns new wsi bound to accept_fd, or closes accept_fd and + * returns NULL, having cleaned up any new wsi pieces. + * */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, + int flags, const char *protocol_name, const char *ifname, + struct lws *parent_wsi, void *opaque, + const lws_retry_bo_t *retry_policy, const char *fi_wsi_name); +#endif + + + +///@} diff --git a/thirdparty/include/libwebsockets/lws-async-dns.h b/thirdparty/include/libwebsockets/lws-async-dns.h new file mode 100755 index 0000000000000000000000000000000000000000..dc8b417dad47ca821119eb391caf79d225c25988 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-async-dns.h @@ -0,0 +1,86 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +#if defined(LWS_WITH_UDP) + +typedef enum dns_query_type { + LWS_ADNS_RECORD_A = 0x01, + LWS_ADNS_RECORD_CNAME = 0x05, + LWS_ADNS_RECORD_MX = 0x0f, + LWS_ADNS_RECORD_AAAA = 0x1c, +} adns_query_type_t; + +typedef enum { + LADNS_RET_FAILED_WSI_CLOSED = -4, + LADNS_RET_NXDOMAIN = -3, + LADNS_RET_TIMEDOUT = -2, + LADNS_RET_FAILED = -1, + LADNS_RET_FOUND, + LADNS_RET_CONTINUING +} lws_async_dns_retcode_t; + +struct addrinfo; + +typedef struct lws * (*lws_async_dns_cb_t)(struct lws *wsi, const char *ads, + const struct addrinfo *result, int n, void *opaque); + +/** + * lws_async_dns_query() - perform a dns lookup using async dns + * + * \param context: the lws_context + * \param tsi: thread service index (usually 0) + * \param name: DNS name to look up + * \param qtype: type of query (A, AAAA etc) + * \param cb: query completion callback + * \param wsi: wsi if the query is related to one + * + * Starts an asynchronous DNS lookup, on completion the \p cb callback will + * be called. + * + * The reference count on the cached object is incremented for every callback + * that was called with the cached addrinfo results. + * + * The cached object can't be evicted until the reference count reaches zero... + * use lws_async_dns_freeaddrinfo() to indicate you're finsihed with the + * results for each callback that happened with them. + */ +LWS_VISIBLE LWS_EXTERN lws_async_dns_retcode_t +lws_async_dns_query(struct lws_context *context, int tsi, const char *name, + adns_query_type_t qtype, lws_async_dns_cb_t cb, + struct lws *wsi, void *opaque); + +/** + * lws_async_dns_freeaddrinfo() - decrement refcount on cached addrinfo results + * + * \param pai: a pointert to a pointer to first addrinfo returned as result in the callback + * + * Decrements the cache object's reference count. When it reaches zero, the + * cached object may be reaped subject to LRU rules. + * + * The pointer to the first addrinfo give in the argument is set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_async_dns_freeaddrinfo(const struct addrinfo **ai); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-bb-i2c.h b/thirdparty/include/libwebsockets/lws-bb-i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..bd9718e92dd49ca04bf7021f7bd7716699b773dd --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-bb-i2c.h @@ -0,0 +1,66 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +typedef struct lws_bb_i2c { + lws_i2c_ops_t bb_ops; /* init to lws_bb_i2c_ops */ + + /* implementation-specific members */ + + _lws_plat_gpio_t scl; + _lws_plat_gpio_t sda; + + const lws_gpio_ops_t *gpio; + void (*delay)(void); +} lws_bb_i2c_t; + +#define lws_bb_i2c_ops \ + { \ + .init = lws_bb_i2c_init, \ + .start = lws_bb_i2c_start, \ + .stop = lws_bb_i2c_stop, \ + .write = lws_bb_i2c_write, \ + .read = lws_bb_i2c_read, \ + .set_ack = lws_bb_i2c_set_ack, \ + } + +int +lws_bb_i2c_init(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_start(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_stop(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data); + +int +lws_bb_i2c_read(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack); diff --git a/thirdparty/include/libwebsockets/lws-bb-spi.h b/thirdparty/include/libwebsockets/lws-bb-spi.h new file mode 100755 index 0000000000000000000000000000000000000000..52c801c6a908aa99394a046e6619edd548a8c78d --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-bb-spi.h @@ -0,0 +1,62 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#define LWSBBSPI_FLAG_USE_NCMD3 (1 << 7) +#define LWSBBSPI_FLAG_USE_NCMD2 (1 << 6) +#define LWSBBSPI_FLAG_USE_NCMD1 (1 << 5) +#define LWSBBSPI_FLAG_USE_NCMD0 (1 << 4) +#define LWSBBSPI_FLAG_USE_NCS3 (1 << 3) +#define LWSBBSPI_FLAG_USE_NCS2 (1 << 2) +#define LWSBBSPI_FLAG_USE_NCS1 (1 << 1) +#define LWSBBSPI_FLAG_USE_NCS0 (1 << 0) + +#define LWS_SPI_BB_MAX_CH 4 + +typedef struct lws_bb_spi { + lws_spi_ops_t bb_ops; /* init to lws_bb_spi_ops */ + + /* implementation-specific members */ + const lws_gpio_ops_t *gpio; + + _lws_plat_gpio_t clk; + _lws_plat_gpio_t ncs[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t ncmd[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t mosi; + _lws_plat_gpio_t miso; + + uint8_t flags; +} lws_bb_spi_t; + +#define lws_bb_spi_ops \ + .init = lws_bb_spi_init, \ + .queue = lws_bb_spi_queue + +int +lws_bb_spi_init(const lws_spi_ops_t *octx); + +int +lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc); diff --git a/thirdparty/include/libwebsockets/lws-button.h b/thirdparty/include/libwebsockets/lws-button.h new file mode 100755 index 0000000000000000000000000000000000000000..e1981423e01f55003d23f8a1e869a74360352b75 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-button.h @@ -0,0 +1,120 @@ +/* + * Generic button ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * Leverages the lws generic gpio pieces to bind gpio buttons to smd events + */ + +#if !defined(__LWS_BUTTON_H__) +#define __LWS_BUTTON_H__ + +typedef uint16_t lws_button_idx_t; + +/* actual minimum may be 1 x RTOS tick depending on platform */ +#define LWS_BUTTON_MON_TIMER_MS 5 + +typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state); + +/* These are specified in ms but the granularity is LWS_BUTTON_MON_TIMER_MS, + * which may have been rounded up to an RTOS tick depending on platform */ + +enum { + LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK = (1 << 0) +}; + +typedef struct lws_button_regime { + uint16_t ms_min_down; + uint16_t ms_min_down_longpress; + uint16_t ms_up_settle; + uint16_t ms_doubleclick_grace; + uint16_t ms_repeat_down; + uint8_t flags; + /**< when double-click classification is enabled, clicks are delayed + * by ms_min_down + ms_doubleclick_grace to wait and see if it will + * become a double-click. Set LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK to + * enable it or leave that bit at 0 to get faster single-click + * classification. + */ +} lws_button_regime_t; + +/* + * This is the const part of the button controller, describing the static + * bindings to gpio, and lws_smd event name information + */ + +typedef struct lws_button_map { + _lws_plat_gpio_t gpio; + const char *smd_interaction_name; + const lws_button_regime_t *regime; + /**< a default regime is applied if this is left NULL */ +} lws_button_map_t; + +typedef struct lws_button_controller { + const char *smd_bc_name; + const lws_gpio_ops_t *gpio_ops; + const lws_button_map_t *button_map; + lws_button_idx_t active_state_bitmap; + uint8_t count_buttons; +} lws_button_controller_t; + +struct lws_button_state; /* opaque */ + +/** + * lws_button_controller_create() - instantiate a button controller + * + * \param ctx: the lws_context + * \param controller: the static controller definition + * + * Instantiates a button controller from a static definition of the buttons + * and their smd names, and active levels, and binds it to a gpio implementation + */ + +LWS_VISIBLE LWS_EXTERN struct lws_button_state * +lws_button_controller_create(struct lws_context *ctx, + const lws_button_controller_t *controller); + +/** + * lws_button_controller_destroy() - destroys a button controller + * + * \param bcs: button controller state previously created + * + * Disables all buttons and then destroys and frees a previously created + * button controller. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_controller_destroy(struct lws_button_state *bcs); + + +LWS_VISIBLE LWS_EXTERN lws_button_idx_t +lws_button_get_bit(struct lws_button_state *bcs, const char *name); + +/* + * lws_button_enable() - enable and disable buttons + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_enable(struct lws_button_state *bcs, + lws_button_idx_t _reset, lws_button_idx_t _set); + +#endif + diff --git a/thirdparty/include/libwebsockets/lws-cache-ttl.h b/thirdparty/include/libwebsockets/lws-cache-ttl.h new file mode 100755 index 0000000000000000000000000000000000000000..9942dc7d79c43e35df9b9793f192b84fc50203db --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-cache-ttl.h @@ -0,0 +1,348 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/** \defgroup lws_cache_ttl Cache supporting expiry + * ##Cache supporting expiry + * + * These apis let you quickly and reliably implement caches of named objects, + * that have a "destroy-by date" and cache limits that will be observed. + * + * You can instantiate as many caches as you need. The first one must be an + * L1 / heap cache type, it can have parents and grandparents of other types + * which are accessible why writing / looking up and getting from the L1 cache. + * The outer "cache" layer may persistently store items to a backing store. + * + * Allocated object memory is entirely for the use of user code, up to the + * requested size. + * + * The key name for the listed objects may be any string chosen by the user, + * there is no special length limit as it is also allocated. + * + * Both expiry and LRU orderings are kept so it is easy to find out usage + * ordering and when the next object that will expire. + * + * Cached objects may be destroyed any time you go around the event loop, when + * you allocate new objects (to keep the whole cache under the specified limit), + * or when their expiry time arrives. So you shouldn't keep copies of pointers + * to cached objects after returning to the event loop. + */ +///@{ + + +struct lws_cache_ttl_lru; + +/** + * lws_cache_write_through() - add a new cache item object in all layers + * + * \param cache: the existing cache to allocate the object in + * \param specific_key: a key string that identifies the item in the cache + * \param source: optional payload for the cached item, NULL means caller will + * write the payload + * \param size: the size of the object to allocate + * \param expiry: the usec time that the object will autodestroy + * \param ppay: NULL, or a pointer to a void * to be set to the L1 payload + * + * If an item with the key already exists, it is destroyed before allocating a + * new one. + * + * Returns 0 if successful. The written entry will be scheduled to be auto- + * destroyed when \p expiry occurs. + * + * Adding or removing cache items may cause invalidation of cached queries. + */ +LWS_VISIBLE LWS_EXTERN int /* only valid until return to event loop */ +lws_cache_write_through(struct lws_cache_ttl_lru *cache, + const char *specific_key, const uint8_t *source, + size_t size, lws_usec_t expiry, void **ppay); + +typedef struct lws_cache_match { + lws_dll2_t list; + lws_usec_t expiry; + /* earliest expiry amongst results */ + size_t payload_size; + /**< the payload is not attached here. This is a hint about what + * (*get)() will return for this tag name. + */ + size_t tag_size; + + /* tag name + NUL is overcommitted */ +} lws_cache_match_t; + +/** + * lws_cache_heap_lookup() - get a list of matching items + * + * \param cache: the cache to search for the key + * \param wildcard_key: the item key string, may contain wildcards + * \param pdata: pointer to pointer to be set to the serialized result list + * \param psize: pointer to size_t to receive length of serialized result list + * + * This finds all unique items in the final cache that match search_key, which + * may contain wildcards. It does not return the payloads for matching items, + * just a list of specific tags in the that match. + * + * If successful, results are provided in a serialized list format, in no + * particular order, each result has the following fields + * + * - BE32: payload size in bytes (payload itself is not included) + * - BE32: specific tag name length in bytes + * - chars: tag name with terminating NUL + * + * These serialized results are themselves cached in L1 cache (only) and the + * result pointers are set pointing into that. If the results are still in L1 + * cache next time this api is called, the results will be returned directly + * from that without repeating the expensive lookup on the backup store. That + * is why the results are provided in serialized form. + * + * The cached results list expiry is set to the earliest expiry of any listed + * item. Additionally any cached results are invalidated on addition or + * deletion (update is done as addition + deletion) of any item that would + * match the results' original wildcard_key. For the typical case new items + * are rare compared to lookups, this is efficient. + * + * Lookup matching does not itself affect LRU or cache status of the result + * itsems. Typically user code will get the lookup results, and then perform + * get operations on each item in its desired order, that will bring the items + * to the head of the LRU list and occupy L1 cache. + * + * Returns 0 if proceeded alright, or nonzero if error. If there was an error, + * any partial results set has been deallocated cleanly before returning. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + const void **pdata, size_t *psize); + +/** + * lws_cache_item_get() - bring a specific item into L1 and get payload info + * + * \param cache: the cache to search for the key + * \param specific_key: the key string of the item to get + * \param pdata: pointer to a void * to be set to the payload in L1 cache + * \param psize: pointer to a size_t to be set to the payload size + * + * If the cache still has an item matching the key string, it will be destroyed. + * + * Adding or removing cache items may cause invalidation of cached queries. + * + * Notice the cache payload is a blob of the given size. If you are storing + * strings, there is no NUL termination unless you stored them with it. + * + * Returns 0 if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize); + +/** + * lws_cache_item_remove() - remove item from all cache levels + * + * \param cache: the cache to search for the key + * \param wildcard_key: the item key string + * + * Removes any copy of any item matching the \p wildcard_key from any cache + * level in one step. + * + * Adding or removing cache items may cause invalidation of cached queries + * that could refer to the removed item. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key); + +/** + * lws_cache_footprint() - query the amount of storage used by the cache layer + * + * \param cache: cache to query + * + * Returns number of payload bytes stored in cache currently + */ +LWS_VISIBLE LWS_EXTERN uint64_t +lws_cache_footprint(struct lws_cache_ttl_lru *cache); + +/** + * lws_cache_debug_dump() - if built in debug mode dump cache contents to log + * + * \param cache: cache to dump + * + * If lws was built in debug mode, dump cache to log, otherwise a NOP. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cache_debug_dump(struct lws_cache_ttl_lru *cache); + +typedef struct lws_cache_results { + const uint8_t *ptr; /* set before using walk api */ + size_t size; /* set before using walk api */ + + size_t payload_len; + size_t tag_len; + const uint8_t *tag; +} lws_cache_results_t; + +/** + * lws_cache_results_walk() - parse next result + * + * \param walk_ctx: the context of the results blob to walk + * + * Caller must initialize \p walk_ctx.ptr and \p walk_ctx.size before calling. + * These are set to the results returned from a _lookup api call. + * + * The call returns 0 if the struct elements have been set to a result, or 1 + * if there where no more results in the blob to walk. + * + * If successful, after the call \p payload_len is set to the length of the + * payload related to this result key (the payload itself is not present), + * \p tag_len is set to the length of the result key name, and \p tag is set + * to the result tag name, with a terminating NUL. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_results_walk(lws_cache_results_t *walk_ctx); + +typedef void (*lws_cache_item_destroy_cb)(void *item, size_t size); +struct lws_cache_creation_info { + struct lws_context *cx; + /**< Mandatory: the lws_context */ + const char *name; + /**< Mandatory: short cache name */ + lws_cache_item_destroy_cb cb; + /**< NULL, or a callback that can hook cache item destory */ + struct lws_cache_ttl_lru *parent; + /**< NULL, or next cache level */ + const struct lws_cache_ops *ops; + /**< NULL for default, heap-based ops, else custom cache storage and + * query implementation */ + + union { + struct { + const char *filepath; + /**< the filepath to store items in */ + } nscookiejar; + } u; + /**< these are extra configuration for specific cache types */ + + size_t max_footprint; + /**< 0, or the max heap allocation allowed before destroying + * lru items to keep it under the limit */ + size_t max_items; + /**< 0, or the max number of items allowed in the cache before + * destroying lru items to keep it under the limit */ + size_t max_payload; + /**< 0, or the max allowed payload size for one item */ + int tsi; + /**< 0 unless using SMP, then tsi to bind sul to */ +}; + +struct lws_cache_ops { + struct lws_cache_ttl_lru * + (*create)(const struct lws_cache_creation_info *info); + /**< create an instance of the cache type specified in info */ + + void + (*destroy)(struct lws_cache_ttl_lru **_cache); + /**< destroy the logical cache instance pointed to by *_cache, doesn't + * affect any NV backing storage */ + + int + (*expunge)(struct lws_cache_ttl_lru *cache); + /**< completely delete any backing storage related to the cache + * instance, eg, delete the backing file */ + + int + (*write)(struct lws_cache_ttl_lru *cache, const char *specific_key, + const uint8_t *source, size_t size, lws_usec_t expiry, + void **ppvoid); + /**< create an entry in the cache level according to the given info */ + int + (*tag_match)(struct lws_cache_ttl_lru *cache, const char *wc, + const char *tag, char lookup_rules); + /**< Just tell us if tag would match wildcard, using whatever special + * rules the backing store might use for tag matching. 0 indicates + * it is a match on wildcard, nonzero means does not match. + */ + int + (*lookup)(struct lws_cache_ttl_lru *cache, const char *wildcard_key, + lws_dll2_owner_t *results_owner); + /**+ add keys for search_key matches not already listed in the results + * owner */ + int + (*invalidate)(struct lws_cache_ttl_lru *cache, const char *wildcard_key); + /**< remove matching item(s) from cache level */ + + int + (*get)(struct lws_cache_ttl_lru *cache, const char *specific_key, + const void **pdata, size_t *psize); + /**< if it has the item, fills L1 with item. updates LRU, and returns + * pointer to payload in L1 */ + + void + (*debug_dump)(struct lws_cache_ttl_lru *cache); + /**< Helper to dump the whole cache contents to log, useful for debug */ +}; + +/** + * lws_cache_create() - create an empty cache you can allocate items in + * + * \param info: a struct describing the cache to create + * + * Create an empty cache you can allocate items in. The cache will be kept + * below the max_footprint and max_items limits if they are nonzero, by + * destroying least-recently-used items until it remains below the limits. + * + * Items will auto-destroy when their expiry time is reached. + * + * When items are destroyed from the cache, if \p cb is non-NULL, it will be + * called back with the item pointer after it has been removed from the cache, + * but before it is deallocated and destroyed. + * + * context and tsi are used when scheduling expiry callbacks + */ +LWS_VISIBLE LWS_EXTERN struct lws_cache_ttl_lru * +lws_cache_create(const struct lws_cache_creation_info *info); + +/** + * lws_cache_destroy() - destroy a previously created cache + * + * \param cache: pointer to the cache + * + * Everything in the cache is destroyed, then the cache itself is destroyed, + * and *cache set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cache_destroy(struct lws_cache_ttl_lru **cache); + +/** + * lws_cache_expunge() - destroy all items in cache and parents + * + * \param cache: pointer to the cache + * + * Everything in the cache and parents is destroyed, leaving it empty. + * If the cache has a backing store, it is deleted. + * + * Returns 0 if no problems reported at any cache layer, else nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_cache_expunge(struct lws_cache_ttl_lru *cache); + +LWS_VISIBLE extern const struct lws_cache_ops lws_cache_ops_heap, + lws_cache_ops_nscookiejar; + +///@} + diff --git a/thirdparty/include/libwebsockets/lws-callbacks.h b/thirdparty/include/libwebsockets/lws-callbacks.h new file mode 100755 index 0000000000000000000000000000000000000000..62848fa5ae59c68a276cbfcbcfc97891ada77f99 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-callbacks.h @@ -0,0 +1,924 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup usercb User Callback + * + * ##User protocol callback + * + * The protocol callback is the primary way lws interacts with + * user code. For one of a list of a few dozen reasons the callback gets + * called at some event to be handled. + * + * All of the events can be ignored, returning 0 is taken as "OK" and returning + * nonzero in most cases indicates that the connection should be closed. + */ +///@{ + +struct lws_ssl_info { + int where; + int ret; +}; + +enum lws_cert_update_state { + LWS_CUS_IDLE, + LWS_CUS_STARTING, + LWS_CUS_SUCCESS, + LWS_CUS_FAILED, + + LWS_CUS_CREATE_KEYS, + LWS_CUS_REG, + LWS_CUS_AUTH, + LWS_CUS_CHALLENGE, + LWS_CUS_CREATE_REQ, + LWS_CUS_REQ, + LWS_CUS_CONFIRM, + LWS_CUS_ISSUE, +}; + +enum { + LWS_TLS_REQ_ELEMENT_COUNTRY, + LWS_TLS_REQ_ELEMENT_STATE, + LWS_TLS_REQ_ELEMENT_LOCALITY, + LWS_TLS_REQ_ELEMENT_ORGANIZATION, + LWS_TLS_REQ_ELEMENT_COMMON_NAME, + LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME, + LWS_TLS_REQ_ELEMENT_EMAIL, + + LWS_TLS_REQ_ELEMENT_COUNT, + + LWS_TLS_SET_DIR_URL = LWS_TLS_REQ_ELEMENT_COUNT, + LWS_TLS_SET_AUTH_PATH, + LWS_TLS_SET_CERT_PATH, + LWS_TLS_SET_KEY_PATH, + + LWS_TLS_TOTAL_COUNT +}; + +struct lws_acme_cert_aging_args { + struct lws_vhost *vh; + const char *element_overrides[LWS_TLS_TOTAL_COUNT]; /* NULL = use pvo */ +}; + +/* + * With LWS_CALLBACK_FILTER_NETWORK_CONNECTION callback, user_data pointer + * points to one of these + */ + +struct lws_filter_network_conn_args { + struct sockaddr_storage cli_addr; + socklen_t clilen; + lws_sockfd_type accept_fd; +}; + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +/** enum lws_callback_reasons - reason you're getting a protocol callback */ +enum lws_callback_reasons { + + /* --------------------------------------------------------------------- + * ----- Callbacks related to wsi and protocol binding lifecycle ----- + */ + + LWS_CALLBACK_PROTOCOL_INIT = 27, + /**< One-time call per protocol, per-vhost using it, so it can + * do initial setup / allocations etc */ + + LWS_CALLBACK_PROTOCOL_DESTROY = 28, + /**< One-time call per protocol, per-vhost using it, indicating + * this protocol won't get used at all after this callback, the + * vhost is getting destroyed. Take the opportunity to + * deallocate everything that was allocated by the protocol. */ + + LWS_CALLBACK_WSI_CREATE = 29, + /**< outermost (earliest) wsi create notification to protocols[0] */ + + LWS_CALLBACK_WSI_DESTROY = 30, + /**< outermost (latest) wsi destroy notification to protocols[0] */ + + LWS_CALLBACK_WSI_TX_CREDIT_GET = 103, + /**< manually-managed connection received TX credit (len is int32) */ + + + /* --------------------------------------------------------------------- + * ----- Callbacks related to Server TLS ----- + */ + + LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS = 21, + /**< if configured for + * including OpenSSL support, this callback allows your user code + * to perform extra SSL_CTX_load_verify_locations() or similar + * calls to direct OpenSSL where to find certificates the client + * can use to confirm the remote server identity. user is the + * OpenSSL SSL_CTX* */ + + LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS = 22, + /**< if configured for + * including OpenSSL support, this callback allows your user code + * to load extra certificates into the server which allow it to + * verify the validity of certificates returned by clients. user + * is the server's OpenSSL SSL_CTX* and in is the lws_vhost */ + + LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION = 23, + /**< if the libwebsockets vhost was created with the option + * LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this + * callback is generated during OpenSSL verification of the cert + * sent from the client. It is sent to protocol[0] callback as + * no protocol has been negotiated on the connection yet. + * Notice that the libwebsockets context and wsi are both NULL + * during this callback. See + * http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html + * to understand more detail about the OpenSSL callback that + * generates this libwebsockets callback and the meanings of the + * arguments passed. In this callback, user is the x509_ctx, + * in is the ssl pointer and len is preverify_ok + * Notice that this callback maintains libwebsocket return + * conventions, return 0 to mean the cert is OK or 1 to fail it. + * This also means that if you don't handle this callback then + * the default callback action of returning 0 allows the client + * certificates. */ + + LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY = 37, + /**< if configured for including OpenSSL support but no private key + * file has been specified (ssl_private_key_filepath is NULL), this is + * called to allow the user to set the private key directly via + * libopenssl and perform further operations if required; this might be + * useful in situations where the private key is not directly accessible + * by the OS, for example if it is stored on a smartcard. + * user is the server's OpenSSL SSL_CTX* */ + + LWS_CALLBACK_SSL_INFO = 67, + /**< SSL connections only. An event you registered an + * interest in at the vhost has occurred on a connection + * using the vhost. in is a pointer to a + * struct lws_ssl_info containing information about the + * event*/ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to Client TLS ----- + */ + + LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION = 58, + /**< Similar to LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION + * this callback is called during OpenSSL verification of the cert + * sent from the server to the client. It is sent to protocol[0] + * callback as no protocol has been negotiated on the connection yet. + * Notice that the wsi is set because lws_client_connect_via_info was + * successful. + * + * See http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html + * to understand more detail about the OpenSSL callback that + * generates this libwebsockets callback and the meanings of the + * arguments passed. In this callback, user is the x509_ctx, + * in is the ssl pointer and len is preverify_ok. + * + * THIS IS NOT RECOMMENDED BUT if a cert validation error shall be + * overruled and cert shall be accepted as ok, + * X509_STORE_CTX_set_error((X509_STORE_CTX*)user, X509_V_OK); must be + * called and return value must be 0 to mean the cert is OK; + * returning 1 will fail the cert in any case. + * + * This also means that if you don't handle this callback then + * the default callback action of returning 0 will not accept the + * certificate in case of a validation error decided by the SSL lib. + * + * This is expected and secure behaviour when validating certificates. + * + * Note: LCCSCF_ALLOW_SELFSIGNED and + * LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK still work without this + * callback being implemented. + */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to HTTP Server ----- + */ + + LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED = 19, + /**< A new client has been accepted by the ws server. This + * callback allows setting any relevant property to it. Because this + * happens immediately after the instantiation of a new client, + * there's no websocket protocol selected yet so this callback is + * issued only to protocol 0. Only wsi is defined, pointing to the + * new client, and the return value is ignored. */ + + LWS_CALLBACK_HTTP = 12, + /**< an http request has come from a client that is not + * asking to upgrade the connection to a websocket + * one. This is a chance to serve http content, + * for example, to send a script to the client + * which will then open the websockets connection. + * in points to the URI path requested and + * lws_serve_http_file() makes it very + * simple to send back a file to the client. + * Normally after sending the file you are done + * with the http connection, since the rest of the + * activity will come by websockets from the script + * that was delivered by http, so you will want to + * return 1; to close and free up the connection. */ + + LWS_CALLBACK_HTTP_BODY = 13, + /**< the next len bytes data from the http + * request body HTTP connection is now available in in. */ + + LWS_CALLBACK_HTTP_BODY_COMPLETION = 14, + /**< the expected amount of http request body has been delivered */ + + LWS_CALLBACK_HTTP_FILE_COMPLETION = 15, + /**< a file requested to be sent down http link has completed. */ + + LWS_CALLBACK_HTTP_WRITEABLE = 16, + /**< you can write more down the http protocol link now. */ + + LWS_CALLBACK_CLOSED_HTTP = 5, + /**< when a HTTP (non-websocket) session ends */ + + LWS_CALLBACK_FILTER_HTTP_CONNECTION = 18, + /**< called when the request has + * been received and parsed from the client, but the response is + * not sent yet. Return non-zero to disallow the connection. + * user is a pointer to the connection user space allocation, + * in is the URI, eg, "/" + * In your handler you can use the public APIs + * lws_hdr_total_length() / lws_hdr_copy() to access all of the + * headers using the header enums lws_token_indexes from + * libwebsockets.h to check for and read the supported header + * presence and content before deciding to allow the http + * connection to proceed or to kill the connection. */ + + LWS_CALLBACK_ADD_HEADERS = 53, + /**< This gives your user code a chance to add headers to a server + * transaction bound to your protocol. `in` points to a + * `struct lws_process_html_args` describing a buffer and length + * you can add headers into using the normal lws apis. + * + * (see LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to add headers to + * a client transaction) + * + * Only `args->p` and `args->len` are valid, and `args->p` should + * be moved on by the amount of bytes written, if any. Eg + * + * case LWS_CALLBACK_ADD_HEADERS: + * + * struct lws_process_html_args *args = + * (struct lws_process_html_args *)in; + * + * if (lws_add_http_header_by_name(wsi, + * (unsigned char *)"set-cookie:", + * (unsigned char *)cookie, cookie_len, + * (unsigned char **)&args->p, + * (unsigned char *)args->p + args->max_len)) + * return 1; + * + * break; + */ + + LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION = 102, + /**< This gives the user code a chance to accept or reject credentials + * provided HTTP to basic authorization. It will only be called if the + * http mount's authentication_mode is set to LWSAUTHM_BASIC_AUTH_CALLBACK + * `in` points to a credential string of the form `username:password` If + * the callback returns zero (the default if unhandled), then the + * transaction ends with HTTP_STATUS_UNAUTHORIZED, otherwise the request + * will be processed */ + + LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 51, + /**< This gives the user code a chance to forbid an http access. + * `in` points to a `struct lws_process_html_args`, which + * describes the URL, and a bit mask describing the type of + * authentication required. If the callback returns nonzero, + * the transaction ends with HTTP_STATUS_UNAUTHORIZED. */ + + LWS_CALLBACK_PROCESS_HTML = 52, + /**< This gives your user code a chance to mangle outgoing + * HTML. `in` points to a `struct lws_process_html_args` + * which describes the buffer containing outgoing HTML. + * The buffer may grow up to `.max_len` (currently +128 + * bytes per buffer). + */ + + LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49, + /**< By default, all HTTP handling is done in protocols[0]. + * However you can bind different protocols (by name) to + * different parts of the URL space using callback mounts. This + * callback occurs in the new protocol when a wsi is bound + * to that protocol. Any protocol allocation related to the + * http transaction processing should be created then. + * These specific callbacks are necessary because with HTTP/1.1, + * a single connection may perform at series of different + * transactions at different URLs, thus the lifetime of the + * protocol bind is just for one transaction, not connection. */ + + LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50, + /**< This is called when a transaction is unbound from a protocol. + * It indicates the connection completed its transaction and may + * do something different now. Any protocol allocation related + * to the http transaction processing should be destroyed. */ + + LWS_CALLBACK_HTTP_CONFIRM_UPGRADE = 86, + /**< This is your chance to reject an HTTP upgrade action. The + * name of the protocol being upgraded to is in 'in', and the ah + * is still bound to the wsi, so you can look at the headers. + * + * The default of returning 0 (ie, also if not handled) means the + * upgrade may proceed. Return <0 to just hang up the connection, + * or >0 if you have rejected the connection by returning http headers + * and response code yourself. + * + * There is no need for you to call transaction_completed() as the + * caller will take care of it when it sees you returned >0. + */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to HTTP Client ----- + */ + + LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP = 44, + /**< The HTTP client connection has succeeded, and is now + * connected to the server */ + + LWS_CALLBACK_CLOSED_CLIENT_HTTP = 45, + /**< The HTTP client connection is closing */ + + LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ = 48, + /**< This is generated by lws_http_client_read() used to drain + * incoming data. In the case the incoming data was chunked, it will + * be split into multiple smaller callbacks for each chunk block, + * removing the chunk headers. If not chunked, it will appear all in + * one callback. */ + + LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46, + /**< This indicates data was received on the HTTP client connection. It + * does NOT actually drain or provide the data, so if you are doing + * http client, you MUST handle this and call lws_http_client_read(). + * Failure to deal with it as in the minimal examples may cause spinning + * around the event loop as it's continuously signalled the same data + * is available for read. The related minimal examples show how to + * handle it. + * + * It's possible to defer calling lws_http_client_read() if you use + * rx flow control to stop further rx handling on the connection until + * you did deal with it. But normally you would call it in the handler. + * + * lws_http_client_read() strips any chunked framing and calls back + * with only payload data to LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ. The + * chunking is the reason this is not just all done in one callback for + * http. + */ + LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47, + /**< The client transaction completed... at the moment this + * is the same as closing since transaction pipelining on + * client side is not yet supported. */ + + LWS_CALLBACK_CLIENT_HTTP_WRITEABLE = 57, + /**< when doing an HTTP type client connection, you can call + * lws_client_http_body_pending(wsi, 1) from + * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to get these callbacks + * sending the HTTP headers. + * + * From this callback, when you have sent everything, you should let + * lws know by calling lws_client_http_body_pending(wsi, 0) + */ + + LWS_CALLBACK_CLIENT_HTTP_REDIRECT = 104, + /**< we're handling a 3xx redirect... return nonzero to hang up */ + + LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL = 85, + LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL = 76, + + /* --------------------------------------------------------------------- + * ----- Callbacks related to Websocket Server ----- + */ + + LWS_CALLBACK_ESTABLISHED = 0, + /**< (VH) after the server completes a handshake with an incoming + * client. If you built the library with ssl support, in is a + * pointer to the ssl struct associated with the connection or NULL. + * + * b0 of len is set if the connection was made using ws-over-h2 + */ + + LWS_CALLBACK_CLOSED = 4, + /**< when the websocket session ends */ + + LWS_CALLBACK_SERVER_WRITEABLE = 11, + /**< See LWS_CALLBACK_CLIENT_WRITEABLE */ + + LWS_CALLBACK_RECEIVE = 6, + /**< data has appeared for this server endpoint from a + * remote client, it can be found at *in and is + * len bytes long */ + + LWS_CALLBACK_RECEIVE_PONG = 7, + /**< servers receive PONG packets with this callback reason */ + + LWS_CALLBACK_WS_PEER_INITIATED_CLOSE = 38, + /**< The peer has sent an unsolicited Close WS packet. in and + * len are the optional close code (first 2 bytes, network + * order) and the optional additional information which is not + * defined in the standard, and may be a string or non human-readable + * data. + * If you return 0 lws will echo the close and then close the + * connection. If you return nonzero lws will just close the + * connection. */ + + LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION = 20, + /**< called when the handshake has + * been received and parsed from the client, but the response is + * not sent yet. Return non-zero to disallow the connection. + * user is a pointer to the connection user space allocation, + * in is the requested protocol name + * In your handler you can use the public APIs + * lws_hdr_total_length() / lws_hdr_copy() to access all of the + * headers using the header enums lws_token_indexes from + * libwebsockets.h to check for and read the supported header + * presence and content before deciding to allow the handshake + * to proceed or to kill the connection. */ + + LWS_CALLBACK_CONFIRM_EXTENSION_OKAY = 25, + /**< When the server handshake code + * sees that it does support a requested extension, before + * accepting the extension by additing to the list sent back to + * the client it gives this callback just to check that it's okay + * to use that extension. It calls back to the requested protocol + * and with in being the extension name, len is 0 and user is + * valid. Note though at this time the ESTABLISHED callback hasn't + * happened yet so if you initialize user content there, user + * content during this callback might not be useful for anything. */ + + LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL = 77, + LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL = 78, + + /* --------------------------------------------------------------------- + * ----- Callbacks related to Websocket Client ----- + */ + + LWS_CALLBACK_CLIENT_CONNECTION_ERROR = 1, + /**< the request client connection has been unable to complete a + * handshake with the remote server. If in is non-NULL, you can + * find an error string of length len where it points to + * + * Diagnostic strings that may be returned include + * + * "getaddrinfo (ipv6) failed" + * "unknown address family" + * "getaddrinfo (ipv4) failed" + * "set socket opts failed" + * "insert wsi failed" + * "lws_ssl_client_connect1 failed" + * "lws_ssl_client_connect2 failed" + * "Peer hung up" + * "read failed" + * "HS: URI missing" + * "HS: Redirect code but no Location" + * "HS: URI did not parse" + * "HS: Redirect failed" + * "HS: Server did not return 200" + * "HS: OOM" + * "HS: disallowed by client filter" + * "HS: disallowed at ESTABLISHED" + * "HS: ACCEPT missing" + * "HS: ws upgrade response not 101" + * "HS: UPGRADE missing" + * "HS: Upgrade to something other than websocket" + * "HS: CONNECTION missing" + * "HS: UPGRADE malformed" + * "HS: PROTOCOL malformed" + * "HS: Cannot match protocol" + * "HS: EXT: list too big" + * "HS: EXT: failed setting defaults" + * "HS: EXT: failed parsing defaults" + * "HS: EXT: failed parsing options" + * "HS: EXT: Rejects server options" + * "HS: EXT: unknown ext" + * "HS: Accept hash wrong" + * "HS: Rejected by filter cb" + * "HS: OOM" + * "HS: SO_SNDBUF failed" + * "HS: Rejected at CLIENT_ESTABLISHED" + */ + + LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH = 2, + /**< this is the last chance for the client user code to examine the + * http headers and decide to reject the connection. If the + * content in the headers is interesting to the + * client (url, etc) it needs to copy it out at + * this point since it will be destroyed before + * the CLIENT_ESTABLISHED call */ + + LWS_CALLBACK_CLIENT_ESTABLISHED = 3, + /**< after your client connection completed the websocket upgrade + * handshake with the remote server */ + + LWS_CALLBACK_CLIENT_CLOSED = 75, + /**< when a client websocket session ends */ + + LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER = 24, + /**< this callback happens + * when a client handshake is being compiled. user is NULL, + * in is a char **, it's pointing to a char * which holds the + * next location in the header buffer where you can add + * headers, and len is the remaining space in the header buffer, + * which is typically some hundreds of bytes. So, to add a canned + * cookie, your handler code might look similar to: + * + * char **p = (char **)in, *end = (*p) + len; + * + * if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COOKIE, + * (unsigned char)"a=b", 3, p, end)) + * return -1; + * + * See LWS_CALLBACK_ADD_HEADERS for adding headers to server + * transactions. + */ + + LWS_CALLBACK_CLIENT_RECEIVE = 8, + /**< data has appeared from the server for the client connection, it + * can be found at *in and is len bytes long */ + + LWS_CALLBACK_CLIENT_RECEIVE_PONG = 9, + /**< clients receive PONG packets with this callback reason */ + + LWS_CALLBACK_CLIENT_WRITEABLE = 10, + /**< If you call lws_callback_on_writable() on a connection, you will + * get one of these callbacks coming when the connection socket + * is able to accept another write packet without blocking. + * If it already was able to take another packet without blocking, + * you'll get this callback at the next call to the service loop + * function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE + * and servers get LWS_CALLBACK_SERVER_WRITEABLE. */ + + LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED = 26, + /**< When a ws client + * connection is being prepared to start a handshake to a server, + * each supported extension is checked with protocols[0] callback + * with this reason, giving the user code a chance to suppress the + * claim to support that extension by returning non-zero. If + * unhandled, by default 0 will be returned and the extension + * support included in the header to the server. Notice this + * callback comes to protocols[0]. */ + + LWS_CALLBACK_WS_EXT_DEFAULTS = 39, + /**< Gives client connections an opportunity to adjust negotiated + * extension defaults. `user` is the extension name that was + * negotiated (eg, "permessage-deflate"). `in` points to a + * buffer and `len` is the buffer size. The user callback can + * set the buffer to a string describing options the extension + * should parse. Or just ignore for defaults. */ + + + LWS_CALLBACK_FILTER_NETWORK_CONNECTION = 17, + /**< called when a client connects to + * the server at network level; the connection is accepted but then + * passed to this callback to decide whether to hang up immediately + * or not, based on the client IP. + * + * user_data in the callback points to a + * struct lws_filter_network_conn_args that is prepared with the + * sockfd, and the peer's address information. + * + * in contains the connection socket's descriptor. + * + * Since the client connection information is not available yet, + * wsi still pointing to the main server socket. + * + * Return non-zero to terminate the connection before sending or + * receiving anything. Because this happens immediately after the + * network connection from the client, there's no websocket protocol + * selected yet so this callback is issued only to protocol 0. */ + + LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL = 79, + LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL = 80, + + /* --------------------------------------------------------------------- + * ----- Callbacks related to external poll loop integration ----- + */ + + LWS_CALLBACK_GET_THREAD_ID = 31, + /**< lws can accept callback when writable requests from other + * threads, if you implement this callback and return an opaque + * current thread ID integer. */ + + /* external poll() management support */ + LWS_CALLBACK_ADD_POLL_FD = 32, + /**< lws normally deals with its poll() or other event loop + * internally, but in the case you are integrating with another + * server you will need to have lws sockets share a + * polling array with the other server. This and the other + * POLL_FD related callbacks let you put your specialized + * poll array interface code in the callback for protocol 0, the + * first protocol you support, usually the HTTP protocol in the + * serving case. + * This callback happens when a socket needs to be + * added to the polling loop: in points to a struct + * lws_pollargs; the fd member of the struct is the file + * descriptor, and events contains the active events + * + * If you are using the internal lws polling / event loop + * you can just ignore these callbacks. */ + + LWS_CALLBACK_DEL_POLL_FD = 33, + /**< This callback happens when a socket descriptor + * needs to be removed from an external polling array. in is + * again the struct lws_pollargs containing the fd member + * to be removed. If you are using the internal polling + * loop, you can just ignore it. */ + + LWS_CALLBACK_CHANGE_MODE_POLL_FD = 34, + /**< This callback happens when lws wants to modify the events for + * a connection. + * in is the struct lws_pollargs with the fd to change. + * The new event mask is in events member and the old mask is in + * the prev_events member. + * If you are using the internal polling loop, you can just ignore + * it. */ + + LWS_CALLBACK_LOCK_POLL = 35, + /**< These allow the external poll changes driven + * by lws to participate in an external thread locking + * scheme around the changes, so the whole thing is threadsafe. + * These are called around three activities in the library, + * - inserting a new wsi in the wsi / fd table (len=1) + * - deleting a wsi from the wsi / fd table (len=1) + * - changing a wsi's POLLIN/OUT state (len=0) + * Locking and unlocking external synchronization objects when + * len == 1 allows external threads to be synchronized against + * wsi lifecycle changes if it acquires the same lock for the + * duration of wsi dereference from the other thread context. */ + + LWS_CALLBACK_UNLOCK_POLL = 36, + /**< See LWS_CALLBACK_LOCK_POLL, ignore if using lws internal poll */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to CGI serving ----- + */ + + LWS_CALLBACK_CGI = 40, + /**< CGI: CGI IO events on stdin / out / err are sent here on + * protocols[0]. The provided `lws_callback_http_dummy()` + * handles this and the callback should be directed there if + * you use CGI. */ + + LWS_CALLBACK_CGI_TERMINATED = 41, + /**< CGI: The related CGI process ended, this is called before + * the wsi is closed. Used to, eg, terminate chunking. + * The provided `lws_callback_http_dummy()` + * handles this and the callback should be directed there if + * you use CGI. The child PID that terminated is in len. */ + + LWS_CALLBACK_CGI_STDIN_DATA = 42, + /**< CGI: Data is, to be sent to the CGI process stdin, eg from + * a POST body. The provided `lws_callback_http_dummy()` + * handles this and the callback should be directed there if + * you use CGI. */ + + LWS_CALLBACK_CGI_STDIN_COMPLETED = 43, + /**< CGI: no more stdin is coming. The provided + * `lws_callback_http_dummy()` handles this and the callback + * should be directed there if you use CGI. */ + + LWS_CALLBACK_CGI_PROCESS_ATTACH = 70, + /**< CGI: Sent when the CGI process is spawned for the wsi. The + * len parameter is the PID of the child process */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to Generic Sessions ----- + */ + + LWS_CALLBACK_SESSION_INFO = 54, + /**< This is only generated by user code using generic sessions. + * It's used to get a `struct lws_session_info` filled in by + * generic sessions with information about the logged-in user. + * See the messageboard sample for an example of how to use. */ + + LWS_CALLBACK_GS_EVENT = 55, + /**< Indicates an event happened to the Generic Sessions session. + * `in` contains a `struct lws_gs_event_args` describing the event. */ + + LWS_CALLBACK_HTTP_PMO = 56, + /**< per-mount options for this connection, called before + * the normal LWS_CALLBACK_HTTP when the mount has per-mount + * options. + */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to RAW PROXY ----- + */ + + LWS_CALLBACK_RAW_PROXY_CLI_RX = 89, + /**< RAW mode client (outgoing) RX */ + + LWS_CALLBACK_RAW_PROXY_SRV_RX = 90, + /**< RAW mode server (listening) RX */ + + LWS_CALLBACK_RAW_PROXY_CLI_CLOSE = 91, + /**< RAW mode client (outgoing) is closing */ + + LWS_CALLBACK_RAW_PROXY_SRV_CLOSE = 92, + /**< RAW mode server (listening) is closing */ + + LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE = 93, + /**< RAW mode client (outgoing) may be written */ + + LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE = 94, + /**< RAW mode server (listening) may be written */ + + LWS_CALLBACK_RAW_PROXY_CLI_ADOPT = 95, + /**< RAW mode client (onward) accepted socket was adopted + * (equivalent to 'wsi created') */ + + LWS_CALLBACK_RAW_PROXY_SRV_ADOPT = 96, + /**< RAW mode server (listening) accepted socket was adopted + * (equivalent to 'wsi created') */ + + LWS_CALLBACK_RAW_PROXY_CLI_BIND_PROTOCOL = 97, + LWS_CALLBACK_RAW_PROXY_SRV_BIND_PROTOCOL = 98, + LWS_CALLBACK_RAW_PROXY_CLI_DROP_PROTOCOL = 99, + LWS_CALLBACK_RAW_PROXY_SRV_DROP_PROTOCOL = 100, + + + /* --------------------------------------------------------------------- + * ----- Callbacks related to RAW sockets ----- + */ + + LWS_CALLBACK_RAW_RX = 59, + /**< RAW mode connection RX */ + + LWS_CALLBACK_RAW_CLOSE = 60, + /**< RAW mode connection is closing */ + + LWS_CALLBACK_RAW_WRITEABLE = 61, + /**< RAW mode connection may be written */ + + LWS_CALLBACK_RAW_ADOPT = 62, + /**< RAW mode connection was adopted (equivalent to 'wsi created') */ + + LWS_CALLBACK_RAW_CONNECTED = 101, + /**< outgoing client RAW mode connection was connected */ + + LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL = 81, + LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL = 82, + + /* --------------------------------------------------------------------- + * ----- Callbacks related to RAW file handles ----- + */ + + LWS_CALLBACK_RAW_ADOPT_FILE = 63, + /**< RAW mode file was adopted (equivalent to 'wsi created') */ + + LWS_CALLBACK_RAW_RX_FILE = 64, + /**< This is the indication the RAW mode file has something to read. + * This doesn't actually do the read of the file and len is always + * 0... your code should do the read having been informed there is + * something to read now. */ + + LWS_CALLBACK_RAW_WRITEABLE_FILE = 65, + /**< RAW mode file is writeable */ + + LWS_CALLBACK_RAW_CLOSE_FILE = 66, + /**< RAW mode wsi that adopted a file is closing */ + + LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL = 83, + LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL = 84, + + /* --------------------------------------------------------------------- + * ----- Callbacks related to generic wsi events ----- + */ + + LWS_CALLBACK_TIMER = 73, + /**< When the time elapsed after a call to + * lws_set_timer_usecs(wsi, usecs) is up, the wsi will get one of + * these callbacks. The deadline can be continuously extended into the + * future by later calls to lws_set_timer_usecs() before the deadline + * expires, or cancelled by lws_set_timer_usecs(wsi, -1); + */ + + LWS_CALLBACK_EVENT_WAIT_CANCELLED = 71, + /**< This is sent to every protocol of every vhost in response + * to lws_cancel_service() or lws_cancel_service_pt(). This + * callback is serialized in the lws event loop normally, even + * if the lws_cancel_service[_pt]() call was from a different + * thread. */ + + LWS_CALLBACK_CHILD_CLOSING = 69, + /**< Sent to parent to notify them a child is closing / being + * destroyed. in is the child wsi. + */ + + LWS_CALLBACK_CONNECTING = 105, + /**< Called before a socketfd is about to connect(). In is the + * socketfd, cast to a (void *), if on a platform where the socketfd + * is an int, recover portably using (lws_sockfd_type)(intptr_t)in. + * + * It's also called in SOCKS5 or http_proxy cases where the socketfd is + * going to try to connect to its proxy. + */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to TLS certificate management ----- + */ + + LWS_CALLBACK_VHOST_CERT_AGING = 72, + /**< When a vhost TLS cert has its expiry checked, this callback + * is broadcast to every protocol of every vhost in case the + * protocol wants to take some action with this information. + * \p in is a pointer to a struct lws_acme_cert_aging_args, + * and \p len is the number of days left before it expires, as + * a (ssize_t). In the struct lws_acme_cert_aging_args, vh + * points to the vhost the cert aging information applies to, + * and element_overrides[] is an optional way to update information + * from the pvos... NULL in an index means use the information from + * from the pvo for the cert renewal, non-NULL in the array index + * means use that pointer instead for the index. */ + + LWS_CALLBACK_VHOST_CERT_UPDATE = 74, + /**< When a vhost TLS cert is being updated, progress is + * reported to the vhost in question here, including completion + * and failure. in points to optional JSON, and len represents the + * connection state using enum lws_cert_update_state */ + + /* --------------------------------------------------------------------- + * ----- Callbacks related to MQTT Client ----- + */ + + LWS_CALLBACK_MQTT_NEW_CLIENT_INSTANTIATED = 200, + LWS_CALLBACK_MQTT_IDLE = 201, + LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED = 202, + LWS_CALLBACK_MQTT_SUBSCRIBED = 203, + LWS_CALLBACK_MQTT_CLIENT_WRITEABLE = 204, + LWS_CALLBACK_MQTT_CLIENT_RX = 205, + LWS_CALLBACK_MQTT_UNSUBSCRIBED = 206, + LWS_CALLBACK_MQTT_DROP_PROTOCOL = 207, + LWS_CALLBACK_MQTT_CLIENT_CLOSED = 208, + LWS_CALLBACK_MQTT_ACK = 209, + /**< When a message is fully sent, if QoS0 this callback is generated + * to locally "acknowledge" it. For QoS1, this callback is only + * generated when the matching PUBACK is received. Return nonzero to + * close the wsi. + */ + LWS_CALLBACK_MQTT_RESEND = 210, + /**< In QoS1 or QoS2, this callback is generated instead of the _ACK one + * if we timed out waiting for a PUBACK or a PUBREC, and we must resend + * the message. Return nonzero to close the wsi. + */ + LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT = 211, + /**< When a UNSUBSCRIBE is sent, this callback is generated instead of + * the _UNSUBSCRIBED one if we timed out waiting for a UNSUBACK. + * Return nonzero to close the wsi. + */ + + /****** add new things just above ---^ ******/ + + LWS_CALLBACK_USER = 1000, + /**< user code can use any including above without fear of clashes */ +}; + + + +/** + * typedef lws_callback_function() - User server actions + * \param wsi: Opaque websocket instance pointer + * \param reason: The reason for the call + * \param user: Pointer to per-session user data allocated by library + * \param in: Pointer used for some callback reasons + * \param len: Length set for some callback reasons + * + * This callback is the way the user controls what is served. All the + * protocol detail is hidden and handled by the library. + * + * For each connection / session there is user data allocated that is + * pointed to by "user". You set the size of this user data area when + * the library is initialized with lws_create_server. + */ +typedef int +lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); + +#define LWS_CB_REASON_AUX_BF__CGI 1 +#define LWS_CB_REASON_AUX_BF__PROXY 2 +#define LWS_CB_REASON_AUX_BF__CGI_CHUNK_END 4 +#define LWS_CB_REASON_AUX_BF__CGI_HEADERS 8 +#define LWS_CB_REASON_AUX_BF__PROXY_TRANS_END 16 +#define LWS_CB_REASON_AUX_BF__PROXY_HEADERS 32 +///@} diff --git a/thirdparty/include/libwebsockets/lws-cgi.h b/thirdparty/include/libwebsockets/lws-cgi.h new file mode 100755 index 0000000000000000000000000000000000000000..fe42fd8e6e460a2a955673db37ef1644a0cb84d2 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-cgi.h @@ -0,0 +1,104 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup cgi cgi handling + * + * ##CGI handling + * + * These functions allow low-level control over stdin/out/err of the cgi. + * + * However for most cases, binding the cgi to http in and out, the default + * lws implementation already does the right thing. + */ + +enum lws_enum_stdinouterr { + LWS_STDIN = 0, + LWS_STDOUT = 1, + LWS_STDERR = 2, +}; + +enum lws_cgi_hdr_state { + LCHS_HEADER, + LCHS_CR1, + LCHS_LF1, + LCHS_CR2, + LCHS_LF2, + LHCS_RESPONSE, + LHCS_DUMP_HEADERS, + LHCS_PAYLOAD, + LCHS_SINGLE_0A, +}; + +struct lws_cgi_args { + struct lws **stdwsi; /**< get fd with lws_get_socket_fd() */ + enum lws_enum_stdinouterr ch; /**< channel index */ + unsigned char *data; /**< for messages with payload */ + enum lws_cgi_hdr_state hdr_state; /**< track where we are in cgi headers */ + int len; /**< length */ +}; + +#ifdef LWS_WITH_CGI +/** + * lws_cgi: spawn network-connected cgi process + * + * \param wsi: connection to own the process + * \param exec_array: array of "exec-name" "arg1" ... "argn" NULL + * \param script_uri_path_len: how many chars on the left of the uri are the + * path to the cgi, or -1 to spawn without URL-related env vars + * \param timeout_secs: seconds script should be allowed to run + * \param mp_cgienv: pvo list with per-vhost cgi options to put in env + */ +LWS_VISIBLE LWS_EXTERN int +lws_cgi(struct lws *wsi, const char * const *exec_array, + int script_uri_path_len, int timeout_secs, + const struct lws_protocol_vhost_options *mp_cgienv); + +/** + * lws_cgi_write_split_stdout_headers: write cgi output accounting for header part + * + * \param wsi: connection to own the process + */ +LWS_VISIBLE LWS_EXTERN int +lws_cgi_write_split_stdout_headers(struct lws *wsi); + +/** + * lws_cgi_kill: terminate cgi process associated with wsi + * + * \param wsi: connection to own the process + */ +LWS_VISIBLE LWS_EXTERN int +lws_cgi_kill(struct lws *wsi); + +/** + * lws_cgi_get_stdwsi: get wsi for stdin, stdout, or stderr + * + * \param wsi: parent wsi that has cgi + * \param ch: which of LWS_STDIN, LWS_STDOUT or LWS_STDERR + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch); + +#endif +///@} + diff --git a/thirdparty/include/libwebsockets/lws-client.h b/thirdparty/include/libwebsockets/lws-client.h new file mode 100755 index 0000000000000000000000000000000000000000..8727cf56babfdc453de93bfade7e58d96fe90341 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-client.h @@ -0,0 +1,411 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/*! \defgroup client Client related functions + * ##Client releated functions + * \ingroup lwsapi + * + * */ +///@{ + +/** enum lws_client_connect_ssl_connection_flags - flags that may be used + * with struct lws_client_connect_info ssl_connection member to control if + * and how SSL checks apply to the client connection being created + */ + +enum lws_client_connect_ssl_connection_flags { + LCCSCF_USE_SSL = (1 << 0), + LCCSCF_ALLOW_SELFSIGNED = (1 << 1), + LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK = (1 << 2), + LCCSCF_ALLOW_EXPIRED = (1 << 3), + LCCSCF_ALLOW_INSECURE = (1 << 4), + LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM = (1 << 5), + LCCSCF_H2_QUIRK_OVERFLOWS_TXCR = (1 << 6), + LCCSCF_H2_AUTH_BEARER = (1 << 7), + LCCSCF_H2_HEXIFY_AUTH_TOKEN = (1 << 8), + LCCSCF_H2_MANUAL_RXFLOW = (1 << 9), + LCCSCF_HTTP_MULTIPART_MIME = (1 << 10), + LCCSCF_HTTP_X_WWW_FORM_URLENCODED = (1 << 11), + LCCSCF_HTTP_NO_FOLLOW_REDIRECT = (1 << 12), + + LCCSCF_PIPELINE = (1 << 16), + /**< Serialize / pipeline multiple client connections + * on a single connection where possible. + * + * HTTP/1.0: possible if Keep-Alive: yes sent by server + * HTTP/1.1: always possible... uses pipelining + * HTTP/2: always possible... uses parallel streams + */ + LCCSCF_MUXABLE_STREAM = (1 << 17), + LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18), + LCCSCF_WAKE_SUSPEND__VALIDITY = (1 << 19), + /* our validity checks are important enough to wake from suspend */ + LCCSCF_PRIORITIZE_READS = (1 << 20), + /**< + * Normally lws balances reads and writes on all connections, so both + * are possible even on busy connections, and we go around the event + * loop more often to facilitate that, even if there is pending data. + * + * This flag indicates that you want to handle any pending reads on this + * connection without yielding the service loop for anything else. This + * means you may block other connection processing in favour of incoming + * data processing on this one if it receives back to back incoming rx. + */ + LCCSCF_SECSTREAM_CLIENT = (1 << 21), + /**< used to mark client wsi as bound to secure stream */ + LCCSCF_SECSTREAM_PROXY_LINK = (1 << 22), + /**< client is a link between SS client and SS proxy */ + LCCSCF_SECSTREAM_PROXY_ONWARD = (1 << 23), + /**< client the SS proxy's onward connection */ + + LCCSCF_IP_LOW_LATENCY = (1 << 24), + /**< set the "low delay" bit on the IP packets of this connection */ + LCCSCF_IP_HIGH_THROUGHPUT = (1 << 25), + /**< set the "high throughput" bit on the IP packets of this + * connection */ + LCCSCF_IP_HIGH_RELIABILITY = (1 << 26), + /**< set the "high reliability" bit on the IP packets of this + * connection */ + LCCSCF_IP_LOW_COST = (1 << 27), + /**< set the "minimize monetary cost" bit on the IP packets of this + * connection */ + LCCSCF_CONMON = (1 << 28), + /**< If LWS_WITH_CONMON enabled for build, keeps a copy of the + * getaddrinfo results so they can be queried subsequently */ + LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS = (1 << 29), + /**< By default lws rejects https redirecting to http. Set this + * flag on the client connection to allow it. */ + LCCSCF_CACHE_COOKIES = (1 << 30), + /**< If built with -DLWS_WITH_CACHE_NSCOOKIEJAR, store and reapply + * http cookies in a Netscape Cookie Jar on this connection */ +}; + +/** struct lws_client_connect_info - parameters to connect with when using + * lws_client_connect_via_info() */ + +struct lws_client_connect_info { + struct lws_context *context; + /**< lws context to create connection in */ + const char *address; + /**< remote address to connect to */ + int port; + /**< remote port to connect to */ + int ssl_connection; + /**< 0, or a combination of LCCSCF_ flags */ + const char *path; + /**< uri path */ + const char *host; + /**< content of host header */ + const char *origin; + /**< content of origin header */ + const char *protocol; + /**< list of ws protocols we could accept */ + int ietf_version_or_minus_one; + /**< deprecated: currently leave at 0 or -1 */ + void *userdata; + /**< if non-NULL, use this as wsi user_data instead of malloc it */ + const void *client_exts; + /**< UNUSED... provide in info.extensions at context creation time */ + const char *method; + /**< if non-NULL, do this http method instead of ws[s] upgrade. + * use "GET" to be a simple http client connection. "RAW" gets + * you a connected socket that lws itself will leave alone once + * connected. */ + struct lws *parent_wsi; + /**< if another wsi is responsible for this connection, give it here. + * this is used to make sure if the parent closes so do any + * child connections first. */ + const char *uri_replace_from; + /**< if non-NULL, when this string is found in URIs in + * text/html content-encoding, it's replaced with uri_replace_to */ + const char *uri_replace_to; + /**< see uri_replace_from */ + struct lws_vhost *vhost; + /**< vhost to bind to (used to determine related SSL_CTX) */ + struct lws **pwsi; + /**< if not NULL, store the new wsi here early in the connection + * process. Although we return the new wsi, the call to create the + * client connection does progress the connection somewhat and may + * meet an error that will result in the connection being scrubbed and + * NULL returned. While the wsi exists though, he may process a + * callback like CLIENT_CONNECTION_ERROR with his wsi: this gives the + * user callback a way to identify which wsi it is that faced the error + * even before the new wsi is returned and even if ultimately no wsi + * is returned. + */ + const char *iface; + /**< NULL to allow routing on any interface, or interface name or IP + * to bind the socket to */ + const char *local_protocol_name; + /**< NULL: .protocol is used both to select the local protocol handler + * to bind to and as the list of remote ws protocols we could + * accept. + * non-NULL: this protocol name is used to bind the connection to + * the local protocol handler. .protocol is used for the + * list of remote ws protocols we could accept */ + const char *alpn; + /**< NULL: allow lws default ALPN list, from vhost if present or from + * list of roles built into lws + * non-NULL: require one from provided comma-separated list of alpn + * tokens + */ + + struct lws_sequencer *seq; + /**< NULL, or an lws_seq_t that wants to be given messages about + * this wsi's lifecycle as it connects, errors or closes. + */ + + void *opaque_user_data; + /**< This data has no meaning to lws but is applied to the client wsi + * and can be retrieved by user code with lws_get_opaque_user_data(). + * It's also provided with sequencer messages if the wsi is bound to + * an lws_seq_t. + */ + + const lws_retry_bo_t *retry_and_idle_policy; + /**< optional retry and idle policy to apply to this connection. + * Currently only the idle parts are applied to the connection. + */ + + int manual_initial_tx_credit; + /**< if LCCSCF_H2_MANUAL_REFLOW is set, this becomes the initial tx + * credit for the stream. + */ + + uint8_t sys_tls_client_cert; + /**< 0 means no client cert. 1+ means apply lws_system client cert 0+ + * to the client connection. + */ + + uint8_t priority; + /**< 0 means normal priority... otherwise sets the IP priority on + * packets coming from this connection, from 1 - 7. Setting 7 + * (network management priority) requires CAP_NET_ADMIN capability but + * the others can be set by anyone. + */ + +#if defined(LWS_ROLE_MQTT) + const lws_mqtt_client_connect_param_t *mqtt_cp; +#else + void *mqtt_cp; +#endif + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_fi_ctx_t fic; + /**< Attach external Fault Injection context to the client wsi, + * hierarchy is wsi -> vhost -> context */ +#endif + /* for convenience, available when FI disabled in build */ + const char *fi_wsi_name; + /**< specific Fault Injection namespace name for wsi created for this + * connection, allows targeting by "wsi=XXX/..." if you give XXX here. + */ + + uint16_t keep_warm_secs; + /**< 0 means 5s. If the client connection to the endpoint becomes idle, + * defer closing it for this many seconds in case another outgoing + * connection to the same endpoint turns up. + */ + + lws_log_cx_t *log_cx; + /**< NULL to use lws_context log context, else a pointer to a log + * context template to take a copy of for this wsi. Used to isolate + * wsi-specific logs into their own stream or file. + */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility + * + * The below is to ensure later library versions with new + * members added above will see 0 (default) even if the app + * was not built against the newer headers. + */ + + void *_unused[4]; /**< dummy */ +}; + +/** + * lws_client_connect_via_info() - Connect to another websocket server + * \param ccinfo: pointer to lws_client_connect_info struct + * + * This function creates a connection to a remote server using the + * information provided in ccinfo. + */ +LWS_VISIBLE LWS_EXTERN struct lws * +lws_client_connect_via_info(const struct lws_client_connect_info *ccinfo); + +/** + * lws_init_vhost_client_ssl() - also enable client SSL on an existing vhost + * + * \param info: client ssl related info + * \param vhost: which vhost to initialize client ssl operations on + * + * You only need to call this if you plan on using SSL client connections on + * the vhost. For non-SSL client connections, it's not necessary to call this. + * + * The following members of info are used during the call + * + * - options must have LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT set, + * otherwise the call does nothing + * - provided_client_ssl_ctx must be NULL to get a generated client + * ssl context, otherwise you can pass a prepared one in by setting it + * - ssl_cipher_list may be NULL or set to the client valid cipher list + * - ssl_ca_filepath may be NULL or client cert filepath + * - ssl_cert_filepath may be NULL or client cert filepath + * - ssl_private_key_filepath may be NULL or client cert private key + * + * You must create your vhost explicitly if you want to use this, so you have + * a pointer to the vhost. Create the context first with the option flag + * LWS_SERVER_OPTION_EXPLICIT_VHOSTS and then call lws_create_vhost() with + * the same info struct. + */ +LWS_VISIBLE LWS_EXTERN int +lws_init_vhost_client_ssl(const struct lws_context_creation_info *info, + struct lws_vhost *vhost); +/** + * lws_http_client_read() - consume waiting received http client data + * + * \param wsi: client connection + * \param buf: pointer to buffer pointer - fill with pointer to your buffer + * \param len: pointer to chunk length - fill with max length of buffer + * + * This is called when the user code is notified client http data has arrived. + * The user code may choose to delay calling it to consume the data, for example + * waiting until an onward connection is writeable. + * + * For non-chunked connections, up to len bytes of buf are filled with the + * received content. len is set to the actual amount filled before return. + * + * For chunked connections, the linear buffer content contains the chunking + * headers and it cannot be passed in one lump. Instead, this function will + * call back LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ with in pointing to the + * chunk start and len set to the chunk length. There will be as many calls + * as there are chunks or partial chunks in the buffer. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_client_read(struct lws *wsi, char **buf, int *len); + +/** + * lws_http_client_http_response() - get last HTTP response code + * + * \param wsi: client connection + * + * Returns the last server response code, eg, 200 for client http connections. + * + * You should capture this during the LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP + * callback, because after that the memory reserved for storing the related + * headers is freed and this value is lost. + */ +LWS_VISIBLE LWS_EXTERN unsigned int +lws_http_client_http_response(struct lws *wsi); + +/** + * lws_tls_client_vhost_extra_cert_mem() - add more certs to vh client tls ctx + * + * \param vh: the vhost to give more client certs to + * \param der: pointer to der format additional cert + * \param der_len: size in bytes of der + * + * After the vhost is created with one cert for client verification, you + * can add additional, eg, intermediate, certs to the client tls context + * of the vhost, for use with validating the incoming server cert(s). + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh, + const uint8_t *der, size_t der_len); + +/** + * lws_client_http_body_pending() - control if client connection needs to send body + * + * \param wsi: client connection + * \param something_left_to_send: nonzero if need to send more body, 0 (default) + * if nothing more to send + * + * If you will send payload data with your HTTP client connection, eg, for POST, + * when you set the related http headers in + * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER callback you should also call + * this API with something_left_to_send nonzero, and call + * lws_callback_on_writable(wsi); + * + * After sending the headers, lws will call your callback with + * LWS_CALLBACK_CLIENT_HTTP_WRITEABLE reason when writable. You can send the + * next part of the http body payload, calling lws_callback_on_writable(wsi); + * if there is more to come, or lws_client_http_body_pending(wsi, 0); to + * let lws know the last part is sent and the connection can move on. + */ +LWS_VISIBLE LWS_EXTERN void +lws_client_http_body_pending(struct lws *wsi, int something_left_to_send); + +/** + * lws_client_http_multipart() - issue appropriate multipart header or trailer + * + * \param wsi: client connection + * \param name: multipart header name field, or NULL if end of multipart + * \param filename: multipart header filename field, or NULL if none + * \param content_type: multipart header content-type part, or NULL if none + * \param p: pointer to position in buffer + * \param end: end of buffer + * + * This issues a multipart mime boundary, or terminator if name = NULL. + * + * Returns 0 if OK or nonzero if couldn't fit in buffer + */ +LWS_VISIBLE LWS_EXTERN int +lws_client_http_multipart(struct lws *wsi, const char *name, + const char *filename, const char *content_type, + char **p, char *end); + +/** + * lws_http_basic_auth_gen() - helper to encode client basic auth string + * + * \param user: user name + * \param pw: password + * \param buf: where to store base64 result + * \param len: max usable size of buf + * + * Encodes a username and password in Basic Auth format for use with the + * Authorization header. On return, buf is filled with something like + * "Basic QWxhZGRpbjpPcGVuU2VzYW1l". + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_basic_auth_gen(const char *user, const char *pw, char *buf, size_t len); + +/** + * lws_tls_session_is_reused() - returns nonzero if tls session was cached + * + * \param wsi: the wsi + * + * Returns zero if the tls session is fresh, else nonzero if the tls session was + * taken from the cache. If lws is built with LWS_WITH_TLS_SESSIONS and the vhost + * was created with the option LWS_SERVER_OPTION_ENABLE_TLS_SESSION_CACHE, then + * on full tls session establishment of a client connection, the session is added + * to the tls cache. + * + * This lets you find out if your session was new (0) or from the cache (nonzero), + * it'a mainly useful for stats and testing. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_session_is_reused(struct lws *wsi); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-conmon.h b/thirdparty/include/libwebsockets/lws-conmon.h new file mode 100755 index 0000000000000000000000000000000000000000..12a0eec75eb9c56c633a82821382fdcc417338b2 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-conmon.h @@ -0,0 +1,155 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/** \defgroup conmon Connection Latency information + * ## Connection Latency information + * + * When LWS_WITH_CONMON is enabled at build, collects detailed statistics + * about the client connection setup latency, available to the connection + * itself + */ +///@{ + +/* enough for 4191s, or just over an hour */ +typedef uint32_t lws_conmon_interval_us_t; + +/* + * Connection latency information... note that not all wsi actually make + * connections, for example h2 streams after the initial one will have 0 + * for everything except ciu_txn_resp. + * + * If represented in JSON, it should look like this + * + * { + * "peer": "46.105.127.147", + * "dns_us": 1234, + * "dns_disp": 1, + * "sockconn_us": 1234, + * "tls_us": 1234, + * "txn_resp_us": 1234, + * "dns":["46.105.127.147", "2001:41d0:2:ee93::1"], + * "prot_specific": { + * "protocol": "http", + * "resp": 200 + * } + * } + * + * The indexes in "dns_disp" are declared in lws_conmon_dns_disposition_t + * below. + * + * "prot_specific" may not be present if the protocol doesn't have anything + * to report or is not supported. + */ + +typedef enum lws_conmon_pcol { + LWSCONMON_PCOL_NONE, + LWSCONMON_PCOL_HTTP, /* .protocol_specific.http is valid */ +} lws_conmon_pcol_t; + +typedef enum lws_conmon_dns_disposition { + LWSCONMON_DNS_NONE, + /**< did not attempt DNS */ + LWSCONMON_DNS_OK = 1, + /**< DNS lookup did give results */ + LWSCONMON_DNS_SERVER_UNREACHABLE = 2, + /**< DNS server was not reachable */ + LWSCONMON_DNS_NO_RESULT = 3 + /**< DNS server replied but nothing usable */ +} lws_conmon_dns_disposition_t; + +struct lws_conmon { + lws_sockaddr46 peer46; + /**< The peer we actually connected to, if any. .peer46.sa4.sa_family + * is either 0 if invalid, or the AF_ */ + + union { + struct { + int response; + /**< h1 http response code */ + } http; + } protocol_specific; + /**< possibly-present protocol-specific additional information. This + * is only valid for the first transaction after connection and does + * not capture results for persistent or muxed connections like ws + * messages, mqtt messages, or h2 streams */ + + struct addrinfo *dns_results_copy; + /**< NULL, or Allocated copy of dns results, owned by this object and + * freed when object destroyed. + * Only set if client flag LCCSCF_CONMON applied */ + + lws_conmon_interval_us_t ciu_dns; + /**< 0, or if a socket connection, us taken to acquire this DNS response + * + */ + lws_conmon_interval_us_t ciu_sockconn; + /**< 0, or if connection-based, the us interval between the socket + * connect() attempt that succeeded, and the connection setup */ + lws_conmon_interval_us_t ciu_tls; + /**< 0 if no tls, or us taken to establish the tls tunnel */ + lws_conmon_interval_us_t ciu_txn_resp; + /**< 0, or if the protocol supports transactions, the interval between + * sending the initial transaction request and starting to receive the + * response */ + + lws_conmon_pcol_t pcol; + /**< indicates which extra protocol_specific info member is valid, + * if any */ + + lws_conmon_dns_disposition_t dns_disposition; + /**< indicates general disposition of DNS request */ +}; + +/** + * lws_conmon_wsi_take() - create a connection latency object from client wsi + * + * \param context: lws wsi + * \param dest: conmon struct to fill + * + * Copies wsi conmon data into the caller's struct. Passes ownership of + * any allocations in the addrinfo list to the caller, lws will not delete that + * any more on wsi close after this call. The caller must call + * lws_conmon_release() on the struct to destroy any addrinfo in the struct + * that is prepared by this eventually but it can defer it as long as it wants. + * + * Other than the addrinfo list, the contents of the returned object are + * completely selfcontained and don't point outside of the object itself, ie, + * everything else in there remains in scope while the object itself does. + */ +LWS_VISIBLE LWS_EXTERN void +lws_conmon_wsi_take(struct lws *wsi, struct lws_conmon *dest); + +/** + * lws_conmon_release() - free any allocations in the conmon struct + * + * \param conmon: pointer to conmon struct + * + * Destroys any allocations in the conmon struct so it can go out of scope. + * It doesn't free \p dest itself, it's designed to clean out a struct that + * is on the stack or embedded in another object. + */ +LWS_VISIBLE LWS_EXTERN void +lws_conmon_release(struct lws_conmon *conmon); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-context-vhost.h b/thirdparty/include/libwebsockets/lws-context-vhost.h new file mode 100755 index 0000000000000000000000000000000000000000..b3de140b5802737bb35ae65e786bb41c9885d306 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-context-vhost.h @@ -0,0 +1,1332 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/*! \defgroup context-and-vhost context and vhost related functions + * ##Context and Vhost releated functions + * \ingroup lwsapi + * + * + * LWS requires that there is one context, in which you may define multiple + * vhosts. Each vhost is a virtual host, with either its own listen port + * or sharing an existing one. Each vhost has its own SSL context that can + * be set up individually or left disabled. + * + * If you don't care about multiple "site" support, you can ignore it and + * lws will create a single default vhost at context creation time. + */ +///@{ + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ + + +#define LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT ((1ll << 1) | \ + (1ll << 12)) + /**< (VH) Don't allow the connection unless the client has a + * client cert that we recognize; provides + * LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT */ +#define LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME (1ll << 2) + /**< (CTX) Don't try to get the server's hostname */ +#define LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT ((1ll << 3) | \ + (1ll << 12)) + /**< (VH) Allow non-SSL (plaintext) connections on the same + * port as SSL is listening. If combined with + * LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS it will try to + * force http connections on an https listener (eg, http://x.com:443) to + * redirect to an explicit https connection (eg, https://x.com) + */ +#define LWS_SERVER_OPTION_LIBEV (1ll << 4) + /**< (CTX) Use libev event loop */ +#define LWS_SERVER_OPTION_DISABLE_IPV6 (1ll << 5) + /**< (VH) Disable IPV6 support */ +#define LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS (1ll << 6) + /**< (VH) Don't load OS CA certs, you will need to load your + * own CA cert(s) */ +#define LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED (1ll << 7) + /**< (VH) Accept connections with no valid Cert (eg, selfsigned) */ +#define LWS_SERVER_OPTION_VALIDATE_UTF8 (1ll << 8) + /**< (VH) Check UT-8 correctness */ +#define LWS_SERVER_OPTION_SSL_ECDH ((1ll << 9) | \ + (1ll << 12)) + /**< (VH) initialize ECDH ciphers */ +#define LWS_SERVER_OPTION_LIBUV (1ll << 10) + /**< (CTX) Use libuv event loop */ +#define LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS ((1ll << 11) |\ + (1ll << 12)) + /**< (VH) Use an http redirect to force the client to ask for https. + * Notice if your http server issues the STS header and the client has + * ever seen that, the client will fail the http connection before it + * can actually do the redirect. + * + * Combine with LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS to handle, eg, + * http://x.com:443 -> https://x.com + * + * (deprecated: use mount redirection) */ +#define LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT (1ll << 12) + /**< (CTX) Initialize the SSL library at all */ +#define LWS_SERVER_OPTION_EXPLICIT_VHOSTS (1ll << 13) + /**< (CTX) Only create the context when calling context + * create api, implies user code will create its own vhosts */ +#define LWS_SERVER_OPTION_UNIX_SOCK (1ll << 14) + /**< (VH) Use Unix socket */ +#define LWS_SERVER_OPTION_STS (1ll << 15) + /**< (VH) Send Strict Transport Security header, making + * clients subsequently go to https even if user asked for http */ +#define LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY (1ll << 16) + /**< (VH) Enable LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE to take effect */ +#define LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE (1ll << 17) + /**< (VH) if set, only ipv6 allowed on the vhost */ +#define LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN (1ll << 18) + /**< (CTX) Libuv only: Do not spin on SIGSEGV / SIGFPE. A segfault + * normally makes the lib spin so you can attach a debugger to it + * even if it happened without a debugger in place. You can disable + * that by giving this option. + */ +#define LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN (1ll << 19) + /**< For backwards-compatibility reasons, by default + * lws prepends "http://" to the origin you give in the client + * connection info struct. If you give this flag when you create + * the context, only the string you give in the client connect + * info for .origin (if any) will be used directly. + */ +#define LWS_SERVER_OPTION_FALLBACK_TO_RAW /* use below name */ (1ll << 20) +#define LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG (1ll << 20) + /**< (VH) if invalid http is coming in the first line, then abandon + * trying to treat the connection as http, and belatedly apply the + * .listen_accept_role / .listen_accept_protocol info struct members to + * the connection. If they are NULL, for backwards-compatibility the + * connection is bound to "raw-skt" role, and in order of priority: + * 1) the vh protocol with a pvo named "raw", 2) the vh protocol with a + * pvo named "default", or 3) protocols[0]. + * + * Must be combined with LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT + * to work with a socket listening with tls. + */ + +#define LWS_SERVER_OPTION_LIBEVENT (1ll << 21) + /**< (CTX) Use libevent event loop */ + +#define LWS_SERVER_OPTION_ONLY_RAW /* Use below name instead */ (1ll << 22) +#define LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG (1ll << 22) + /**< (VH) All connections to this vhost / port are bound to the + * role and protocol given in .listen_accept_role / + * .listen_accept_protocol. + * + * If those explicit user-controlled names are NULL, for backwards- + * compatibility the connection is bound to "raw-skt" role, and in order + * of priority: 1) the vh protocol with a pvo named "raw", 2) the vh + * protocol with a pvo named "default", or 3) protocols[0]. + * + * It's much preferred to specify the role + protocol using the + * .listen_accept_role and .listen_accept_protocol in the info struct. + */ +#define LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE (1ll << 23) + /**< (VH) Set to allow multiple listen sockets on one interface + + * address + port. The default is to strictly allow only one + * listen socket at a time. This is automatically selected if you + * have multiple service threads. Linux only. + */ +#define LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX (1ll << 24) + /**< (VH) Force setting up the vhost SSL_CTX, even though the user + * code doesn't explicitly provide a cert in the info struct. It + * implies the user code is going to provide a cert at the + * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS callback, which + * provides the vhost SSL_CTX * in the user parameter. + */ +#define LWS_SERVER_OPTION_SKIP_PROTOCOL_INIT (1ll << 25) + /**< (VH) You probably don't want this. It forces this vhost to not + * call LWS_CALLBACK_PROTOCOL_INIT on its protocols. It's used in the + * special case of a temporary vhost bound to a single protocol. + */ +#define LWS_SERVER_OPTION_IGNORE_MISSING_CERT (1ll << 26) + /**< (VH) Don't fail if the vhost TLS cert or key are missing, just + * continue. The vhost won't be able to serve anything, but if for + * example the ACME plugin was configured to fetch a cert, this lets + * you bootstrap your vhost from having no cert to start with. + */ +#define LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK (1ll << 27) + /**< (VH) On this vhost, if the connection is being upgraded, insist + * that there's a Host: header and that the contents match the vhost + * name + port (443 / 80 are assumed if no :port given based on if the + * connection is using TLS). + * + * By default, without this flag, on upgrade lws just checks that the + * Host: header was given without checking the contents... this is to + * allow lax hostname mappings like localhost / 127.0.0.1, and CNAME + * mappings like www.mysite.com / mysite.com + */ +#define LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE (1ll << 28) + /**< (VH) Send lws default HTTP headers recommended by Mozilla + * Observatory for security. This is a helper option that sends canned + * headers on each http response enabling a VERY strict Content Security + * Policy. The policy is so strict, for example it won't let the page + * run its own inline JS nor show images or take CSS from a different + * server. In many cases your JS only comes from your server as do the + * image sources and CSS, so that is what you want... attackers hoping + * to inject JS into your DOM are completely out of luck since even if + * they succeed, it will be rejected for execution by the browser + * according to the strict CSP. In other cases you have to deviate from + * the complete strictness, in which case don't use this flag: use the + * .headers member in the vhost init described in struct + * lws_context_creation_info instead to send the adapted headers + * yourself. + */ + +#define LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER (1ll << 29) + /**< (VH) If you really want to allow HTTP connections on a tls + * listener, you can do it with this combined with + * LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT. But this is allowing + * accidental loss of the security assurances provided by tls depending + * on the client using http when he meant https... it's not + * recommended. + */ +#define LWS_SERVER_OPTION_FAIL_UPON_UNABLE_TO_BIND (1ll << 30) + /**< (VH) When instantiating a new vhost and the specified port is + * already in use, a null value shall be return to signal the error. + */ + +#define LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW (1ll << 31) + /**< (VH) Indicates the connections using this vhost should ignore + * h2 WINDOW_UPDATE from broken peers and fix them up */ + +#define LWS_SERVER_OPTION_VH_H2_HALF_CLOSED_LONG_POLL (1ll << 32) + /**< (VH) Tell the vhost to treat half-closed remote clients as + * entered into an immortal (ie, not subject to normal timeouts) long + * poll mode. + */ + +#define LWS_SERVER_OPTION_GLIB (1ll << 33) + /**< (CTX) Use glib event loop */ + +#define LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE (1ll << 34) + /**< (VH) Tell the vhost to treat plain text http connections as + * H2 with prior knowledge (no upgrade request involved) + */ + +#define LWS_SERVER_OPTION_NO_LWS_SYSTEM_STATES (1ll << 35) + /**< (CTX) Disable lws_system state, eg, because we are a secure streams + * proxy client that is not trying to track system state by itself. */ + +#define LWS_SERVER_OPTION_SS_PROXY (1ll << 36) + /**< (VH) We are being a SS Proxy listen socket for the vhost */ + +#define LWS_SERVER_OPTION_SDEVENT (1ll << 37) + /**< (CTX) Use sd-event loop */ + +#define LWS_SERVER_OPTION_ULOOP (1ll << 38) + /**< (CTX) Use libubox / uloop event loop */ + +#define LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE (1ll << 39) + /**< (VHOST) Disallow use of client tls caching (on by default) */ + + + /****** add new things just above ---^ ******/ + + +#define lws_check_opt(c, f) ((((uint64_t)c) & ((uint64_t)f)) == ((uint64_t)f)) + +struct lws_plat_file_ops; +struct lws_ss_policy; +struct lws_ss_plugin; +struct lws_metric_policy; + +typedef int (*lws_context_ready_cb_t)(struct lws_context *context); + +typedef int (*lws_peer_limits_notify_t)(struct lws_context *ctx, + lws_sockfd_type sockfd, + lws_sockaddr46 *sa46); + +/** struct lws_context_creation_info - parameters to create context and /or vhost with + * + * This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS + * is not given, then for backwards compatibility one vhost is created at + * context-creation time using the info from this struct. + * + * If LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, then no vhosts are created + * at the same time as the context, they are expected to be created afterwards. + */ +struct lws_context_creation_info { +#if defined(LWS_WITH_NETWORK) + const char *iface; + /**< VHOST: NULL to bind the listen socket to all interfaces, or the + * interface name, eg, "eth2" + * If options specifies LWS_SERVER_OPTION_UNIX_SOCK, this member is + * the pathname of a UNIX domain socket. you can use the UNIX domain + * sockets in abstract namespace, by prepending an at symbol to the + * socket name. */ + const struct lws_protocols *protocols; + /**< VHOST: Array of structures listing supported protocols and a + * protocol-specific callback for each one. The list is ended with an + * entry that has a NULL callback pointer. SEE ALSO .pprotocols below, + * which gives an alternative way to provide an array of pointers to + * protocol structs. */ +#if defined(LWS_ROLE_WS) + const struct lws_extension *extensions; + /**< VHOST: NULL or array of lws_extension structs listing the + * extensions this context supports. */ +#endif +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + const struct lws_token_limits *token_limits; + /**< CONTEXT: NULL or struct lws_token_limits pointer which is + * initialized with a token length limit for each possible WSI_TOKEN_ */ + const char *http_proxy_address; + /**< VHOST: If non-NULL, attempts to proxy via the given address. + * If proxy auth is required, use format + * "username:password\@server:port" */ + const struct lws_protocol_vhost_options *headers; + /**< VHOST: pointer to optional linked list of per-vhost + * canned headers that are added to server responses */ + + const struct lws_protocol_vhost_options *reject_service_keywords; + /**< CONTEXT: Optional list of keywords and rejection codes + text. + * + * The keywords are checked for existing in the user agent string. + * + * Eg, "badrobot" "404 Not Found" + */ + const struct lws_protocol_vhost_options *pvo; + /**< VHOST: pointer to optional linked list of per-vhost + * options made accessible to protocols */ + const char *log_filepath; + /**< VHOST: filepath to append logs to... this is opened before + * any dropping of initial privileges */ + const struct lws_http_mount *mounts; + /**< VHOST: optional linked list of mounts for this vhost */ + const char *server_string; + /**< CONTEXT: string used in HTTP headers to identify server + * software, if NULL, "libwebsockets". */ + + const char *error_document_404; + /**< VHOST: If non-NULL, when asked to serve a non-existent file, + * lws attempts to server this url path instead. Eg, + * "/404.html" */ + int port; + /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress + * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are + * writing a server but you are using \ref sock-adopt instead of the + * built-in listener. + * + * You can also set port to 0, in which case the kernel will pick + * a random port that is not already in use. You can find out what + * port the vhost is listening on using lws_get_vhost_listen_port() */ + + unsigned int http_proxy_port; + /**< VHOST: If http_proxy_address was non-NULL, uses this port */ + unsigned int max_http_header_data2; + /**< CONTEXT: if max_http_header_data is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version, + * this is unsigned int length. */ + unsigned int max_http_header_pool2; + /**< CONTEXT: if max_http_header_pool is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version: + * this is unsigned int length. */ + + int keepalive_timeout; + /**< VHOST: (default = 0 = 5s, 31s for http/2) seconds to allow remote + * client to hold on to an idle HTTP/1.1 connection. Timeout lifetime + * applied to idle h2 network connections */ + uint32_t http2_settings[7]; + /**< VHOST: if http2_settings[0] is nonzero, the values given in + * http2_settings[1]..[6] are used instead of the lws + * platform default values. + * Just leave all at 0 if you don't care. + */ + + unsigned short max_http_header_data; + /**< CONTEXT: The max amount of header payload that can be handled + * in an http request (unrecognized header payload is dropped) */ + unsigned short max_http_header_pool; + /**< CONTEXT: The max number of connections with http headers that + * can be processed simultaneously (the corresponding memory is + * allocated and deallocated dynamically as needed). If the pool is + * fully busy new incoming connections must wait for accept until one + * becomes free. 0 = allow as many ah as number of availble fds for + * the process */ + +#endif + +#if defined(LWS_WITH_TLS) + const char *ssl_private_key_password; + /**< VHOST: NULL or the passphrase needed for the private key. (For + * backwards compatibility, this can also be used to pass the client + * cert passphrase when setting up a vhost client SSL context, but it is + * preferred to use .client_ssl_private_key_password for that.) */ + const char *ssl_cert_filepath; + /**< VHOST: If libwebsockets was compiled to use ssl, and you want + * to listen using SSL, set to the filepath to fetch the + * server cert from, otherwise NULL for unencrypted. (For backwards + * compatibility, this can also be used to pass the client certificate + * when setting up a vhost client SSL context, but it is preferred to + * use .client_ssl_cert_filepath for that.) + * + * Notice you can alternatively set a single DER or PEM from a memory + * buffer as the vhost tls cert using \p server_ssl_cert_mem and + * \p server_ssl_cert_mem_len. + */ + const char *ssl_private_key_filepath; + /**< VHOST: filepath to private key if wanting SSL mode; + * if this is set to NULL but ssl_cert_filepath is set, the + * OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called + * to allow setting of the private key directly via openSSL + * library calls. (For backwards compatibility, this can also be used + * to pass the client cert private key filepath when setting up a + * vhost client SSL context, but it is preferred to use + * .client_ssl_private_key_filepath for that.) + * + * Notice you can alternatively set a DER or PEM private key from a + * memory buffer as the vhost tls private key using + * \p server_ssl_private_key_mem and \p server_ssl_private_key_mem_len. + */ + const char *ssl_ca_filepath; + /**< VHOST: CA certificate filepath or NULL. (For backwards + * compatibility, this can also be used to pass the client CA + * filepath when setting up a vhost client SSL context, + * but it is preferred to use .client_ssl_ca_filepath for that.) + * + * Notice you can alternatively set a DER or PEM CA cert from a memory + * buffer using \p server_ssl_ca_mem and \p server_ssl_ca_mem_len. + */ + const char *ssl_cipher_list; + /**< VHOST: List of valid ciphers to use ON TLS1.2 AND LOWER ONLY (eg, + * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" + * or you can leave it as NULL to get "DEFAULT" (For backwards + * compatibility, this can also be used to pass the client cipher + * list when setting up a vhost client SSL context, + * but it is preferred to use .client_ssl_cipher_list for that.) + * SEE .tls1_3_plus_cipher_list and .client_tls_1_3_plus_cipher_list + * for the equivalent for tls1.3. + */ + const char *ecdh_curve; + /**< VHOST: if NULL, defaults to initializing server with + * "prime256v1" */ + const char *tls1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for incoming server connections + * ON TLS1.3 AND ABOVE (eg, "TLS_CHACHA20_POLY1305_SHA256" on this vhost + * or you can leave it as NULL to get "DEFAULT". + * SEE .client_tls_1_3_plus_cipher_list to do the same on the vhost + * client SSL_CTX. + */ + + const void *server_ssl_cert_mem; + /**< VHOST: Alternative for \p ssl_cert_filepath that allows setting + * from memory instead of from a file. At most one of + * \p ssl_cert_filepath or \p server_ssl_cert_mem should be non-NULL. */ + const void *server_ssl_private_key_mem; + /**< VHOST: Alternative for \p ssl_private_key_filepath allowing + * init from a private key in memory instead of a file. At most one + * of \p ssl_private_key_filepath or \p server_ssl_private_key_mem + * should be non-NULL. */ + const void *server_ssl_ca_mem; + /**< VHOST: Alternative for \p ssl_ca_filepath allowing + * init from a CA cert in memory instead of a file. At most one + * of \p ssl_ca_filepath or \p server_ssl_ca_mem should be non-NULL. */ + + long ssl_options_set; + /**< VHOST: Any bits set here will be set as server SSL options */ + long ssl_options_clear; + /**< VHOST: Any bits set here will be cleared as server SSL options */ + int simultaneous_ssl_restriction; + /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions + * possible.*/ + int simultaneous_ssl_handshake_restriction; + /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL handshakes ongoing */ + int ssl_info_event_mask; + /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO + * callback for connections on this vhost. The mask values are of + * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of + * 0 means no info events will be reported. + */ + unsigned int server_ssl_cert_mem_len; + /**< VHOST: Server SSL context init: length of server_ssl_cert_mem in + * bytes */ + unsigned int server_ssl_private_key_mem_len; + /**< VHOST: length of \p server_ssl_private_key_mem in memory */ + unsigned int server_ssl_ca_mem_len; + /**< VHOST: length of \p server_ssl_ca_mem in memory */ + + const char *alpn; + /**< CONTEXT: If non-NULL, default list of advertised alpn, comma- + * separated + * + * VHOST: If non-NULL, per-vhost list of advertised alpn, comma- + * separated + */ + + +#if defined(LWS_WITH_CLIENT) + const char *client_ssl_private_key_password; + /**< VHOST: Client SSL context init: NULL or the passphrase needed + * for the private key */ + const char *client_ssl_cert_filepath; + /**< VHOST: Client SSL context init: The certificate the client + * should present to the peer on connection */ + const void *client_ssl_cert_mem; + /**< VHOST: Client SSL context init: client certificate memory buffer or + * NULL... use this to load client cert from memory instead of file */ + unsigned int client_ssl_cert_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_cert_mem in + * bytes */ + const char *client_ssl_private_key_filepath; + /**< VHOST: Client SSL context init: filepath to client private key + * if this is set to NULL but client_ssl_cert_filepath is set, you + * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS + * callback of protocols[0] to allow setting of the private key directly + * via tls library calls */ + const void *client_ssl_key_mem; + /**< VHOST: Client SSL context init: client key memory buffer or + * NULL... use this to load client key from memory instead of file */ + const char *client_ssl_ca_filepath; + /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ + const void *client_ssl_ca_mem; + /**< VHOST: Client SSL context init: CA certificate memory buffer or + * NULL... use this to load CA cert from memory instead of file */ + + const char *client_ssl_cipher_list; + /**< VHOST: Client SSL context init: List of valid ciphers to use (eg, + * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" + * or you can leave it as NULL to get "DEFAULT" */ + const char *client_tls_1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for outgoing client connections + * ON TLS1.3 AND ABOVE on this vhost (eg, + * "TLS_CHACHA20_POLY1305_SHA256") or you can leave it as NULL to get + * "DEFAULT". + */ + + long ssl_client_options_set; + /**< VHOST: Any bits set here will be set as CLIENT SSL options */ + long ssl_client_options_clear; + /**< VHOST: Any bits set here will be cleared as CLIENT SSL options */ + + + unsigned int client_ssl_ca_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_ca_mem in + * bytes */ + unsigned int client_ssl_key_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_key_mem in + * bytes */ + +#endif + +#if !defined(LWS_WITH_MBEDTLS) + SSL_CTX *provided_client_ssl_ctx; + /**< CONTEXT: If non-null, swap out libwebsockets ssl + * implementation for the one provided by provided_ssl_ctx. + * Libwebsockets no longer is responsible for freeing the context + * if this option is selected. */ +#else /* WITH_MBEDTLS */ + const char *mbedtls_client_preload_filepath; + /**< CONTEXT: If NULL, no effect. Otherwise it should point to a + * filepath where every created client SSL_CTX is preloaded from the + * system trust bundle. + * + * This sets a processwide variable that affects all contexts. + * + * Requires that the mbedtls provides mbedtls_x509_crt_parse_file(), + * else disabled. + */ +#endif +#endif + + int ka_time; + /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive + * timeout to all libwebsocket sockets, client or server */ + int ka_probes; + /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many + * times to try to get a response from the peer before giving up + * and killing the connection */ + int ka_interval; + /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes + * attempt */ + unsigned int timeout_secs; + /**< VHOST: various processes involving network roundtrips in the + * library are protected from hanging forever by timeouts. If + * nonzero, this member lets you set the timeout used in seconds. + * Otherwise a default timeout is used. */ + unsigned int connect_timeout_secs; + /**< VHOST: client connections have this long to find a working server + * from the DNS results, or the whole connection times out. If zero, + * a default timeout is used */ + int bind_iface; + /**< VHOST: nonzero to strictly bind sockets to the interface name in + * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE. + * + * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW + * capability. + * + * Notice that common things like access network interface IP from + * your local machine use your lo / loopback interface and will be + * disallowed by this. + */ + unsigned int timeout_secs_ah_idle; + /**< VHOST: seconds to allow a client to hold an ah without using it. + * 0 defaults to 10s. */ +#endif /* WITH_NETWORK */ + +#if defined(LWS_WITH_TLS_SESSIONS) + uint32_t tls_session_timeout; + /**< VHOST: seconds until timeout/ttl for newly created sessions. + * 0 means default timeout (defined per protocol, usually 300s). */ + uint32_t tls_session_cache_max; + /**< VHOST: 0 for default limit of 10, or the maximum number of + * client tls sessions we are willing to cache */ +#endif + + gid_t gid; + /**< CONTEXT: group id to change to after setting listen socket, + * or -1. See also .username below. */ + uid_t uid; + /**< CONTEXT: user id to change to after setting listen socket, + * or -1. See also .groupname below. */ + uint64_t options; + /**< VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields */ + void *user; + /**< VHOST + CONTEXT: optional user pointer that will be associated + * with the context when creating the context (and can be retrieved by + * lws_context_user(context), or with the vhost when creating the vhost + * (and can be retrieved by lws_vhost_user(vhost)). You will need to + * use LWS_SERVER_OPTION_EXPLICIT_VHOSTS and create the vhost separately + * if you care about giving the context and vhost different user pointer + * values. + */ + unsigned int count_threads; + /**< CONTEXT: how many contexts to create in an array, 0 = 1 */ + unsigned int fd_limit_per_thread; + /**< CONTEXT: nonzero means restrict each service thread to this + * many fds, 0 means the default which is divide the process fd + * limit by the number of threads. + * + * Note if this is nonzero, and fd_limit_per_thread multiplied by the + * number of service threads is less than the process ulimit, then lws + * restricts internal lookup table allocation to the smaller size, and + * switches to a less efficient lookup scheme. You should use this to + * trade off speed against memory usage if you know the lws context + * will only use a handful of fds. + * + * Bear in mind lws may use some fds internally, for example for the + * cancel pipe, so you may need to allow for some extras for normal + * operation. + */ + const char *vhost_name; + /**< VHOST: name of vhost, must match external DNS name used to + * access the site, like "warmcat.com" as it's used to match + * Host: header and / or SNI name for SSL. + * CONTEXT: NULL, or the name to associate with the context for + * context-specific logging + */ +#if defined(LWS_WITH_PLUGINS) + const char * const *plugin_dirs; + /**< CONTEXT: NULL, or NULL-terminated array of directories to + * scan for lws protocol plugins at context creation time */ +#endif + void *external_baggage_free_on_destroy; + /**< CONTEXT: NULL, or pointer to something externally malloc'd, that + * should be freed when the context is destroyed. This allows you to + * automatically sync the freeing action to the context destruction + * action, so there is no need for an external free() if the context + * succeeded to create. + */ + + + unsigned int pt_serv_buf_size; + /**< CONTEXT: 0 = default of 4096. This buffer is used by + * various service related features including file serving, it + * defines the max chunk of file that can be sent at once. + * At the risk of lws having to buffer failed large sends, it + * can be increased to, eg, 128KiB to improve throughput. */ +#if defined(LWS_WITH_FILE_OPS) + const struct lws_plat_file_ops *fops; + /**< CONTEXT: NULL, or pointer to an array of fops structs, terminated + * by a sentinel with NULL .open. + * + * If NULL, lws provides just the platform file operations struct for + * backwards compatibility. + */ +#endif + +#if defined(LWS_WITH_SOCKS5) + const char *socks_proxy_address; + /**< VHOST: If non-NULL, attempts to proxy via the given address. + * If proxy auth is required, use format + * "username:password\@server:port" */ + unsigned int socks_proxy_port; + /**< VHOST: If socks_proxy_address was non-NULL, uses this port + * if nonzero, otherwise requires "server:port" in .socks_proxy_address + */ +#endif + +#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) + cap_value_t caps[4]; + /**< CONTEXT: array holding Linux capabilities you want to + * continue to be available to the server after it transitions + * to a noprivileged user. Usually none are needed but for, eg, + * .bind_iface, CAP_NET_RAW is required. This gives you a way + * to still have the capability but drop root. + */ + char count_caps; + /**< CONTEXT: count of Linux capabilities in .caps[]. 0 means + * no capabilities will be inherited from root (the default) */ +#endif + void **foreign_loops; + /**< CONTEXT: This is ignored if the context is not being started with + * an event loop, ie, .options has a flag like + * LWS_SERVER_OPTION_LIBUV. + * + * NULL indicates lws should start its own even loop for + * each service thread, and deal with closing the loops + * when the context is destroyed. + * + * Non-NULL means it points to an array of external + * ("foreign") event loops that are to be used in turn for + * each service thread. In the default case of 1 service + * thread, it can just point to one foreign event loop. + */ + void (*signal_cb)(void *event_lib_handle, int signum); + /**< CONTEXT: NULL: default signal handling. Otherwise this receives + * the signal handler callback. event_lib_handle is the + * native event library signal handle, eg uv_signal_t * + * for libuv. + */ + struct lws_context **pcontext; + /**< CONTEXT: if non-NULL, at the end of context destroy processing, + * the pointer pointed to by pcontext is written with NULL. You can + * use this to let foreign event loops know that lws context destruction + * is fully completed. + */ + void (*finalize)(struct lws_vhost *vh, void *arg); + /**< VHOST: NULL, or pointer to function that will be called back + * when the vhost is just about to be freed. The arg parameter + * will be set to whatever finalize_arg is below. + */ + void *finalize_arg; + /**< VHOST: opaque pointer lws ignores but passes to the finalize + * callback. If you don't care, leave it NULL. + */ + const char *listen_accept_role; + /**< VHOST: NULL for default, or force accepted incoming connections to + * bind to this role. Uses the role names from their ops struct, eg, + * "raw-skt". + */ + const char *listen_accept_protocol; + /**< VHOST: NULL for default, or force accepted incoming connections to + * bind to this vhost protocol name. + */ + const struct lws_protocols **pprotocols; + /**< VHOST: NULL: use .protocols, otherwise ignore .protocols and use + * this array of pointers to protocols structs. The end of the array + * is marked by a NULL pointer. + * + * This is preferred over .protocols, because it allows the protocol + * struct to be opaquely defined elsewhere, with just a pointer to it + * needed to create the context with it. .protocols requires also + * the type of the user data to be known so its size can be given. + */ + + const char *username; /**< CONTEXT: string username for post-init + * permissions. Like .uid but takes a string username. */ + const char *groupname; /**< CONTEXT: string groupname for post-init + * permissions. Like .gid but takes a string groupname. */ + const char *unix_socket_perms; /**< VHOST: if your vhost is listening + * on a unix socket, you can give a "username:groupname" string here + * to control the owner:group it's created with. It's always created + * with 0660 mode. */ + const lws_system_ops_t *system_ops; + /**< CONTEXT: hook up lws_system_ apis to system-specific + * implementations */ + const lws_retry_bo_t *retry_and_idle_policy; + /**< VHOST: optional retry and idle policy to apply to this vhost. + * Currently only the idle parts are applied to the connections. + */ +#if defined(LWS_WITH_SYS_STATE) + lws_state_notify_link_t * const *register_notifier_list; + /**< CONTEXT: NULL, or pointer to an array of notifiers that should + * be registered during context creation, so they can see state change + * events from very early on. The array should end with a NULL. */ +#endif +#if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + const struct lws_ss_policy *pss_policies; /**< CONTEXT: point to first + * in a linked-list of streamtype policies prepared by user code */ +#else + const char *pss_policies_json; /**< CONTEXT: point to a string + * containing a JSON description of the secure streams policies. Set + * to NULL if not using Secure Streams. + * If the platform supports files and the string does not begin with + * '{', lws treats the string as a filepath to open to get the JSON + * policy. + */ +#endif + const struct lws_ss_plugin **pss_plugins; /**< CONTEXT: point to an array + * of pointers to plugin structs here, terminated with a NULL ptr. + * Set to NULL if not using Secure Streams. */ + const char *ss_proxy_bind; /**< CONTEXT: NULL, or: ss_proxy_port == 0: + * point to a string giving the Unix Domain Socket address to use (start + * with @ for abstract namespace), ss_proxy_port nonzero: set the + * network interface address (not name, it's ambiguous for ipv4/6) to + * bind the tcp connection to the proxy to */ + const char *ss_proxy_address; /**< CONTEXT: NULL, or if ss_proxy_port + * nonzero: the tcp address of the ss proxy to connect to */ + uint16_t ss_proxy_port; /* 0 = if connecting to ss proxy, do it via a + * Unix Domain Socket, "+@proxy.ss.lws" if ss_proxy_bind is NULL else + * the socket path given in ss_proxy_bind (start it with a + or +@); + * nonzero means connect via a tcp socket to the tcp address in + * ss_proxy_bind and the given port */ +#endif + + int rlimit_nofile; + /**< 0 = inherit the initial ulimit for files / sockets from the startup + * environment. Nonzero = try to set the limit for this process. + */ +#if defined(LWS_WITH_PEER_LIMITS) + lws_peer_limits_notify_t pl_notify_cb; + /**< CONTEXT: NULL, or a callback to receive notifications each time a + * connection is being dropped because of peer limits. + * + * The callback provides the context, and an lws_sockaddr46 with the + * peer address and port. + */ + unsigned short ip_limit_ah; + /**< CONTEXT: max number of ah a single IP may use simultaneously + * 0 is no limit. This is a soft limit: if the limit is + * reached, connections from that IP will wait in the ah + * waiting list and not be able to acquire an ah until + * a connection belonging to the IP relinquishes one it + * already has. + */ + unsigned short ip_limit_wsi; + /**< CONTEXT: max number of wsi a single IP may use simultaneously. + * 0 is no limit. This is a hard limit, connections from + * the same IP will simply be dropped once it acquires the + * amount of simultaneous wsi / accepted connections + * given here. + */ + +#endif /* PEER_LIMITS */ + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_fi_ctx_t fic; + /**< CONTEXT | VHOST: attach external Fault Injection context to the + * lws_context or vhost. If creating the context + default vhost in + * one step, only the context binds to \p fi. When creating a vhost + * otherwise this can bind to the vhost so the faults can be injected + * from the start. + */ +#endif + +#if defined(LWS_WITH_SYS_SMD) + lws_smd_notification_cb_t early_smd_cb; + /**< CONTEXT: NULL, or an smd notification callback that will be registered + * immediately after the smd in the context is initialized. This ensures + * you can get all notifications without having to intercept the event loop + * creation, eg, when using an event library. Other callbacks can be + * registered later manually without problems. + */ + void *early_smd_opaque; + lws_smd_class_t early_smd_class_filter; + lws_usec_t smd_ttl_us; + /**< CONTEXT: SMD messages older than this many us are removed from the + * queue and destroyed even if not fully delivered yet. If zero, + * defaults to 2 seconds (5 second for FREERTOS). + */ + uint16_t smd_queue_depth; + /**< CONTEXT: Maximum queue depth, If zero defaults to 40 + * (20 for FREERTOS) */ +#endif + +#if defined(LWS_WITH_SYS_METRICS) + const struct lws_metric_policy *metrics_policies; + /**< CONTEXT: non-SS policy metrics policies */ + const char *metrics_prefix; + /**< CONTEXT: prefix for this context's metrics, used to distinguish + * metrics pooled from different processes / applications, so, eg what + * would be "cpu.svc" if this is NULL becomes "myapp.cpu.svc" is this is + * set to "myapp". Policies are applied using the name with the prefix, + * if present. + */ +#endif + + int fo_listen_queue; + /**< VHOST: 0 = no TCP_FASTOPEN, nonzero = enable TCP_FASTOPEN if the + * platform supports it, with the given queue length for the listen + * socket. + */ + + const struct lws_plugin_evlib *event_lib_custom; + /**< CONTEXT: If non-NULL, override event library selection so it uses + * this custom event library implementation, instead of default internal + * loop. Don't set any other event lib context creation flags in that + * case. it will be used automatically. This is useful for integration + * where an existing application is using its own handrolled event loop + * instead of an event library, it provides a way to allow lws to use + * the custom event loop natively as if it were an "event library". + */ + +#if defined(LWS_WITH_TLS_JIT_TRUST) + size_t jitt_cache_max_footprint; + /**< CONTEXT: 0 for no limit, else max bytes used by JIT Trust cache... + * LRU items are evicted to keep under this limit */ + int vh_idle_grace_ms; + /**< CONTEXT: 0 for default of 5000ms, or number of ms JIT Trust vhosts + * are allowed to live without active connections using them. */ +#endif + + lws_log_cx_t *log_cx; + /**< CONTEXT: NULL to use the default, process-scope logging context, + * else a specific logging context to associate with this context */ + +#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) + const char *http_nsc_filepath; + /**< CONTEXT: Filepath to use for http netscape cookiejar file */ + + size_t http_nsc_heap_max_footprint; + /**< CONTEXT: 0, or limit in bytes for heap usage of memory cookie + * cache */ + size_t http_nsc_heap_max_items; + /**< CONTEXT: 0, or the max number of items allowed in the cookie cache + * before destroying lru items to keep it under the limit */ + size_t http_nsc_heap_max_payload; + /**< CONTEXT: 0, or the maximum size of a single cookie we are able to + * handle */ +#endif + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility + * + * The below is to ensure later library versions with new + * members added above will see 0 (default) even if the app + * was not built against the newer headers. + */ + + void *_unused[2]; /**< dummy */ +}; + +/** + * lws_create_context() - Create the websocket handler + * \param info: pointer to struct with parameters + * + * This function creates the listening socket (if serving) and takes care + * of all initialization in one step. + * + * If option LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, no vhost is + * created; you're expected to create your own vhosts afterwards using + * lws_create_vhost(). Otherwise a vhost named "default" is also created + * using the information in the vhost-related members, for compatibility. + * + * After initialization, it returns a struct lws_context * that + * represents this server. After calling, user code needs to take care + * of calling lws_service() with the context pointer to get the + * server's sockets serviced. This must be done in the same process + * context as the initialization call. + * + * The protocol callback functions are called for a handful of events + * including http requests coming in, websocket connections becoming + * established, and data arriving; it's also called periodically to allow + * async transmission. + * + * HTTP requests are sent always to the FIRST protocol in protocol, since + * at that time websocket protocol has not been negotiated. Other + * protocols after the first one never see any HTTP callback activity. + * + * The server created is a simple http server by default; part of the + * websocket standard is upgrading this http connection to a websocket one. + * + * This allows the same server to provide files like scripts and favicon / + * images or whatever over http and dynamic data over websockets all in + * one place; they're all handled in the user callback. + */ +LWS_VISIBLE LWS_EXTERN struct lws_context * +lws_create_context(const struct lws_context_creation_info *info); + + +/** + * lws_context_destroy() - Destroy the websocket context + * \param context: Websocket context + * + * This function closes any active connections and then frees the + * context. After calling this, any further use of the context is + * undefined. + */ +LWS_VISIBLE LWS_EXTERN void +lws_context_destroy(struct lws_context *context); + +typedef int (*lws_reload_func)(void); + +/** + * lws_context_deprecate() - Deprecate the websocket context + * + * \param context: Websocket context + * \param cb: Callback notified when old context listen sockets are closed + * + * This function is used on an existing context before superceding it + * with a new context. + * + * It closes any listen sockets in the context, so new connections are + * not possible. + * + * And it marks the context to be deleted when the number of active + * connections into it falls to zero. + * + * This is aimed at allowing seamless configuration reloads. + * + * The callback cb will be called after the listen sockets are actually + * closed and may be reopened. In the callback the new context should be + * configured and created. (With libuv, socket close happens async after + * more loop events). + */ +LWS_VISIBLE LWS_EXTERN void +lws_context_deprecate(struct lws_context *context, lws_reload_func cb); + +LWS_VISIBLE LWS_EXTERN int +lws_context_is_deprecated(struct lws_context *context); + +/** + * lws_set_proxy() - Setups proxy to lws_context. + * \param vhost: pointer to struct lws_vhost you want set proxy for + * \param proxy: pointer to c string containing proxy in format address:port + * + * Returns 0 if proxy string was parsed and proxy was setup. + * Returns -1 if proxy is NULL or has incorrect format. + * + * This is only required if your OS does not provide the http_proxy + * environment variable (eg, OSX) + * + * IMPORTANT! You should call this function right after creation of the + * lws_context and before call to connect. If you call this + * function after connect behavior is undefined. + * This function will override proxy settings made on lws_context + * creation with genenv() call. + */ +LWS_VISIBLE LWS_EXTERN int +lws_set_proxy(struct lws_vhost *vhost, const char *proxy); + +/** + * lws_set_socks() - Setup socks to lws_context. + * \param vhost: pointer to struct lws_vhost you want set socks for + * \param socks: pointer to c string containing socks in format address:port + * + * Returns 0 if socks string was parsed and socks was setup. + * Returns -1 if socks is NULL or has incorrect format. + * + * This is only required if your OS does not provide the socks_proxy + * environment variable (eg, OSX) + * + * IMPORTANT! You should call this function right after creation of the + * lws_context and before call to connect. If you call this + * function after connect behavior is undefined. + * This function will override proxy settings made on lws_context + * creation with genenv() call. + */ +LWS_VISIBLE LWS_EXTERN int +lws_set_socks(struct lws_vhost *vhost, const char *socks); + +struct lws_vhost; + +/** + * lws_create_vhost() - Create a vhost (virtual server context) + * \param context: pointer to result of lws_create_context() + * \param info: pointer to struct with parameters + * + * This function creates a virtual server (vhost) using the vhost-related + * members of the info struct. You can create many vhosts inside one context + * if you created the context with the option LWS_SERVER_OPTION_EXPLICIT_VHOSTS + */ +LWS_VISIBLE LWS_EXTERN struct lws_vhost * +lws_create_vhost(struct lws_context *context, + const struct lws_context_creation_info *info); + +/** + * lws_vhost_destroy() - Destroy a vhost (virtual server context) + * + * \param vh: pointer to result of lws_create_vhost() + * + * This function destroys a vhost. Normally, if you just want to exit, + * then lws_destroy_context() will take care of everything. If you want + * to destroy an individual vhost and all connections and allocations, you + * can do it with this. + * + * If the vhost has a listen sockets shared by other vhosts, it will be given + * to one of the vhosts sharing it rather than closed. + * + * The vhost close is staged according to the needs of the event loop, and if + * there are multiple service threads. At the point the vhost itself if + * about to be freed, if you provided a finalize callback and optional arg at + * vhost creation time, it will be called just before the vhost is freed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_vhost_destroy(struct lws_vhost *vh); + +/** + * lwsws_get_config_globals() - Parse a JSON server config file + * \param info: pointer to struct with parameters + * \param d: filepath of the config file + * \param config_strings: storage for the config strings extracted from JSON, + * the pointer is incremented as strings are stored + * \param len: pointer to the remaining length left in config_strings + * the value is decremented as strings are stored + * + * This function prepares a n lws_context_creation_info struct with global + * settings from a file d. + * + * Requires CMake option LWS_WITH_LEJP_CONF to have been enabled + */ +LWS_VISIBLE LWS_EXTERN int +lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d, + char **config_strings, int *len); + +/** + * lwsws_get_config_vhosts() - Create vhosts from a JSON server config file + * \param context: pointer to result of lws_create_context() + * \param info: pointer to struct with parameters + * \param d: filepath of the config file + * \param config_strings: storage for the config strings extracted from JSON, + * the pointer is incremented as strings are stored + * \param len: pointer to the remaining length left in config_strings + * the value is decremented as strings are stored + * + * This function creates vhosts into a context according to the settings in + *JSON files found in directory d. + * + * Requires CMake option LWS_WITH_LEJP_CONF to have been enabled + */ +LWS_VISIBLE LWS_EXTERN int +lwsws_get_config_vhosts(struct lws_context *context, + struct lws_context_creation_info *info, const char *d, + char **config_strings, int *len); + +/** + * lws_get_vhost() - return the vhost a wsi belongs to + * + * \param wsi: which connection + */ +LWS_VISIBLE LWS_EXTERN struct lws_vhost * +lws_get_vhost(struct lws *wsi); + +/** + * lws_get_vhost_name() - returns the name of a vhost + * + * \param vhost: which vhost + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_get_vhost_name(struct lws_vhost *vhost); + +/** + * lws_get_vhost_by_name() - returns the vhost with the requested name, or NULL + * + * \param context: the lws_context to look in + * \param name: vhost name we are looking for + * + * Returns NULL, or the vhost with the name \p name + */ +LWS_VISIBLE LWS_EXTERN struct lws_vhost * +lws_get_vhost_by_name(struct lws_context *context, const char *name); + +/** + * lws_get_vhost_port() - returns the port a vhost listens on, or -1 + * + * \param vhost: which vhost + */ +LWS_VISIBLE LWS_EXTERN int +lws_get_vhost_port(struct lws_vhost *vhost); + +/** + * lws_get_vhost_user() - returns the user pointer for the vhost + * + * \param vhost: which vhost + */ +LWS_VISIBLE LWS_EXTERN void * +lws_get_vhost_user(struct lws_vhost *vhost); + +/** + * lws_get_vhost_iface() - returns the binding for the vhost listen socket + * + * \param vhost: which vhost + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_get_vhost_iface(struct lws_vhost *vhost); + +/** + * lws_json_dump_vhost() - describe vhost state and stats in JSON + * + * \param vh: the vhost + * \param buf: buffer to fill with JSON + * \param len: max length of buf + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len); + +/** + * lws_json_dump_context() - describe context state and stats in JSON + * + * \param context: the context + * \param buf: buffer to fill with JSON + * \param len: max length of buf + * \param hide_vhosts: nonzero to not provide per-vhost mount etc information + * + * Generates a JSON description of vhost state into buf + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_dump_context(const struct lws_context *context, char *buf, int len, + int hide_vhosts); + +/** + * lws_vhost_user() - get the user data associated with the vhost + * \param vhost: Websocket vhost + * + * This returns the optional user pointer that can be attached to + * a vhost when it was created. Lws never dereferences this pointer, it only + * sets it when the vhost is created, and returns it using this api. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_vhost_user(struct lws_vhost *vhost); + +/** + * lws_context_user() - get the user data associated with the context + * \param context: Websocket context + * + * This returns the optional user allocation that can be attached to + * the context the sockets live in at context_create time. It's a way + * to let all sockets serviced in the same context share data without + * using globals statics in the user code. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_context_user(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN const char * +lws_vh_tag(struct lws_vhost *vh); + +/** + * lws_context_is_being_destroyed() - find out if context is being destroyed + * + * \param context: the struct lws_context pointer + * + * Returns nonzero if the context has had lws_context_destroy() called on it... + * when using event library loops the destroy process can be asynchronous. In + * the special case of libuv foreign loops, the failure to create the context + * may have to do work on the foreign loop to reverse the partial creation, + * meaning a failed context create cannot unpick what it did and return NULL. + * + * In that condition, a valid context that is already started the destroy + * process is returned, and this test api will return nonzero as a way to + * find out the create is in the middle of failing. + */ +LWS_VISIBLE LWS_EXTERN int +lws_context_is_being_destroyed(struct lws_context *context); + +/*! \defgroup vhost-mounts Vhost mounts and options + * \ingroup context-and-vhost-creation + * + * ##Vhost mounts and options + */ +///@{ +/** struct lws_protocol_vhost_options - linked list of per-vhost protocol + * name=value options + * + * This provides a general way to attach a linked-list of name=value pairs, + * which can also have an optional child link-list using the options member. + */ +struct lws_protocol_vhost_options { + const struct lws_protocol_vhost_options *next; /**< linked list */ + const struct lws_protocol_vhost_options *options; /**< child linked-list of more options for this node */ + const char *name; /**< name of name=value pair */ + const char *value; /**< value of name=value pair */ +}; + +/** enum lws_mount_protocols + * This specifies the mount protocol for a mountpoint, whether it is to be + * served from a filesystem, or it is a cgi etc. + */ +enum lws_mount_protocols { + LWSMPRO_HTTP = 0, /**< http reverse proxy */ + LWSMPRO_HTTPS = 1, /**< https reverse proxy */ + LWSMPRO_FILE = 2, /**< serve from filesystem directory */ + LWSMPRO_CGI = 3, /**< pass to CGI to handle */ + LWSMPRO_REDIR_HTTP = 4, /**< redirect to http:// url */ + LWSMPRO_REDIR_HTTPS = 5, /**< redirect to https:// url */ + LWSMPRO_CALLBACK = 6, /**< hand by named protocol's callback */ +}; + +/** enum lws_authentication_mode + * This specifies the authentication mode of the mount. The basic_auth_login_file mount parameter + * is ignored unless LWSAUTHM_DEFAULT is set. + */ +enum lws_authentication_mode { + LWSAUTHM_DEFAULT = 0, /**< default authenticate only if basic_auth_login_file is provided */ + LWSAUTHM_BASIC_AUTH_CALLBACK = 1 << 28 /**< Basic auth with a custom verifier */ +}; + +/** The authentication mode is stored in the top 4 bits of lws_http_mount.auth_mask */ +#define AUTH_MODE_MASK 0xF0000000 + +/** struct lws_http_mount + * + * arguments for mounting something in a vhost's url namespace + */ +struct lws_http_mount { + const struct lws_http_mount *mount_next; + /**< pointer to next struct lws_http_mount */ + const char *mountpoint; + /**< mountpoint in http pathspace, eg, "/" */ + const char *origin; + /**< path to be mounted, eg, "/var/www/warmcat.com" */ + const char *def; + /**< default target, eg, "index.html" */ + const char *protocol; + /**<"protocol-name" to handle mount */ + + const struct lws_protocol_vhost_options *cgienv; + /**< optional linked-list of cgi options. These are created + * as environment variables for the cgi process + */ + const struct lws_protocol_vhost_options *extra_mimetypes; + /**< optional linked-list of mimetype mappings */ + const struct lws_protocol_vhost_options *interpret; + /**< optional linked-list of files to be interpreted */ + + int cgi_timeout; + /**< seconds cgi is allowed to live, if cgi://mount type */ + int cache_max_age; + /**< max-age for reuse of client cache of files, seconds */ + unsigned int auth_mask; + /**< bits set here must be set for authorized client session */ + + unsigned int cache_reusable:1; /**< set if client cache may reuse this */ + unsigned int cache_revalidate:1; /**< set if client cache should revalidate on use */ + unsigned int cache_intermediaries:1; /**< set if intermediaries are allowed to cache */ + + unsigned char origin_protocol; /**< one of enum lws_mount_protocols */ + unsigned char mountpoint_len; /**< length of mountpoint string */ + + const char *basic_auth_login_file; + /** + * + * 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. + */ + +/** \defgroup cose COSE apis + * ##COSE related functions + * \ingroup lwsaoi + * + * COSE RFC 8152 relates to signed and encrypted CBOR + */ +//@{ + +enum { + /* RFC8152: Table 2: Common Header Parameters + * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters + */ + + LWSCOSE_WKL_ALG = 1, /* int / tstr */ + LWSCOSE_WKL_CRIT, /* [+ label ] */ + LWSCOSE_WKL_CONTENT_TYPE, /* tstr / uint */ + LWSCOSE_WKL_KID, /* bstr */ + LWSCOSE_WKL_IV, /* bstr */ + LWSCOSE_WKL_IV_PARTIAL, /* bstr */ + LWSCOSE_WKL_COUNTERSIG, /* COSE sig(s) */ + LWSCOSE_WKL_COUNTERSIG0 = 9, /* bstr */ + LWSCOSE_WKL_KID_CONTEXT, /* bstr */ + LWSCOSE_WKL_CUPH_NONCE = 256, /* bstr */ + LWSCOSE_WKL_CUPH_OWNER_PUBKEY = 257, /* array */ + + /* RFC8152: Table 3: key map labels */ + + LWSCOSE_WKK_KTY = 1, /* int / tstr */ + LWSCOSE_WKK_KID, /* bstr */ + LWSCOSE_WKK_ALG, /* int / tstr */ + LWSCOSE_WKK_KEY_OPS, /* [ + (int / tstr) ] */ + LWSCOSE_WKK_BASE_IV, /* bstr */ + + /* RFC8152: Table 4: Key Operation Values */ + + LWSCOSE_WKKO_SIGN = 1, + LWSCOSE_WKKO_VERIFY, + LWSCOSE_WKKO_ENCRYPT, + LWSCOSE_WKKO_DECRYPT, + LWSCOSE_WKKO_WRAP_KEY, + LWSCOSE_WKKO_UNWRAP_KEY, + LWSCOSE_WKKO_DERIVE_KEY, + LWSCOSE_WKKO_DERIVE_BITS, + LWSCOSE_WKKO_MAC_CREATE, + LWSCOSE_WKKO_MAC_VERIFY, + + /* RFC8152: Table 5: ECDSA algs */ + + LWSCOSE_WKAECDSA_ALG_ES256 = -7, + LWSCOSE_WKAECDSA_ALG_ES384 = -35, + LWSCOSE_WKAECDSA_ALG_ES512 = -36, + + /* RFC8152: Table 6: EDDSA algs */ + + LWSCOSE_WKAEDDSA_ALG_EDDSA = -8, + + /* RFC8152: Table 7: HMAC algs */ + + LWSCOSE_WKAHMAC_256_64 = 4, + LWSCOSE_WKAHMAC_256_256, + LWSCOSE_WKAHMAC_384_384, + LWSCOSE_WKAHMAC_512_512, + + /* RFC8152: Table 8: AES algs */ + + LWSCOSE_WKAAES_128_64 = 14, + LWSCOSE_WKAAES_256_64, + LWSCOSE_WKAAES_128_128 = 25, + LWSCOSE_WKAAES_256_128, + + /* RFC8152: Table 9: AES GCM algs */ + + LWSCOSE_WKAAESGCM_128 = 1, + LWSCOSE_WKAAESGCM_192, + LWSCOSE_WKAAESGCM_256, + + /* RFC8152: Table 10: AES CCM algs */ + + LWSCOSE_WKAAESCCM_16_64_128 = 10, + LWSCOSE_WKAAESCCM_16_64_256, + LWSCOSE_WKAAESCCM_64_64_128, + LWSCOSE_WKAAESCCM_64_64_256, + LWSCOSE_WKAAESCCM_16_128_128, + LWSCOSE_WKAAESCCM_16_128_256, + LWSCOSE_WKAAESCCM_64_128_128, + LWSCOSE_WKAAESCCM_64_128_256, + + /* RFC8152: Table 11: CHACHA20 / Poly1305 */ + + LWSCOSE_WKACHACHA_POLY1305 = 24, + + /* RFC8152: Table 13: HKDF param */ + + LWSCOSE_WKAPHKDF_SALT = -20, + + /* RFC8152: Table 14: Context Algorithm Parameters */ + + LWSCOSE_WKAPCTX_PARTY_U_IDENTITY = -21, + LWSCOSE_WKAPCTX_PARTY_U_NONCE = -22, + LWSCOSE_WKAPCTX_PARTY_U_OTHER = -23, + LWSCOSE_WKAPCTX_PARTY_V_IDENTITY = -24, + LWSCOSE_WKAPCTX_PARTY_V_NONCE = -25, + LWSCOSE_WKAPCTX_PARTY_V_OTHER = -26, + + /* RFC8152: Table 15: Direct key */ + + LWSCOSE_WKK_DIRECT_CEK = -6, + + /* RFC8152: Table 16: Direct key with KDF */ + + LWSCOSE_WKK_DIRECT_HKDF_SHA_256 = -10, + LWSCOSE_WKK_DIRECT_HKDF_SHA_512 = -11, + LWSCOSE_WKK_DIRECT_HKDF_AES_128 = -12, + LWSCOSE_WKK_DIRECT_HKDF_AES_256 = -13, + + /* RFC8152: Table 17: AES Key Wrap Algorithm Values */ + + LWSCOSE_WKK_DIRECT_HKDFKW_SHA_256 = -3, + LWSCOSE_WKK_DIRECT_HKDFKW_SHA_512 = -4, + LWSCOSE_WKK_DIRECT_HKDFKW_AES_128 = -5, + + /* RFC8152: Table 18: ECDH Algorithm Values */ + + LWSCOSE_WKAECDH_ALG_ES_HKDF_256 = -25, + LWSCOSE_WKAECDH_ALG_ES_HKDF_512 = -26, + LWSCOSE_WKAECDH_ALG_SS_HKDF_256 = -27, + LWSCOSE_WKAECDH_ALG_SS_HKDF_512 = -28, + + /* RFC8152: Table 19: ECDH Algorithm Parameters */ + + LWSCOSE_WKAPECDH_EPHEMERAL_KEY = -1, + LWSCOSE_WKAPECDH_STATIC_KEY = -2, + LWSCOSE_WKAPECDH_STATIC_KEY_ID = -3, + + /* RFC8152: Table 20: ECDH Algorithm Parameters with key wrap */ + + LWSCOSE_WKAPECDH_ES_A128KW = -29, + LWSCOSE_WKAPECDH_ES_A192KW = -30, + LWSCOSE_WKAPECDH_ES_A256KW = -31, + LWSCOSE_WKAPECDH_SS_A128KW = -32, + LWSCOSE_WKAPECDH_SS_A192KW = -33, + LWSCOSE_WKAPECDH_SS_A256KW = -34, + + /* RFC8152: Table 21: Key Type Values + * https://www.iana.org/assignments/cose/cose.xhtml#key-type + */ + + LWSCOSE_WKKTV_OKP = 1, + LWSCOSE_WKKTV_EC2 = 2, + LWSCOSE_WKKTV_RSA = 3, + LWSCOSE_WKKTV_SYMMETRIC = 4, + LWSCOSE_WKKTV_HSS_LMS = 5, + LWSCOSE_WKKTV_WALNUTDSA = 6, + + + /* RFC8152: Table 22: Elliptic Curves + * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves + */ + + LWSCOSE_WKEC_P256 = 1, + LWSCOSE_WKEC_P384, + LWSCOSE_WKEC_P521, + LWSCOSE_WKEC_X25519, + LWSCOSE_WKEC_X448, + LWSCOSE_WKEC_ED25519, + LWSCOSE_WKEC_ED448, + LWSCOSE_WKEC_SECP256K1, + + /* RFC8152: Table 23: EC Key Parameters */ + + LWSCOSE_WKECKP_CRV = -1, + LWSCOSE_WKECKP_X = -2, + LWSCOSE_WKECKP_Y = -3, + LWSCOSE_WKECKP_D = -4, + + /* RFC8152: Table 24: Octet Key Pair (OKP) Parameters */ + + LWSCOSE_WKOKP_CRV = -1, + LWSCOSE_WKOKP_X = -2, + LWSCOSE_WKOKP_D = -4, + + /* Additional from + * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters + */ + + LWSCOSE_WKKPRSA_N = -1, + LWSCOSE_WKKPRSA_E = -2, + LWSCOSE_WKKPRSA_D = -3, + LWSCOSE_WKKPRSA_P = -4, + LWSCOSE_WKKPRSA_Q = -5, + LWSCOSE_WKKPRSA_DP = -6, + LWSCOSE_WKKPRSA_DQ = -7, + LWSCOSE_WKKPRSA_QINV = -8, + LWSCOSE_WKKPRSA_OTHER = -9, + LWSCOSE_WKKPRSA_RI = -10, + LWSCOSE_WKKPRSA_DI = -11, + LWSCOSE_WKKPRSA_TI = -12, + + /* RFC8152: Table 25: Symmetric Key Parameters */ + + LWSCOSE_WKSYMKP_KEY_VALUE = 4, + + /* RFC8152: Table 26: CoAP Content-Formats for COSE */ + + LWSCOAP_CONTENTFORMAT_COSE_SIGN = 98, + LWSCOAP_CONTENTFORMAT_COSE_SIGN1 = 18, + LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT = 96, + LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT0 = 16, + LWSCOAP_CONTENTFORMAT_COSE_MAC = 97, + LWSCOAP_CONTENTFORMAT_COSE_MAC0 = 17, + LWSCOAP_CONTENTFORMAT_COSE_KEY = 101, + LWSCOAP_CONTENTFORMAT_COSE_KEY_SET = 102, + + /* RFC8152: Table 27: Header Parameter for CounterSignature0 */ + + LWSCOSE_WKL_COUNTERSIGNATURE0 = 9, /* bstr */ + + /* RFC8812: Table 1: RSASSA-PKCS1-v1_5 Algorithm Values */ + + LWSCOSE_WKARSA_ALG_RS256 = -257, /* + SHA-256 */ + LWSCOSE_WKARSA_ALG_RS384 = -258, /* + SHA-384 */ + LWSCOSE_WKARSA_ALG_RS512 = -259, /* + SHA-512 */ +}; + +enum enum_cose_key_meta_tok { + COSEKEY_META_KTY, + COSEKEY_META_KID, + COSEKEY_META_KEY_OPS, + COSEKEY_META_BASE_IV, + COSEKEY_META_ALG, + + LWS_COUNT_COSE_KEY_ELEMENTS +}; + +typedef int64_t cose_param_t; + +LWS_VISIBLE LWS_EXTERN const char * +lws_cose_alg_to_name(cose_param_t alg); + +LWS_VISIBLE LWS_EXTERN cose_param_t +lws_cose_name_to_alg(const char *name); + +/* + * cose_key + */ + +typedef struct lws_cose_key { + /* key data elements */ + struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT]; + /* generic meta key elements, like KID */ + struct lws_gencrypto_keyelem meta[LWS_COUNT_COSE_KEY_ELEMENTS]; + lws_dll2_t list; /* used when part of a set */ + int gencrypto_kty; /**< one of LWS_GENCRYPTO_KTY_ */ + cose_param_t kty; + cose_param_t cose_alg; + cose_param_t cose_curve; + char private_key; /* nonzero = has private key elements */ +} lws_cose_key_t; + +typedef int (*lws_cose_key_import_callback)(struct lws_cose_key *s, void *user); + +/** lws_cose_jwk_import() - Create an lws_cose_key_t object from cose_key CBOR + * + * \param pkey_set: NULL, or a pointer to an lws_dll2_owner_t for a cose_key set + * \param cb: callback for each jwk-processed key, or NULL if importing a single + * key with no parent "keys" JSON + * \param user: pointer to be passed to the callback, otherwise ignored by lws. + * NULL if importing a single key with no parent "keys" JSON + * \param in: a single cose_key + * \param len: the length of the cose_key in bytes + * + * Creates a single lws_cose_key_t if \p pkey_set is NULL or if the incoming + * CBOR doesn't start with an array, otherwise expects a CBOR array containing + * zero or more cose_key CBOR, and adds each to the \p pkey_set + * lws_dll2_owner_t struct. Created lws_cose_key_t are filled with data from + * the COSE representation and can be used with other COSE crypto ops. + */ +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb, + void *user, const uint8_t *in, size_t len); + +/** lws_cose_key_export() - Create cose_key CBOR from an lws_cose_key_t + * + * \param ck: the lws_cose_key_t to export to CBOR + * \param ctx: the CBOR writing context (same as for lws_lec_printf()) + * \param flags: 0 to export only public elements, or LWSJWKF_EXPORT_PRIVATE + * + * Creates an lws_jwk struct filled with data from the COSE representation. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags); + +/** + * lws_cose_key_generate() - generate a fresh key + * + * \param context: the lws_context used to get random + * \param cose_kty: one of LWSCOSE_WKKTV_ indicating the well-known key type + * \param use_mask: 0, or a bitfield where (1 << LWSCOSE_WKKO_...) set means valid for use + * \param bits: key bits for RSA + * \param curve: for EC keys, one of "P-256", "P-384" or "P-521" currently + * \param kid: string describing the key, or NULL + * + * Create an lws_cose_key_t of the specified type and return it + */ +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty, + int use_mask, int bits, const char *curve, + const uint8_t *kid, size_t kl); + +LWS_VISIBLE LWS_EXTERN lws_cose_key_t * +lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_destroy(lws_cose_key_t **ck); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_set_destroy(lws_dll2_owner_t *o); + +/* only available in _DEBUG build */ + +LWS_VISIBLE LWS_EXTERN void +lws_cose_key_dump(const lws_cose_key_t *ck); + +/* + * cose_sign + */ + +struct lws_cose_validate_context; + + +enum lws_cose_sig_types { + SIGTYPE_UNKNOWN, + SIGTYPE_MULTI, + SIGTYPE_SINGLE, + SIGTYPE_COUNTERSIGNED, /* not yet supported */ + SIGTYPE_MAC, /* only supported for validation */ + SIGTYPE_MAC0, +}; + +/* a list of these result objects is the output of the validation process */ + +typedef struct { + lws_dll2_t list; + + const lws_cose_key_t *cose_key; + cose_param_t cose_alg; + + int result; /* 0 = validated */ + +} lws_cose_validate_res_t; + +enum { + LCOSESIGEXTCB_RET_FINISHED, + LCOSESIGEXTCB_RET_AGAIN, + LCOSESIGEXTCB_RET_ERROR = -1 +}; + +typedef struct { + struct lws_cose_validate_context *cps; + const uint8_t *ext; + size_t xl; +} lws_cose_sig_ext_pay_t; + +typedef int (*lws_cose_sign_ext_pay_cb_t)(lws_cose_sig_ext_pay_t *x); +typedef int (*lws_cose_validate_pay_cb_t)(struct lws_cose_validate_context *cps, + void *opaque, const uint8_t *paychunk, + size_t paychunk_len); + +typedef struct lws_cose_validate_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + enum lws_cose_sig_types sigtype; + /**< 0 if a CBOR tag is in the sig, else one of SIGTYPE_MULTI, + * SIGTYPE_SINGLE, etc*/ + + lws_cose_validate_pay_cb_t pay_cb; + /**< optional: called back with unvalidated payload pieces */ + void *pay_opaque; + /**< optional: passed into pay_cb callback along with payload chunk */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ +} lws_cose_validate_create_info_t; + +/** + * lws_cose_validate_create() - create a signature validation context + * + * \param info: struct describing the validation context to create + * + * Creates a signature validation context set up as described in \p info. + * + * You can then pass the signature cbor chunks to it using + * lws_cose_validate_chunk(), finialize and get the results list using + * lws_cose_validate_results() and destroy with lws_cose_validate_destroy(). + */ +LWS_VISIBLE LWS_EXTERN struct lws_cose_validate_context * +lws_cose_validate_create(const lws_cose_validate_create_info_t *info); + +/** + * lws_cose_validate_chunk() - passes chunks of CBOR into the signature validator + * + * \param cps: the validation context + * \param in: the chunk of CBOR (does not have to be logically complete) + * \param in_len: number of bytes available at \p in + * + * Parses signature CBOR to produce a list of result objects. + * + * + */ +LWS_VISIBLE LWS_EXTERN int +lws_cose_validate_chunk(struct lws_cose_validate_context *cps, + const uint8_t *in, size_t in_len, size_t *used_in); + +LWS_VISIBLE LWS_EXTERN lws_dll2_owner_t * +lws_cose_validate_results(struct lws_cose_validate_context *cps); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_validate_destroy(struct lws_cose_validate_context **cps); + +struct lws_cose_sign_context; + +#define LCSC_FL_ADD_CBOR_TAG (1 << 0) +#define LCSC_FL_ADD_CBOR_PREFER_MAC0 (1 << 1) + +typedef struct lws_cose_sign_create_info { + struct lws_context *cx; + /**< REQUIRED: the lws context */ + lws_dll2_owner_t *keyset; + /**< REQUIRED: one or more cose_keys */ + + lws_lec_pctx_t *lec; + /**< REQUIRED: the cbor output context to emit to, user must + * initialize with lws_lec_init() beforehand */ + + lws_cose_sign_ext_pay_cb_t ext_cb; + /**< optional extra application data provision callback */ + void *ext_opaque; + /**< optional extra application data provision callback opaque */ + size_t ext_len; + /**< if we have extra app data, this must be set to the length of it */ + + size_t inline_payload_len; + /**< REQUIRED: size of the inline payload we will provide */ + + int flags; + /**< bitmap of LCSC_FL_* */ + enum lws_cose_sig_types sigtype; + /**< 0, or sign type hint */ +} lws_cose_sign_create_info_t; + +/** + * lws_cose_sign_create() - Create a signing context + * + * \param info: a structure describing the signing context you want to create + * + * This allocates and returns a signing context created according to what is in + * the \p info parameter. + * + * \p info must be prepared with the lws_context, a keyset to use, a CBOR + * output context, and the inline payload length. + * + * Returns NULL on failure or the created signing context ready to add alg(s) + * to. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_cose_sign_context * +lws_cose_sign_create(const lws_cose_sign_create_info_t *info); + +LWS_VISIBLE LWS_EXTERN int +lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, + const lws_cose_key_t *ck); + +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, + const uint8_t *in, size_t in_len); + +LWS_VISIBLE LWS_EXTERN void +lws_cose_sign_destroy(struct lws_cose_sign_context **csc); + +//@} diff --git a/thirdparty/include/libwebsockets/lws-dbus.h b/thirdparty/include/libwebsockets/lws-dbus.h new file mode 100755 index 0000000000000000000000000000000000000000..2a82d810335507d9c4a9f201c838cf147b134aa5 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-dbus.h @@ -0,0 +1,94 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + * + * must be included manually as + * + * #include + * + * if dbus apis needed + */ + +#if !defined(__LWS_DBUS_H__) +#define __LWS_DBUS_H__ + +#include + +/* helper type to simplify implementing methods as individual functions */ +typedef DBusHandlerResult (*lws_dbus_message_handler)(DBusConnection *conn, + DBusMessage *message, DBusMessage **reply, void *d); + +struct lws_dbus_ctx; +typedef void (*lws_dbus_closing_t)(struct lws_dbus_ctx *ctx); + +struct lws_dbus_ctx { + struct lws_dll2_owner owner; /* dbusserver ctx: HEAD of accepted list */ + struct lws_dll2 next; /* dbusserver ctx: HEAD of accepted list */ + struct lws_vhost *vh; /* the vhost we logically bind to in lws */ + int tsi; /* the lws thread service index (0 if only one service + thread as is the default */ + DBusConnection *conn; + DBusServer *dbs; + DBusWatch *w[4]; + DBusPendingCall *pc; + + char hup; + char timeouts; + + /* cb_closing callback will be called after the connection and this + * related ctx struct have effectively gone out of scope. + * + * The callback should close and clean up the connection and free the + * ctx. + */ + lws_dbus_closing_t cb_closing; +}; + +/** + * lws_dbus_connection_setup() - bind dbus connection object to lws event loop + * + * \param ctx: additional information about the connection + * \param conn: the DBusConnection object to bind + * + * This configures a DBusConnection object to use lws for watchers and timeout + * operations. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dbus_connection_setup(struct lws_dbus_ctx *ctx, DBusConnection *conn, + lws_dbus_closing_t cb_closing); + +/** + * lws_dbus_server_listen() - bind dbus connection object to lws event loop + * + * \param ctx: additional information about the connection + * \param ads: the DBUS address to listen on, eg, "unix:abstract=mysocket" + * \param err: a DBusError object to take any extra error information + * \param new_conn: a callback function to prepare new accepted connections + * + * This creates a DBusServer and binds it to the lws event loop, and your + * callback to accept new connections. + */ +LWS_VISIBLE LWS_EXTERN DBusServer * +lws_dbus_server_listen(struct lws_dbus_ctx *ctx, const char *ads, + DBusError *err, DBusNewConnectionFunction new_conn); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-diskcache.h b/thirdparty/include/libwebsockets/lws-diskcache.h new file mode 100755 index 0000000000000000000000000000000000000000..ebca888d500f5a33a0749a48ab0ffe8b011b5a32 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-diskcache.h @@ -0,0 +1,187 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup diskcache LWS disk cache + * ## Disk cache API + * + * Lws provides helper apis useful if you need a disk cache containing hashed + * files and need to delete files from it on an LRU basis to keep it below some + * size limit. + * + * The API `lws_diskcache_prepare()` deals with creating the cache dir and + * 256 subdirs, which are used according to the first two chars of the hex + * hash of the cache file. + * + * `lws_diskcache_create()` and `lws_diskcache_destroy()` allocate and free + * an opaque struct that represents the disk cache. + * + * `lws_diskcache_trim()` should be called at eg, 1s intervals to perform the + * cache dir monitoring and LRU autodelete in the background lazily. It can + * be done in its own thread or on a timer... it monitors the directories in a + * stateful way that stats one or more file in the cache per call, and keeps + * a list of the oldest files as it goes. When it completes a scan, if the + * aggregate size is over the limit, it will delete oldest files first to try + * to keep it under the limit. + * + * The cache size monitoring is extremely efficient in time and memory even when + * the cache directory becomes huge. + * + * `lws_diskcache_query()` is used to determine if the file already exists in + * the cache, or if it must be created. If it must be created, then the file + * is opened using a temp name that must be converted to a findable name with + * `lws_diskcache_finalize_name()` when the generation of the file contents are + * complete. Aborted cached files that did not complete generation will be + * flushed by the LRU eventually. If the file already exists, it is 'touched' + * to make it new again and the fd returned. + * + */ +///@{ + +struct lws_diskcache_scan; + +/** + * lws_diskcache_create() - creates an opaque struct representing the disk cache + * + * \param cache_dir_base: The cache dir path, eg `/var/cache/mycache` + * \param cache_size_limit: maximum size on disk the cache is allowed to use + * + * This returns an opaque `struct lws_diskcache_scan *` which represents the + * disk cache, the trim scanning state and so on. You should use + * `lws_diskcache_destroy()` to free it to destroy it. + */ +LWS_VISIBLE LWS_EXTERN struct lws_diskcache_scan * +lws_diskcache_create(const char *cache_dir_base, uint64_t cache_size_limit); + +/** + * lws_diskcache_destroy() - destroys the pointer returned by ...create() + * + * \param lds: pointer to the pointer returned by lws_diskcache_create() + * + * Frees *lds and any allocations it did, and then sets *lds to NULL and + * returns. + */ +LWS_VISIBLE LWS_EXTERN void +lws_diskcache_destroy(struct lws_diskcache_scan **lds); + +/** + * lws_diskcache_prepare() - ensures the cache dir structure exists on disk + * + * \param cache_base_dir: The cache dir path, eg `/var/cache/mycache` + * \param mode: octal dir mode to enforce, like 0700 + * \param uid: uid the cache dir should belong to + * + * This should be called while your app is still privileged. It will create + * the cache directory structure on disk as necessary, enforce the given access + * mode on it and set the given uid as the owner. It won't make any trouble + * if the cache already exists. + * + * Typically the mode is 0700 and the owner is the user that your application + * will transition to use when it drops root privileges. + */ +LWS_VISIBLE LWS_EXTERN int +lws_diskcache_prepare(const char *cache_base_dir, int mode, uid_t uid); + +#define LWS_DISKCACHE_QUERY_NO_CACHE 0 +#define LWS_DISKCACHE_QUERY_EXISTS 1 +#define LWS_DISKCACHE_QUERY_CREATING 2 +#define LWS_DISKCACHE_QUERY_ONGOING 3 /* something else is creating it */ + +/** + * lws_diskcache_query() - ensures the cache dir structure exists on disk + * + * \param lds: The opaque struct representing the disk cache + * \param is_bot: nonzero means the request is from a bot. Don't create new cache contents if so. + * \param hash_hex: hex string representation of the cache object hash + * \param _fd: pointer to the fd to be set + * \param cache: destination string to take the cache filepath + * \param cache_len: length of the buffer at `cache` + * \param extant_cache_len: pointer to a size_t to take any extant cached file size + * + * This function is called when you want to find if the hashed name already + * exists in the cache. The possibilities for the return value are + * + * - LWS_DISKCACHE_QUERY_NO_CACHE: It's not in the cache and you can't create + * it in the cache for whatever reason. + * - LWS_DISKCACHE_QUERY_EXISTS: It exists in the cache. It's open RDONLY and + * *_fd has been set to the file descriptor. *extant_cache_len has been set + * to the size of the cached file in bytes. cache has been set to the + * full filepath of the cached file. Closing _fd is your responsibility. + * - LWS_DISKCACHE_QUERY_CREATING: It didn't exist, but a temp file has been + * created in the cache and *_fd set to a file descriptor opened on it RDWR. + * You should create the contents, and call `lws_diskcache_finalize_name()` + * when it is done. Closing _fd is your responsibility. + * - LWS_DISKCACHE_QUERY_ONGOING: not returned by this api, but you may find it + * desirable to make a wrapper function which can handle another asynchronous + * process that is already creating the cached file. This can be used to + * indicate that situation externally... how to determine the same thing is + * already being generated is out of scope of this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_diskcache_query(struct lws_diskcache_scan *lds, int is_bot, + const char *hash_hex, int *_fd, char *cache, int cache_len, + size_t *extant_cache_len); + +/** + * lws_diskcache_query() - ensures the cache dir structure exists on disk + * + * \param cache: The cache file temp name returned with LWS_DISKCACHE_QUERY_CREATING + * + * This renames the cache file you are creating to its final name. It should + * be called on the temp name returned by `lws_diskcache_query()` if it gave a + * LWS_DISKCACHE_QUERY_CREATING return, after you have filled the cache file and + * closed it. + */ +LWS_VISIBLE LWS_EXTERN int +lws_diskcache_finalize_name(char *cache); + +/** + * lws_diskcache_trim() - performs one or more file checks in the cache for size management + * + * \param lds: The opaque object representing the cache + * + * This should be called periodically to statefully walk the cache on disk + * collecting the oldest files. When it has visited every file, if the cache + * is oversize it will delete the oldest files until it's back under size again. + * + * Each time it's called, it will look at one or more dir in the cache. If + * called when the cache is oversize, it increases the amount of work done each + * call until it is reduced again. Typically it will take 256 calls before it + * deletes anything, so if called once per second, it will delete files once + * every 4 minutes. Each call is very inexpensive both in memory and time. + */ +LWS_VISIBLE LWS_EXTERN int +lws_diskcache_trim(struct lws_diskcache_scan *lds); + + +/** + * lws_diskcache_secs_to_idle() - see how long to idle before calling trim + * + * \param lds: The opaque object representing the cache + * + * If the cache is undersize, there's no need to monitor it immediately. This + * suggests how long to "sleep" before calling `lws_diskcache_trim()` again. + */ +LWS_VISIBLE LWS_EXTERN int +lws_diskcache_secs_to_idle(struct lws_diskcache_scan *lds); +///@} diff --git a/thirdparty/include/libwebsockets/lws-display.h b/thirdparty/include/libwebsockets/lws-display.h new file mode 100755 index 0000000000000000000000000000000000000000..203cfc57b557b0bba2e4579253149ce29b5cd69b --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-display.h @@ -0,0 +1,158 @@ +/* + * lws abstract display + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_H__) +#define __LWS_DISPLAY_H__ + +#include + +typedef uint16_t lws_display_scalar; + +/* + * This is embedded in the actual display implementation object at the top, + * so a pointer to this can be cast to a pointer to the implementation object + * by any code that is specific to how it was implemented. + * + * Notice for the backlight / display intensity we contain pwm_ops... these can + * be some other pwm_ops like existing gpio pwm ops, or handled in a customized + * way like set oled contrast. Either way, the pwm level is arrived at via a + * full set of lws_led_sequences capable of generic lws transitions + */ + +typedef struct lws_display { + int (*init)(const struct lws_display *disp); + const lws_pwm_ops_t *bl_pwm_ops; + int (*contrast)(const struct lws_display *disp, uint8_t contrast); + int (*blit)(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); + int (*power)(const struct lws_display *disp, int state); + + const lws_led_sequence_def_t *bl_active; + const lws_led_sequence_def_t *bl_dim; + const lws_led_sequence_def_t *bl_transition; + + void *variant; + + int bl_index; + + lws_display_scalar w; + /**< display surface width in pixels */ + lws_display_scalar h; + /**< display surface height in pixels */ + + uint8_t latency_wake_ms; + /**< ms required after wake from sleep before display usable again... + * delay bringing up the backlight for this amount of time on wake. + * This is managed via a sul on the event loop, not blocking. */ +} lws_display_t; + +/* + * This contains dynamic data related to display state + */ + +enum lws_display_controller_state { + LWSDISPS_OFF, + LWSDISPS_AUTODIMMED, /* is in pre- blanking static dim mode */ + LWSDISPS_BECOMING_ACTIVE, /* waiting for wake latency before active */ + LWSDISPS_ACTIVE, /* is active */ + LWSDISPS_GOING_OFF /* dimming then off */ +}; + +typedef struct lws_display_state { + + lws_sorted_usec_list_t sul_autodim; + const lws_display_t *disp; + struct lws_context *ctx; + + int autodim_ms; + int off_ms; + + struct lws_led_state *bl_lcs; + + lws_led_state_chs_t chs; + /* set of sequencer transition channels */ + + enum lws_display_controller_state state; + +} lws_display_state_t; + +/** + * lws_display_state_init() - initialize display states + * + * \param lds: the display state object + * \param ctx: the lws context + * \param autodim_ms: ms since last active report to dim display (<0 = never) + * \param off_ms: ms since dim to turn display off (<0 = never) + * \param bl_lcs: the led controller instance that has the backlight + * \param disp: generic display object we belong to + * + * This initializes a display's state, and sets up the optional screen auto-dim + * and blanking on inactive, and gradual brightness change timer. + * + * - auto-dim then off: set autodim to some ms and off_ms to some ms + * - auto-dim only: set autodim to some ms and off_ms to -1 + * - off-only: set autodim to some ms and off_ms to 0 + * - neither: set both autodim and off_ms to -1 + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, + int autodim_ms, int off_ms, struct lws_led_state *bl_lcs, + const lws_display_t *disp); + +/** + * lws_display_state_set_brightness() - gradually change the brightness + * + * \param lds: the display state we are changing + * \param target: the target brightness to transition to + * + * Adjusts the brightness gradually twoards the target at 20Hz + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_set_brightness(lws_display_state_t *lds, + const lws_led_sequence_def_t *pwmseq); + +/* + * lws_display_state_active() - inform the system the display is active + * + * \param lds: the display state we are marking as active + * + * Resets the auto-dim and auto-off timers and makes sure the display is on and + * at the active brightness level + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_active(lws_display_state_t *lds); + +/* + * lws_display_state_off() - turns off the related display + * + * \param lds: the display state we are turning off + * + * Turns the display to least power mode or completely off if possible. + * Disables the timers related to dimming and blanking. + */ +LWS_VISIBLE LWS_EXTERN void +lws_display_state_off(lws_display_state_t *lds); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-dll2.h b/thirdparty/include/libwebsockets/lws-dll2.h new file mode 100755 index 0000000000000000000000000000000000000000..14f0fcd47852782a7c3f5fdd66db5471aec642c5 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-dll2.h @@ -0,0 +1,305 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup ll linked-lists +* ##Linked list apis +* +* simple single and doubly-linked lists +*/ +///@{ + +/** + * lws_start_foreach_ll(): linkedlist iterator helper start + * + * \param type: type of iteration, eg, struct xyz * + * \param it: iterator var name to create + * \param start: start of list + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at start and + * ends when it gets a NULL. + * The while loop should be terminated using lws_start_foreach_ll(). + */ +#define lws_start_foreach_ll(type, it, start)\ +{ \ + type it = start; \ + while (it) { + +/** + * lws_end_foreach_ll(): linkedlist iterator helper end + * + * \param it: same iterator var name given when starting + * \param nxt: member name in the iterator pointing to next list element + * + * This helper is the partner for lws_start_foreach_ll() that ends the + * while loop. + */ + +#define lws_end_foreach_ll(it, nxt) \ + it = it->nxt; \ + } \ +} + +/** + * lws_start_foreach_ll_safe(): linkedlist iterator helper start safe against delete + * + * \param type: type of iteration, eg, struct xyz * + * \param it: iterator var name to create + * \param start: start of list + * \param nxt: member name in the iterator pointing to next list element + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at start and + * ends when it gets a NULL. + * The while loop should be terminated using lws_end_foreach_ll_safe(). + * Performs storage of next increment for situations where iterator can become invalidated + * during iteration. + */ +#define lws_start_foreach_ll_safe(type, it, start, nxt)\ +{ \ + type it = start; \ + while (it) { \ + type next_##it = it->nxt; + +/** + * lws_end_foreach_ll_safe(): linkedlist iterator helper end (pre increment storage) + * + * \param it: same iterator var name given when starting + * + * This helper is the partner for lws_start_foreach_ll_safe() that ends the + * while loop. It uses the precreated next_ variable already stored during + * start. + */ + +#define lws_end_foreach_ll_safe(it) \ + it = next_##it; \ + } \ +} + +/** + * lws_start_foreach_llp(): linkedlist pointer iterator helper start + * + * \param type: type of iteration, eg, struct xyz ** + * \param it: iterator var name to create + * \param start: start of list + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at the + * address of start and ends when it gets a NULL. + * The while loop should be terminated using lws_start_foreach_llp(). + * + * This helper variant iterates using a pointer to the previous linked-list + * element. That allows you to easily delete list members by rewriting the + * previous pointer to the element's next pointer. + */ +#define lws_start_foreach_llp(type, it, start)\ +{ \ + type it = &(start); \ + while (*(it)) { + +#define lws_start_foreach_llp_safe(type, it, start, nxt)\ +{ \ + type it = &(start); \ + type next; \ + while (*(it)) { \ + next = &((*(it))->nxt); \ + +/** + * lws_end_foreach_llp(): linkedlist pointer iterator helper end + * + * \param it: same iterator var name given when starting + * \param nxt: member name in the iterator pointing to next list element + * + * This helper is the partner for lws_start_foreach_llp() that ends the + * while loop. + */ + +#define lws_end_foreach_llp(it, nxt) \ + it = &(*(it))->nxt; \ + } \ +} + +#define lws_end_foreach_llp_safe(it) \ + it = next; \ + } \ +} + +#define lws_ll_fwd_insert(\ + ___new_object, /* pointer to new object */ \ + ___m_list, /* member for next list object ptr */ \ + ___list_head /* list head */ \ + ) {\ + ___new_object->___m_list = ___list_head; \ + ___list_head = ___new_object; \ + } + +#define lws_ll_fwd_remove(\ + ___type, /* type of listed object */ \ + ___m_list, /* member for next list object ptr */ \ + ___target, /* object to remove from list */ \ + ___list_head /* list head */ \ + ) { \ + lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \ + if (*___ppss == ___target) { \ + *___ppss = ___target->___m_list; \ + break; \ + } \ + } lws_end_foreach_llp(___ppss, ___m_list); \ + } + + +/* + * doubly linked-list + */ + +/* + * lws_dll2_owner / lws_dll2 : more capable version of lws_dll. Differences: + * + * - there's an explicit lws_dll2_owner struct which holds head, tail and + * count of members. + * + * - list members all hold a pointer to their owner. So user code does not + * have to track anything about exactly what lws_dll2_owner list the object + * is a member of. + * + * - you can use lws_dll unless you want the member count or the ability to + * not track exactly which list it's on. + * + * - layout is compatible with lws_dll (but lws_dll apis will not update the + * new stuff) + */ + + +struct lws_dll2; +struct lws_dll2_owner; + +typedef struct lws_dll2 { + struct lws_dll2 *prev; + struct lws_dll2 *next; + struct lws_dll2_owner *owner; +} lws_dll2_t; + +typedef struct lws_dll2_owner { + struct lws_dll2 *tail; + struct lws_dll2 *head; + + uint32_t count; +} lws_dll2_owner_t; + +LWS_VISIBLE LWS_EXTERN int +lws_dll2_is_detached(const struct lws_dll2 *d); + +static LWS_INLINE const struct lws_dll2_owner * +lws_dll2_owner(const struct lws_dll2 *d) { return d->owner; } + +static LWS_INLINE struct lws_dll2 * +lws_dll2_get_head(struct lws_dll2_owner *owner) { return owner->head; } + +static LWS_INLINE struct lws_dll2 * +lws_dll2_get_tail(struct lws_dll2_owner *owner) { return owner->tail; } + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_add_head(struct lws_dll2 *d, struct lws_dll2_owner *owner); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_remove(struct lws_dll2 *d); + +typedef int (*lws_dll2_foreach_cb_t)(struct lws_dll2 *d, void *user); + +LWS_VISIBLE LWS_EXTERN int +lws_dll2_foreach_safe(struct lws_dll2_owner *owner, void *user, + lws_dll2_foreach_cb_t cb); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_clear(struct lws_dll2 *d); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_owner_clear(struct lws_dll2_owner *d); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_add_before(struct lws_dll2 *d, struct lws_dll2 *after); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own, + int (*compare)(const lws_dll2_t *d, const lws_dll2_t *i)); + +LWS_VISIBLE LWS_EXTERN void +lws_dll2_add_sorted_priv(lws_dll2_t *d, lws_dll2_owner_t *own, void *priv, + int (*compare3)(void *priv, const lws_dll2_t *d, + const lws_dll2_t *i)); + +LWS_VISIBLE LWS_EXTERN void * +_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen, + size_t dll2_ofs, size_t ptr_ofs); + +/* + * Searches objects in an owner list linearly and returns one with a given + * member C-string matching a supplied length-provided string if it exists, else + * NULL. + */ + +#define lws_dll2_search_sz_pl(own, name, namelen, type, membd2list, membptr) \ + ((type *)_lws_dll2_search_sz_pl(own, name, namelen, \ + offsetof(type, membd2list), \ + offsetof(type, membptr))) + +#if defined(_DEBUG) +void +lws_dll2_describe(struct lws_dll2_owner *owner, const char *desc); +#else +#define lws_dll2_describe(x, y) +#endif + +/* + * these are safe against the current container object getting deleted, + * since the hold his next in a temp and go to that next. ___tmp is + * the temp. + */ + +#define lws_start_foreach_dll_safe(___type, ___it, ___tmp, ___start) \ +{ \ + ___type ___it = ___start; \ + while (___it) { \ + ___type ___tmp = (___it)->next; + +#define lws_end_foreach_dll_safe(___it, ___tmp) \ + ___it = ___tmp; \ + } \ +} + +#define lws_start_foreach_dll(___type, ___it, ___start) \ +{ \ + ___type ___it = ___start; \ + while (___it) { + +#define lws_end_foreach_dll(___it) \ + ___it = (___it)->next; \ + } \ +} + +///@} + diff --git a/thirdparty/include/libwebsockets/lws-dsh.h b/thirdparty/include/libwebsockets/lws-dsh.h new file mode 100755 index 0000000000000000000000000000000000000000..09c950c05727bc092becc5f2edf06cb94b65199b --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-dsh.h @@ -0,0 +1,148 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/* + * lws_dsh (Disordered Shared Heap) is an opaque abstraction supporting a single + * linear buffer (overallocated at end of the lws_dsh_t) which may contain + * multiple kinds of packets that are retired out of order, and tracked by kind. + * + * Each kind of packet has an lws_dll2 list of its kind of packets and acts as + * a FIFO; packets of a particular type are always retired in order. But there + * is no requirement about the order types are retired matching the original + * order they arrived. + * + * Gaps are tracked as just another kind of "packet" list. + * + * "allocations" (including gaps) are prepended by an lws_dsh_object_t. + * + * dsh may themselves be on an lws_dll2_owner list, and under memory pressure + * allocate into other buffers on the list. + * + * All management structures exist inside the allocated buffer. + */ + +/** + * lws_dsh_create() - Allocate a DSH buffer + * + * \param owner: the owning list this dsh belongs on, or NULL if standalone + * \param buffer_size: the allocation in bytes + * \param count_kinds: how many separately-tracked fifos use the buffer + * + * This makes a single heap allocation that includes internal tracking objects + * in the buffer. Sub-allocated objects are bound to a "kind" index and + * managed via a FIFO for each kind. + * + * Every "kind" of allocation shares the same buffer space. + * + * Multiple buffers may be bound together in an lws_dll2 list, and if an + * allocation cannot be satisfied by the local buffer, space can be borrowed + * from other dsh in the same list (the local dsh FIFO tracks these "foreign" + * allocations as if they were local). + * + * Returns an opaque pointer to the dsh, or NULL if allocation failed. + */ +LWS_VISIBLE LWS_EXTERN struct lws_dsh * +lws_dsh_create(lws_dll2_owner_t *owner, size_t buffer_size, int count_kinds); + +/** + * lws_dsh_destroy() - Destroy a DSH buffer + * + * \param pdsh: pointer to the dsh pointer + * + * Deallocates the DSH and sets *pdsh to NULL. + * + * Before destruction, any foreign buffer usage on the part of this dsh are + * individually freed. All dsh on the same list are walked and checked if they + * have their own foreign allocations on the dsh buffer being destroyed. If so, + * it attempts to migrate the allocation to a dsh that is not currently being + * destroyed. If all else fails (basically the buffer memory is being shrunk) + * unmigratable objects are cleanly destroyed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_dsh_destroy(struct lws_dsh **pdsh); + +/** + * lws_dsh_alloc_tail() - make a suballocation inside a dsh + * + * \param dsh: the dsh tracking the allocation + * \param kind: the kind of allocation + * \param src1: the first source data to copy + * \param size1: the size of the first source data + * \param src2: the second source data to copy (after the first), or NULL + * \param size2: the size of the second source data + * + * Allocates size1 + size2 bytes in a dsh (it prefers the given dsh but will + * borrow space from other dsh on the same list if necessary) and copies size1 + * bytes into it from src1, followed by size2 bytes from src2 if src2 isn't + * NULL. The actual suballocation is a bit larger because of alignment and a + * prepended management header. + * + * The suballocation is added to the kind-specific FIFO at the tail. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dsh_alloc_tail(struct lws_dsh *dsh, int kind, const void *src1, + size_t size1, const void *src2, size_t size2); + +/** + * lws_dsh_free() - free a suballocation from the dsh + * + * \param obj: a pointer to a void * that pointed to the allocated payload + * + * This returns the space used by \p obj in the dsh buffer to the free list + * of the dsh the allocation came from. + */ +LWS_VISIBLE LWS_EXTERN void +lws_dsh_free(void **obj); + +LWS_VISIBLE LWS_EXTERN size_t +lws_dsh_get_size(struct lws_dsh *dsh, int kind); + +/** + * lws_dsh_get_head() - get the head allocation inside the dsh + * + * \param dsh: the dsh tracking the allocation + * \param kind: the kind of allocation + * \param obj: pointer to a void * to be set to the payload + * \param size: set to the size of the allocation + * + * This gets the "next" object in the kind FIFO for the dsh, and returns 0 if + * any. If none, returns nonzero. + * + * This is nondestructive of the fifo or the payload. Use lws_dsh_free on + * obj to remove the entry from the kind fifo and return the payload to the + * free list. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dsh_get_head(struct lws_dsh *dsh, int kind, void **obj, size_t *size); + +/** + * lws_dsh_describe() - DEBUG BUILDS ONLY dump the dsh to the logs + * + * \param dsh: the dsh to dump + * \param desc: text that appears at the top of the dump + * + * Useful information for debugging lws_dsh + */ +LWS_VISIBLE LWS_EXTERN void +lws_dsh_describe(struct lws_dsh *dsh, const char *desc); diff --git a/thirdparty/include/libwebsockets/lws-eventlib-exports.h b/thirdparty/include/libwebsockets/lws-eventlib-exports.h new file mode 100755 index 0000000000000000000000000000000000000000..5d01caa9d7df20bd0df76b49512c3f50d660bedc --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-eventlib-exports.h @@ -0,0 +1,150 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + * + * These are exports needed by event lib plugins. + */ + +enum lws_event_lib_ops_flags { + LELOF_ISPOLL = (1 >> 0), + LELOF_DESTROY_FINAL = (1 >> 1), +}; + +enum { + LWS_EV_READ = (1 << 0), + LWS_EV_WRITE = (1 << 1), + LWS_EV_START = (1 << 2), + LWS_EV_STOP = (1 << 3), +}; + +struct lws_event_loop_ops { + const char *name; + /* event loop-specific context init during context creation */ + int (*init_context)(struct lws_context *context, + const struct lws_context_creation_info *info); + /* called during lws_destroy_context */ + int (*destroy_context1)(struct lws_context *context); + /* called during lws_destroy_context2 */ + int (*destroy_context2)(struct lws_context *context); + /* init vhost listening wsi */ + int (*init_vhost_listen_wsi)(struct lws *wsi); + /* init the event loop for a pt */ + int (*init_pt)(struct lws_context *context, void *_loop, int tsi); + /* called at end of first phase of close_free_wsi() */ + int (*wsi_logical_close)(struct lws *wsi); + /* return nonzero if client connect not allowed */ + int (*check_client_connect_ok)(struct lws *wsi); + /* close handle manually */ + void (*close_handle_manually)(struct lws *wsi); + /* event loop accept processing */ + int (*sock_accept)(struct lws *wsi); + /* control wsi active events */ + void (*io)(struct lws *wsi, unsigned int flags); + /* run the event loop for a pt */ + void (*run_pt)(struct lws_context *context, int tsi); + /* called before pt is destroyed */ + void (*destroy_pt)(struct lws_context *context, int tsi); + /* called just before wsi is freed */ + void (*destroy_wsi)(struct lws *wsi); + /* return nonzero if caller thread is not loop service thread */ + int (*foreign_thread)(struct lws_context *context, int tsi); + + uint8_t flags; + + uint16_t evlib_size_ctx; + uint16_t evlib_size_pt; + uint16_t evlib_size_vh; + uint16_t evlib_size_wsi; +}; + +LWS_VISIBLE LWS_EXTERN void * +lws_evlib_wsi_to_evlib_pt(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void * +lws_evlib_tsi_to_evlib_pt(struct lws_context *ctx, int tsi); + + /* + * You should consider these opaque for normal user code. + */ + +LWS_VISIBLE LWS_EXTERN void * +lws_realloc(void *ptr, size_t size, const char *reason); + +LWS_VISIBLE LWS_EXTERN void +lws_vhost_destroy1(struct lws_vhost *vh); + +LWS_VISIBLE LWS_EXTERN void +lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, + const char *caller); + +LWS_VISIBLE LWS_EXTERN int +lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg, + lws_dll2_foreach_cb_t cb); + +struct lws_context_per_thread; +LWS_VISIBLE LWS_EXTERN void +lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt); + +#if !defined(wsi_from_fd) && !defined(WIN32) && !defined(_WIN32) +struct lws_context; +LWS_VISIBLE LWS_EXTERN struct lws * +wsi_from_fd(const struct lws_context *context, int fd); +#endif + +LWS_VISIBLE LWS_EXTERN int +_lws_plat_service_forced_tsi(struct lws_context *context, int tsi); + +LWS_VISIBLE LWS_EXTERN void +lws_context_destroy2(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN void +lws_destroy_event_pipe(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +__lws_close_free_wsi_final(struct lws *wsi); + +#if LWS_MAX_SMP > 1 + +struct lws_mutex_refcount { + pthread_mutex_t lock; + pthread_t lock_owner; + const char *last_lock_reason; + char lock_depth; + char metadata; +}; + +LWS_VISIBLE LWS_EXTERN void +lws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr); + +LWS_VISIBLE LWS_EXTERN void +lws_mutex_refcount_init(struct lws_mutex_refcount *mr); + +LWS_VISIBLE LWS_EXTERN void +lws_mutex_refcount_destroy(struct lws_mutex_refcount *mr); + +LWS_VISIBLE LWS_EXTERN void +lws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason); + +LWS_VISIBLE LWS_EXTERN void +lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-fault-injection.h b/thirdparty/include/libwebsockets/lws-fault-injection.h new file mode 100755 index 0000000000000000000000000000000000000000..e9133763e42e68ce6122a6ce319ba5a52b729bce --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-fault-injection.h @@ -0,0 +1,251 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + * + * Fault injection api if built with LWS_WITH_SYS_FAULT_INJECTION + */ + +typedef struct lws_xos { + uint64_t s[4]; +} lws_xos_t; + +/** + * lws_xos_init() - seed xoshiro256 PRNG + * + * \param xos: the prng state object to initialize + * \param seed: the 64-bit seed + * + * Initialize PRNG \xos with the starting state represented by \p seed + */ +LWS_VISIBLE LWS_EXTERN void +lws_xos_init(struct lws_xos *xos, uint64_t seed); + +/** + * lws_xos() - get next xoshiro256 PRNG result and update state + * + * \param xos: the PRNG state to use + * + * Returns next 64-bit PRNG result. These are cheap to get, + * quite a white noise sequence, and completely deterministic + * according to the seed it was initialized with. + */ +LWS_VISIBLE LWS_EXTERN uint64_t LWS_WARN_UNUSED_RESULT +lws_xos(struct lws_xos *xos); + +/** + * lws_xos_percent() - return 1 a given percent of the time on average + * + * \param xos: the PRNG state to use + * \param percent: chance in 100 of returning 1 + * + * Returns 1 if next random % 100 is < \p percent, such that + * 100 always returns 1, 0 never returns 1, and the chance linearly scales + * inbetween + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_xos_percent(struct lws_xos *xos, int percent); + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + +enum { + LWSFI_ALWAYS, + LWSFI_DETERMINISTIC, /* do .count injections after .pre then stop */ + LWSFI_PROBABILISTIC, /* .pre % chance of injection */ + LWSFI_PATTERN, /* use .count bits in .pattern after .pre */ + LWSFI_PATTERN_ALLOC, /* as _PATTERN, but .pattern is malloc'd */ + LWSFI_RANGE /* pick a number between pre and count */ +}; + +typedef struct lws_fi { + const char *name; + const uint8_t *pattern; + uint64_t pre; + uint64_t count; + uint64_t times; /* start at 0, tracks usage */ + char type; /* LWSFI_* */ +} lws_fi_t; + +typedef struct lws_fi_ctx { + lws_dll2_owner_t fi_owner; + struct lws_xos xos; + const char *name; +} lws_fi_ctx_t; + +/** + * lws_fi() - find out if we should perform the named fault injection this time + * + * \param fic: fault injection tracking context + * \param fi_name: name of fault injection + * + * This checks if the named fault is configured in the fi tracking context + * provided, if it is, then it will make a decision if the named fault should + * be applied this time, using the tracking in the named lws_fi_t. + * + * If the provided context has a parent, that is also checked for the named fi + * item recursively, with the first found being used to determine if to inject + * or not. + * + * If LWS_WITH_SYS_FAULT_INJECTION is not defined, then this always return 0. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fi(const lws_fi_ctx_t *fic, const char *fi_name); + +/** + * lws_fi_range() - get a random number from a range + * + * \param fic: fault injection tracking context + * \param fi_name: name of fault injection + * \param result: points to uint64_t to be set to the result + * + * This lets you get a random number from an externally-set range, set using a + * fault injection syntax like "myfault(123..456)". That will cause us to + * return a number between those two inclusive, from the seeded PRNG. + * + * This is useful when you used lws_fi() with its own fault name to decide + * whether to inject the fault, and then the code to cause the fault needs + * additional constrained pseudo-random fuzzing for, eg, delays before issuing + * the fault. + * + * Returns 0 if \p *result is set, else nonzero for failure. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result); + +/** + * lws_fi_add() - add an allocated copy of fault injection to a context + * + * \param fic: fault injection tracking context + * \param fi: the fault injection details + * + * This allocates a copy of \p fi and attaches it to the fault injection context + * \p fic. \p fi can go out of scope after this safely. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi); + +/** + * lws_fi_remove() - remove an allocated copy of fault injection from a context + * + * \param fic: fault injection tracking context + * \param name: the fault injection name to remove + * + * This looks for the named fault injection and removes and destroys it from + * the specified fault injection context + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_remove(lws_fi_ctx_t *fic, const char *name); + +/** + * lws_fi_import() - transfers all the faults from one context to another + * + * \param fic_dest: the fault context to receive the faults + * \param fic_src: the fault context that will be emptied out into \p fic_dest + * + * This is used to initialize created object fault injection contexts from + * the caller. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src); + +/** + * lws_fi_inherit_copy() - attach copies of matching fault injection objects to dest + * + * \param fic_dest: destination Fault Injection context + * \param fic_src: parent fault context that may contain matching rules + * \param scope: the name of the path match required, eg, "vh" + * \param value: the dynamic name of our match, eg, "myvhost" + * + * If called with scope "vh" and value "myvhost", then matches faults starting + * "vh=myvhost/", strips that part of the name if it matches and makes a copy + * of the rule with the modified name attached to the destination Fault Injection + * context. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src, + const char *scope, const char *value); + +/** + * lws_fi_destroy() - removes all allocated fault injection entries + * + * \param fic: fault injection tracking context + * + * This walks any allocated fault injection entries in \p fic and detaches and + * destroys them. It doesn't try to destroc \p fic itself, since this is + * not usually directly allocated. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fi_destroy(const lws_fi_ctx_t *fic); + +/** + * lws_fi_deserialize() - adds fault in string form to Fault Injection Context + * + * \p fic: the fault injection context + * \p sers: the string serializing the desired fault details + * + * This turns a string like "ss=captive_portal_detect/wsi/dnsfail(10%)" into + * a fault injection struct added to the fault injection context \p fic + * + * You can prepare the context creation info .fic with these before creating + * the context, and use namespace paths on those to target other objects. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers); + +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_wsi_fi(struct lws *wsi, const char *name); +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_context_fi(struct lws_context *ctx, const char *name); + +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_ss_handle; +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name); +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) +struct lws_sspc_handle; +LWS_VISIBLE LWS_EXTERN int +_lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name); +#endif +#endif + +#define lws_fi_user_wsi_fi(_wsi, _name) _lws_fi_user_wsi_fi(_wsi, _name) +#define lws_fi_user_context_fi(_ctx, _name) _lws_fi_user_context_fi(_ctx, _name) +#define lws_fi_user_ss_fi(_h, _name) _lws_fi_user_ss_fi(_h, _name) +#define lws_fi_user_sspc_fi(_h, _name) _lws_fi_user_sspc_fi(_h, _name) + +#else + +/* + * Helper so we can leave lws_fi() calls embedded in the code being tested, + * if fault injection is not enabled then it just always says "no" at buildtime. + */ + +#define lws_fi(_fi_name, _fic) (0) +#define lws_fi_destroy(_x) +#define lws_fi_inherit_copy(_a, _b, _c, _d) +#define lws_fi_deserialize(_x, _y) +#define lws_fi_user_wsi_fi(_wsi, _name) (0) +#define lws_fi_user_context_fi(_wsi, _name) (0) +#define lws_fi_user_ss_fi(_h, _name) (0) +#define lws_fi_user_sspc_fi(_h, _name) (0) + +#endif diff --git a/thirdparty/include/libwebsockets/lws-freertos.h b/thirdparty/include/libwebsockets/lws-freertos.h new file mode 100755 index 0000000000000000000000000000000000000000..a78722995bd1ea1f4994eaf9c6bd8a7f3729e17a --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-freertos.h @@ -0,0 +1,87 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * This is included from libwebsockets.h if LWS_PLAT_FREERTOS + */ + +typedef int lws_sockfd_type; +typedef int lws_filefd_type; + +#if defined(LWS_AMAZON_RTOS) +#include +#include +#include +#include "timers.h" +#include + +/* + * Later lwip (at least 2.1.12) already defines these in its own headers + * protected by the same test as used here... if POLLIN / POLLOUT already exist + * then assume no need to declare those and struct pollfd. + * + * Older lwip needs these declarations done here. + */ + +#if !defined(POLLIN) && !defined(POLLOUT) + +struct pollfd { + lws_sockfd_type fd; /**< fd related to */ + short events; /**< which POLL... events to respond to */ + short revents; /**< which POLL... events occurred */ +}; +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +#endif + +#else /* LWS_AMAZON_RTOS */ +#include +#include +#include +#include "esp_wifi.h" +#include "esp_system.h" +#include "esp_event.h" +//#include "esp_event_loop.h" +#include "nvs.h" +#include "driver/gpio.h" +#include "esp_spi_flash.h" +#include "freertos/timers.h" + +#if defined(LWS_ESP_PLATFORM) +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#if defined(LWS_WITH_DRIVERS) +#include "libwebsockets/lws-gpio.h" +extern const lws_gpio_ops_t lws_gpio_plat; +#endif +#endif + +#endif /* LWS_AMAZON_RTOS */ + +#if !defined(CONFIG_FREERTOS_HZ) +#define CONFIG_FREERTOS_HZ 100 +#endif diff --git a/thirdparty/include/libwebsockets/lws-fts.h b/thirdparty/include/libwebsockets/lws-fts.h new file mode 100755 index 0000000000000000000000000000000000000000..e7d31aff0fcefd0790d0a9f610b717a578795237 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-fts.h @@ -0,0 +1,215 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup search Search + * + * ##Full-text search + * + * Lws provides superfast indexing and fulltext searching from index files on + * storage. + */ +///@{ + +struct lws_fts; +struct lws_fts_file; + +/* + * Queries produce their results in an lwsac, using these public API types. + * The first thing in the lwsac is always a struct lws_fts_result (see below) + * containing heads for linked-lists of the other result types. + */ + +/* one filepath's results */ + +struct lws_fts_result_filepath { + struct lws_fts_result_filepath *next; + int matches; /* logical number of matches */ + int matches_length; /* bytes in length table (may be zero) */ + int lines_in_file; + int filepath_length; + + /* - uint32_t line table follows (first for alignment) */ + /* - filepath (of filepath_length) follows */ +}; + +/* autocomplete result */ + +struct lws_fts_result_autocomplete { + struct lws_fts_result_autocomplete *next; + int instances; + int agg_instances; + int ac_length; + char elided; /* children skipped in interest of antecedent children */ + char has_children; + + /* - autocomplete suggestion (of length ac_length) follows */ +}; + +/* + * The results lwsac always starts with this. If no results and / or no + * autocomplete the members may be NULL. This implies the symbol nor any + * suffix on it exists in the trie file. + */ +struct lws_fts_result { + struct lws_fts_result_filepath *filepath_head; + struct lws_fts_result_autocomplete *autocomplete_head; + int duration_ms; + int effective_flags; /* the search flags that were used */ +}; + +/* + * index creation functions + */ + +/** + * lws_fts_create() - Create a new index file + * + * \param fd: The fd opened for write + * + * Inits a new index file, returning a struct lws_fts to represent it + */ +LWS_VISIBLE LWS_EXTERN struct lws_fts * +lws_fts_create(int fd); + +/** + * lws_fts_destroy() - Finalize a new index file / destroy the trie lwsac + * + * \param trie: The previously opened index being finalized + * + * Finalizes an index file that was being created, and frees the memory involved + * *trie is set to NULL afterwards. + */ +LWS_VISIBLE LWS_EXTERN void +lws_fts_destroy(struct lws_fts **trie); + +/** + * lws_fts_file_index() - Create a new entry in the trie file for an input path + * + * \param t: The previously opened index being written + * \param filepath: The filepath (which may be virtual) associated with this file + * \param filepath_len: The number of chars in the filepath + * \param priority: not used yet + * + * Returns an ordinal that represents this new filepath in the index file. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fts_file_index(struct lws_fts *t, const char *filepath, int filepath_len, + int priority); + +/** + * lws_fts_fill() - Process all or a bufferload of input file + * + * \param t: The previously opened index being written + * \param file_index: The ordinal representing this input filepath + * \param buf: A bufferload of data from the input file + * \param len: The number of bytes in buf + * + * Indexes a buffer of data from the input file. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fts_fill(struct lws_fts *t, uint32_t file_index, const char *buf, + size_t len); + +/** + * lws_fts_serialize() - Store the in-memory trie into the index file + * + * \param t: The previously opened index being written + * + * The trie is held in memory where it can be added to... after all the input + * filepaths and data have been processed, this is called to serialize / + * write the trie data into the index file. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fts_serialize(struct lws_fts *t); + +/* + * index search functions + */ + +/** + * lws_fts_open() - Open an existing index file to search it + * + * \param filepath: The filepath to the index file to open + * + * Opening the index file returns an opaque struct lws_fts_file * that is + * used to perform other operations on it, or NULL if it can't be opened. + */ +LWS_VISIBLE LWS_EXTERN struct lws_fts_file * +lws_fts_open(const char *filepath); + +#define LWSFTS_F_QUERY_AUTOCOMPLETE (1 << 0) +#define LWSFTS_F_QUERY_FILES (1 << 1) +#define LWSFTS_F_QUERY_FILE_LINES (1 << 2) +#define LWSFTS_F_QUERY_QUOTE_LINE (1 << 3) + +struct lws_fts_search_params { + /* the actual search term */ + const char *needle; + /* if non-NULL, FILE results for this filepath only */ + const char *only_filepath; + /* will be set to the results lwsac */ + struct lwsac *results_head; + /* combination of LWSFTS_F_QUERY_* flags */ + int flags; + /* maximum number of autocomplete suggestions to return */ + int max_autocomplete; + /* maximum number of filepaths to return */ + int max_files; + /* maximum number of line number results to return per filepath */ + int max_lines; +}; + +/** + * lws_fts_search() - Perform a search operation on an index + * + * \param jtf: The index file struct returned by lws_fts_open + * \param ftsp: The struct lws_fts_search_params filled in by the caller + * + * The caller should memset the ftsp struct to 0 to ensure members that may be + * introduced in later versions contain known values, then set the related + * members to describe the kind of search action required. + * + * ftsp->results_head is the results lwsac, or NULL. It should be freed with + * lwsac_free() when the results are finished with. + * + * Returns a pointer into the results lwsac that is a struct lws_fts_result + * containing the head pointers into linked-lists of results for autocomplete + * and filepath data, along with some sundry information. This does not need + * to be freed since freeing the lwsac will also remove this and everything it + * points to. + */ +LWS_VISIBLE LWS_EXTERN struct lws_fts_result * +lws_fts_search(struct lws_fts_file *jtf, struct lws_fts_search_params *ftsp); + +/** + * lws_fts_close() - Close a previously-opened index file + * + * \param jtf: The pointer returned from the open + * + * Closes the file handle on the index and frees any allocations + */ +LWS_VISIBLE LWS_EXTERN void +lws_fts_close(struct lws_fts_file *jtf); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-genaes.h b/thirdparty/include/libwebsockets/lws-genaes.h new file mode 100755 index 0000000000000000000000000000000000000000..6095f6837c97592b0d5216862e57a1f0ea0cc4ce --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-genaes.h @@ -0,0 +1,170 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/*! \defgroup generic AES + * ## Generic AES related functions + * + * Lws provides generic AES functions that abstract the ones + * provided by whatever tls library you are linking against. + * + * It lets you use the same code if you build against mbedtls or OpenSSL + * for example. + */ +///@{ + +#if defined(LWS_WITH_MBEDTLS) +#include +#include +#endif + +enum enum_aes_modes { + LWS_GAESM_CBC, + LWS_GAESM_CFB128, + LWS_GAESM_CFB8, + LWS_GAESM_CTR, + LWS_GAESM_ECB, + LWS_GAESM_OFB, + LWS_GAESM_XTS, /* care... requires double-length key */ + LWS_GAESM_GCM, + LWS_GAESM_KW, +}; + +enum enum_aes_operation { + LWS_GAESO_ENC, + LWS_GAESO_DEC +}; + +enum enum_aes_padding { + LWS_GAESP_NO_PADDING, + LWS_GAESP_WITH_PADDING +}; + +/* include/libwebsockets/lws-jwk.h must be included before this */ + +#define LWS_AES_BLOCKSIZE 128 +#define LWS_AES_CBC_BLOCKLEN 16 + +struct lws_genaes_ctx { +#if defined(LWS_WITH_MBEDTLS) + union { + mbedtls_aes_context ctx; +#if defined(MBEDTLS_CIPHER_MODE_XTS) + mbedtls_aes_xts_context ctx_xts; +#endif + mbedtls_gcm_context ctx_gcm; + } u; +#else + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + ENGINE *engine; + char init; +#endif + unsigned char tag[16]; + struct lws_gencrypto_keyelem *k; + enum enum_aes_operation op; + enum enum_aes_modes mode; + enum enum_aes_padding padding; + int taglen; + char underway; +}; + +/** lws_genaes_create() - Create RSA public decrypt context + * + * \param ctx: your struct lws_genaes_ctx + * \param op: LWS_GAESO_ENC or LWS_GAESO_DEC + * \param mode: one of LWS_GAESM_ + * \param el: struct prepared with key element data + * \param padding: 0 = no padding, 1 = padding + * \param engine: if openssl engine used, pass the pointer here + * + * Creates an RSA context with a public key associated with it, formed from + * the key elements in \p el. + * + * Returns 0 for OK or nonzero for error. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op, + enum enum_aes_modes mode, struct lws_gencrypto_keyelem *el, + enum enum_aes_padding padding, void *engine); + +/** lws_genaes_destroy() - Destroy genaes AES context + * + * \param ctx: your struct lws_genaes_ctx + * \param tag: NULL, or, GCM-only: buffer to receive tag + * \param tlen: 0, or, GCM-only: length of tag buffer + * + * Destroys any allocations related to \p ctx. + * + * For GCM only, up to tlen bytes of tag buffer will be set on exit. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen); + +/** lws_genaes_crypt() - Encrypt or decrypt + * + * \param ctx: your struct lws_genaes_ctx + * \param in: input plaintext or ciphertext + * \param len: length of input (which is always length of output) + * \param out: output plaintext or ciphertext + * \param iv_or_nonce_ctr_or_data_unit_16: NULL, iv, nonce_ctr16, or data_unit16 + * \param stream_block_16: pointer to 16-byte stream block for CTR mode only + * \param nc_or_iv_off: NULL or pointer to nc, or iv_off + * \param taglen: length of tag + * + * Encrypts or decrypts using the AES mode set when the ctx was created. + * The last three arguments have different meanings depending on the mode: + * + * KW CBC CFB128 CFB8 CTR ECB OFB XTS + * iv_or_nonce_ct.._unit_16 : iv iv iv iv nonce NULL iv dataunt + * stream_block_16 : NULL NULL NULL NULL stream NULL NULL NULL + * nc_or_iv_off : NULL NULL iv_off NULL nc_off NULL iv_off NULL + * + * For GCM: + * + * iv_or_nonce_ctr_or_data_unit_16 : iv + * stream_block_16 : pointer to tag + * nc_or_iv_off : set pointed-to size_t to iv length + * in : first call: additional data, subsequently + * : input data + * len : first call: add data length, subsequently + * : input / output length + * + * The length of the optional arg is always 16 if used, regardless of the mode. + * + * Returns 0 for OK or nonzero for error. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, + uint8_t *out, + uint8_t *iv_or_nonce_ctr_or_data_unit_16, + uint8_t *stream_block_16, + size_t *nc_or_iv_off, int taglen); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-gencrypto.h b/thirdparty/include/libwebsockets/lws-gencrypto.h new file mode 100755 index 0000000000000000000000000000000000000000..001823100b6c07e2e4ce3e39ce0697be94587337 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-gencrypto.h @@ -0,0 +1,137 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/* + * These are gencrypto-level constants... they are used by both JOSE and direct + * gencrypto code. However while JWK relies on these, using gencrypto apis has + * no dependency at all on any JOSE type. + */ + +enum lws_gencrypto_kty { + LWS_GENCRYPTO_KTY_UNKNOWN, + + LWS_GENCRYPTO_KTY_OCT, + LWS_GENCRYPTO_KTY_RSA, + LWS_GENCRYPTO_KTY_EC +}; + +/* + * Keytypes where the same element name is reused must all agree to put the + * same-named element at the same e[] index. It's because when used with jwk, + * we parse and store in incoming key data, but we may not be informed of the + * definitive keytype until the end. + */ + +enum lws_gencrypto_oct_tok { + LWS_GENCRYPTO_OCT_KEYEL_K, /* note... same offset as AES K */ + + LWS_GENCRYPTO_OCT_KEYEL_COUNT +}; + +enum lws_gencrypto_rsa_tok { + LWS_GENCRYPTO_RSA_KEYEL_E, + LWS_GENCRYPTO_RSA_KEYEL_N, + LWS_GENCRYPTO_RSA_KEYEL_D, /* note... same offset as EC D */ + LWS_GENCRYPTO_RSA_KEYEL_P, + LWS_GENCRYPTO_RSA_KEYEL_Q, + LWS_GENCRYPTO_RSA_KEYEL_DP, + LWS_GENCRYPTO_RSA_KEYEL_DQ, + LWS_GENCRYPTO_RSA_KEYEL_QI, + + /* we don't actively use these if given, but may come from COSE */ + + LWS_GENCRYPTO_RSA_KEYEL_OTHER, + LWS_GENCRYPTO_RSA_KEYEL_RI, + LWS_GENCRYPTO_RSA_KEYEL_DI, + LWS_GENCRYPTO_RSA_KEYEL_TI, + + LWS_GENCRYPTO_RSA_KEYEL_COUNT +}; + +enum lws_gencrypto_ec_tok { + LWS_GENCRYPTO_EC_KEYEL_CRV, + LWS_GENCRYPTO_EC_KEYEL_X, + /* note... same offset as RSA D */ + LWS_GENCRYPTO_EC_KEYEL_D = LWS_GENCRYPTO_RSA_KEYEL_D, + LWS_GENCRYPTO_EC_KEYEL_Y, + + LWS_GENCRYPTO_EC_KEYEL_COUNT +}; + +enum lws_gencrypto_aes_tok { + /* note... same offset as OCT K */ + LWS_GENCRYPTO_AES_KEYEL_K = LWS_GENCRYPTO_OCT_KEYEL_K, + + LWS_GENCRYPTO_AES_KEYEL_COUNT +}; + +/* largest number of key elements for any algorithm */ +#define LWS_GENCRYPTO_MAX_KEYEL_COUNT LWS_GENCRYPTO_RSA_KEYEL_COUNT + +/* this "stretchy" type holds individual key element data in binary form. + * It's typcially used in an array with the layout mapping the element index to + * the key element meaning defined by the enums above. An array of these of + * length LWS_GENCRYPTO_MAX_KEYEL_COUNT can define key elements for any key + * type. + */ + +typedef struct lws_gencrypto_keyelem { + uint8_t *buf; + uint32_t len; +} lws_gc_elem_t; + + +/** + * lws_gencrypto_bits_to_bytes() - returns rounded up bytes needed for bits + * + * \param bits + * + * Returns the number of bytes needed to store the given number of bits. If + * a byte is partially used, the byte count is rounded up. + */ +LWS_VISIBLE LWS_EXTERN int +lws_gencrypto_bits_to_bytes(int bits); + +/** + * lws_base64_size() - returns estimated size of base64 encoding + * + * \param bytes + * + * Returns a slightly oversize estimate of the size of a base64 encoded version + * of the given amount of unencoded data. + */ +LWS_VISIBLE LWS_EXTERN int +lws_base64_size(int bytes); + +/** + * lws_gencrypto_padded_length() - returns PKCS#5/#7 padded length + * + * @param blocksize - blocksize to pad to + * @param len - Length of input to pad + * + * Returns the length of a buffer originally of size len after PKCS#5 or PKCS#7 + * padding has been applied to it. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_gencrypto_padded_length(size_t block_size, size_t len); diff --git a/thirdparty/include/libwebsockets/lws-genec.h b/thirdparty/include/libwebsockets/lws-genec.h new file mode 100755 index 0000000000000000000000000000000000000000..c18cc1e1f4962036ec2043a9efeabfb59ef3b585 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-genec.h @@ -0,0 +1,211 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +enum enum_genec_alg { + LEGENEC_UNKNOWN, + + LEGENEC_ECDH, + LEGENEC_ECDSA +}; + +struct lws_genec_ctx { +#if defined(LWS_WITH_MBEDTLS) + union { + mbedtls_ecdh_context *ctx_ecdh; + mbedtls_ecdsa_context *ctx_ecdsa; + } u; +#else + EVP_PKEY_CTX *ctx[2]; +#endif + struct lws_context *context; + const struct lws_ec_curves *curve_table; + enum enum_genec_alg genec_alg; + + char has_private; +}; + +#if defined(LWS_WITH_MBEDTLS) +enum enum_lws_dh_side { + LDHS_OURS = MBEDTLS_ECDH_OURS, + LDHS_THEIRS = MBEDTLS_ECDH_THEIRS +}; +#else +enum enum_lws_dh_side { + LDHS_OURS, + LDHS_THEIRS +}; +#endif + +struct lws_ec_curves { + const char *name; + int tls_lib_nid; + uint16_t key_bytes; +}; + + +/* ECDH-specific apis */ + +/** lws_genecdh_create() - Create a genecdh + * + * \param ctx: your genec context + * \param context: your lws_context (for RNG access) + * \param curve_table: NULL, enabling P-256, P-384 and P-521, or a replacement + * struct lws_ec_curves array, terminated by an entry with + * .name = NULL, of curves you want to allow + * + * Initializes a genecdh + */ +LWS_VISIBLE int +lws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context, + const struct lws_ec_curves *curve_table); + +/** lws_genecdh_set_key() - Apply an EC key to our or theirs side + * + * \param ctx: your genecdh context + * \param el: your key elements + * \param side: LDHS_OURS or LDHS_THEIRS + * + * Applies an EC key to one side or the other of an ECDH ctx + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el, + enum enum_lws_dh_side side); + +/** lws_genecdh_new_keypair() - Create a genec with a new public / private key + * + * \param ctx: your genec context + * \param side: LDHS_OURS or LDHS_THEIRS + * \param curve_name: an EC curve name, like "P-256" + * \param el: array pf LWS_GENCRYPTO_EC_KEYEL_COUNT key elems to take the new key + * + * Creates a genecdh with a newly minted EC public / private key + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side, + const char *curve_name, struct lws_gencrypto_keyelem *el); + +LWS_VISIBLE LWS_EXTERN int +lws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss, + int *ss_len); + + +/* ECDSA-specific apis */ + +/** lws_genecdsa_create() - Create a genecdsa and + * + * \param ctx: your genec context + * \param context: your lws_context (for RNG access) + * \param curve_table: NULL, enabling P-256, P-384 and P-521, or a replacement + * struct lws_ec_curves array, terminated by an entry with + * .name = NULL, of curves you want to allow + * + * Initializes a genecdh + */ +LWS_VISIBLE int +lws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context, + const struct lws_ec_curves *curve_table); + +/** lws_genecdsa_new_keypair() - Create a genecdsa with a new public / private key + * + * \param ctx: your genec context + * \param curve_name: an EC curve name, like "P-256" + * \param el: array pf LWS_GENCRYPTO_EC_KEYEL_COUNT key elements to take the new key + * + * Creates a genecdsa with a newly minted EC public / private key + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name, + struct lws_gencrypto_keyelem *el); + +/** lws_genecdsa_set_key() - Apply an EC key to an ecdsa context + * + * \param ctx: your genecdsa context + * \param el: your key elements + * + * Applies an EC key to an ecdsa context + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdsa_set_key(struct lws_genec_ctx *ctx, + const struct lws_gencrypto_keyelem *el); + +/** lws_genecdsa_hash_sig_verify_jws() - Verifies a JWS ECDSA signature on a given hash + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: unencrypted payload (usually a recomputed hash) + * \param hash_type: one of LWS_GENHASH_TYPE_ + * \param keybits: number of bits in the crypto key + * \param sig: pointer to the signature we received with the payload + * \param sig_len: length of the signature we are checking in bytes + * + * This just looks at the signed hash... that's why there's no input length + * parameter, it's decided by the choice of hash. It's up to you to confirm + * separately the actual payload matches the hash that was confirmed by this to + * be validly signed. + * + * Returns <0 for error, or 0 if signature matches the hash + key.. + * + * The JWS ECDSA signature verification algorithm differs to generic ECDSA + * signatures and they're not interoperable. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, + enum lws_genhash_types hash_type, int keybits, + const uint8_t *sig, size_t sig_len); + +/** lws_genecdsa_hash_sign_jws() - Creates a JWS ECDSA signature for a hash you provide + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: precomputed hash + * \param hash_type: one of LWS_GENHASH_TYPE_ + * \param keybits: number of bits in the crypto key + * \param sig: pointer to buffer to take signature + * \param sig_len: length of the buffer (must be >= length of key N) + * + * Returns <0 for error, or 0 for success. + * + * This creates a JWS ECDSA signature for a hash you already computed and provide. + * + * The JWS ECDSA signature generation algorithm differs to generic ECDSA + * signatures and they're not interoperable. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in, + enum lws_genhash_types hash_type, int keybits, + uint8_t *sig, size_t sig_len); + + +/* Apis that apply to both ECDH and ECDSA */ + +LWS_VISIBLE LWS_EXTERN void +lws_genec_destroy(struct lws_genec_ctx *ctx); + +LWS_VISIBLE LWS_EXTERN void +lws_genec_destroy_elements(struct lws_gencrypto_keyelem *el); + +LWS_VISIBLE LWS_EXTERN int +lws_genec_dump(struct lws_gencrypto_keyelem *el); diff --git a/thirdparty/include/libwebsockets/lws-genhash.h b/thirdparty/include/libwebsockets/lws-genhash.h new file mode 100755 index 0000000000000000000000000000000000000000..8407d2f03a2a0083ddb3f996bf0921cd67a9b3b7 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-genhash.h @@ -0,0 +1,187 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup generichash Generic Hash + * ## Generic Hash related functions + * + * Lws provides generic hash / digest accessors that abstract the ones + * provided by whatever tls library you are linking against. + * + * It lets you use the same code if you build against mbedtls or OpenSSL + * for example. + */ +///@{ + +enum lws_genhash_types { + LWS_GENHASH_TYPE_UNKNOWN, + LWS_GENHASH_TYPE_MD5, + LWS_GENHASH_TYPE_SHA1, + LWS_GENHASH_TYPE_SHA256, + LWS_GENHASH_TYPE_SHA384, + LWS_GENHASH_TYPE_SHA512, +}; + +enum lws_genhmac_types { + LWS_GENHMAC_TYPE_UNKNOWN, + LWS_GENHMAC_TYPE_SHA256, + LWS_GENHMAC_TYPE_SHA384, + LWS_GENHMAC_TYPE_SHA512, +}; + +#define LWS_GENHASH_LARGEST 64 + +struct lws_genhash_ctx { + uint8_t type; +#if defined(LWS_WITH_MBEDTLS) + union { + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + mbedtls_sha256_context sha256; + mbedtls_sha512_context sha512; /* 384 also uses this */ + const mbedtls_md_info_t *hmac; + } u; +#else + const EVP_MD *evp_type; + EVP_MD_CTX *mdctx; +#endif +}; + +struct lws_genhmac_ctx { + uint8_t type; +#if defined(LWS_WITH_MBEDTLS) + const mbedtls_md_info_t *hmac; + mbedtls_md_context_t ctx; +#else + const EVP_MD *evp_type; + +#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) + EVP_MD_CTX *ctx; + EVP_PKEY *key; +#else +#if defined(LWS_HAVE_HMAC_CTX_new) + HMAC_CTX *ctx; +#else + HMAC_CTX ctx; +#endif +#endif + +#endif +}; + +/** lws_genhash_size() - get hash size in bytes + * + * \param type: one of LWS_GENHASH_TYPE_... + * + * Returns number of bytes in this type of hash + */ +LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT +lws_genhash_size(enum lws_genhash_types type); + +/** lws_genhmac_size() - get hash size in bytes + * + * \param type: one of LWS_GENHASH_TYPE_... + * + * Returns number of bytes in this type of hmac + */ +LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT +lws_genhmac_size(enum lws_genhmac_types type); + +/** lws_genhash_init() - prepare your struct lws_genhash_ctx for use + * + * \param ctx: your struct lws_genhash_ctx + * \param type: one of LWS_GENHASH_TYPE_... + * + * Initializes the hash context for the type you requested + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type); + +/** lws_genhash_update() - digest len bytes of the buffer starting at in + * + * \param ctx: your struct lws_genhash_ctx + * \param in: start of the bytes to digest + * \param len: count of bytes to digest + * + * Updates the state of your hash context to reflect digesting len bytes from in + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len); + +/** lws_genhash_destroy() - copy out the result digest and destroy the ctx + * + * \param ctx: your struct lws_genhash_ctx + * \param result: NULL, or where to copy the result hash + * + * Finalizes the hash and copies out the digest. Destroys any allocations such + * that ctx can safely go out of scope after calling this. + * + * NULL result is supported so that you can destroy the ctx cleanly on error + * conditions, where there is no valid result. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result); + +/** lws_genhmac_init() - prepare your struct lws_genhmac_ctx for use + * + * \param ctx: your struct lws_genhmac_ctx + * \param type: one of LWS_GENHMAC_TYPE_... + * \param key: pointer to the start of the HMAC key + * \param key_len: length of the HMAC key + * + * Initializes the hash context for the type you requested + * + * If the return is nonzero, it failed and there is nothing needing to be + * destroyed. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, + const uint8_t *key, size_t key_len); + +/** lws_genhmac_update() - digest len bytes of the buffer starting at in + * + * \param ctx: your struct lws_genhmac_ctx + * \param in: start of the bytes to digest + * \param len: count of bytes to digest + * + * Updates the state of your hash context to reflect digesting len bytes from in + * + * If the return is nonzero, it failed and needs destroying. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len); + +/** lws_genhmac_destroy() - copy out the result digest and destroy the ctx + * + * \param ctx: your struct lws_genhmac_ctx + * \param result: NULL, or where to copy the result hash + * + * Finalizes the hash and copies out the digest. Destroys any allocations such + * that ctx can safely go out of scope after calling this. + * + * NULL result is supported so that you can destroy the ctx cleanly on error + * conditions, where there is no valid result. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result); +///@} diff --git a/thirdparty/include/libwebsockets/lws-genrsa.h b/thirdparty/include/libwebsockets/lws-genrsa.h new file mode 100755 index 0000000000000000000000000000000000000000..c9409463f652065968ef57c53acfb18c1759f471 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-genrsa.h @@ -0,0 +1,255 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup genericRSA Generic RSA + * ## Generic RSA related functions + * + * Lws provides generic RSA functions that abstract the ones + * provided by whatever OpenSSL library you are linking against. + * + * It lets you use the same code if you build against mbedtls or OpenSSL + * for example. + */ +///@{ + +/* include/libwebsockets/lws-jwk.h must be included before this */ + +enum enum_genrsa_mode { + LGRSAM_PKCS1_1_5, + LGRSAM_PKCS1_OAEP_PSS, + + LGRSAM_COUNT +}; + +struct lws_genrsa_ctx { +#if defined(LWS_WITH_MBEDTLS) + mbedtls_rsa_context *ctx; +#else + BIGNUM *bn[LWS_GENCRYPTO_RSA_KEYEL_COUNT]; + EVP_PKEY_CTX *ctx; + RSA *rsa; +#endif + struct lws_context *context; + enum enum_genrsa_mode mode; +}; + +/** lws_genrsa_public_decrypt_create() - Create RSA public decrypt context + * + * \param ctx: your struct lws_genrsa_ctx + * \param el: struct prepared with key element data + * \param context: lws_context for RNG + * \param mode: RSA mode, one of LGRSAM_ constants + * \param oaep_hashid: the lws genhash id for the hash used in MFG1 hash + * used in OAEP mode - normally, SHA1 + * + * Creates an RSA context with a public key associated with it, formed from + * the key elements in \p el. + * + * Mode LGRSAM_PKCS1_1_5 is in widespread use but has weaknesses. It's + * recommended to use LGRSAM_PKCS1_OAEP_PSS for new implementations. + * + * Returns 0 for OK or nonzero for error. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_create(struct lws_genrsa_ctx *ctx, + const struct lws_gencrypto_keyelem *el, + struct lws_context *context, enum enum_genrsa_mode mode, + enum lws_genhash_types oaep_hashid); + +/** lws_genrsa_destroy_elements() - Free allocations in genrsa_elements + * + * \param el: your struct lws_gencrypto_keyelem + * + * This is a helper for user code making use of struct lws_gencrypto_keyelem + * where the elements are allocated on the heap, it frees any non-NULL + * buf element and sets the buf to NULL. + * + * NB: lws_genrsa_public_... apis do not need this as they take care of the key + * creation and destruction themselves. + */ +LWS_VISIBLE LWS_EXTERN void +lws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el); + +/** lws_genrsa_new_keypair() - Create new RSA keypair + * + * \param context: your struct lws_context (may be used for RNG) + * \param ctx: your struct lws_genrsa_ctx + * \param mode: RSA mode, one of LGRSAM_ constants + * \param el: struct to get the new key element data allocated into it + * \param bits: key size, eg, 4096 + * + * Creates a new RSA context and generates a new keypair into it, with \p bits + * bits. + * + * Returns 0 for OK or nonzero for error. + * + * Mode LGRSAM_PKCS1_1_5 is in widespread use but has weaknesses. It's + * recommended to use LGRSAM_PKCS1_OAEP_PSS for new implementations. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx, + enum enum_genrsa_mode mode, struct lws_gencrypto_keyelem *el, + int bits); + +/** lws_genrsa_public_encrypt() - Perform RSA public key encryption + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: plaintext input + * \param in_len: length of plaintext input + * \param out: encrypted output + * + * Performs PKCS1 v1.5 Encryption + * + * Returns <0 for error, or length of decrypted data. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out); + +/** lws_genrsa_private_encrypt() - Perform RSA private key encryption + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: plaintext input + * \param in_len: length of plaintext input + * \param out: encrypted output + * + * Performs PKCS1 v1.5 Encryption + * + * Returns <0 for error, or length of decrypted data. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out); + +/** lws_genrsa_public_decrypt() - Perform RSA public key decryption + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: encrypted input + * \param in_len: length of encrypted input + * \param out: decrypted output + * \param out_max: size of output buffer + * + * Performs PKCS1 v1.5 Decryption + * + * Returns <0 for error, or length of decrypted data. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_max); + +/** lws_genrsa_private_decrypt() - Perform RSA private key decryption + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: encrypted input + * \param in_len: length of encrypted input + * \param out: decrypted output + * \param out_max: size of output buffer + * + * Performs PKCS1 v1.5 Decryption + * + * Returns <0 for error, or length of decrypted data. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_max); + +/** lws_genrsa_hash_sig_verify() - Verifies RSA signature on a given hash + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: input to be hashed + * \param hash_type: one of LWS_GENHASH_TYPE_ + * \param sig: pointer to the signature we received with the payload + * \param sig_len: length of the signature we are checking in bytes + * + * Returns <0 for error, or 0 if signature matches the payload + key. + * + * This just looks at a hash... that's why there's no input length + * parameter, it's decided by the choice of hash. It's up to you to confirm + * separately the actual payload matches the hash that was confirmed by this to + * be validly signed. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, + enum lws_genhash_types hash_type, + const uint8_t *sig, size_t sig_len); + +/** lws_genrsa_hash_sign() - Creates an ECDSA signature for a hash you provide + * + * \param ctx: your struct lws_genrsa_ctx + * \param in: input to be hashed and signed + * \param hash_type: one of LWS_GENHASH_TYPE_ + * \param sig: pointer to buffer to take signature + * \param sig_len: length of the buffer (must be >= length of key N) + * + * Returns <0 for error, or 0 for success. + * + * This creates an RSA signature for a hash you already computed and provide. + * You should have created the hash before calling this by iterating over the + * actual payload you need to confirm. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in, + enum lws_genhash_types hash_type, + uint8_t *sig, size_t sig_len); + +/** lws_genrsa_public_decrypt_destroy() - Destroy RSA public decrypt context + * + * \param ctx: your struct lws_genrsa_ctx + * + * Destroys any allocations related to \p ctx. + * + * This and related APIs operate identically with OpenSSL or mbedTLS backends. + */ +LWS_VISIBLE LWS_EXTERN void +lws_genrsa_destroy(struct lws_genrsa_ctx *ctx); + +/** lws_genrsa_render_pkey_asn1() - Exports public or private key to ASN1/DER + * + * \param ctx: your struct lws_genrsa_ctx + * \param _private: 0 = public part only, 1 = all parts of the key + * \param pkey_asn1: pointer to buffer to take the ASN1 + * \param pkey_asn1_len: max size of the pkey_asn1_len + * + * Returns length of pkey_asn1 written, or -1 for error. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private, + uint8_t *pkey_asn1, size_t pkey_asn1_len); +///@} diff --git a/thirdparty/include/libwebsockets/lws-gpio.h b/thirdparty/include/libwebsockets/lws-gpio.h new file mode 100755 index 0000000000000000000000000000000000000000..f86620ad1cd52f16fd1624f00fe7a2773e95b062 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-gpio.h @@ -0,0 +1,60 @@ +/* + * Generic GPIO ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#if !defined(__LWS_GPIO_H__) +#define __LWS_GPIO_H__ + +typedef int _lws_plat_gpio_t; + +typedef enum { + LWSGGPIO_IRQ_NONE, + LWSGGPIO_IRQ_RISING, + LWSGGPIO_IRQ_FALLING, + LWSGGPIO_IRQ_CHANGE, + LWSGGPIO_IRQ_LOW, + LWSGGPIO_IRQ_HIGH +} lws_gpio_irq_t; + +enum { + LWSGGPIO_FL_READ = (1 << 0), + LWSGGPIO_FL_WRITE = (1 << 1), + LWSGGPIO_FL_PULLUP = (1 << 2), + LWSGGPIO_FL_PULLDOWN = (1 << 3), + LWSGGPIO_FL_START_LOW = (1 << 4), +}; + +typedef void (*lws_gpio_irq_cb_t)(void *arg); + +typedef struct lws_gpio_ops { + void (*mode)(_lws_plat_gpio_t gpio, int flags); + int (*read)(_lws_plat_gpio_t gpio); + void (*set)(_lws_plat_gpio_t gpio, int val); + int (*irq_mode)(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq, + lws_gpio_irq_cb_t cb, void *arg); +} lws_gpio_ops_t; + +#endif diff --git a/thirdparty/include/libwebsockets/lws-http.h b/thirdparty/include/libwebsockets/lws-http.h new file mode 100755 index 0000000000000000000000000000000000000000..9d6090322175446b5247b526ef2c6228a29fdec5 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-http.h @@ -0,0 +1,1030 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/* minimal space for typical headers and CSP stuff */ + +#define LWS_RECOMMENDED_MIN_HEADER_SPACE 2048 + +/*! \defgroup http HTTP + + Modules related to handling HTTP +*/ +//@{ + +/*! \defgroup httpft HTTP File transfer + * \ingroup http + + APIs for sending local files in response to HTTP requests +*/ +//@{ + +/** + * lws_get_mimetype() - Determine mimetype to use from filename + * + * \param file: filename + * \param m: NULL, or mount context + * + * This uses a canned list of known filetypes first, if no match and m is + * non-NULL, then tries a list of per-mount file suffix to mimtype mappings. + * + * Returns either NULL or a pointer to the mimetype matching the file. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_get_mimetype(const char *file, const struct lws_http_mount *m); + +/** + * lws_serve_http_file() - Send a file back to the client using http + * \param wsi: Websocket instance (available from user callback) + * \param file: The file to issue over http + * \param content_type: The http content type, eg, text/html + * \param other_headers: NULL or pointer to header string + * \param other_headers_len: length of the other headers if non-NULL + * + * This function is intended to be called from the callback in response + * to http requests from the client. It allows the callback to issue + * local files down the http link in a single step. + * + * Returning <0 indicates error and the wsi should be closed. Returning + * >0 indicates the file was completely sent and + * lws_http_transaction_completed() called on the wsi (and close if != 0) + * ==0 indicates the file transfer is started and needs more service later, + * the wsi should be left alone. + */ +LWS_VISIBLE LWS_EXTERN int +lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, + const char *other_headers, int other_headers_len); + +LWS_VISIBLE LWS_EXTERN int +lws_serve_http_file_fragment(struct lws *wsi); +//@} + + +enum http_status { + HTTP_STATUS_CONTINUE = 100, + + HTTP_STATUS_OK = 200, + HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_PARTIAL_CONTENT = 206, + + HTTP_STATUS_MOVED_PERMANENTLY = 301, + HTTP_STATUS_FOUND = 302, + HTTP_STATUS_SEE_OTHER = 303, + HTTP_STATUS_NOT_MODIFIED = 304, + + HTTP_STATUS_BAD_REQUEST = 400, + HTTP_STATUS_UNAUTHORIZED, + HTTP_STATUS_PAYMENT_REQUIRED, + HTTP_STATUS_FORBIDDEN, + HTTP_STATUS_NOT_FOUND, + HTTP_STATUS_METHOD_NOT_ALLOWED, + HTTP_STATUS_NOT_ACCEPTABLE, + HTTP_STATUS_PROXY_AUTH_REQUIRED, + HTTP_STATUS_REQUEST_TIMEOUT, + HTTP_STATUS_CONFLICT, + HTTP_STATUS_GONE, + HTTP_STATUS_LENGTH_REQUIRED, + HTTP_STATUS_PRECONDITION_FAILED, + HTTP_STATUS_REQ_ENTITY_TOO_LARGE, + HTTP_STATUS_REQ_URI_TOO_LONG, + HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, + HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, + HTTP_STATUS_EXPECTATION_FAILED, + + HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, + HTTP_STATUS_NOT_IMPLEMENTED, + HTTP_STATUS_BAD_GATEWAY, + HTTP_STATUS_SERVICE_UNAVAILABLE, + HTTP_STATUS_GATEWAY_TIMEOUT, + HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED, +}; +/*! \defgroup html-chunked-substitution HTML Chunked Substitution + * \ingroup http + * + * ##HTML chunked Substitution + * + * APIs for receiving chunks of text, replacing a set of variable names via + * a callback, and then prepending and appending HTML chunked encoding + * headers. + */ +//@{ + +struct lws_process_html_args { + char *p; /**< pointer to the buffer containing the data */ + int len; /**< length of the original data at p */ + int max_len; /**< maximum length we can grow the data to */ + int final; /**< set if this is the last chunk of the file */ + int chunked; /**< 0 == unchunked, 1 == produce chunk headers + (incompatible with HTTP/2) */ +}; + +typedef const char *(*lws_process_html_state_cb)(void *data, int index); + +struct lws_process_html_state { + char *start; /**< pointer to start of match */ + char swallow[16]; /**< matched character buffer */ + int pos; /**< position in match */ + void *data; /**< opaque pointer */ + const char * const *vars; /**< list of variable names */ + int count_vars; /**< count of variable names */ + + lws_process_html_state_cb replace; + /**< called on match to perform substitution */ +}; + +/*! lws_chunked_html_process() - generic chunked substitution + * \param args: buffer to process using chunked encoding + * \param s: current processing state + */ +LWS_VISIBLE LWS_EXTERN int +lws_chunked_html_process(struct lws_process_html_args *args, + struct lws_process_html_state *s); +//@} + +/** \defgroup HTTP-headers-read HTTP headers: read + * \ingroup http + * + * ##HTTP header releated functions + * + * In lws the client http headers are temporarily stored in a pool, only for the + * duration of the http part of the handshake. It's because in most cases, + * the header content is ignored for the whole rest of the connection lifetime + * and would then just be taking up space needlessly. + * + * During LWS_CALLBACK_HTTP when the URI path is delivered is the last time + * the http headers are still allocated, you can use these apis then to + * look at and copy out interesting header content (cookies, etc) + * + * Notice that the header total length reported does not include a terminating + * '\0', however you must allocate for it when using the _copy apis. So the + * length reported for a header containing "123" is 3, but you must provide + * a buffer of length 4 so that "123\0" may be copied into it, or the copy + * will fail with a nonzero return code. + * + * In the special case of URL arguments, like ?x=1&y=2, the arguments are + * stored in a token named for the method, eg, WSI_TOKEN_GET_URI if it + * was a GET or WSI_TOKEN_POST_URI if POST. You can check the total + * length to confirm the method. + * + * For URL arguments, each argument is stored urldecoded in a "fragment", so + * you can use the fragment-aware api lws_hdr_copy_fragment() to access each + * argument in turn: the fragments contain urldecoded strings like x=1 or y=2. + * + * As a convenience, lws has an api that will find the fragment with a + * given name= part, lws_get_urlarg_by_name(). + */ +///@{ + +/** struct lws_tokens + * you need these to look at headers that have been parsed if using the + * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum + * list below is absent, .token = NULL and len = 0. Otherwise .token + * points to .len chars containing that header content. + */ +struct lws_tokens { + unsigned char *token; /**< pointer to start of the token */ + int len; /**< length of the token's value */ +}; + +/* enum lws_token_indexes + * these have to be kept in sync with lextable.h / minilex.c + * + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +enum lws_token_indexes { + WSI_TOKEN_GET_URI, /* 0 */ + WSI_TOKEN_POST_URI, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_OPTIONS_URI, +#endif + WSI_TOKEN_HOST, + WSI_TOKEN_CONNECTION, + WSI_TOKEN_UPGRADE, /* 5 */ + WSI_TOKEN_ORIGIN, +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_DRAFT, +#endif + WSI_TOKEN_CHALLENGE, +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_EXTENSIONS, + WSI_TOKEN_KEY1, /* 10 */ + WSI_TOKEN_KEY2, + WSI_TOKEN_PROTOCOL, + WSI_TOKEN_ACCEPT, + WSI_TOKEN_NONCE, +#endif + WSI_TOKEN_HTTP, +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP2_SETTINGS, /* 16 */ +#endif + WSI_TOKEN_HTTP_ACCEPT, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_AC_REQUEST_HEADERS, +#endif + WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, + WSI_TOKEN_HTTP_IF_NONE_MATCH, /* 20 */ + WSI_TOKEN_HTTP_ACCEPT_ENCODING, + WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, + WSI_TOKEN_HTTP_PRAGMA, + WSI_TOKEN_HTTP_CACHE_CONTROL, + WSI_TOKEN_HTTP_AUTHORIZATION, + WSI_TOKEN_HTTP_COOKIE, + WSI_TOKEN_HTTP_CONTENT_LENGTH, /* 27 */ + WSI_TOKEN_HTTP_CONTENT_TYPE, + WSI_TOKEN_HTTP_DATE, + WSI_TOKEN_HTTP_RANGE, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_REFERER, +#endif +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_KEY, + WSI_TOKEN_VERSION, + WSI_TOKEN_SWORIGIN, +#endif +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_COLON_AUTHORITY, + WSI_TOKEN_HTTP_COLON_METHOD, + WSI_TOKEN_HTTP_COLON_PATH, + WSI_TOKEN_HTTP_COLON_SCHEME, + WSI_TOKEN_HTTP_COLON_STATUS, +#endif + +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_ACCEPT_CHARSET, +#endif + WSI_TOKEN_HTTP_ACCEPT_RANGES, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN, +#endif + WSI_TOKEN_HTTP_AGE, + WSI_TOKEN_HTTP_ALLOW, + WSI_TOKEN_HTTP_CONTENT_DISPOSITION, + WSI_TOKEN_HTTP_CONTENT_ENCODING, + WSI_TOKEN_HTTP_CONTENT_LANGUAGE, + WSI_TOKEN_HTTP_CONTENT_LOCATION, + WSI_TOKEN_HTTP_CONTENT_RANGE, + WSI_TOKEN_HTTP_ETAG, + WSI_TOKEN_HTTP_EXPECT, + WSI_TOKEN_HTTP_EXPIRES, + WSI_TOKEN_HTTP_FROM, + WSI_TOKEN_HTTP_IF_MATCH, + WSI_TOKEN_HTTP_IF_RANGE, + WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE, + WSI_TOKEN_HTTP_LAST_MODIFIED, + WSI_TOKEN_HTTP_LINK, + WSI_TOKEN_HTTP_LOCATION, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_MAX_FORWARDS, + WSI_TOKEN_HTTP_PROXY_AUTHENTICATE, + WSI_TOKEN_HTTP_PROXY_AUTHORIZATION, +#endif + WSI_TOKEN_HTTP_REFRESH, + WSI_TOKEN_HTTP_RETRY_AFTER, + WSI_TOKEN_HTTP_SERVER, + WSI_TOKEN_HTTP_SET_COOKIE, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY, +#endif + WSI_TOKEN_HTTP_TRANSFER_ENCODING, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_HTTP_USER_AGENT, + WSI_TOKEN_HTTP_VARY, + WSI_TOKEN_HTTP_VIA, + WSI_TOKEN_HTTP_WWW_AUTHENTICATE, +#endif +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_PATCH_URI, + WSI_TOKEN_PUT_URI, + WSI_TOKEN_DELETE_URI, +#endif + + WSI_TOKEN_HTTP_URI_ARGS, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_PROXY, + WSI_TOKEN_HTTP_X_REAL_IP, +#endif + WSI_TOKEN_HTTP1_0, + WSI_TOKEN_X_FORWARDED_FOR, + WSI_TOKEN_CONNECT, + WSI_TOKEN_HEAD_URI, +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_TE, + WSI_TOKEN_REPLAY_NONCE, /* ACME */ +#endif +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_COLON_PROTOCOL, +#endif + WSI_TOKEN_X_AUTH_TOKEN, + WSI_TOKEN_DSS_SIGNATURE, + + /****** add new things just above ---^ ******/ + + /* use token storage to stash these internally, not for + * user use */ + + _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, + _WSI_TOKEN_CLIENT_PEER_ADDRESS, + _WSI_TOKEN_CLIENT_URI, + _WSI_TOKEN_CLIENT_HOST, + _WSI_TOKEN_CLIENT_ORIGIN, + _WSI_TOKEN_CLIENT_METHOD, + _WSI_TOKEN_CLIENT_IFACE, + _WSI_TOKEN_CLIENT_ALPN, + + /* always last real token index*/ + WSI_TOKEN_COUNT, + + /* parser state additions, no storage associated */ + WSI_TOKEN_NAME_PART, +#if defined(LWS_WITH_CUSTOM_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + WSI_TOKEN_UNKNOWN_VALUE_PART, +#endif + WSI_TOKEN_SKIPPING, + WSI_TOKEN_SKIPPING_SAW_CR, + WSI_PARSING_COMPLETE, + WSI_INIT_TOKEN_MUXURL, +}; + +struct lws_token_limits { + unsigned short token_limit[WSI_TOKEN_COUNT]; /**< max chars for this token */ +}; + +enum lws_h2_settings { + H2SET_HEADER_TABLE_SIZE = 1, + H2SET_ENABLE_PUSH, + H2SET_MAX_CONCURRENT_STREAMS, + H2SET_INITIAL_WINDOW_SIZE, + H2SET_MAX_FRAME_SIZE, + H2SET_MAX_HEADER_LIST_SIZE, + H2SET_RESERVED7, + H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */ + + H2SET_COUNT /* always last */ +}; + +/** + * lws_token_to_string() - returns a textual representation of a hdr token index + * + * \param token: token index + */ +LWS_VISIBLE LWS_EXTERN const unsigned char * +lws_token_to_string(enum lws_token_indexes token); + +/** + * lws_hdr_total_length: report length of all fragments of a header totalled up + * The returned length does not include the space for a + * terminating '\0' + * + * \param wsi: websocket connection + * \param h: which header index we are interested in + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h); + +/** + * lws_hdr_fragment_length: report length of a single fragment of a header + * The returned length does not include the space for a + * terminating '\0' + * + * \param wsi: websocket connection + * \param h: which header index we are interested in + * \param frag_idx: which fragment of h we want to get the length of + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, + int frag_idx); + +/** + * lws_hdr_copy() - copy all fragments of the given header to a buffer + * The buffer length len must include space for an additional + * terminating '\0', or it will fail returning -1. + * + * \param wsi: websocket connection + * \param dest: destination buffer + * \param len: length of destination buffer + * \param h: which header index we are interested in + * + * copies the whole, aggregated header, even if it was delivered in + * several actual headers piece by piece. Returns -1 or length of the whole + * header. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_copy(struct lws *wsi, char *dest, int len, enum lws_token_indexes h); + +/** + * lws_hdr_copy_fragment() - copy a single fragment of the given header to a buffer + * The buffer length len must include space for an additional + * terminating '\0', or it will fail returning -1. + * If the requested fragment index is not present, it fails + * returning -1. + * + * \param wsi: websocket connection + * \param dest: destination buffer + * \param len: length of destination buffer + * \param h: which header index we are interested in + * \param frag_idx: which fragment of h we want to copy + * + * Normally this is only useful + * to parse URI arguments like ?x=1&y=2, token index WSI_TOKEN_HTTP_URI_ARGS + * fragment 0 will contain "x=1" and fragment 1 "y=2" + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_copy_fragment(struct lws *wsi, char *dest, int len, + enum lws_token_indexes h, int frag_idx); + +/** + * lws_hdr_custom_length() - return length of a custom header + * + * \param wsi: websocket connection + * \param name: header string (including terminating :) + * \param nlen: length of name + * + * Lws knows about 100 common http headers, and parses them into indexes when + * it recognizes them. When it meets a header that it doesn't know, it stores + * the name and value directly, and you can look them up using + * lws_hdr_custom_length() and lws_hdr_custom_copy(). + * + * This api returns -1, or the length of the value part of the header if it + * exists. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to + * use this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_custom_length(struct lws *wsi, const char *name, int nlen); + +/** + * lws_hdr_custom_copy() - copy value part of a custom header + * + * \param wsi: websocket connection + * \param dst: pointer to buffer to receive the copy + * \param len: number of bytes available at dst + * \param name: header string (including terminating :) + * \param nlen: length of name + * + * Lws knows about 100 common http headers, and parses them into indexes when + * it recognizes them. When it meets a header that it doesn't know, it stores + * the name and value directly, and you can look them up using + * lws_hdr_custom_length() and lws_hdr_custom_copy(). + * + * This api returns -1, or the length of the string it copied into dst if it + * was big enough to contain both the string and an extra terminating NUL. Lws + * must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to use this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, + int nlen); + +typedef void (*lws_hdr_custom_fe_cb_t)(const char *name, int nlen, void *opaque); +/** + * lws_hdr_custom_name_foreach() - Iterate the custom header names + * + * \param wsi: websocket connection + * \param cb: callback for each custom header name + * \param opaque: ignored by lws except to pass to callback + * + * Lws knows about 100 common http headers, and parses them into indexes when + * it recognizes them. When it meets a header that it doesn't know, it stores + * the name and value directly, and you can look them up using + * lws_hdr_custom_length() and lws_hdr_custom_copy(). + * + * This api returns -1 on error else 0. Use lws_hdr_custom_copy() to get the + * values of headers. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by + * default) to use this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, void *opaque); + +/** + * lws_get_urlarg_by_name_safe() - get copy and return length of y for x=y urlargs + * + * \param wsi: the connection to check + * \param name: the arg name, like "token" or "token=" + * \param buf: the buffer to receive the urlarg (including the name= part) + * \param len: the length of the buffer to receive the urlarg + * + * Returns -1 if not present, else the length of y in the urlarg name=y. If + * zero or greater, then buf contains a copy of the string y. Any = after the + * name match is trimmed off if the name does not end with = itself. + * + * This returns the explicit length and so can deal with binary blobs that are + * percent-encoded. It also makes sure buf has a NUL just after the valid + * length so it can work with NUL-based apis if you don't care about truncation. + * + * buf may have been written even when -1 is returned indicating no match. + * + * Use this in place of lws_get_urlarg_by_name() that does not return an + * explicit length. + * + * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. + */ +LWS_VISIBLE LWS_EXTERN int +lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len); + +/** + * lws_get_urlarg_by_name() - return pointer to arg value if present + * + * \param wsi: the connection to check + * \param name: the arg name, like "token=" + * \param buf: the buffer to receive the urlarg (including the name= part) + * \param len: the length of the buffer to receive the urlarg + * + * Returns NULL if not found or a pointer inside buf to just after the + * name= part. + * + * This assumed the argument can be represented with a NUL-terminated string. + * It can't correctly deal with binary values encoded with %XX, eg. %00 will + * be understood to terminate the string. + * + * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len) +/* LWS_WARN_DEPRECATED */; +///@} + +/*! \defgroup HTTP-headers-create HTTP headers: create + * + * ## HTTP headers: Create + * + * These apis allow you to create HTTP response headers in a way compatible with + * both HTTP/1.x and HTTP/2. + * + * They each append to a buffer taking care about the buffer end, which is + * passed in as a pointer. When data is written to the buffer, the current + * position p is updated accordingly. + * + * All of these apis are LWS_WARN_UNUSED_RESULT as they can run out of space + * and fail with nonzero return. + */ +///@{ + +#define LWSAHH_CODE_MASK ((1 << 16) - 1) +#define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30) + +/** + * lws_add_http_header_status() - add the HTTP response status code + * + * \param wsi: the connection to check + * \param code: an HTTP code like 200, 404 etc (see enum http_status) + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Adds the initial response code, so should be called first. + * + * Code may additionally take OR'd flags: + * + * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_add_http_header_status(struct lws *wsi, + unsigned int code, unsigned char **p, + unsigned char *end); +/** + * lws_add_http_header_by_name() - append named header and value + * + * \param wsi: the connection to check + * \param name: the hdr name, like "my-header:" + * \param value: the value after the = for this header + * \param length: the length of the value + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Appends name: value to the headers + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, + const unsigned char *value, int length, + unsigned char **p, unsigned char *end); +/** + * lws_add_http_header_by_token() - append given header and value + * + * \param wsi: the connection to check + * \param token: the token index for the hdr + * \param value: the value after the = for this header + * \param length: the length of the value + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Appends name=value to the headers, but is able to take advantage of better + * HTTP/2 coding mechanisms where possible. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token, + const unsigned char *value, int length, + unsigned char **p, unsigned char *end); +/** + * lws_add_http_header_content_length() - append content-length helper + * + * \param wsi: the connection to check + * \param content_length: the content length to use + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Appends content-length: content_length to the headers + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_add_http_header_content_length(struct lws *wsi, + lws_filepos_t content_length, + unsigned char **p, unsigned char *end); +/** + * lws_finalize_http_header() - terminate header block + * + * \param wsi: the connection to check + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Indicates no more headers will be added + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_finalize_http_header(struct lws *wsi, unsigned char **p, + unsigned char *end); + +/** + * lws_finalize_write_http_header() - Helper finializing and writing http headers + * + * \param wsi: the connection to check + * \param start: pointer to the start of headers in the buffer, eg &buf[LWS_PRE] + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Terminates the headers correctly accoring to the protocol in use (h1 / h2) + * and writes the headers. Returns nonzero for error. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_finalize_write_http_header(struct lws *wsi, unsigned char *start, + unsigned char **p, unsigned char *end); + +#define LWS_ILLEGAL_HTTP_CONTENT_LEN ((lws_filepos_t)-1ll) + +/** + * lws_add_http_common_headers() - Helper preparing common http headers + * + * \param wsi: the connection to check + * \param code: an HTTP code like 200, 404 etc (see enum http_status) + * \param content_type: the content type, like "text/html" + * \param content_len: the content length, in bytes + * \param p: pointer to current position in buffer pointer + * \param end: pointer to end of buffer + * + * Adds the initial response code, so should be called first. + * + * Code may additionally take OR'd flags: + * + * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time + * + * This helper just calls public apis to simplify adding headers that are + * commonly needed. If it doesn't fit your case, or you want to add additional + * headers just call the public apis directly yourself for what you want. + * + * You can miss out the content length header by providing the constant + * LWS_ILLEGAL_HTTP_CONTENT_LEN for the content_len. + * + * It does not call lws_finalize_http_header(), to allow you to add further + * headers after calling this. You will need to call that yourself at the end. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_add_http_common_headers(struct lws *wsi, unsigned int code, + const char *content_type, lws_filepos_t content_len, + unsigned char **p, unsigned char *end); + +enum { + LWSHUMETH_GET, + LWSHUMETH_POST, + LWSHUMETH_OPTIONS, + LWSHUMETH_PUT, + LWSHUMETH_PATCH, + LWSHUMETH_DELETE, + LWSHUMETH_CONNECT, + LWSHUMETH_HEAD, + LWSHUMETH_COLON_PATH, +}; + +/** + * lws_http_get_uri_and_method() - Get information on method and url + * + * \param wsi: the connection to get information on + * \param puri_ptr: points to pointer to set to url + * \param puri_len: points to int to set to uri length + * + * Returns -1 or method index as one of the LWSHUMETH_ constants + * + * If returns method, *puri_ptr is set to the method's URI string and *puri_len + * to its length + */ + +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len); + +///@} + +/*! \defgroup urlendec Urlencode and Urldecode + * \ingroup http + * + * ##HTML chunked Substitution + * + * APIs for receiving chunks of text, replacing a set of variable names via + * a callback, and then prepending and appending HTML chunked encoding + * headers. + */ +//@{ + +/** + * lws_urlencode() - like strncpy but with urlencoding + * + * \param escaped: output buffer + * \param string: input buffer ('/0' terminated) + * \param len: output buffer max length + * + * Because urlencoding expands the output string, it's not + * possible to do it in-place, ie, with escaped == string + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_urlencode(char *escaped, const char *string, int len); + +/* + * URLDECODE 1 / 2 + * + * This simple urldecode only operates until the first '\0' and requires the + * data to exist all at once + */ +/** + * lws_urldecode() - like strncpy but with urldecoding + * + * \param string: output buffer + * \param escaped: input buffer ('\0' terminated) + * \param len: output buffer max length + * + * This is only useful for '\0' terminated strings + * + * Since urldecoding only shrinks the output string, it is possible to + * do it in-place, ie, string == escaped + * + * Returns 0 if completed OK or nonzero for urldecode violation (non-hex chars + * where hex required, etc) + */ +LWS_VISIBLE LWS_EXTERN int +lws_urldecode(char *string, const char *escaped, int len); +///@} + +/** + * lws_http_date_render_from_unix() - render unixtime as RFC7231 date string + * + * \param buf: Destination string buffer + * \param len: avilable length of dest string buffer in bytes + * \param t: pointer to the time_t to render + * + * Returns 0 if time_t is rendered into the string buffer successfully, else + * nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t); + +/** + * lws_http_date_parse_unix() - parse a RFC7231 date string into unixtime + * + * \param b: Source string buffer + * \param len: avilable length of source string buffer in bytes + * \param t: pointer to the destination time_t to set + * + * Returns 0 if string buffer parsed as RFC7231 time successfully, and + * *t set to the parsed unixtime, else return nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_date_parse_unix(const char *b, size_t len, time_t *t); + +/** + * lws_http_check_retry_after() - increase a timeout if retry-after present + * + * \param wsi: http stream this relates to + * \param us_interval_in_out: default us retry interval on entry may be updated + * + * This function may extend the incoming retry interval if the server has + * requested that using retry-after: header. It won't reduce the incoming + * retry interval, only leave it alone or increase it. + * + * *us_interval_in_out should be set to a default retry interval on entry, if + * the wsi has a retry-after time or interval that resolves to an interval + * longer than the entry *us_interval_in_out, that will be updated to the longer + * interval and return 0. + * + * If no usable retry-after or the time is now or in the past, + * *us_interval_in_out is left alone and the function returns nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out); + +/** + * lws_return_http_status() - Return simple http status + * \param wsi: Websocket instance (available from user callback) + * \param code: Status index, eg, 404 + * \param html_body: User-readable HTML description < 1KB, or NULL + * + * Helper to report HTTP errors back to the client cleanly and + * consistently + */ +LWS_VISIBLE LWS_EXTERN int +lws_return_http_status(struct lws *wsi, unsigned int code, + const char *html_body); + +/** + * lws_http_redirect() - write http redirect out on wsi + * + * \param wsi: websocket connection + * \param code: HTTP response code (eg, 301) + * \param loc: where to redirect to + * \param len: length of loc + * \param p: pointer current position in buffer (updated as we write) + * \param end: pointer to end of buffer + * + * Returns amount written, or < 0 indicating fatal write failure. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, + unsigned char **p, unsigned char *end); + +/** + * lws_http_transaction_completed() - wait for new http transaction or close + * \param wsi: websocket connection + * + * Returns 1 if the HTTP connection must close now + * Returns 0 and resets connection to wait for new HTTP header / + * transaction if possible + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_http_transaction_completed(struct lws *wsi); + +/** + * lws_http_headers_detach() - drop the associated headers storage and allow + * it to be reused by another connection + * \param wsi: http connection + * + * If the wsi has an ah headers struct attached, detach it. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_headers_detach(struct lws *wsi); + +/** + * lws_http_mark_sse() - called to indicate this http stream is now doing SSE + * + * \param wsi: http connection + * + * Cancel any timeout on the wsi, and for h2, mark the network connection as + * containing an immortal stream for the duration the SSE stream is open. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_mark_sse(struct lws *wsi); + +/** + * lws_h2_client_stream_long_poll_rxonly() - h2 stream to immortal read-only + * + * \param wsi: h2 stream client wsi + * + * Send END_STREAM-flagged zero-length DATA frame to set client stream wsi into + * half-closed (local) and remote into half-closed (remote). Set the client + * stream wsi to be immortal (not subject to timeouts). + * + * Used if the remote server supports immortal long poll to put the stream into + * a read-only state where it can wait as long as needed for rx. + * + * Returns 0 if the process (which happens asynchronously) started or non-zero + * if it wasn't an h2 stream. + */ +LWS_VISIBLE LWS_EXTERN int +lws_h2_client_stream_long_poll_rxonly(struct lws *wsi); + +/** + * lws_http_compression_apply() - apply an http compression transform + * + * \param wsi: the wsi to apply the compression transform to + * \param name: NULL, or the name of the compression transform, eg, "deflate" + * \param p: pointer to pointer to headers buffer + * \param end: pointer to end of headers buffer + * \param decomp: 0 = add compressor to wsi, 1 = add decompressor + * + * This allows transparent compression of dynamically generated HTTP. The + * requested compression (eg, "deflate") is only applied if the client headers + * indicated it was supported (and it has support in lws), otherwise it's a NOP. + * + * If the requested compression method is NULL, then the supported compression + * formats are tried, and for non-decompression (server) mode the first that's + * found on the client's accept-encoding header is chosen. + * + * NOTE: the compression transform, same as h2 support, relies on the user + * code using LWS_WRITE_HTTP and then LWS_WRITE_HTTP_FINAL on the last part + * written. The internal lws fileserving code already does this. + * + * If the library was built without the cmake option + * LWS_WITH_HTTP_STREAM_COMPRESSION set, then a NOP is provided for this api, + * allowing user code to build either way and use compression if available. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_compression_apply(struct lws *wsi, const char *name, + unsigned char **p, unsigned char *end, char decomp); + +/** + * lws_http_is_redirected_to_get() - true if redirected to GET + * + * \param wsi: the wsi to check + * + * Check if the wsi is currently in GET mode, after, eg, doing a POST and + * receiving a 303. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_is_redirected_to_get(struct lws *wsi); + +/** + * lws_http_cookie_get() - return copy of named cookie if present + * + * \param wsi: the wsi to check + * \param name: name of the cookie + * \param buf: buffer to store the cookie contents into + * \param max_len: on entry, maximum length of buf... on exit, used len of buf + * + * If no cookie header, or no cookie of the requested name, or the value is + * larger than can fit in buf, returns nonzero. + * + * If the cookie is found, copies its value into buf with a terminating NUL, + * sets *max_len to the used length, and returns 0. + * + * This handles the parsing of the possibly multi-cookie header string and + * terminating the requested cookie at the next ; if present. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); + +/** + * lws_http_client_http_error() - determine if the response code indicates an error + * + * \param code: the response code to test + * + * Returns nonzero if the code indicates an error, else zero if reflects a + * non-error condition + */ +#define lws_http_client_http_resp_is_error(code) (!(code < 400)) + +/** + * lws_h2_update_peer_txcredit() - manually update stream peer tx credit + * + * \param wsi: the h2 child stream whose peer credit to change + * \param sid: the stream ID, or LWS_H2_STREAM_SID for the wsi stream ID + * \param bump: signed change to confer upon peer tx credit for sid + * + * In conjunction with LCCSCF_H2_MANUAL_RXFLOW flag, allows the user code to + * selectively starve the remote peer of the ability to send us data on a client + * connection. + * + * Normally lws sends an initial window size for the peer to send to it of 0, + * but during the header phase it sends a WINDOW_UPDATE to increase the amount + * available. LCCSCF_H2_MANUAL_RXFLOW restricts this initial increase in tx + * credit for the stream, before it has been asked to send us anything, to the + * amount specified in the client info .manual_initial_tx_credit member, and + * this api can be called to send the other side permission to send us up to + * \p bump additional bytes. + * + * The nwsi tx credit is updated automatically for exactly what was sent to us + * on a stream with LCCSCF_H2_MANUAL_RXFLOW flag, but the stream's own tx credit + * must be handled manually by user code via this api. + * + * Returns 0 for success or nonzero for failure. + */ +#define LWS_H2_STREAM_SID -1 +LWS_VISIBLE LWS_EXTERN int +lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump); + + +/** + * lws_h2_get_peer_txcredit_estimate() - return peer tx credit estimate + * + * \param wsi: the h2 child stream whose peer credit estimate to return + * + * Returns the estimated amount of tx credit at the peer, in other words the + * number of bytes the peer is authorized to send to us. + * + * It's an 'estimate' because we don't know how much is already in flight + * towards us and actually already used. + */ +LWS_VISIBLE LWS_EXTERN int +lws_h2_get_peer_txcredit_estimate(struct lws *wsi); + +///@} + diff --git a/thirdparty/include/libwebsockets/lws-i2c.h b/thirdparty/include/libwebsockets/lws-i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..3bd81ed375107156837376072422b76d4ed57901 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-i2c.h @@ -0,0 +1,54 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for i2c, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + */ + +#if !defined(__LWS_I2C_H__) +#define __LWS_I2C_H__ + +#include +#include + +typedef struct lws_i2c_ops { + int (*init)(const struct lws_i2c_ops *ctx); + int (*start)(const struct lws_i2c_ops *ctx); + void (*stop)(const struct lws_i2c_ops *ctx); + int (*write)(const struct lws_i2c_ops *ctx, uint8_t data); + int (*read)(const struct lws_i2c_ops *ctx); + void (*set_ack)(const struct lws_i2c_ops *octx, int ack); +} lws_i2c_ops_t; + +/* + * These are implemented by calling the ops above, and so are generic + */ + +LWS_VISIBLE LWS_EXTERN int +lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c); + +LWS_VISIBLE LWS_EXTERN int +lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, + size_t len); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-ili9341-spi.h b/thirdparty/include/libwebsockets/lws-ili9341-spi.h new file mode 100755 index 0000000000000000000000000000000000000000..70a361a44b9ccb31e3b89b339a3eec10eb67e1b4 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ili9341-spi.h @@ -0,0 +1,54 @@ +/* + * lws abstract display implementation for ili9341 on spi + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_ILI9341_SPI_H__) +#define __LWS_DISPLAY_ILI9341_SPI_H__ + + +typedef struct lws_display_ili9341 { + + lws_display_t disp; /* use lws_display_ili9341_ops to set */ + const lws_spi_ops_t *spi; /* spi ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t spi_index; /* cs index starting from 0 */ + +} lws_display_ili9341_t; + +int +lws_display_ili9341_spi_init(const struct lws_display *disp); +int +lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ili9341_spi_power(const struct lws_display *disp, int state); + +#define lws_display_ili9341_ops \ + .init = lws_display_ili9341_spi_init, \ + .blit = lws_display_ili9341_spi_blit, \ + .power = lws_display_ili9341_spi_power +#endif diff --git a/thirdparty/include/libwebsockets/lws-jose.h b/thirdparty/include/libwebsockets/lws-jose.h new file mode 100755 index 0000000000000000000000000000000000000000..247d02c68642e3fbad4f49c5658f7a3f3a318067 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-jose.h @@ -0,0 +1,212 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +enum lws_jws_jose_hdr_indexes { + LJJHI_ALG, /* REQUIRED */ + LJJHI_JKU, /* Optional: string */ + LJJHI_JWK, /* Optional: jwk JSON object: public key: */ + LJJHI_KID, /* Optional: string */ + LJJHI_X5U, /* Optional: string: url of public key cert / chain */ + LJJHI_X5C, /* Optional: base64 (NOT -url): actual cert */ + LJJHI_X5T, /* Optional: base64url: SHA-1 of actual cert */ + LJJHI_X5T_S256, /* Optional: base64url: SHA-256 of actual cert */ + LJJHI_TYP, /* Optional: string: media type */ + LJJHI_CTY, /* Optional: string: content media type */ + LJJHI_CRIT, /* Optional for send, REQUIRED: array of strings: + * mustn't contain standardized strings or null set */ + + LJJHI_RECIPS_HDR, + LJJHI_RECIPS_HDR_ALG, + LJJHI_RECIPS_HDR_KID, + LJJHI_RECIPS_EKEY, + + LJJHI_ENC, /* JWE only: Optional: string */ + LJJHI_ZIP, /* JWE only: Optional: string ("DEF" = deflate) */ + + LJJHI_EPK, /* Additional arg for JWE ECDH: ephemeral public key */ + LJJHI_APU, /* Additional arg for JWE ECDH: base64url */ + LJJHI_APV, /* Additional arg for JWE ECDH: base64url */ + LJJHI_IV, /* Additional arg for JWE AES: base64url */ + LJJHI_TAG, /* Additional arg for JWE AES: base64url */ + LJJHI_P2S, /* Additional arg for JWE PBES2: base64url: salt */ + LJJHI_P2C, /* Additional arg for JWE PBES2: integer: count */ + + LWS_COUNT_JOSE_HDR_ELEMENTS +}; + +enum lws_jose_algtype { + LWS_JOSE_ENCTYPE_NONE, + + LWS_JOSE_ENCTYPE_RSASSA_PKCS1_1_5, + LWS_JOSE_ENCTYPE_RSASSA_PKCS1_OAEP, + LWS_JOSE_ENCTYPE_RSASSA_PKCS1_PSS, + + LWS_JOSE_ENCTYPE_ECDSA, + LWS_JOSE_ENCTYPE_ECDHES, + + LWS_JOSE_ENCTYPE_AES_CBC, + LWS_JOSE_ENCTYPE_AES_CFB128, + LWS_JOSE_ENCTYPE_AES_CFB8, + LWS_JOSE_ENCTYPE_AES_CTR, + LWS_JOSE_ENCTYPE_AES_ECB, + LWS_JOSE_ENCTYPE_AES_OFB, + LWS_JOSE_ENCTYPE_AES_XTS, /* care: requires double-length key */ + LWS_JOSE_ENCTYPE_AES_GCM, +}; + +/* there's a table of these defined in lws-gencrypto-common.c */ + +struct lws_jose_jwe_alg { + enum lws_genhash_types hash_type; + enum lws_genhmac_types hmac_type; + enum lws_jose_algtype algtype_signing; /* the signing cipher */ + enum lws_jose_algtype algtype_crypto; /* the encryption cipher */ + const char *alg; /* the JWA enc alg name, eg "ES512" */ + const char *curve_name; /* NULL, or, eg, "P-256" */ + unsigned short keybits_min, keybits_fixed; + unsigned short ivbits; +}; + +/* + * For JWS, "JOSE header" is defined to be the union of... + * + * o JWS Protected Header + * o JWS Unprotected Header + * + * For JWE, the "JOSE header" is the union of... + * + * o JWE Protected Header + * o JWE Shared Unprotected Header + * o JWE Per-Recipient Unprotected Header + */ + +#define LWS_JWS_MAX_RECIPIENTS 3 + +struct lws_jws_recpient { + /* + * JOSE per-recipient unprotected header... for JWS this contains + * protected / header / signature + */ + struct lws_gencrypto_keyelem unprot[LWS_COUNT_JOSE_HDR_ELEMENTS]; + struct lws_jwk jwk_ephemeral; /* recipient ephemeral key if any */ + struct lws_jwk jwk; /* recipient "jwk" key if any */ +}; + +struct lws_jose { + /* JOSE protected and unprotected header elements */ + struct lws_gencrypto_keyelem e[LWS_COUNT_JOSE_HDR_ELEMENTS]; + + struct lws_jws_recpient recipient[LWS_JWS_MAX_RECIPIENTS]; + + char typ[32]; + + /* information from the protected header part */ + const struct lws_jose_jwe_alg *alg; + const struct lws_jose_jwe_alg *enc_alg; + + int recipients; /* count of used recipient[] entries */ +}; + +/** + * lws_jose_init() - prepare a struct lws_jose for use + * + * \param jose: the jose header struct to prepare + */ +LWS_VISIBLE LWS_EXTERN void +lws_jose_init(struct lws_jose *jose); + +/** + * lws_jose_destroy() - retire a struct lws_jose from use + * + * \param jose: the jose header struct to destroy + */ +LWS_VISIBLE LWS_EXTERN void +lws_jose_destroy(struct lws_jose *jose); + +/** + * lws_gencrypto_jws_alg_to_definition() - look up a jws alg name + * + * \param alg: the jws alg name + * \param jose: pointer to the pointer to the info struct to set on success + * + * Returns 0 if *jose set, else nonzero for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_gencrypto_jws_alg_to_definition(const char *alg, + const struct lws_jose_jwe_alg **jose); + +/** + * lws_gencrypto_jwe_alg_to_definition() - look up a jwe alg name + * + * \param alg: the jwe alg name + * \param jose: pointer to the pointer to the info struct to set on success + * + * Returns 0 if *jose set, else nonzero for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_gencrypto_jwe_alg_to_definition(const char *alg, + const struct lws_jose_jwe_alg **jose); + +/** + * lws_gencrypto_jwe_enc_to_definition() - look up a jwe enc name + * + * \param alg: the jwe enc name + * \param jose: pointer to the pointer to the info struct to set on success + * + * Returns 0 if *jose set, else nonzero for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_gencrypto_jwe_enc_to_definition(const char *enc, + const struct lws_jose_jwe_alg **jose); + +/** + * lws_jws_parse_jose() - parse a JWS JOSE header + * + * \param jose: the jose struct to set to parsing results + * \param buf: the raw JOSE header + * \param len: the length of the raw JOSE header + * \param temp: parent-owned buffer to "allocate" elements into + * \param temp_len: amount of space available in temp + * + * returns the amount of temp used, or -1 for error + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_parse_jose(struct lws_jose *jose, + const char *buf, int len, char *temp, int *temp_len); + +/** + * lws_jwe_parse_jose() - parse a JWE JOSE header + * + * \param jose: the jose struct to set to parsing results + * \param buf: the raw JOSE header + * \param len: the length of the raw JOSE header + * \param temp: parent-owned buffer to "allocate" elements into + * \param temp_len: amount of space available in temp + * + * returns the amount of temp used, or -1 for error + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwe_parse_jose(struct lws_jose *jose, + const char *buf, int len, char *temp, int *temp_len); + diff --git a/thirdparty/include/libwebsockets/lws-jwe.h b/thirdparty/include/libwebsockets/lws-jwe.h new file mode 100755 index 0000000000000000000000000000000000000000..6fa99793d2fdfc21f55a21fd4ca8b05d350704ee --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-jwe.h @@ -0,0 +1,164 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + * + * JWE Compact Serialization consists of + * + * BASE64URL(UTF8(JWE Protected Header)) || '.' || + * BASE64URL(JWE Encrypted Key) || '.' || + * BASE64URL(JWE Initialization Vector) || '.' || + * BASE64URL(JWE Ciphertext) || '.' || + * BASE64URL(JWE Authentication Tag) + */ + +#define LWS_JWE_RFC3394_OVERHEAD_BYTES 8 +#define LWS_JWE_AES_IV_BYTES 16 + +#define LWS_JWE_LIMIT_RSA_KEY_BITS 4096 +#define LWS_JWE_LIMIT_AES_KEY_BITS (512 + 64) /* RFC3394 Key Wrap adds 64b */ +#define LWS_JWE_LIMIT_EC_KEY_BITS 528 /* 521 rounded to byte boundary */ +#define LWS_JWE_LIMIT_HASH_BITS (LWS_GENHASH_LARGEST * 8) + +/* the largest key element for any cipher */ +#define LWS_JWE_LIMIT_KEY_ELEMENT_BYTES (LWS_JWE_LIMIT_RSA_KEY_BITS / 8) + + +struct lws_jwe { + struct lws_jose jose; + struct lws_jws jws; + struct lws_jwk jwk; + + /* + * We have to keep a copy of the CEK so we can reuse it with later + * key encryptions for the multiple recipient case. + */ + uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; + unsigned int cek_valid:1; + + int recip; +}; + +LWS_VISIBLE LWS_EXTERN void +lws_jwe_init(struct lws_jwe *jwe, struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN void +lws_jwe_destroy(struct lws_jwe *jwe); + +LWS_VISIBLE LWS_EXTERN void +lws_jwe_be64(uint64_t c, uint8_t *p8); + +/* + * JWE Compact Serialization consists of + * + * BASE64URL(UTF8(JWE Protected Header)) || '.' || + * BASE64URL(JWE Encrypted Key) || '.' || + * BASE64URL(JWE Initialization Vector) || '.' || + * BASE64URL(JWE Ciphertext) || '.' || + * BASE64URL(JWE Authentication Tag) + */ + +LWS_VISIBLE LWS_EXTERN int +lws_jwe_render_compact(struct lws_jwe *jwe, char *out, size_t out_len); + +LWS_VISIBLE int +lws_jwe_render_flattened(struct lws_jwe *jwe, char *out, size_t out_len); + +LWS_VISIBLE LWS_EXTERN int +lws_jwe_json_parse(struct lws_jwe *jwe, const uint8_t *buf, int len, + char *temp, int *temp_len); + +/** + * lws_jwe_auth_and_decrypt() - confirm and decrypt JWE + * + * \param jose: jose context + * \param jws: jws / jwe context... .map and .map_b64 must be filled already + * + * This is a high level JWE decrypt api that takes a jws with the maps + * already processed, and if the authentication passes, returns the decrypted + * plaintext in jws.map.buf[LJWE_CTXT] and its length in jws.map.len[LJWE_CTXT]. + * + * In the jws, the following fields must have been set by the caller + * + * .context + * .jwk (the key encryption key) + * .map + * .map_b64 + * + * Having the b64 and decoded maps filled externally makes it flexible where + * the data was picked from, eg, from a Complete JWE JSON serialization, a + * flattened one, or a Compact Serialization. + * + * Returns decrypt length, or -1 for failure. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwe_auth_and_decrypt(struct lws_jwe *jwe, char *temp, int *temp_len); + +/** + * lws_jwe_encrypt() - perform JWE encryption + * + * \param jose: the JOSE header information (encryption types, etc) + * \param jws: the JWE elements, pointer to jwk etc + * \param temp: parent-owned buffer to "allocate" elements into + * \param temp_len: amount of space available in temp + * + * May be called up to LWS_JWS_MAX_RECIPIENTS times to encrypt the same CEK + * multiple ways on the same JWE payload. + * + * returns the amount of temp used, or -1 for error. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwe_encrypt(struct lws_jwe *jwe, char *temp, int *temp_len); + +/** + * lws_jwe_create_packet() - add b64 sig to b64 hdr + payload + * + * \param jwe: the struct lws_jwe we are trying to render + * \param payload: unencoded payload JSON + * \param len: length of unencoded payload JSON + * \param nonce: Nonse string to include in protected header + * \param out: buffer to take signed packet + * \param out_len: size of \p out buffer + * \param conext: lws_context to get random from + * + * This creates a "flattened" JWS packet from the jwk and the plaintext + * payload, and signs it. The packet is written into \p out. + * + * This does the whole packet assembly and signing, calling through to + * lws_jws_sign_from_b64() as part of the process. + * + * Returns the length written to \p out, or -1. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwe_create_packet(struct lws_jwe *jwe, + const char *payload, size_t len, const char *nonce, + char *out, size_t out_len, struct lws_context *context); + + +/* only exposed because we have test vectors that need it */ +LWS_VISIBLE LWS_EXTERN int +lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek, + uint8_t *aad, int aad_len); + +/* only exposed because we have test vectors that need it */ +LWS_VISIBLE LWS_EXTERN int +lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, + uint8_t *out, const uint8_t *shared_secret, int sslen); diff --git a/thirdparty/include/libwebsockets/lws-jwk.h b/thirdparty/include/libwebsockets/lws-jwk.h new file mode 100755 index 0000000000000000000000000000000000000000..bf33b80418fd590ad974ea6d76b894631ffb2b17 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-jwk.h @@ -0,0 +1,220 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup jwk JSON Web Keys + * ## JSON Web Keys API + * + * Lws provides an API to parse JSON Web Keys into a struct lws_gencrypto_keyelem. + * + * "oct" and "RSA" type keys are supported. For "oct" keys, they are held in + * the "e" member of the struct lws_gencrypto_keyelem. + * + * Keys elements are allocated on the heap. You must destroy the allocations + * in the struct lws_gencrypto_keyelem by calling + * lws_genrsa_destroy_elements() when you are finished with it. + */ +///@{ + +enum enum_jwk_meta_tok { + JWK_META_KTY, + JWK_META_KID, + JWK_META_USE, + JWK_META_KEY_OPS, + JWK_META_X5C, + JWK_META_ALG, + + LWS_COUNT_JWK_ELEMENTS +}; + +struct lws_jwk { + /* key data elements */ + struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT]; + /* generic meta key elements, like KID */ + struct lws_gencrypto_keyelem meta[LWS_COUNT_JWK_ELEMENTS]; + int kty; /**< one of LWS_GENCRYPTO_KTY_ */ + char private_key; /* nonzero = has private key elements */ +}; + +typedef int (*lws_jwk_key_import_callback)(struct lws_jwk *s, void *user); + +struct lws_jwk_parse_state { + struct lws_jwk *jwk; + char b64[(((8192 / 8) * 4) / 3) + 1]; /* enough for 8Kb key */ + lws_jwk_key_import_callback per_key_cb; + void *user; + int pos; + int cose_state; + int seen; + unsigned short possible; +}; + +/** lws_jwk_import() - Create a JSON Web key from the textual representation + * + * \param jwk: the JWK object to create + * \param cb: callback for each jwk-processed key, or NULL if importing a single + * key with no parent "keys" JSON + * \param user: pointer to be passed to the callback, otherwise ignored by lws. + * NULL if importing a single key with no parent "keys" JSON + * \param in: a single JWK JSON stanza in utf-8 + * \param len: the length of the JWK JSON stanza in bytes + * + * Creates an lws_jwk struct filled with data from the JSON representation. + * + * There are two ways to use this... with some protocols a single jwk is + * delivered with no parent "keys": [] array. If you call this with cb and + * user as NULL, then the input will be interpreted like that and the results + * placed in s. + * + * The second case is that you are dealing with a "keys":[] array with one or + * more keys in it. In this case, the function iterates through the keys using + * s as a temporary jwk, and calls the user-provided callback for each key in + * turn while it return 0 (nonzero return from the callback terminates the + * iteration through any further keys). + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, + const char *in, size_t len); + +/** lws_jwk_destroy() - Destroy a JSON Web key + * + * \param jwk: the JWK object to destroy + * + * All allocations in the lws_jwk are destroyed + */ +LWS_VISIBLE LWS_EXTERN void +lws_jwk_destroy(struct lws_jwk *jwk); + +/** lws_jwk_dup_oct() - Set a jwk to a dup'd binary OCT key + * + * \param jwk: the JWK object to set + * \param key: the JWK object to destroy + * \param len: the JWK object to destroy + * + * Sets the kty to OCT, allocates len bytes for K and copies len bytes of key + * into the allocation. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len); + +#define LWSJWKF_EXPORT_PRIVATE (1 << 0) +#define LWSJWKF_EXPORT_NOCRLF (1 << 1) + +/** lws_jwk_export() - Export a JSON Web key to a textual representation + * + * \param jwk: the JWK object to export + * \param flags: control export options + * \param p: the buffer to write the exported JWK to + * \param len: the length of the buffer \p p in bytes... reduced by used amount + * + * Returns length of the used part of the buffer if OK, or -1 for error. + * + * \p flags can be OR-ed together + * + * LWSJWKF_EXPORT_PRIVATE: default is only public part, set this to also export + * the private part + * + * LWSJWKF_EXPORT_NOCRLF: normally adds a CRLF at the end of the export, if + * you need to suppress it, set this flag + * + * Serializes the content of the JWK into a char buffer. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len); + +/** lws_jwk_load() - Import a JSON Web key from a file + * + * \param jwk: the JWK object to load into + * \param filename: filename to load from + * \param cb: optional callback for each key + * \param user: opaque user pointer passed to cb if given + * + * Returns 0 for OK or -1 for failure + * + * There are two ways to use this... with some protocols a single jwk is + * delivered with no parent "keys": [] array. If you call this with cb and + * user as NULL, then the input will be interpreted like that and the results + * placed in s. + * + * The second case is that you are dealing with a "keys":[] array with one or + * more keys in it. In this case, the function iterates through the keys using + * s as a temporary jwk, and calls the user-provided callback for each key in + * turn while it return 0 (nonzero return from the callback terminates the + * iteration through any further keys, leaving the last one in s). + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_load(struct lws_jwk *jwk, const char *filename, + lws_jwk_key_import_callback cb, void *user); + +/** lws_jwk_save() - Export a JSON Web key to a file + * + * \param jwk: the JWK object to save from + * \param filename: filename to save to + * + * Returns 0 for OK or -1 for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_save(struct lws_jwk *jwk, const char *filename); + +/** lws_jwk_rfc7638_fingerprint() - jwk to RFC7638 compliant fingerprint + * + * \param jwk: the JWK object to fingerprint + * \param digest32: buffer to take 32-byte digest + * + * Returns 0 for OK or -1 for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32); + +/** lws_jwk_strdup_meta() - allocate a duplicated string meta element + * + * \param jwk: the JWK object to fingerprint + * \param idx: JWK_META_ element index + * \param in: string to copy + * \param len: length of string to copy + * + * Returns 0 for OK or -1 for failure + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx, + const char *in, int len); + + +LWS_VISIBLE LWS_EXTERN int +lws_jwk_dump(struct lws_jwk *jwk); + +/** lws_jwk_generate() - create a new key of given type and characteristics + * + * \param context: the struct lws_context used for RNG + * \param jwk: the JWK object to fingerprint + * \param kty: One of the LWS_GENCRYPTO_KTY_ key types + * \param bits: for OCT and RSA keys, the number of bits + * \param curve: for EC keys, the name of the curve + * + * Returns 0 for OK or -1 for failure + */ +LWS_VISIBLE int +lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, + enum lws_gencrypto_kty kty, int bits, const char *curve); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-jws.h b/thirdparty/include/libwebsockets/lws-jws.h new file mode 100755 index 0000000000000000000000000000000000000000..0ad4714b7c492030c6e232be4376365556951fc5 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-jws.h @@ -0,0 +1,599 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup jws JSON Web Signature + * ## JSON Web Signature API + * + * Lws provides an API to check and create RFC7515 JSON Web Signatures + * + * SHA256/384/512 HMAC, and RSA 256/384/512 are supported. + * + * The API uses your TLS library crypto, but works exactly the same no matter + * what your TLS backend is. + */ +///@{ + +/* + * The maps are built to work with both JWS (LJWS_) and JWE (LJWE_), and are + * sized to the slightly larger JWE case. + */ + +enum enum_jws_sig_elements { + + /* JWS block namespace */ + LJWS_JOSE, + LJWS_PYLD, + LJWS_SIG, + LJWS_UHDR, + + /* JWE block namespace */ + LJWE_JOSE = 0, + LJWE_EKEY, + LJWE_IV, + LJWE_CTXT, + LJWE_ATAG, + LJWE_AAD, + + LWS_JWS_MAX_COMPACT_BLOCKS +}; + +struct lws_jws_map { + const char *buf[LWS_JWS_MAX_COMPACT_BLOCKS]; + uint32_t len[LWS_JWS_MAX_COMPACT_BLOCKS]; +}; + +#define LWS_JWS_MAX_SIGS 3 + +struct lws_jws { + struct lws_jwk *jwk; /* the struct lws_jwk containing the signing key */ + struct lws_context *context; /* the lws context (used to get random) */ + struct lws_jws_map map, map_b64; +}; + +/* jws EC signatures do not have ASN.1 in them, meaning they're incompatible + * with generic signatures. + */ + +/** + * lws_jws_init() - initialize a jws for use + * + * \param jws: pointer to the jws to initialize + * \param jwk: the jwk to use with this jws + * \param context: the lws_context to use + */ +LWS_VISIBLE LWS_EXTERN void +lws_jws_init(struct lws_jws *jws, struct lws_jwk *jwk, + struct lws_context *context); + +/** + * lws_jws_destroy() - scrub a jws + * + * \param jws: pointer to the jws to destroy + * + * Call before the jws goes out of scope. + * + * Elements defined in the jws are zeroed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_jws_destroy(struct lws_jws *jws); + +/** + * lws_jws_sig_confirm_compact() - check signature + * + * \param map: pointers and lengths for each of the unencoded JWS elements + * \param jwk: public key + * \param context: lws_context + * \param temp: scratchpad + * \param temp_len: length of scratchpad + * + * Confirms the signature on a JWS. Use if you have non-b64 plain JWS elements + * in a map... it'll make a temp b64 version needed for comparison. See below + * for other variants. + * + * Returns 0 on match. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_sig_confirm_compact(struct lws_jws_map *map, struct lws_jwk *jwk, + struct lws_context *context, + char *temp, int *temp_len); + +LWS_VISIBLE LWS_EXTERN int +lws_jws_sig_confirm_compact_b64_map(struct lws_jws_map *map_b64, + struct lws_jwk *jwk, + struct lws_context *context, + char *temp, int *temp_len); + +/** + * lws_jws_sig_confirm_compact_b64() - check signature on b64 compact JWS + * + * \param in: pointer to b64 jose.payload[.hdr].sig + * \param len: bytes available at \p in + * \param map: map to take decoded non-b64 content + * \param jwk: public key + * \param context: lws_context + * \param temp: scratchpad + * \param temp_len: size of scratchpad + * + * Confirms the signature on a JWS. Use if you have you have b64 compact layout + * (jose.payload.hdr.sig) as an aggregated string... it'll make a temp plain + * version needed for comparison. + * + * Returns 0 on match. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_sig_confirm_compact_b64(const char *in, size_t len, + struct lws_jws_map *map, + struct lws_jwk *jwk, + struct lws_context *context, + char *temp, int *temp_len); + +/** + * lws_jws_sig_confirm() - check signature on plain + b64 JWS elements + * + * \param map_b64: pointers and lengths for each of the b64-encoded JWS elements + * \param map: pointers and lengths for each of the unencoded JWS elements + * \param jwk: public key + * \param context: lws_context + * + * Confirms the signature on a JWS. Use if you have you already have both b64 + * compact layout (jose.payload.hdr.sig) and decoded JWS elements in maps. + * + * If you had the b64 string and called lws_jws_compact_decode() on it, you + * will end up with both maps, and can use this api version, saving needlessly + * regenerating any temp map. + * + * Returns 0 on match. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */ + struct lws_jws_map *map, /* non-b64 */ + struct lws_jwk *jwk, struct lws_context *context); + +/** + * lws_jws_sign_from_b64() - add b64 sig to b64 hdr + payload + * + * \param jose: jose header information + * \param jws: information to include in the signature + * \param b64_sig: output buffer for b64 signature + * \param sig_len: size of \p b64_sig output buffer + * + * This adds a b64-coded JWS signature of the b64-encoded protected header + * and b64-encoded payload, at \p b64_sig. The signature will be as large + * as the N element of the RSA key when the RSA key is used, eg, 512 bytes for + * a 4096-bit key, and then b64-encoding on top. + * + * In some special cases, there is only payload to sign and no header, in that + * case \p b64_hdr may be NULL, and only the payload will be hashed before + * signing. + * + * Returns the length of the encoded signature written to \p b64_sig, or -1. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig, + size_t sig_len); + +/** + * lws_jws_compact_decode() - converts and maps compact serialization b64 sections + * + * \param in: the incoming compact serialized b64 + * \param len: the length of the incoming compact serialized b64 + * \param map: pointer to the results structure + * \param map_b64: NULL, or pointer to a second results structure taking block + * information about the undecoded b64 + * \param out: buffer to hold decoded results + * \param out_len: size of out in bytes + * + * Returns number of sections (2 if "none", else 3), or -1 if illegal. + * + * map is set to point to the start and hold the length of each decoded block. + * If map_b64 is non-NULL, then it's set with information about the input b64 + * blocks. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_compact_decode(const char *in, int len, struct lws_jws_map *map, + struct lws_jws_map *map_b64, char *out, int *out_len); + +LWS_VISIBLE LWS_EXTERN int +lws_jws_compact_encode(struct lws_jws_map *map_b64, /* b64-encoded */ + const struct lws_jws_map *map, /* non-b64 */ + char *buf, int *out_len); + +LWS_VISIBLE LWS_EXTERN int +lws_jws_sig_confirm_json(const char *in, size_t len, + struct lws_jws *jws, struct lws_jwk *jwk, + struct lws_context *context, + char *temp, int *temp_len); + +/** + * lws_jws_write_flattened_json() - create flattened JSON sig + * + * \param jws: information to include in the signature + * \param flattened: output buffer for JSON + * \param len: size of \p flattened output buffer + * + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_write_flattened_json(struct lws_jws *jws, char *flattened, size_t len); + +/** + * lws_jws_write_compact() - create flattened JSON sig + * + * \param jws: information to include in the signature + * \param compact: output buffer for compact format + * \param len: size of \p flattened output buffer + * + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len); + + + +/* + * below apis are not normally needed if dealing with whole JWS... they're + * useful for creating from scratch + */ + + +/** + * lws_jws_dup_element() - allocate space for an element and copy data into it + * + * \param map: map to create the element in + * \param idx: index of element in the map to create + * \param temp: space to allocate in + * \param temp_len: available space at temp + * \param in: data to duplicate into element + * \param in_len: length of data to duplicate + * \param actual_alloc: 0 for same as in_len, else actual allocation size + * + * Copies in_len from in to temp, if temp_len is sufficient. + * + * Returns 0 or -1 if not enough space in temp / temp_len. + * + * Over-allocation can be acheived by setting actual_alloc to the real + * allocation desired... in_len will be copied into it. + * + * *temp_len is reduced by actual_alloc if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_dup_element(struct lws_jws_map *map, int idx, + char *temp, int *temp_len, const void *in, size_t in_len, + size_t actual_alloc); + +/** + * lws_jws_randomize_element() - create an element and fill with random + * + * \param context: lws_context used for random + * \param map: map to create the element in + * \param idx: index of element in the map to create + * \param temp: space to allocate in + * \param temp_len: available space at temp + * \param random_len: length of data to fill with random + * \param actual_alloc: 0 for same as random_len, else actual allocation size + * + * Randomize random_len bytes at temp, if temp_len is sufficient. + * + * Returns 0 or -1 if not enough space in temp / temp_len. + * + * Over-allocation can be acheived by setting actual_alloc to the real + * allocation desired... the first random_len will be filled with random. + * + * *temp_len is reduced by actual_alloc if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_randomize_element(struct lws_context *context, + struct lws_jws_map *map, + int idx, char *temp, int *temp_len, size_t random_len, + size_t actual_alloc); + +/** + * lws_jws_alloc_element() - create an element and reserve space for content + * + * \param map: map to create the element in + * \param idx: index of element in the map to create + * \param temp: space to allocate in + * \param temp_len: available space at temp + * \param len: logical length of element + * \param actual_alloc: 0 for same as len, else actual allocation size + * + * Allocate len bytes at temp, if temp_len is sufficient. + * + * Returns 0 or -1 if not enough space in temp / temp_len. + * + * Over-allocation can be acheived by setting actual_alloc to the real + * allocation desired... the element logical length will be set to len. + * + * *temp_len is reduced by actual_alloc if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_alloc_element(struct lws_jws_map *map, int idx, char *temp, + int *temp_len, size_t len, size_t actual_alloc); + +/** + * lws_jws_encode_b64_element() - create an b64-encoded element + * + * \param map: map to create the element in + * \param idx: index of element in the map to create + * \param temp: space to allocate in + * \param temp_len: available space at temp + * \param in: pointer to unencoded input + * \param in_len: length of unencoded input + * + * Allocate len bytes at temp, if temp_len is sufficient. + * + * Returns 0 or -1 if not enough space in temp / temp_len. + * + * Over-allocation can be acheived by setting actual_alloc to the real + * allocation desired... the element logical length will be set to len. + * + * *temp_len is reduced by actual_alloc if successful. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_encode_b64_element(struct lws_jws_map *map, int idx, + char *temp, int *temp_len, const void *in, + size_t in_len); + + +/** + * lws_jws_b64_compact_map() - find block starts and lengths in compact b64 + * + * \param in: pointer to b64 jose.payload[.hdr].sig + * \param len: bytes available at \p in + * \param map: output struct with pointers and lengths for each JWS element + * + * Scans a jose.payload[.hdr].sig b64 string and notes where the blocks start + * and their length into \p map. + * + * Returns number of blocks if OK. May return <0 if malformed. + * May not fill all map entries. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_jws_b64_compact_map(const char *in, int len, struct lws_jws_map *map); + + +/** + * lws_jws_base64_enc() - encode input data into b64url data + * + * \param in: the incoming plaintext + * \param in_len: the length of the incoming plaintext in bytes + * \param out: the buffer to store the b64url encoded data to + * \param out_max: the length of \p out in bytes + * + * Returns either -1 if problems, or the number of bytes written to \p out. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max); + +/** + * lws_jws_encode_section() - encode input data into b64url data, + * prepending . if not first + * + * \param in: the incoming plaintext + * \param in_len: the length of the incoming plaintext in bytes + * \param first: nonzero if the first section + * \param p: the buffer to store the b64url encoded data to + * \param end: just past the end of p + * + * Returns either -1 if problems, or the number of bytes written to \p out. + * If the section is not the first one, '.' is prepended. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, + char *end); + +/** + * lws_jwt_signed_validate() - check a compact JWT against a key and alg + * + * \param ctx: the lws_context + * \param jwk: the key for checking the signature + * \param alg_list: the expected alg name, like "ES512" + * \param com: the compact JWT + * \param len: the length of com + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param out: the output buffer to hold the validated plaintext + * \param out_len: on entry, max length of out; on exit, used length of out + * + * Returns nonzero if the JWT cannot be validated or the plaintext can't fit the + * provided output buffer, or 0 if it is validated as being signed by the + * provided jwk. + * + * If validated, the plaintext in the JWT is copied into out and out_len set to + * the used length. + * + * temp can be discarded or reused after the call returned, it's used to hold + * transformations of the B64 JWS in the JWT. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg_list, const char *com, size_t len, + char *temp, int tl, char *out, size_t *out_len); + +/** + * lws_jwt_sign_compact() - generate a compact JWT using a key and alg + * + * \param ctx: the lws_context + * \param jwk: the signing key + * \param alg: the signing alg name, like "ES512" + * \param out: the output buffer to hold the signed JWT in compact form + * \param out_len: on entry, the length of out; on exit, the used amount of out + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param format: a printf style format specification + * \param ...: zero or more args for the format specification + * + * Creates a JWT in a single step, from the format string and args through to + * outputting a well-formed compact JWT representation in out. + * + * Returns 0 if all is well and *out_len is the amount of data in out, else + * nonzero if failed. Temp must be large enough to hold various intermediate + * representations. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg, char *out, size_t *out_len, char *temp, + int tl, const char *format, ...) LWS_FORMAT(8); + +struct lws_jwt_sign_info { + const char *alg; + /**< entry: signing alg name, like "RS256" */ + const char *jose_hdr; + /**< entry: optional JOSE hdr; if present, alg field is ignored; instead the + * whole claim object has to be provided in this parameter */ + size_t jose_hdr_len; + /**< entry: if jose_hdr is not NULL, JOSE header length without terminating '\0' */ + char *out; + /**< exit: signed JWT in compact form*/ + size_t *out_len; + /**< entry,exit: buffer size of out; actual size of JWT on exit */ + char *temp; + /**< exit undefined content, used by the function as a temporary scratchpad; MUST + * be large enogh to store various intermediate representations */ + int tl; + /**< entry: size of temp buffer */ +}; + +/** + * lws_jwt_sign_compact() - generate a compact JWT using a key and JOSE header + * + * \param ctx: the lws_context + * \param jwk: the signing key + * \param info: info describing the JWT's content and output/temp buffers + * \param format: a printf style format specification of the claims object + * \param ...: zero or more args for the format specification + * + * Creates a JWT in a single step, from the format string and args through to + * outputting a well-formed compact JWT representation in out. The provided + * JOSE header's syntax is checked before it is added to the JWT. + * + * Returns 0 if all is well and *out_len is the amount of data in out, else + * nonzero if failed. Temp must be large enough to hold various intermediate + * representations. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_sign_via_info(struct lws_context *ctx, struct lws_jwk *jwk, + const struct lws_jwt_sign_info *info, const char *format, ...) LWS_FORMAT(4); + +/** + * lws_jwt_token_sanity() - check a validated jwt payload for sanity + * + * \param in: the JWT payload + * \param in_len: the length of the JWT payload + * \param iss: the expected issuer of the token + * \param aud: the expected audience of the token + * \param csrf_in: NULL, or the csrf token that came in on a URL + * \param sub: a buffer to hold the subject name in the JWT (eg, account name) + * \param sub_len: the max length of the sub buffer + * \param secs_left: set to the number of seconds of valid auth left if valid + * + * This performs some generic sanity tests on validated JWT payload... + * + * - the issuer is as expected + * - the audience is us + * - current time is OK for nbf ("not before") in the token + * - current time is OK for exp ("expiry") in the token + * - if csrf_in is not NULL, that the JWK has a csrf and it matches it + * - if sub is not NULL, that the JWK provides a subject (and copies it to sub) + * + * If the tests pass, *secs_left is set to the number of remaining seconds the + * auth is valid. + * + * Returns 0 if no inconsistency, else nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_token_sanity(const char *in, size_t in_len, + const char *iss, const char *aud, const char *csrf_in, + char *sub, size_t sub_len, unsigned long *exp_unix_time); + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + +struct lws_jwt_sign_set_cookie { + struct lws_jwk *jwk; + /**< entry: required signing key */ + const char *alg; + /**< entry: required signing alg, eg, "ES512" */ + const char *iss; + /**< entry: issuer name to use */ + const char *aud; + /**< entry: audience */ + const char *cookie_name; + /**< entry: the name of the cookie */ + char sub[33]; + /**< sign-entry, validate-exit: subject */ + const char *extra_json; + /**< sign-entry, validate-exit: + * optional "ext" JSON object contents for the JWT */ + size_t extra_json_len; + /**< validate-exit: + * length of optional "ext" JSON object contents for the JWT */ + const char *csrf_in; + /**< validate-entry: + * NULL, or an external CSRF token to check against what is in the JWT */ + unsigned long expiry_unix_time; + /**< sign-entry: seconds the JWT and cookie may live, + * validate-exit: expiry unix time */ +}; + +/** + * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie + * + * \param wsi: the wsi to create the cookie header on + * \param i: structure describing what should be in the JWT + * \param p: wsi headers area + * \param end: end of wsi headers area + * + * Creates a JWT specified \p i, and attaches it to the outgoing headers on + * wsi. Returns 0 if successful. + * + * Best-practice security restrictions are applied to the cookie set action, + * including forcing httponly, and __Host- prefix. As required by __Host-, the + * cookie Path is set to /. __Host- is applied by the function, the cookie_name + * should just be "xyz" for "__Host-xyz". + * + * \p extra_json should just be the bare JSON, a { } is provided around it by + * the function if it's non-NULL. For example, "\"authorization\": 1". + * + * It's recommended the secs parameter is kept as small as consistent with one + * user session on the site if possible, eg, 10 minutes or 20 minutes. At the + * server, it can determine how much time is left in the auth and inform the + * client; if the JWT validity expires, the page should reload so the UI always + * reflects what's possible to do with the authorization state correctly. If + * the JWT expires, the user can log back in using credentials usually stored in + * the browser and auto-filled-in, so this is not very inconvenient. + * + * This is a helper on top of the other JOSE and JWT apis that somewhat crosses + * over between JWT and HTTP, since it knows about cookies. So it is only built + * if both LWS_WITH_JOSE and one of the http-related roles enabled. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_sign_token_set_http_cookie(struct lws *wsi, + const struct lws_jwt_sign_set_cookie *i, + uint8_t **p, uint8_t *end); +LWS_VISIBLE LWS_EXTERN int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len); +#endif + +///@} diff --git a/thirdparty/include/libwebsockets/lws-lecp.h b/thirdparty/include/libwebsockets/lws-lecp.h new file mode 100755 index 0000000000000000000000000000000000000000..04de86add11aa7fc51f16a5a0d142a847d82a3c5 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-lecp.h @@ -0,0 +1,542 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/** \defgroup lecp CBOR parser + * ##CBOR parsing related functions + * \ingroup lwsapi + * + * LECP is an extremely lightweight CBOR stream parser included in lws. It + * is aligned in approach with the LEJP JSON stream parser, with some additional + * things needed for CBOR. + */ +//@{ + +#ifndef LECP_MAX_PARSING_STACK_DEPTH +#define LECP_MAX_PARSING_STACK_DEPTH 5 +#endif +#ifndef LECP_MAX_DEPTH +#define LECP_MAX_DEPTH 12 +#endif +#ifndef LECP_MAX_INDEX_DEPTH +#define LECP_MAX_INDEX_DEPTH 8 +#endif +#ifndef LECP_MAX_PATH +#define LECP_MAX_PATH 128 +#endif +#ifndef LECP_STRING_CHUNK +/* must be >= 30 to assemble floats */ +#define LECP_STRING_CHUNK 254 +#endif + +#define LECP_FLAG_CB_IS_VALUE 64 + +/* + * CBOR initial byte 3 x MSB bits are these + */ + +enum { + LWS_CBOR_MAJTYP_UINT = 0 << 5, + LWS_CBOR_MAJTYP_INT_NEG = 1 << 5, + LWS_CBOR_MAJTYP_BSTR = 2 << 5, + LWS_CBOR_MAJTYP_TSTR = 3 << 5, + LWS_CBOR_MAJTYP_ARRAY = 4 << 5, + LWS_CBOR_MAJTYP_MAP = 5 << 5, + LWS_CBOR_MAJTYP_TAG = 6 << 5, + LWS_CBOR_MAJTYP_FLOAT = 7 << 5, /* also BREAK */ + + LWS_CBOR_MAJTYP_MASK = 7 << 5, + + /* + * For the low 5 bits of the opcode, 0-23 are literals, unless it's + * FLOAT. + * + * 24 = 1 byte; 25 = 2..., 26 = 4... and 27 = 8 bytes following literal. + */ + LWS_CBOR_1 = 24, + LWS_CBOR_2 = 25, + LWS_CBOR_4 = 26, + LWS_CBOR_8 = 27, + + LWS_CBOR_RESERVED = 28, + + LWS_CBOR_SUBMASK = 0x1f, + + /* + * Major type 7 discriminators in low 5 bits + * 0 - 23 is SIMPLE implicit value (like, eg, LWS_CBOR_SWK_TRUE) + */ + LWS_CBOR_SWK_FALSE = 20, + LWS_CBOR_SWK_TRUE = 21, + LWS_CBOR_SWK_NULL = 22, + LWS_CBOR_SWK_UNDEFINED = 23, + + LWS_CBOR_M7_SUBTYP_SIMPLE_X8 = 24, /* simple with additional byte */ + LWS_CBOR_M7_SUBTYP_FLOAT16 = 25, + LWS_CBOR_M7_SUBTYP_FLOAT32 = 26, + LWS_CBOR_M7_SUBTYP_FLOAT64 = 27, + LWS_CBOR_M7_BREAK = 31, + +/* 28, 29, 30 are illegal. + * + * 31 is illegal for UINT, INT_NEG, and TAG; + * for BSTR, TSTR, ARRAY and MAP it means "indefinite length", ie, + * it's made up of an endless amount of determinite-length + * fragments terminated with a BREAK (FLOAT | 31) instead of the + * next determinite-length fragment. The second framing level + * means no need for escapes for BREAK in the data. + */ + + LWS_CBOR_INDETERMINITE = 31, + +/* + * Well-known tags + */ + + LWS_CBOR_WKTAG_DATETIME_STD = 0, /* text */ + LWS_CBOR_WKTAG_DATETIME_EPOCH = 1, /* int or float */ + LWS_CBOR_WKTAG_BIGNUM_UNSIGNED = 2, /* byte string */ + LWS_CBOR_WKTAG_BIGNUM_NEGATIVE = 3, /* byte string */ + LWS_CBOR_WKTAG_DECIMAL_FRAC = 4, /* array */ + LWS_CBOR_WKTAG_BIGFLOAT = 5, /* array */ + + LWS_CBOR_WKTAG_COSE_ENC0 = 16, + LWS_CBOR_WKTAG_COSE_MAC0 = 17, + LWS_CBOR_WKTAG_COSE_SIGN1 = 18, + + LWS_CBOR_WKTAG_TO_B64U = 21, /* any */ + LWS_CBOR_WKTAG_TO_B64 = 22, /* any */ + LWS_CBOR_WKTAG_TO_B16 = 23, /* any */ + LWS_CBOR_WKTAG_CBOR = 24, /* byte string */ + + LWS_CBOR_WKTAG_URI = 32, /* text string */ + LWS_CBOR_WKTAG_B64U = 33, /* text string */ + LWS_CBOR_WKTAG_B64 = 34, /* text string */ + LWS_CBOR_WKTAG_MIME = 36, /* text string */ + + LWS_CBOR_WKTAG_COSE_ENC = 96, + LWS_CBOR_WKTAG_COSE_MAC = 97, + LWS_CBOR_WKTAG_COSE_SIGN = 98, + + LWS_CBOR_WKTAG_SELFDESCCBOR = 55799 +}; + +enum lecp_callbacks { + LECPCB_CONSTRUCTED = 0, + LECPCB_DESTRUCTED = 1, + + LECPCB_COMPLETE = 3, + LECPCB_FAILED = 4, + + LECPCB_PAIR_NAME = 5, + + LECPCB_VAL_TRUE = LECP_FLAG_CB_IS_VALUE | 6, + LECPCB_VAL_FALSE = LECP_FLAG_CB_IS_VALUE | 7, + LECPCB_VAL_NULL = LECP_FLAG_CB_IS_VALUE | 8, + LECPCB_VAL_NUM_INT = LECP_FLAG_CB_IS_VALUE | 9, + LECPCB_VAL_RESERVED = LECP_FLAG_CB_IS_VALUE | 10, + LECPCB_VAL_STR_START = 11, /* notice handle separately */ + LECPCB_VAL_STR_CHUNK = LECP_FLAG_CB_IS_VALUE | 12, + LECPCB_VAL_STR_END = LECP_FLAG_CB_IS_VALUE | 13, + + LECPCB_ARRAY_START = 14, + LECPCB_ARRAY_END = 15, + + LECPCB_OBJECT_START = 16, + LECPCB_OBJECT_END = 17, + + LECPCB_TAG_START = 18, + LECPCB_TAG_END = 19, + + LECPCB_VAL_NUM_UINT = LECP_FLAG_CB_IS_VALUE | 20, + LECPCB_VAL_UNDEFINED = LECP_FLAG_CB_IS_VALUE | 21, + LECPCB_VAL_FLOAT16 = LECP_FLAG_CB_IS_VALUE | 22, + LECPCB_VAL_FLOAT32 = LECP_FLAG_CB_IS_VALUE | 23, + LECPCB_VAL_FLOAT64 = LECP_FLAG_CB_IS_VALUE | 24, + + LECPCB_VAL_SIMPLE = LECP_FLAG_CB_IS_VALUE | 25, + + LECPCB_VAL_BLOB_START = 26, /* notice handle separately */ + LECPCB_VAL_BLOB_CHUNK = LECP_FLAG_CB_IS_VALUE | 27, + LECPCB_VAL_BLOB_END = LECP_FLAG_CB_IS_VALUE | 28, + + LECPCB_ARRAY_ITEM_START = 29, + LECPCB_ARRAY_ITEM_END = 30, + + LECPCB_LITERAL_CBOR = 31, +}; + +enum lecp_reasons { + LECP_CONTINUE = -1, + LECP_REJECT_BAD_CODING = -2, + LECP_REJECT_UNKNOWN = -3, + LECP_REJECT_CALLBACK = -4, + LECP_STACK_OVERFLOW = -5, +}; + + +struct lecp_item { + union { + uint64_t u64; + int64_t i64; + + uint64_t u32; + + uint16_t hf; +#if defined(LWS_WITH_CBOR_FLOAT) + float f; + double d; +#else + uint32_t f; + uint64_t d; +#endif + } u; + uint8_t opcode; +}; + +struct lecp_ctx; +typedef signed char (*lecp_callback)(struct lecp_ctx *ctx, char reason); + +struct _lecp_stack { + char s; /* lejp_state stack*/ + uint8_t p; /* path length */ + char i; /* index array length */ + char indet; /* indeterminite */ + char intermediate; /* in middle of string */ + + char pop_iss; + uint64_t tag; + uint64_t collect_rem; + uint32_t ordinal; + uint8_t opcode; + uint8_t send_new_array_item; + uint8_t barrier; +}; + +struct _lecp_parsing_stack { + void *user; /* private to the stack level */ + lecp_callback cb; + const char * const *paths; + uint8_t count_paths; + uint8_t ppos; + uint8_t path_match; +}; + +struct lecp_ctx { + + /* sorted by type for most compact alignment + * + * pointers + */ + void *user; + uint8_t *collect_tgt; + + /* arrays */ + + struct _lecp_parsing_stack pst[LECP_MAX_PARSING_STACK_DEPTH]; + struct _lecp_stack st[LECP_MAX_DEPTH]; + uint16_t i[LECP_MAX_INDEX_DEPTH]; /* index array */ + uint16_t wild[LECP_MAX_INDEX_DEPTH]; /* index array */ + char path[LECP_MAX_PATH]; + uint8_t cbor[64]; /* literal cbor capture */ + + struct lecp_item item; + + + /* size_t */ + + size_t path_stride; /* 0 means default ptr size, else + * stride... allows paths to be + * provided composed inside a + * larger user struct instead of a + * duplicated array */ + size_t used_in; /* bytes of input consumed */ + + /* short */ + + uint16_t uni; + + /* char */ + + uint8_t npos; + uint8_t dcount; + uint8_t f; + uint8_t sp; /* stack head */ + uint8_t ipos; /* index stack depth */ + uint8_t count_paths; + uint8_t path_match; + uint8_t path_match_len; + uint8_t wildcount; + uint8_t pst_sp; /* parsing stack head */ + uint8_t outer_array; + uint8_t cbor_pos; + uint8_t literal_cbor_report; + char present; /* temp for cb reason to use */ + + uint8_t be; /* big endian */ + + /* at end so we can memset the rest of it */ + + char buf[LECP_STRING_CHUNK + 1]; +}; + +struct lws_lec_pctx; +typedef struct lws_lec_pctx lws_lec_pctx_t; + +enum lws_lec_pctx_ret { + LWS_LECPCTX_RET_FINISHED = 0, + LWS_LECPCTX_RET_AGAIN, /* call again to continue writing buffer */ + LWS_LECPCTX_RET_FAIL /* something broken, eg, format string */ +}; + +enum cbp_state { + CBPS_IDLE, + CBPS_PC1, + CBPS_PC2, + CBPS_PC3, + + CBPS_STRING_BODY, + + CBPS_NUM_LIT, + + CBPS_STRING_LIT, + + CBPS_CONTYPE, +}; + +typedef struct lws_lec_pctx { + uint8_t stack[16]; + uint8_t vaa[16]; + uint8_t indet[16]; + uint8_t scratch[24]; + uint8_t *start; /* the beginning of the out buf */ + uint8_t *buf; /* cur pos in output buf */ + uint8_t *end; /* the end of the output buf */ + + const uint8_t *ongoing_src; + uint64_t ongoing_len; + uint64_t ongoing_done; + + struct lecp_item item; + + size_t used; /* number of bytes valid from start */ + + int opaque[4]; /* ignored by lws, caller may use */ + + enum cbp_state state; + unsigned int fmt_pos; + uint8_t sp; + uint8_t scratch_len; + uint8_t escflag; + uint8_t _long; + uint8_t vaa_pos; + uint8_t dotstar; +} lws_lec_pctx_t; + +LWS_VISIBLE LWS_EXTERN void +lws_lec_int(lws_lec_pctx_t *ctx, uint8_t opcode, uint8_t indet, uint64_t num); + +LWS_VISIBLE LWS_EXTERN int +lws_lec_scratch(lws_lec_pctx_t *ctx); + +/* + * lws_lec_init() - prepare a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param buf: the output buffer start + * \param len: the amount of the output buffer we can use + * + * Prepares a cbor writing context so that les_lec_printf can be used to + * write into it. + */ +LWS_VISIBLE LWS_EXTERN void +lws_lec_init(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len); + +/* + * lws_lec_setbuf() - update the output buffer for an initialized cbor writing ctx + * + * \param ctx: the cbor writing context to prepare + * \param buf: the output buffer start + * \param len: the amount of the output buffer we can use + * + * Leaves the cbor writing context state as it is, but resets the output buffer + * it writes into as given in \p buf and \p len + */ +LWS_VISIBLE LWS_EXTERN void +lws_lec_setbuf(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len); + +/* + * lws_lec_vsprintf() - write into a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param format: a printf style argument map + * \param args: the va args + * + * CBOR-aware vsprintf which pauses output when it fills the output buffer. You + * can call it again with the same args and same lws_lex_pctx to resume filling + * + * Returns either LWS_LECPCTX_RET_FINISHED if we have nothing left over that we + * want to put in the buffer, or LWS_LECPCTX_RET_AGAIN if the function should + * be called again with the same arguments (perhaps into a different output + * buffer) to continue emitting output from where it left off. + * + * If LWS_LECPCTX_RET_AGAIN is returned, lws_lec_setbuf() must be used on the + * context to reset or change the output buffer before calling again. + * + * The number of bytes placed in the output buffer is available in ctx->used. + * + * \p format is a printf-type format string that is specialized for CBOR + * generation. It understands the following specifiers + * + * |`123`||unsigned literal number| + * |`-123`||signed literal number| + * |`%u`|`unsigned int`|number| + * |`%lu`|`unsigned long int`|number| + * |`%llu`|`unsigned long long int`|number| + * |`%d`|`signed int`|number| + * |`%ld`|`signed long int`|number| + * |`%lld`|`signed long long int`|number| + * |`%f`|`double`|floating point number| + * |`123(...)`||literal tag and scope| + * |`%t(...)`|`unsigned int`|tag and scope| + * |`%lt(...)`|`unsigned long int`|tag and scope| + * |`%llt(...)`|`unsigned long long int`|tag and scope| + * |`[...]`||Array (fixed len if `]` in same format string)| + * |`{...}`||Map (fixed len if `}` in same format string)| + * |``||Container for indeterminite text string frags| + * |``||Container for indeterminite binary string frags| + * |`'string'`||Literal text of known length| + * |`%s`|`const char *`|NUL-terminated string| + * |`%.*s`|`int`, `const char *`|length-specified string| + * |`%.*b`|`int`, `const uint8_t *`|length-specified binary| + * |`:`||separator between Map items (a:b)| + * |`,`||separator between Map pairs or array items| + * + * See READMEs/README.cbor-lecp.md for more details. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_lec_vsprintf(lws_lec_pctx_t *ctx, const char *format, va_list args); + +/* + * lws_lec_printf() - write into a cbor writing context + * + * \param ctx: the cbor writing context to prepare + * \param format: a printf style argument map + * \param ...: format args + * + * See lws_lec_vsprintf() for format details. This is the most common way + * to format the CBOR output. + * + * See READMEs/README.cbor-lecp.md for more details. + */ +LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret +lws_lec_printf(lws_lec_pctx_t *ctx, const char *format, ...); + +/** + * lecp_construct() - Construct an LECP parser context + * + * \param ctx: the parser context object to be initialized + * \param cb: the user callback to receive the parsing events + * \param user: an opaque user pointer available at \p cb + * \param paths: an optional array of parsing paths + * \param paths_count: how many paths in \p paths + * + * Prepares an LECP parser context for parsing. + */ +LWS_VISIBLE LWS_EXTERN void +lecp_construct(struct lecp_ctx *ctx, lecp_callback cb, void *user, + const char * const *paths, unsigned char paths_count); + +/** + * lecp_destruct() - Destroys an LECP parser context + * + * \param ctx: the parser context object to be destroyed + */ +LWS_VISIBLE LWS_EXTERN void +lecp_destruct(struct lecp_ctx *ctx); + +/** + * lecp_parse() - parses a chunk of input CBOR + * + * \p ctx: the parsing context + * \p cbor: the start of the chunk of CBOR + * \p len: the number of bytes of CBOR available at \p cbor + * + * Returns LECP_CONTINUE if more input needed, one of enum lecp_reasons for a + * fatal error, else 0 for successful parsing completion. + * + * On success or _CONTINUE, ctx->used_in is set to the number of input bytes + * consumed. + */ +LWS_VISIBLE LWS_EXTERN int +lecp_parse(struct lecp_ctx *ctx, const uint8_t *cbor, size_t len); + +LWS_VISIBLE LWS_EXTERN void +lecp_change_callback(struct lecp_ctx *ctx, lecp_callback cb); + +LWS_VISIBLE LWS_EXTERN const char * +lecp_error_to_string(int e); + +/** + * lecp_parse_report_raw() - turn cbor raw reporting on and off + * + * \param ctx: the lecp context + * \param on: 0 to disable (defaults disabled), 1 to enable + * + * For cose_sign, it needs access to raw cbor subtrees for the hash input. + * This api causes LECPCB_LITERAL_CBOR parse callbacks when there are + * ctx->cbor_pos bytes of raw cbor available in ctx->cbor[]. the callbacks + * occur when the ctx->cbor[] buffer fills or if it holds anything when this + * spi is used to stop the reports. + * + * The same CBOR that is being captured continues to be passed for parsing. + */ +LWS_VISIBLE LWS_EXTERN void +lecp_parse_report_raw(struct lecp_ctx *ctx, int on); + +/** + * lecp_parse_map_is_key() - return nonzero if we're in a map and this is a key + * + * \param ctx: the lwcp context + * + * Checks if the current value is a key in a map, ie, that you are on a "key" in + * a list of "{key: value}" pairs. Zero means you're either not in a map or not + * on the key part, and nonzero means you are in a map and on a key part. + */ +LWS_VISIBLE LWS_EXTERN int +lecp_parse_map_is_key(struct lecp_ctx *ctx); + +LWS_VISIBLE LWS_EXTERN int +lecp_parse_subtree(struct lecp_ctx *ctx, const uint8_t *in, size_t len); + +/* + * Helpers for half-float + */ + +LWS_VISIBLE LWS_EXTERN void +lws_singles2halfp(uint16_t *hp, uint32_t x); + +LWS_VISIBLE LWS_EXTERN void +lws_halfp2singles(uint32_t *xp, uint16_t h); + +//@} diff --git a/thirdparty/include/libwebsockets/lws-led.h b/thirdparty/include/libwebsockets/lws-led.h new file mode 100755 index 0000000000000000000000000000000000000000..79e03432afcb8edab34bf6a5bf843195891d5b90 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-led.h @@ -0,0 +1,146 @@ +/* + * Generic LED controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for leds, a real implementation provides + * functions for the ops that use the underlying, eg, OS gpio arrangements. + */ + +/* only b15 significant for GPIO */ +typedef uint16_t lws_led_intensity_t; +typedef uint16_t lws_led_seq_phase_t; + +/* the normalized max intensity */ +#define LWS_LED_MAX_INTENSITY (0xffff) + +/* the normalized 360 degree phase count for intensity functions */ +#define LWS_LED_FUNC_PHASE 65536 +/* used when the sequence doesn't stop by itself and goes around forever */ +#define LWS_SEQ_LEDPHASE_TOTAL_ENDLESS (-1) + +#define LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS 33 + +struct lws_led_state; /* opaque */ +struct lws_pwm_ops; /* forward ref */ + +typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph); + +typedef struct lws_led_sequence_def_t { + lws_led_lookup_t func; + lws_led_seq_phase_t ledphase_offset; + int ledphase_total; /* 65536= one cycle */ + uint16_t ms; + uint8_t flags; +} lws_led_sequence_def_t; + +enum { + LLSI_CURR, + LLSI_NEXT, + LLSI_TRANS +}; + +typedef struct lws_led_state_ch +{ + const lws_led_sequence_def_t *seq; /* NULL = inactive */ + lws_led_seq_phase_t ph; + lws_led_seq_phase_t step; + int phase_budget; + lws_led_intensity_t last; + /**< at the end of the sequence we decouple the sequencer, but leave + * the last computed sample behind for further transitions to base off + */ +} lws_led_state_ch_t; + +typedef struct lws_led_state_chs +{ + lws_led_state_ch_t seqs[3]; +} lws_led_state_chs_t; + +/* this should always be first in the subclassed implementation types */ + +typedef struct lws_led_ops { + void (*intensity)(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten); + /**< for BOOL led control like GPIO, only inten b15 is significant */ + struct lws_led_state * (*create)(const struct lws_led_ops *led_ops); + void (*destroy)(struct lws_led_state *); +} lws_led_ops_t; + +typedef struct lws_led_gpio_map { + const char *name; + _lws_plat_gpio_t gpio; + lws_led_lookup_t intensity_correction; + /**< May be NULL. If GPIO-based LED, ignored. If pwm_ops provided, + * NULL means use default CIE 100% correction function. If non-NULL, + * use the pointed-to correction function. This is useful to provide + * LED-specific intensity correction / scaling so different types of + * LED can "look the same". */ + const struct lws_pwm_ops *pwm_ops; + /**< if NULL, gpio controls the led directly. If set to a pwm_ops, + * the led control is outsourced to the pwm controller. */ + uint8_t active_level; +} lws_led_gpio_map_t; + +typedef struct lws_led_gpio_controller { + const lws_led_ops_t led_ops; + + const lws_gpio_ops_t *gpio_ops; + const lws_led_gpio_map_t *led_map; + uint8_t count_leds; +} lws_led_gpio_controller_t; + +/* ops */ + +LWS_VISIBLE LWS_EXTERN struct lws_led_state * +lws_led_gpio_create(const lws_led_ops_t *led_ops); + +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_destroy(struct lws_led_state *lcs); + +/** + * lws_led_gpio_intensity() - set the static intensity of an led + * + * \param lo: the base class of the led controller + * \param index: which led in the controller set + * \param inten: 16-bit unsigned intensity + * + * For LEDs controlled by a BOOL like GPIO, only inten b15 is significant. + * For PWM type LED control, as many bits as the hardware can support from b15 + * down are significant. + */ +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten); + +LWS_VISIBLE LWS_EXTERN int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans); + + +#define lws_led_gpio_ops \ + { \ + .create = lws_led_gpio_create, \ + .destroy = lws_led_gpio_destroy, \ + .intensity = lws_led_gpio_intensity, \ + } + diff --git a/thirdparty/include/libwebsockets/lws-lejp.h b/thirdparty/include/libwebsockets/lws-lejp.h new file mode 100755 index 0000000000000000000000000000000000000000..f9f50270d7ea817144a9bc6bb5e4f3ced07a08e6 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-lejp.h @@ -0,0 +1,301 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup lejp JSON parser + * ##JSON parsing related functions + * \ingroup lwsapi + * + * LEJP is an extremely lightweight JSON stream parser included in lws. + */ +//@{ +struct lejp_ctx; + +#if !defined(LWS_ARRAY_SIZE) +#define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0])) +#endif +#define LEJP_FLAG_WS_KEEP 64 +#define LEJP_FLAG_WS_COMMENTLINE 32 + +enum lejp_states { + LEJP_IDLE = 0, + LEJP_MEMBERS = 1, + LEJP_M_P = 2, + LEJP_MP_STRING = LEJP_FLAG_WS_KEEP | 3, + LEJP_MP_STRING_ESC = LEJP_FLAG_WS_KEEP | 4, + LEJP_MP_STRING_ESC_U1 = LEJP_FLAG_WS_KEEP | 5, + LEJP_MP_STRING_ESC_U2 = LEJP_FLAG_WS_KEEP | 6, + LEJP_MP_STRING_ESC_U3 = LEJP_FLAG_WS_KEEP | 7, + LEJP_MP_STRING_ESC_U4 = LEJP_FLAG_WS_KEEP | 8, + LEJP_MP_DELIM = 9, + LEJP_MP_VALUE = 10, + LEJP_MP_VALUE_NUM_INT = LEJP_FLAG_WS_KEEP | 11, + LEJP_MP_VALUE_NUM_EXP = LEJP_FLAG_WS_KEEP | 12, + LEJP_MP_VALUE_TOK = LEJP_FLAG_WS_KEEP | 13, + LEJP_MP_COMMA_OR_END = 14, + LEJP_MP_ARRAY_END = 15, +}; + +enum lejp_reasons { + LEJP_CONTINUE = -1, + LEJP_REJECT_IDLE_NO_BRACE = -2, + LEJP_REJECT_MEMBERS_NO_CLOSE = -3, + LEJP_REJECT_MP_NO_OPEN_QUOTE = -4, + LEJP_REJECT_MP_STRING_UNDERRUN = -5, + LEJP_REJECT_MP_ILLEGAL_CTRL = -6, + LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC = -7, + LEJP_REJECT_ILLEGAL_HEX = -8, + LEJP_REJECT_MP_DELIM_MISSING_COLON = -9, + LEJP_REJECT_MP_DELIM_BAD_VALUE_START = -10, + LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC = -11, + LEJP_REJECT_MP_VAL_NUM_FORMAT = -12, + LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP = -13, + LEJP_REJECT_MP_VAL_TOK_UNKNOWN = -14, + LEJP_REJECT_MP_C_OR_E_UNDERF = -15, + LEJP_REJECT_MP_C_OR_E_NOTARRAY = -16, + LEJP_REJECT_MP_ARRAY_END_MISSING = -17, + LEJP_REJECT_STACK_OVERFLOW = -18, + LEJP_REJECT_MP_DELIM_ISTACK = -19, + LEJP_REJECT_NUM_TOO_LONG = -20, + LEJP_REJECT_MP_C_OR_E_NEITHER = -21, + LEJP_REJECT_UNKNOWN = -22, + LEJP_REJECT_CALLBACK = -23 +}; + +#define LEJP_FLAG_CB_IS_VALUE 64 + +enum lejp_callbacks { + LEJPCB_CONSTRUCTED = 0, + LEJPCB_DESTRUCTED = 1, + + LEJPCB_START = 2, + LEJPCB_COMPLETE = 3, + LEJPCB_FAILED = 4, + + LEJPCB_PAIR_NAME = 5, + + LEJPCB_VAL_TRUE = LEJP_FLAG_CB_IS_VALUE | 6, + LEJPCB_VAL_FALSE = LEJP_FLAG_CB_IS_VALUE | 7, + LEJPCB_VAL_NULL = LEJP_FLAG_CB_IS_VALUE | 8, + LEJPCB_VAL_NUM_INT = LEJP_FLAG_CB_IS_VALUE | 9, + LEJPCB_VAL_NUM_FLOAT = LEJP_FLAG_CB_IS_VALUE | 10, + LEJPCB_VAL_STR_START = 11, /* notice handle separately */ + LEJPCB_VAL_STR_CHUNK = LEJP_FLAG_CB_IS_VALUE | 12, + LEJPCB_VAL_STR_END = LEJP_FLAG_CB_IS_VALUE | 13, + + LEJPCB_ARRAY_START = 14, + LEJPCB_ARRAY_END = 15, + + LEJPCB_OBJECT_START = 16, + LEJPCB_OBJECT_END = 17, +}; + +/** + * _lejp_callback() - User parser actions + * \param ctx: LEJP context + * \param reason: Callback reason + * + * Your user callback is associated with the context at construction time, + * and receives calls as the parsing progresses. + * + * All of the callbacks may be ignored and just return 0. + * + * The reasons it might get called, found in @reason, are: + * + * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to + * perform one-time allocation for the life of the context. + * + * LEJPCB_DESTRUCTED: The context is being destructed... if you made any + * allocations at construction-time, you can free them now + * + * LEJPCB_START: Parsing is beginning at the first byte of input + * + * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or + * positive return code from lejp_parse indicating the + * amount of unused bytes left in the input buffer + * + * LEJPCB_FAILED: Parsing failed. You'll get a negative error code + * returned from lejp_parse + * + * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed, + * this callback occurs. You can find the new name at + * the end of ctx->path[] + * + * LEJPCB_VAL_TRUE: The "true" value appeared + * + * LEJPCB_VAL_FALSE: The "false" value appeared + * + * LEJPCB_VAL_NULL: The "null" value appeared + * + * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf + * + * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf + * + * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet + * + * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not + * the end of the string. We produce this to spill the + * intermediate buffer to the user code, so we can handle + * huge JSON strings using only the small buffer in the + * ctx. If the whole JSON string fits in the ctx buffer, + * you won't get these callbacks. + * + * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the + * string is in ctx->buf. + * + * LEJPCB_ARRAY_START: An array started + * + * LEJPCB_ARRAY_END: An array ended + * + * LEJPCB_OBJECT_START: An object started + * + * LEJPCB_OBJECT_END: An object ended + */ +LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason); + +typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason); + +#ifndef LEJP_MAX_PARSING_STACK_DEPTH +#define LEJP_MAX_PARSING_STACK_DEPTH 5 +#endif +#ifndef LEJP_MAX_DEPTH +#define LEJP_MAX_DEPTH 12 +#endif +#ifndef LEJP_MAX_INDEX_DEPTH +#define LEJP_MAX_INDEX_DEPTH 8 +#endif +#ifndef LEJP_MAX_PATH +#define LEJP_MAX_PATH 128 +#endif +#ifndef LEJP_STRING_CHUNK +/* must be >= 30 to assemble floats */ +#define LEJP_STRING_CHUNK 254 +#endif + +enum num_flags { + LEJP_SEEN_MINUS = (1 << 0), + LEJP_SEEN_POINT = (1 << 1), + LEJP_SEEN_POST_POINT = (1 << 2), + LEJP_SEEN_EXP = (1 << 3) +}; + +struct _lejp_stack { + char s; /* lejp_state stack*/ + char p; /* path length */ + char i; /* index array length */ + char b; /* user bitfield */ +}; + +struct _lejp_parsing_stack { + void *user; /* private to the stack level */ + signed char (*callback)(struct lejp_ctx *ctx, char reason); + const char * const *paths; + uint8_t count_paths; + uint8_t ppos; + uint8_t path_match; +}; + +struct lejp_ctx { + + /* sorted by type for most compact alignment + * + * pointers + */ + void *user; + + /* arrays */ + + struct _lejp_parsing_stack pst[LEJP_MAX_PARSING_STACK_DEPTH]; + struct _lejp_stack st[LEJP_MAX_DEPTH]; + uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */ + uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */ + char path[LEJP_MAX_PATH]; + char buf[LEJP_STRING_CHUNK + 1]; + + /* size_t */ + + size_t path_stride; /* 0 means default ptr size, else stride */ + + /* int */ + + uint32_t line; + + /* short */ + + uint16_t uni; + + /* char */ + + uint8_t npos; + uint8_t dcount; + uint8_t f; + uint8_t sp; /* stack head */ + uint8_t ipos; /* index stack depth */ + uint8_t count_paths; + uint8_t path_match; + uint8_t path_match_len; + uint8_t wildcount; + uint8_t pst_sp; /* parsing stack head */ + uint8_t outer_array; +}; + +LWS_VISIBLE LWS_EXTERN void +lejp_construct(struct lejp_ctx *ctx, + signed char (*callback)(struct lejp_ctx *ctx, char reason), + void *user, const char * const *paths, unsigned char paths_count); + +LWS_VISIBLE LWS_EXTERN void +lejp_destruct(struct lejp_ctx *ctx); + +LWS_VISIBLE LWS_EXTERN int +lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len); + +LWS_VISIBLE LWS_EXTERN void +lejp_change_callback(struct lejp_ctx *ctx, + signed char (*callback)(struct lejp_ctx *ctx, char reason)); + +/* + * push the current paths / paths_count and lejp_cb to a stack in the ctx, and + * start using the new ones + */ +LWS_VISIBLE LWS_EXTERN int +lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths, + unsigned char paths_count, lejp_callback lejp_cb); + +/* + * pop the previously used paths / paths_count and lejp_cb, and continue + * parsing using those as before + */ +LWS_VISIBLE LWS_EXTERN int +lejp_parser_pop(struct lejp_ctx *ctx); + +/* exported for use when reevaluating a path for use with a subcontext */ +LWS_VISIBLE LWS_EXTERN void +lejp_check_path_match(struct lejp_ctx *ctx); + +LWS_VISIBLE LWS_EXTERN int +lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len); + +LWS_VISIBLE LWS_EXTERN const char * +lejp_error_to_string(int e); +//@} diff --git a/thirdparty/include/libwebsockets/lws-logs.h b/thirdparty/include/libwebsockets/lws-logs.h new file mode 100755 index 0000000000000000000000000000000000000000..3f21b81009263600489bb43ffa85540527937576 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-logs.h @@ -0,0 +1,786 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/** \defgroup log Logging + * + * ##Logging + * + * Lws provides flexible and filterable logging facilities, which can be + * used inside lws and in user code. + * + * Log categories may be individually filtered bitwise, and directed to built-in + * sinks for syslog-compatible logging, or a user-defined function. + * + * Traditional logs use a single, processwide logging context. New style log + * apis (lws_xxx_cx()) can pass the logging context to use in. + */ +///@{ + +#define LLL_ERR (1 << 0) +#define LLL_WARN (1 << 1) +#define LLL_NOTICE (1 << 2) +#define LLL_INFO (1 << 3) +#define LLL_DEBUG (1 << 4) +#define LLL_PARSER (1 << 5) +#define LLL_HEADER (1 << 6) +#define LLL_EXT (1 << 7) +#define LLL_CLIENT (1 << 8) +#define LLL_LATENCY (1 << 9) +#define LLL_USER (1 << 10) +#define LLL_THREAD (1 << 11) + +#define LLL_COUNT (12) /* set to count of valid flags */ + +#define LLLF_SECRECY_PII (1 << 16) + /**< contains Personally Identifiable Information */ +#define LLLF_SECRECY_BEARER (1 << 17) + /**< possession of this data allows impersonation */ + +#define LLLF_LOG_TIMESTAMP (1 << 18) + /**< set to prepend logs with timestamp */ + +#define LLLF_LOG_CONTEXT_AWARE (1 << 30) +/**< set if the context uses an emit function that takes the logctx, auto- + * applied when setting emit using lws_set_log_level_cx() api */ + +struct lws_log_cx; + +typedef void (*lws_log_emit_t)(int level, const char *line); +typedef void (*lws_log_emit_cx_t)(struct lws_log_cx *cx, int level, + const char *line, size_t len); +typedef void (*lws_log_prepend_cx_t)(struct lws_log_cx *cx, void *obj, + char **p, char *e); +typedef void (*lws_log_use_cx_t)(struct lws_log_cx *cx, int _new); + +/* + * This is the logging context + */ + +typedef struct lws_log_cx { + union { + lws_log_emit_t emit; /* legacy emit function */ + lws_log_emit_cx_t emit_cx; /* LLLF_LOG_CONTEXT_AWARE */ + } u; + lws_log_use_cx_t refcount_cb; + /**< NULL, or a function called after each change to .refcount below, + * this enables implementing side-effects like opening and closing + * log files when the first and last object binds / unbinds */ + lws_log_prepend_cx_t prepend; + /**< NULL, or a cb to optionally prepend a string to logs we are a + * parent of */ + struct lws_log_cx *parent; + /**< NULL, or points to log ctx we are a child of */ + void *opaque; + /**< ignored by lws, used to pass config to emit_cx, eg, filepath */ + void *stg; + /**< ignored by lws, may be used a storage by refcount_cb / emit_cx */ + uint32_t lll_flags; + /**< mask of log levels we want to emit in this context */ + int32_t refcount; + /**< refcount of objects bound to this log context */ +} lws_log_cx_t; + +/** + * lwsl_timestamp: generate logging timestamp string + * + * \param level: logging level + * \param p: char * buffer to take timestamp + * \param len: length of p + * + * returns length written in p + */ +LWS_VISIBLE LWS_EXTERN int +lwsl_timestamp(int level, char *p, size_t len); + +#if defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK) +#define _lws_log(aaa, ...) SMSG(__VA_ARGS__) +#else +LWS_VISIBLE LWS_EXTERN void +_lws_log(int filter, const char *format, ...) LWS_FORMAT(2); +LWS_VISIBLE LWS_EXTERN void +_lws_logv(int filter, const char *format, va_list vl); +#endif + +struct lws_vhost; +struct lws; + +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_context_get_cx(struct lws_context *cx); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_vhost_get_cx(struct lws_vhost *vh); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_wsi_get_cx(struct lws *wsi); +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_ss_handle; +struct lws_sspc_handle; +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_ss_get_cx(struct lws_ss_handle *ss); +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_sspc_get_cx(struct lws_sspc_handle *ss); +#endif + +LWS_VISIBLE LWS_EXTERN void +lws_log_emit_cx_file(struct lws_log_cx *cx, int level, const char *line, + size_t len); + +LWS_VISIBLE LWS_EXTERN void +lws_log_use_cx_file(struct lws_log_cx *cx, int _new); + +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_vhost(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e); +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_ss(struct lws_log_cx *cx, void *obj, char **p, char *e); +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e); +#endif + +LWS_VISIBLE LWS_EXTERN void +_lws_log_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int filter, const char *_fun, const char *format, ...) LWS_FORMAT(6); + +#define lwsl_cx(_c, _fil, ...) \ + _lws_log_cx(lwsl_context_get_cx(_c), lws_log_prepend_context, \ + _c, _fil, __func__, __VA_ARGS__) +#define lwsl_vhost(_v, _fil, ...) \ + _lws_log_cx(lwsl_vhost_get_cx(_v), lws_log_prepend_vhost, _v, \ + _fil, __func__, __VA_ARGS__) +#define lwsl_wsi(_w, _fil, ...) \ + _lws_log_cx(lwsl_wsi_get_cx(_w), lws_log_prepend_wsi, _w, \ + _fil, __func__, __VA_ARGS__) +#define lwsl_ss(_h, _fil, ...) \ + _lws_log_cx(lwsl_ss_get_cx(_h), lws_log_prepend_ss, _h, \ + _fil, __func__, __VA_ARGS__) + +#define lwsl_hexdump_context(_c, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_context_get_cx(_c), \ + lws_log_prepend_context, \ + _c, _fil, _buf, _len) +#define lwsl_hexdump_vhost(_v, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_vhost_get_cx(_v), \ + lws_log_prepend_vhost, \ + _v, _fil, _buf, _len) +#define lwsl_hexdump_wsi(_w, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_wsi_get_cx(_w), \ + lws_log_prepend_wsi, \ + _w, _fil, _buf, _len) +#define lwsl_hexdump_ss(_h, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_ss_get_cx(_h), \ + lws_log_prepend_ss, \ + _h, _fil, _buf, _len) + +/* + * Figure out which logs to build in or not + */ + +#if defined(_DEBUG) + /* + * In DEBUG build, select all logs unless NO_LOGS + */ + #if defined(LWS_WITH_NO_LOGS) + #define _LWS_LINIT (LLL_ERR | LLL_USER) + #else + #define _LWS_LINIT ((1 << LLL_COUNT) - 1) + #endif +#else /* not _DEBUG */ +#if defined(LWS_WITH_NO_LOGS) +#define _LWS_LINIT (LLL_ERR | LLL_USER) +#else + #define _LWS_LINIT (LLL_ERR | LLL_USER | LLL_WARN | LLL_NOTICE) +#endif +#endif /* _DEBUG */ + +/* + * Create either empty overrides or the ones forced at build-time. + * These overrides have the final say... any bits set in + * LWS_LOGGING_BITFIELD_SET force the build of those logs, any bits + * set in LWS_LOGGING_BITFIELD_CLEAR disable the build of those logs. + * + * If not defined lws decides based on CMAKE_BUILD_TYPE=DEBUG or not + */ + +#if defined(LWS_LOGGING_BITFIELD_SET) + #define _LWS_LBS (LWS_LOGGING_BITFIELD_SET) +#else + #define _LWS_LBS 0 +#endif + +#if defined(LWS_LOGGING_BITFIELD_CLEAR) + #define _LWS_LBC (LWS_LOGGING_BITFIELD_CLEAR) +#else + #define _LWS_LBC 0 +#endif + +/* + * Compute the final active logging bitfield for build + */ +#define _LWS_ENABLED_LOGS (((_LWS_LINIT) | (_LWS_LBS)) & ~(_LWS_LBC)) + +/* + * Individually enable or disable log levels for build + * depending on what was computed + */ + +/* + * Process scope logs + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__) +#else +#define lwsl_err(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__) +#else +#define lwsl_warn(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_notice(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__) +#else +#define lwsl_info(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_debug(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_parser(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_header(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__) +#else +#define lwsl_ext(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_client(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_latency(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_thread(...) _lws_log(LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_thread(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__) +#else +#define lwsl_user(...) do {} while(0) +#endif + +#define lwsl_hexdump_err(...) lwsl_hexdump_level(LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_warn(...) lwsl_hexdump_level(LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_notice(...) lwsl_hexdump_level(LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_info(...) lwsl_hexdump_level(LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_debug(...) lwsl_hexdump_level(LLL_DEBUG, __VA_ARGS__) + +/* + * lws_context scope logs + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_cx_err(_c, ...) lwsl_cx(_c, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_cx_err(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_cx_warn(_c, ...) lwsl_cx(_c, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_cx_warn(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_cx_notice(_c, ...) lwsl_cx(_c, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_cx_notice(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_cx_info(_c, ...) lwsl_cx(_c, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_cx_info(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_cx_debug(_c, ...) lwsl_cx(_c, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_cx_debug(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_cx_parser(_c, ...) lwsl_cx(_c, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_cx_parser(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_cx_header(_c, ...) lwsl_cx(_c, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_cx_header(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_cx_ext(_c, ...) lwsl_cx(_c, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_cx_ext(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_cx_client(_c, ...) lwsl_cx(_c, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_cx_client(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_cx_latency(_c, ...) lwsl_cx(_c, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_cx_latency(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_cx_thread(_c, ...) lwsl_cx(_c, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_cx_thread(_c, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_cx_user(_c, ...) lwsl_cx(_c, LLL_USER, __VA_ARGS__) +#else +#define lwsl_cx_user(_c, ...) do {} while(0) +#endif + +#define lwsl_hexdump_cx_err(_c, ...) lwsl_hexdump_context(_c, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_cx_warn(_c, ...) lwsl_hexdump_context(_c, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_cx_notice(_c, ...) lwsl_hexdump_context(_c, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_cx_info(_c, ...) lwsl_hexdump_context(_c, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_cx_debug(_c, ...) lwsl_hexdump_context(_c, LLL_DEBUG, __VA_ARGS__) + +/* + * lws_vhost + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_vhost_err(_v, ...) lwsl_vhost(_v, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_vhost_err(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_vhost_warn(_v, ...) lwsl_vhost(_v, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_vhost_warn(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_vhost_notice(_v, ...) lwsl_vhost(_v, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_vhost_notice(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_vhost_info(_v, ...) lwsl_vhost(_v, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_vhost_info(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_vhost_debug(_v, ...) lwsl_vhost(_v, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_vhost_debug(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_vhost_parser(_v, ...) lwsl_vhost(_v, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_vhost_parser(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_vhost_header(_v, ...) lwsl_vhost(_v, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_vhost_header(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_vhost_ext(_v, ...) lwsl_vhost(_v, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_vhost_ext(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_vhost_client(_v, ...) lwsl_vhost(_v, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_vhost_client(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_vhost_latency(_v, ...) lwsl_vhost(_v, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_vhost_latency(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_vhost_thread(_v, ...) lwsl_vhost(_v, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_vhost_thread(_v, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_vhost_user(_v, ...) lwsl_vhost(_v, LLL_USER, __VA_ARGS__) +#else +#define lwsl_vhost_user(_v, ...) do {} while(0) +#endif + +#define lwsl_hexdump_vhost_err(_v, ...) lwsl_hexdump_vhost(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_vhost_warn(_v, ...) lwsl_hexdump_vhost(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_vhost_notice(_v, ...) lwsl_hexdump_vhost(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_vhost_info(_v, ...) lwsl_hexdump_vhost(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_vhost_debug(_v, ...) lwsl_hexdump_vhost(_v, LLL_DEBUG, __VA_ARGS__) + + +/* + * lws_wsi + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_wsi_err(_w, ...) lwsl_wsi(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_wsi_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_wsi_warn(_w, ...) lwsl_wsi(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_wsi_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_wsi_notice(_w, ...) lwsl_wsi(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_wsi_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_wsi_info(_w, ...) lwsl_wsi(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_wsi_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_wsi_debug(_w, ...) lwsl_wsi(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_wsi_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_wsi_parser(_w, ...) lwsl_wsi(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_wsi_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_wsi_header(_w, ...) lwsl_wsi(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_wsi_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_wsi_ext(_w, ...) lwsl_wsi(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_wsi_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_wsi_client(_w, ...) lwsl_wsi(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_wsi_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_wsi_latency(_w, ...) lwsl_wsi(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_wsi_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_wsi_thread(_w, ...) lwsl_wsi(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_wsi_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_wsi_user(_w, ...) lwsl_wsi(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_wsi_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_wsi_err(_v, ...) lwsl_hexdump_wsi(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_wsi_warn(_v, ...) lwsl_hexdump_wsi(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_wsi_notice(_v, ...) lwsl_hexdump_wsi(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_wsi_info(_v, ...) lwsl_hexdump_wsi(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_wsi_debug(_v, ...) lwsl_hexdump_wsi(_v, LLL_DEBUG, __VA_ARGS__) + + +/* + * lwsl_ss + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_ss_err(_w, ...) lwsl_ss(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_ss_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_ss_warn(_w, ...) lwsl_ss(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_ss_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_ss_notice(_w, ...) lwsl_ss(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_ss_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_ss_info(_w, ...) lwsl_ss(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_ss_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_ss_debug(_w, ...) lwsl_ss(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_ss_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_ss_parser(_w, ...) lwsl_ss(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_ss_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_ss_header(_w, ...) lwsl_ss(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_ss_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_ss_ext(_w, ...) lwsl_ss(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_ss_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_ss_client(_w, ...) lwsl_ss(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_ss_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_ss_latency(_w, ...) lwsl_ss(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_ss_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_ss_thread(_w, ...) lwsl_ss(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_ss_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_ss_user(_w, ...) lwsl_ss(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_ss_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_ss_err(_v, ...) lwsl_hexdump_ss(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_ss_warn(_v, ...) lwsl_hexdump_ss(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_ss_notice(_v, ...) lwsl_hexdump_ss(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_ss_info(_v, ...) lwsl_hexdump_ss(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_ss_debug(_v, ...) lwsl_hexdump_ss(_v, LLL_DEBUG, __VA_ARGS__) + + + +/** + * lwsl_hexdump_level() - helper to hexdump a buffer at a selected debug level + * + * \param level: one of LLL_ constants + * \param vbuf: buffer start to dump + * \param len: length of buffer to dump + * + * If \p level is visible, does a nice hexdump -C style dump of \p vbuf for + * \p len bytes. This can be extremely convenient while debugging. + */ +LWS_VISIBLE LWS_EXTERN void +lwsl_hexdump_level(int level, const void *vbuf, size_t len); + +LWS_VISIBLE LWS_EXTERN void +lwsl_hexdump_level_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj, + int hexdump_level, const void *vbuf, size_t len); + +/** + * lwsl_hexdump() - helper to hexdump a buffer (DEBUG builds only) + * + * \param buf: buffer start to dump + * \param len: length of buffer to dump + * + * Calls through to lwsl_hexdump_level(LLL_DEBUG, ... for compatability. + * It's better to use lwsl_hexdump_level(level, ... directly so you can control + * the visibility. + */ +LWS_VISIBLE LWS_EXTERN void +lwsl_hexdump(const void *buf, size_t len); + +/** + * lws_is_be() - returns nonzero if the platform is Big Endian + */ +static LWS_INLINE int lws_is_be(void) { + const int probe = ~0xff; + + return *(const char *)&probe; +} + +/** + * lws_set_log_level() - Set the logging bitfield + * \param level: OR together the LLL_ debug contexts you want output from + * \param log_emit_function: NULL to leave it as it is, or a user-supplied + * function to perform log string emission instead of + * the default stderr one. + * + * log level defaults to "err", "warn" and "notice" contexts enabled and + * emission on stderr. If stderr is a tty (according to isatty()) then + * the output is coloured according to the log level using ANSI escapes. + * + * You can set the default security level for logging using the + * secrecy_and_log_level() macro to set the \p level parameter, eg + * + * lws_set_log_level(secrecy_and_log_level(LWS_SECRECY_PII, LLL_ERR | LLL_WARN), + * my_emit_function); + * + * Normally you can just leave it at the default. + */ +LWS_VISIBLE LWS_EXTERN void +lws_set_log_level(int level, lws_log_emit_t log_emit_function); + +/** + * lwsl_emit_syslog() - helper log emit function writes to system log + * + * \param level: one of LLL_ log level indexes + * \param line: log string + * + * You use this by passing the function pointer to lws_set_log_level(), to set + * it as the log emit function, it is not called directly. + */ +LWS_VISIBLE LWS_EXTERN void +lwsl_emit_syslog(int level, const char *line); + +/** + * lwsl_emit_stderr() - helper log emit function writes to stderr + * + * \param level: one of LLL_ log level indexes + * \param line: log string + * + * You use this by passing the function pointer to lws_set_log_level(), to set + * it as the log emit function, it is not called directly. + * + * It prepends a system timestamp like [2018/11/13 07:41:57:3989] + * + * If stderr is a tty, then ansi colour codes are added. + */ +LWS_VISIBLE LWS_EXTERN void +lwsl_emit_stderr(int level, const char *line); + +/** + * lwsl_emit_stderr_notimestamp() - helper log emit function writes to stderr + * + * \param level: one of LLL_ log level indexes + * \param line: log string + * + * You use this by passing the function pointer to lws_set_log_level(), to set + * it as the log emit function, it is not called directly. + * + * If stderr is a tty, then ansi colour codes are added. + */ +LWS_VISIBLE LWS_EXTERN void +lwsl_emit_stderr_notimestamp(int level, const char *line); + +/** + * lwsl_visible() - returns true if the log level should be printed + * + * \param level: one of LLL_ log level indexes + * + * This is useful if you have to do work to generate the log content, you + * can skip the work if the log level used to print it is not actually + * enabled at runtime. + */ +LWS_VISIBLE LWS_EXTERN int +lwsl_visible(int level); + +struct lws; + +LWS_VISIBLE LWS_EXTERN const char * +lws_wsi_tag(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +lwsl_refcount_cx(lws_log_cx_t *cx, int _new); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-lwsac.h b/thirdparty/include/libwebsockets/lws-lwsac.h new file mode 100755 index 0000000000000000000000000000000000000000..229503985163f305a65aa888d21f6f286f8bf298 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-lwsac.h @@ -0,0 +1,290 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/** \defgroup lwsac lwsac + * + * ##Allocated Chunks + * + * If you know you will be allocating a large, unknown number of same or + * differently sized objects, it's certainly possible to do it with libc + * malloc. However the allocation cost in time and memory overhead can + * add up, and deallocation means walking the structure of every object and + * freeing them in turn. + * + * lwsac (LWS Allocated Chunks) allocates chunks intended to be larger + * than your objects (4000 bytes by default) which you linearly allocate from + * using lwsac_use(). + * + * If your next request won't fit in the current chunk, a new chunk is added + * to the chain of chunks and the allocaton done from there. If the request + * is larger than the chunk size, an oversize chunk is created to satisfy it. + * + * When you are finished with the allocations, you call lwsac_free() and + * free all the *chunks*. So you may have thousands of objects in the chunks, + * but they are all destroyed with the chunks without having to deallocate them + * one by one pointlessly. + */ +///@{ + +struct lwsac; +typedef unsigned char * lwsac_cached_file_t; + + +#define lws_list_ptr_container(P,T,M) ((T *)((char *)(P) - offsetof(T, M))) + +/* + * linked-list helper that's commonly useful to manage lists of things + * allocated using lwsac. + * + * These lists point to their corresponding "next" member in the target, NOT + * the original containing struct. To get the containing struct, you must use + * lws_list_ptr_container() to convert. + * + * It's like that because it means we no longer have to have the next pointer + * at the start of the struct, and we can have the same struct on multiple + * linked-lists with everything held in the struct itself. + */ +typedef void * lws_list_ptr; + +/* + * optional sorting callback called by lws_list_ptr_insert() to sort the right + * things inside the opqaue struct being sorted / inserted on the list. + */ +typedef int (*lws_list_ptr_sort_func_t)(lws_list_ptr a, lws_list_ptr b); + +#define lws_list_ptr_advance(_lp) _lp = *((void **)_lp) + +/* sort may be NULL if you don't care about order */ +LWS_VISIBLE LWS_EXTERN void +lws_list_ptr_insert(lws_list_ptr *phead, lws_list_ptr *add, + lws_list_ptr_sort_func_t sort); + + +/** + * lwsac_use - allocate / use some memory from a lwsac + * + * \param head: pointer to the lwsac list object + * \param ensure: the number of bytes we want to use + * \param chunk_size: 0, or the size of the chunk to (over)allocate if + * what we want won't fit in the current tail chunk. If + * 0, the default value of 4000 is used. If ensure is + * larger, it is used instead. + * + * This also serves to init the lwsac if *head is NULL. Basically it does + * whatever is necessary to return you a pointer to ensure bytes of memory + * reserved for the caller. + * + * This always allocates in the current chunk or a new chunk... see the + * lwsac_use_backfill() variant to try first to find space in earlier chunks. + * + * Returns NULL if OOM. + */ +LWS_VISIBLE LWS_EXTERN void * +lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size); + +/** + * lwsac_use_backfill - allocate / use some memory from a lwsac + * + * \param head: pointer to the lwsac list object + * \param ensure: the number of bytes we want to use + * \param chunk_size: 0, or the size of the chunk to (over)allocate if + * what we want won't fit in the current tail chunk. If + * 0, the default value of 4000 is used. If ensure is + * larger, it is used instead. + * + * This also serves to init the lwsac if *head is NULL. Basically it does + * whatever is necessary to return you a pointer to ensure bytes of memory + * reserved for the caller. + * + * Also checks if earlier blocks have enough remaining space to take the + * allocation before making a new allocation. + * + * Returns NULL if OOM. + */ +LWS_VISIBLE LWS_EXTERN void * +lwsac_use_backfill(struct lwsac **head, size_t ensure, size_t chunk_size); + +/** + * lwsac_use - allocate / use some memory from a lwsac + * + * \param head: pointer to the lwsac list object + * \param ensure: the number of bytes we want to use, which must be zeroed + * \param chunk_size: 0, or the size of the chunk to (over)allocate if + * what we want won't fit in the current tail chunk. If + * 0, the default value of 4000 is used. If ensure is + * larger, it is used instead. + * + * Same as lwsac_use(), but \p ensure bytes of memory at the return address + * are zero'd before returning. + * + * Returns NULL if OOM. + */ +LWS_VISIBLE LWS_EXTERN void * +lwsac_use_zero(struct lwsac **head, size_t ensure, size_t chunk_size); + +#define lwsac_use_zeroed lwsac_use_zero + +/** + * lwsac_free - deallocate all chunks in the lwsac and set head NULL + * + * \param head: pointer to the lwsac list object + * + * This deallocates all chunks in the lwsac, then sets *head to NULL. All + * lwsac_use() pointers are invalidated in one hit without individual frees. + */ +LWS_VISIBLE LWS_EXTERN void +lwsac_free(struct lwsac **head); + +/* + * Optional helpers useful for where consumers may need to defer destruction + * until all consumers are finished with the lwsac + */ + +/** + * lwsac_detach() - destroy an lwsac unless somebody else is referencing it + * + * \param head: pointer to the lwsac list object + * + * The creator of the lwsac can all this instead of lwsac_free() when it itself + * has finished with the lwsac, but other code may be consuming it. + * + * If there are no other references, the lwsac is destroyed, *head is set to + * NULL and that's the end; however if something else has called + * lwsac_reference() on the lwsac, it simply returns. When lws_unreference() + * is called and no references are left, it will be destroyed then. + */ +LWS_VISIBLE LWS_EXTERN void +lwsac_detach(struct lwsac **head); + +/** + * lwsac_reference() - increase the lwsac reference count + * + * \param head: pointer to the lwsac list object + * + * Increment the reference count on the lwsac to defer destruction. + */ +LWS_VISIBLE LWS_EXTERN void +lwsac_reference(struct lwsac *head); + +/** + * lwsac_unreference() - decrease the lwsac reference count + * + * \param head: pointer to the lwsac list object + * + * Decrement the reference count on the lwsac... if it reached 0 on a detached + * lwsac then the lwsac is immediately destroyed and *head set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lwsac_unreference(struct lwsac **head); + +/** + * lwsac_extend() - try to increase the size of the last block + * + * \param head: pointer to the lwsac list object + * \param amount: amount to try to increase usage for + * + * This will either increase the usage reservation of the last allocated block + * by amount and return 0, or fail and return 1. + * + * This is very cheap to call and is designed to optimize usage after a static + * struct for vari-sized additional content which may flow into an additional + * block in a new chunk if necessary, but wants to make the most of the space + * in front of it first to try to avoid gaps and the new chunk if it can. + * + * The additional area if the call succeeds will have been memset to 0. + * + * To use it, the following must be true: + * + * - only the last lwsac use can be extended + * + * - if another use happens inbetween the use and extend, it will break + * + * - the use cannot have been using backfill + * + * - a user object must be tracking the current allocated size of the last use + * (lwsac doesn't know it) and increment by amount if the extend call succeeds + * + * Despite these restrictions this can be an important optimization for some + * cases + */ +LWS_VISIBLE LWS_EXTERN int +lwsac_extend(struct lwsac *head, size_t amount); + +/* helpers to keep a file cached in memory */ + +LWS_VISIBLE LWS_EXTERN void +lwsac_use_cached_file_start(lwsac_cached_file_t cache); + +LWS_VISIBLE LWS_EXTERN void +lwsac_use_cached_file_end(lwsac_cached_file_t *cache); + +LWS_VISIBLE LWS_EXTERN void +lwsac_use_cached_file_detach(lwsac_cached_file_t *cache); + +LWS_VISIBLE LWS_EXTERN int +lwsac_cached_file(const char *filepath, lwsac_cached_file_t *cache, + size_t *len); + +/* more advanced helpers */ + +/* offset from lac to start of payload, first = 1 = first lac in chain */ +LWS_VISIBLE LWS_EXTERN size_t +lwsac_sizeof(int first); + +LWS_VISIBLE LWS_EXTERN size_t +lwsac_get_tail_pos(struct lwsac *lac); + +LWS_VISIBLE LWS_EXTERN struct lwsac * +lwsac_get_next(struct lwsac *lac); + +LWS_VISIBLE LWS_EXTERN size_t +lwsac_align(size_t length); + +LWS_VISIBLE LWS_EXTERN void +lwsac_info(struct lwsac *head); + +LWS_VISIBLE LWS_EXTERN uint64_t +lwsac_total_alloc(struct lwsac *head); + +LWS_VISIBLE LWS_EXTERN uint64_t +lwsac_total_overhead(struct lwsac *head); + +/** + * lwsac_scan_extant() - returns existing copy of blob, or NULL + * + * \param head: the lwsac to scan + * \param find: the blob to look for + * \param len: the length of the blob to look for + * \param nul: nonzero if the next byte must be NUL + * + * Helper that looks through a whole lwsac for a given binary blob already + * present. Used in the case that lwsac contents are const once written, and + * strings or blobs may be repeated in the input: this allows the earlier + * copy to be pointed to by subsequent references without repeating the string + * or blob redundantly. + */ +LWS_VISIBLE LWS_EXTERN uint8_t * +lwsac_scan_extant(struct lwsac *head, uint8_t *find, size_t len, int nul); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-map.h b/thirdparty/include/libwebsockets/lws-map.h new file mode 100755 index 0000000000000000000000000000000000000000..4462881be44cba14471f5c50f9e3a4ca2cb5b89d --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-map.h @@ -0,0 +1,188 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/** \defgroup lws_map generic map apis + * ##Generic map structures and apis + * \ingroup lwsapi + * + * lws_map + * + * Discrete owner object represents the whole map, created with key-specific + * ops for hashing the key to a uint32_t and comparing two keys. Owns a list + * of hash tables whose size / modulo it set at creation time. + * + * Items in the map are contained in a lws_map_item_t that is indexed in a + * hash table. + * + * It's difficult to make a single compact map abstraction that fits all cases, + * this is useful to the extent you have the memory to trade off the number of + * hashtables needed for the amount of items and the lookup latency limit for + * your application, typically for hundreds or low thousands of items. + */ +//@{ + +typedef struct lws_map lws_map_t; +typedef struct lws_map_item lws_map_item_t; + +typedef void * lws_map_key_t; +typedef void * lws_map_value_t; +typedef uint32_t lws_map_hash_t; + +typedef lws_map_hash_t (*lws_map_hash_from_key_t)(const lws_map_key_t key, + size_t kl); +typedef int (*lws_map_compare_key_t)(const lws_map_key_t key1, size_t kl1, + const lws_map_value_t key2, size_t kl2); +typedef void * (*lws_map_alloc_t)(struct lws_map *mo, size_t x); +typedef void (*lws_map_free_t)(void *); + +/* + * Creation parameters for the map, copied into the map owner + */ + +typedef struct lws_map_info { + lws_map_hash_from_key_t _hash; + lws_map_compare_key_t _compare; + lws_map_alloc_t _alloc; /* NULL = lws_malloc */ + lws_map_free_t _free; /* NULL = lws_free */ + + void *opaque; + /**< &lwsac if using lwsac allocator */ + void *aux; + /**< chunk size if using lwsac allocator */ + /**< this can be used by the alloc handler, eg for lws_ac */ + size_t modulo; + /**< number of hashed owner lists to create */ +} lws_map_info_t; + +LWS_VISIBLE LWS_EXTERN const void * +lws_map_item_key(lws_map_item_t *_item); +LWS_VISIBLE LWS_EXTERN const void * +lws_map_item_value(lws_map_item_t *_item); +LWS_VISIBLE LWS_EXTERN size_t +lws_map_item_key_len(lws_map_item_t *_item); +LWS_VISIBLE LWS_EXTERN size_t +lws_map_item_value_len(lws_map_item_t *_item); + +/* + * Helpers for C string keys case + */ + +#define lws_map_item_create_ks(_map, _str, _v, _vl) \ + lws_map_item_create(_map, (const lws_map_key_t)_str, \ + strlen(_str), (const lws_map_value_t)_v, \ + _vl) +#define lws_map_item_lookup_ks(_map, _str) \ + lws_map_item_lookup(_map, (const lws_map_key_t)_str, strlen(_str)) + +/** + * lws_map_create() - create a map object and hashtables on heap + * + * \param info: description of map to create + * + * Creates a map object on heap, using lws_malloc(). + * + * \p info may be all zeros inside, if so, modulo defaults to 8, and the + * operation callbacks default to using lws_malloc() / _free() for item alloc, + * a default xor / shift based hash and simple linear memory key compare. + * + * For less typical use-cases, the provided \p info members can be tuned to + * control how the allocation of mapped items is done, lws provides two exports + * lws_map_alloc_lwsac() and lws_map_free_lwsac() that can be used for _alloc + * and _free to have items allocated inside an lwsac. + * + * The map itself is created on the heap directly, the info._alloc() op is only + * used when creating items. + * + * keys have individual memory sizes and do not need to all be the same length. + */ +LWS_VISIBLE LWS_EXTERN lws_map_t * +lws_map_create(const lws_map_info_t *info); + +/* + * helpers that can be used for info._alloc and info._free if using lwsac + * allocation for items, set info.opaque to point to the lwsac pointer, and + * aux to (void *)chunksize, or leave zero / NULL for the default + */ + +LWS_VISIBLE LWS_EXTERN void * +lws_map_alloc_lwsac(struct lws_map *map, size_t x); + +LWS_VISIBLE LWS_EXTERN void +lws_map_free_lwsac(void *v); + +/** + * lws_map_destroy() - deallocate all items and free map + * + * \param pmap: pointer to pointer map object to deallocate + * + * Frees all items in the map, using info._free(), and then frees the map + * from heap directly. \p *pmap is set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_map_destroy(lws_map_t **pmap); + +/** + * lws_map_item_create() - allocate and map an item into an existing map + * + * \param map: the map to add items into + * \param key: the key, may be any kind of object + * \param keylen: the length of the key in bytes + * \param value: the value, may be any kind of object + * \param valuelen: the length of value + * + * Allocates space for the item, key and value using the map allocator, and + * if non-NULL, copies the key and value into the item. + * + * If an item with the same key exists, it is removed and destroyed before + * creating and adding the new one. + */ + +LWS_VISIBLE LWS_EXTERN lws_map_item_t * +lws_map_item_create(lws_map_t *map, + const lws_map_key_t key, size_t keylen, + const lws_map_value_t value, size_t valuelen); + +/** + * lws_map_item_destroy() - remove item from map and free + * + * \param item: the item in the map to remove and free + */ +LWS_VISIBLE LWS_EXTERN void +lws_map_item_destroy(lws_map_item_t *item); + +/** + * lws_map_item_lookup() - look for a item with the given key in the map + * + * \param map: the map + * \param key: the key to look for + * \param keylen: the length of the key to look for + * + * Searches for the key in the map, using the map's key hash and key compare + * functions. + */ + +LWS_VISIBLE LWS_EXTERN lws_map_item_t * +lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen); + +//@} diff --git a/thirdparty/include/libwebsockets/lws-metrics.h b/thirdparty/include/libwebsockets/lws-metrics.h new file mode 100755 index 0000000000000000000000000000000000000000..4df7a266dceacfc758d66f2b5fcee2d74ea6d357 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-metrics.h @@ -0,0 +1,329 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + * + * Public apis related to metric collection and reporting + */ + +/* lws_metrics public part */ + +typedef uint64_t u_mt_t; + +enum { + LWSMTFL_REPORT_OUTLIERS = (1 << 0), + /**< track outliers and report them internally */ + LWSMTFL_REPORT_OOB = (1 << 1), + /**< report events as they happen */ + LWSMTFL_REPORT_INACTIVITY_AT_PERIODIC = (1 << 2), + /**< explicitly externally report no activity at periodic cb, by + * default no events in the period is just not reported */ + LWSMTFL_REPORT_MEAN = (1 << 3), + /**< average/min/max is meaningful, else only sum is meaningful */ + LWSMTFL_REPORT_ONLY_GO = (1 << 4), + /**< no-go pieces invalid */ + LWSMTFL_REPORT_DUTY_WALLCLOCK_US = (1 << 5), + /**< aggregate compares to wallclock us for duty cycle */ + LWSMTFL_REPORT_HIST = (1 << 6), + /**< our type is histogram (otherwise, sum / mean aggregation) */ +}; + +/* + * lws_metrics_tag allows your object to accumulate OpenMetrics-style + * descriptive tags before accounting for it with a metrics object at the end. + * + * Tags should represent low entropy information that is likely to repeat + * identically, so, eg, http method name, not eg, latency in us which is + * unlikely to be seen the same twice. + * + * Tags are just a list of name=value pairs, used for qualifying the final + * metrics entry with decorations in additional dimensions. For example, + * rather than keep individual metrics on methods, scheme, mountpoint, result + * code, you can keep metrics on http transactions only, and qualify the + * transaction metrics entries with tags that can be queried on the metrics + * backend to get the finer-grained information. + * + * http_srv{code="404",mount="/",method="GET",scheme="http"} 3 + * + * For OpenMetrics the tags are converted to a { list } and appended to the base + * metrics name before using with actual metrics objects, the same set of tags + * on different transactions resolve to the same qualification string. + */ + +typedef struct lws_metrics_tag { + lws_dll2_t list; + + const char *name; /* tag, intended to be in .rodata, not copied */ + /* overallocated value */ +} lws_metrics_tag_t; + +LWS_EXTERN LWS_VISIBLE int +lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val); + +#if defined(LWS_WITH_SYS_METRICS) +/* + * wsi-specific version that also appends the tag value to the lifecycle tag + * used for logging the wsi identity + */ +LWS_EXTERN LWS_VISIBLE int +lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val); +#else +#define lws_metrics_tag_wsi_add(_a, _b, _c) +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) +/* + * ss-specific version that also appends the tag value to the lifecycle tag + * used for logging the ss identity + */ +#if defined(LWS_WITH_SYS_METRICS) +LWS_EXTERN LWS_VISIBLE int +lws_metrics_tag_ss_add(struct lws_ss_handle *ss, const char *name, const char *val); +#else +#define lws_metrics_tag_ss_add(_a, _b, _c) +#endif +#endif + +LWS_EXTERN LWS_VISIBLE void +lws_metrics_tags_destroy(lws_dll2_owner_t *owner); + +LWS_EXTERN LWS_VISIBLE size_t +lws_metrics_tags_serialize(lws_dll2_owner_t *owner, char *buf, size_t len); + +LWS_EXTERN LWS_VISIBLE const char * +lws_metrics_tag_get(lws_dll2_owner_t *owner, const char *name); + +/* histogram bucket */ + +typedef struct lws_metric_bucket { + struct lws_metric_bucket *next; + uint64_t count; + + /* name + NUL is overallocated */ +} lws_metric_bucket_t; + +/* get overallocated name of bucket from bucket pointer */ +#define lws_metric_bucket_name_len(_b) (*((uint8_t *)&(_b)[1])) +#define lws_metric_bucket_name(_b) (((const char *)&(_b)[1]) + 1) + +/* + * These represent persistent local event measurements. They may aggregate + * a large number of events inbetween external dumping of summaries of the + * period covered, in two different ways + * + * 1) aggregation by sum or mean, to absorb multiple scalar readings + * + * - go / no-go ratio counting + * - mean averaging for, eg, latencies + * - min / max for averaged values + * - period the stats covers + * + * 2) aggregation by histogram, to absorb a range of outcomes that may occur + * multiple times + * + * - add named buckets to histogram + * - bucket has a 64-bit count + * - bumping a bucket just increments the count if already exists, else adds + * a new one with count set to 1 + * + * The same type with a union covers both cases. + * + * The lws_system ops api that hooks lws_metrics up to a metrics backend is + * given a pointer to these according to the related policy, eg, hourly, or + * every event passed straight through. + */ + +typedef struct lws_metric_pub { + const char *name; + /**< eg, "n.cn.dns", "vh.myendpoint" */ + void *backend_opaque; + /**< ignored by lws, backend handler completely owns it */ + + lws_usec_t us_first; + /**< us time metric started collecting, reset to us_dumped at dump */ + lws_usec_t us_last; + /**< 0, or us time last event, reset to 0 at last dump */ + lws_usec_t us_dumped; + /**< 0 if never, else us time of last dump to external api */ + + /* scope of data in .u is "since last dump" --> */ + + union { + /* aggregation, by sum or mean */ + + struct { + u_mt_t sum[2]; + /**< go, no-go summed for mean or plan sum */ + u_mt_t min; + /**< smallest individual measurement */ + u_mt_t max; + /**< largest individual measurement */ + + uint32_t count[2]; + /**< go, no-go count of measurements in sum */ + } agg; + + /* histogram with dynamic named buckets */ + + struct { + lws_metric_bucket_t *head; + /**< first bucket in our bucket list */ + + uint64_t total_count; + /**< total count in all of our buckets */ + uint32_t list_size; + /**< number of buckets in our bucket list */ + } hist; + } u; + + uint8_t flags; + +} lws_metric_pub_t; + +LWS_EXTERN LWS_VISIBLE void +lws_metrics_hist_bump_priv_tagged(lws_metric_pub_t *mt, lws_dll2_owner_t *tow, + lws_dll2_owner_t *tow2); + + +/* + * Calipers are a helper struct for implementing "hanging latency" detection, + * where setting the start time and finding the end time may happen in more than + * one place. + * + * There are convenience wrappers to eliminate caliper definitions and code + * cleanly if WITH_SYS_METRICS is disabled for the build. + */ + +struct lws_metric; + +typedef struct lws_metric_caliper { + struct lws_dll2_owner mtags_owner; /**< collect tags here during + * caliper lifetime */ + struct lws_metric *mt; /**< NULL == inactive */ + lws_usec_t us_start; +} lws_metric_caliper_t; + +#if defined(LWS_WITH_SYS_METRICS) +#define lws_metrics_caliper_compose(_name) \ + lws_metric_caliper_t _name; +#define lws_metrics_caliper_bind(_name, _mt) \ + { if (_name.mt) { \ + lwsl_err("caliper: overwrite %s\n", \ + lws_metrics_priv_to_pub(_name.mt)->name); \ + assert(0); } \ + _name.mt = _mt; _name.us_start = lws_now_usecs(); } +#define lws_metrics_caliper_declare(_name, _mt) \ + lws_metric_caliper_t _name = { .mt = _mt, .us_start = lws_now_usecs() } +#define lws_metrics_caliper_report(_name, _go_nogo) \ + { if (_name.us_start) { lws_metric_event(_name.mt, _go_nogo, \ + (u_mt_t)(lws_now_usecs() - \ + _name.us_start)); \ + } lws_metrics_caliper_done(_name); } +#define lws_metrics_caliper_report_hist(_name, pwsi) if (_name.mt) { \ + lws_metrics_hist_bump_priv_tagged(lws_metrics_priv_to_pub(_name.mt), \ + &_name.mtags_owner, \ + pwsi ? &((pwsi)->cal_conn.mtags_owner) : NULL); \ + lws_metrics_caliper_done(_name); } + +#define lws_metrics_caliper_cancel(_name) { lws_metrics_caliper_done(_name); } +#define lws_metrics_hist_bump(_mt, _name) \ + lws_metrics_hist_bump_(_mt, _name) +#define lws_metrics_hist_bump_priv(_mt, _name) \ + lws_metrics_hist_bump_(lws_metrics_priv_to_pub(_mt), _name) +#define lws_metrics_caliper_done(_name) { \ + _name.us_start = 0; _name.mt = NULL; \ + lws_metrics_tags_destroy(&_name.mtags_owner); } +#else +#define lws_metrics_caliper_compose(_name) +#define lws_metrics_caliper_bind(_name, _mt) +#define lws_metrics_caliper_declare(_name, _mp) +#define lws_metrics_caliper_report(_name, _go_nogo) +#define lws_metrics_caliper_report_hist(_name, pwsiconn) +#define lws_metrics_caliper_cancel(_name) +#define lws_metrics_hist_bump(_mt, _name) +#define lws_metrics_hist_bump_priv(_mt, _name) +#define lws_metrics_caliper_done(_name) +#endif + +/** + * lws_metrics_format() - helper to format a metrics object for logging + * + * \param pub: public part of metrics object + * \param buf: output buffer to place string in + * \param len: available length of \p buf + * + * Helper for describing the state of a metrics object as a human-readable + * string, accounting for how its flags indicate what it contains. This is not + * how you would report metrics, but during development it can be useful to + * log them inbetween possibily long report intervals. + * + * It uses the metric's flags to adapt the format shown appropriately, eg, + * as a histogram if LWSMTFL_REPORT_HIST etc + */ +LWS_EXTERN LWS_VISIBLE int +lws_metrics_format(lws_metric_pub_t *pub, lws_metric_bucket_t **sub, + char *buf, size_t len); + +/** + * lws_metrics_hist_bump() - add or increment histogram bucket + * + * \param pub: public part of metrics object + * \param name: bucket name to increment + * + * Either increment the count of an existing bucket of the right name in the + * metrics object, or add a new bucket of the given name and set its count to 1. + * + * The metrics object must have been created with flag LWSMTFL_REPORT_HIST + * + * Normally, you will actually use the preprocessor wrapper + * lws_metrics_hist_bump() defined above, since this automatically takes care of + * removing itself from the build if WITH_SYS_METRICS is not defined, without + * needing any preprocessor conditionals. + */ +LWS_EXTERN LWS_VISIBLE int +lws_metrics_hist_bump_(lws_metric_pub_t *pub, const char *name); + +LWS_VISIBLE LWS_EXTERN int +lws_metrics_foreach(struct lws_context *ctx, void *user, + int (*cb)(lws_metric_pub_t *pub, void *user)); + +LWS_VISIBLE LWS_EXTERN int +lws_metrics_hist_bump_describe_wsi(struct lws *wsi, lws_metric_pub_t *pub, + const char *name); + +enum { + LMT_NORMAL = 0, /* related to successful events */ + LMT_OUTLIER, /* related to successful events outside of bounds */ + + LMT_FAIL, /* related to failed events */ + + LMT_COUNT, +}; + +typedef enum lws_metric_rpt { + LMR_PERIODIC = 0, /* we are reporting on a schedule */ + LMR_OUTLIER, /* we are reporting the last outlier */ +} lws_metric_rpt_kind_t; + +#define METRES_GO 0 +#define METRES_NOGO 1 + + diff --git a/thirdparty/include/libwebsockets/lws-misc.h b/thirdparty/include/libwebsockets/lws-misc.h new file mode 100755 index 0000000000000000000000000000000000000000..c6dc4397a8a7933a4f43df3734de172d45f75529 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-misc.h @@ -0,0 +1,1122 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +#if defined(LWS_WITH_SPAWN) + +#if defined(WIN32) || defined(_WIN32) +#else +#include +#include +#endif +#endif + +#if defined(__OpenBSD__) +#include +#endif + +/** \defgroup misc Miscellaneous APIs +* ##Miscellaneous APIs +* +* Various APIs outside of other categories +*/ +///@{ + +struct lws_buflist; + +/** + * lws_buflist_append_segment(): add buffer to buflist at head + * + * \param head: list head + * \param buf: buffer to stash + * \param len: length of buffer to stash + * + * Returns -1 on OOM, 1 if this was the first segment on the list, and 0 if + * it was a subsequent segment. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_buflist_append_segment(struct lws_buflist **head, const uint8_t *buf, + size_t len); +/** + * lws_buflist_next_segment_len(): number of bytes left in current segment + * + * \param head: list head + * \param buf: if non-NULL, *buf is written with the address of the start of + * the remaining data in the segment + * + * Returns the number of bytes left in the current segment. 0 indicates + * that the buflist is empty (there are no segments on the buflist). + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_buflist_next_segment_len(struct lws_buflist **head, uint8_t **buf); + +/** + * lws_buflist_use_segment(): remove len bytes from the current segment + * + * \param head: list head + * \param len: number of bytes to mark as used + * + * If len is less than the remaining length of the current segment, the position + * in the current segment is simply advanced and it returns. + * + * If len uses up the remaining length of the current segment, then the segment + * is deleted and the list head moves to the next segment if any. + * + * Returns the number of bytes left in the current segment. 0 indicates + * that the buflist is empty (there are no segments on the buflist). + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_buflist_use_segment(struct lws_buflist **head, size_t len); + +/** + * lws_buflist_total_len(): Get the total size of the buflist + * + * \param head: list head + * + * Returns the total number of bytes held on all segments of the buflist + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_buflist_total_len(struct lws_buflist **head); + +/** + * lws_buflist_linear_copy(): copy everything out as one without consuming + * + * \param head: list head + * \param ofs: start offset into buflist in bytes + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * + * Returns -1 if len is too small, or bytes copied. Happy to do partial + * copies, returns 0 when there are no more bytes to copy. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, + size_t len); + +/** + * lws_buflist_linear_use(): copy and consume from buflist head + * + * \param head: list head + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * + * Copies a possibly fragmented buflist from the head into the linear output + * buffer \p buf for up to length \p len, and consumes the buflist content that + * was copied out. + * + * Since it was consumed, calling again will resume copying out and consuming + * from as far as it got the first time. + * + * Returns the number of bytes written into \p buf. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_linear_use(struct lws_buflist **head, uint8_t *buf, size_t len); + +/** + * lws_buflist_fragment_use(): copy and consume <= 1 frag from buflist head + * + * \param head: list head + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * \param frag_first: pointer to char written on exit to if this is start of frag + * \param frag_fin: pointer to char written on exit to if this is end of frag + * + * Copies all or part of the fragment at the start of a buflist from the head + * into the output buffer \p buf for up to length \p len, and consumes the + * buflist content that was copied out. + * + * Since it was consumed, calling again will resume copying out and consuming + * from as far as it got the first time. + * + * Returns the number of bytes written into \p buf. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_fragment_use(struct lws_buflist **head, uint8_t *buf, + size_t len, char *frag_first, char *frag_fin); + +/** + * lws_buflist_destroy_all_segments(): free all segments on the list + * + * \param head: list head + * + * This frees everything on the list unconditionally. *head is always + * NULL after this. + */ +LWS_VISIBLE LWS_EXTERN void +lws_buflist_destroy_all_segments(struct lws_buflist **head); + +/** + * lws_buflist_describe(): debug helper logging buflist status + * + * \param head: list head + * \param id: pointer shown in debug list + * \param reason: reason string show in debug list + * + * Iterates through the buflist segments showing position and size. + * This only exists when lws was built in debug mode + */ +LWS_VISIBLE LWS_EXTERN void +lws_buflist_describe(struct lws_buflist **head, void *id, const char *reason); + +/** + * lws_ptr_diff(): helper to report distance between pointers as an int + * + * \param head: the pointer with the larger address + * \param tail: the pointer with the smaller address + * + * This helper gives you an int representing the number of bytes further + * forward the first pointer is compared to the second pointer. + */ +#define lws_ptr_diff(head, tail) \ + ((int)((char *)(head) - (char *)(tail))) + +#define lws_ptr_diff_size_t(head, tail) \ + ((size_t)(ssize_t)((char *)(head) - (char *)(tail))) + +/** + * lws_snprintf(): snprintf that truncates the returned length too + * + * \param str: destination buffer + * \param size: bytes left in destination buffer + * \param format: format string + * \param ...: args for format + * + * This lets you correctly truncate buffers by concatenating lengths, if you + * reach the limit the reported length doesn't exceed the limit. + */ +LWS_VISIBLE LWS_EXTERN int +lws_snprintf(char *str, size_t size, const char *format, ...) LWS_FORMAT(3); + +/** + * lws_strncpy(): strncpy that guarantees NUL on truncated copy + * + * \param dest: destination buffer + * \param src: source buffer + * \param size: bytes left in destination buffer + * + * This lets you correctly truncate buffers by concatenating lengths, if you + * reach the limit the reported length doesn't exceed the limit. + */ +LWS_VISIBLE LWS_EXTERN char * +lws_strncpy(char *dest, const char *src, size_t size); + +/* + * Variation where we want to use the smaller of two lengths, useful when the + * source string is not NUL terminated + */ +#define lws_strnncpy(dest, src, size1, destsize) \ + lws_strncpy(dest, src, (size_t)(size1 + 1) < (size_t)(destsize) ? \ + (size_t)(size1 + 1) : (size_t)(destsize)) + +/** + * lws_nstrstr(): like strstr for length-based strings without terminating NUL + * + * \param buf: the string to search + * \param len: the length of the string to search + * \param name: the substring to search for + * \param nl: the length of name + * + * Returns NULL if \p name is not present in \p buf. Otherwise returns the + * address of the first instance of \p name in \p buf. + * + * Neither buf nor name need to be NUL-terminated. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl); + +/** + * lws_json_simple_find(): dumb JSON string parser + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param alen: set to the length of the argument part if non-NULL return + * + * Either returns NULL if \p name is not present in buf, or returns a pointer + * to the argument body of the first instance of \p name, and sets *alen to the + * length of the argument body. + * + * This can cheaply handle fishing out, eg, myarg from {"myname": "myarg"} by + * searching for "\"myname\":". It will return a pointer to myarg and set *alen + * to 5. It equally handles args like "myname": true, or "myname":false, and + * null or numbers are all returned as delimited strings. + * + * Anything more complicated like the value is a subobject or array, you should + * parse it using a full parser like lejp. This is suitable is the JSON is + * and will remain short and simple, and contains well-known names amongst other + * extensible JSON members. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen); + +/** + * lws_json_simple_strcmp(): dumb JSON string comparison + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param comp: return a strcmp of this and the discovered argument + * + * Helper that combines lws_json_simple_find() with strcmp() if it was found. + * If the \p name was not found, returns -1. Otherwise returns a strcmp() + * between what was found and \p comp, ie, return 0 if they match or something + * else if they don't. + * + * If the JSON is relatively simple and you want to target constrained + * devices, this can be a good choice. If the JSON may be complex, you + * should use a full JSON parser. + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char *comp); + + +/** + * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data + * + * \param h: incoming NUL-terminated hex string + * \param dest: array to fill with binary decodes of hex pairs from h + * \param max: maximum number of bytes dest can hold, must be at least half + * the size of strlen(h) + * + * This converts hex strings into an array of 8-bit representations, ie the + * input "abcd" produces two bytes of value 0xab and 0xcd. + * + * Returns number of bytes produced into \p dest, or -1 on error. + * + * Errors include non-hex chars and an odd count of hex chars in the input + * string. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hex_to_byte_array(const char *h, uint8_t *dest, int max); + +/** + * lws_hex_from_byte_array(): render byte array as hex char string + * + * \param src: incoming binary source array + * \param slen: length of src in bytes + * \param dest: array to fill with hex chars representing src + * \param len: max extent of dest + * + * This converts binary data of length slen at src, into a hex string at dest + * of maximum length len. Even if truncated, the result will be NUL-terminated. + */ +LWS_VISIBLE LWS_EXTERN void +lws_hex_from_byte_array(const uint8_t *src, size_t slen, char *dest, size_t len); + +/** + * lws_hex_random(): generate len - 1 or - 2 characters of random ascii hex + * + * \param context: the lws_context used to get the random + * \param dest: destination for hex ascii chars + * \param len: the number of bytes the buffer dest points to can hold + * + * This creates random ascii-hex strings up to a given length, with a + * terminating NUL. + * + * There will not be any characters produced that are not 0-9, a-f, so it's + * safe to go straight into, eg, JSON. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hex_random(struct lws_context *context, char *dest, size_t len); + +/* + * lws_timingsafe_bcmp(): constant time memcmp + * + * \param a: first buffer + * \param b: second buffer + * \param len: count of bytes to compare + * + * Return 0 if the two buffers are the same, else nonzero. + * + * Always compares all of the buffer before returning, so it can't be used as + * a timing oracle. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_timingsafe_bcmp(const void *a, const void *b, uint32_t len); + +/** + * lws_get_random(): fill a buffer with platform random data + * + * \param context: the lws context + * \param buf: buffer to fill + * \param len: how much to fill + * + * Fills buf with len bytes of random. Returns the number of bytes set, if + * not equal to len, then getting the random failed. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_get_random(struct lws_context *context, void *buf, size_t len); +/** + * lws_daemonize(): make current process run in the background + * + * \param _lock_path: the filepath to write the lock file + * + * Spawn lws as a background process, taking care of various things + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_daemonize(const char *_lock_path); +/** + * lws_get_library_version(): return string describing the version of lws + * + * On unix, also includes the git describe + */ +LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT +lws_get_library_version(void); + +/** + * lws_wsi_user() - get the user data associated with the connection + * \param wsi: lws connection + * + * Not normally needed since it's passed into the callback + */ +LWS_VISIBLE LWS_EXTERN void * +lws_wsi_user(struct lws *wsi); + +/** + * lws_wsi_tsi() - get the service thread index the wsi is bound to + * \param wsi: lws connection + * + * Only useful is LWS_MAX_SMP > 1 + */ +LWS_VISIBLE LWS_EXTERN int +lws_wsi_tsi(struct lws *wsi); + +/** + * lws_set_wsi_user() - set the user data associated with the client connection + * \param wsi: lws connection + * \param user: user data + * + * By default lws allocates this and it's not legal to externally set it + * yourself. However client connections may have it set externally when the + * connection is created... if so, this api can be used to modify it at + * runtime additionally. + */ +LWS_VISIBLE LWS_EXTERN void +lws_set_wsi_user(struct lws *wsi, void *user); + +/** + * lws_parse_uri: cut up prot:/ads:port/path into pieces + * Notice it does so by dropping '\0' into input string + * and the leading / on the path is consequently lost + * + * \param p: incoming uri string.. will get written to + * \param prot: result pointer for protocol part (https://) + * \param ads: result pointer for address part + * \param port: result pointer for port part + * \param path: result pointer for path part + * + * You may also refer to unix socket addresses, using a '+' at the start of + * the address. In this case, the address should end with ':', which is + * treated as the separator between the address and path (the normal separator + * '/' is a valid part of the socket path). Eg, + * + * http://+/var/run/mysocket:/my/path + * + * If the first character after the + is '@', it's interpreted by lws client + * processing as meaning to use linux abstract namespace sockets, the @ is + * replaced with a '\0' before use. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_parse_uri(char *p, const char **prot, const char **ads, int *port, + const char **path); +/** + * lws_cmdline_option(): simple commandline parser + * + * \param argc: count of argument strings + * \param argv: argument strings + * \param val: string to find + * + * Returns NULL if the string \p val is not found in the arguments. + * + * If it is found, then it returns a pointer to the next character after \p val. + * So if \p val is "-d", then for the commandlines "myapp -d15" and + * "myapp -d 15", in both cases the return will point to the "15". + * + * In the case there is no argument, like "myapp -d", the return will + * either point to the '\\0' at the end of -d, or to the start of the + * next argument, ie, will be non-NULL. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_cmdline_option(int argc, const char **argv, const char *val); + +/** + * lws_cmdline_option_handle_builtin(): apply standard cmdline options + * + * \param argc: count of argument strings + * \param argv: argument strings + * \param info: context creation info + * + * Applies standard options to the context creation info to save them having + * to be (unevenly) copied into the minimal examples. + * + * Applies default log levels that can be overriden by -d + */ +LWS_VISIBLE LWS_EXTERN void +lws_cmdline_option_handle_builtin(int argc, const char **argv, + struct lws_context_creation_info *info); + +/** + * lws_now_secs(): return seconds since 1970-1-1 + */ +LWS_VISIBLE LWS_EXTERN unsigned long +lws_now_secs(void); + +/** + * lws_now_usecs(): return useconds since 1970-1-1 + */ +LWS_VISIBLE LWS_EXTERN lws_usec_t +lws_now_usecs(void); + +/** + * lws_get_context - Allow getting lws_context from a Websocket connection + * instance + * + * With this function, users can access context in the callback function. + * Otherwise users may have to declare context as a global variable. + * + * \param wsi: Websocket connection instance + */ +LWS_VISIBLE LWS_EXTERN struct lws_context * LWS_WARN_UNUSED_RESULT +lws_get_context(const struct lws *wsi); + +/** + * lws_get_vhost_listen_port - Find out the port number a vhost is listening on + * + * In the case you passed 0 for the port number at context creation time, you + * can discover the port number that was actually chosen for the vhost using + * this api. + * + * \param vhost: Vhost to get listen port from + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_get_vhost_listen_port(struct lws_vhost *vhost); + +/** + * lws_get_count_threads(): how many service threads the context uses + * + * \param context: the lws context + * + * By default this is always 1, if you asked for more than lws can handle it + * will clip the number of threads. So you can use this to find out how many + * threads are actually in use. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_get_count_threads(struct lws_context *context); + +/** + * lws_get_parent() - get parent wsi or NULL + * \param wsi: lws connection + * + * Specialized wsi like cgi stdin/out/err are associated to a parent wsi, + * this allows you to get their parent. + */ +LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT +lws_get_parent(const struct lws *wsi); + +/** + * lws_get_child() - get child wsi or NULL + * \param wsi: lws connection + * + * Allows you to find a related wsi from the parent wsi. + */ +LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT +lws_get_child(const struct lws *wsi); + +/** + * lws_get_effective_uid_gid() - find out eventual uid and gid while still root + * + * \param context: lws context + * \param uid: pointer to uid result + * \param gid: pointer to gid result + * + * This helper allows you to find out what the uid and gid for the process will + * be set to after the privileges are dropped, beforehand. So while still root, + * eg in LWS_CALLBACK_PROTOCOL_INIT, you can arrange things like cache dir + * and subdir creation / permissions down /var/cache dynamically. + */ +LWS_VISIBLE LWS_EXTERN void +lws_get_effective_uid_gid(struct lws_context *context, uid_t *uid, gid_t *gid); + +/** + * lws_get_udp() - get wsi's udp struct + * + * \param wsi: lws connection + * + * Returns NULL or pointer to the wsi's UDP-specific information + */ +LWS_VISIBLE LWS_EXTERN const struct lws_udp * LWS_WARN_UNUSED_RESULT +lws_get_udp(const struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void * +lws_get_opaque_parent_data(const struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +lws_set_opaque_parent_data(struct lws *wsi, void *data); + +LWS_VISIBLE LWS_EXTERN void * +lws_get_opaque_user_data(const struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +lws_set_opaque_user_data(struct lws *wsi, void *data); + +LWS_VISIBLE LWS_EXTERN int +lws_get_child_pending_on_writable(const struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN void +lws_clear_child_pending_on_writable(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN int +lws_get_close_length(struct lws *wsi); + +LWS_VISIBLE LWS_EXTERN unsigned char * +lws_get_close_payload(struct lws *wsi); + +/** + * lws_get_network_wsi() - Returns wsi that has the tcp connection for this wsi + * + * \param wsi: wsi you have + * + * Returns wsi that has the tcp connection (which may be the incoming wsi) + * + * HTTP/1 connections will always return the incoming wsi + * HTTP/2 connections may return a different wsi that has the tcp connection + */ +LWS_VISIBLE LWS_EXTERN +struct lws *lws_get_network_wsi(struct lws *wsi); + +/** + * lws_set_allocator() - custom allocator support + * + * \param realloc + * + * Allows you to replace the allocator (and deallocator) used by lws + */ +LWS_VISIBLE LWS_EXTERN void +lws_set_allocator(void *(*realloc)(void *ptr, size_t size, const char *reason)); + +enum { + /* + * Flags for enable and disable rxflow with reason bitmap and with + * backwards-compatible single bool + */ + LWS_RXFLOW_REASON_USER_BOOL = (1 << 0), + LWS_RXFLOW_REASON_HTTP_RXBUFFER = (1 << 6), + LWS_RXFLOW_REASON_H2_PPS_PENDING = (1 << 7), + + LWS_RXFLOW_REASON_APPLIES = (1 << 14), + LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT = (1 << 13), + LWS_RXFLOW_REASON_APPLIES_ENABLE = LWS_RXFLOW_REASON_APPLIES | + LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT, + LWS_RXFLOW_REASON_APPLIES_DISABLE = LWS_RXFLOW_REASON_APPLIES, + LWS_RXFLOW_REASON_FLAG_PROCESS_NOW = (1 << 12), + +}; + +/** + * lws_rx_flow_control() - Enable and disable socket servicing for + * received packets. + * + * If the output side of a server process becomes choked, this allows flow + * control for the input side. + * + * \param wsi: Websocket connection instance to get callback for + * \param enable: 0 = disable read servicing for this connection, 1 = enable + * + * If you need more than one additive reason for rxflow control, you can give + * iLWS_RXFLOW_REASON_APPLIES_ENABLE or _DISABLE together with one or more of + * b5..b0 set to idicate which bits to enable or disable. If any bits are + * enabled, rx on the connection is suppressed. + * + * LWS_RXFLOW_REASON_FLAG_PROCESS_NOW flag may also be given to force any change + * in rxflowbstatus to benapplied immediately, this should be used when you are + * changing a wsi flow control state from outside a callback on that wsi. + */ +LWS_VISIBLE LWS_EXTERN int +lws_rx_flow_control(struct lws *wsi, int enable); + +/** + * lws_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive + * + * When the user server code realizes it can accept more input, it can + * call this to have the RX flow restriction removed from all connections using + * the given protocol. + * \param context: lws_context + * \param protocol: all connections using this protocol will be allowed to receive + */ +LWS_VISIBLE LWS_EXTERN void +lws_rx_flow_allow_all_protocol(const struct lws_context *context, + const struct lws_protocols *protocol); + +/** + * lws_remaining_packet_payload() - Bytes to come before "overall" + * rx fragment is complete + * \param wsi: Websocket instance (available from user callback) + * + * This tracks how many bytes are left in the current ws fragment, according + * to the ws length given in the fragment header. + * + * If the message was in a single fragment, and there is no compression, this + * is the same as "how much data is left to read for this message". + * + * However, if the message is being sent in multiple fragments, this will + * reflect the unread amount of the current **fragment**, not the message. With + * ws, it is legal to not know the length of the message before it completes. + * + * Additionally if the message is sent via the negotiated permessage-deflate + * extension, this number only tells the amount of **compressed** data left to + * be read, since that is the only information available at the ws layer. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_remaining_packet_payload(struct lws *wsi); + +#if defined(LWS_WITH_DIR) + +typedef enum { + LDOT_UNKNOWN, + LDOT_FILE, + LDOT_DIR, + LDOT_LINK, + LDOT_FIFO, + LDOTT_SOCKET, + LDOT_CHAR, + LDOT_BLOCK +} lws_dir_obj_type_t; + +struct lws_dir_entry { + const char *name; + lws_dir_obj_type_t type; +}; + +typedef int +lws_dir_callback_function(const char *dirpath, void *user, + struct lws_dir_entry *lde); + +/** + * lws_dir() - get a callback for everything in a directory + * + * \param dirpath: the directory to scan + * \param user: pointer to give to callback + * \param cb: callback to receive information on each file or dir + * + * Calls \p cb (with \p user) for every object in dirpath. + * + * This wraps whether it's using POSIX apis, or libuv (as needed for windows, + * since it refuses to support POSIX apis for this). + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb); + +/** + * lws_dir_rm_rf_cb() - callback for lws_dir that performs recursive rm -rf + * + * \param dirpath: directory we are at in lws_dir + * \param user: ignored + * \param lde: lws_dir info on the file or directory we are at + * + * This is a readymade rm -rf callback for use with lws_dir. It recursively + * removes everything below the starting dir and then the starting dir itself. + * Works on linux, OSX and Windows at least. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + +/* + * We pass every file in the base dir through a filter, and call back on the + * ones that match. Directories are ignored. + * + * The original path filter string may look like, eg, "sai-*.deb" or "*.txt" + */ + +typedef int (*lws_dir_glob_cb_t)(void *data, const char *path); + +typedef struct lws_dir_glob { + const char *filter; + lws_dir_glob_cb_t cb; + void *user; +} lws_dir_glob_t; + +/** + * lws_dir_glob_cb() - callback for lws_dir that performs filename globbing + * + * \param dirpath: directory we are at in lws_dir + * \param user: pointer to your prepared lws_dir_glob_cb_t + * \param lde: lws_dir info on the file or directory we are at + * + * \p user is prepared with an `lws_dir_glob_t` containing a callback for paths + * that pass the filtering, a user pointer to pass to that callback, and a + * glob string like "*.txt". It may not contain directories, the lws_dir musr + * be started at the correct dir. + * + * Only the base path passed to lws_dir is scanned, it does not look in subdirs. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + +#endif + +/** + * lws_get_allocated_heap() - if the platform supports it, returns amount of + * heap allocated by lws itself + * + * On glibc currently, this reports the total amount of current logical heap + * allocation, found by tracking the amount allocated by lws_malloc() and + * friends and accounting for freed allocations via lws_free(). + * + * This is useful for confirming where processwide heap allocations actually + * come from... this number represents all lws internal allocations, for + * fd tables, wsi allocations, ah, etc combined. It doesn't include allocations + * from user code, since lws_malloc() etc are not exported from the library. + * + * On other platforms, it always returns 0. + */ +size_t lws_get_allocated_heap(void); + +/** + * lws_get_tsi() - Get thread service index wsi belong to + * \param wsi: websocket connection to check + * + * Returns more than zero (or zero if only one service thread as is the default). + */ +LWS_VISIBLE LWS_EXTERN int +lws_get_tsi(struct lws *wsi); + +/** + * lws_is_ssl() - Find out if connection is using SSL + * \param wsi: websocket connection to check + * + * Returns nonzero if the wsi is inside a tls tunnel, else zero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_is_ssl(struct lws *wsi); +/** + * lws_is_cgi() - find out if this wsi is running a cgi process + * + * \param wsi: lws connection + */ +LWS_VISIBLE LWS_EXTERN int +lws_is_cgi(struct lws *wsi); + +/** + * lws_tls_jit_trust_blob_queury_skid() - walk jit trust blob for skid + * + * \param _blob: the start of the blob in memory + * \param blen: the length of the blob in memory + * \param skid: the SKID we are looking for + * \param skid_len: the length of the SKID we are looking for + * \param prpder: result pointer to receive a pointer to the matching DER + * \param prder_len: result pointer to receive matching DER length + * + * Helper to scan a JIT Trust blob in memory for a trusted CA cert matching + * a given SKID. Returns 0 if found and *prpder and *prder_len are set, else + * nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_jit_trust_blob_queury_skid(const void *_blob, size_t blen, + const uint8_t *skid, size_t skid_len, + const uint8_t **prpder, size_t *prder_len); + +/** + * lws_open() - platform-specific wrapper for open that prepares the fd + * + * \param __file: the filepath to open + * \param __oflag: option flags + * + * This is a wrapper around platform open() that sets options on the fd + * according to lws policy. Currently that is FD_CLOEXEC to stop the opened + * fd being available to any child process forked by user code. + */ +LWS_VISIBLE LWS_EXTERN int +lws_open(const char *__file, int __oflag, ...); + +struct lws_wifi_scan { /* generic wlan scan item */ + struct lws_wifi_scan *next; + char ssid[32]; + int32_t rssi; /* divide by .count to get db */ + uint8_t bssid[6]; + uint8_t count; + uint8_t channel; + uint8_t authmode; +}; + +#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) +/** + * lws_get_ssl() - Return wsi's SSL context structure + * \param wsi: websocket connection + * + * Returns pointer to the SSL library's context structure + */ +LWS_VISIBLE LWS_EXTERN SSL* +lws_get_ssl(struct lws *wsi); +#endif + +LWS_VISIBLE LWS_EXTERN void +lws_explicit_bzero(void *p, size_t len); + +typedef struct lws_humanize_unit { + const char *name; /* array ends with NULL name */ + uint64_t factor; +} lws_humanize_unit_t; + +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si_bytes[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_us[8]; + +/** + * lws_humanize() - Convert possibly large number to human-readable uints + * + * \param buf: result string buffer + * \param len: remaining length in \p buf + * \param value: the uint64_t value to represent + * \param schema: and array of scaling factors and units + * + * This produces a concise string representation of \p value, referencing the + * schema \p schema of scaling factors and units to find the smallest way to + * render it. + * + * Three schema are exported from lws for general use, humanize_schema_si, which + * represents as, eg, " 22.130Gi" or " 128 "; humanize_schema_si_bytes + * which is the same but shows, eg, " 22.130GiB", and humanize_schema_us, + * which represents a count of us as a human-readable time like " 14.350min", + * or " 1.500d". + * + * You can produce your own schema. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_humanize(char *buf, size_t len, uint64_t value, + const lws_humanize_unit_t *schema); + +LWS_VISIBLE LWS_EXTERN void +lws_ser_wu16be(uint8_t *b, uint16_t u); + +LWS_VISIBLE LWS_EXTERN void +lws_ser_wu32be(uint8_t *b, uint32_t u32); + +LWS_VISIBLE LWS_EXTERN void +lws_ser_wu64be(uint8_t *b, uint64_t u64); + +LWS_VISIBLE LWS_EXTERN uint16_t +lws_ser_ru16be(const uint8_t *b); + +LWS_VISIBLE LWS_EXTERN uint32_t +lws_ser_ru32be(const uint8_t *b); + +LWS_VISIBLE LWS_EXTERN uint64_t +lws_ser_ru64be(const uint8_t *b); + +LWS_VISIBLE LWS_EXTERN int +lws_vbi_encode(uint64_t value, void *buf); + +LWS_VISIBLE LWS_EXTERN int +lws_vbi_decode(const void *buf, uint64_t *value, size_t len); + +///@} + +#if defined(LWS_WITH_SPAWN) + +/* opaque internal struct */ +struct lws_spawn_piped; + +#if defined(WIN32) +struct _lws_siginfo_t { + int retcode; +}; +typedef struct _lws_siginfo_t siginfo_t; +#endif + +typedef void (*lsp_cb_t)(void *opaque, lws_usec_t *accounting, siginfo_t *si, + int we_killed_him); + + +/** + * lws_spawn_piped_info - details given to create a spawned pipe + * + * \p owner: lws_dll2_owner_t that lists all active spawns, or NULL + * \p vh: vhost to bind stdwsi to... from opt_parent if given + * \p opt_parent: optional parent wsi for stdwsi + * \p exec_array: argv for process to spawn + * \p env_array: environment for spawned process, NULL ends env list + * \p protocol_name: NULL, or vhost protocol name to bind stdwsi to + * \p chroot_path: NULL, or chroot patch for child process + * \p wd: working directory to cd to after fork, NULL defaults to /tmp + * \p plsp: NULL, or pointer to the outer lsp pointer so it can be set NULL when destroyed + * \p opaque: pointer passed to the reap callback, if any + * \p timeout: optional us-resolution timeout, or zero + * \p reap_cb: callback when child process has been reaped and the lsp destroyed + * \p tsi: tsi to bind stdwsi to... from opt_parent if given + */ +struct lws_spawn_piped_info { + struct lws_dll2_owner *owner; + struct lws_vhost *vh; + struct lws *opt_parent; + + const char * const *exec_array; + const char **env_array; + const char *protocol_name; + const char *chroot_path; + const char *wd; + + struct lws_spawn_piped **plsp; + + void *opaque; + + lsp_cb_t reap_cb; + + lws_usec_t timeout_us; + int max_log_lines; + int tsi; + + const struct lws_role_ops *ops; /* NULL is raw file */ + + uint8_t disable_ctrlc; +}; + +/** + * lws_spawn_piped() - spawn a child process with stdxxx redirected + * + * \p lspi: info struct describing details of spawn to create + * + * This spawns a child process managed in the lsp object and with attributes + * set in the arguments. The stdin/out/err streams are redirected to pipes + * which are instantiated into wsi that become child wsi of \p parent if non- + * NULL. .opaque_user_data on the stdwsi created is set to point to the + * lsp object, so this can be recovered easily in the protocol handler. + * + * If \p owner is non-NULL, successful spawns join the given dll2 owner in the + * original process. + * + * If \p timeout is non-zero, successful spawns register a sul with the us- + * resolution timeout to callback \p timeout_cb, in the original process. + * + * Returns 0 if the spawn went OK or nonzero if it failed and was cleaned up. + * The spawned process continues asynchronously and this will return after + * starting it if all went well. + */ +LWS_VISIBLE LWS_EXTERN struct lws_spawn_piped * +lws_spawn_piped(const struct lws_spawn_piped_info *lspi); + +/* + * lws_spawn_piped_kill_child_process() - attempt to kill child process + * + * \p lsp: child object to kill + * + * Attempts to signal the child process in \p lsp to terminate. + */ +LWS_VISIBLE LWS_EXTERN int +lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp); + +/** + * lws_spawn_stdwsi_closed() - inform the spawn one of its stdxxx pipes closed + * + * \p lsp: the spawn object + * \p wsi: the wsi that is closing + * + * When you notice one of the spawn stdxxx pipes closed, inform the spawn + * instance using this api. When it sees all three have closed, it will + * automatically try to reap the child process. + * + * This is the mechanism whereby the spawn object can understand its child + * has closed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi); + +/** + * lws_spawn_get_stdfd() - return std channel index for stdwsi + * + * \p wsi: the wsi + * + * If you know wsi is a stdwsi from a spawn, you can determine its original + * channel index / fd before the pipes replaced the default fds. It will return + * one of 0 (STDIN), 1 (STDOUT) or 2 (STDERR). You can handle all three in the + * same protocol handler and then disambiguate them using this api. + */ +LWS_VISIBLE LWS_EXTERN int +lws_spawn_get_stdfd(struct lws *wsi); + +#endif + +struct lws_fsmount { + const char *layers_path; /* where layers live */ + const char *overlay_path; /* where overlay instantiations live */ + + char mp[256]; /* mountpoint path */ + char ovname[64]; /* unique name for mount instance */ + char distro[64]; /* unique name for layer source */ + +#if defined(__linux__) + const char *layers[4]; /* distro layers, like "base", "env" */ +#endif +}; + +/** + * lws_fsmount_mount() - Mounts an overlayfs stack of layers + * + * \p fsm: struct lws_fsmount specifying the mount layout + * + * This api is able to assemble up to 4 layer directories on to a mountpoint + * using overlayfs mount (Linux only). + * + * Set fsm.layers_path to the base dir where the layers themselves live, the + * entries in fsm.layers[] specifies the relative path to the layer, comprising + * fsm.layers_path/fsm.distro/fsm.layers[], with [0] being the deepest, earliest + * layer and the rest being progressively on top of [0]; NULL indicates the + * layer is unused. + * + * fsm.overlay_path is the base path of the overlayfs instantiations... empty + * dirs must exist at + * + * fsm.overlay_path/overlays/fsm.ovname/work + * fsm.overlay_path/overlays/fsm.ovname/session + * + * Set fsm.mp to the path of an already-existing empty dir that will be the + * mountpoint, this can be whereever you like. + * + * Overlayfs merges the union of all the contributing layers at the mountpoint, + * the mount is writeable but the layer themselves are immutable, all additions + * and changes are stored in + * + * fsm.overlay_path/overlays/fsm.ovname/session + * + * Returns 0 if mounted OK, nonzero if errors. + * + * Retain fsm for use with unmounting. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fsmount_mount(struct lws_fsmount *fsm); + +/** + * lws_fsmount_unmount() - Unmounts an overlayfs dir + * + * \p fsm: struct lws_fsmount specifying the mount layout + * + * Unmounts the mountpoint in fsm.mp. + * + * Delete fsm.overlay_path/overlays/fsm.ovname/session to permanently eradicate + * all changes from the time the mountpoint was in use. + * + * Returns 0 if unmounted OK. + */ +LWS_VISIBLE LWS_EXTERN int +lws_fsmount_unmount(struct lws_fsmount *fsm); diff --git a/thirdparty/include/libwebsockets/lws-mqtt.h b/thirdparty/include/libwebsockets/lws-mqtt.h new file mode 100755 index 0000000000000000000000000000000000000000..71193e662830baadce74c21c51f4a90b94e6b054 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-mqtt.h @@ -0,0 +1,344 @@ +/* + * libwebsockets - protocol - mqtt + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + * + * included from libwebsockets.h + */ + +#ifndef _LWS_MQTT_H +#define _LWS_MQTT_H 1 + +struct _lws_mqtt_related; +typedef struct _lws_mqtt_related lws_mqtt_related_t; +struct lws_mqtt_str_st; +typedef struct lws_mqtt_str_st lws_mqtt_str_t; + +#define MQTT_VER_3_1_1 4 + +#define LWS_MQTT_FINAL_PART 1 + +#define LWS_MQTT_MAX_AWSIOT_TOPICLEN 256 +#define LWS_MQTT_MAX_TOPICLEN 65535 +#define LWS_MQTT_MAX_CIDLEN 128 +#define LWS_MQTT_RANDOM_CIDLEN 23 /* 3.1.3.1-5: Server MUST... between + 1 and 23 chars... */ + +typedef enum { + QOS0, + QOS1, + QOS2, /* not supported */ + RESERVED_QOS_LEVEL, + FAILURE_QOS_LEVEL = 0x80 +} lws_mqtt_qos_levels_t; + +typedef union { + struct { + uint8_t retain:1; + uint8_t qos:2; + uint8_t dup:1; + uint8_t ctrl_pkt_type:4; + } flags; + uint8_t bits; +} lws_mqtt_fixed_hdr_t; + +/* + * MQTT connection parameters, passed into struct + * lws_client_connect_info to establish a connection using + * lws_client_connect_via_info(). +*/ +typedef struct lws_mqtt_client_connect_param_s { + const char *client_id; /* Client ID */ + uint16_t keep_alive; /* MQTT keep alive + interval in + seconds */ + uint8_t clean_start:1; /* MQTT clean + session */ + uint8_t client_id_nofree:1; + /**< do not free the client id */ + struct { + const char *topic; + const char *message; + lws_mqtt_qos_levels_t qos; + uint8_t retain; + } will_param; /* MQTT LWT + parameters */ + const char *username; + const char *password; + uint8_t aws_iot; +} lws_mqtt_client_connect_param_t; + +/* + * MQTT publish parameters +*/ +typedef struct lws_mqtt_publish_param_s { + char *topic; /* Topic Name */ + uint16_t topic_len; + const void *payload; /* Publish Payload */ + uint32_t payload_len; /* Size of the + complete payload */ + uint32_t payload_pos; /* where we are in payload */ + lws_mqtt_qos_levels_t qos; + + /*--v-Following will be used by LWS-v--*/ + uint16_t packet_id; /* Packet ID for QoS > + 0 */ + uint8_t dup:1; /* Retried PUBLISH, + for QoS > 0 */ +} lws_mqtt_publish_param_t; + +typedef struct topic_elem { + const char *name; /* Topic Name */ + lws_mqtt_qos_levels_t qos; /* Requested QoS */ + + /*--v-Following will be used by LWS-v--*/ + uint8_t acked; +} lws_mqtt_topic_elem_t; + +/* + * MQTT publish parameters +*/ +typedef struct lws_mqtt_subscribe_param_s { + uint32_t num_topics; /* Number of topics */ + lws_mqtt_topic_elem_t *topic; /* Array of topic elements */ + + /*--v-Following will be used by LWS-v--*/ + uint16_t packet_id; +} lws_mqtt_subscribe_param_t; + +typedef enum { + LMQCP_RESERVED, + LMQCP_CTOS_CONNECT, /* Connection request */ + LMQCP_STOC_CONNACK, /* Connection acknowledgment */ + LMQCP_PUBLISH, /* Publish Message */ + LMQCP_PUBACK, /* QoS 1: Publish acknowledgment */ + LMQCP_PUBREC, /* QoS 2.1: Publish received */ + LMQCP_PUBREL, /* QoS 2.2: Publish release */ + LMQCP_PUBCOMP, /* QoS 2.3: Publish complete */ + LMQCP_CTOS_SUBSCRIBE, /* Subscribe request */ + LMQCP_STOC_SUBACK, /* Subscribe acknowledgment */ + LMQCP_CTOS_UNSUBSCRIBE, /* Unsubscribe request */ + LMQCP_STOC_UNSUBACK, /* Unsubscribe acknowledgment */ + LMQCP_CTOS_PINGREQ, /* PING request */ + LMQCP_STOC_PINGRESP, /* PONG response */ + LMQCP_DISCONNECT, /* Disconnect notification */ + LMQCP_AUTH /* Authentication exchange */ +} lws_mqtt_control_packet_t; + +/* flags from byte 8 of C_TO_S CONNECT */ +typedef enum { + LMQCFT_CLIENT_ID_NOFREE = (1 << 8), + /* only the low 8 are standardized and go out in the protocol */ + LMQCFT_USERNAME = (1 << 7), + LMQCFT_PASSWORD = (1 << 6), + LMQCFT_WILL_RETAIN = (1 << 5), + LMQCFT_WILL_QOS = (1 << 3), + LMQCFT_WILL_FLAG = (1 << 2), + LMQCFT_CLEAN_START = (1 << 1), + LMQCFT_RESERVED = (1 << 0), + + LMQCFT_WILL_QOS_MASK = (3 << 3), +} lws_mqtt_connect_flags_t; + +/* flags for S_TO_C CONNACK */ +typedef enum { + LMQCFT_SESSION_PRESENT = (1 << 0), +} lws_mqtt_connack_flags_t; + +typedef enum { + LMQCP_REASON_SUCCESS = 0x00, + LMQCP_REASON_NORMAL_DISCONNECTION = 0x00, + LMQCP_REASON_GRANTED_QOS0 = 0x00, + LMQCP_REASON_GRANTED_QOS1 = 0x01, + LMQCP_REASON_GRANTED_QOS2 = 0x02, + LMQCP_REASON_DISCONNECT_WILL = 0x04, + LMQCP_REASON_NO_MATCHING_SUBSCRIBER = 0x10, + LMQCP_REASON_NO_SUBSCRIPTION_EXISTED = 0x11, + LMQCP_REASON_CONTINUE_AUTHENTICATION = 0x18, + LMQCP_REASON_RE_AUTHENTICATE = 0x19, + + LMQCP_REASON_UNSPECIFIED_ERROR = 0x80, + LMQCP_REASON_MALFORMED_PACKET = 0x81, + LMQCP_REASON_PROTOCOL_ERROR = 0x82, + LMQCP_REASON_IMPLEMENTATION_SPECIFIC_ERROR = 0x83, + + /* Begin - Error codes for CONNACK */ + LMQCP_REASON_UNSUPPORTED_PROTOCOL = 0x84, + LMQCP_REASON_CLIENT_ID_INVALID = 0x85, + LMQCP_REASON_BAD_CREDENTIALS = 0x86, + LMQCP_REASON_NOT_AUTHORIZED = 0x87, + /* End - Error codes for CONNACK */ + + LMQCP_REASON_SERVER_UNAVAILABLE = 0x88, + LMQCP_REASON_SERVER_BUSY = 0x89, + LMQCP_REASON_BANNED = 0x8a, + LMQCP_REASON_SERVER_SHUTTING_DOWN = 0x8b, + LMQCP_REASON_BAD_AUTHENTICATION_METHOD = 0x8c, + LMQCP_REASON_KEEPALIVE_TIMEOUT = 0x8d, + LMQCP_REASON_SESSION_TAKEN_OVER = 0x8e, + LMQCP_REASON_TOPIC_FILTER_INVALID = 0x8f, + LMQCP_REASON_TOPIC_NAME_INVALID = 0x90, + LMQCP_REASON_PACKET_ID_IN_USE = 0x91, + LMQCP_REASON_PACKET_ID_NOT_FOUND = 0x92, + LMQCP_REASON_MAX_RX_EXCEEDED = 0x93, + LMQCP_REASON_TOPIC_ALIAS_INVALID = 0x94, + LMQCP_REASON_PACKET_TOO_LARGE = 0x95, + LMQCP_REASON_RATELIMIT = 0x96, + LMQCP_REASON_QUOTA_EXCEEDED = 0x97, + LMQCP_REASON_ADMINISTRATIVE_ACTION = 0x98, + LMQCP_REASON_PAYLOAD_FORMAT_INVALID = 0x99, + LMQCP_REASON_RETAIN_NOT_SUPPORTED = 0x9a, + LMQCP_REASON_QOS_NOT_SUPPORTED = 0x9b, + LMQCP_REASON_USE_ANOTHER_SERVER = 0x9c, + LMQCP_REASON_SERVER_MOVED = 0x9d, + LMQCP_REASON_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 0x9e, + LMQCP_REASON_CONNECTION_RATE_EXCEEDED = 0x9f, + LMQCP_REASON_MAXIMUM_CONNECT_TIME = 0xa0, + LMQCP_REASON_SUBSCRIPTION_IDS_NOT_SUPPORTED = 0xa1, + LMQCP_REASON_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 0xa2, +} lws_mqtt_reason_t; + +typedef enum { + LMQPROP_INVALID, + LMQPROP_PAYLOAD_FORMAT_INDICATOR = 0x01, + LMQPROP_MESSAGE_EXPIRY_INTERVAL = 0x02, + LMQPROP_CONTENT_TYPE = 0x03, + LMQPROP_RESPONSE_TOPIC = 0x08, + LMQPROP_CORRELATION_DATA = 0x09, + LMQPROP_SUBSCRIPTION_IDENTIFIER = 0x0b, + LMQPROP_SESSION_EXPIRY_INTERVAL = 0x11, + LMQPROP_ASSIGNED_CLIENT_IDENTIFIER = 0x12, + LMQPROP_SERVER_KEEP_ALIVE = 0x13, + LMQPROP_AUTHENTICATION_METHOD = 0x15, + LMQPROP_AUTHENTICATION_DATA = 0x16, + LMQPROP_REQUEST_PROBLEM_INFORMATION = 0x17, + LMQPROP_WILL_DELAY_INTERVAL = 0x18, + LMQPROP_REQUEST_RESPONSE_INFORMATION = 0x19, + LMQPROP_RESPONSE_INFORMATION = 0x1a, + LMQPROP_SERVER_REFERENCE = 0x1c, + LMQPROP_REASON_STRING = 0x1f, + LMQPROP_RECEIVE_MAXIMUM = 0x21, + LMQPROP_TOPIC_ALIAS_MAXIMUM = 0x22, + LMQPROP_TOPIC_ALIAS = 0x23, + LMQPROP_MAXIMUM_QOS = 0x24, + LMQPROP_RETAIN_AVAILABLE = 0x25, + LMQPROP_USER_PROPERTY = 0x26, + LMQPROP_MAXIMUM_PACKET_SIZE = 0x27, + LMQPROP_WILDCARD_SUBSCRIPTION_AVAIL = 0x28, + LMQPROP_SUBSCRIPTION_IDENTIFIER_AVAIL = 0x29, + LMQPROP_SHARED_SUBSCRIPTION_AVAIL = 0x2a +} lws_mqtt_property; + +int +lws_read_mqtt(struct lws *wsi, unsigned char *buf, lws_filepos_t len); + +/* returns 0 if bd1 and bd2 are "the same", that includes empty, else nonzero */ +LWS_VISIBLE LWS_EXTERN int +lws_mqtt_bindata_cmp(const lws_mqtt_str_t *bd1, const lws_mqtt_str_t *bd2); + +LWS_VISIBLE LWS_EXTERN void +lws_mqtt_str_init(lws_mqtt_str_t *s, uint8_t *buf, uint16_t lim, char nf); + +LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * +lws_mqtt_str_create(uint16_t lim); + +LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * +lws_mqtt_str_create_init(uint8_t *buf, uint16_t len, uint16_t lim); + +LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * +lws_mqtt_str_create_cstr_dup(const char *buf, uint16_t lim); + +LWS_VISIBLE LWS_EXTERN uint8_t * +lws_mqtt_str_next(lws_mqtt_str_t *s, uint16_t *budget); + +LWS_VISIBLE LWS_EXTERN int +lws_mqtt_str_advance(lws_mqtt_str_t *s, int n); + +LWS_VISIBLE LWS_EXTERN void +lws_mqtt_str_free(lws_mqtt_str_t **s); + + +/** + * lws_mqtt_client_send_publish() - lws_write a publish packet + * + * \param wsi: the mqtt child wsi + * \param pub: additional information on what we're publishing + * \param buf: payload to send + * \param len: length of data in buf + * \param final: flag indicating this is the last part + * + * Issues part of, or the whole of, a PUBLISH frame. The first part of the + * frame contains the header, and uses the .qos and .payload_len parts of \p pub + * since MQTT requires the frame to specify the PUBLISH message length at the + * start. The \p len paramter may be less than \p pub.payload_len, in which + * case subsequent calls with more payload are needed to complete the frame. + * + * Although the connection is stuck waiting for the remainder, in that it can't + * issue any other frames until the current one is completed, lws returns to the + * event loop normally and can continue the calls with additional payload even + * for huge frames as the data becomes available, consistent with timeout needs + * and latency to start any new frame (even, eg, related to ping / pong). + * + * If you're sending large frames, the OS will typically not allow the data to + * be sent all at once to kernel side. So you should ideally cut the payload + * up into 1 or 2- mtu sized chunks and send that. + * + * Final should be set when you're calling with the last part of the payload. + */ +LWS_VISIBLE LWS_EXTERN int +lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, + const void *buf, uint32_t len, int final); + +/** + * lws_mqtt_client_send_subcribe() - lws_write a subscribe packet + * + * \param wsi: the mqtt child wsi + * \param sub: which topic(s) we want to subscribe to + * + * For topics other child streams have not already subscribed to, send a packet + * to the server asking to subscribe to them. If all topics listed are already + * subscribed to be the shared network connection, just trigger the + * LWS_CALLBACK_MQTT_SUBSCRIBED callback as if a SUBACK had come. + * + * \p sub doesn't need to exist after the return from this function. + */ +LWS_VISIBLE LWS_EXTERN int +lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub); + +/** + * lws_mqtt_client_send_unsubcribe() - lws_write a unsubscribe packet + * + * \param wsi: the mqtt child wsi + * \param sub: which topic(s) we want to unsubscribe from + * + * For topics other child streams are not subscribed to, send a packet + * to the server asking to unsubscribe from them. If all topics + * listed are already subscribed by other child streams on the shared + * network connection, just trigger the LWS_CALLBACK_MQTT_UNSUBSCRIBED + * callback as if a UNSUBACK had come. + * + * \p unsub doesn't need to exist after the return from this function. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_mqtt_client_send_unsubcribe(struct lws *wsi, + const lws_mqtt_subscribe_param_t *unsub); + +#endif /* _LWS_MQTT_H */ diff --git a/thirdparty/include/libwebsockets/lws-netdev.h b/thirdparty/include/libwebsockets/lws-netdev.h new file mode 100755 index 0000000000000000000000000000000000000000..8a0dc03f7590e686a48d5311b4f7a71f4c002d07 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-netdev.h @@ -0,0 +1,283 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_WIFI_MAX_SCAN_TRACK 16 +#define LWS_ETH_ALEN 6 + +typedef uint8_t lws_wifi_ch_t; +typedef int8_t lws_wifi_rssi_t; +struct lws_netdev_instance; + +typedef enum { + LWSNDTYP_UNKNOWN, + LWSNDTYP_WIFI, + LWSNDTYP_ETH, +} lws_netdev_type_t; + +/* + * Base class for netdev configuration + */ + +typedef struct lws_netdev_config { + void *plat_config; +} lws_netdev_config_t; + +/* + * Const Logical generic network interface ops + */ + +typedef struct lws_netdev_ops { + struct lws_netdev_instance * (*create)(struct lws_context *ctx, + const struct lws_netdev_ops *ops, + const char *name, void *platinfo); + int (*configure)(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); + int (*up)(struct lws_netdev_instance *nd); + int (*down)(struct lws_netdev_instance *nd); + int (*event)(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); + /**< these are SMD events coming from lws event loop thread context */ + void (*destroy)(struct lws_netdev_instance **pnd); + int (*connect)(struct lws_netdev_instance *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + void (*scan)(struct lws_netdev_instance *nd); +} lws_netdev_ops_t; + +/* + * Network devices on this platform + * + * We also hold a list of all known network credentials (when they are needed + * because there is a network interface without anything to connect to) and + * the lws_settings instance they are stored in + */ + +typedef struct lws_netdevs { + lws_dll2_owner_t owner; + /**< list of netdevs / lws_netdev_instance_t -based objects */ + + lws_dll2_owner_t owner_creds; + /**< list of known credentials */ + struct lwsac *ac_creds; + /**< lwsac holding retreived credentials settings, or NULL */ + lws_settings_instance_t *si; + + lws_sockaddr46 sa46_dns_resolver; + + uint8_t refcount_creds; + /**< when there are multiple netdevs, must refcount creds in mem */ +} lws_netdevs_t; + +/* + * Base class for an allocated instantiated derived object using lws_netdev_ops, + * ie, a specific ethernet device + */ + +typedef struct lws_netdev_instance { + const char *name; + const lws_netdev_ops_t *ops; + void *platinfo; + lws_dll2_t list; + uint8_t mac[LWS_ETH_ALEN]; + uint8_t type; /* lws_netdev_type_t */ +} lws_netdev_instance_t; + +enum { + LNDIW_ALG_OPEN, + LNDIW_ALG_WPA2, + + LNDIW_MODE_STA = (1 << 0), + LNDIW_MODE_AP = (1 << 1), + LNDIW_UP = (1 << 7), + + LNDIW_ACQ_IPv4 = (1 << 0), + LNDIW_ACQ_IPv6 = (1 << 1), +}; + +/* + * Group AP / Station State + */ + +typedef enum { + LWSNDVWIFI_STATE_INITIAL, + /* + * We should gratuitously try whatever last worked for us, then + * if that fails, worry about the rest of the logic + */ + LWSNDVWIFI_STATE_SCAN, + /* + * Unconnected, scanning: AP known in one of the config slots -> + * configure it, start timeout + LWSNDVWIFI_STATE_STAT, if no AP + * already up in same group with lower MAC, after a random + * period start up our AP (LWSNDVWIFI_STATE_AP) + */ + LWSNDVWIFI_STATE_AP, + /* Trying to be the group AP... periodically do a scan + * LWSNDVWIFI_STATE_AP_SCAN, faster and then slower + */ + LWSNDVWIFI_STATE_AP_SCAN, + /* + * doing a scan while trying to be the group AP... if we see a + * lower MAC being the AP for the same group AP, abandon being + * an AP and join that AP as a station + */ + LWSNDVWIFI_STATE_STAT_GRP_AP, + /* + * We have decided to join another group member who is being the + * AP, as its MAC is lower than ours. This is a stable state, + * but we still do periodic scans + * LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN and will always prefer an + * AP configured in a slot. + */ + LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN, + /* + * We have joined a group member who is doing the AP job... we + * want to check every now and then if a configured AP has + * appeared that we should better use instead. Otherwise stay + * in LWSNDVWIFI_STATE_STAT_GRP_AP + */ + LWSNDVWIFI_STATE_STAT, + /* + * trying to connect to another non-group AP. If we don't get an + * IP within a timeout and retries, mark it as unusable it and go back + */ + LWSNDVWIFI_STATE_STAT_HAPPY, +} lws_netdev_wifi_state_t; + +/* + * Generic WIFI credentials + */ + +typedef struct lws_wifi_creds { + lws_dll2_t list; + + uint8_t bssid[LWS_ETH_ALEN]; + char passphrase[64]; + char ssid[33]; + uint8_t alg; +} lws_wifi_creds_t; + +/* + * Generic WIFI Network Device Instance + */ + +typedef struct lws_netdev_instance_wifi { + lws_netdev_instance_t inst; + lws_dll2_owner_t scan; /* sorted scan results */ + lws_sorted_usec_list_t sul_scan; + + lws_wifi_creds_t *ap_cred; + const char *ap_ip; + + const char *sta_ads; + + char current_attempt_ssid[33]; + uint8_t current_attempt_bssid[LWS_ETH_ALEN]; + + uint8_t flags; + uint8_t state; /* lws_netdev_wifi_state_t */ +} lws_netdev_instance_wifi_t; + +/* + * Logical scan results sorted list item + */ + +typedef struct lws_wifi_sta { + lws_dll2_t list; + + uint32_t last_seen; /* unix time */ + uint32_t last_tried; /* unix time */ + + uint8_t bssid[LWS_ETH_ALEN]; + char *ssid; /* points to overallocation */ + uint8_t ssid_len; + lws_wifi_ch_t ch; + lws_wifi_rssi_t rssi[8]; + int16_t rssi_avg; + uint8_t authmode; + + uint8_t rssi_count; + uint8_t rssi_next; + + /* ssid overallocated afterwards */ +} lws_wifi_sta_t; + +#define rssi_averaged(_x) (_x->rssi_count ? \ + ((int)_x->rssi_avg / (int)_x->rssi_count) : \ + -200) + +LWS_VISIBLE LWS_EXTERN lws_netdevs_t * +lws_netdevs_from_ctx(struct lws_context *ctx); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_set(lws_netdevs_t *nds); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_get(lws_netdevs_t *nds); + +LWS_VISIBLE LWS_EXTERN struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_connect_plat(lws_netdev_instance_t *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + +LWS_VISIBLE LWS_EXTERN lws_netdev_instance_t * +lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname); + +#define lws_netdev_wifi_plat_ops \ + .create = lws_netdev_wifi_create_plat, \ + .configure = lws_netdev_wifi_configure_plat, \ + .event = lws_netdev_wifi_event_plat, \ + .up = lws_netdev_wifi_up_plat, \ + .down = lws_netdev_wifi_down_plat, \ + .connect = lws_netdev_wifi_connect_plat, \ + .scan = lws_netdev_wifi_scan_plat, \ + .destroy = lws_netdev_wifi_destroy_plat + +/* + * This is for plat / OS level init that is necessary to be able to use + * networking or wifi at all, without mentioning any specific device + */ + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_init(void); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_wifi_init(void); diff --git a/thirdparty/include/libwebsockets/lws-network-helper.h b/thirdparty/include/libwebsockets/lws-network-helper.h new file mode 100755 index 0000000000000000000000000000000000000000..4ad16bef836b6cb4727e6dde8a4f9bfe18eb6d8f --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-network-helper.h @@ -0,0 +1,246 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/** \defgroup net Network related helper APIs + * ##Network related helper APIs + * + * These wrap miscellaneous useful network-related functions + */ +///@{ + +#if defined(LWS_ESP_PLATFORM) +#include +#endif + +typedef uint8_t lws_route_uidx_t; + +typedef struct lws_dns_score { + uint8_t precedence; + uint8_t label; +} lws_dns_score_t; + +/* + * This represents an entry in the system routing table + */ + +typedef struct lws_route { + lws_dll2_t list; + + lws_sockaddr46 src; + lws_sockaddr46 dest; + lws_sockaddr46 gateway; + + struct lws_route *source; /* when used as lws_dns_sort_t */ + lws_dns_score_t score; /* when used as lws_dns_sort_t */ + + int if_idx; + int priority; + int ifa_flags; /* if source_ads */ + + lws_route_uidx_t uidx; /* unique index for this route */ + + uint8_t proto; + uint8_t dest_len; + uint8_t src_len; + uint8_t scope; /* if source_ads */ + uint8_t af; /* if source_ads */ + + uint8_t source_ads:1; +} lws_route_t; + +/* + * We reuse the route object as the dns sort granule, so there's only one + * struct needs to know all the gnarly ipv6 details + */ + +typedef lws_route_t lws_dns_sort_t; + +/** + * lws_canonical_hostname() - returns this host's hostname + * + * This is typically used by client code to fill in the host parameter + * when making a client connection. You can only call it after the context + * has been created. + * + * \param context: Websocket context + */ +LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT +lws_canonical_hostname(struct lws_context *context); + +/** + * lws_get_peer_addresses() - Get client address information + * \param wsi: Local struct lws associated with + * \param fd: Connection socket descriptor + * \param name: Buffer to take client address name + * \param name_len: Length of client address name buffer + * \param rip: Buffer to take client address IP dotted quad + * \param rip_len: Length of client address IP buffer + * + * This function fills in name and rip with the name and IP of + * the client connected with socket descriptor fd. Names may be + * truncated if there is not enough room. If either cannot be + * determined, they will be returned as valid zero-length strings. + */ +LWS_VISIBLE LWS_EXTERN void +lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name, + int name_len, char *rip, int rip_len); + +/** + * lws_get_peer_simple() - Get client address information without RDNS + * + * \param wsi: Local struct lws associated with + * \param name: Buffer to take client address name + * \param namelen: Length of client address name buffer + * + * This provides a 123.123.123.123 type IP address in name from the + * peer that has connected to wsi + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_get_peer_simple(struct lws *wsi, char *name, size_t namelen); + +LWS_VISIBLE LWS_EXTERN const char * +lws_get_peer_simple_fd(lws_sockfd_type fd, char *name, size_t namelen); + +#define LWS_ITOSA_USABLE 0 +#define LWS_ITOSA_NOT_EXIST -1 +#define LWS_ITOSA_NOT_USABLE -2 +#define LWS_ITOSA_BUSY -3 /* only returned by lws_socket_bind() on + EADDRINUSE */ + +#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) +/** + * lws_interface_to_sa() - Convert interface name or IP to sockaddr struct + * + * \param ipv6: Allow IPV6 addresses + * \param ifname: Interface name or IP + * \param addr: struct sockaddr_in * to be written + * \param addrlen: Length of addr + * + * This converts a textual network interface name to a sockaddr usable by + * other network functions. + * + * If the network interface doesn't exist, it will return LWS_ITOSA_NOT_EXIST. + * + * If the network interface is not usable, eg ethernet cable is removed, it + * may logically exist but not have any IP address. As such it will return + * LWS_ITOSA_NOT_USABLE. + * + * If the network interface exists and is usable, it will return + * LWS_ITOSA_USABLE. + */ +LWS_VISIBLE LWS_EXTERN int +lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, + size_t addrlen); +#endif + +/** + * lws_sa46_compare_ads() - checks if two sa46 have the same address + * + * \param sa46a: first + * \param sa46b: second + * + * Returns 0 if the address family is INET or INET6 and the address is the same, + * or if the AF is the same but not INET or INET6, otherwise nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b); + +/** + * lws_sa46_on_net() - checks if an sa46 is on the subnet represented by another + * + * \param sa46a: first + * \param sa46_net: network + * \param net_len: length of network non-mask + * + * Returns 0 if sa46a belongs on network sa46_net/net_len + * + * If there is an ipv4 / v6 mismatch between the ip and the net, the ipv4 + * address is promoted to ::ffff:x.x.x.x before the comparison. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sa46_on_net(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46_net, + int net_len); + +/* + * lws_parse_numeric_address() - converts numeric ipv4 or ipv6 to byte address + * + * \param ads: the numeric ipv4 or ipv6 address string + * \param result: result array + * \param max_len: max length of result array + * + * Converts a 1.2.3.4 or 2001:abcd:123:: or ::ffff:1.2.3.4 formatted numeric + * address into an array of network ordered byte address elements. + * + * Returns < 0 on error, else length of result set, either 4 or 16 for ipv4 / + * ipv6. + */ +LWS_VISIBLE LWS_EXTERN int +lws_parse_numeric_address(const char *ads, uint8_t *result, size_t max_len); + +/* + * lws_sa46_parse_numeric_address() - converts numeric ipv4 or ipv6 to sa46 + * + * \param ads: the numeric ipv4 or ipv6 address string + * \param sa46: pointer to sa46 to set + * + * Converts a 1.2.3.4 or 2001:abcd:123:: or ::ffff:1.2.3.4 formatted numeric + * address into an sa46, a union of sockaddr_in or sockaddr_in6 depending on + * what kind of address was found. sa46->sa4.sin_fmaily will be AF_INET if + * ipv4, or AF_INET6 if ipv6. + * + * Returns 0 if the sa46 was set, else < 0 on error. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46); + +/** + * lws_write_numeric_address() - convert network byte order ads to text + * + * \param ads: network byte order address array + * \param size: number of bytes valid in ads + * \param buf: result buffer to take text format + * \param len: max size of text buffer + * + * Converts an array of network-ordered byte address elements to a textual + * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 + * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + */ +LWS_VISIBLE LWS_EXTERN int +lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); + +/** + * lws_sa46_write_numeric_address() - convert sa46 ads to textual numeric ads + * + * \param sa46: the sa46 whose address to show + * \param buf: result buffer to take text format + * \param len: max size of text buffer + * + * Converts the ipv4 or ipv6 address in an lws_sockaddr46 to a textual + * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 + * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-optee.h b/thirdparty/include/libwebsockets/lws-optee.h new file mode 100755 index 0000000000000000000000000000000000000000..1f58194721f5f470b0490571c0d48064d625d093 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-optee.h @@ -0,0 +1,77 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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 __LWS_OPTEE_H +#define __LWS_OPTEE_H + +/* 128-bit IP6 address */ +struct in6_addr { + union { + uint8_t u6_addr8[16]; + uint16_t u6_addr16[8]; + uint32_t u6_addr32[4]; + }; +}; + +#define _SS_MAXSIZE 128U +#define _SS_ALIGNSIZE (sizeof(int64_t)) +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - \ + sizeof(sa_family_t)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - \ + sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE) + +struct sockaddr_storage { + sa_family_t ss_family; /* address family */ + char __ss_pad1[_SS_PAD1SIZE]; + int64_t __ss_align; /* force desired struct alignment */ + char __ss_pad2[_SS_PAD2SIZE]; +}; + +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr { + sa_family_t sa_family; /* address family */ + uint8_t sa_data[__SOCK_SIZE__ /* address value */ + - sizeof(sa_family_t)]; +}; + +/* 16 bytes */ +struct sockaddr_in { + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + uint8_t sin_zero[__SOCK_SIZE__ /* padding until 16 bytes */ + - sizeof(sa_family_t) + - sizeof(in_port_t) + - sizeof(struct in_addr)]; +}; + +struct sockaddr_in6 { + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IP6 flow information */ + struct in6_addr sin6_addr; /* IP6 address */ + uint32_t sin6_scope_id; /* scope zone index */ +}; + +#endif /* __LWS_OPTEE_H */ diff --git a/thirdparty/include/libwebsockets/lws-protocols-plugins.h b/thirdparty/include/libwebsockets/lws-protocols-plugins.h new file mode 100755 index 0000000000000000000000000000000000000000..66240c9673ea9f0e0c28aef0052d69e531990b4a --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-protocols-plugins.h @@ -0,0 +1,383 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup Protocols-and-Plugins Protocols and Plugins + * \ingroup lwsapi + * + * ##Protocol and protocol plugin -related apis + * + * Protocols bind ws protocol names to a custom callback specific to that + * protocol implementaion. + * + * A list of protocols can be passed in at context creation time, but it is + * also legal to leave that NULL and add the protocols and their callback code + * using plugins. + * + * Plugins are much preferable compared to cut and pasting code into an + * application each time, since they can be used standalone. + */ +///@{ +/** struct lws_protocols - List of protocols and handlers client or server + * supports. */ + +struct lws_protocols { + const char *name; + /**< Protocol name that must match the one given in the client + * Javascript new WebSocket(url, 'protocol') name. */ + lws_callback_function *callback; + /**< The service callback used for this protocol. It allows the + * service action for an entire protocol to be encapsulated in + * the protocol-specific callback */ + size_t per_session_data_size; + /**< Each new connection using this protocol gets + * this much memory allocated on connection establishment and + * freed on connection takedown. A pointer to this per-connection + * allocation is passed into the callback in the 'user' parameter */ + size_t rx_buffer_size; + /**< lws allocates this much space for rx data and informs callback + * when something came. Due to rx flow control, the callback may not + * be able to consume it all without having to return to the event + * loop. That is supported in lws. + * + * If .tx_packet_size is 0, this also controls how much may be sent at + * once for backwards compatibility. + */ + unsigned int id; + /**< ignored by lws, but useful to contain user information bound + * to the selected protocol. For example if this protocol was + * called "myprotocol-v2", you might set id to 2, and the user + * code that acts differently according to the version can do so by + * switch (wsi->a.protocol->id), user code might use some bits as + * capability flags based on selected protocol version, etc. */ + void *user; /**< ignored by lws, but user code can pass a pointer + here it can later access from the protocol callback */ + size_t tx_packet_size; + /**< 0 indicates restrict send() size to .rx_buffer_size for backwards- + * compatibility. + * If greater than zero, a single send() is restricted to this amount + * and any remainder is buffered by lws and sent afterwards also in + * these size chunks. Since that is expensive, it's preferable + * to restrict one fragment you are trying to send to match this + * size. + */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility */ +}; + +#define LWS_PROTOCOL_LIST_TERM { NULL, NULL, 0, 0, 0, NULL, 0 } + +/** + * lws_vhost_name_to_protocol() - get vhost's protocol object from its name + * + * \param vh: vhost to search + * \param name: protocol name + * + * Returns NULL or a pointer to the vhost's protocol of the requested name + */ +LWS_VISIBLE LWS_EXTERN const struct lws_protocols * +lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name); + +/** + * lws_get_protocol() - Returns a protocol pointer from a websocket + * connection. + * \param wsi: pointer to struct websocket you want to know the protocol of + * + * + * Some apis can act on all live connections of a given protocol, + * this is how you can get a pointer to the active protocol if needed. + */ +LWS_VISIBLE LWS_EXTERN const struct lws_protocols * +lws_get_protocol(struct lws *wsi); + +/** lws_protocol_get() - deprecated: use lws_get_protocol */ +LWS_VISIBLE LWS_EXTERN const struct lws_protocols * +lws_protocol_get(struct lws *wsi) LWS_WARN_DEPRECATED; + +/** + * lws_protocol_vh_priv_zalloc() - Allocate and zero down a protocol's per-vhost + * storage + * \param vhost: vhost the instance is related to + * \param prot: protocol the instance is related to + * \param size: bytes to allocate + * + * Protocols often find it useful to allocate a per-vhost struct, this is a + * helper to be called in the per-vhost init LWS_CALLBACK_PROTOCOL_INIT + */ +LWS_VISIBLE LWS_EXTERN void * +lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, + const struct lws_protocols *prot, int size); + +/** + * lws_protocol_vh_priv_get() - retreive a protocol's per-vhost storage + * + * \param vhost: vhost the instance is related to + * \param prot: protocol the instance is related to + * + * Recover a pointer to the allocated per-vhost storage for the protocol created + * by lws_protocol_vh_priv_zalloc() earlier + */ +LWS_VISIBLE LWS_EXTERN void * +lws_protocol_vh_priv_get(struct lws_vhost *vhost, + const struct lws_protocols *prot); + +/** + * lws_vhd_find_by_pvo() - find a partner vhd + * + * \param cx: the lws_context + * \param protname: the name of the lws_protocol the vhd belongs to + * \param pvo_name: the name of a pvo that must exist bound to the vhd + * \param pvo_value: the required value of the named pvo + * + * This allows architectures with multiple protocols bound together to + * cleanly discover partner protocol instances even on completely + * different vhosts. For example, a proxy may consist of two protocols + * listening on different vhosts, and there may be multiple instances + * of the proxy in the same process. It's desirable that each side of + * the proxy is an independent protocol that can be freely bound to any + * vhost, eg, allowing Unix Domain to tls / h2 proxying, or each side + * bound to different network interfaces for localhost-only visibility + * on one side, using existing vhost management. + * + * That leaves the problem that the two sides have to find each other + * and bind at runtime. This api allows each side to specify the + * protocol name, and a common pvo name and pvo value that indicates + * the two sides belong together, and search through all the instantiated + * vhost-protocols looking for a match. If found, the private allocation + * (aka "vhd" of the match is returned). NULL is returned on no match. + * + * Since this can only succeed when called by the last of the two + * protocols to be instantiated, both sides should call it and handle + * NULL gracefully, since it may mean that they were first and their + * partner vhsot-protocol has not been instantiated yet. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_vhd_find_by_pvo(struct lws_context *cx, const char *protname, + const char *pvo_name, const char *pvo_value); + + +/** + * lws_adjust_protocol_psds - change a vhost protocol's per session data size + * + * \param wsi: a connection with the protocol to change + * \param new_size: the new size of the per session data size for the protocol + * + * Returns user_space for the wsi, after allocating + * + * This should not be used except to initalize a vhost protocol's per session + * data size one time, before any connections are accepted. + * + * Sometimes the protocol wraps another protocol and needs to discover and set + * its per session data size at runtime. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_adjust_protocol_psds(struct lws *wsi, size_t new_size); + +/** + * lws_finalize_startup() - drop initial process privileges + * + * \param context: lws context + * + * This is called after the end of the vhost protocol initializations, but + * you may choose to call it earlier + */ +LWS_VISIBLE LWS_EXTERN int +lws_finalize_startup(struct lws_context *context); + +/** + * lws_pvo_search() - helper to find a named pvo in a linked-list + * + * \param pvo: the first pvo in the linked-list + * \param name: the name of the pvo to return if found + * + * Returns NULL, or a pointer to the name pvo in the linked-list + */ +LWS_VISIBLE LWS_EXTERN const struct lws_protocol_vhost_options * +lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name); + +/** + * lws_pvo_get_str() - retreive a string pvo value + * + * \param in: the first pvo in the linked-list + * \param name: the name of the pvo to return if found + * \param result: pointer to a const char * to get the result if any + * + * Returns 0 if found and *result set, or nonzero if not found + */ +LWS_VISIBLE LWS_EXTERN int +lws_pvo_get_str(void *in, const char *name, const char **result); + +LWS_VISIBLE LWS_EXTERN int +lws_protocol_init(struct lws_context *context); + +#define LWS_PLUGIN_API_MAGIC 191 + +/* + * Abstract plugin header for any kind of plugin class, always at top of + * actual class plugin export type. + * + * The export type object must be exported with the same name as the plugin + * file, eg, libmyplugin.so must export a const one of these as the symbol + * "myplugin". + * + * That is the only expected export from the plugin. + */ + +typedef struct lws_plugin_header { + const char *name; + const char *_class; + const char *lws_build_hash; /* set to LWS_BUILD_HASH */ + + unsigned int api_magic; + /* set to LWS_PLUGIN_API_MAGIC at plugin build time */ + + /* plugin-class specific superclass data follows */ +} lws_plugin_header_t; + +/* + * "lws_protocol_plugin" class export, for lws_protocol implementations done + * as plugins + */ +typedef struct lws_plugin_protocol { + lws_plugin_header_t hdr; + + const struct lws_protocols *protocols; /**< array of supported protocols provided by plugin */ + const struct lws_extension *extensions; /**< array of extensions provided by plugin */ + int count_protocols; /**< how many protocols */ + int count_extensions; /**< how many extensions */ +} lws_plugin_protocol_t; + + +/* + * This is the dynamic, runtime created part of the plugin instantiation. + * These are kept in a linked-list and destroyed with the context. + */ + +struct lws_plugin { + struct lws_plugin *list; /**< linked list */ + + const lws_plugin_header_t *hdr; + + union { +#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP) +#if (UV_VERSION_MAJOR > 0) + uv_lib_t lib; /**< shared library pointer */ +#endif +#endif + void *l; /**< */ + } u; +}; + +/* + * Event lib library plugin type (when LWS_WITH_EVLIB_PLUGINS) + * Public so new event libs can equally be supported outside lws itself + */ + +typedef struct lws_plugin_evlib { + lws_plugin_header_t hdr; + const struct lws_event_loop_ops *ops; +} lws_plugin_evlib_t; + +typedef int (*each_plugin_cb_t)(struct lws_plugin *p, void *user); + +/** + * lws_plugins_init() - dynamically load plugins of matching class from dirs + * + * \param pplugin: pointer to linked-list for this kind of plugin + * \param d: array of directory paths to look in + * \param _class: class string that plugin must declare + * \param filter: NULL, or a string that must appear after the third char of the plugin filename + * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin + * \param each_user: pointer passed to each callback + * + * Allows you to instantiate a class of plugins to a specified linked-list. + * The each callback allows you to init each inistantiated callback and pass a + * pointer each_user to it. + * + * To take down the plugins, pass a pointer to the linked-list head to + * lws_plugins_destroy. + * + * This is used for lws protocol plugins but you can define your own plugin + * class name like "mypluginclass", declare it in your plugin headers, and load + * your own plugins to your own list using this api the same way. + */ +LWS_VISIBLE LWS_EXTERN int +lws_plugins_init(struct lws_plugin **pplugin, const char * const *d, + const char *_class, const char *filter, + each_plugin_cb_t each, void *each_user); + +/** + * lws_plugins_destroy() - dynamically unload list of plugins + * + * \param pplugin: pointer to linked-list for this kind of plugin + * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin + * \param each_user: pointer passed to each callback + * + * Allows you to destroy a class of plugins from a specified linked-list + * created by a call to lws_plugins_init(). + * + * The each callback allows you to deinit each inistantiated callback and pass a + * pointer each_user to it, just before its footprint is destroyed. + */ +LWS_VISIBLE LWS_EXTERN int +lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each, + void *each_user); + +#if defined(LWS_WITH_PLUGINS_BUILTIN) + +/* provide exports for builtin plugin protocols */ + +extern const struct lws_protocols post_demo_protocols[1]; +extern const struct lws_protocols lws_raw_proxy_protocols[1]; +extern const struct lws_protocols lws_status_protocols[1]; +extern const struct lws_protocols lws_mirror_protocols[1]; +extern const struct lws_protocols lws_ssh_base_protocols[2]; +extern const struct lws_protocols post_demo_protocols[1]; +extern const struct lws_protocols dumb_increment_protocols[1]; +extern const struct lws_protocols deaddrop_protocols[1]; +extern const struct lws_protocols lws_raw_test_protocols[1]; +extern const struct lws_protocols lws_sshd_demo_protocols[1]; +extern const struct lws_protocols lws_acme_client_protocols[1]; +extern const struct lws_protocols client_loopback_test_protocols[1]; +extern const struct lws_protocols fulltext_demo_protocols[1]; +extern const struct lws_protocols lws_openmetrics_export_protocols[ +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT) && defined(LWS_ROLE_WS) + 4 +#else +#if defined(LWS_WITH_SERVER) + 3 +#else + 1 +#endif +#endif + ]; + +#define LWSOMPROIDX_DIRECT_HTTP_SERVER 0 +#define LWSOMPROIDX_PROX_HTTP_SERVER 1 +#define LWSOMPROIDX_PROX_WS_SERVER 2 +#define LWSOMPROIDX_PROX_WS_CLIENT 3 + +#endif + +///@} diff --git a/thirdparty/include/libwebsockets/lws-purify.h b/thirdparty/include/libwebsockets/lws-purify.h new file mode 100755 index 0000000000000000000000000000000000000000..68acc60552902a2902dbdde2eafcd00ba6e3419d --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-purify.h @@ -0,0 +1,105 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup pur Sanitize / purify SQL and JSON helpers + * + * ##Sanitize / purify SQL and JSON helpers + * + * APIs for escaping untrusted JSON and SQL safely before use + */ +//@{ + +/** + * lws_sql_purify() - like strncpy but with escaping for sql quotes + * + * \param escaped: output buffer + * \param string: input buffer ('/0' terminated) + * \param len: output buffer max length + * + * Because escaping expands the output string, it's not + * possible to do it in-place, ie, with escaped == string + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_sql_purify(char *escaped, const char *string, size_t len); + +/** + * lws_sql_purify_len() - return length of purified version of input string + * + * \param string: input buffer ('/0' terminated) + * + * Calculates any character escaping without writing it anywhere and returns the + * calculated length of the purified string. + */ +int +lws_sql_purify_len(const char *p); + +/** + * lws_json_purify() - like strncpy but with escaping for json chars + * + * \param escaped: output buffer + * \param string: input buffer ('/0' terminated) + * \param len: output buffer max length + * \param in_used: number of bytes of string we could escape in len + * + * Because escaping expands the output string, it's not + * possible to do it in-place, ie, with escaped == string + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_json_purify(char *escaped, const char *string, int len, int *in_used); + +/** + * lws_json_purify_len() - find out the escaped length of a string + * + * \param string: input buffer ('/0' terminated) + * + * JSON may have to expand escapes by up to 6x the original depending on what + * it is. This doesn't actually do the escaping but goes through the motions + * and computes the length of the escaped string. + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_purify_len(const char *string); + +/** + * lws_filename_purify_inplace() - replace scary filename chars with underscore + * + * \param filename: filename to be purified + * + * Replace scary characters in the filename (it should not be a path) + * with underscore, so it's safe to use. + */ +LWS_VISIBLE LWS_EXTERN void +lws_filename_purify_inplace(char *filename); + +LWS_VISIBLE LWS_EXTERN int +lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf, + size_t len); +LWS_VISIBLE LWS_EXTERN int +lws_plat_write_file(const char *filename, void *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_plat_read_file(const char *filename, void *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_plat_recommended_rsa_bits(void); +///@} diff --git a/thirdparty/include/libwebsockets/lws-pwm.h b/thirdparty/include/libwebsockets/lws-pwm.h new file mode 100755 index 0000000000000000000000000000000000000000..b57635f7b41c60cb371fe7e7022f0f3603f2d044 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-pwm.h @@ -0,0 +1,67 @@ +/* + * Generic PWM controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +typedef struct lws_pwm_map { + _lws_plat_gpio_t gpio; + uint8_t index; + uint8_t active_level; +} lws_pwm_map_t; + +typedef struct lws_pwm_ops { + int (*init)(const struct lws_pwm_ops *lo); + void (*intensity)(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + const lws_pwm_map_t *pwm_map; + uint8_t count_pwm_map; +} lws_pwm_ops_t; + +LWS_VISIBLE LWS_EXTERN int +lws_pwm_plat_init(const struct lws_pwm_ops *lo); + +LWS_VISIBLE LWS_EXTERN void +lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + +#define lws_pwm_plat_ops \ + .init = lws_pwm_plat_init, \ + .intensity = lws_pwm_plat_intensity + +/* + * May be useful for making your own transitions or sequences + */ + +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n); +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_sine(lws_led_seq_phase_t n); + +/* canned sequences that can work out of the box */ + +extern const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow, + lws_pwmseq_sine_endless_fast, + lws_pwmseq_linear_wipe, + lws_pwmseq_sine_up, lws_pwmseq_sine_down, + lws_pwmseq_static_on, + lws_pwmseq_static_half, + lws_pwmseq_static_off; diff --git a/thirdparty/include/libwebsockets/lws-retry.h b/thirdparty/include/libwebsockets/lws-retry.h new file mode 100755 index 0000000000000000000000000000000000000000..386ccdcdc268a3b70c45e63574afad292381bc64 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-retry.h @@ -0,0 +1,95 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +typedef struct lws_retry_bo { + const uint32_t *retry_ms_table; /* base delay in ms */ + uint16_t retry_ms_table_count; /* entries in table */ + uint16_t conceal_count; /* max retries to conceal */ + uint16_t secs_since_valid_ping; /* idle before PING issued */ + uint16_t secs_since_valid_hangup; /* idle before hangup conn */ + uint8_t jitter_percent; /* % additional random jitter */ +} lws_retry_bo_t; + +#define LWS_RETRY_CONCEAL_ALWAYS (0xffff) + +/** + * lws_retry_get_delay_ms() - get next delay from backoff table + * + * \param lws_context: the lws context (used for getting random) + * \param retry: the retry backoff table we are using, or NULL for default + * \param ctry: pointer to the try counter + * \param conceal: pointer to flag set to nonzero if the try should be concealed + * in terms of creating an error + * + * Increments *\p try and retruns the number of ms that should elapse before the + * next connection retry, according to the backoff table \p retry. *\p conceal is + * set if the number of tries is less than the backoff table conceal_count, or + * is zero if it exceeded it. This lets you conceal a certain number of retries + * before alerting the caller there is a problem. + * + * If \p retry is NULL, a default of 3s + (0..300ms jitter) is used. If it's + * non-NULL but jitter_percent is 0, the default of 30% jitter is retained. + */ + +LWS_VISIBLE LWS_EXTERN unsigned int +lws_retry_get_delay_ms(struct lws_context *context, const lws_retry_bo_t *retry, + uint16_t *ctry, char *conceal); + +/** + * lws_retry_sul_schedule() - schedule a sul according to the backoff table + * + * \param lws_context: the lws context (used for getting random) + * \param sul: pointer to the sul to schedule + * \param retry: the retry backoff table we are using, or NULL for default + * \param cb: the callback for when the sul schedule time arrives + * \param ctry: pointer to the try counter + * + * Helper that combines interpreting the retry table with scheduling a sul to + * the computed delay. If conceal is not set, it will not schedule the sul + * and just return 1. Otherwise the sul is scheduled and it returns 0. + */ +LWS_VISIBLE LWS_EXTERN int +lws_retry_sul_schedule(struct lws_context *context, int tid, + lws_sorted_usec_list_t *sul, const lws_retry_bo_t *retry, + sul_cb_t cb, uint16_t *ctry); + +/** + * lws_retry_sul_schedule_retry_wsi() - retry sul schedule helper using wsi + * + * \param wsi: the wsi to set the hrtimer sul on to the next retry interval + * \param sul: pointer to the sul to schedule + * \param cb: the callback for when the sul schedule time arrives + * \param ctry: pointer to the try counter + * + * Helper that uses context, tid and retry policy from a wsi to call + * lws_retry_sul_schedule. + * + * Since a udp connection can have many writes in flight, the retry count and + * the sul used to track each thing that wants to be written have to be handled + * individually, not the wsi. But the retry policy and the other things can + * be filled in from the wsi conveniently. + */ +LWS_VISIBLE LWS_EXTERN int +lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, + sul_cb_t cb, uint16_t *ctry); diff --git a/thirdparty/include/libwebsockets/lws-ring.h b/thirdparty/include/libwebsockets/lws-ring.h new file mode 100755 index 0000000000000000000000000000000000000000..e642f0f24e9bbe34b6e5739723bf290e521cd331 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ring.h @@ -0,0 +1,306 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup lws_ring LWS Ringbuffer APIs + * ##lws_ring: generic ringbuffer struct + * + * Provides an abstract ringbuffer api supporting one head and one or an + * unlimited number of tails. + * + * All of the members are opaque and manipulated by lws_ring_...() apis. + * + * The lws_ring and its buffer is allocated at runtime on the heap, using + * + * - lws_ring_create() + * - lws_ring_destroy() + * + * It may contain any type, the size of the "element" stored in the ring + * buffer and the number of elements is given at creation time. + * + * When you create the ringbuffer, you can optionally provide an element + * destroy callback that frees any allocations inside the element. This is then + * automatically called for elements with no tail behind them, ie, elements + * which don't have any pending consumer are auto-freed. + * + * Whole elements may be inserted into the ringbuffer and removed from it, using + * + * - lws_ring_insert() + * - lws_ring_consume() + * + * You can find out how many whole elements are free or waiting using + * + * - lws_ring_get_count_free_elements() + * - lws_ring_get_count_waiting_elements() + * + * In addition there are special purpose optional byte-centric apis + * + * - lws_ring_next_linear_insert_range() + * - lws_ring_bump_head() + * + * which let you, eg, read() directly into the ringbuffer without needing + * an intermediate bounce buffer. + * + * The accessors understand that the ring wraps, and optimizes insertion and + * consumption into one or two memcpy()s depending on if the head or tail + * wraps. + * + * lws_ring only supports a single head, but optionally multiple tails with + * an API to inform it when the "oldest" tail has moved on. You can give + * NULL where-ever an api asks for a tail pointer, and it will use an internal + * single tail pointer for convenience. + * + * The "oldest tail", which is the only tail if you give it NULL instead of + * some other tail, is used to track which elements in the ringbuffer are + * still unread by anyone. + * + * - lws_ring_update_oldest_tail() + */ +///@{ +struct lws_ring; + +/** + * lws_ring_create(): create a new ringbuffer + * + * \param element_len: the size in bytes of one element in the ringbuffer + * \param count: the number of elements the ringbuffer can contain + * \param destroy_element: NULL, or callback to be called for each element + * that is removed from the ringbuffer due to the + * oldest tail moving beyond it + * + * Creates the ringbuffer and allocates the storage. Returns the new + * lws_ring *, or NULL if the allocation failed. + * + * If non-NULL, destroy_element will get called back for every element that is + * retired from the ringbuffer after the oldest tail has gone past it, and for + * any element still left in the ringbuffer when it is destroyed. It replaces + * all other element destruction code in your user code. + */ +LWS_VISIBLE LWS_EXTERN struct lws_ring * +lws_ring_create(size_t element_len, size_t count, + void (*destroy_element)(void *element)); + +/** + * lws_ring_destroy(): destroy a previously created ringbuffer + * + * \param ring: the struct lws_ring to destroy + * + * Destroys the ringbuffer allocation and the struct lws_ring itself. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ring_destroy(struct lws_ring *ring); + +/** + * lws_ring_get_count_free_elements(): return how many elements can fit + * in the free space + * + * \param ring: the struct lws_ring to report on + * + * Returns how much room is left in the ringbuffer for whole element insertion. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_ring_get_count_free_elements(struct lws_ring *ring); + +/** + * lws_ring_get_count_waiting_elements(): return how many elements can be consumed + * + * \param ring: the struct lws_ring to report on + * \param tail: a pointer to the tail struct to use, or NULL for single tail + * + * Returns how many elements are waiting to be consumed from the perspective + * of the tail pointer given. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_ring_get_count_waiting_elements(struct lws_ring *ring, uint32_t *tail); + +/** + * lws_ring_insert(): attempt to insert up to max_count elements from src + * + * \param ring: the struct lws_ring to report on + * \param src: the array of elements to be inserted + * \param max_count: the number of available elements at src + * + * Attempts to insert as many of the elements at src as possible, up to the + * maximum max_count. Returns the number of elements actually inserted. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_ring_insert(struct lws_ring *ring, const void *src, size_t max_count); + +/** + * lws_ring_consume(): attempt to copy out and remove up to max_count elements + * to src + * + * \param ring: the struct lws_ring to report on + * \param tail: a pointer to the tail struct to use, or NULL for single tail + * \param dest: the array of elements to be inserted. or NULL for no copy + * \param max_count: the number of available elements at src + * + * Attempts to copy out as many waiting elements as possible into dest, from + * the perspective of the given tail, up to max_count. If dest is NULL, the + * copying out is not done but the elements are logically consumed as usual. + * NULL dest is useful in combination with lws_ring_get_element(), where you + * can use the element direct from the ringbuffer and then call this with NULL + * dest to logically consume it. + * + * Increments the tail position according to how many elements could be + * consumed. + * + * Returns the number of elements consumed. + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_ring_consume(struct lws_ring *ring, uint32_t *tail, void *dest, + size_t max_count); + +/** + * lws_ring_get_element(): get a pointer to the next waiting element for tail + * + * \param ring: the struct lws_ring to report on + * \param tail: a pointer to the tail struct to use, or NULL for single tail + * + * Points to the next element that tail would consume, directly in the + * ringbuffer. This lets you write() or otherwise use the element without + * having to copy it out somewhere first. + * + * After calling this, you must call lws_ring_consume(ring, &tail, NULL, 1) + * which will logically consume the element you used up and increment your + * tail (tail may also be NULL there if you use a single tail). + * + * Returns NULL if no waiting element, or a const void * pointing to it. + */ +LWS_VISIBLE LWS_EXTERN const void * +lws_ring_get_element(struct lws_ring *ring, uint32_t *tail); + +/** + * lws_ring_update_oldest_tail(): free up elements older than tail for reuse + * + * \param ring: the struct lws_ring to report on + * \param tail: a pointer to the tail struct to use, or NULL for single tail + * + * If you are using multiple tails, you must use this API to inform the + * lws_ring when none of the tails still need elements in the fifo any more, + * by updating it when the "oldest" tail has moved on. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ring_update_oldest_tail(struct lws_ring *ring, uint32_t tail); + +/** + * lws_ring_get_oldest_tail(): get current oldest available data index + * + * \param ring: the struct lws_ring to report on + * + * If you are initializing a new ringbuffer consumer, you can set its tail to + * this to start it from the oldest ringbuffer entry still available. + */ +LWS_VISIBLE LWS_EXTERN uint32_t +lws_ring_get_oldest_tail(struct lws_ring *ring); + +/** + * lws_ring_next_linear_insert_range(): used to write directly into the ring + * + * \param ring: the struct lws_ring to report on + * \param start: pointer to a void * set to the start of the next ringbuffer area + * \param bytes: pointer to a size_t set to the max length you may use from *start + * + * This provides a low-level, bytewise access directly into the ringbuffer + * allowing direct insertion of data without having to use a bounce buffer. + * + * The api reports the position and length of the next linear range that can + * be written in the ringbuffer, ie, up to the point it would wrap, and sets + * *start and *bytes accordingly. You can then, eg, directly read() into + * *start for up to *bytes, and use lws_ring_bump_head() to update the lws_ring + * with what you have done. + * + * Returns nonzero if no insertion is currently possible. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ring_next_linear_insert_range(struct lws_ring *ring, void **start, + size_t *bytes); + +/** + * lws_ring_bump_head(): used to write directly into the ring + * + * \param ring: the struct lws_ring to operate on + * \param bytes: the number of bytes you inserted at the current head + */ +LWS_VISIBLE LWS_EXTERN void +lws_ring_bump_head(struct lws_ring *ring, size_t bytes); + +LWS_VISIBLE LWS_EXTERN void +lws_ring_dump(struct lws_ring *ring, uint32_t *tail); + +/* + * This is a helper that combines the common pattern of needing to consume + * some ringbuffer elements, move the consumer tail on, and check if that + * has moved any ringbuffer elements out of scope, because it was the last + * consumer that had not already consumed them. + * + * Elements that go out of scope because the oldest tail is now after them + * get garbage-collected by calling the destroy_element callback on them + * defined when the ringbuffer was created. + */ + +#define lws_ring_consume_and_update_oldest_tail(\ + ___ring, /* the lws_ring object */ \ + ___type, /* type of objects with tails */ \ + ___ptail, /* ptr to tail of obj with tail doing consuming */ \ + ___count, /* count of payload objects being consumed */ \ + ___list_head, /* head of list of objects with tails */ \ + ___mtail, /* member name of tail in ___type */ \ + ___mlist /* member name of next list member ptr in ___type */ \ + ) { \ + int ___n, ___m; \ + \ + ___n = lws_ring_get_oldest_tail(___ring) == *(___ptail); \ + lws_ring_consume(___ring, ___ptail, NULL, ___count); \ + if (___n) { \ + uint32_t ___oldest; \ + ___n = 0; \ + ___oldest = *(___ptail); \ + lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \ + ___m = (int)lws_ring_get_count_waiting_elements( \ + ___ring, &(*___ppss)->___mtail); \ + if (___m >= ___n) { \ + ___n = ___m; \ + ___oldest = (*___ppss)->___mtail; \ + } \ + } lws_end_foreach_llp(___ppss, ___mlist); \ + \ + lws_ring_update_oldest_tail(___ring, ___oldest); \ + } \ +} + +/* + * This does the same as the lws_ring_consume_and_update_oldest_tail() + * helper, but for the simpler case there is only one consumer, so one + * tail, and that tail is always the oldest tail. + */ + +#define lws_ring_consume_single_tail(\ + ___ring, /* the lws_ring object */ \ + ___ptail, /* ptr to tail of obj with tail doing consuming */ \ + ___count /* count of payload objects being consumed */ \ + ) { \ + lws_ring_consume(___ring, ___ptail, NULL, ___count); \ + lws_ring_update_oldest_tail(___ring, *(___ptail)); \ +} +///@} diff --git a/thirdparty/include/libwebsockets/lws-secure-streams-client.h b/thirdparty/include/libwebsockets/lws-secure-streams-client.h new file mode 100755 index 0000000000000000000000000000000000000000..adca1db1694a856b4a1deb46713da0cbd1ccac86 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-secure-streams-client.h @@ -0,0 +1,332 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is the headers for secure stream api variants that deal with clients in + * different threads or even different processes. + * + * lws_ss_ when client is directly using the event loop + * lws_sstc_ when client is in a different thread to the event loop + * lws_sspc_ when client is in a different process to the event loop + * + * The client api is almost the same except the slightly diffent names. + */ + +/* + * lws_sspc_ apis... different process + */ + +/* + * Helper translation so user code written to lws_ss_ can be built for + * lws_sspc_ in one step by #define LWS_SS_USE_SSPC before including + */ + +struct lws_sspc_handle; + +#if defined(LWS_SS_USE_SSPC) +#define lws_ss_handle lws_sspc_handle +#define lws_ss_create lws_sspc_create +#define lws_ss_destroy lws_sspc_destroy +#define lws_ss_request_tx lws_sspc_request_tx +#define lws_ss_request_tx_len lws_sspc_request_tx_len +#define lws_ss_client_connect lws_sspc_client_connect +#define lws_ss_get_sequencer lws_sspc_get_sequencer +#define lws_ss_proxy_create lws_sspc_proxy_create +#define lws_ss_get_context lws_sspc_get_context +#define lws_ss_rideshare lws_sspc_rideshare +#define lws_ss_set_metadata lws_sspc_set_metadata +#define lws_ss_get_metadata lws_sspc_get_metadata +#define lws_ss_add_peer_tx_credit lws_sspc_add_peer_tx_credit +#define lws_ss_get_est_peer_tx_credit lws_sspc_get_est_peer_tx_credit +#define lws_ss_start_timeout lws_sspc_start_timeout +#define lws_ss_cancel_timeout lws_sspc_cancel_timeout +#define lws_ss_to_user_object lws_sspc_to_user_object +#define lws_ss_change_handlers lws_sspc_change_handlers +#define lws_smd_ss_rx_forward lws_smd_sspc_rx_forward +#define lws_ss_tag lws_sspc_tag +#define _lws_fi_user_ss_fi _lws_fi_user_sspc_fi +#define lwsl_ss_get_cx lwsl_sspc_get_cx + +LWS_VISIBLE LWS_EXTERN void +lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e); + +LWS_VISIBLE LWS_EXTERN struct lws_log_cx * +lwsl_sspc_get_cx(struct lws_sspc_handle *ss); + +#undef lwsl_ss +#define lwsl_ss lwsl_sspc + +#undef lwsl_hexdump_ss +#define lwsl_hexdump_ss lwsl_hexdump_sspc +#endif + +#define lwsl_sspc(_h, _fil, ...) \ + _lws_log_cx(lwsl_sspc_get_cx(_h), lws_log_prepend_sspc, _h, \ + _fil, __func__, __VA_ARGS__) + +#define lwsl_hexdump_sspc(_h, _fil, _buf, _len) \ + lwsl_hexdump_level_cx(lwsl_sspc_get_cx(_h), \ + lws_log_prepend_sspc, \ + _h, _fil, _buf, _len) + +/* + * lwsl_sspc + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_sspc_err(_w, ...) lwsl_sspc(_w, LLL_ERR, __VA_ARGS__) +#else +#define lwsl_sspc_err(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_sspc_warn(_w, ...) lwsl_sspc(_w, LLL_WARN, __VA_ARGS__) +#else +#define lwsl_sspc_warn(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_sspc_notice(_w, ...) lwsl_sspc(_w, LLL_NOTICE, __VA_ARGS__) +#else +#define lwsl_sspc_notice(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_sspc_info(_w, ...) lwsl_sspc(_w, LLL_INFO, __VA_ARGS__) +#else +#define lwsl_sspc_info(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_sspc_debug(_w, ...) lwsl_sspc(_w, LLL_DEBUG, __VA_ARGS__) +#else +#define lwsl_sspc_debug(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_sspc_parser(_w, ...) lwsl_sspc(_w, LLL_PARSER, __VA_ARGS__) +#else +#define lwsl_sspc_parser(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_sspc_header(_w, ...) lwsl_sspc(_w, LLL_HEADER, __VA_ARGS__) +#else +#define lwsl_sspc_header(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_sspc_ext(_w, ...) lwsl_sspc(_w, LLL_EXT, __VA_ARGS__) +#else +#define lwsl_sspc_ext(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_sspc_client(_w, ...) lwsl_sspc(_w, LLL_CLIENT, __VA_ARGS__) +#else +#define lwsl_sspc_client(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_sspc_latency(_w, ...) lwsl_sspc(_w, LLL_LATENCY, __VA_ARGS__) +#else +#define lwsl_sspc_latency(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_sspc_thread(_w, ...) lwsl_sspc(_w, LLL_THREAD, __VA_ARGS__) +#else +#define lwsl_sspc_thread(_w, ...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_sspc_user(_w, ...) lwsl_sspc(_w, LLL_USER, __VA_ARGS__) +#else +#define lwsl_sspc_user(_w, ...) do {} while(0) +#endif + +#define lwsl_hexdump_sspc_err(_v, ...) lwsl_hexdump_sspc(_v, LLL_ERR, __VA_ARGS__) +#define lwsl_hexdump_sspc_warn(_v, ...) lwsl_hexdump_sspc(_v, LLL_WARN, __VA_ARGS__) +#define lwsl_hexdump_sspc_notice(_v, ...) lwsl_hexdump_sspc(_v, LLL_NOTICE, __VA_ARGS__) +#define lwsl_hexdump_sspc_info(_v, ...) lwsl_hexdump_sspc(_v, LLL_INFO, __VA_ARGS__) +#define lwsl_hexdump_sspc_debug(_v, ...) lwsl_hexdump_sspc(_v, LLL_DEBUG, __VA_ARGS__) + + +LWS_VISIBLE LWS_EXTERN int +lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, + void *opaque_user_data, struct lws_sspc_handle **ppss, + struct lws_sequencer *seq_owner, const char **ppayload_fmt); + +/** + * lws_sspc_destroy() - Destroy secure stream + * + * \param ppss: pointer to lws_ss_t pointer to be destroyed + * + * Destroys the lws_ss_t pointed to by *ppss, and sets *ppss to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_sspc_destroy(struct lws_sspc_handle **ppss); + +/** + * lws_sspc_request_tx() - Schedule stream for tx + * + * \param pss: pointer to lws_ss_t representing stream that wants to transmit + * + * Schedules a write on the stream represented by \p pss. When it's possible to + * write on this stream, the *tx callback will occur with an empty buffer for + * the stream owner to fill in. + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +lws_sspc_request_tx(struct lws_sspc_handle *pss); + +/** + * lws_sspc_request_tx_len() - Schedule stream for tx with length hint + * + * \param h: pointer to handle representing stream that wants to transmit + * \param len: the length of the write in bytes + * + * Schedules a write on the stream represented by \p pss. When it's possible to + * write on this stream, the *tx callback will occur with an empty buffer for + * the stream owner to fill in. + * + * This api variant should be used when it's possible the payload will go out + * over h1 with x-web-form-urlencoded or similar Content-Type. + * + * The serialized, sspc type api actually serializes and forwards the length + * hint to its upstream proxy, where it's available for use to produce the + * internet-capable protocol framing. + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +lws_sspc_request_tx_len(struct lws_sspc_handle *h, unsigned long len); + +/** + * lws_sspc_client_connect() - Attempt the client connect + * + * \param h: secure streams handle + * + * Starts the connection process for the secure stream. Returns 0 if OK or + * nonzero if we have already failed. + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t +lws_sspc_client_connect(struct lws_sspc_handle *h); + +/** + * lws_sspc_get_sequencer() - Return parent sequencer pointer if any + * + * \param h: secure streams handle + * + * Returns NULL if the secure stream is not associated with a sequencer. + * Otherwise returns a pointer to the owning sequencer. You can use this to + * identify which sequencer to direct messages to, from the secure stream + * callback. + */ +LWS_VISIBLE LWS_EXTERN struct lws_sequencer * +lws_sspc_get_sequencer(struct lws_sspc_handle *h); + +/** + * lws_sspc_proxy_create() - Start a unix domain socket proxy for Secure Streams + * + * \param context: lws_context + * + * Creates a vhost that listens on an abstract namespace unix domain socket at + * address "proxy.ss.lws". Client connections to this proxy to Secure Streams + */ +LWS_VISIBLE LWS_EXTERN int +lws_sspc_proxy_create(struct lws_context *context); + +/** + * lws_ss_get_context() - convenience helper to recover the lws context + * + * \h: secure streams handle + * + * Returns the lws context. Dispenses with the need to pass a copy of it into + * your secure streams handler. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_context * +lws_sspc_get_context(struct lws_sspc_handle *h); + +LWS_VISIBLE extern const struct lws_protocols lws_sspc_protocols[2]; + +LWS_VISIBLE LWS_EXTERN const char * +lws_sspc_rideshare(struct lws_sspc_handle *h); + + +/** + * lws_sspc_set_metadata() - allow user to bind external data to defined ss metadata + * + * \h: secure streams handle + * \name: metadata name from the policy + * \value: pointer to user-managed data to bind to name + * \len: length of the user-managed data in value + * + * Binds user-managed data to the named metadata item from the ss policy. + * If present, the metadata item is handled in a protocol-specific way using + * the associated policy information. For example, in the policy + * + * "\"metadata\":" "[" + * "{\"uptag\":" "\"X-Upload-Tag:\"}," + * "{\"ctype\":" "\"Content-Type:\"}," + * "{\"xctype\":" "\"X-Content-Type:\"}" + * "]," + * + * when the policy is using h1 is interpreted to add h1 headers of the given + * name with the value of the metadata on the left. + * + * Return 0 if OK. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, + const void *value, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_sspc_get_metadata(struct lws_sspc_handle *h, const char *name, + const void **value, size_t *len); + +LWS_VISIBLE LWS_EXTERN int +lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add); + +LWS_VISIBLE LWS_EXTERN int +lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_cancel_timeout(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void * +lws_sspc_to_user_object(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void +lws_sspc_change_handlers(struct lws_sspc_handle *h, + lws_ss_state_return_t (*rx)(void *userobj, const uint8_t *buf, + size_t len, int flags), + lws_ss_state_return_t (*tx)(void *userobj, lws_ss_tx_ordinal_t ord, + uint8_t *buf, size_t *len, int *flags), + lws_ss_state_return_t (*state)(void *userobj, void *h_src + /* ss handle type */, + lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack)); + +const char * +lws_sspc_tag(struct lws_sspc_handle *h); diff --git a/thirdparty/include/libwebsockets/lws-secure-streams-policy.h b/thirdparty/include/libwebsockets/lws-secure-streams-policy.h new file mode 100755 index 0000000000000000000000000000000000000000..f84edec993c001c45dee429187f33ecbf8d6ad8f --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-secure-streams-policy.h @@ -0,0 +1,412 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2021 Andy Green + * + * 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. + * + * included from libwebsockets.h + */ + +typedef int (*plugin_auth_status_cb)(struct lws_ss_handle *ss, int status); + +/** + * lws_ss_plugin_auth_t - api for an auth plugin + * + * Auth plugins create and sequence authenticated connections that can carry one + * or more streams to an endpoint. That may involve other connections to other + * places to eg, gather authenticated tokens and then make the real connection + * using the tokens. + * + * The secure stream object contains members to record which auth plugin the + * stream is bound to and an over-allocation of the secure stream object to + * contain the plugin auth private data. + * + * The auth plugin controls the state of the stream connection via the status + * callback, and handles retries. + * + * Network connections may require one kind of auth sequencing, and streams + * inside those connections another kind of auth sequencing depending on their + * role. So the secure stream object allows defining plugins for both kinds. + * + * Streams may disappear at any time and require reauth to bring a new one up. + * The auth plugin sequencer will connect / reconnect either on demand, or from + * the start and after any connectivity loss if any stream using the connection + * has the LWSSSPOLF_NAILED_UP flag. + */ + +#if defined(LWS_WITH_SSPLUGINS) +typedef struct lws_ss_plugin { + struct lws_ss_plugin *next; + const char *name; /**< auth plugin name */ + size_t alloc; /**< size of private allocation */ + + int (*create)(struct lws_ss_handle *ss, void *info, + plugin_auth_status_cb status); + /**< called when the auth plugin is instantiated + and bound to the secure stream. status is + called back with advisory information about + the authenticated stream state as it + proceeds */ + int (*destroy)(struct lws_ss_handle *ss); + /**< called when the related secure stream is + being destroyed, and anything the auth + plugin is doing should also be destroyed */ + int (*munge)(struct lws_ss_handle *ss, char *path, + size_t path_len); + /**< if the plugin needs to munge transactions + that have metadata outside the payload (eg, + add http headers) this callback will give + it the opportunity to do so */ +} lws_ss_plugin_t; +#endif + +/* the public, const metrics policy definition */ + +typedef struct lws_metric_policy { + /* order of first two mandated by JSON policy parsing scope union */ + const struct lws_metric_policy *next; + const char *name; + + const char *report; + + /**< the metrics policy name in the policy, used to bind to it */ + uint64_t us_schedule; + /**< us interval between lws_system metrics api reports */ + + uint32_t us_decay_unit; + /**< how many us to decay avg by half, 0 = no decay */ + uint8_t min_contributors; + /**< before we can judge something is an outlier */ +} lws_metric_policy_t; + +typedef struct lws_ss_x509 { + struct lws_ss_x509 *next; + const char *vhost_name; /**< vhost name using cert ctx */ + const uint8_t *ca_der; /**< DER x.509 cert */ + size_t ca_der_len; /**< length of DER cert */ + uint8_t keep:1; /**< ie, if used in server tls */ +} lws_ss_x509_t; + +enum { + LWSSSPOLF_OPPORTUNISTIC = (1 << 0), + /**< the connection doesn't exist unless client asks to write */ + LWSSSPOLF_NAILED_UP = (1 << 1), + /**< the connection tries to be connected the whole life of the ss */ + LWSSSPOLF_URGENT_TX = (1 << 2), + /**< this connection carries critical tx data */ + LWSSSPOLF_URGENT_RX = (1 << 3), + /**< this connection carries critical rx data */ + LWSSSPOLF_TLS = (1 << 4), + /**< stream must be connected via a tls tunnel */ + LWSSSPOLF_LONG_POLL = (1 << 5), + /**< stream used to receive async rx at arbitrary intervals */ + LWSSSPOLF_AUTH_BEARER = (1 << 6), + /**< for http, use lws_system auth token 0 in authentication: bearer */ + LWSSSPOLF_HTTP_NO_CONTENT_LENGTH = (1 << 7), + /**< don't add any content length even if we have it */ + LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM = (1 << 8), + /**< set the client flag LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM */ + LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR = (1 << 9), + /**< set the client flag LCCSCF_H2_QUIRK_OVERFLOWS_TXCR */ + LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE = (1 << 10), + /**< HPACK decoder state does not end cleanly */ + LWSSSPOLF_HTTP_MULTIPART = (1 << 11), + /**< indicates stream goes out as specifically a multipart mime POST + * section... if the tx has LWSSS_FLAG_COALESCE_CONTINUES flag then more + * multipart sections are expected. Without it, the multipart wrapper + * is closed and the http transaction issue completed when this message + * finishes. */ + LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED = (1 << 12), + /**< set up lws_system client cert */ + LWSSSPOLF_LOCAL_SINK = (1 << 13), + /**< expected to bind to a local sink only */ + LWSSSPOLF_WAKE_SUSPEND__VALIDITY = (1 << 14), + /**< this stream's idle validity checks are critical enough we + * should arrange to wake from suspend to perform them + */ + LWSSSPOLF_SERVER = (1 << 15), + /**< we listen on a socket as a server */ + LWSSSPOLF_ALLOW_REDIRECTS = (1 << 16), + /**< follow redirects */ + LWSSSPOLF_HTTP_MULTIPART_IN = (1 << 17), + /**< handle inbound multipart mime at SS level */ + + LWSSSPOLF_ATTR_LOW_LATENCY = (1 << 18), + /**< stream requires low latency */ + LWSSSPOLF_ATTR_HIGH_THROUGHPUT = (1 << 19), + /**< stream requires high throughput */ + LWSSSPOLF_ATTR_HIGH_RELIABILITY = (1 << 20), + /**< stream requires high reliability */ + LWSSSPOLF_ATTR_LOW_COST = (1 << 21), + /**< stream is not critical and should be handled as cheap as poss */ + LWSSSPOLF_PERF = (1 << 22), + /**< capture and report performace information */ + LWSSSPOLF_DIRECT_PROTO_STR = (1 << 23), + /**< metadata as direct protocol string, e.g. http header */ + LWSSSPOLF_HTTP_CACHE_COOKIES = (1 << 24), + /**< Record http cookies and pass them back on future requests */ + LWSSSPOLF_PRIORITIZE_READS = (1 << 25), + /**< prioritize clearing reads at expense of writes */ + +}; + +typedef struct lws_ss_trust_store { + struct lws_ss_trust_store *next; + const char *name; + + const lws_ss_x509_t *ssx509[6]; + int count; +} lws_ss_trust_store_t; + +enum { + LWSSSP_H1, + LWSSSP_H2, + LWSSSP_WS, + LWSSSP_MQTT, + LWSSSP_RAW, + + + LWSSS_HBI_AUTH = 0, + LWSSS_HBI_DSN, + LWSSS_HBI_FWV, + LWSSS_HBI_TYPE, + + _LWSSS_HBI_COUNT /* always last */ +}; + +/* + * This does for both the static policy metadata entry, and the runtime metadata + * handling object. + */ + +typedef struct lws_ss_metadata { + struct lws_ss_metadata *next; + const char *name; + void *value__may_own_heap; + size_t length; + + uint8_t value_length; /* only valid if set by policy */ + uint8_t value_is_http_token; /* valid if set by policy */ +#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) + uint8_t name_on_lws_heap:1; /* proxy metatadata does this */ +#endif + uint8_t value_on_lws_heap:1; /* proxy + rx metadata does this */ +#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) + uint8_t pending_onward:1; +#endif +} lws_ss_metadata_t; + +typedef struct lws_ss_http_respmap { + uint16_t resp; /* the http response code */ + uint16_t state; /* low 16-bits of associated state */ +} lws_ss_http_respmap_t; + +/* + * This is a mapping between an auth streamtype and a name and other information + * that can be independently instantiated. Other streamtypes can indicate they + * require this authentication on their connection. + */ + +typedef struct lws_ss_auth { + struct lws_ss_auth *next; + const char *name; + + const char *type; + const char *streamtype; + uint8_t blob_index; +} lws_ss_auth_t; + +/** + * lws_ss_policy_t: policy database entry for a stream type + * + * Decides the system policy for how to implement connections of name + * .streamtype. + * + * Streams may need one kind of auth sequencing for the network connection and + * another kind of auth sequencing for the streams that are carried inside it, + * this is the purpose of .nauth and .sauth. Both are optional and may be NULL. + * + * An array of these is set at context creation time, ending with one with a + * NULL streamtype. + */ +typedef struct lws_ss_policy { + struct lws_ss_policy *next; + const char *streamtype; /**< stream type lhs to match on */ + + const char *endpoint; /**< DNS address to connect to */ + const char *rideshare_streamtype; /**< optional transport + * on another, preexisting stream of this + * streamtype name */ + const char *payload_fmt; + const char *socks5_proxy; + lws_ss_metadata_t *metadata; /* linked-list of metadata */ + const lws_metric_policy_t *metrics; /* linked-list of metric policies */ + const lws_ss_auth_t *auth; /* NULL or auth object we bind to */ + + /* protocol-specific connection policy details */ + + union { + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_WS) + + /* details for http-related protocols... */ + + struct { + + /* common to all http-related protocols */ + + const char *method; + const char *url; + + const char *multipart_name; + const char *multipart_filename; + const char *multipart_content_type; + + const char *blob_header[_LWSSS_HBI_COUNT]; + const char *auth_preamble; + + const lws_ss_http_respmap_t *respmap; + + union { +// struct { /* LWSSSP_H1 */ +// } h1; +// struct { /* LWSSSP_H2 */ +// } h2; + struct { /* LWSSSP_WS */ + const char *subprotocol; + uint8_t binary; + /* false = TEXT, true = BINARY */ + } ws; + } u; + + uint16_t resp_expect; + uint8_t count_respmap; + uint8_t fail_redirect:1; + } http; + +#endif + +#if defined(LWS_ROLE_MQTT) + + struct { + const char *topic; /* stream sends on this topic */ + const char *subscribe; /* stream subscribes to this topic */ + + const char *will_topic; + const char *will_message; + + uint16_t keep_alive; + uint8_t qos; + uint8_t clean_start; + uint8_t will_qos; + uint8_t will_retain; + uint8_t aws_iot; + + } mqtt; + +#endif + + /* details for non-http related protocols... */ + } u; + +#if defined(LWS_WITH_SSPLUGINS) + const + struct lws_ss_plugin *plugins[2]; /**< NULL or auth plugin */ + const void *plugins_info[2]; /**< plugin-specific data */ +#endif + +#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) + /* directly point to the metadata name, no need to expand */ + const char *aws_region; + const char *aws_service; +#endif + /* + * We're either a client connection policy that wants a trust store, + * or we're a server policy that wants a mem cert and key... Hold + * these mutually-exclusive things in a union. + */ + + union { + const lws_ss_trust_store_t *store; + /**< CA certs needed for conn validation, only set between + * policy parsing and vhost creation */ + struct { + const lws_ss_x509_t *cert; + /**< the server's signed cert with the pubkey */ + const lws_ss_x509_t *key; + /**< the server's matching private key */ + } server; + } trust; + + const lws_retry_bo_t *retry_bo; /**< retry policy to use */ + + uint32_t proxy_buflen; /**< max dsh alloc for proxy */ + uint32_t proxy_buflen_rxflow_on_above; + uint32_t proxy_buflen_rxflow_off_below; + + uint32_t client_buflen; /**< max dsh alloc for client */ + uint32_t client_buflen_rxflow_on_above; + uint32_t client_buflen_rxflow_off_below; + + + uint32_t timeout_ms; /**< default message response + * timeout in ms */ + uint32_t flags; /**< stream attribute flags */ + + uint16_t port; /**< endpoint port */ + + uint8_t metadata_count; /**< metadata count */ + uint8_t protocol; /**< protocol index */ + uint8_t client_cert; /**< which client cert to apply + 0 = none, 1+ = cc 0+ */ + uint8_t priority; /* 0 = normal, 6 = max normal, + * 7 = network management */ +} lws_ss_policy_t; + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + +/* + * These only exist / have meaning if there's a dynamic JSON policy enabled + */ + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_begin(struct lws_context *context, int overlay); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_abandon(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay); + +/* + * You almost certainly don't want these, they return the first policy or auth + * object in a linked-list of objects created by lws_ss_policy_parse above, + * they are exported to generate static policy with + */ +LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t * +lws_ss_policy_get(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN const lws_ss_auth_t * +lws_ss_auth_get(struct lws_context *context); + +#endif diff --git a/thirdparty/include/libwebsockets/lws-secure-streams.h b/thirdparty/include/libwebsockets/lws-secure-streams.h new file mode 100755 index 0000000000000000000000000000000000000000..8157c70028e35d9ec341864716994d33cbdf3eaa --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-secure-streams.h @@ -0,0 +1,846 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * included from libwebsockets.h + * + * + * Secure Streams is a *payload-only* client communication channel where all the + * details about the connection are held in a systemwide policy database and + * are keyed by the streamtype field... the user of the communication channel + * does not know or manage the choice of endpoint, tls CA, or even wire + * protocol. The advantage is he then does not have any dependency on any of + * those and they can be changed just by changing the policy database without + * touching the code using the stream. + * + * There are two ways secure streams interfaces to user code: + * + * 1) [Linux / RTOS] the natural, smallest interface is to call back to user + * code that only operates directly from the lws event loop thread context + * (direct callbacks from lws_ss_t) + * + * lws_thread( [user code] ---- lws ) + * + * 2) [Linux] where the user code is in a different process and communicates + * asynchronously via a proxy socket + * + * user_process{ [user code] | shim | socket-}------ lws_process{ lws } + * + * In the second, IPC, case, all packets are prepended by one or more bytes + * indicating the packet type and serializing any associated data, known as + * Serialized Secure Streams or SSS. + * + * Serialized Secure Streams + * ------------------------- + * + * On the transport, adjacent packets may be coalesced, that is, the original + * packet sizes are lost and two or more packets are combined. For that reason + * the serialization format always contains a 1-byte type and then a 2-byte + * frame length. + * + * Client to proxy + * + * - Proxied connection setup + * + * - 0: LWSSS_SER_TXPRE_STREAMTYPE + * - 1: 2-byte MSB-first rest-of-frame length + * - 3: 1-byte Client SSS protocol version (introduced in SSSv1) + * - 4: 4-byte Client PID (introduced in SSSv1) + * - 8: 4-byte MSB-first initial tx credit + * - 12: the streamtype name with no NUL + * + * - Proxied tx + * + * - 0: LWSSS_SER_TXPRE_TX_PAYLOAD + * - 1: 2 byte MSB-first rest-of-frame length + * - 3: 4-byte MSB-first flags + * - 7: 4-byte MSB-first us between client requested write and wrote to proxy + * - 11: 8-byte MSB-first us resolution unix time client wrote to proxy + * - 19: payload + * + * - Proxied secure stream destroy + * + * - 0: LWSSS_SER_TXPRE_DESTROYING + * - 1: 00, 00 + * + * - Proxied metadata - sent when one metadata item set clientside + * + * - 0: LWSSS_SER_TXPRE_METADATA + * - 1: 2-byte MSB-first rest-of-frame length + * - 3: 1-byte metadata name length + * - 4: metadata name + * - ...: metadata value (for rest of packet) + * + * - TX credit management - sent when using tx credit apis, cf METADATA + * + * - 0: LWSSS_SER_TXPRE_TXCR_UPDATE + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte additional tx credit adjust value + * + * - Stream timeout management - forwarded when user applying or cancelling t.o. + * + * - 0: LWSSS_SER_TXPRE_TIMEOUT_UPDATE + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte MSB-first unsigned 32-bit timeout, 0 = use policy, -1 = cancel + * + * - Passing up payload length hint + * + * - 0: LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT + * - 1: 2-byte MSB-first rest-of-frame length 00, 04 + * - 3: 4-byte MSB-first unsigned 32-bit payload length hint + * + * Proxy to client + * + * - Proxied connection setup result + * + * - 0: LWSSS_SER_RXPRE_CREATE_RESULT + * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03) + * - 3: 1 byte result, 0 = success. On failure, proxy will close connection. + * - 4: 4 byte client dsh allocation recommended for stream type, from policy + * (introduced in SSSv1) + * - 8: 2 byte MSB-first initial tx credit + * - 10: if present, comma-sep list of rideshare types from policy + * + * - Proxied rx + * + * - 0: LWSSS_SER_RXPRE_RX_PAYLOAD + * - 1: 2 byte MSB-first rest-of-frame length + * - 3: 4-byte MSB-first flags + * - 7: 4-byte MSB-first us between inbound read and wrote to client + * - 11: 8-byte MSB-first us resolution unix time proxy wrote to client + * - 17: (rideshare name len + rideshare name if flags & LWSSS_FLAG_RIDESHARE) + * payload + * + * - Proxied tx credit + * + * - 0: LWSSS_SER_RXPRE_TXCR_UPDATE + * - 1: 00, 04 + * - 3: 4-byte MSB-first addition tx credit bytes + * + * - Proxied rx metadata + * + * - 0: LWSSS_SER_RXPRE_METADATA + * - 1: 2-byte MSB-first rest-of-frame length + * - 3: 1-byte metadata name length + * - 4: metadata name + * - ...: metadata value (for rest of packet) + * + * - Proxied state (8 or 11 byte packet) + * + * - 0: LWSSS_SER_RXPRE_CONNSTATE + * - 1: 00, 05 if state < 256, else 00, 08 + * - 3: 1 byte state index if state < 256, else 4-byte MSB-first state index + * - 4 or 7: 4-byte MSB-first ordinal + * + * - Proxied performance information + * + * - 0: LWSSS_SER_RXPRE_PERF + * - 1: 2-byte MSB-first rest-of-frame length + * - 3: ... performance JSON (for rest of packet) + * + * Proxied tx may be read by the proxy but rejected due to lack of buffer space + * at the proxy. For that reason, tx must be held at the sender until it has + * been acknowledged or denied. + * + * Sinks + * ----- + * + * Sinks are logical "servers", you can register as a sink for a particular + * streamtype by using the lws_ss_create() api with ssi->register_sink set to 1. + * + * For directly fulfilled Secure Streams, new streams of that streamtype bind + * to the rx, tx and state handlers given when it was registered. + * + * - When new streams are created the registered sink handler for (*state) is + * called with event LWSSSCS_SINK_JOIN and the new client stream handle in + * the h_src parameter. + * + * - When the client stream sends something to the sink, it calls the sink's + * (*rx) with the client stream's + */ + +/** \defgroup secstr Secure Streams +* ##Secure Streams +* +* Secure Streams related apis +*/ +///@{ + +#define LWS_SS_MTU 1540 + +struct lws_ss_handle; +typedef uint32_t lws_ss_tx_ordinal_t; + +/* + * connection state events + * + * If you add states, take care about the state names and state transition + * validity enforcement tables too + */ +typedef enum { + /* zero means unset */ + LWSSSCS_CREATING = 1, + LWSSSCS_DISCONNECTED, + LWSSSCS_UNREACHABLE, /* oridinal arg = 1 = caused by dns + * server reachability failure */ + LWSSSCS_AUTH_FAILED, + LWSSSCS_CONNECTED, + LWSSSCS_CONNECTING, + LWSSSCS_DESTROYING, + LWSSSCS_POLL, + LWSSSCS_ALL_RETRIES_FAILED, /* all retries in bo policy failed */ + LWSSSCS_QOS_ACK_REMOTE, /* remote peer received and acked tx */ + LWSSSCS_QOS_NACK_REMOTE, + LWSSSCS_QOS_ACK_LOCAL, /* local proxy accepted our tx */ + LWSSSCS_QOS_NACK_LOCAL, /* local proxy refused our tx */ + LWSSSCS_TIMEOUT, /* optional timeout timer fired */ + + LWSSSCS_SERVER_TXN, + LWSSSCS_SERVER_UPGRADE, /* the server protocol upgraded */ + + LWSSSCS_EVENT_WAIT_CANCELLED, /* somebody called lws_cancel_service */ + + LWSSSCS_UPSTREAM_LINK_RETRY, /* if we are being proxied over some + * intermediate link, this transient + * state may be sent to indicate we are + * waiting to establish that link before + * creation can proceed.. ack is the + * number of ms we have been trying */ + + LWSSSCS_SINK_JOIN, /* sinks get this when a new source + * stream joins the sink */ + LWSSSCS_SINK_PART, /* sinks get this when a new source + * stream leaves the sink */ + + LWSSSCS_USER_BASE = 1000 +} lws_ss_constate_t; + +enum { + LWSSS_FLAG_SOM = (1 << 0), + /* payload contains the start of new message */ + LWSSS_FLAG_EOM = (1 << 1), + /* payload contains the end of message */ + LWSSS_FLAG_POLL = (1 << 2), + /* Not a real transmit... poll for rx if protocol needs it */ + LWSSS_FLAG_RELATED_START = (1 << 3), + /* Appears in a zero-length message indicating a message group of zero + * or more messages is now starting. */ + LWSSS_FLAG_RELATED_END = (1 << 4), + /* Appears in a zero-length message indicating a message group of zero + * or more messages has now finished. */ + LWSSS_FLAG_RIDESHARE = (1 << 5), + /* Serialized payload starts with non-default rideshare name length and + * name string without NUL, then payload */ + LWSSS_FLAG_PERF_JSON = (1 << 6), + /* This RX is JSON performance data, only on streams with "perf" flag + * set */ + + /* + * In the case the secure stream is proxied across a process or thread + * boundary, eg by proxying through a socket for IPC, metadata must be + * carried in-band. A byte is prepended to each rx payload to + * differentiate what it is. + * + * Secure streams where the user is called back directly does not need + * any of this and only pure payloads are passed. + * + * rx (received by client) prepends for proxied connections + */ + + LWSSS_SER_RXPRE_RX_PAYLOAD = 0x55, + LWSSS_SER_RXPRE_CREATE_RESULT, + LWSSS_SER_RXPRE_CONNSTATE, + LWSSS_SER_RXPRE_TXCR_UPDATE, + LWSSS_SER_RXPRE_METADATA, + LWSSS_SER_RXPRE_TLSNEG_ENCLAVE_SIGN, + LWSSS_SER_RXPRE_PERF, + + /* tx (send by client) prepends for proxied connections */ + + LWSSS_SER_TXPRE_STREAMTYPE = 0xaa, + LWSSS_SER_TXPRE_ONWARD_CONNECT, + LWSSS_SER_TXPRE_DESTROYING, + LWSSS_SER_TXPRE_TX_PAYLOAD, + LWSSS_SER_TXPRE_METADATA, + LWSSS_SER_TXPRE_TXCR_UPDATE, + LWSSS_SER_TXPRE_TIMEOUT_UPDATE, + LWSSS_SER_TXPRE_PAYLOAD_LENGTH_HINT, + LWSSS_SER_TXPRE_TLSNEG_ENCLAVE_SIGNED, +}; + +typedef enum { + LPCSPROX_WAIT_INITIAL_TX = 1, /* after connect, must send streamtype */ + LPCSPROX_REPORTING_FAIL, /* stream creation failed, wait to to tell */ + LPCSPROX_REPORTING_OK, /* stream creation succeeded, wait to to tell */ + LPCSPROX_OPERATIONAL, /* ready for payloads */ + LPCSPROX_DESTROYED, + + LPCSCLI_SENDING_INITIAL_TX, /* after connect, must send streamtype */ + LPCSCLI_WAITING_CREATE_RESULT, /* wait to hear if proxy ss create OK */ + LPCSCLI_LOCAL_CONNECTED, /* we are in touch with the proxy */ + LPCSCLI_ONWARD_CONNECT, /* request onward ss connection */ + LPCSCLI_OPERATIONAL, /* ready for payloads */ + +} lws_ss_conn_states_t; + +/* + * Returns from state() callback can tell the caller what the user code + * wants to do + */ + +typedef enum lws_ss_state_return { + LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only, or failure */ + + LWSSSSRET_OK = 0, /* no error */ + LWSSSSRET_DISCONNECT_ME = -1, /* caller should disconnect us */ + LWSSSSRET_DESTROY_ME = -2, /* caller should destroy us */ +} lws_ss_state_return_t; + +/** + * lws_ss_info_t: information about stream to be created + * + * Prepare this struct with information about what the stream type is and how + * the stream should interface with your code, and pass it to lws_ss_create() + * to create the requested stream. + */ + +enum { + LWSSSINFLAGS_REGISTER_SINK = (1 << 0), + /**< If set, we're not creating a specific stream, but registering + * ourselves as the "sink" for .streamtype. It's analogous to saying + * we want to be the many-to-one "server" for .streamtype; when other + * streams are created with that streamtype, they should be forwarded + * to this stream owner, where they join and part from the sink via + * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle + * being provided in the h_src parameter. + */ + LWSSSINFLAGS_PROXIED = (1 << 1), + /**< Set if the stream is being created as a stand-in at the proxy */ + LWSSSINFLAGS_SERVER = (1 << 2), + /**< Set on the server object copy of the ssi / info to indicate that + * stream creation using this ssi is for Accepted connections belonging + * to a server */ + LWSSSINFLAGS_ACCEPTED = (1 << 3), + /**< Set on the accepted object copy of the ssi / info to indicate that + * we are an accepted connection from a server's listening socket */ +}; + +typedef lws_ss_state_return_t (*lws_sscb_rx)(void *userobj, const uint8_t *buf, + size_t len, int flags); +typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj, + lws_ss_tx_ordinal_t ord, + uint8_t *buf, size_t *len, + int *flags); +typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src, + lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack); + +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) +typedef void (*lws_ss_buffer_dump_cb)(void *userobj, const uint8_t *buf, + size_t len, int done); +#endif + +struct lws_ss_policy; + +typedef struct lws_ss_info { + const char *streamtype; /**< type of stream we want to create */ + size_t user_alloc; /**< size of user allocation */ + size_t handle_offset; /**< offset of handle stg in user_alloc type, + set to offsetof(mytype, my_handle_member) */ + size_t opaque_user_data_offset; + /**< offset of opaque user data ptr in user_alloc type, set to + offsetof(mytype, opaque_ud_member) */ + +#if defined(LWS_WITH_SECURE_STREAMS_CPP) + const struct lws_ss_policy *policy; + /**< Normally NULL, or a locally-generated policy to apply to this + * connection instead of a named streamtype */ +#endif + +#if defined(LWS_WITH_SYS_FAULT_INJECTION) + lws_fi_ctx_t fic; + /**< Attach external Fault Injection context to the stream, hierarchy + * is ss->context */ +#endif + + lws_sscb_rx rx; + /**< callback with rx payload for this stream */ + lws_sscb_tx tx; + /**< callback to send payload on this stream... 0 = send as set in + * len and flags, 1 = do not send anything (ie, not even 0 len frame) */ + lws_sscb_state state; + /**< advisory cb about state of stream and QoS status if applicable... + * h_src is only used with sinks and LWSSSCS_SINK_JOIN/_PART events. + * Return nonzero to indicate you want to destroy the stream. */ +#if defined(LWS_WITH_SECURE_STREAMS_BUFFER_DUMP) + lws_ss_buffer_dump_cb dump; + /**< cb to record needed protocol buffer data*/ +#endif + int manual_initial_tx_credit; + /**< 0 = manage any tx credit automatically, nonzero explicitly sets the + * peer stream to have the given amount of tx credit, if the protocol + * can support it. + * + * In the special case of _lws_smd streamtype, this is used to indicate + * the connection's rx class mask. + * */ + uint32_t client_pid; + /**< used in proxy / serialization case to hold the client pid this + * proxied connection is to be tagged with + */ + uint8_t flags; + uint8_t sss_protocol_version; + /**< used in proxy / serialization case to hold the SS serialization + * protocol level to use with this peer... clients automatically request + * the most recent version they were built with + * (LWS_SSS_CLIENT_PROTOCOL_VERSION) and the proxy stores the requested + * version in here + */ + +} lws_ss_info_t; + +/** + * lws_ss_create() - Create secure stream + * + * \param context: the lws context to create this inside + * \param tsi: service thread index to create on (normally 0) + * \param ssi: pointer to lws_ss_info_t filled in with info about desired stream + * \param opaque_user_data: opaque data to set in the stream's user object + * \param ppss: pointer to secure stream handle pointer set on exit + * \param ppayload_fmt: NULL or pointer to a string ptr to take payload format + * name from the policy + * + * Requests a new secure stream described by \p ssi be created. If successful, + * the stream is created, its state callback called with LWSSSCS_CREATING, \p *ppss + * is set to point to the handle, and it returns 0. If it failed, it returns + * nonzero. + * + * Along with the opaque stream object, streams overallocate + * + * 1) a user data struct whose size is set in ssi + * 2) nauth plugin instantiation data (size set in the plugin struct) + * 3) sauth plugin instantiation data (size set in the plugin struct) + * 4) space for a copy of the stream type name + * + * The user data struct is initialized to all zeros, then the .handle_offset and + * .opaque_user_data_offset fields of the ssi are used to prepare the user data + * struct with the ss handle that was created, and a copy of the + * opaque_user_data pointer given as an argument. + * + * If you want to set up the stream with specific information, point to it in + * opaque_user_data and use the copy of that pointer in your user data member + * for it starting from the LWSSSCS_CREATING state call. + * + * Since different endpoints chosen by the policy may require different payload + * formats, \p ppayload_fmt is set to point to the name of the needed payload + * format from the policy database if non-NULL. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, + void *opaque_user_data, struct lws_ss_handle **ppss, + struct lws_sequencer *seq_owner, const char **ppayload_fmt); + +/** + * lws_ss_destroy() - Destroy secure stream + * + * \param ppss: pointer to lws_ss_t pointer to be destroyed + * + * Destroys the lws_ss_t pointed to by \p *ppss, and sets \p *ppss to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_destroy(struct lws_ss_handle **ppss); + +/** + * lws_ss_request_tx() - Schedule stream for tx + * + * \param pss: pointer to lws_ss_t representing stream that wants to transmit + * + * Schedules a write on the stream represented by \p pss. When it's possible to + * write on this stream, the \p *tx callback will occur with an empty buffer for + * the stream owner to fill in. + * + * Returns 0 or LWSSSSRET_DESTROY_ME + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT +lws_ss_request_tx(struct lws_ss_handle *pss); + +/** + * lws_ss_request_tx() - Schedule stream for tx + * + * \param pss: pointer to lws_ss_t representing stream that wants to transmit + * \param len: the length of the write in bytes + * + * Schedules a write on the stream represented by \p pss. When it's possible to + * write on this stream, the \p *tx callback will occur with an empty buffer for + * the stream owner to fill in. + * + * This api variant should be used when it's possible the payload will go out + * over h1 with x-web-form-urlencoded or similar Content-Type. + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT +lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); + +/** + * lws_ss_client_connect() - Attempt the client connect + * + * \param h: secure streams handle + * + * Starts the connection process for the secure stream. + * + * Can return any of the lws_ss_state_return_t values depending on user + * state callback returns. + * + * LWSSSSRET_OK means the connection is ongoing. + * + */ +LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT +lws_ss_client_connect(struct lws_ss_handle *h); + +/** + * lws_ss_get_sequencer() - Return parent sequencer pointer if any + * + * \param h: secure streams handle + * + * Returns NULL if the secure stream is not associated with a sequencer. + * Otherwise returns a pointer to the owning sequencer. You can use this to + * identify which sequencer to direct messages to, from the secure stream + * callback. + */ +LWS_VISIBLE LWS_EXTERN struct lws_sequencer * +lws_ss_get_sequencer(struct lws_ss_handle *h); + +/** + * lws_ss_proxy_create() - Start a unix domain socket proxy for Secure Streams + * + * \param context: lws_context + * \param bind: if port is 0, unix domain path with leading @ for abstract. + * if port nonzero, NULL, or network interface to bind listen to + * \param port: tcp port to listen on + * + * Creates a vhost that listens either on an abstract namespace unix domain + * socket (port = 0) or a tcp listen socket (port nonzero). If bind is NULL + * and port is 0, the abstract unix domain socket defaults to "proxy.ss.lws". + * + * Client connections to this proxy to Secure Streams are fulfilled using the + * policy local to the proxy and the data passed between the client and the + * proxy using serialized Secure Streams protocol. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ss_proxy_create(struct lws_context *context, const char *bind, int port); + +/** + * lws_ss_state_name() - convenience helper to get a printable conn state name + * + * \param state: the connection state index + * + * Returns a printable name for the connection state index passed in. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_ss_state_name(int state); + +/** + * lws_ss_get_context() - convenience helper to recover the lws context + * + * \param h: secure streams handle + * + * Returns the lws context. Dispenses with the need to pass a copy of it into + * your secure streams handler. + */ +LWS_VISIBLE LWS_EXTERN struct lws_context * +lws_ss_get_context(struct lws_ss_handle *h); + +#define LWSSS_TIMEOUT_FROM_POLICY 0 + +/** + * lws_ss_start_timeout() - start or restart the timeout on the stream + * + * \param h: secure streams handle + * \param timeout_ms: LWSSS_TIMEOUT_FROM_POLICY for policy value, else use timeout_ms + * + * Starts or restarts the stream's own timeout timer. If the specified time + * passes without lws_ss_cancel_timeout() being called on the stream, then the + * stream state callback receives LWSSSCS_TIMEOUT + * + * The process being protected by the timeout is up to the user code, it may be + * arbitrarily long and cross multiple protocol transactions or involve other + * streams. It's up to the user to decide when to start and when / if to cancel + * the stream timeout. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms); + +/** + * lws_ss_cancel_timeout() - remove any timeout on the stream + * + * \param h: secure streams handle + * + * Disable any timeout that was applied to the stream by lws_ss_start_timeout(). + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_cancel_timeout(struct lws_ss_handle *h); + +/** + * lws_ss_to_user_object() - convenience helper to get user object from handle + * + * \param h: secure streams handle + * + * Returns the user allocation related to the handle. Normally you won't need + * this since it's available in the rx, tx and state callbacks as "userdata" + * already. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_ss_to_user_object(struct lws_ss_handle *h); + +/** + * lws_ss_rideshare() - find the current streamtype when types rideshare + * + * \param h: the stream handle + * + * Under some conditions, the payloads may be structured using protocol- + * specific formatting, eg, http multipart mime. It's possible to map the + * logical partitions in the payload to different stream types using + * the policy "rideshare" feature. + * + * This api lets the callback code find out which rideshare stream type the + * current payload chunk belongs to. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_ss_rideshare(struct lws_ss_handle *h); + + +/** + * lws_ss_set_metadata() - allow user to bind external data to defined ss metadata + * + * \param h: secure streams handle + * \param name: metadata name from the policy + * \param value: pointer to user-managed data to bind to name + * \param len: length of the user-managed data in value + * + * Binds user-managed data to the named metadata item from the ss policy. + * If present, the metadata item is handled in a protocol-specific way using + * the associated policy information. For example, in the policy + * + * "\"metadata\":" "[" + * "{\"uptag\":" "\"X-Upload-Tag:\"}," + * "{\"ctype\":" "\"Content-Type:\"}," + * "{\"xctype\":" "\"\"}" + * "]," + * + * when the policy is using h1 is interpreted to add h1 headers of the given + * name with the value of the metadata on the left. + * + * Return 0 if OK or nonzero if, eg, metadata name does not exist on the + * streamtype. You must check the result of this, eg, transient OOM can cause + * these to fail and you should retry later. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, + const void *value, size_t len); + +/** + * lws_ss_alloc_set_metadata() - copy data and bind to ss metadata + * + * \param h: secure streams handle + * \param name: metadata name from the policy + * \param value: pointer to user-managed data to bind to name + * \param len: length of the user-managed data in value + * + * Same as lws_ss_set_metadata(), but allocates a heap buffer for the data + * first and takes a copy of it, so the original can go out of scope + * immediately after. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_ss_alloc_set_metadata(struct lws_ss_handle *h, const char *name, + const void *value, size_t len); + +/** + * lws_ss_get_metadata() - get current value of stream metadata item + * + * \param h: secure streams handle + * \param name: metadata name from the policy + * \param value: pointer to pointer to be set to point at the value + * \param len: pointer to size_t to set to the length of the value + * + * Binds user-managed data to the named metadata item from the ss policy. + * If present, the metadata item is handled in a protocol-specific way using + * the associated policy information. For example, in the policy + * + * "\"metadata\":" "[" + * "{\"uptag\":" "\"X-Upload-Tag:\"}," + * "{\"ctype\":" "\"Content-Type:\"}," + * "{\"xctype\":" "\"\"}" + * "]," + * + * when the policy is using h1 is interpreted to add h1 headers of the given + * name with the value of the metadata on the left. + * + * Return 0 if \p *value and \p *len set OK, or nonzero if, eg, metadata \p name does + * not exist on the streamtype. + * + * The pointed-to values may only exist until the next time around the event + * loop. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, + const void **value, size_t *len); + +/** + * lws_ss_server_ack() - indicate how we feel about what the server has sent + * + * \param h: ss handle of accepted connection + * \param nack: 0 means we are OK with it, else some problem + * + * For SERVER secure streams + * + * Depending on the protocol, the server sending us something may be + * transactional, ie, built into it sending something is the idea we will + * respond somehow out-of-band; HTTP is like this with, eg, 200 response code. + * + * Calling this with nack=0 indicates that when we later respond, we want to + * acknowledge the transaction (eg, it means a 200 if http underneath), if + * nonzero that the transaction should act like it failed. + * + * If the underlying protocol doesn't understand transactions (eg, ws) then this + * has no effect either way. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_server_ack(struct lws_ss_handle *h, int nack); + +typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg); + +/** + * lws_ss_server_foreach_client() - callback for each live client connected to server + * + * \param h: server ss handle + * \param cb: the callback + * \param arg: arg passed to callback + * + * For SERVER secure streams + * + * Call the callback \p cb once for each client ss connected to the server, + * passing \p arg as an additional callback argument each time. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, + void *arg); + +/** + * lws_ss_change_handlers() - helper for dynamically changing stream handlers + * + * \param h: ss handle + * \param rx: the new RX handler + * \param tx: the new TX handler + * \param state: the new state handler + * + * Handlers set to NULL are left unchanged. + * + * This works on any handle, client or server and takes effect immediately. + * + * Depending on circumstances this may be helpful when + * + * a) a server stream undergoes an LWSSSCS_SERVER_UPGRADE (as in http -> ws) and + * the payloads in the new protocol have a different purpose that is best + * handled in their own rx and tx callbacks, and + * + * b) you may want to serve several different, possibly large things based on + * what was requested. Setting a customized handler allows clean encapsulation + * of the different serving strategies. + * + * If the stream is long-lived, like ws, you should set the changed handler back + * to the default when the transaction wanting it is completed. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_change_handlers(struct lws_ss_handle *h, lws_sscb_rx rx, lws_sscb_tx tx, + lws_sscb_state state); + +/** + * lws_ss_add_peer_tx_credit() - allow peer to transmit more to us + * + * \param h: secure streams handle + * \param add: additional tx credit (signed) + * + * Indicate to remote peer that we can accept \p add bytes more payload being + * sent to us. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add); + +/** + * lws_ss_get_est_peer_tx_credit() - get our current estimate of peer's tx credit + * + * \param h: secure streams handle + * + * Based on what credit we gave it, and what we have received, report our + * estimate of peer's tx credit usable to transmit to us. This may be outdated + * in that some or all of its credit may already have been expended by sending + * stuff to us that is in flight already. + */ +LWS_VISIBLE LWS_EXTERN int +lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h); + +LWS_VISIBLE LWS_EXTERN const char * +lws_ss_tag(struct lws_ss_handle *h); + + +#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) +/** + * lws_ss_sigv4_set_aws_key() - set aws credential into system blob + * + * \param context: lws_context + * \param idx: the system blob index specified in the policy, currently + * up to 4 blobs. + * \param keyid: aws access keyid + * \param key: aws access key + * + * Return 0 if OK or nonzero if e.g. idx is invalid; system blob heap appending + * fails. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx, + const char * keyid, const char * key); + +/** + * lws_aws_filesystem_credentials_helper() - read aws credentials from file + * + * \param path: path to read, ~ at start is converted to $HOME contents if any + * \param kid: eg, "aws_access_key_id" + * \param ak: eg, "aws_secret_access_key" + * \param aws_keyid: pointer to pointer for allocated keyid from credentials file + * \param aws_key: pointer to pointer for allocated key from credentials file + * + * Return 0 if both *aws_keyid and *aws_key allocated from the config file, else + * nonzero, and neither *aws_keyid or *aws_key are allocated. + * + * If *aws_keyid and *aws_key are set, it's the user's responsibility to + * free() them when they are no longer needed. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_aws_filesystem_credentials_helper(const char *path, const char *kid, + const char *ak, char **aws_keyid, + char **aws_key); + +#endif + +///@} + diff --git a/thirdparty/include/libwebsockets/lws-sequencer.h b/thirdparty/include/libwebsockets/lws-sequencer.h new file mode 100755 index 0000000000000000000000000000000000000000..7189788b99160cfed7d895d7c873e67ebce2fdc3 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-sequencer.h @@ -0,0 +1,243 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + * + * lws_sequencer is intended to help implement sequences that: + * + * - outlive a single connection lifetime, + * - are not associated with a particular protocol, + * - are not associated with a particular vhost, + * - must receive and issue events inside the event loop + * + * lws_sequencer-s are bound to a pt (per-thread) which for the default case of + * one service thread is the same as binding to an lws_context. + */ +/* + * retry backoff table... retry n happens after .retry_ms_table[n] ms, with + * the last entry used if n is greater than the number of entries. + * + * The first .conceal_count retries are concealed, but after that the failures + * are reported. + */ + +typedef enum { + LWSSEQ_CREATED, /* sequencer created */ + LWSSEQ_DESTROYED, /* sequencer destroyed */ + LWSSEQ_TIMED_OUT, /* sequencer timeout */ + LWSSEQ_HEARTBEAT, /* 1Hz callback */ + + LWSSEQ_WSI_CONNECTED, /* wsi we bound to us has connected */ + LWSSEQ_WSI_CONN_FAIL, /* wsi we bound to us has failed to connect */ + LWSSEQ_WSI_CONN_CLOSE, /* wsi we bound to us has closed */ + + + LWSSEQ_SS_STATE_BASE, /* secure streams owned by a sequencer provide + * automatic messages about state changes on + * the sequencer, passing the oridinal in the + * event argument field. The message index is + * LWSSEQ_SS_STATE_BASE + the enum from + * lws_ss_constate_t */ + + LWSSEQ_USER_BASE = 100 /* define your events from here */ +} lws_seq_events_t; + +typedef enum lws_seq_cb_return { + LWSSEQ_RET_CONTINUE, + LWSSEQ_RET_DESTROY +} lws_seq_cb_return_t; + +/* + * handler for this sequencer. Return 0 if OK else nonzero to destroy the + * sequencer. LWSSEQ_DESTROYED will be called back to the handler so it can + * close / destroy any private assets associated with the sequence. + * + * The callback may return either LWSSEQ_RET_CONTINUE for the sequencer to + * resume or LWSSEQ_RET_DESTROY to indicate the sequence is finished. + * + * Event indexes consist of some generic ones but mainly user-defined ones + * starting from LWSSEQ_USER_BASE. + */ +typedef lws_seq_cb_return_t (*lws_seq_event_cb)(struct lws_sequencer *seq, + void *user, int event, void *data, void *aux); + +typedef struct lws_seq_info { + struct lws_context *context; /* lws_context for seq */ + int tsi; /* thread service idx */ + size_t user_size; /* size of user alloc */ + void **puser; /* place ptr to user */ + lws_seq_event_cb cb; /* seq callback */ + const char *name; /* seq name */ + const lws_retry_bo_t *retry; /* retry policy */ + uint8_t wakesuspend:1; /* important enough to + * wake system */ +} lws_seq_info_t; + +/** + * lws_seq_create() - create and bind sequencer to a pt + * + * \param info: information about sequencer to create + * + * This binds an abstract sequencer to a per-thread (by default, the single + * event loop of an lws_context). After the event loop starts, the sequencer + * will receive an LWSSEQ_CREATED event on its callback from the event loop + * context, where it can begin its sequence flow. + * + * Lws itself will only call the callback subsequently with LWSSEQ_DESTROYED + * when the sequencer is being destroyed. + * + * pt locking is used to protect the related data structures. + */ +LWS_VISIBLE LWS_EXTERN struct lws_sequencer * +lws_seq_create(lws_seq_info_t *info); + +/** + * lws_seq_destroy() - destroy the sequencer + * + * \param seq: pointer to the the opaque sequencer pointer returned by + * lws_seq_create() + * + * This proceeds to destroy the sequencer, calling LWSSEQ_DESTROYED and then + * freeing the sequencer object itself. The pointed-to seq pointer will be + * set to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_seq_destroy(struct lws_sequencer **seq); + +/** + * lws_seq_queue_event() - queue an event on the given sequencer + * + * \param seq: the opaque sequencer pointer returned by lws_seq_create() + * \param e: the event index to queue + * \param data: associated opaque (to lws) data to provide the callback + * \param aux: second opaque data to provide the callback + * + * This queues the event on a given sequencer. Queued events are delivered one + * per sequencer each subsequent time around the event loop, so the cb is called + * from the event loop thread context. + * + * Notice that because the events are delivered in order from the event loop, + * the scope of objects pointed to by \p data or \p aux may exceed the lifetime + * of the thing containing the pointed-to data. So it's usually better to pass + * values here. + */ +LWS_VISIBLE LWS_EXTERN int +lws_seq_queue_event(struct lws_sequencer *seq, lws_seq_events_t e, void *data, + void *aux); + +/** + * lws_seq_check_wsi() - check if wsi still extant + * + * \param seq: the sequencer interested in the wsi + * \param wsi: the wsi we want to confirm hasn't closed yet + * + * Check if wsi still extant, by peeking in the message queue for a + * LWSSEQ_WSI_CONN_CLOSE message about wsi. (Doesn't need to do the same for + * CONN_FAIL since that will never have produced any messages prior to that). + * + * Use this to avoid trying to perform operations on wsi that have already + * closed but we didn't get to that message yet. + * + * Returns 0 if not closed yet or 1 if it has closed but we didn't process the + * close message yet. + */ +LWS_VISIBLE LWS_EXTERN int +lws_seq_check_wsi(struct lws_sequencer *seq, struct lws *wsi); + +#define LWSSEQTO_NONE 0 + +/** + * lws_seq_timeout_us() - set a timeout by which the sequence must have + * completed by a different event or inform the + * sequencer + * + * \param seq: The sequencer to set the timeout on + * \param us: How many us in the future to fire the timeout + * LWS_SET_TIMER_USEC_CANCEL = cancel any existing timeout + * + * This api allows the sequencer to ask to be informed if it has not completed + * or disabled its timeout after secs seconds. Lws will send a LWSSEQ_TIMED_OUT + * event to the sequencer if the timeout expires. + * + * Typically the sequencer sets the timeout when starting a step, then waits to + * hear a queued event informing it the step completed or failed. The timeout + * provides a way to deal with the case the step neither completed nor failed + * within the timeout period. + * + * Lws wsi timeouts are not really suitable for this since they are focused on + * short-term protocol timeout protection and may be set and reset many times + * in one transaction. Wsi timeouts also enforce closure of the wsi when they + * trigger, sequencer timeouts have no side effect except to queue the + * LWSSEQ_TIMED_OUT message and leave it to the sequencer to decide how to + * react appropriately. + */ +LWS_VISIBLE LWS_EXTERN int +lws_seq_timeout_us(struct lws_sequencer *seq, lws_usec_t us); + +/** + * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr + * + * \param u: the sequencer user allocation returned by lws_seq_create() or + * provided in the sequencer callback + * + * This gets the lws_seq_t * from the sequencer user allocation pointer. + * Actually these are allocated at the same time in one step, with the user + * allocation immediately after the lws_seq_t, so lws can compute where + * the lws_seq_t is from having the user allocation pointer. Since the + * size of the lws_seq_t is unknown to user code, this helper does it for + * you. + */ +LWS_VISIBLE LWS_EXTERN struct lws_sequencer * +lws_seq_from_user(void *u); + +/** + * lws_seq_us_since_creation(): elapsed seconds since sequencer created + * + * \param seq: pointer to the lws_seq_t + * + * Returns the number of us elapsed since the lws_seq_t was + * created. This is useful to calculate sequencer timeouts for the current + * step considering a global sequencer lifetime limit. + */ +LWS_VISIBLE LWS_EXTERN lws_usec_t +lws_seq_us_since_creation(struct lws_sequencer *seq); + +/** + * lws_seq_name(): get the name of this sequencer + * + * \param seq: pointer to the lws_seq_t + * + * Returns the name given when the sequencer was created. This is useful to + * annotate logging when then are multiple sequencers in play. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_seq_name(struct lws_sequencer *seq); + +/** + * lws_seq_get_context(): get the lws_context sequencer was created on + * + * \param seq: pointer to the lws_seq_t + * + * Returns the lws_context. Saves you having to store it if you have a seq + * pointer handy. + */ +LWS_VISIBLE LWS_EXTERN struct lws_context * +lws_seq_get_context(struct lws_sequencer *seq); diff --git a/thirdparty/include/libwebsockets/lws-service.h b/thirdparty/include/libwebsockets/lws-service.h new file mode 100755 index 0000000000000000000000000000000000000000..2f597b317a20813b1c5cf147d25c89a23d37492b --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-service.h @@ -0,0 +1,202 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup service Built-in service loop entry + * + * ##Built-in service loop entry + * + * If you're not using libev / libuv, these apis are needed to enter the poll() + * wait in lws and service any connections with pending events. + */ +///@{ + +/** + * lws_service() - Service any pending websocket activity + * \param context: Websocket context + * \param timeout_ms: Set to 0; ignored; for backward compatibility + * + * This function deals with any pending websocket traffic, for three + * kinds of event. It handles these events on both server and client + * types of connection the same. + * + * 1) Accept new connections to our context's server + * + * 2) Call the receive callback for incoming frame data received by + * server or client connections. + * + * Since v3.2 internally the timeout wait is ignored, the lws scheduler is + * smart enough to stay asleep until an event is queued. + */ +LWS_VISIBLE LWS_EXTERN int +lws_service(struct lws_context *context, int timeout_ms); + +/** + * lws_service_tsi() - Service any pending websocket activity + * + * \param context: Websocket context + * \param timeout_ms: Set to 0; ignored; for backwards compatibility + * \param tsi: Thread service index, starting at 0 + * + * Same as lws_service(), but for a specific thread service index. Only needed + * if you are spawning multiple service threads. + */ +LWS_VISIBLE LWS_EXTERN int +lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi); + +/** + * lws_cancel_service_pt() - Cancel servicing of pending socket activity + * on one thread + * \param wsi: Cancel service on the thread this wsi is serviced by + * + * Same as lws_cancel_service(), but targets a single service thread, the one + * the wsi belongs to. You probably want to use lws_cancel_service() instead. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cancel_service_pt(struct lws *wsi); + +/** + * lws_cancel_service() - Cancel wait for new pending socket activity + * \param context: Websocket context + * + * This function creates an immediate "synchronous interrupt" to the lws poll() + * wait or event loop. As soon as possible in the serialzed service sequencing, + * a LWS_CALLBACK_EVENT_WAIT_CANCELLED callback is sent to every protocol on + * every vhost. + * + * lws_cancel_service() may be called from another thread while the context + * exists, and its effect will be immediately serialized. + */ +LWS_VISIBLE LWS_EXTERN void +lws_cancel_service(struct lws_context *context); + +/** + * lws_service_fd() - Service polled socket with something waiting + * \param context: Websocket context + * \param pollfd: The pollfd entry describing the socket fd and which events + * happened + * + * This function takes a pollfd that has POLLIN or POLLOUT activity and + * services it according to the state of the associated + * struct lws. + * + * The one call deals with all "service" that might happen on a socket + * including listen accepts, http files as well as websocket protocol. + * + * If a pollfd says it has something, you can just pass it to + * lws_service_fd() whether it is a socket handled by lws or not. + * If it sees it is a lws socket, the traffic will be handled and + * pollfd->revents will be zeroed now. + * + * If the socket is foreign to lws, it leaves revents alone. So you can + * see if you should service yourself by checking the pollfd revents + * after letting lws try to service it. + * + * lws before v3.2 allowed pollfd to be NULL, to indicate that background + * periodic processing should be done. Since v3.2, lws schedules any items + * that need handling in the future using lws_sul and NULL is no longer valid. + */ +LWS_VISIBLE LWS_EXTERN int +lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd); + +/** + * lws_service_fd_tsi() - Service polled socket in specific service thread + * \param context: Websocket context + * \param pollfd: The pollfd entry describing the socket fd and which events + * happened. + * \param tsi: thread service index + * + * Same as lws_service_fd() but used with multiple service threads + */ +LWS_VISIBLE LWS_EXTERN int +lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, + int tsi); + +/** + * lws_service_adjust_timeout() - Check for any connection needing forced service + * \param context: Websocket context + * \param timeout_ms: The original poll timeout value. You can just set this + * to 1 if you don't really have a poll timeout. + * \param tsi: thread service index + * + * Under some conditions connections may need service even though there is no + * pending network action on them, this is "forced service". For default + * poll() and libuv / libev, the library takes care of calling this and + * dealing with it for you. But for external poll() integration, you need + * access to the apis. + * + * If anybody needs "forced service", returned timeout is zero. In that case, + * you can call lws_service_tsi() with a timeout of -1 to only service + * guys who need forced service. + */ +LWS_VISIBLE LWS_EXTERN int +lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi); + +/* Backwards compatibility */ +#define lws_plat_service_tsi lws_service_tsi + +LWS_VISIBLE LWS_EXTERN int +lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd); + +///@} + +/*! \defgroup uv libuv helpers + * + * ##libuv helpers + * + * APIs specific to libuv event loop itegration + */ +///@{ +#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP) + +/* + * Any direct libuv allocations in lws protocol handlers must participate in the + * lws reference counting scheme. Two apis are provided: + * + * - lws_libuv_static_refcount_add(handle, context, tsi) to mark the handle with + * a pointer to the context and increment the global uv object counter + * + * - lws_libuv_static_refcount_del() which should be used as the close callback + * for your own libuv objects declared in the protocol scope. + * + * Using the apis allows lws to detach itself from a libuv loop completely + * cleanly and at the moment all of its libuv objects have completed close. + */ + +LWS_VISIBLE LWS_EXTERN uv_loop_t * +lws_uv_getloop(struct lws_context *context, int tsi); + +LWS_VISIBLE LWS_EXTERN void +lws_libuv_static_refcount_add(uv_handle_t *, struct lws_context *context, + int tsi); + +LWS_VISIBLE LWS_EXTERN void +lws_libuv_static_refcount_del(uv_handle_t *); + +#endif /* LWS_WITH_LIBUV */ + +#if defined(LWS_PLAT_FREERTOS) +#define lws_libuv_static_refcount_add(_a, _b, _c) +#define lws_libuv_static_refcount_del NULL +#endif +///@} diff --git a/thirdparty/include/libwebsockets/lws-settings.h b/thirdparty/include/libwebsockets/lws-settings.h new file mode 100755 index 0000000000000000000000000000000000000000..56b47119fd58e2d4a6fcb05376847a98a8895254 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-settings.h @@ -0,0 +1,112 @@ +/* + * Generic Settings storage + * + * Copyright (C) 2020 Andy Green + * + * 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. + * + * + * This is like an abstract class for non-volatile storage, whether in a file- + * system or flash-backed blocks, etc. Named blobs of variable size are stored + * in nonvolatile media of some sort. Typically, these are JSON objects under + * a naming scheme like, eg, "network". + * + * There's a platform-specific storage identifier opaque_plat provided when the + * storage object is instantiated, this describes eg the storage device or + * partition in instantiation-specific terms. + * + * Blobs have a further "filename" associated with them. + */ + +#define LSOOPEN_FLAG_WRITEABLE (1 << 0) + +struct lws_settings_ops; + +typedef struct { + void *handle_plat; + const struct lws_settings_ops *so; + uint8_t refcount; + void *opaque_plat; +} lws_settings_instance_t; + +typedef struct lws_settings_ops { + int (*get)(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); + /**< if dest is NULL, max_actual is set to the actual length without + * copying anything out */ + int (*set)(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); +} lws_settings_ops_t; + +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param dest: NULL, or the buffer to copy the setting blob info + * \param max_actual: point to size of dest, or zero; actual blob size on exit + * + * If the named blob doesn't exist in the si, or can't read, returns nonzero. + * Otherwise, returns 0 and sets *max_actual to the true blob size. If dest is + * non-NULL, as much of the blob as will fit in the amount specified by + * *max_actual on entry is copied to dest. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_get(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); + +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param src: blob to copy to settings instance + * \param len: length of blob to copy + * + * Creates or replaces a settings blob of the given name made up of the \p len + * bytes of data from \p src. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_set(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); + +/** + * lws_settings_plat_printf() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param format: printf-style format string + * + * Creates or replaces a settings blob of the given name from the printf-style + * format string and arguments provided. There's no specific limit to the size, + * the size is computed and then a temp heap buffer used. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_printf(lws_settings_instance_t *si, const char *name, + const char *format, ...) LWS_FORMAT(3); + +#define lws_settings_ops_plat \ + .get = lws_settings_plat_get, \ + .set = lws_settings_plat_set, + +LWS_VISIBLE LWS_EXTERN lws_settings_instance_t * +lws_settings_init(const lws_settings_ops_t *so, void *opaque_plat); + +LWS_VISIBLE LWS_EXTERN void +lws_settings_deinit(lws_settings_instance_t **si); diff --git a/thirdparty/include/libwebsockets/lws-sha1-base64.h b/thirdparty/include/libwebsockets/lws-sha1-base64.h new file mode 100755 index 0000000000000000000000000000000000000000..0438aa9c9e32116979b4b5259c2150c8a5296e6f --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-sha1-base64.h @@ -0,0 +1,109 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup sha SHA and B64 helpers + * ##SHA and B64 helpers + * + * These provide SHA-1 and B64 helper apis + */ +///@{ +#ifdef LWS_SHA1_USE_OPENSSL_NAME +#define lws_SHA1 SHA1 +#else +/** + * lws_SHA1(): make a SHA-1 digest of a buffer + * + * \param d: incoming buffer + * \param n: length of incoming buffer + * \param md: buffer for message digest (must be >= 20 bytes) + * + * Reduces any size buffer into a 20-byte SHA-1 hash. + */ +LWS_VISIBLE LWS_EXTERN unsigned char * +lws_SHA1(const unsigned char *d, size_t n, unsigned char *md); +#endif +/** + * lws_b64_encode_string(): encode a string into base 64 + * + * \param in: incoming buffer + * \param in_len: length of incoming buffer + * \param out: result buffer + * \param out_size: length of result buffer + * + * Encodes a string using b64 + */ +LWS_VISIBLE LWS_EXTERN int +lws_b64_encode_string(const char *in, int in_len, char *out, int out_size); +/** + * lws_b64_encode_string_url(): encode a string into base 64 + * + * \param in: incoming buffer + * \param in_len: length of incoming buffer + * \param out: result buffer + * \param out_size: length of result buffer + * + * Encodes a string using b64 with the "URL" variant (+ -> -, and / -> _) + */ +LWS_VISIBLE LWS_EXTERN int +lws_b64_encode_string_url(const char *in, int in_len, char *out, int out_size); +/** + * lws_b64_decode_string(): decode a string from base 64 + * + * \param in: incoming buffer + * \param out: result buffer + * \param out_size: length of result buffer + * + * Decodes a NUL-terminated string using b64 + */ +LWS_VISIBLE LWS_EXTERN int +lws_b64_decode_string(const char *in, char *out, int out_size); +/** + * lws_b64_decode_string_len(): decode a string from base 64 + * + * \param in: incoming buffer + * \param in_len: length of incoming buffer + * \param out: result buffer + * \param out_size: length of result buffer + * + * Decodes a range of chars using b64 + */ +LWS_VISIBLE LWS_EXTERN int +lws_b64_decode_string_len(const char *in, int in_len, char *out, int out_size); + +struct lws_b64state { + unsigned char quad[4]; + size_t done; + size_t len; + int i; + int c; +}; + +LWS_VISIBLE LWS_EXTERN void +lws_b64_decode_state_init(struct lws_b64state *state); + +LWS_VISIBLE LWS_EXTERN int +lws_b64_decode_stateful(struct lws_b64state *s, const char *in, size_t *in_len, + uint8_t *out, size_t *out_size, int final); +///@} + diff --git a/thirdparty/include/libwebsockets/lws-smd.h b/thirdparty/include/libwebsockets/lws-smd.h new file mode 100755 index 0000000000000000000000000000000000000000..50dbc9ecf556600b8845bdd752ac4a865f7cb0fa --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-smd.h @@ -0,0 +1,227 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_SMD_MAX_PAYLOAD 384 +#define LWS_SMD_CLASS_BITFIELD_BYTES 4 + +#define LWS_SMD_STREAMTYPENAME "_lws_smd" +#define LWS_SMD_SS_RX_HEADER_LEN 16 + +typedef uint32_t lws_smd_class_t; + +struct lws_smd_msg; /* opaque */ +struct lws_smd_peer; /* opaque */ + +/* + * Well-known device classes + */ + +enum { + LWSSMDCL_INTERACTION = (1 << 0), + /**< + * Any kind of event indicating a user was interacting with the device, + * eg, press a button, touched the screen, lifted the device etc + */ + LWSSMDCL_SYSTEM_STATE = (1 << 1), + /**< + * The lws_system state changed, eg, to OPERATIONAL + */ + LWSSMDCL_NETWORK = (1 << 2), + /**< + * Something happened on the network, eg, link-up or DHCP, or captive + * portal state update + */ + LWSSMDCL_METRICS = (1 << 3), + /**< + * An SS client process is reporting a metric to the proxy (this class + * is special in that it is not rebroadcast by the proxy) + */ + + LWSSMDCL_USER_BASE_BITNUM = 24 +}; + +/** + * lws_smd_msg_alloc() - allocate a message of length len + * + * \param ctx: the lws_context + * \param _class: the smd message class, recipients filter on this + * \param len: the required payload length + * + * This helper returns an opaque lws_smd_msg pointer and sets *buf to a buffer + * associated with it of length \p len. + * + * In this way the lws_msg_smd type remains completely opaque and the allocated + * area can be prepared by the caller directly, without copying. + * + * On failure, it returns NULL... it may fail for OOM but it may also fail if + * you request to allocate for a message class that the system has no + * participant who is listening for that class of event currently... the event + * generation action at the caller should be bypassed without error then. + * + * This is useful if you have a message you know the length of. For text-based + * messages like JSON, lws_smd_msg_printf() is more convenient. + */ +LWS_VISIBLE LWS_EXTERN void * /* payload */ +lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len); + +/** + * lws_smd_msg_free() - abandon a previously allocated message before sending + * + * \param payload: pointer the previously-allocated message payload + * + * Destroys a previously-allocated opaque message object and the requested + * buffer space, in the case that between allocating it and sending it, some + * condition was met that means it can no longer be sent, eg, an error + * generating the content. Otherwise there is no need to destroy allocated + * message objects with this, lws will take care of it. + */ +LWS_VISIBLE LWS_EXTERN void +lws_smd_msg_free(void **payload); + +/** + * lws_smd_msg_send() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param msg: the prepared message + * + * Queues an allocated, prepared message for delivery to smd clients + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_send(struct lws_context *ctx, void *payload); + +/** + * lws_smd_msg_printf() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param _class: the message class + * \param format: the format string to prepare the payload with + * \param ...: arguments for the format string, if any + * + * For string-based messages, eg, JSON, allows formatted creating of the payload + * size discovery, allocation and message send all in one step. + * + * Unlike lws_smd_msg_alloc() you do not need to know the length beforehand as + * this computes it and calls lws_smd_msg_alloc() with the correct length. + * + * To be clear this also calls through to lws_smd_msg_send(), it really does + * everything in one step. If there are no registered participants that want + * messages of \p _class, this function returns immediately without doing any + * allocation or anything else. + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...) LWS_FORMAT(3); + +/** + * lws_smd_ss_msg_printf() - helper to prepare smd ss message tx + * + * \param h: the ss handle + * \param buf: the ss tx buffer + * \param len: on entry, points to the ss tx buffer length, on exit, set to used + * \param _class: the message class + * \param format: the format string to prepare the payload with + * \param ...: arguments for the format string, if any + * + * This helper lets you produce SMD messages on an SS link of the builtin + * streamtype LWS_SMD_STREAMTYPENAME, using the same api format as + * lws_smd_msg_prinf(), but writing the message into the ss tx buffer from + * its tx() callback. + */ + +struct lws_ss_handle; +LWS_VISIBLE LWS_EXTERN int +lws_smd_ss_msg_printf(const char *tag, uint8_t *buf, size_t *len, + lws_smd_class_t _class, const char *format, ...) + LWS_FORMAT(5); + +/** + * lws_smd_ss_rx_forward() - helper to forward smd messages that came in by SS + * + * \param ss_user: ss user pointer, as delivered to rx callback + * \param buf: the ss rx buffer + * \param len: the length of the ss rx buffer + * + * Proxied Secure Streams with the streamtype LWS_SMD_STREAMTYPENAME receive + * serialized SMD messages from the proxy, this helper allows them to be + * translated into deserialized SMD messages and forwarded to registered SMD + * participants in the local context in one step. + * + * Just pass through what arrived in the LWS_SMD_STREAMTYPENAME rx() callback + * to this api. + * + * Returns 0 if OK else nonzero if unable to queue the SMD message. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_ss_rx_forward(void *ss_user, const uint8_t *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_smd_sspc_rx_forward(void *ss_user, const uint8_t *buf, size_t len); + +typedef int (*lws_smd_notification_cb_t)(void *opaque, lws_smd_class_t _class, + lws_usec_t timestamp, void *buf, + size_t len); + +#define LWSSMDREG_FLAG_PROXIED_SS (1 << 0) +/**< It's actually a proxied SS connection registering, opaque is the ss h */ + +/* + * lws_smd_register() - register to receive smd messages + * + * \param ctx: the lws_context + * \param opaque: an opaque pointer handed to the callback + * \param flags: typically 0 + * \param _class_filter: bitmap of message classes we care about + * \param cb: the callback to receive messages + * + * Queues an allocated, prepared message for delivery to smd clients. + * + * Returns NULL on failure, or an opaque handle which may be given to + * lws_smd_unregister() to stop participating in the shared message queue. + * + * This is threadsafe to call from a non-service thread. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_smd_peer * +lws_smd_register(struct lws_context *ctx, void *opaque, int flags, + lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb); + +/* + * lws_smd_unregister() - unregister receiving smd messages + * + * \param pr: the handle returned from the registration + * + * Destroys the registration of the callback for messages and ability to send + * messages. + * + * It's not necessary to call this if the registration wants to survive for as + * long as the lws_context... lws_context_destroy will also clean up any + * registrations still active by then. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_smd_unregister(struct lws_smd_peer *pr); diff --git a/thirdparty/include/libwebsockets/lws-spa.h b/thirdparty/include/libwebsockets/lws-spa.h new file mode 100755 index 0000000000000000000000000000000000000000..c5ddab2c7c011943097086c49e32c2a684da42ae --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-spa.h @@ -0,0 +1,176 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup form-parsing Form Parsing + * \ingroup http + * ##POSTed form parsing functions + * + * These lws_spa (stateful post arguments) apis let you parse and urldecode + * POSTed form arguments, both using simple urlencoded and multipart transfer + * encoding. + * + * It's capable of handling file uploads as well a named input parsing, + * and the apis are the same for both form upload styles. + * + * You feed it a list of parameter names and it creates pointers to the + * urldecoded arguments: file upload parameters pass the file data in chunks to + * a user-supplied callback as they come. + * + * Since it's stateful, it handles the incoming data needing more than one + * POST_BODY callback and has no limit on uploaded file size. + */ +///@{ + +/** enum lws_spa_fileupload_states */ +enum lws_spa_fileupload_states { + LWS_UFS_CONTENT, + /**< a chunk of file content has arrived */ + LWS_UFS_FINAL_CONTENT, + /**< the last chunk (possibly zero length) of file content has arrived */ + LWS_UFS_OPEN, + /**< a new file is starting to arrive */ + LWS_UFS_CLOSE + /**< the file decode stuff is being destroyed */ +}; + +/** + * lws_spa_fileupload_cb() - callback to receive file upload data + * + * \param data: opt_data pointer set in lws_spa_create + * \param name: name of the form field being uploaded + * \param filename: original filename from client + * \param buf: start of data to receive + * \param len: length of data to receive + * \param state: information about how this call relates to file + * + * Notice name and filename shouldn't be trusted, as they are passed from + * HTTP provided by the client. + */ +typedef int (*lws_spa_fileupload_cb)(void *data, const char *name, + const char *filename, char *buf, int len, + enum lws_spa_fileupload_states state); + +/** struct lws_spa - opaque urldecode parser capable of handling multipart + * and file uploads */ +struct lws_spa; + +/** + * lws_spa_create() - create urldecode parser + * + * \param wsi: lws connection (used to find Content Type) + * \param param_names: array of form parameter names, like "username" + * \param count_params: count of param_names + * \param max_storage: total amount of form parameter values we can store + * \param opt_cb: NULL, or callback to receive file upload data. + * \param opt_data: NULL, or user pointer provided to opt_cb. + * + * Creates a urldecode parser and initializes it. + * + * It's recommended to use the newer api, lws_spa_create_via_info() + * instead. + * + * opt_cb can be NULL if you just want normal name=value parsing, however + * if one or more entries in your form are bulk data (file transfer), you + * can provide this callback and filter on the name callback parameter to + * treat that urldecoded data separately. The callback should return -1 + * in case of fatal error, and 0 if OK. + */ +LWS_VISIBLE LWS_EXTERN struct lws_spa * +lws_spa_create(struct lws *wsi, const char * const *param_names, + int count_params, int max_storage, lws_spa_fileupload_cb opt_cb, + void *opt_data); + +typedef struct lws_spa_create_info { + const char * const *param_names; /* array of form parameter names, like "username" */ + int count_params; /* count of param_names */ + int max_storage; /* total amount of form parameter values we can store */ + lws_spa_fileupload_cb opt_cb; /* NULL, or callback to receive file upload data. */ + void *opt_data; /* NULL, or user pointer provided to opt_cb. */ + size_t param_names_stride; /* 0 if param_names is an array of char *. + Else stride to next char * */ + struct lwsac **ac; /* NULL, or pointer to lwsac * to contain all + related heap allocations */ + size_t ac_chunk_size; /* 0 for default, or ac chunk size */ +} lws_spa_create_info_t; + +/** + * lws_spa_create_via_info() - create urldecode parser + * + * \param wsi: lws connection (used to find Content Type) + * \param info: pointer to struct defining the arguments + * + * Creates a urldecode parser and initializes it. + * + * opt_cb can be NULL if you just want normal name=value parsing, however + * if one or more entries in your form are bulk data (file transfer), you + * can provide this callback and filter on the name callback parameter to + * treat that urldecoded data separately. The callback should return -1 + * in case of fatal error, and 0 if OK. + */ +LWS_VISIBLE LWS_EXTERN struct lws_spa * +lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *info); + +/** + * lws_spa_process() - parses a chunk of input data + * + * \param spa: the parser object previously created + * \param in: incoming urlencoded data + * \param len: count of bytes valid at \p in + */ +LWS_VISIBLE LWS_EXTERN int +lws_spa_process(struct lws_spa *spa, const char *in, int len); + +/** + * lws_spa_finalize() - indicate incoming data completed + * + * \param spa: the parser object previously created + */ +LWS_VISIBLE LWS_EXTERN int +lws_spa_finalize(struct lws_spa *spa); + +/** + * lws_spa_get_length() - return length of parameter value + * + * \param spa: the parser object previously created + * \param n: parameter ordinal to return length of value for + */ +LWS_VISIBLE LWS_EXTERN int +lws_spa_get_length(struct lws_spa *spa, int n); + +/** + * lws_spa_get_string() - return pointer to parameter value + * \param spa: the parser object previously created + * \param n: parameter ordinal to return pointer to value for + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_spa_get_string(struct lws_spa *spa, int n); + +/** + * lws_spa_destroy() - destroy parser object + * + * \param spa: the parser object previously created + */ +LWS_VISIBLE LWS_EXTERN int +lws_spa_destroy(struct lws_spa *spa); +///@} diff --git a/thirdparty/include/libwebsockets/lws-spi.h b/thirdparty/include/libwebsockets/lws-spi.h new file mode 100755 index 0000000000000000000000000000000000000000..666113ef6f102ec7be6d199a55469052f3bd393a --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-spi.h @@ -0,0 +1,73 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for spi, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + * + * It uses descriptor / queuing semantics but eg the GPIO BB implementantion is + * synchronous. + */ + +#if !defined(__LWS_SPI_H__) +#define __LWS_SPI_H__ + +#include +#include + +typedef int (*lws_spi_cb_t)(void *opaque); + +enum { + LWSSPIMODE_CPOL = (1 << 0), + LWSSPIMODE_CPHA = (1 << 1), + + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING = 0, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_RISING = LWSSPIMODE_CPOL, + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_FALLING = LWSSPIMODE_CPHA, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_FALLING = LWSSPIMODE_CPHA | + LWSSPIMODE_CPOL, + + LWS_SPI_TXN_HALF_DUPLEX_DISCRETE = 0, + /**< separate MISO and MOSI, but only either MISO or MOSI has data at + * one time... i2c style in SPI */ +}; + +typedef struct lws_spi_desc { + const uint8_t *src; + const uint8_t *data; + uint8_t *dest; + void *opaque; + lws_spi_cb_t completion_cb; + uint16_t count_cmd; + uint16_t count_write; + uint16_t count_read; + uint8_t txn_type; + uint8_t channel; +} lws_spi_desc_t; + +typedef struct lws_spi_ops { + int (*init)(const struct lws_spi_ops *ctx); + int (*queue)(const struct lws_spi_ops *ctx, const lws_spi_desc_t *desc); + uint8_t bus_mode; +} lws_spi_ops_t; + +#endif diff --git a/thirdparty/include/libwebsockets/lws-ssd1306-i2c.h b/thirdparty/include/libwebsockets/lws-ssd1306-i2c.h new file mode 100755 index 0000000000000000000000000000000000000000..8b2f6e37e44983542d7c410319ae1d26ea06f2a8 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ssd1306-i2c.h @@ -0,0 +1,64 @@ +/* + * lws abstract display implementation for ssd1306 on i2c + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_SSD1306_I2C_H__) +#define __LWS_DISPLAY_SSD1306_I2C_H__ + +/* + * D/C# pin on SSD1306 sets the I2C device ads + * from these two options (7-bit address) + */ + +#define SSD1306_I2C7_ADS1 0x3c +#define SSD1306_I2C7_ADS2 0x3d + +typedef struct lws_display_ssd1306 { + + lws_display_t disp; /* use lws_display_ssd1306_ops to set ops */ + const lws_i2c_ops_t *i2c; /* i2c ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t i2c7_address; /* one of SSD1306_I2C7_ADS... */ + +} lws_display_ssd1306_t; + +int +lws_display_ssd1306_i2c_init(const struct lws_display *disp); +int +lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b); +int +lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state); + +#define lws_display_ssd1306_ops \ + .init = lws_display_ssd1306_i2c_init, \ + .contrast = lws_display_ssd1306_i2c_contrast, \ + .blit = lws_display_ssd1306_i2c_blit, \ + .power = lws_display_ssd1306_i2c_power +#endif diff --git a/thirdparty/include/libwebsockets/lws-state.h b/thirdparty/include/libwebsockets/lws-state.h new file mode 100755 index 0000000000000000000000000000000000000000..78281539038bc45bda5433872d70a0bd5a3a5c95 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-state.h @@ -0,0 +1,119 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +struct lws_state_notify_link; +struct lws_state_manager; + +#if defined(LWS_WITH_SYS_STATE) + +typedef int (*lws_state_notify_t)(struct lws_state_manager *mgr, + struct lws_state_notify_link *link, + int current, int target); + +typedef struct lws_state_notify_link { + lws_dll2_t list; + lws_state_notify_t notify_cb; + const char *name; +} lws_state_notify_link_t; + +typedef struct lws_state_manager { + lws_dll2_owner_t notify_list; + struct lws_context *context; + void *parent; +#if defined(LWS_WITH_SYS_SMD) + lws_smd_class_t smd_class; +#endif + /**< optional opaque pointer to owning object... useful to make such + * a pointer available to a notification callback. Ignored by lws */ + const char **state_names; + const char *name; + int state; +} lws_state_manager_t; + +/** + * lws_state_reg_notifier() - add dep handler for state notifications + * + * \param context: the lws_context + * \param nl: the handler to add to the notifier linked-list + * + * Add \p notify_link to the context's list of notification handlers for system + * state changes. The handlers can defeat or take over responsibility for + * retrying the change after they have initiated some dependency. + */ + +LWS_EXTERN LWS_VISIBLE void +lws_state_reg_notifier(lws_state_manager_t *mgr, lws_state_notify_link_t *nl); + +/** + * lws_state_reg_deregister() - deregister a notifier + * + * \param nl: notification hardler to deregister + * + * Remove a notification handler from its state manager + */ + +LWS_EXTERN LWS_VISIBLE void +lws_state_reg_deregister(lws_state_notify_link_t *nl); + +/** + * lws_state_reg_notifier_list() - add dep handlers for state notifications + * + * \param context: the lws_context + * \param nl: list of notification handlers + * + * Add a NULL-terminated list of notification handler pointers to a notification + * manager object + */ + +LWS_EXTERN LWS_VISIBLE void +lws_state_reg_notifier_list(lws_state_manager_t *mgr, + lws_state_notify_link_t * const *nl); + +/** + * lws_state_transition_steps() - move to state via starting any deps + * + * \param mgr: the state manager object + * \param target: the state we wish to move to + * + * Advance state by state towards state \p target. At each state, notifiers + * may veto the change and be triggered to perform dependencies, stopping the + * advance towards the target state. + */ +LWS_EXTERN LWS_VISIBLE int +lws_state_transition_steps(lws_state_manager_t *mgr, int target); + +/** + * lws_state_transition() - move to state via starting any deps + * + * \param mgr: the state manager object + * \param target: the state we wish to move to + * + * Jump to state target atomically. Notifiers may veto it. + */ +LWS_EXTERN LWS_VISIBLE int +lws_state_transition(lws_state_manager_t *mgr, int target); + +#else + +#endif diff --git a/thirdparty/include/libwebsockets/lws-struct.h b/thirdparty/include/libwebsockets/lws-struct.h new file mode 100755 index 0000000000000000000000000000000000000000..dac2619729fc3d4660a9cb5251676f1ef1135260 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-struct.h @@ -0,0 +1,284 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#if defined(LWS_WITH_STRUCT_SQLITE3) +#include +#endif + +typedef enum { + LSMT_SIGNED, + LSMT_UNSIGNED, + LSMT_BOOLEAN, + LSMT_STRING_CHAR_ARRAY, + LSMT_STRING_PTR, + LSMT_LIST, + LSMT_CHILD_PTR, + LSMT_SCHEMA, + LSMT_BLOB_PTR, + +} lws_struct_map_type_eum; + +typedef struct lejp_collation { + struct lws_dll2 chunks; + int len; + char buf[LEJP_STRING_CHUNK + 1]; +} lejp_collation_t; + +typedef struct lws_struct_map { + const char *colname; + const struct lws_struct_map *child_map; + lejp_callback lejp_cb; + size_t ofs; /* child dll2; points to dll2_owner */ + size_t aux; + size_t ofs_clist; + size_t child_map_size; + lws_struct_map_type_eum type; +} lws_struct_map_t; + +typedef int (*lws_struct_args_cb)(void *obj, void *cb_arg); + +typedef struct lws_struct_args { + const lws_struct_map_t *map_st[LEJP_MAX_PARSING_STACK_DEPTH]; + lws_struct_args_cb cb; + struct lwsac *ac; + void *cb_arg; + void *dest; + + size_t dest_len; + size_t toplevel_dll2_ofs; + size_t map_entries_st[LEJP_MAX_PARSING_STACK_DEPTH]; + size_t ac_block_size; + int subtype; + + int top_schema_index; + + /* + * temp ac used to collate unknown possibly huge strings before final + * allocation and copy + */ + struct lwsac *ac_chunks; + struct lws_dll2_owner chunks_owner; + size_t chunks_length; +} lws_struct_args_t; + +#define LSM_SIGNED(type, name, qname) \ + { \ + qname, \ + NULL, \ + NULL, \ + offsetof(type, name), \ + sizeof ((type *)0)->name, \ + 0, \ + 0, \ + LSMT_SIGNED \ + } + +#define LSM_UNSIGNED(type, name, qname) \ + { \ + qname, \ + NULL, \ + NULL, \ + offsetof(type, name), \ + sizeof ((type *)0)->name, \ + 0, \ + 0, \ + LSMT_UNSIGNED \ + } + +#define LSM_BOOLEAN(type, name, qname) \ + { \ + qname, \ + NULL, \ + NULL, \ + offsetof(type, name), \ + sizeof ((type *)0)->name, \ + 0, \ + 0, \ + LSMT_BOOLEAN \ + } + +#define LSM_CARRAY(type, name, qname) \ + { \ + qname, \ + NULL, \ + NULL, \ + offsetof(type, name), \ + sizeof (((type *)0)->name), \ + 0, \ + 0, \ + LSMT_STRING_CHAR_ARRAY \ + } + +#define LSM_STRING_PTR(type, name, qname) \ + { \ + qname, \ + NULL, \ + NULL, \ + offsetof(type, name), \ + sizeof (((type *)0)->name), \ + 0, \ + 0, \ + LSMT_STRING_PTR \ + } + +#define LSM_LIST(ptype, pname, ctype, cname, lejp_cb, cmap, qname) \ + { \ + qname, \ + cmap, \ + lejp_cb, \ + offsetof(ptype, pname), \ + sizeof (ctype), \ + offsetof(ctype, cname), \ + LWS_ARRAY_SIZE(cmap), \ + LSMT_LIST \ + } + +#define LSM_CHILD_PTR(ptype, pname, ctype, lejp_cb, cmap, qname) \ + { \ + qname, \ + cmap, \ + lejp_cb, \ + offsetof(ptype, pname), \ + sizeof (ctype), \ + 0, \ + LWS_ARRAY_SIZE(cmap), \ + LSMT_CHILD_PTR \ + } + +#define LSM_SCHEMA(ctype, lejp_cb, map, schema_name) \ + { \ + schema_name, \ + map, \ + lejp_cb, \ + 0, \ + sizeof (ctype), \ + 0, \ + LWS_ARRAY_SIZE(map), \ + LSMT_SCHEMA \ + } + +#define LSM_SCHEMA_DLL2(ctype, cdll2mem, lejp_cb, map, schema_name) \ + { \ + schema_name, \ + map, \ + lejp_cb, \ + offsetof(ctype, cdll2mem), \ + sizeof (ctype), \ + 0, \ + LWS_ARRAY_SIZE(map), \ + LSMT_SCHEMA \ + } + +/* + * This is just used to create the table schema, it is not part of serialization + * and deserialization. Blobs should be accessed separately. + */ + +#define LSM_BLOB_PTR(type, blobptr_name, qname) \ + { \ + qname, /* JSON item, or sqlite3 column name */ \ + NULL, \ + NULL, \ + offsetof(type, blobptr_name), /* member that points to blob */ \ + sizeof (((type *)0)->blobptr_name), /* size of blob pointer */ \ + 0, /* member holding blob len */ \ + 0, /* size of blob length member */ \ + LSMT_BLOB_PTR \ + } + +typedef struct lws_struct_serialize_st { + const struct lws_dll2 *dllpos; + const lws_struct_map_t *map; + const char *obj; + size_t map_entries; + size_t map_entry; + size_t size; + char subsequent; + char idt; +} lws_struct_serialize_st_t; + +enum { + LSSERJ_FLAG_PRETTY = (1 << 0), + LSSERJ_FLAG_OMIT_SCHEMA = (1 << 1) +}; + +typedef struct lws_struct_serialize { + lws_struct_serialize_st_t st[LEJP_MAX_PARSING_STACK_DEPTH]; + + size_t offset; + size_t remaining; + + int sp; + int flags; +} lws_struct_serialize_t; + +typedef enum { + LSJS_RESULT_CONTINUE, + LSJS_RESULT_FINISH, + LSJS_RESULT_ERROR +} lws_struct_json_serialize_result_t; + +LWS_VISIBLE LWS_EXTERN int +lws_struct_json_init_parse(struct lejp_ctx *ctx, lejp_callback cb, + void *user); + +LWS_VISIBLE LWS_EXTERN signed char +lws_struct_schema_only_lejp_cb(struct lejp_ctx *ctx, char reason); + +LWS_VISIBLE LWS_EXTERN signed char +lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason); + +LWS_VISIBLE LWS_EXTERN lws_struct_serialize_t * +lws_struct_json_serialize_create(const lws_struct_map_t *map, + size_t map_entries, int flags, + const void *ptoplevel); + +LWS_VISIBLE LWS_EXTERN void +lws_struct_json_serialize_destroy(lws_struct_serialize_t **pjs); + +LWS_VISIBLE LWS_EXTERN lws_struct_json_serialize_result_t +lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, + size_t len, size_t *written); + +typedef struct sqlite3 sqlite3; + +LWS_VISIBLE LWS_EXTERN int +lws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema, + lws_dll2_owner_t *owner, uint32_t manual_idx); + +LWS_VISIBLE LWS_EXTERN int +lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, + const lws_struct_map_t *schema, lws_dll2_owner_t *o, + struct lwsac **ac, int start, int limit); + +LWS_VISIBLE LWS_EXTERN int +lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema); + +LWS_VISIBLE LWS_EXTERN int +lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, + char create_if_missing, sqlite3 **pdb); + +LWS_VISIBLE LWS_EXTERN int +lws_struct_sq3_close(sqlite3 **pdb); + diff --git a/thirdparty/include/libwebsockets/lws-system.h b/thirdparty/include/libwebsockets/lws-system.h new file mode 100755 index 0000000000000000000000000000000000000000..07900e02b1cf97731c9c22fc98aded7ff68e1467 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-system.h @@ -0,0 +1,399 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + * + * This provides a clean way to interface lws user code to be able to + * work unchanged on different systems for fetching common system information, + * and performing common system operations like reboot. + */ + +/* + * Types of system blob that can be set and retreived + */ + +typedef enum { + LWS_SYSBLOB_TYPE_AUTH, + LWS_SYSBLOB_TYPE_CLIENT_CERT_DER = LWS_SYSBLOB_TYPE_AUTH + 2, + LWS_SYSBLOB_TYPE_CLIENT_KEY_DER, + LWS_SYSBLOB_TYPE_DEVICE_SERIAL, + LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, + LWS_SYSBLOB_TYPE_DEVICE_TYPE, + LWS_SYSBLOB_TYPE_NTP_SERVER, + LWS_SYSBLOB_TYPE_MQTT_CLIENT_ID, + LWS_SYSBLOB_TYPE_MQTT_USERNAME, + LWS_SYSBLOB_TYPE_MQTT_PASSWORD, + +#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) + /* extend 4 more auth blobs, each has 2 slots */ + LWS_SYSBLOB_TYPE_EXT_AUTH1, + LWS_SYSBLOB_TYPE_EXT_AUTH2 = LWS_SYSBLOB_TYPE_EXT_AUTH1 + 2, + LWS_SYSBLOB_TYPE_EXT_AUTH3 = LWS_SYSBLOB_TYPE_EXT_AUTH2 + 2, + LWS_SYSBLOB_TYPE_EXT_AUTH4 = LWS_SYSBLOB_TYPE_EXT_AUTH3 + 2, + LWS_SYSBLOB_TYPE_EXT_AUTH4_1, +#endif + + LWS_SYSBLOB_TYPE_COUNT /* ... always last */ +} lws_system_blob_item_t; + +/* opaque generic blob whose content may be on-the-heap or pointed-to + * directly case by case. When it's on the heap, it can be produced by + * appending (it's a buflist underneath). Either way, it can be consumed by + * copying out a given length from a given offset. + */ + +typedef struct lws_system_blob lws_system_blob_t; + +LWS_EXTERN LWS_VISIBLE void +lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len); + +LWS_EXTERN LWS_VISIBLE void +lws_system_blob_heap_empty(lws_system_blob_t *b); + +LWS_EXTERN LWS_VISIBLE int +lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *ptr, size_t len); + +LWS_EXTERN LWS_VISIBLE size_t +lws_system_blob_get_size(lws_system_blob_t *b); + +/* return 0 and sets *ptr to point to blob data if possible, nonzero = fail */ +LWS_EXTERN LWS_VISIBLE int +lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr); + +LWS_EXTERN LWS_VISIBLE int +lws_system_blob_get(lws_system_blob_t *b, uint8_t *ptr, size_t *len, size_t ofs); + +LWS_EXTERN LWS_VISIBLE void +lws_system_blob_destroy(lws_system_blob_t *b); + +/* + * Get the opaque blob for index idx of various system blobs. Returns 0 if + * *b was set otherwise nonzero means out of range + */ + +LWS_EXTERN LWS_VISIBLE lws_system_blob_t * +lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type, + int idx); + +/* + * Lws view of system state... normal operation from user code perspective is + * dependent on implicit (eg, knowing the date for cert validation) and + * explicit dependencies. + * + * Bit of lws and user code can register notification handlers that can enforce + * dependent operations before state transitions can complete. + */ + +typedef enum { /* keep system_state_names[] in sync in context.c */ + LWS_SYSTATE_UNKNOWN, + + LWS_SYSTATE_CONTEXT_CREATED, /* context was just created */ + LWS_SYSTATE_INITIALIZED, /* protocols initialized. Lws itself + * can operate normally */ + LWS_SYSTATE_IFACE_COLDPLUG, /* existing net ifaces iterated */ + LWS_SYSTATE_DHCP, /* at least one net iface configured */ + LWS_SYSTATE_CPD_PRE_TIME, /* Captive portal detect without valid + * time, good for non-https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ + LWS_SYSTATE_TIME_VALID, /* ntpclient ran, or hw time valid... + * tls cannot work until we reach here + */ + LWS_SYSTATE_CPD_POST_TIME, /* Captive portal detect after time was + * time, good for https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ + + LWS_SYSTATE_POLICY_VALID, /* user code knows how to operate... */ + LWS_SYSTATE_REGISTERED, /* device has an identity... */ + LWS_SYSTATE_AUTH1, /* identity used for main auth token */ + LWS_SYSTATE_AUTH2, /* identity used for optional auth */ + + LWS_SYSTATE_OPERATIONAL, /* user code can operate normally */ + + LWS_SYSTATE_POLICY_INVALID, /* user code is changing its policies + * drop everything done with old + * policy, switch to new then enter + * LWS_SYSTATE_POLICY_VALID */ + LWS_SYSTATE_CONTEXT_DESTROYING, /* Context is being destroyed */ +} lws_system_states_t; + +/* Captive Portal Detect -related */ + +typedef enum { + LWS_CPD_UNKNOWN = 0, /* test didn't happen ince last DHCP acq yet */ + LWS_CPD_INTERNET_OK, /* no captive portal: our CPD test passed OK, + * we can go out on the internet */ + LWS_CPD_CAPTIVE_PORTAL, /* we inferred we're behind a captive portal */ + LWS_CPD_NO_INTERNET, /* we couldn't touch anything */ +} lws_cpd_result_t; + +typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); +struct lws_attach_item; + +LWS_EXTERN LWS_VISIBLE int +lws_tls_jit_trust_got_cert_cb(struct lws_context *cx, void *got_opaque, + const uint8_t *skid, size_t skid_len, + const uint8_t *der, size_t der_len); + +typedef struct lws_system_ops { + int (*reboot)(void); + int (*set_clock)(lws_usec_t us); + int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb, + lws_system_states_t state, void *opaque, + struct lws_attach_item **get); + /**< if \p get is NULL, add an attach callback request to the pt for + * \p cb with arg \p opaque, that should be called when we're at or past + * system state \p state. + * + * If \p get is non-NULL, look for the first listed item on the pt whose + * state situation is ready, and set *get to point to it. If no items, + * or none where the system state is right, set *get to NULL. + * + * It's done like this so (*attach) can perform system-specific + * locking outside of lws core, for both getting and adding items the + * same so it is thread-safe. A non-threadsafe helper + * __lws_system_attach() is provided to do the actual work inside the + * system-specific locking. + */ + int (*captive_portal_detect_request)(struct lws_context *context); + /**< Check if we can go out on the internet cleanly, or if we are being + * redirected or intercepted by a captive portal. + * Start the check that proceeds asynchronously, and report the results + * by calling lws_captive_portal_detect_result() api + */ + + int (*metric_report)(lws_metric_pub_t *mdata); + /**< metric \p item is reporting an event of kind \p rpt, + * held in \p mdata... return 0 to leave the metric object as it is, + * or nonzero to reset it. */ + + int (*jit_trust_query)(struct lws_context *cx, const uint8_t *skid, + size_t skid_len, void *got_opaque); + /**< user defined trust store search, if we do trust a cert with SKID + * matching skid / skid_len, then it should get hold of the DER for the + * matching root CA and call + * lws_tls_jit_trust_got_cert_cb(..., got_opaque) before cleaning up and + * returning. The DER should be destroyed if in heap before returning. + */ + + uint32_t wake_latency_us; + /**< time taken for this device to wake from suspend, in us + */ +} lws_system_ops_t; + +#if defined(LWS_WITH_SYS_STATE) + +/** + * lws_system_get_state_manager() - return the state mgr object for system state + * + * \param context: the lws_context + * + * The returned pointer can be used with the lws_state_ apis + */ + +LWS_EXTERN LWS_VISIBLE lws_state_manager_t * +lws_system_get_state_manager(struct lws_context *context); + +#endif + +/* wrappers handle NULL members or no ops struct set at all cleanly */ + +#define LWSSYSGAUTH_HEX (1 << 0) + +/** + * lws_system_get_ops() - get ahold of the system ops struct from the context + * + * \param context: the lws_context + * + * Returns the system ops struct. It may return NULL and if not, anything in + * there may be NULL. + */ +LWS_EXTERN LWS_VISIBLE const lws_system_ops_t * +lws_system_get_ops(struct lws_context *context); + +#if defined(LWS_WITH_SYS_STATE) + +/** + * lws_system_context_from_system_mgr() - return context from system state mgr + * + * \param mgr: pointer to specifically the system state mgr + * + * Returns the context from the system state mgr. Helper since the lws_context + * is opaque. + */ +LWS_EXTERN LWS_VISIBLE struct lws_context * +lws_system_context_from_system_mgr(lws_state_manager_t *mgr); + +#endif + +/** + * __lws_system_attach() - get and set items on context attach list + * + * \param context: context to get or set attach items to + * \param tsi: thread service index (normally 0) + * \param cb: callback to call from context event loop thread + * \param state: the lws_system state we have to be in or have passed through + * \param opaque: optional pointer to user specific info given to callback + * \param get: NULL, or pointer to pointer to take detached tail item on exit + * + * This allows other threads to enqueue callback requests to happen from a pt's + * event loop thread safely. The callback gets the context pointer and a user + * opaque pointer that can be optionally given when the item is added to the + * attach list. + * + * This api is the no-locking core function for getting and setting items on the + * pt's attach list. The lws_system operation (*attach) is the actual + * api that user and internal code calls for this feature, it should perform + * system-specific locking, call this helper, release the locking and then + * return the result. This api is public only so it can be used in the locked + * implementation of (*attach). + * + * If get is NULL, then the call adds to the head of the pt attach list using + * cb, state, and opaque; if get is non-NULL, then *get is set to the first + * waiting attached item that meets the state criteria and that item is removed + * from the list. + * + * This is a non-threadsafe helper only designed to be called from + * implementations of struct lws_system's (*attach) operation where system- + * specific locking has been applied around it, making it threadsafe. + */ +LWS_EXTERN LWS_VISIBLE int +__lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb, + lws_system_states_t state, void *opaque, + struct lws_attach_item **get); + + +enum { + LWSDH_IPV4_SUBNET_MASK = 0, + LWSDH_IPV4_BROADCAST, + LWSDH_LEASE_SECS, + LWSDH_REBINDING_SECS, + LWSDH_RENEWAL_SECS, + + _LWSDH_NUMS_COUNT, + + LWSDH_SA46_IP = 0, + LWSDH_SA46_DNS_SRV_1, + LWSDH_SA46_DNS_SRV_2, + LWSDH_SA46_DNS_SRV_3, + LWSDH_SA46_DNS_SRV_4, + LWSDH_SA46_IPV4_ROUTER, + LWSDH_SA46_NTP_SERVER, + LWSDH_SA46_DHCP_SERVER, + + _LWSDH_SA46_COUNT, +}; + +typedef struct lws_dhcpc_ifstate { + char ifname[16]; + char domain[64]; + uint8_t mac[6]; + uint32_t nums[_LWSDH_NUMS_COUNT]; + lws_sockaddr46 sa46[_LWSDH_SA46_COUNT]; +} lws_dhcpc_ifstate_t; + +typedef int (*dhcpc_cb_t)(void *opaque, lws_dhcpc_ifstate_t *is); + +/** + * lws_dhcpc_request() - add a network interface to dhcpc management + * + * \param c: the lws_context + * \param i: the interface name, like "eth0" + * \param af: address family + * \param cb: the change callback + * \param opaque: opaque pointer given to the callback + * + * Register a network interface as being managed by DHCP. lws will proceed to + * try to acquire an IP. Requires LWS_WITH_SYS_DHCP_CLIENT at cmake. + */ +LWS_EXTERN LWS_VISIBLE int +lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb, + void *opaque); + +/** + * lws_dhcpc_remove() - remove a network interface to dhcpc management + * + * \param context: the lws_context + * \param iface: the interface name, like "eth0" + * + * Remove handling of the network interface from dhcp. + */ +LWS_EXTERN LWS_VISIBLE int +lws_dhcpc_remove(struct lws_context *context, const char *iface); + +/** + * lws_dhcpc_status() - has any interface reached BOUND state + * + * \param context: the lws_context + * \param sa46: set to a DNS server from a bound interface, or NULL + * + * Returns 1 if any network interface managed by dhcpc has reached the BOUND + * state (has acquired an IP, gateway and DNS server), otherwise 0. + */ +LWS_EXTERN LWS_VISIBLE int +lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46); + +/** + * lws_system_cpd_start() - helper to initiate captive portal detection + * + * \param context: the lws_context + * + * Resets the context's captive portal state to LWS_CPD_UNKNOWN and calls the + * lws_system_ops_t captive_portal_detect_request() implementation to begin + * testing the captive portal state. + */ +LWS_EXTERN LWS_VISIBLE int +lws_system_cpd_start(struct lws_context *context); + +LWS_EXTERN LWS_VISIBLE void +lws_system_cpd_start_defer(struct lws_context *cx, lws_usec_t defer_us); + + +/** + * lws_system_cpd_set() - report the result of the captive portal detection + * + * \param context: the lws_context + * \param result: one of the LWS_CPD_ constants representing captive portal state + * + * Sets the context's captive portal detection state to result. User captive + * portal detection code would call this once it had a result from its test. + */ +LWS_EXTERN LWS_VISIBLE void +lws_system_cpd_set(struct lws_context *context, lws_cpd_result_t result); + + +/** + * lws_system_cpd_state_get() - returns the last tested captive portal state + * + * \param context: the lws_context + * + * Returns one of the LWS_CPD_ constants indicating the system's understanding + * of the current captive portal situation. + */ +LWS_EXTERN LWS_VISIBLE lws_cpd_result_t +lws_system_cpd_state_get(struct lws_context *context); diff --git a/thirdparty/include/libwebsockets/lws-test-sequencer.h b/thirdparty/include/libwebsockets/lws-test-sequencer.h new file mode 100755 index 0000000000000000000000000000000000000000..334116c41e662e8600ae284b58193d2a0240e927 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-test-sequencer.h @@ -0,0 +1,61 @@ + /* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + * + * lws_test_sequencer manages running an array of unit tests. + */ + +typedef void (*lws_test_sequence_cb)(const void *cb_user); + +typedef struct lws_test_sequencer_args { + lws_abs_t *abs; /* abstract protocol + unit test txport */ + lws_unit_test_t *tests; /* array of lws_unit_test_t */ + int *results; /* takes result dispositions */ + int results_max; /* max space usable in results */ + int *count_tests; /* count of done tests */ + int *count_passes; /* count of passed tests */ + lws_test_sequence_cb cb; /* completion callback */ + void *cb_user; /* opaque user ptr given to cb */ +} lws_test_sequencer_args_t; + +/** + * lws_abs_unit_test_sequencer() - helper to sequence multiple unit tests + * + * \param args: lws_test_sequencer_args_t prepared with arguments for the tests + * + * This helper sequences one or more unit tests to run and collects the results. + * + * The incoming abs should be set up for the abstract protocol you want to test + * and the lws unit-test transport. + * + * Results are one of + * + * LPE_SUCCEEDED + * LPE_FAILED + * LPE_FAILED_UNEXPECTED_TIMEOUT + * LPE_FAILED_UNEXPECTED_PASS + * LPE_FAILED_UNEXPECTED_CLOSE + * + * The callback args->cb is called when the tests have been done. + */ +LWS_VISIBLE LWS_EXTERN int +lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args); diff --git a/thirdparty/include/libwebsockets/lws-threadpool.h b/thirdparty/include/libwebsockets/lws-threadpool.h new file mode 100755 index 0000000000000000000000000000000000000000..144c255741f5a3504153504cae238f64a3cc8a34 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-threadpool.h @@ -0,0 +1,280 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +/** \defgroup threadpool Threadpool related functions + * ##Threadpool + * \ingroup lwsapi + * + * This allows you to create one or more pool of threads which can run tasks + * associated with a wsi. If the pool is busy, tasks wait on a queue. + * + * Tasks don't have to be atomic, if they will take more than a few tens of ms + * they should return back to the threadpool worker with a return of 0. This + * will allow them to abort cleanly. + */ +//@{ + +struct lws_threadpool; +struct lws_threadpool_task; + +enum lws_threadpool_task_status { + LWS_TP_STATUS_QUEUED, + LWS_TP_STATUS_RUNNING, + LWS_TP_STATUS_SYNCING, + LWS_TP_STATUS_STOPPING, + LWS_TP_STATUS_FINISHED, /* lws_threadpool_task_status() frees task */ + LWS_TP_STATUS_STOPPED, /* lws_threadpool_task_status() frees task */ +}; + +enum lws_threadpool_task_return { + /** Still work to do, just confirming not being stopped */ + LWS_TP_RETURN_CHECKING_IN, + /** Still work to do, enter cond_wait until service thread syncs. This + * is used if you have filled your buffer(s) of data to the service + * thread and are blocked until the service thread completes sending at + * least one. + */ + LWS_TP_RETURN_SYNC, + /** No more work to do... */ + LWS_TP_RETURN_FINISHED, + /** Responding to request to stop */ + LWS_TP_RETURN_STOPPED, + + /* OR on to indicate this task wishes to outlive its wsi */ + LWS_TP_RETURN_FLAG_OUTLIVE = 64 +}; + +struct lws_threadpool_create_args { + int threads; + int max_queue_depth; +}; + +struct lws_threadpool_task_args { +#if defined(LWS_WITH_SECURE_STREAMS) + struct lws_ss_handle *ss; /**< either wsi or ss must be set */ +#endif + struct lws *wsi; /**< either wsi or ss must be set */ + + void *user; /**< user may set (user-private pointer) */ + const char *name; /**< user may set to describe task */ + char async_task; /**< set to allow the task to shrug off the loss + of the associated wsi and continue to + completion */ + enum lws_threadpool_task_return (*task)(void *user, + enum lws_threadpool_task_status s); + /**< user must set to actual task function */ + void (*cleanup)(struct lws *wsi, void *user); + /**< socket lifecycle may end while task is not stoppable, so the task + * must be able to detach from any wsi and clean itself up when it does + * stop. If NULL, no cleanup necessary, otherwise point to a user- + * supplied function that destroys the stuff in \p user. + * + * wsi may be NULL on entry, indicating the task got detached due to the + * wsi closing before. + */ +}; + +/** + * lws_threadpool_create() - create a pool of worker threads + * + * \param context: the lws_context the threadpool will exist inside + * \param args: argument struct prepared by caller + * \param format: printf-type format for the task name + * \param ...: printf type args for the task name format + * + * Creates a pool of worker threads with \p threads and a queue of up to + * \p max_queue_depth waiting tasks if all the threads are busy. + * + * Returns NULL if OOM, or a struct lws_threadpool pointer that must be + * destroyed by lws_threadpool_destroy(). + */ +LWS_VISIBLE LWS_EXTERN struct lws_threadpool * +lws_threadpool_create(struct lws_context *context, + const struct lws_threadpool_create_args *args, + const char *format, ...) LWS_FORMAT(3); + +/** + * lws_threadpool_finish() - Stop all pending and running tasks + * + * \param tp: the threadpool object + * + * Marks the threadpool as under destruction. Removes everything from the + * pending queue and completes those tasks as LWS_TP_STATUS_STOPPED. + * + * Running tasks will also get LWS_TP_STATUS_STOPPED as soon as they + * "resurface". + * + * This doesn't reap tasks or free the threadpool, the reaping is done by the + * lws_threadpool_task_status() on the done task. + */ +LWS_VISIBLE LWS_EXTERN void +lws_threadpool_finish(struct lws_threadpool *tp); + +/** + * lws_threadpool_destroy() - Destroy a threadpool + * + * \param tp: the threadpool object + * + * Waits for all worker threads to stop, ends the threads and frees the tp. + */ +LWS_VISIBLE LWS_EXTERN void +lws_threadpool_destroy(struct lws_threadpool *tp); + +/** + * lws_threadpool_enqueue() - Queue the task and run it on a worker thread when possible + * + * \param tp: the threadpool to queue / run on + * \param args: information about what to run + * \param format: printf-type format for the task name + * \param ...: printf type args for the task name format + * + * This asks for a task to run ASAP on a worker thread in threadpool \p tp. + * + * The args defines the wsi, a user-private pointer, a timeout in secs and + * a pointer to the task function. + * + * Returns NULL or an opaque pointer to the queued (or running, or completed) + * task. + * + * Once a task is created and enqueued, it can only be destroyed by calling + * lws_threadpool_task_status() on it after it has reached the state + * LWS_TP_STATUS_FINISHED or LWS_TP_STATUS_STOPPED. + */ +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_enqueue(struct lws_threadpool *tp, + const struct lws_threadpool_task_args *args, + const char *format, ...) LWS_FORMAT(3); + +/** + * lws_threadpool_dequeue() - Dequeue or try to stop a running task + * + * \param wsi: the wsi whose current task we want to eliminate + * + * Returns 0 is the task was dequeued or already compeleted, or 1 if the task + * has been asked to stop asynchronously. + * + * This doesn't free the task. It only shortcuts it to state + * LWS_TP_STATUS_STOPPED. lws_threadpool_task_status() must be performed on + * the task separately once it is in LWS_TP_STATUS_STOPPED to free the task. + * + * DEPRECATED: You should use lws_threadpool_dequeue_task() with + * lws_threadpool_get_task_wsi() / _ss() if you know there can only be one task + * per connection, or call it via lws_threadpool_foreach_task_wsi() / _ss() to + * get the tasks bound to the connection. + */ +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_dequeue(struct lws *wsi) LWS_WARN_DEPRECATED; + +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_dequeue_task(struct lws_threadpool_task *task); + + +/** + * lws_threadpool_task_status() - reap completed tasks + * + * \param wsi: the wsi to query the current task of + * \param task: receives a pointer to the opaque task + * \param user: receives a void * pointer to the task user data + * + * This is the equivalent of posix waitpid()... it returns the status of the + * task, and if the task is in state LWS_TP_STATUS_FINISHED or + * LWS_TP_STATUS_STOPPED, frees \p task. If in another state, the task + * continues to exist. + * + * This is designed to be called from the service thread. + * + * Its use is to make sure the service thread has seen the state of the task + * before deleting it. + * + * DEPRECATED... use lws_threadpool_task_status() instead and get the task + * pointer from lws_threadpool_get_task_wsi() / _ss() if you know there can only + * be one, else call it via lws_threadpool_foreach_task_wsi() / _ss() + */ +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_wsi(struct lws *wsi, + struct lws_threadpool_task **task, void **user) + LWS_WARN_DEPRECATED; + +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status(struct lws_threadpool_task *task, void **user); + +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task); + +/** + * lws_threadpool_task_sync() - Indicate to a stalled task it may continue + * + * \param task: the task to unblock + * \param stop: 0 = run after unblock, 1 = when he unblocks, stop him + * + * Inform the task that the service thread has finished with the shared data + * and that the task, if blocked in LWS_TP_RETURN_SYNC, may continue. + * + * If the lws service context determined that the task must be aborted, it + * should still call this but with stop = 1, causing the task to finish. + */ +LWS_VISIBLE LWS_EXTERN void +lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop); + +/** + * lws_threadpool_dump() - dump the state of a threadpool to the log + * + * \param tp: The threadpool to dump + * + * This locks the threadpool and then dumps the pending queue, the worker + * threads and the done queue, together with time information for how long + * the tasks have been in their current state, how long they have occupied a + * thread, etc. + * + * This only does anything on lws builds with CMAKE_BUILD_TYPE=DEBUG, otherwise + * while it still exists, it's a NOP. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_threadpool_dump(struct lws_threadpool *tp); + + + +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_wsi(struct lws *wsi); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_ss(struct lws_ss_handle *ss); +#endif + + +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, + int (*cb)(struct lws_threadpool_task *task, void *user)); +#endif + + +//@} diff --git a/thirdparty/include/libwebsockets/lws-timeout-timer.h b/thirdparty/include/libwebsockets/lws-timeout-timer.h new file mode 100755 index 0000000000000000000000000000000000000000..102a25fcd9519108ebfaf12bc0e067126bf8b360 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-timeout-timer.h @@ -0,0 +1,304 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup timeout Connection timeouts + + APIs related to setting connection timeouts +*/ +//@{ + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +enum pending_timeout { + NO_PENDING_TIMEOUT = 0, + PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE = 1, + PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE = 2, + PENDING_TIMEOUT_ESTABLISH_WITH_SERVER = 3, + PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE = 4, + PENDING_TIMEOUT_AWAITING_PING = 5, + PENDING_TIMEOUT_CLOSE_ACK = 6, + PENDING_TIMEOUT_UNUSED1 = 7, + PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE = 8, + PENDING_TIMEOUT_SSL_ACCEPT = 9, + PENDING_TIMEOUT_HTTP_CONTENT = 10, + PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND = 11, + PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE = 12, + PENDING_TIMEOUT_SHUTDOWN_FLUSH = 13, + PENDING_TIMEOUT_CGI = 14, + PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE = 15, + PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING = 16, + PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG = 17, + PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD = 18, + PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY = 19, + PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY = 20, + PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY = 21, + PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22, + PENDING_TIMEOUT_KILLED_BY_PARENT = 23, + PENDING_TIMEOUT_CLOSE_SEND = 24, + PENDING_TIMEOUT_HOLDING_AH = 25, + PENDING_TIMEOUT_UDP_IDLE = 26, + PENDING_TIMEOUT_CLIENT_CONN_IDLE = 27, + PENDING_TIMEOUT_LAGGING = 28, + PENDING_TIMEOUT_THREADPOOL = 29, + PENDING_TIMEOUT_THREADPOOL_TASK = 30, + PENDING_TIMEOUT_KILLED_BY_PROXY_CLIENT_CLOSE = 31, + PENDING_TIMEOUT_USER_OK = 32, + + /****** add new things just above ---^ ******/ + + PENDING_TIMEOUT_USER_REASON_BASE = 1000 +}; + +#define lws_time_in_microseconds lws_now_usecs + +#define LWS_TO_KILL_ASYNC -1 +/**< If LWS_TO_KILL_ASYNC is given as the timeout sec in a lws_set_timeout() + * call, then the connection is marked to be killed at the next timeout + * check. This is how you should force-close the wsi being serviced if + * you are doing it outside the callback (where you should close by nonzero + * return). + */ +#define LWS_TO_KILL_SYNC -2 +/**< If LWS_TO_KILL_SYNC is given as the timeout sec in a lws_set_timeout() + * call, then the connection is closed before returning (which may delete + * the wsi). This should only be used where the wsi being closed is not the + * wsi currently being serviced. + */ +/** + * lws_set_timeout() - marks the wsi as subject to a timeout some seconds hence + * + * \param wsi: Websocket connection instance + * \param reason: timeout reason + * \param secs: how many seconds. You may set to LWS_TO_KILL_ASYNC to + * force the connection to timeout at the next opportunity, or + * LWS_TO_KILL_SYNC to close it synchronously if you know the + * wsi is not the one currently being serviced. + */ +LWS_VISIBLE LWS_EXTERN void +lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs); + +/** + * lws_set_timeout_us() - marks the wsi as subject to a timeout some us hence + * + * \param wsi: Websocket connection instance + * \param reason: timeout reason + * \param us: 0 removes the timeout, otherwise number of us to wait + * + * Higher-resolution version of lws_set_timeout(). Actual resolution depends + * on platform and load, usually ms. + */ +void +lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us); + +/* helper for clearer LWS_TO_KILL_ASYNC / LWS_TO_KILL_SYNC usage */ +#define lws_wsi_close(w, to_kill) lws_set_timeout(w, 1, to_kill) + + +#define LWS_SET_TIMER_USEC_CANCEL ((lws_usec_t)-1ll) +#define LWS_USEC_PER_SEC ((lws_usec_t)1000000) + +/** + * lws_set_timer_usecs() - schedules a callback on the wsi in the future + * + * \param wsi: Websocket connection instance + * \param usecs: LWS_SET_TIMER_USEC_CANCEL removes any existing scheduled + * callback, otherwise number of microseconds in the future + * the callback will occur at. + * + * NOTE: event loop support for this: + * + * default poll() loop: yes + * libuv event loop: yes + * libev: not implemented (patch welcome) + * libevent: not implemented (patch welcome) + * + * After the deadline expires, the wsi will get a callback of type + * LWS_CALLBACK_TIMER and the timer is exhausted. The deadline may be + * continuously deferred by further calls to lws_set_timer_usecs() with a later + * deadline, or cancelled by lws_set_timer_usecs(wsi, -1). + * + * If the timer should repeat, lws_set_timer_usecs() must be called again from + * LWS_CALLBACK_TIMER. + * + * Accuracy depends on the platform and the load on the event loop or system... + * all that's guaranteed is the callback will come after the requested wait + * period. + */ +LWS_VISIBLE LWS_EXTERN void +lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs); + +struct lws_sorted_usec_list; + +typedef void (*sul_cb_t)(struct lws_sorted_usec_list *sul); + +typedef struct lws_sorted_usec_list { + struct lws_dll2 list; /* simplify the code by keeping this at start */ + lws_usec_t us; + sul_cb_t cb; + uint32_t latency_us; /* us it may safely be delayed */ +} lws_sorted_usec_list_t; + +/* + * There are multiple sul owners to allow accounting for, a) events that must + * wake from suspend, and b) events that can be missued due to suspend + */ +#define LWS_COUNT_PT_SUL_OWNERS 2 + +#define LWSSULLI_MISS_IF_SUSPENDED 0 +#define LWSSULLI_WAKE_IF_SUSPENDED 1 + +/* + * lws_sul2_schedule() - schedule a callback + * + * \param context: the lws_context + * \param tsi: the thread service index (usually 0) + * \param flags: LWSSULLI_... + * \param sul: pointer to the sul element + * + * Generic callback-at-a-later time function. The callback happens on the + * event loop thread context. + * + * Although the api has us resultion, the actual resolution depends on the + * platform and may be, eg, 1ms. + * + * This doesn't allocate and doesn't fail. + * + * If flags contains LWSSULLI_WAKE_IF_SUSPENDED, the scheduled event is placed + * on a sul owner list that, if the system has entered low power suspend mode, + * tries to arrange that the system should wake from platform suspend just + * before the event is due. Scheduled events without this flag will be missed + * in the case the system is in suspend and nothing else happens to have woken + * it. + * + * You can call it again with another us value to change the delay or move the + * event to a different owner (ie, wake or miss on suspend). + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul2_schedule(struct lws_context *context, int tsi, int flags, + lws_sorted_usec_list_t *sul); + +/* + * lws_sul_cancel() - cancel scheduled callback + * + * \param sul: pointer to the sul element + * + * If it's scheduled, remove the sul from its owning sorted list. + * If not scheduled, it's a NOP. + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul_cancel(lws_sorted_usec_list_t *sul); + +/* + * lws_sul_earliest_wakeable_event() - get earliest wake-from-suspend event + * + * \param ctx: the lws context + * \param pearliest: pointer to lws_usec_t to take the result + * + * Either returns 1 if no pending event, or 0 and sets *pearliest to the + * MONOTONIC time of the current earliest next expected event. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sul_earliest_wakeable_event(struct lws_context *ctx, lws_usec_t *pearliest); + +/* + * For backwards compatibility + * + * If us is LWS_SET_TIMER_USEC_CANCEL, the sul is removed from the scheduler. + * New code can use lws_sul_cancel() + */ + +LWS_VISIBLE LWS_EXTERN void +lws_sul_schedule(struct lws_context *ctx, int tsi, lws_sorted_usec_list_t *sul, + sul_cb_t _cb, lws_usec_t _us); +LWS_VISIBLE LWS_EXTERN void +lws_sul_schedule_wakesuspend(struct lws_context *ctx, int tsi, + lws_sorted_usec_list_t *sul, sul_cb_t _cb, + lws_usec_t _us); + +#if defined(LWS_WITH_SUL_DEBUGGING) +/** + * lws_sul_debug_zombies() - assert there are no scheduled sul in a given object + * + * \param ctx: lws_context + * \param po: pointer to the object that is about to be destroyed + * \param len: length of the object that is about to be destroyed + * \param destroy_description: string clue what any failure is related to + * + * This is an optional debugging helper that walks the sul scheduler lists + * confirming that there are no suls scheduled that live inside the object + * footprint described by po and len. When internal objects are about to be + * destroyed, like wsi / user_data or secure stream handles, if + * LWS_WITH_SUL_DEBUGGING is enabled the scheduler is checked for anything + * in the object being destroyed. If something found, an error is printed and + * an assert fired. + * + * Internal sul like timeouts should always be cleaned up correctly, but user + * suls in, eg, wsi user_data area, or in secure stream user allocation, may be + * the cause of difficult to find bugs if valgrind not available and the user + * code left a sul in the scheduler after destroying the object the sul was + * living in. + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul_debug_zombies(struct lws_context *ctx, void *po, size_t len, + const char *destroy_description); +#else +#define lws_sul_debug_zombies(_a, _b, _c, _d) +#endif + +/* + * lws_validity_confirmed() - reset the validity timer for a network connection + * + * \param wsi: the connection that saw traffic proving the connection valid + * + * Network connections are subject to intervals defined by the context, the + * vhost if server connections, or the client connect info if a client + * connection. If the connection goes longer than the specified time since + * last observing traffic that can only happen if traffic is passing in both + * directions, then lws will try to create a PING transaction on the network + * connection. + * + * If the connection reaches the specified `.secs_since_valid_hangup` time + * still without any proof of validity, the connection will be closed. + * + * If the PONG comes, or user code observes traffic that satisfies the proof + * that both directions are passing traffic to the peer and calls this api, + * the connection validity timer is reset and the scheme repeats. + */ +LWS_VISIBLE LWS_EXTERN void +lws_validity_confirmed(struct lws *wsi); + +/* + * These are not normally needed, they're exported for the case there's code + * using lws_sul for which lws is an optional link dependency. + */ + +LWS_VISIBLE LWS_EXTERN int +__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul); + +LWS_VISIBLE LWS_EXTERN lws_usec_t +__lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-tls-sessions.h b/thirdparty/include/libwebsockets/lws-tls-sessions.h new file mode 100755 index 0000000000000000000000000000000000000000..e0b409e6f278d01bb620ae48ade7bc3dd814ed82 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-tls-sessions.h @@ -0,0 +1,81 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2021 Andy Green + * + * 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. + */ + +/*! \defgroup tls_sessions TLS Session Management + + APIs related to managing TLS Sessions +*/ +//@{ + + +#define LWS_SESSION_TAG_LEN 96 + +struct lws_tls_session_dump +{ + char tag[LWS_SESSION_TAG_LEN]; + void *blob; + void *opaque; + size_t blob_len; +}; + +typedef int (*lws_tls_sess_cb_t)(struct lws_context *cx, + struct lws_tls_session_dump *info); + +/** + * lws_tls_session_dump_save() - serialize a tls session via a callback + * + * \param vh: the vhost to load into the session cache + * \param host: the name of the host the session relates to + * \param port: the port the session connects to on the host + * \param cb_save: the callback to perform the saving of the session blob + * \param opq: an opaque pointer passed into the callback + * + * If a session matching the vhost/host/port exists in the vhost's session + * cache, serialize it via the provided callback. + * + * \p opq is passed to the callback without being used by lws at all. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_session_dump_save(struct lws_vhost *vh, const char *host, uint16_t port, + lws_tls_sess_cb_t cb_save, void *opq); + +/** + * lws_tls_session_dump_load() - deserialize a tls session via a callback + * + * \param vh: the vhost to load into the session cache + * \param host: the name of the host the session relates to + * \param port: the port the session connects to on the host + * \param cb_load: the callback to retreive the session blob from + * \param opq: an opaque pointer passed into the callback + * + * Try to preload a session described by the first three parameters into the + * client session cache, from the given callback. + * + * \p opq is passed to the callback without being used by lws at all. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_session_dump_load(struct lws_vhost *vh, const char *host, uint16_t port, + lws_tls_sess_cb_t cb_load, void *opq); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-tokenize.h b/thirdparty/include/libwebsockets/lws-tokenize.h new file mode 100755 index 0000000000000000000000000000000000000000..66b34b41a314f440ce493378222e8afae5bba6f9 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-tokenize.h @@ -0,0 +1,272 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/* Do not treat - as a terminal character, so "my-token" is one token */ +#define LWS_TOKENIZE_F_MINUS_NONTERM (1 << 0) +/* Separately report aggregate colon-delimited tokens */ +#define LWS_TOKENIZE_F_AGG_COLON (1 << 1) +/* Enforce sequencing for a simple token , token , token ... list */ +#define LWS_TOKENIZE_F_COMMA_SEP_LIST (1 << 2) +/* Allow more characters in the tokens and less delimiters... default is + * only alphanumeric + underscore in tokens */ +#define LWS_TOKENIZE_F_RFC7230_DELIMS (1 << 3) +/* Do not treat . as a terminal character, so "warmcat.com" is one token */ +#define LWS_TOKENIZE_F_DOT_NONTERM (1 << 4) +/* If something starts looking like a float, like 1.2, force to be string token. + * This lets you receive dotted-quads like 192.168.0.1 as string tokens, and + * avoids illegal float format detection like 1.myserver.com */ +#define LWS_TOKENIZE_F_NO_FLOATS (1 << 5) +/* Instead of LWS_TOKZE_INTEGER, report integers as any other string token */ +#define LWS_TOKENIZE_F_NO_INTEGERS (1 << 6) +/* # makes the rest of the line a comment */ +#define LWS_TOKENIZE_F_HASH_COMMENT (1 << 7) +/* Do not treat / as a terminal character, so "multipart/related" is one token */ +#define LWS_TOKENIZE_F_SLASH_NONTERM (1 << 8) +/* Do not treat * as a terminal character, so "myfile*" is one token */ +#define LWS_TOKENIZE_F_ASTERISK_NONTERM (1 << 9) +/* Do not treat = as a terminal character, so "x=y" is one token */ +#define LWS_TOKENIZE_F_EQUALS_NONTERM (1 << 10) + +typedef enum { + + LWS_TOKZE_ERRS = 5, /* the number of errors defined */ + + LWS_TOKZE_ERR_BROKEN_UTF8 = -5, /* malformed or partial utf8 */ + LWS_TOKZE_ERR_UNTERM_STRING = -4, /* ended while we were in "" */ + LWS_TOKZE_ERR_MALFORMED_FLOAT = -3, /* like 0..1 or 0.1.1 */ + LWS_TOKZE_ERR_NUM_ON_LHS = -2, /* like 123= or 0.1= */ + LWS_TOKZE_ERR_COMMA_LIST = -1, /* like ",tok", or, "tok,," */ + + LWS_TOKZE_ENDED = 0, /* no more content */ + + /* Note: results have ordinal 1+, EOT is 0 and errors are < 0 */ + + LWS_TOKZE_DELIMITER, /* a delimiter appeared */ + LWS_TOKZE_TOKEN, /* a token appeared */ + LWS_TOKZE_INTEGER, /* an integer appeared */ + LWS_TOKZE_FLOAT, /* a float appeared */ + LWS_TOKZE_TOKEN_NAME_EQUALS, /* token [whitespace] = */ + LWS_TOKZE_TOKEN_NAME_COLON, /* token [whitespace] : (only with + LWS_TOKENIZE_F_AGG_COLON flag) */ + LWS_TOKZE_QUOTED_STRING, /* "*", where * may have any char */ + +} lws_tokenize_elem; + +/* + * helper enums to allow caller to enforce legal delimiter sequencing, eg + * disallow "token,,token", "token,", and ",token" + */ + +enum lws_tokenize_delimiter_tracking { + LWSTZ_DT_NEED_FIRST_CONTENT, + LWSTZ_DT_NEED_DELIM, + LWSTZ_DT_NEED_NEXT_CONTENT, +}; + +typedef struct lws_tokenize { + const char *start; /**< set to the start of the string to tokenize */ + const char *token; /**< the start of an identified token or delimiter */ + size_t len; /**< set to the length of the string to tokenize */ + size_t token_len; /**< the length of the identied token or delimiter */ + + uint16_t flags; /**< optional LWS_TOKENIZE_F_ flags, or 0 */ + uint8_t delim; + + int8_t e; /**< convenient for storing lws_tokenize return */ +} lws_tokenize_t; + +/** + * lws_tokenize() - breaks down a string into tokens and delimiters in-place + * + * \param ts: the lws_tokenize struct to init + * \param start: the string to tokenize + * \param flags: LWS_TOKENIZE_F_ option flags + * + * This initializes the tokenize struct to point to the given string, and + * sets the length to 2GiB - 1 (so there must be a terminating NUL)... you can + * override this requirement by setting ts.len yourself before using it. + * + * .delim is also initialized to LWSTZ_DT_NEED_FIRST_CONTENT. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_tokenize_init(struct lws_tokenize *ts, const char *start, int flags); + +/** + * lws_tokenize() - breaks down a string into tokens and delimiters in-place + * + * \param ts: the lws_tokenize struct with information and state on what to do + * + * The \p ts struct should have its start, len and flags members initialized to + * reflect the string to be tokenized and any options. + * + * Then `lws_tokenize()` may be called repeatedly on the struct, returning one + * of `lws_tokenize_elem` each time, and with the struct's `token` and + * `token_len` members set to describe the content of the delimiter or token + * payload each time. + * + * There are no allocations during the process. + * + * returns lws_tokenize_elem that was identified (LWS_TOKZE_ENDED means reached + * the end of the string). + */ + +LWS_VISIBLE LWS_EXTERN lws_tokenize_elem +lws_tokenize(struct lws_tokenize *ts); + +/** + * lws_tokenize_cstr() - copy token string to NUL-terminated buffer + * + * \param ts: pointer to lws_tokenize struct to operate on + * \param str: destination buffer + * \pparam max: bytes in destination buffer + * + * returns 0 if OK or nonzero if the string + NUL won't fit. + */ + +LWS_VISIBLE LWS_EXTERN int +lws_tokenize_cstr(struct lws_tokenize *ts, char *str, size_t max); + + +/* + * lws_strexp: flexible string expansion helper api + * + * This stateful helper can handle multiple separate input chunks and multiple + * output buffer loads with arbitrary boundaries between literals and expanded + * symbols. This allows it to handle fragmented input as well as arbitrarily + * long symbol expansions that are bigger than the output buffer itself. + * + * A user callback is used to convert symbol names to the symbol value. + * + * A single byte buffer for input and another for output can process any + * length substitution then. The state object is around 64 bytes on a 64-bit + * system and it only uses 8 bytes stack. + */ + + +typedef int (*lws_strexp_expand_cb)(void *priv, const char *name, char *out, + size_t *pos, size_t olen, size_t *exp_ofs); + +typedef struct lws_strexp { + char name[32]; + lws_strexp_expand_cb cb; + void *priv; + char *out; + size_t olen; + size_t pos; + + size_t exp_ofs; + + uint8_t name_pos; + char state; +} lws_strexp_t; + +enum { + LSTRX_DONE, /* it completed OK */ + LSTRX_FILLED_OUT, /* out buf filled and needs resetting */ + LSTRX_FATAL_NAME_TOO_LONG = -1, /* fatal */ + LSTRX_FATAL_NAME_UNKNOWN = -2, +}; + + +/** + * lws_strexp_init() - initialize an lws_strexp_t for use + * + * \p exp: the exp object to init + * \p priv: the user's object pointer to pass to callback + * \p cb: the callback to expand named objects + * \p out: the start of the output buffer, or NULL just to get the length + * \p olen: the length of the output buffer in bytes + * + * Prepares an lws_strexp_t for use and sets the initial output buffer + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. + */ +LWS_VISIBLE LWS_EXTERN void +lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, + char *out, size_t olen); + +/** + * lws_strexp_reset_out() - reset the output buffer on an existing strexp + * + * \p exp: the exp object to init + * \p out: the start of the output buffer, or NULL to just get length + * \p olen: the length of the output buffer in bytes + * + * Provides a new output buffer for lws_strexp_expand() to continue to write + * into. It can be the same as the old one if it has been copied out or used. + * The position of the next write will be reset to the start of the given buf. + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. \p olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. + */ +LWS_VISIBLE LWS_EXTERN void +lws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen); + +/** + * lws_strexp_expand() - copy / expand a string into the output buffer + * + * \p exp: the exp object for the copy / expansion + * \p in: the start of the next input data + * \p len: the length of the input data + * \p pused_in: pointer to write the amount of input used + * \p pused_out: pointer to write the amount of output used + * + * Copies in to the output buffer set in exp, expanding any ${name} tokens using + * the callback. \p *pused_in is set to the number of input chars used and + * \p *pused_out the number of output characters used + * + * May return LSTRX_FILLED_OUT early with *pused < len if the output buffer is + * filled. Handle the output buffer and reset it with lws_strexp_reset_out() + * before calling again with adjusted in / len to continue. + * + * In the case of large expansions, the expansion itself may fill the output + * buffer, in which case the expansion callback returns the LSTRX_FILLED_OUT + * and will be called again to continue with its *exp_ofs parameter set + * appropriately. + */ +LWS_VISIBLE LWS_EXTERN int +lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, + size_t *pused_in, size_t *pused_out); + +/** + * lws_strcmp_wildcard() - strcmp but the first arg can have wildcards + * + * \p wildcard: a string that may contain zero to three *, and may lack a NUL + * \p wlen: length of the wildcard string + * \p check: string to test to see if it matches wildcard + * \p clen: length of check string + * + * Like strcmp, but supports patterns like "a*", "a*b", "a*b*" etc + * where a and b are arbitrary substrings. Both the wc and check strings need + * not be NUL terminated, but are specified by lengths. + */ +LWS_VISIBLE LWS_EXTERN int +lws_strcmp_wildcard(const char *wildcard, size_t wlen, const char *check, + size_t clen); diff --git a/thirdparty/include/libwebsockets/lws-vfs.h b/thirdparty/include/libwebsockets/lws-vfs.h new file mode 100755 index 0000000000000000000000000000000000000000..4b0c7073899a1938f7936297648694aa713276c7 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-vfs.h @@ -0,0 +1,273 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup fops file operation wrapping + * + * ##File operation wrapping + * + * Use these helper functions if you want to access a file from the perspective + * of a specific wsi, which is usually the case. If you just want contextless + * file access, use the fops callbacks directly with NULL wsi instead of these + * helpers. + * + * If so, then it calls the platform handler or user overrides where present + * (as defined in info->fops) + * + * The advantage from all this is user code can be portable for file operations + * without having to deal with differences between platforms. + */ +//@{ + +/** struct lws_plat_file_ops - Platform-specific file operations + * + * These provide platform-agnostic ways to deal with filesystem access in the + * library and in the user code. + */ + +#if defined(LWS_PLAT_FREERTOS) +/* sdk preprocessor defs? compiler issue? gets confused with member names */ +#define LWS_FOP_OPEN _open +#define LWS_FOP_CLOSE _close +#define LWS_FOP_SEEK_CUR _seek_cur +#define LWS_FOP_READ _read +#define LWS_FOP_WRITE _write +#else +#define LWS_FOP_OPEN open +#define LWS_FOP_CLOSE close +#define LWS_FOP_SEEK_CUR seek_cur +#define LWS_FOP_READ read +#define LWS_FOP_WRITE write +#endif + +#define LWS_FOP_FLAGS_MASK ((1 << 23) - 1) +#define LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP (1 << 24) +#define LWS_FOP_FLAG_COMPR_IS_GZIP (1 << 25) +#define LWS_FOP_FLAG_MOD_TIME_VALID (1 << 26) +#define LWS_FOP_FLAG_VIRTUAL (1 << 27) + +struct lws_plat_file_ops; + +struct lws_fop_fd { + lws_filefd_type fd; + /**< real file descriptor related to the file... */ + const struct lws_plat_file_ops *fops; + /**< fops that apply to this fop_fd */ + void *filesystem_priv; + /**< ignored by lws; owned by the fops handlers */ + lws_filepos_t pos; + /**< generic "position in file" */ + lws_filepos_t len; + /**< generic "length of file" */ + lws_fop_flags_t flags; + /**< copy of the returned flags */ + uint32_t mod_time; + /**< optional "modification time of file", only valid if .open() + * set the LWS_FOP_FLAG_MOD_TIME_VALID flag */ +}; +typedef struct lws_fop_fd *lws_fop_fd_t; + +struct lws_fops_index { + const char *sig; /* NULL or vfs signature, eg, ".zip/" */ + uint8_t len; /* length of above string */ +}; + +struct lws_plat_file_ops { + lws_fop_fd_t (*LWS_FOP_OPEN)(const struct lws_plat_file_ops *fops, + const char *filename, const char *vpath, + lws_fop_flags_t *flags); + /**< Open file (always binary access if plat supports it) + * vpath may be NULL, or if the fops understands it, the point at which + * the filename's virtual part starts. + * *flags & LWS_FOP_FLAGS_MASK should be set to O_RDONLY or O_RDWR. + * If the file may be gzip-compressed, + * LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP is set. If it actually is + * gzip-compressed, then the open handler should OR + * LWS_FOP_FLAG_COMPR_IS_GZIP on to *flags before returning. + */ + int (*LWS_FOP_CLOSE)(lws_fop_fd_t *fop_fd); + /**< close file AND set the pointer to NULL */ + lws_fileofs_t (*LWS_FOP_SEEK_CUR)(lws_fop_fd_t fop_fd, + lws_fileofs_t offset_from_cur_pos); + /**< seek from current position */ + int (*LWS_FOP_READ)(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len); + /**< Read from file, on exit *amount is set to amount actually read */ + int (*LWS_FOP_WRITE)(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len); + /**< Write to file, on exit *amount is set to amount actually written */ + + struct lws_fops_index fi[3]; + /**< vfs path signatures implying use of this fops */ + + const struct lws_plat_file_ops *next; + /**< NULL or next fops in list */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility */ +}; + +/** + * lws_get_fops() - get current file ops + * + * \param context: context + */ +LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * LWS_WARN_UNUSED_RESULT +lws_get_fops(struct lws_context *context); +LWS_VISIBLE LWS_EXTERN void +lws_set_fops(struct lws_context *context, const struct lws_plat_file_ops *fops); +/** + * lws_vfs_tell() - get current file position + * + * \param fop_fd: fop_fd we are asking about + */ +LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT +lws_vfs_tell(lws_fop_fd_t fop_fd); +/** + * lws_vfs_get_length() - get current file total length in bytes + * + * \param fop_fd: fop_fd we are asking about + */ +LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT +lws_vfs_get_length(lws_fop_fd_t fop_fd); +/** + * lws_vfs_get_mod_time() - get time file last modified + * + * \param fop_fd: fop_fd we are asking about + */ +LWS_VISIBLE LWS_EXTERN uint32_t LWS_WARN_UNUSED_RESULT +lws_vfs_get_mod_time(lws_fop_fd_t fop_fd); +/** + * lws_vfs_file_seek_set() - seek relative to start of file + * + * \param fop_fd: fop_fd we are seeking in + * \param offset: offset from start of file + */ +LWS_VISIBLE LWS_EXTERN lws_fileofs_t +lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset); +/** + * lws_vfs_file_seek_end() - seek relative to end of file + * + * \param fop_fd: fop_fd we are seeking in + * \param offset: offset from start of file + */ +LWS_VISIBLE LWS_EXTERN lws_fileofs_t +lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset); + +extern struct lws_plat_file_ops fops_zip; + +/** + * lws_plat_file_open() - open vfs filepath + * + * \param fops: file ops struct that applies to this descriptor + * \param vfs_path: filename to open + * \param flags: pointer to open flags + * + * The vfs_path is scanned for known fops signatures, and the open directed + * to any matching fops open. + * + * User code should use this api to perform vfs opens. + * + * returns semi-opaque handle + */ +LWS_VISIBLE LWS_EXTERN lws_fop_fd_t LWS_WARN_UNUSED_RESULT +lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *vfs_path, + lws_fop_flags_t *flags); + +/** + * lws_plat_file_close() - close file + * + * \param fop_fd: file handle to close + */ +static LWS_INLINE int +lws_vfs_file_close(lws_fop_fd_t *fop_fd) +{ + if (*fop_fd && (*fop_fd)->fops) + return (*fop_fd)->fops->LWS_FOP_CLOSE(fop_fd); + + return 0; +} + +/** + * lws_plat_file_seek_cur() - close file + * + * + * \param fop_fd: file handle + * \param offset: position to seek to + */ +static LWS_INLINE lws_fileofs_t +lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) +{ + return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset); +} +/** + * lws_plat_file_read() - read from file + * + * \param fop_fd: file handle + * \param amount: how much to read (rewritten by call) + * \param buf: buffer to write to + * \param len: max length + */ +static LWS_INLINE int LWS_WARN_UNUSED_RESULT +lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len) +{ + return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len); +} +/** + * lws_plat_file_write() - write from file + * + * \param fop_fd: file handle + * \param amount: how much to write (rewritten by call) + * \param buf: buffer to read from + * \param len: max length + */ +static LWS_INLINE int LWS_WARN_UNUSED_RESULT +lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len) +{ + return fop_fd->fops->LWS_FOP_WRITE(fop_fd, amount, buf, len); +} + +/* these are the platform file operations implementations... they can + * be called directly and used in fops arrays + */ + +LWS_VISIBLE LWS_EXTERN lws_fop_fd_t +_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, + const char *vpath, lws_fop_flags_t *flags); +LWS_VISIBLE LWS_EXTERN int +_lws_plat_file_close(lws_fop_fd_t *fop_fd); +LWS_VISIBLE LWS_EXTERN lws_fileofs_t +_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset); +LWS_VISIBLE LWS_EXTERN int +_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len); +LWS_VISIBLE LWS_EXTERN int +_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, + uint8_t *buf, lws_filepos_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_alloc_vfs_file(struct lws_context *context, const char *filename, + uint8_t **buf, lws_filepos_t *amount); +//@} diff --git a/thirdparty/include/libwebsockets/lws-write.h b/thirdparty/include/libwebsockets/lws-write.h new file mode 100755 index 0000000000000000000000000000000000000000..5fffb4d014d3b34a8c0fe1a9e214dfbcf8f21128 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-write.h @@ -0,0 +1,276 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup sending-data Sending data + + APIs related to writing data on a connection +*/ +//@{ +#if !defined(LWS_SIZEOFPTR) +#define LWS_SIZEOFPTR ((int)sizeof (void *)) +#endif + +#if defined(__x86_64__) +#define _LWS_PAD_SIZE 16 /* Intel recommended for best performance */ +#else +#define _LWS_PAD_SIZE LWS_SIZEOFPTR /* Size of a pointer on the target arch */ +#endif +#define _LWS_PAD(n) (((n) % _LWS_PAD_SIZE) ? \ + ((n) + (_LWS_PAD_SIZE - ((n) % _LWS_PAD_SIZE))) : (n)) +/* last 2 is for lws-meta */ +#define LWS_PRE _LWS_PAD(4 + 10 + 2) +/* used prior to 1.7 and retained for backward compatibility */ +#define LWS_SEND_BUFFER_PRE_PADDING LWS_PRE +#define LWS_SEND_BUFFER_POST_PADDING 0 + +#define LWS_WRITE_RAW LWS_WRITE_HTTP + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +enum lws_write_protocol { + LWS_WRITE_TEXT = 0, + /**< Send a ws TEXT message,the pointer must have LWS_PRE valid + * memory behind it. + * + * The receiver expects only valid utf-8 in the payload */ + LWS_WRITE_BINARY = 1, + /**< Send a ws BINARY message, the pointer must have LWS_PRE valid + * memory behind it. + * + * Any sequence of bytes is valid */ + LWS_WRITE_CONTINUATION = 2, + /**< Continue a previous ws message, the pointer must have LWS_PRE valid + * memory behind it */ + LWS_WRITE_HTTP = 3, + /**< Send HTTP content */ + + /* LWS_WRITE_CLOSE is handled by lws_close_reason() */ + LWS_WRITE_PING = 5, + LWS_WRITE_PONG = 6, + + /* Same as write_http but we know this write ends the transaction */ + LWS_WRITE_HTTP_FINAL = 7, + + /* HTTP2 */ + + LWS_WRITE_HTTP_HEADERS = 8, + /**< Send http headers (http2 encodes this payload and LWS_WRITE_HTTP + * payload differently, http 1.x links also handle this correctly. so + * to be compatible with both in the future,header response part should + * be sent using this regardless of http version expected) + */ + LWS_WRITE_HTTP_HEADERS_CONTINUATION = 9, + /**< Continuation of http/2 headers + */ + + /****** add new things just above ---^ ******/ + + /* flags */ + + LWS_WRITE_BUFLIST = 0x20, + /**< Don't actually write it... stick it on the output buflist and + * write it as soon as possible. Useful if you learn you have to + * write something, have the data to write to hand but the timing is + * unrelated as to whether the connection is writable or not, and were + * otherwise going to have to allocate a temp buffer and write it + * later anyway */ + + LWS_WRITE_NO_FIN = 0x40, + /**< This part of the message is not the end of the message */ + + LWS_WRITE_H2_STREAM_END = 0x80, + /**< Flag indicates this packet should go out with STREAM_END if h2 + * STREAM_END is allowed on DATA or HEADERS. + */ + + LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80 + /**< client packet payload goes out on wire unmunged + * only useful for security tests since normal servers cannot + * decode the content if used */ +}; + +/* used with LWS_CALLBACK_CHILD_WRITE_VIA_PARENT */ + +struct lws_write_passthru { + struct lws *wsi; + unsigned char *buf; + size_t len; + enum lws_write_protocol wp; +}; + + +/** + * lws_write() - Apply protocol then write data to client + * + * \param wsi: Websocket instance (available from user callback) + * \param buf: The data to send. For data being sent on a websocket + * connection (ie, not default http), this buffer MUST have + * LWS_PRE bytes valid BEFORE the pointer. + * This is so the protocol header data can be added in-situ. + * \param len: Count of the data bytes in the payload starting from buf + * \param protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one + * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate + * data on a websockets connection. Remember to allow the extra + * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT + * are used. + * + * This function provides the way to issue data back to the client, for any + * role (h1, h2, ws, raw, etc). It can only be called from the WRITEABLE + * callback. + * + * IMPORTANT NOTICE! + * + * When sending with ws protocol + * + * LWS_WRITE_TEXT, + * LWS_WRITE_BINARY, + * LWS_WRITE_CONTINUATION, + * LWS_WRITE_PING, + * LWS_WRITE_PONG, + * + * or sending on http/2... the send buffer has to have LWS_PRE bytes valid + * BEFORE the buffer pointer you pass to lws_write(). Since you'll probably + * want to use http/2 before too long, it's wise to just always do this with + * lws_write buffers... LWS_PRE is typically 16 bytes it's not going to hurt + * usually. + * + * start of alloc ptr passed to lws_write end of allocation + * | | | + * v <-- LWS_PRE bytes --> v v + * [---------------- allocated memory ---------------] + * (for lws use) [====== user buffer ======] + * + * This allows us to add protocol info before the data, and send as one packet + * on the network without payload copying, for maximum efficiency. + * + * So for example you need this kind of code to use lws_write with a + * 128-byte payload + * + * char buf[LWS_PRE + 128]; + * + * // fill your part of the buffer... for example here it's all zeros + * memset(&buf[LWS_PRE], 0, 128); + * + * if (lws_write(wsi, &buf[LWS_PRE], 128, LWS_WRITE_TEXT) < 128) { + * ... the connection is dead ... + * return -1; + * } + * + * LWS_PRE is currently 16, which covers ws and h2 frame headers, and is + * compatible with 32 and 64-bit alignment requirements. + * + * (LWS_SEND_BUFFER_POST_PADDING is deprecated, it's now 0 and can be left off.) + * + * Return may be -1 is the write failed in a way indicating that the connection + * has ended already, in which case you can close your side, or a positive + * number that is at least the number of bytes requested to send (under some + * encapsulation scenarios, it can indicate more than you asked was sent). + * + * The recommended test of the return is less than what you asked indicates + * the connection has failed. + * + * Truncated Writes + * ================ + * + * The OS may not accept everything you asked to write on the connection. + * + * Posix defines POLLOUT indication from poll() to show that the connection + * will accept more write data, but it doesn't specifiy how much. It may just + * accept one byte of whatever you wanted to send. + * + * LWS will buffer the remainder automatically, and send it out autonomously. + * + * During that time, WRITABLE callbacks to user code will be suppressed and + * instead used internally. After it completes, it will send an extra WRITEABLE + * callback to the user code, in case any request was missed. So it is possible + * to receive unasked-for WRITEABLE callbacks, the user code should have enough + * state to know if it wants to write anything and just return if not. + * + * This is to handle corner cases where unexpectedly the OS refuses what we + * usually expect it to accept. It's not recommended as the way to randomly + * send huge payloads, since it is being copied on to heap and is inefficient. + * + * Huge payloads should instead be sent in fragments that are around 2 x mtu, + * which is almost always directly accepted by the OS. To simplify this for + * ws fragments, there is a helper lws_write_ws_flags() below that simplifies + * selecting the correct flags to give lws_write() for each fragment. + * + * In the case of RFC8441 ws-over-h2, you cannot send ws fragments larger than + * the max h2 frame size, typically 16KB, but should further restrict it to + * the same ~2 x mtu limit mentioned above. + */ +LWS_VISIBLE LWS_EXTERN int +lws_write(struct lws *wsi, unsigned char *buf, size_t len, + enum lws_write_protocol protocol); + +/* helper for case where buffer may be const */ +#define lws_write_http(wsi, buf, len) \ + lws_write(wsi, (unsigned char *)(buf), len, LWS_WRITE_HTTP) + +/** + * lws_write_ws_flags() - Helper for multi-frame ws message flags + * + * \param initial: the lws_write flag to use for the start fragment, eg, + * LWS_WRITE_TEXT + * \param is_start: nonzero if this is the first fragment of the message + * \param is_end: nonzero if this is the last fragment of the message + * + * Returns the correct LWS_WRITE_ flag to use for each fragment of a message + * in turn. + */ +static LWS_INLINE int +lws_write_ws_flags(int initial, int is_start, int is_end) +{ + int r; + + if (is_start) + r = initial; + else + r = LWS_WRITE_CONTINUATION; + + if (!is_end) + r |= LWS_WRITE_NO_FIN; + + return r; +} + +/** + * lws_raw_transaction_completed() - Helper for flushing before close + * + * \param wsi: the struct lws to operate on + * + * Returns -1 if the wsi can close now. However if there is buffered, unsent + * data, the wsi is marked as to be closed when the output buffer data is + * drained, and it returns 0. + * + * For raw cases where the transaction completed without failure, + * `return lws_raw_transaction_completed(wsi)` should better be used than + * return -1. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_raw_transaction_completed(struct lws *wsi); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-writeable.h b/thirdparty/include/libwebsockets/lws-writeable.h new file mode 100755 index 0000000000000000000000000000000000000000..88489110759e9aa503f3d9acbc03f0944b6b75c6 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-writeable.h @@ -0,0 +1,246 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup callback-when-writeable Callback when writeable + * + * ##Callback When Writeable + * + * lws can only write data on a connection when it is able to accept more + * data without blocking. + * + * So a basic requirement is we should only use the lws_write() apis when the + * connection we want to write on says that he can accept more data. + * + * When lws cannot complete your send at the time, it will buffer the data + * and send it in the background, suppressing any further WRITEABLE callbacks + * on that connection until it completes. So it is important to write new + * things in a new writeable callback. + * + * These apis reflect the various ways we can indicate we would like to be + * called back when one or more connections is writeable. + */ +///@{ + +/** + * lws_callback_on_writable() - Request a callback when this socket + * becomes able to be written to without + * blocking + * + * \param wsi: Websocket connection instance to get callback for + * + * - Which: only this wsi + * - When: when the individual connection becomes writeable + * - What: LWS_CALLBACK_*_WRITEABLE + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_on_writable(struct lws *wsi); + +/** + * lws_callback_on_writable_all_protocol() - Request a callback for all + * connections using the given protocol when it + * becomes possible to write to each socket without + * blocking in turn. + * + * \param context: lws_context + * \param protocol: Protocol whose connections will get callbacks + * + * - Which: connections using this protocol on ANY VHOST + * - When: when the individual connection becomes writeable + * - What: LWS_CALLBACK_*_WRITEABLE + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_on_writable_all_protocol(const struct lws_context *context, + const struct lws_protocols *protocol); + +/** + * lws_callback_on_writable_all_protocol_vhost() - Request a callback for + * all connections on same vhost using the given protocol + * when it becomes possible to write to each socket without + * blocking in turn. + * + * \param vhost: Only consider connections on this lws_vhost + * \param protocol: Protocol whose connections will get callbacks + * + * - Which: connections using this protocol on GIVEN VHOST ONLY + * - When: when the individual connection becomes writeable + * - What: LWS_CALLBACK_*_WRITEABLE + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost, + const struct lws_protocols *protocol); + +/** + * lws_callback_all_protocol() - Callback all connections using + * the given protocol with the given reason + * + * \param context: lws_context + * \param protocol: Protocol whose connections will get callbacks + * \param reason: Callback reason index + * + * - Which: connections using this protocol on ALL VHOSTS + * - When: before returning + * - What: reason + * + * This isn't normally what you want... normally any update of connection- + * specific information can wait until a network-related callback like rx, + * writable, or close. + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_all_protocol(struct lws_context *context, + const struct lws_protocols *protocol, int reason); + +/** + * lws_callback_all_protocol_vhost() - Callback all connections using + * the given protocol with the given reason. This is + * deprecated since v2.4: use lws_callback_all_protocol_vhost_args + * + * \param vh: Vhost whose connections will get callbacks + * \param protocol: Which protocol to match. NULL means all. + * \param reason: Callback reason index + * + * - Which: connections using this protocol on GIVEN VHOST ONLY + * - When: now + * - What: reason + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_all_protocol_vhost(struct lws_vhost *vh, + const struct lws_protocols *protocol, + int reason) +LWS_WARN_DEPRECATED; + +/** + * lws_callback_all_protocol_vhost_args() - Callback all connections using + * the given protocol with the given reason and args + * + * \param vh: Vhost whose connections will get callbacks + * \param protocol: Which protocol to match. NULL means all. + * \param reason: Callback reason index + * \param argp: Callback "in" parameter + * \param len: Callback "len" parameter + * + * - Which: connections using this protocol on GIVEN VHOST ONLY + * - When: now + * - What: reason + */ +LWS_VISIBLE int +lws_callback_all_protocol_vhost_args(struct lws_vhost *vh, + const struct lws_protocols *protocol, + int reason, void *argp, size_t len); + +/** + * lws_callback_vhost_protocols() - Callback all protocols enabled on a vhost + * with the given reason + * + * \param wsi: wsi whose vhost will get callbacks + * \param reason: Callback reason index + * \param in: in argument to callback + * \param len: len argument to callback + * + * - Which: connections using this protocol on same VHOST as wsi ONLY + * - When: now + * - What: reason + * + * This is deprecated since v2.5, use lws_callback_vhost_protocols_vhost() + * which takes the pointer to the vhost directly without using or needing the + * wsi. + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, size_t len) +LWS_WARN_DEPRECATED; + +/** + * lws_callback_vhost_protocols_vhost() - Callback all protocols enabled on a vhost + * with the given reason + * + * \param vh: vhost that will get callbacks + * \param reason: Callback reason index + * \param in: in argument to callback + * \param len: len argument to callback + * + * - Which: connections using this protocol on same VHOST as wsi ONLY + * - When: now + * - What: reason + */ +LWS_VISIBLE LWS_EXTERN int +lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in, + size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len); + +/** + * lws_get_socket_fd() - returns the socket file descriptor + * + * This is needed to use sendto() on UDP raw sockets + * + * \param wsi: Websocket connection instance + */ +LWS_VISIBLE LWS_EXTERN lws_sockfd_type +lws_get_socket_fd(struct lws *wsi); + +/** + * lws_get_peer_write_allowance() - get the amount of data writeable to peer + * if known + * + * \param wsi: Websocket connection instance + * + * if the protocol does not have any guidance, returns -1. Currently only + * http2 connections get send window information from this API. But your code + * should use it so it can work properly with any protocol. + * + * If nonzero return is the amount of payload data the peer or intermediary has + * reported it has buffer space for. That has NO relationship with the amount + * of buffer space your OS can accept on this connection for a write action. + * + * This number represents the maximum you could send to the peer or intermediary + * on this connection right now without the protocol complaining. + * + * lws manages accounting for send window updates and payload writes + * automatically, so this number reflects the situation at the peer or + * intermediary dynamically. + */ +LWS_VISIBLE LWS_EXTERN lws_fileofs_t +lws_get_peer_write_allowance(struct lws *wsi); + +/** + * lws_wsi_tx_credit() - get / set generic tx credit if role supports it + * + * \param wsi: connection to set / get tx credit on + * \param peer_to_us: 0 = set / get us-to-peer direction, else peer-to-us + * \param add: amount of credit to add + * + * If the wsi does not support tx credit, returns 0. + * + * If add is zero, returns one of the wsi tx credit values for the wsi. + * If add is nonzero, \p add is added to the selected tx credit value + * for the wsi. + */ +#define LWSTXCR_US_TO_PEER 0 +#define LWSTXCR_PEER_TO_US 1 + +LWS_VISIBLE LWS_EXTERN int +lws_wsi_tx_credit(struct lws *wsi, char peer_to_us, int add); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-ws-close.h b/thirdparty/include/libwebsockets/lws-ws-close.h new file mode 100755 index 0000000000000000000000000000000000000000..0d7b22b44c80688edac15bbec2dedd0885a4fd6b --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ws-close.h @@ -0,0 +1,125 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup wsclose Websocket Close + * + * ##Websocket close frame control + * + * When we close a ws connection, we can send a reason code and a short + * UTF-8 description back with the close packet. + */ +///@{ + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +/** enum lws_close_status - RFC6455 close status codes */ +enum lws_close_status { + LWS_CLOSE_STATUS_NOSTATUS = 0, + LWS_CLOSE_STATUS_NORMAL = 1000, + /**< 1000 indicates a normal closure, meaning that the purpose for + which the connection was established has been fulfilled. */ + LWS_CLOSE_STATUS_GOINGAWAY = 1001, + /**< 1001 indicates that an endpoint is "going away", such as a server + going down or a browser having navigated away from a page. */ + LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002, + /**< 1002 indicates that an endpoint is terminating the connection due + to a protocol error. */ + LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003, + /**< 1003 indicates that an endpoint is terminating the connection + because it has received a type of data it cannot accept (e.g., an + endpoint that understands only text data MAY send this if it + receives a binary message). */ + LWS_CLOSE_STATUS_RESERVED = 1004, + /**< Reserved. The specific meaning might be defined in the future. */ + LWS_CLOSE_STATUS_NO_STATUS = 1005, + /**< 1005 is a reserved value and MUST NOT be set as a status code in a + Close control frame by an endpoint. It is designated for use in + applications expecting a status code to indicate that no status + code was actually present. */ + LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006, + /**< 1006 is a reserved value and MUST NOT be set as a status code in a + Close control frame by an endpoint. It is designated for use in + applications expecting a status code to indicate that the + connection was closed abnormally, e.g., without sending or + receiving a Close control frame. */ + LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007, + /**< 1007 indicates that an endpoint is terminating the connection + because it has received data within a message that was not + consistent with the type of the message (e.g., non-UTF-8 [RFC3629] + data within a text message). */ + LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008, + /**< 1008 indicates that an endpoint is terminating the connection + because it has received a message that violates its policy. This + is a generic status code that can be returned when there is no + other more suitable status code (e.g., 1003 or 1009) or if there + is a need to hide specific details about the policy. */ + LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009, + /**< 1009 indicates that an endpoint is terminating the connection + because it has received a message that is too big for it to + process. */ + LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010, + /**< 1010 indicates that an endpoint (client) is terminating the + connection because it has expected the server to negotiate one or + more extension, but the server didn't return them in the response + message of the WebSocket handshake. The list of extensions that + are needed SHOULD appear in the /reason/ part of the Close frame. + Note that this status code is not used by the server, because it + can fail the WebSocket handshake instead */ + LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011, + /**< 1011 indicates that a server is terminating the connection because + it encountered an unexpected condition that prevented it from + fulfilling the request. */ + LWS_CLOSE_STATUS_TLS_FAILURE = 1015, + /**< 1015 is a reserved value and MUST NOT be set as a status code in a + Close control frame by an endpoint. It is designated for use in + applications expecting a status code to indicate that the + connection was closed due to a failure to perform a TLS handshake + (e.g., the server certificate can't be verified). */ + + LWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE = 2000, + + /****** add new things just above ---^ ******/ + + LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY = 9999, +}; + +/** + * lws_close_reason - Set reason and aux data to send with Close packet + * If you are going to return nonzero from the callback + * requesting the connection to close, you can optionally + * call this to set the reason the peer will be told if + * possible. + * + * \param wsi: The websocket connection to set the close reason on + * \param status: A valid close status from websocket standard + * \param buf: NULL or buffer containing up to 124 bytes of auxiliary data + * \param len: Length of data in \p buf to send + */ +LWS_VISIBLE LWS_EXTERN void +lws_close_reason(struct lws *wsi, enum lws_close_status status, + unsigned char *buf, size_t len); + +///@} diff --git a/thirdparty/include/libwebsockets/lws-ws-ext.h b/thirdparty/include/libwebsockets/lws-ws-ext.h new file mode 100755 index 0000000000000000000000000000000000000000..10c7a644d99a132f4e1ede8310f5eefc721a83fb --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ws-ext.h @@ -0,0 +1,198 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/*! \defgroup extensions Extension related functions + * ##Extension releated functions + * + * Ws defines optional extensions, lws provides the ability to implement these + * in user code if so desired. + * + * We provide one extensions permessage-deflate. + */ +///@{ + +/* + * NOTE: These public enums are part of the abi. If you want to add one, + * add it at where specified so existing users are unaffected. + */ +enum lws_extension_callback_reasons { + LWS_EXT_CB_CONSTRUCT = 4, + LWS_EXT_CB_CLIENT_CONSTRUCT = 5, + LWS_EXT_CB_DESTROY = 8, + LWS_EXT_CB_PACKET_TX_PRESEND = 12, + LWS_EXT_CB_PAYLOAD_TX = 21, + LWS_EXT_CB_PAYLOAD_RX = 22, + LWS_EXT_CB_OPTION_DEFAULT = 23, + LWS_EXT_CB_OPTION_SET = 24, + LWS_EXT_CB_OPTION_CONFIRM = 25, + LWS_EXT_CB_NAMED_OPTION_SET = 26, + + /****** add new things just above ---^ ******/ +}; + +/** enum lws_ext_options_types */ +enum lws_ext_options_types { + EXTARG_NONE, /**< does not take an argument */ + EXTARG_DEC, /**< requires a decimal argument */ + EXTARG_OPT_DEC /**< may have an optional decimal argument */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility */ +}; + +/** struct lws_ext_options - Option arguments to the extension. These are + * used in the negotiation at ws upgrade time. + * The helper function lws_ext_parse_options() + * uses these to generate callbacks */ +struct lws_ext_options { + const char *name; /**< Option name, eg, "server_no_context_takeover" */ + enum lws_ext_options_types type; /**< What kind of args the option can take */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility */ +}; + +/** struct lws_ext_option_arg */ +struct lws_ext_option_arg { + const char *option_name; /**< may be NULL, option_index used then */ + int option_index; /**< argument ordinal to use if option_name missing */ + const char *start; /**< value */ + int len; /**< length of value */ +}; + +/** + * typedef lws_extension_callback_function() - Hooks to allow extensions to operate + * \param context: Websockets context + * \param ext: This extension + * \param wsi: Opaque websocket instance pointer + * \param reason: The reason for the call + * \param user: Pointer to ptr to per-session user data allocated by library + * \param in: Pointer used for some callback reasons + * \param len: Length set for some callback reasons + * + * Each extension that is active on a particular connection receives + * callbacks during the connection lifetime to allow the extension to + * operate on websocket data and manage itself. + * + * Libwebsockets takes care of allocating and freeing "user" memory for + * each active extension on each connection. That is what is pointed to + * by the user parameter. + * + * LWS_EXT_CB_CONSTRUCT: called when the server has decided to + * select this extension from the list provided by the client, + * just before the server will send back the handshake accepting + * the connection with this extension active. This gives the + * extension a chance to initialize its connection context found + * in user. + * + * LWS_EXT_CB_CLIENT_CONSTRUCT: same as LWS_EXT_CB_CONSTRUCT + * but called when client is instantiating this extension. Some + * extensions will work the same on client and server side and then + * you can just merge handlers for both CONSTRUCTS. + * + * LWS_EXT_CB_DESTROY: called when the connection the extension was + * being used on is about to be closed and deallocated. It's the + * last chance for the extension to deallocate anything it has + * allocated in the user data (pointed to by user) before the + * user data is deleted. This same callback is used whether you + * are in client or server instantiation context. + * + * LWS_EXT_CB_PACKET_TX_PRESEND: this works the same way as + * LWS_EXT_CB_PACKET_RX_PREPARSE above, except it gives the + * extension a chance to change websocket data just before it will + * be sent out. Using the same lws_token pointer scheme in in, + * the extension can change the buffer and the length to be + * transmitted how it likes. Again if it wants to grow the + * buffer safely, it should copy the data into its own buffer and + * set the lws_tokens token pointer to it. + * + * LWS_EXT_CB_ARGS_VALIDATE: + */ +typedef int +lws_extension_callback_function(struct lws_context *context, + const struct lws_extension *ext, struct lws *wsi, + enum lws_extension_callback_reasons reason, + void *user, void *in, size_t len); + +/** struct lws_extension - An extension we support */ +struct lws_extension { + const char *name; /**< Formal extension name, eg, "permessage-deflate" */ + lws_extension_callback_function *callback; /**< Service callback */ + const char *client_offer; /**< String containing exts and options client offers */ + + /* Add new things just above here ---^ + * This is part of the ABI, don't needlessly break compatibility */ +}; + +/** + * lws_set_extension_option(): set extension option if possible + * + * \param wsi: websocket connection + * \param ext_name: name of ext, like "permessage-deflate" + * \param opt_name: name of option, like "rx_buf_size" + * \param opt_val: value to set option to + */ +LWS_VISIBLE LWS_EXTERN int +lws_set_extension_option(struct lws *wsi, const char *ext_name, + const char *opt_name, const char *opt_val); + +/** + * lws_ext_parse_options() - deal with parsing negotiated extension options + * + * \param ext: related extension struct + * \param wsi: websocket connection + * \param ext_user: per-connection extension private data + * \param opts: list of supported options + * \param o: option string to parse + * \param len: length + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, + void *ext_user, const struct lws_ext_options *opts, + const char *o, int len); + +/** lws_extension_callback_pm_deflate() - extension for RFC7692 + * + * \param context: lws context + * \param ext: related lws_extension struct + * \param wsi: websocket connection + * \param reason: incoming callback reason + * \param user: per-connection extension private data + * \param in: pointer parameter + * \param len: length parameter + * + * Built-in callback implementing RFC7692 permessage-deflate + */ +LWS_EXTERN int +lws_extension_callback_pm_deflate(struct lws_context *context, + const struct lws_extension *ext, + struct lws *wsi, + enum lws_extension_callback_reasons reason, + void *user, void *in, size_t len); + +/* + * The internal exts are part of the public abi + * If we add more extensions, publish the callback here ------v + */ +///@} diff --git a/thirdparty/include/libwebsockets/lws-ws-state.h b/thirdparty/include/libwebsockets/lws-ws-state.h new file mode 100755 index 0000000000000000000000000000000000000000..d21c2a75bd2bacb1397a4cb3d06efeff401864b1 --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-ws-state.h @@ -0,0 +1,93 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +/** \defgroup wsstatus Websocket status APIs + * ##Websocket connection status APIs + * + * These provide information about ws connection or message status + */ +///@{ +/** + * lws_send_pipe_choked() - tests if socket is writable or not + * \param wsi: lws connection + * + * Allows you to check if you can write more on the socket + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_send_pipe_choked(struct lws *wsi); + +/** + * lws_is_final_fragment() - tests if last part of ws message + * + * \param wsi: lws connection + */ +LWS_VISIBLE LWS_EXTERN int +lws_is_final_fragment(struct lws *wsi); + +/** + * lws_is_first_fragment() - tests if first part of ws message + * + * \param wsi: lws connection + */ +LWS_VISIBLE LWS_EXTERN int +lws_is_first_fragment(struct lws *wsi); + +/** + * lws_get_reserved_bits() - access reserved bits of ws frame + * \param wsi: lws connection + */ +LWS_VISIBLE LWS_EXTERN unsigned char +lws_get_reserved_bits(struct lws *wsi); + +/** + * lws_partial_buffered() - find out if lws buffered the last write + * \param wsi: websocket connection to check + * + * Returns 1 if you cannot use lws_write because the last + * write on this connection is still buffered, and can't be cleared without + * returning to the service loop and waiting for the connection to be + * writeable again. + * + * If you will try to do >1 lws_write call inside a single + * WRITEABLE callback, you must check this after every write and bail if + * set, ask for a new writeable callback and continue writing from there. + * + * This is never set at the start of a writeable callback, but any write + * may set it. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_partial_buffered(struct lws *wsi); + +/** + * lws_frame_is_binary(): true if the current frame was sent in binary mode + * + * \param wsi: the connection we are inquiring about + * + * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if + * it's interested to see if the frame it's dealing with was sent in binary + * mode. + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_frame_is_binary(struct lws *wsi); +///@} diff --git a/thirdparty/include/libwebsockets/lws-x509.h b/thirdparty/include/libwebsockets/lws-x509.h new file mode 100755 index 0000000000000000000000000000000000000000..17a834c190b5072143f742e658d1a7828590a4ba --- /dev/null +++ b/thirdparty/include/libwebsockets/lws-x509.h @@ -0,0 +1,293 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2019 Andy Green + * + * 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. + */ + +enum lws_tls_cert_info { + LWS_TLS_CERT_INFO_VALIDITY_FROM, + /**< fills .time with the time_t the cert validity started from */ + LWS_TLS_CERT_INFO_VALIDITY_TO, + /**< fills .time with the time_t the cert validity ends at */ + LWS_TLS_CERT_INFO_COMMON_NAME, + /**< fills up to len bytes of .ns.name with the cert common name */ + LWS_TLS_CERT_INFO_ISSUER_NAME, + /**< fills up to len bytes of .ns.name with the cert issuer name */ + LWS_TLS_CERT_INFO_USAGE, + /**< fills verified with a bitfield asserting the valid uses */ + LWS_TLS_CERT_INFO_VERIFIED, + /**< fills .verified with a bool representing peer cert validity, + * call returns -1 if no cert */ + LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY, + /**< the certificate's public key, as an opaque bytestream. These + * opaque bytestreams can only be compared with each other using the + * same tls backend, ie, OpenSSL or mbedTLS. The different backends + * produce different, incompatible representations for the same cert. + */ + LWS_TLS_CERT_INFO_DER_RAW, + /**< the certificate's raw DER representation. If it's too big, + * -1 is returned and the size will be returned in buf->ns.len. + * If the certificate cannot be found -1 is returned and 0 in + * buf->ns.len. */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, + /**< If the cert has one, the key ID responsible for the signature */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER, + /**< If the cert has one, the issuer responsible for the signature */ + LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL, + /**< If the cert has one, serial number responsible for the signature */ + LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, + /**< If the cert has one, the cert's subject key ID */ +}; + +union lws_tls_cert_info_results { + unsigned int verified; + time_t time; + unsigned int usage; + struct { + int len; + /* KEEP LAST... notice the [64] is only there because + * name[] is not allowed in a union. The actual length of + * name[] is arbitrary and is passed into the api using the + * len parameter. Eg + * + * char big[1024]; + * union lws_tls_cert_info_results *buf = + * (union lws_tls_cert_info_results *)big; + * + * lws_tls_peer_cert_info(wsi, type, buf, sizeof(big) - + * sizeof(*buf) + sizeof(buf->ns.name)); + */ + char name[64]; + } ns; +}; + +struct lws_x509_cert; +struct lws_jwk; + +/** + * lws_x509_create() - Allocate an lws_x509_cert object + * + * \param x509: pointer to lws_x509_cert pointer to be set to allocated object + * + * Allocates an lws_x509_cert object and set *x509 to point to it. + */ +LWS_VISIBLE LWS_EXTERN int +lws_x509_create(struct lws_x509_cert **x509); + +/** + * lws_x509_parse_from_pem() - Read one or more x509 certs in PEM format from memory + * + * \param x509: pointer to lws_x509_cert object + * \param pem: pointer to PEM format content + * \param len: length of PEM format content + * + * Parses PEM certificates in memory into a native x509 representation for the + * TLS library. If there are multiple PEM certs concatenated, they are all + * read into the same object and exist as a "chain". + * + * IMPORTANT for compatibility with mbedtls, the last used byte of \p pem + * must be '\0' and the \p len must include it. + * + * Returns 0 if all went OK. + */ +LWS_VISIBLE LWS_EXTERN int +lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len); + +/** + * lws_x509_verify() - Validate signing relationship between one or more certs + * and a trusted CA cert + * + * \param x509: pointer to lws_x509_cert object, may contain multiple + * \param trusted: a single, trusted cert object that we are checking for + * \param common_name: NULL, or required CN (Common Name) of \p x509 + * + * Returns 0 if the cert or certs in \p x509 represent a complete chain that is + * ultimately signed by the cert in \p trusted. Returns nonzero if that's not + * the case. + */ +LWS_VISIBLE LWS_EXTERN int +lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted, + const char *common_name); + +/** + * lws_x509_public_to_jwk() - Copy the public key out of a cert and into a JWK + * + * \param jwk: pointer to the jwk to initialize and set to the public key + * \param x509: pointer to lws_x509_cert object that has the public key + * \param curves: NULL to disallow EC, else a comma-separated list of valid + * curves using the JWA naming, eg, "P-256,P-384,P-521". + * \param rsabits: minimum number of RSA bits required in the cert if RSA + * + * Returns 0 if JWK was set to the certificate public key correctly and the + * curve / the RSA key size was acceptable. Automatically produces an RSA or + * EC JWK depending on what the cert had. + */ +LWS_VISIBLE LWS_EXTERN int +lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, + const char *curves, int rsabits); + +/** + * lws_x509_jwk_privkey_pem() - Copy a private key PEM into a jwk that has the + * public part already + * + * \param cx: lws_context (for random) + * \param jwk: pointer to the jwk to initialize and set to the public key + * \param pem: pointer to PEM private key in memory + * \param len: length of PEM private key in memory + * \param passphrase: NULL or passphrase needed to decrypt private key + * + * IMPORTANT for compatibility with mbedtls, the last used byte of \p pem + * must be '\0' and the \p len must include it. + * + * Returns 0 if the private key was successfully added to the JWK, else + * nonzero if failed. + * + * The PEM image in memory is zeroed down on both successful and failed exits. + * The caller should take care to zero down passphrase if used. + */ +LWS_VISIBLE LWS_EXTERN int +lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, + void *pem, size_t len, const char *passphrase); + +/** + * lws_x509_destroy() - Destroy a previously allocated lws_x509_cert object + * + * \param x509: pointer to lws_x509_cert pointer + * + * Deallocates an lws_x509_cert object and sets its pointer to NULL. + */ +LWS_VISIBLE LWS_EXTERN void +lws_x509_destroy(struct lws_x509_cert **x509); + +LWS_VISIBLE LWS_EXTERN int +lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type, + union lws_tls_cert_info_results *buf, size_t len); + +/** + * lws_tls_peer_cert_info() - get information from the peer's TLS cert + * + * \param wsi: the connection to query + * \param type: one of LWS_TLS_CERT_INFO_ + * \param buf: pointer to union to take result + * \param len: when result is a string, the true length of buf->ns.name[] + * + * lws_tls_peer_cert_info() lets you get hold of information from the peer + * certificate. + * + * Return 0 if there is a result in \p buf, or -1 indicating there was no cert + * or another problem. + * + * This function works the same no matter if the TLS backend is OpenSSL or + * mbedTLS. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, + union lws_tls_cert_info_results *buf, size_t len); + +/** + * lws_tls_vhost_cert_info() - get information from the vhost's own TLS cert + * + * \param vhost: the vhost to query + * \param type: one of LWS_TLS_CERT_INFO_ + * \param buf: pointer to union to take result + * \param len: when result is a string, the true length of buf->ns.name[] + * + * lws_tls_vhost_cert_info() lets you get hold of information from the vhost + * certificate. + * + * Return 0 if there is a result in \p buf, or -1 indicating there was no cert + * or another problem. + * + * This function works the same no matter if the TLS backend is OpenSSL or + * mbedTLS. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, + union lws_tls_cert_info_results *buf, size_t len); + +/** + * lws_tls_acme_sni_cert_create() - creates a temp selfsigned cert + * and attaches to a vhost + * + * \param vhost: the vhost to acquire the selfsigned cert + * \param san_a: SAN written into the certificate + * \param san_b: second SAN written into the certificate + * + * + * Returns 0 if created and attached to the vhost. Returns -1 if problems and + * frees all allocations before returning. + * + * On success, any allocations are destroyed at vhost destruction automatically. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, + const char *san_b); + +/** + * lws_tls_acme_sni_csr_create() - creates a CSR and related private key PEM + * + * \param context: lws_context used for random + * \param elements: array of LWS_TLS_REQ_ELEMENT_COUNT const char * + * \param csr: buffer that will get the b64URL(ASN-1 CSR) + * \param csr_len: max length of the csr buffer + * \param privkey_pem: pointer to pointer allocated to hold the privkey_pem + * \param privkey_len: pointer to size_t set to the length of the privkey_pem + * + * Creates a CSR according to the information in \p elements, and a private + * RSA key used to sign the CSR. + * + * The outputs are the b64URL(ASN-1 CSR) into csr, and the PEM private key into + * privkey_pem. + * + * Notice that \p elements points to an array of const char *s pointing to the + * information listed in the enum above. If an entry is NULL or an empty + * string, the element is set to "none" in the CSR. + * + * Returns 0 on success or nonzero for failure. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[], + uint8_t *csr, size_t csr_len, char **privkey_pem, + size_t *privkey_len); + +/** + * lws_tls_cert_updated() - update every vhost using the given cert path + * + * \param context: our lws_context + * \param certpath: the filepath to the certificate + * \param keypath: the filepath to the private key of the certificate + * \param mem_cert: copy of the cert in memory + * \param len_mem_cert: length of the copy of the cert in memory + * \param mem_privkey: copy of the private key in memory + * \param len_mem_privkey: length of the copy of the private key in memory + * + * Checks every vhost to see if it is the using certificate described by the + * the given filepaths. If so, it attempts to update the vhost ssl_ctx to use + * the new certificate. + * + * Returns 0 on success or nonzero for failure. + */ +LWS_VISIBLE LWS_EXTERN int +lws_tls_cert_updated(struct lws_context *context, const char *certpath, + const char *keypath, + const char *mem_cert, size_t len_mem_cert, + const char *mem_privkey, size_t len_mem_privkey); + diff --git a/thirdparty/include/libyuv.h b/thirdparty/include/libyuv.h new file mode 100755 index 0000000000000000000000000000000000000000..aeffd5ef7a4ca249883c0986894ab752ad8fe665 --- /dev/null +++ b/thirdparty/include/libyuv.h @@ -0,0 +1,32 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_H_ +#define INCLUDE_LIBYUV_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/compare.h" +#include "libyuv/convert.h" +#include "libyuv/convert_argb.h" +#include "libyuv/convert_from.h" +#include "libyuv/convert_from_argb.h" +#include "libyuv/cpu_id.h" +#include "libyuv/mjpeg_decoder.h" +#include "libyuv/planar_functions.h" +#include "libyuv/rotate.h" +#include "libyuv/rotate_argb.h" +#include "libyuv/row.h" +#include "libyuv/scale.h" +#include "libyuv/scale_argb.h" +#include "libyuv/scale_row.h" +#include "libyuv/version.h" +#include "libyuv/video_common.h" + +#endif // INCLUDE_LIBYUV_H_ diff --git a/thirdparty/include/libyuv/basic_types.h b/thirdparty/include/libyuv/basic_types.h new file mode 100755 index 0000000000000000000000000000000000000000..1bea67f2f2547081684704fc61a0acfdcd5e5de2 --- /dev/null +++ b/thirdparty/include/libyuv/basic_types.h @@ -0,0 +1,68 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_ +#define INCLUDE_LIBYUV_BASIC_TYPES_H_ + +#include // For size_t and NULL + +#if !defined(INT_TYPES_DEFINED) && !defined(GG_LONGLONG) +#define INT_TYPES_DEFINED + +#if defined(_MSC_VER) && (_MSC_VER < 1600) +#include // for uintptr_t on x86 +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; +#else +#include // for uintptr_t and C99 types +#endif // defined(_MSC_VER) && (_MSC_VER < 1600) +// Types are deprecated. Enable this macro for legacy types. +#ifdef LIBYUV_LEGACY_TYPES +typedef uint64_t uint64; +typedef int64_t int64; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint8_t uint8; +typedef int8_t int8; +#endif // LIBYUV_LEGACY_TYPES +#endif // INT_TYPES_DEFINED + +#if !defined(LIBYUV_API) +#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(LIBYUV_BUILDING_SHARED_LIBRARY) +#define LIBYUV_API __declspec(dllexport) +#elif defined(LIBYUV_USING_SHARED_LIBRARY) +#define LIBYUV_API __declspec(dllimport) +#else +#define LIBYUV_API +#endif // LIBYUV_BUILDING_SHARED_LIBRARY +#elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \ + (defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \ + defined(LIBYUV_USING_SHARED_LIBRARY)) +#define LIBYUV_API __attribute__((visibility("default"))) +#else +#define LIBYUV_API +#endif // __GNUC__ +#endif // LIBYUV_API + +// TODO(fbarchard): Remove bool macros. +#define LIBYUV_BOOL int +#define LIBYUV_FALSE 0 +#define LIBYUV_TRUE 1 + +#endif // INCLUDE_LIBYUV_BASIC_TYPES_H_ diff --git a/thirdparty/include/libyuv/compare.h b/thirdparty/include/libyuv/compare.h new file mode 100755 index 0000000000000000000000000000000000000000..3353ad71c68a805146cf4ca6edfe39ed2636271d --- /dev/null +++ b/thirdparty/include/libyuv/compare.h @@ -0,0 +1,111 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_COMPARE_H_ +#define INCLUDE_LIBYUV_COMPARE_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Compute a hash for specified memory. Seed of 5381 recommended. +LIBYUV_API +uint32_t HashDjb2(const uint8_t* src, uint64_t count, uint32_t seed); + +// Hamming Distance +LIBYUV_API +uint64_t ComputeHammingDistance(const uint8_t* src_a, + const uint8_t* src_b, + int count); + +// Scan an opaque argb image and return fourcc based on alpha offset. +// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. +LIBYUV_API +uint32_t ARGBDetect(const uint8_t* argb, + int stride_argb, + int width, + int height); + +// Sum Square Error - used to compute Mean Square Error or PSNR. +LIBYUV_API +uint64_t ComputeSumSquareError(const uint8_t* src_a, + const uint8_t* src_b, + int count); + +LIBYUV_API +uint64_t ComputeSumSquareErrorPlane(const uint8_t* src_a, + int stride_a, + const uint8_t* src_b, + int stride_b, + int width, + int height); + +static const int kMaxPsnr = 128; + +LIBYUV_API +double SumSquareErrorToPsnr(uint64_t sse, uint64_t count); + +LIBYUV_API +double CalcFramePsnr(const uint8_t* src_a, + int stride_a, + const uint8_t* src_b, + int stride_b, + int width, + int height); + +LIBYUV_API +double I420Psnr(const uint8_t* src_y_a, + int stride_y_a, + const uint8_t* src_u_a, + int stride_u_a, + const uint8_t* src_v_a, + int stride_v_a, + const uint8_t* src_y_b, + int stride_y_b, + const uint8_t* src_u_b, + int stride_u_b, + const uint8_t* src_v_b, + int stride_v_b, + int width, + int height); + +LIBYUV_API +double CalcFrameSsim(const uint8_t* src_a, + int stride_a, + const uint8_t* src_b, + int stride_b, + int width, + int height); + +LIBYUV_API +double I420Ssim(const uint8_t* src_y_a, + int stride_y_a, + const uint8_t* src_u_a, + int stride_u_a, + const uint8_t* src_v_a, + int stride_v_a, + const uint8_t* src_y_b, + int stride_y_b, + const uint8_t* src_u_b, + int stride_u_b, + const uint8_t* src_v_b, + int stride_v_b, + int width, + int height); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_COMPARE_H_ diff --git a/thirdparty/include/libyuv/compare_row.h b/thirdparty/include/libyuv/compare_row.h new file mode 100755 index 0000000000000000000000000000000000000000..e95b9d93eb2c64a69712abe83a32ff4f9997351c --- /dev/null +++ b/thirdparty/include/libyuv/compare_row.h @@ -0,0 +1,141 @@ +/* + * Copyright 2013 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_COMPARE_ROW_H_ +#define INCLUDE_LIBYUV_COMPARE_ROW_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__native_client__) && defined(__x86_64__)) || \ + (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) +#define LIBYUV_DISABLE_X86 +#endif +#if defined(__native_client__) +#define LIBYUV_DISABLE_NEON +#endif +// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define LIBYUV_DISABLE_X86 +#endif +#endif +// Visual C 2012 required for AVX2. +#if defined(_M_IX86) && !defined(__clang__) && defined(_MSC_VER) && \ + _MSC_VER >= 1700 +#define VISUALC_HAS_AVX2 1 +#endif // VisualStudio >= 2012 + +// clang >= 3.4.0 required for AVX2. +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) +#define CLANG_HAS_AVX2 1 +#endif // clang >= 3.4 +#endif // __clang__ + +// The following are available for Visual C and GCC: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || defined(__i386__) || defined(_M_IX86)) +#define HAS_HASHDJB2_SSE41 +#define HAS_SUMSQUAREERROR_SSE2 +#define HAS_HAMMINGDISTANCE_SSE42 +#endif + +// The following are available for Visual C and clangcl 32 bit: +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) && \ + (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) +#define HAS_HASHDJB2_AVX2 +#define HAS_SUMSQUAREERROR_AVX2 +#endif + +// The following are available for GCC and clangcl 64 bit: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) +#define HAS_HAMMINGDISTANCE_SSSE3 +#endif + +// The following are available for GCC and clangcl 64 bit: +#if !defined(LIBYUV_DISABLE_X86) && defined(CLANG_HAS_AVX2) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) +#define HAS_HAMMINGDISTANCE_AVX2 +#endif + +// The following are available for Neon: +#if !defined(LIBYUV_DISABLE_NEON) && \ + (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) +#define HAS_SUMSQUAREERROR_NEON +#define HAS_HAMMINGDISTANCE_NEON +#endif + +#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) +#define HAS_HAMMINGDISTANCE_MSA +#define HAS_SUMSQUAREERROR_MSA +#endif + +#if !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A) +#define HAS_HAMMINGDISTANCE_MMI +#define HAS_SUMSQUAREERROR_MMI +#endif + +uint32_t HammingDistance_C(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_SSE42(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_SSSE3(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_AVX2(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_NEON(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_MSA(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t HammingDistance_MMI(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_C(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_SSE2(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_AVX2(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_NEON(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_MSA(const uint8_t* src_a, + const uint8_t* src_b, + int count); +uint32_t SumSquareError_MMI(const uint8_t* src_a, + const uint8_t* src_b, + int count); + +uint32_t HashDjb2_C(const uint8_t* src, int count, uint32_t seed); +uint32_t HashDjb2_SSE41(const uint8_t* src, int count, uint32_t seed); +uint32_t HashDjb2_AVX2(const uint8_t* src, int count, uint32_t seed); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_COMPARE_ROW_H_ diff --git a/thirdparty/include/libyuv/convert.h b/thirdparty/include/libyuv/convert.h new file mode 100755 index 0000000000000000000000000000000000000000..91d81ac0533ac6b6595e69a8f6b86929dadd5d51 --- /dev/null +++ b/thirdparty/include/libyuv/convert.h @@ -0,0 +1,513 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_CONVERT_H_ +#define INCLUDE_LIBYUV_CONVERT_H_ + +#include "libyuv/basic_types.h" + +#include "libyuv/rotate.h" // For enum RotationMode. + +// TODO(fbarchard): fix WebRTC source to include following libyuv headers: +#include "libyuv/convert_argb.h" // For WebRTC I420ToARGB. b/620 +#include "libyuv/convert_from.h" // For WebRTC ConvertFromI420. b/620 +#include "libyuv/planar_functions.h" // For WebRTC I420Rect, CopyPlane. b/618 + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Convert I444 to I420. +LIBYUV_API +int I444ToI420(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert I444 to NV12. +LIBYUV_API +int I444ToNV12(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Convert I444 to NV21. +LIBYUV_API +int I444ToNV21(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Convert I422 to I420. +LIBYUV_API +int I422ToI420(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert I422 to NV21. +LIBYUV_API +int I422ToNV21(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Copy I420 to I420. +#define I420ToI420 I420Copy +LIBYUV_API +int I420Copy(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Copy I010 to I010 +#define I010ToI010 I010Copy +#define H010ToH010 I010Copy +LIBYUV_API +int I010Copy(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert 10 bit YUV to 8 bit +#define H010ToH420 I010ToI420 +LIBYUV_API +int I010ToI420(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert I400 (grey) to I420. +LIBYUV_API +int I400ToI420(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert I400 (grey) to NV21. +LIBYUV_API +int I400ToNV21(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +#define J400ToJ420 I400ToI420 + +// Convert NV12 to I420. +LIBYUV_API +int NV12ToI420(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert NV21 to I420. +LIBYUV_API +int NV21ToI420(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert YUY2 to I420. +LIBYUV_API +int YUY2ToI420(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert UYVY to I420. +LIBYUV_API +int UYVYToI420(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert AYUV to NV12. +LIBYUV_API +int AYUVToNV12(const uint8_t* src_ayuv, + int src_stride_ayuv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Convert AYUV to NV21. +LIBYUV_API +int AYUVToNV21(const uint8_t* src_ayuv, + int src_stride_ayuv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Convert Android420 to I420. +LIBYUV_API +int Android420ToI420(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_pixel_stride_uv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// ARGB little endian (bgra in memory) to I420. +LIBYUV_API +int ARGBToI420(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// BGRA little endian (argb in memory) to I420. +LIBYUV_API +int BGRAToI420(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// ABGR little endian (rgba in memory) to I420. +LIBYUV_API +int ABGRToI420(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGBA little endian (abgr in memory) to I420. +LIBYUV_API +int RGBAToI420(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB little endian (bgr in memory) to I420. +LIBYUV_API +int RGB24ToI420(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB little endian (bgr in memory) to J420. +LIBYUV_API +int RGB24ToJ420(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB big endian (rgb in memory) to I420. +LIBYUV_API +int RAWToI420(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB16 (RGBP fourcc) little endian to I420. +LIBYUV_API +int RGB565ToI420(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB15 (RGBO fourcc) little endian to I420. +LIBYUV_API +int ARGB1555ToI420(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB12 (R444 fourcc) little endian to I420. +LIBYUV_API +int ARGB4444ToI420(const uint8_t* src_argb4444, + int src_stride_argb4444, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// RGB little endian (bgr in memory) to J400. +LIBYUV_API +int RGB24ToJ400(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_yj, + int dst_stride_yj, + int width, + int height); + +// RGB big endian (rgb in memory) to J400. +LIBYUV_API +int RAWToJ400(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_yj, + int dst_stride_yj, + int width, + int height); + +// src_width/height provided by capture. +// dst_width/height for clipping determine final size. +LIBYUV_API +int MJPGToI420(const uint8_t* sample, + size_t sample_size, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int src_width, + int src_height, + int dst_width, + int dst_height); + +// JPEG to NV21 +LIBYUV_API +int MJPGToNV21(const uint8_t* sample, + size_t sample_size, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int src_width, + int src_height, + int dst_width, + int dst_height); + +// Query size of MJPG in pixels. +LIBYUV_API +int MJPGSize(const uint8_t* sample, + size_t sample_size, + int* width, + int* height); + +// Convert camera sample to I420 with cropping, rotation and vertical flip. +// "src_size" is needed to parse MJPG. +// "dst_stride_y" number of bytes in a row of the dst_y plane. +// Normally this would be the same as dst_width, with recommended alignment +// to 16 bytes for better efficiency. +// If rotation of 90 or 270 is used, stride is affected. The caller should +// allocate the I420 buffer according to rotation. +// "dst_stride_u" number of bytes in a row of the dst_u plane. +// Normally this would be the same as (dst_width + 1) / 2, with +// recommended alignment to 16 bytes for better efficiency. +// If rotation of 90 or 270 is used, stride is affected. +// "crop_x" and "crop_y" are starting position for cropping. +// To center, crop_x = (src_width - dst_width) / 2 +// crop_y = (src_height - dst_height) / 2 +// "src_width" / "src_height" is size of src_frame in pixels. +// "src_height" can be negative indicating a vertically flipped image source. +// "crop_width" / "crop_height" is the size to crop the src to. +// Must be less than or equal to src_width/src_height +// Cropping parameters are pre-rotation. +// "rotation" can be 0, 90, 180 or 270. +// "fourcc" is a fourcc. ie 'I420', 'YUY2' +// Returns 0 for successful; -1 for invalid parameter. Non-zero for failure. +LIBYUV_API +int ConvertToI420(const uint8_t* sample, + size_t sample_size, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int crop_x, + int crop_y, + int src_width, + int src_height, + int crop_width, + int crop_height, + enum RotationMode rotation, + uint32_t fourcc); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_CONVERT_H_ diff --git a/thirdparty/include/libyuv/convert_argb.h b/thirdparty/include/libyuv/convert_argb.h new file mode 100755 index 0000000000000000000000000000000000000000..715a3dad97d93548370b466fbdaaea0541825b45 --- /dev/null +++ b/thirdparty/include/libyuv/convert_argb.h @@ -0,0 +1,1611 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_CONVERT_ARGB_H_ +#define INCLUDE_LIBYUV_CONVERT_ARGB_H_ + +#include "libyuv/basic_types.h" + +#include "libyuv/rotate.h" // For enum RotationMode. + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Conversion matrix for YUV to RGB +LIBYUV_API extern const struct YuvConstants kYuvI601Constants; // BT.601 +LIBYUV_API extern const struct YuvConstants kYuvJPEGConstants; // JPeg +LIBYUV_API extern const struct YuvConstants kYuvH709Constants; // BT.709 +LIBYUV_API extern const struct YuvConstants kYuv2020Constants; // BT.2020 + +// Conversion matrix for YVU to BGR +LIBYUV_API extern const struct YuvConstants kYvuI601Constants; // BT.601 +LIBYUV_API extern const struct YuvConstants kYvuJPEGConstants; // JPeg +LIBYUV_API extern const struct YuvConstants kYvuH709Constants; // BT.709 +LIBYUV_API extern const struct YuvConstants kYvu2020Constants; // BT.2020 + +// Macros for end swapped destination Matrix conversions. +// Swap UV and pass mirrored kYvuJPEGConstants matrix. +// TODO(fbarchard): Add macro for each Matrix function. +#define kYuvI601ConstantsVU kYvuI601Constants +#define kYuvJPEGConstantsVU kYvuJPEGConstants +#define kYuvH709ConstantsVU kYvuH709Constants +#define kYuv2020ConstantsVU kYvu2020Constants +#define NV12ToABGRMatrix(a, b, c, d, e, f, g, h, i) \ + NV21ToARGBMatrix(a, b, c, d, e, f, g##VU, h, i) +#define NV21ToABGRMatrix(a, b, c, d, e, f, g, h, i) \ + NV12ToARGBMatrix(a, b, c, d, e, f, g##VU, h, i) +#define NV12ToRAWMatrix(a, b, c, d, e, f, g, h, i) \ + NV21ToRGB24Matrix(a, b, c, d, e, f, g##VU, h, i) +#define NV21ToRAWMatrix(a, b, c, d, e, f, g, h, i) \ + NV12ToRGB24Matrix(a, b, c, d, e, f, g##VU, h, i) +#define I420AlphaToABGRMatrix(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \ + I420AlphaToARGBMatrix(a, b, e, f, c, d, g, h, i, j, k##VU, l, m, n) + +// Alias. +#define ARGBToARGB ARGBCopy + +// Copy ARGB to ARGB. +LIBYUV_API +int ARGBCopy(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I420 to ARGB. +LIBYUV_API +int I420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I420 to ABGR. +LIBYUV_API +int I420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert J420 to ARGB. +LIBYUV_API +int J420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert J420 to ABGR. +LIBYUV_API +int J420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert H420 to ARGB. +LIBYUV_API +int H420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert H420 to ABGR. +LIBYUV_API +int H420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert U420 to ARGB. +LIBYUV_API +int U420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert U420 to ABGR. +LIBYUV_API +int U420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I422 to ARGB. +LIBYUV_API +int I422ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I422 to ABGR. +LIBYUV_API +int I422ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert J422 to ARGB. +LIBYUV_API +int J422ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert J422 to ABGR. +LIBYUV_API +int J422ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert H422 to ARGB. +LIBYUV_API +int H422ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert H422 to ABGR. +LIBYUV_API +int H422ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert U422 to ARGB. +LIBYUV_API +int U422ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert U422 to ABGR. +LIBYUV_API +int U422ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I444 to ARGB. +LIBYUV_API +int I444ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I444 to ABGR. +LIBYUV_API +int I444ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert J444 to ARGB. +LIBYUV_API +int J444ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert J444 to ABGR. +LIBYUV_API +int J444ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert H444 to ARGB. +LIBYUV_API +int H444ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert H444 to ABGR. +LIBYUV_API +int H444ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert U444 to ARGB. +LIBYUV_API +int U444ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert U444 to ABGR. +LIBYUV_API +int U444ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I010 to ARGB. +LIBYUV_API +int I010ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I010 to ABGR. +LIBYUV_API +int I010ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert H010 to ARGB. +LIBYUV_API +int H010ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert H010 to ABGR. +LIBYUV_API +int H010ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert U010 to ARGB. +LIBYUV_API +int U010ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert U010 to ABGR. +LIBYUV_API +int U010ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I210 to ARGB. +LIBYUV_API +int I210ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I210 to ABGR. +LIBYUV_API +int I210ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert H210 to ARGB. +LIBYUV_API +int H210ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert H210 to ABGR. +LIBYUV_API +int H210ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert U210 to ARGB. +LIBYUV_API +int U210ToARGB(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert U210 to ABGR. +LIBYUV_API +int U210ToABGR(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I420 with Alpha to preattenuated ARGB. +LIBYUV_API +int I420AlphaToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + const uint8_t* src_a, + int src_stride_a, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height, + int attenuate); + +// Convert I420 with Alpha to preattenuated ABGR. +LIBYUV_API +int I420AlphaToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + const uint8_t* src_a, + int src_stride_a, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height, + int attenuate); + +// Convert I400 (grey) to ARGB. Reverse of ARGBToI400. +LIBYUV_API +int I400ToARGB(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert J400 (jpeg grey) to ARGB. +LIBYUV_API +int J400ToARGB(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Alias. +#define YToARGB I400ToARGB + +// Convert NV12 to ARGB. +LIBYUV_API +int NV12ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert NV21 to ARGB. +LIBYUV_API +int NV21ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert NV12 to ABGR. +LIBYUV_API +int NV12ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert NV21 to ABGR. +LIBYUV_API +int NV21ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert NV12 to RGB24. +LIBYUV_API +int NV12ToRGB24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +// Convert NV21 to RGB24. +LIBYUV_API +int NV21ToRGB24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +// Convert NV21 to YUV24. +LIBYUV_API +int NV21ToYUV24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_yuv24, + int dst_stride_yuv24, + int width, + int height); + +// Convert NV12 to RAW. +LIBYUV_API +int NV12ToRAW(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +// Convert NV21 to RAW. +LIBYUV_API +int NV21ToRAW(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +// Convert YUY2 to ARGB. +LIBYUV_API +int YUY2ToARGB(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert UYVY to ARGB. +LIBYUV_API +int UYVYToARGB(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I010 to AR30. +LIBYUV_API +int I010ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert I010 to AB30. +LIBYUV_API +int I010ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// Convert H010 to AR30. +LIBYUV_API +int H010ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert H010 to AB30. +LIBYUV_API +int H010ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// Convert U010 to AR30. +LIBYUV_API +int U010ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert U010 to AB30. +LIBYUV_API +int U010ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// Convert I210 to AR30. +LIBYUV_API +int I210ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert I210 to AB30. +LIBYUV_API +int I210ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// Convert H210 to AR30. +LIBYUV_API +int H210ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert H210 to AB30. +LIBYUV_API +int H210ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// Convert U210 to AR30. +LIBYUV_API +int U210ToAR30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert U210 to AB30. +LIBYUV_API +int U210ToAB30(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// BGRA little endian (argb in memory) to ARGB. +LIBYUV_API +int BGRAToARGB(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// ABGR little endian (rgba in memory) to ARGB. +LIBYUV_API +int ABGRToARGB(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// RGBA little endian (abgr in memory) to ARGB. +LIBYUV_API +int RGBAToARGB(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Deprecated function name. +#define BG24ToARGB RGB24ToARGB + +// RGB little endian (bgr in memory) to ARGB. +LIBYUV_API +int RGB24ToARGB(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// RGB big endian (rgb in memory) to ARGB. +LIBYUV_API +int RAWToARGB(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// RGB big endian (rgb in memory) to RGBA. +LIBYUV_API +int RAWToRGBA(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_rgba, + int dst_stride_rgba, + int width, + int height); + +// RGB16 (RGBP fourcc) little endian to ARGB. +LIBYUV_API +int RGB565ToARGB(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// RGB15 (RGBO fourcc) little endian to ARGB. +LIBYUV_API +int ARGB1555ToARGB(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// RGB12 (R444 fourcc) little endian to ARGB. +LIBYUV_API +int ARGB4444ToARGB(const uint8_t* src_argb4444, + int src_stride_argb4444, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Aliases +#define AB30ToARGB AR30ToABGR +#define AB30ToABGR AR30ToARGB +#define AB30ToAR30 AR30ToAB30 + +// Convert AR30 To ARGB. +LIBYUV_API +int AR30ToARGB(const uint8_t* src_ar30, + int src_stride_ar30, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert AR30 To ABGR. +LIBYUV_API +int AR30ToABGR(const uint8_t* src_ar30, + int src_stride_ar30, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert AR30 To AB30. +LIBYUV_API +int AR30ToAB30(const uint8_t* src_ar30, + int src_stride_ar30, + uint8_t* dst_ab30, + int dst_stride_ab30, + int width, + int height); + +// src_width/height provided by capture +// dst_width/height for clipping determine final size. +LIBYUV_API +int MJPGToARGB(const uint8_t* sample, + size_t sample_size, + uint8_t* dst_argb, + int dst_stride_argb, + int src_width, + int src_height, + int dst_width, + int dst_height); + +// Convert Android420 to ARGB. +LIBYUV_API +int Android420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_pixel_stride_uv, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert Android420 to ABGR. +LIBYUV_API +int Android420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_pixel_stride_uv, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert NV12 to RGB565. +LIBYUV_API +int NV12ToRGB565(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +// Convert I422 to BGRA. +LIBYUV_API +int I422ToBGRA(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_bgra, + int dst_stride_bgra, + int width, + int height); + +// Convert I422 to ABGR. +LIBYUV_API +int I422ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I422 to RGBA. +LIBYUV_API +int I422ToRGBA(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgba, + int dst_stride_rgba, + int width, + int height); + +LIBYUV_API +int I420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +LIBYUV_API +int I420ToBGRA(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_bgra, + int dst_stride_bgra, + int width, + int height); + +LIBYUV_API +int I420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +LIBYUV_API +int I420ToRGBA(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgba, + int dst_stride_rgba, + int width, + int height); + +LIBYUV_API +int I420ToRGB24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +LIBYUV_API +int I420ToRAW(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +LIBYUV_API +int H420ToRGB24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +LIBYUV_API +int H420ToRAW(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +LIBYUV_API +int J420ToRGB24(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +LIBYUV_API +int J420ToRAW(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +LIBYUV_API +int I420ToRGB565(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +LIBYUV_API +int J420ToRGB565(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +LIBYUV_API +int H420ToRGB565(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +LIBYUV_API +int I422ToRGB565(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +// Convert I420 To RGB565 with 4x4 dither matrix (16 bytes). +// Values in dither matrix from 0 to 7 recommended. +// The order of the dither matrix is first byte is upper left. + +LIBYUV_API +int I420ToRGB565Dither(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + const uint8_t* dither4x4, + int width, + int height); + +LIBYUV_API +int I420ToARGB1555(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb1555, + int dst_stride_argb1555, + int width, + int height); + +LIBYUV_API +int I420ToARGB4444(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb4444, + int dst_stride_argb4444, + int width, + int height); + +// Convert I420 to AR30. +LIBYUV_API +int I420ToAR30(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert H420 to AR30. +LIBYUV_API +int H420ToAR30(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert I420 to ARGB with matrix. +LIBYUV_API +int I420ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I422 to ARGB with matrix. +LIBYUV_API +int I422ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I444 to ARGB with matrix. +LIBYUV_API +int I444ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// multiply 10 bit yuv into high bits to allow any number of bits. +LIBYUV_API +int I010ToAR30Matrix(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// multiply 10 bit yuv into high bits to allow any number of bits. +LIBYUV_API +int I210ToAR30Matrix(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert 10 bit YUV to ARGB with matrix. +LIBYUV_API +int I010ToARGBMatrix(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert 10 bit 422 YUV to ARGB with matrix. +LIBYUV_API +int I210ToARGBMatrix(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I420 with Alpha to preattenuated ARGB with matrix. +LIBYUV_API +int I420AlphaToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + const uint8_t* src_a, + int src_stride_a, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height, + int attenuate); + +// Convert NV12 to ARGB with matrix. +LIBYUV_API +int NV12ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert NV21 to ARGB with matrix. +LIBYUV_API +int NV21ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert NV12 to RGB565 with matrix. +LIBYUV_API +int NV12ToRGB565Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert NV12 to RGB24 with matrix. +LIBYUV_API +int NV12ToRGB24Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert NV21 to RGB24 with matrix. +LIBYUV_API +int NV21ToRGB24Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert Android420 to ARGB with matrix. +LIBYUV_API +int Android420ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_pixel_stride_uv, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I422 to RGBA with matrix. +LIBYUV_API +int I422ToRGBAMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgba, + int dst_stride_rgba, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I422 to RGBA with matrix. +LIBYUV_API +int I420ToRGBAMatrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgba, + int dst_stride_rgba, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I420 to RGB24 with matrix. +LIBYUV_API +int I420ToRGB24Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I420 to RGB565 with specified color matrix. +LIBYUV_API +int I420ToRGB565Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I420 to AR30 with matrix. +LIBYUV_API +int I420ToAR30Matrix(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_ar30, + int dst_stride_ar30, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert I400 (grey) to ARGB. Reverse of ARGBToI400. +LIBYUV_API +int I400ToARGBMatrix(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_argb, + int dst_stride_argb, + const struct YuvConstants* yuvconstants, + int width, + int height); + +// Convert camera sample to ARGB with cropping, rotation and vertical flip. +// "sample_size" is needed to parse MJPG. +// "dst_stride_argb" number of bytes in a row of the dst_argb plane. +// Normally this would be the same as dst_width, with recommended alignment +// to 16 bytes for better efficiency. +// If rotation of 90 or 270 is used, stride is affected. The caller should +// allocate the I420 buffer according to rotation. +// "dst_stride_u" number of bytes in a row of the dst_u plane. +// Normally this would be the same as (dst_width + 1) / 2, with +// recommended alignment to 16 bytes for better efficiency. +// If rotation of 90 or 270 is used, stride is affected. +// "crop_x" and "crop_y" are starting position for cropping. +// To center, crop_x = (src_width - dst_width) / 2 +// crop_y = (src_height - dst_height) / 2 +// "src_width" / "src_height" is size of src_frame in pixels. +// "src_height" can be negative indicating a vertically flipped image source. +// "crop_width" / "crop_height" is the size to crop the src to. +// Must be less than or equal to src_width/src_height +// Cropping parameters are pre-rotation. +// "rotation" can be 0, 90, 180 or 270. +// "fourcc" is a fourcc. ie 'I420', 'YUY2' +// Returns 0 for successful; -1 for invalid parameter. Non-zero for failure. +LIBYUV_API +int ConvertToARGB(const uint8_t* sample, + size_t sample_size, + uint8_t* dst_argb, + int dst_stride_argb, + int crop_x, + int crop_y, + int src_width, + int src_height, + int crop_width, + int crop_height, + enum RotationMode rotation, + uint32_t fourcc); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_CONVERT_ARGB_H_ diff --git a/thirdparty/include/libyuv/convert_from.h b/thirdparty/include/libyuv/convert_from.h new file mode 100755 index 0000000000000000000000000000000000000000..5140ed4f3e91fe98b16ac496a9b557908ccc6413 --- /dev/null +++ b/thirdparty/include/libyuv/convert_from.h @@ -0,0 +1,185 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_CONVERT_FROM_H_ +#define INCLUDE_LIBYUV_CONVERT_FROM_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/rotate.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// See Also convert.h for conversions from formats to I420. + +// Convert 8 bit YUV to 10 bit. +#define H420ToH010 I420ToI010 +LIBYUV_API +int I420ToI010(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int width, + int height); + +LIBYUV_API +int I420ToI422(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +LIBYUV_API +int I420ToI444(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Copy to I400. Source can be I420, I422, I444, I400, NV12 or NV21. +LIBYUV_API +int I400Copy(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +LIBYUV_API +int I420ToNV12(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +LIBYUV_API +int I420ToNV21(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +LIBYUV_API +int I420ToYUY2(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_yuy2, + int dst_stride_yuy2, + int width, + int height); + +LIBYUV_API +int I420ToUYVY(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uyvy, + int dst_stride_uyvy, + int width, + int height); + +// The following are from convert_argb.h +// DEPRECATED: The prototypes will be removed in future. Use convert_argb.h + +// Convert I420 to ARGB. +LIBYUV_API +int I420ToARGB(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I420 to ABGR. +LIBYUV_API +int I420ToABGR(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert I420 to specified format. +// "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the +// buffer has contiguous rows. Can be negative. A multiple of 16 is optimal. +LIBYUV_API +int ConvertFromI420(const uint8_t* y, + int y_stride, + const uint8_t* u, + int u_stride, + const uint8_t* v, + int v_stride, + uint8_t* dst_sample, + int dst_sample_stride, + int width, + int height, + uint32_t fourcc); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_CONVERT_FROM_H_ diff --git a/thirdparty/include/libyuv/convert_from_argb.h b/thirdparty/include/libyuv/convert_from_argb.h new file mode 100755 index 0000000000000000000000000000000000000000..96e1557ca9ba88ebcc60099539c24f93b0db86e9 --- /dev/null +++ b/thirdparty/include/libyuv/convert_from_argb.h @@ -0,0 +1,311 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ +#define INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Copy ARGB to ARGB. +#define ARGBToARGB ARGBCopy +LIBYUV_API +int ARGBCopy(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert ARGB To BGRA. +LIBYUV_API +int ARGBToBGRA(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_bgra, + int dst_stride_bgra, + int width, + int height); + +// Convert ARGB To ABGR. +LIBYUV_API +int ARGBToABGR(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_abgr, + int dst_stride_abgr, + int width, + int height); + +// Convert ARGB To RGBA. +LIBYUV_API +int ARGBToRGBA(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_rgba, + int dst_stride_rgba, + int width, + int height); + +// Aliases +#define ARGBToAB30 ABGRToAR30 +#define ABGRToAB30 ARGBToAR30 + +// Convert ABGR To AR30. +LIBYUV_API +int ABGRToAR30(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Convert ARGB To AR30. +LIBYUV_API +int ARGBToAR30(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_ar30, + int dst_stride_ar30, + int width, + int height); + +// Aliases +#define ABGRToRGB24 ARGBToRAW +#define ABGRToRAW ARGBToRGB24 + +// Convert ARGB To RGB24. +LIBYUV_API +int ARGBToRGB24(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +// Convert ARGB To RAW. +LIBYUV_API +int ARGBToRAW(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_raw, + int dst_stride_raw, + int width, + int height); + +// Convert ARGB To RGB565. +LIBYUV_API +int ARGBToRGB565(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + int width, + int height); + +// Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). +// Values in dither matrix from 0 to 7 recommended. +// The order of the dither matrix is first byte is upper left. +// TODO(fbarchard): Consider pointer to 2d array for dither4x4. +// const uint8_t(*dither)[4][4]; +LIBYUV_API +int ARGBToRGB565Dither(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_rgb565, + int dst_stride_rgb565, + const uint8_t* dither4x4, + int width, + int height); + +// Convert ARGB To ARGB1555. +LIBYUV_API +int ARGBToARGB1555(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb1555, + int dst_stride_argb1555, + int width, + int height); + +// Convert ARGB To ARGB4444. +LIBYUV_API +int ARGBToARGB4444(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb4444, + int dst_stride_argb4444, + int width, + int height); + +// Convert ARGB To I444. +LIBYUV_API +int ARGBToI444(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert ARGB To I422. +LIBYUV_API +int ARGBToI422(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert ARGB To I420. (also in convert.h) +LIBYUV_API +int ARGBToI420(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert ARGB to J420. (JPeg full range I420). +LIBYUV_API +int ARGBToJ420(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_yj, + int dst_stride_yj, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert ARGB to J422. +LIBYUV_API +int ARGBToJ422(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_yj, + int dst_stride_yj, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert ARGB to J400. (JPeg full range). +LIBYUV_API +int ARGBToJ400(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_yj, + int dst_stride_yj, + int width, + int height); + +// Convert RGBA to J400. (JPeg full range). +LIBYUV_API +int RGBAToJ400(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_yj, + int dst_stride_yj, + int width, + int height); + +// Convert ARGB to I400. +LIBYUV_API +int ARGBToI400(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Convert ARGB to G. (Reverse of J400toARGB, which replicates G back to ARGB) +LIBYUV_API +int ARGBToG(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_g, + int dst_stride_g, + int width, + int height); + +// Convert ARGB To NV12. +LIBYUV_API +int ARGBToNV12(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Convert ARGB To NV21. +LIBYUV_API +int ARGBToNV21(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Convert ABGR To NV12. +LIBYUV_API +int ABGRToNV12(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Convert ABGR To NV21. +LIBYUV_API +int ABGRToNV21(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Convert ARGB To YUY2. +LIBYUV_API +int ARGBToYUY2(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_yuy2, + int dst_stride_yuy2, + int width, + int height); + +// Convert ARGB To UYVY. +LIBYUV_API +int ARGBToUYVY(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_uyvy, + int dst_stride_uyvy, + int width, + int height); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ diff --git a/thirdparty/include/libyuv/cpu_id.h b/thirdparty/include/libyuv/cpu_id.h new file mode 100755 index 0000000000000000000000000000000000000000..3e27cc107dcd6e549b810e7a2ced4bc6725dd957 --- /dev/null +++ b/thirdparty/include/libyuv/cpu_id.h @@ -0,0 +1,122 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_CPU_ID_H_ +#define INCLUDE_LIBYUV_CPU_ID_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Internal flag to indicate cpuid requires initialization. +static const int kCpuInitialized = 0x1; + +// These flags are only valid on ARM processors. +static const int kCpuHasARM = 0x2; +static const int kCpuHasNEON = 0x4; +// 0x8 reserved for future ARM flag. + +// These flags are only valid on x86 processors. +static const int kCpuHasX86 = 0x10; +static const int kCpuHasSSE2 = 0x20; +static const int kCpuHasSSSE3 = 0x40; +static const int kCpuHasSSE41 = 0x80; +static const int kCpuHasSSE42 = 0x100; // unused at this time. +static const int kCpuHasAVX = 0x200; +static const int kCpuHasAVX2 = 0x400; +static const int kCpuHasERMS = 0x800; +static const int kCpuHasFMA3 = 0x1000; +static const int kCpuHasF16C = 0x2000; +static const int kCpuHasGFNI = 0x4000; +static const int kCpuHasAVX512BW = 0x8000; +static const int kCpuHasAVX512VL = 0x10000; +static const int kCpuHasAVX512VBMI = 0x20000; +static const int kCpuHasAVX512VBMI2 = 0x40000; +static const int kCpuHasAVX512VBITALG = 0x80000; +static const int kCpuHasAVX512VPOPCNTDQ = 0x100000; + +// These flags are only valid on MIPS processors. +static const int kCpuHasMIPS = 0x200000; +static const int kCpuHasMSA = 0x400000; +static const int kCpuHasMMI = 0x800000; + +// Optional init function. TestCpuFlag does an auto-init. +// Returns cpu_info flags. +LIBYUV_API +int InitCpuFlags(void); + +// Detect CPU has SSE2 etc. +// Test_flag parameter should be one of kCpuHas constants above. +// Returns non-zero if instruction set is detected +static __inline int TestCpuFlag(int test_flag) { + LIBYUV_API extern int cpu_info_; +#ifdef __ATOMIC_RELAXED + int cpu_info = __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED); +#else + int cpu_info = cpu_info_; +#endif + return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag; +} + +// Internal function for parsing /proc/cpuinfo. +LIBYUV_API +int ArmCpuCaps(const char* cpuinfo_name); +LIBYUV_API +int MipsCpuCaps(const char* cpuinfo_name); + +// For testing, allow CPU flags to be disabled. +// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. +// MaskCpuFlags(-1) to enable all cpu specific optimizations. +// MaskCpuFlags(1) to disable all cpu specific optimizations. +// MaskCpuFlags(0) to reset state so next call will auto init. +// Returns cpu_info flags. +LIBYUV_API +int MaskCpuFlags(int enable_flags); + +// Sets the CPU flags to |cpu_flags|, bypassing the detection code. |cpu_flags| +// should be a valid combination of the kCpuHas constants above and include +// kCpuInitialized. Use this method when running in a sandboxed process where +// the detection code might fail (as it might access /proc/cpuinfo). In such +// cases the cpu_info can be obtained from a non sandboxed process by calling +// InitCpuFlags() and passed to the sandboxed process (via command line +// parameters, IPC...) which can then call this method to initialize the CPU +// flags. +// Notes: +// - when specifying 0 for |cpu_flags|, the auto initialization is enabled +// again. +// - enabling CPU features that are not supported by the CPU will result in +// undefined behavior. +// TODO(fbarchard): consider writing a helper function that translates from +// other library CPU info to libyuv CPU info and add a .md doc that explains +// CPU detection. +static __inline void SetCpuFlags(int cpu_flags) { + LIBYUV_API extern int cpu_info_; +#ifdef __ATOMIC_RELAXED + __atomic_store_n(&cpu_info_, cpu_flags, __ATOMIC_RELAXED); +#else + cpu_info_ = cpu_flags; +#endif +} + +// Low level cpuid for X86. Returns zeros on other CPUs. +// eax is the info type that you want. +// ecx is typically the cpu number, and should normally be zero. +LIBYUV_API +void CpuId(int info_eax, int info_ecx, int* cpu_info); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_CPU_ID_H_ diff --git a/thirdparty/include/libyuv/macros_msa.h b/thirdparty/include/libyuv/macros_msa.h new file mode 100755 index 0000000000000000000000000000000000000000..4e232b66bfef3a25083c47d40b00cf12e46846f1 --- /dev/null +++ b/thirdparty/include/libyuv/macros_msa.h @@ -0,0 +1,236 @@ +/* + * Copyright 2016 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_MACROS_MSA_H_ +#define INCLUDE_LIBYUV_MACROS_MSA_H_ + +#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) +#include +#include + +#if (__mips_isa_rev >= 6) +#define LW(psrc) \ + ({ \ + const uint8_t* psrc_lw_m = (const uint8_t*)(psrc); \ + uint32_t val_m; \ + asm volatile("lw %[val_m], %[psrc_lw_m] \n" \ + : [val_m] "=r"(val_m) \ + : [psrc_lw_m] "m"(*psrc_lw_m)); \ + val_m; \ + }) + +#if (__mips == 64) +#define LD(psrc) \ + ({ \ + const uint8_t* psrc_ld_m = (const uint8_t*)(psrc); \ + uint64_t val_m = 0; \ + asm volatile("ld %[val_m], %[psrc_ld_m] \n" \ + : [val_m] "=r"(val_m) \ + : [psrc_ld_m] "m"(*psrc_ld_m)); \ + val_m; \ + }) +#else // !(__mips == 64) +#define LD(psrc) \ + ({ \ + const uint8_t* psrc_ld_m = (const uint8_t*)(psrc); \ + uint32_t val0_m, val1_m; \ + uint64_t val_m = 0; \ + val0_m = LW(psrc_ld_m); \ + val1_m = LW(psrc_ld_m + 4); \ + val_m = (uint64_t)(val1_m); /* NOLINT */ \ + val_m = (uint64_t)((val_m << 32) & 0xFFFFFFFF00000000); /* NOLINT */ \ + val_m = (uint64_t)(val_m | (uint64_t)val0_m); /* NOLINT */ \ + val_m; \ + }) +#endif // (__mips == 64) + +#define SW(val, pdst) \ + ({ \ + uint8_t* pdst_sw_m = (uint8_t*)(pdst); /* NOLINT */ \ + uint32_t val_m = (val); \ + asm volatile("sw %[val_m], %[pdst_sw_m] \n" \ + : [pdst_sw_m] "=m"(*pdst_sw_m) \ + : [val_m] "r"(val_m)); \ + }) + +#if (__mips == 64) +#define SD(val, pdst) \ + ({ \ + uint8_t* pdst_sd_m = (uint8_t*)(pdst); /* NOLINT */ \ + uint64_t val_m = (val); \ + asm volatile("sd %[val_m], %[pdst_sd_m] \n" \ + : [pdst_sd_m] "=m"(*pdst_sd_m) \ + : [val_m] "r"(val_m)); \ + }) +#else // !(__mips == 64) +#define SD(val, pdst) \ + ({ \ + uint8_t* pdst_sd_m = (uint8_t*)(pdst); /* NOLINT */ \ + uint32_t val0_m, val1_m; \ + val0_m = (uint32_t)((val)&0x00000000FFFFFFFF); \ + val1_m = (uint32_t)(((val) >> 32) & 0x00000000FFFFFFFF); \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + }) +#endif // !(__mips == 64) +#else // !(__mips_isa_rev >= 6) +#define LW(psrc) \ + ({ \ + const uint8_t* psrc_lw_m = (const uint8_t*)(psrc); \ + uint32_t val_m; \ + asm volatile("ulw %[val_m], %[psrc_lw_m] \n" \ + : [val_m] "=r"(val_m) \ + : [psrc_lw_m] "m"(*psrc_lw_m)); \ + val_m; \ + }) + +#if (__mips == 64) +#define LD(psrc) \ + ({ \ + const uint8_t* psrc_ld_m = (const uint8_t*)(psrc); \ + uint64_t val_m = 0; \ + asm volatile("uld %[val_m], %[psrc_ld_m] \n" \ + : [val_m] "=r"(val_m) \ + : [psrc_ld_m] "m"(*psrc_ld_m)); \ + val_m; \ + }) +#else // !(__mips == 64) +#define LD(psrc) \ + ({ \ + const uint8_t* psrc_ld_m = (const uint8_t*)(psrc); \ + uint32_t val0_m, val1_m; \ + uint64_t val_m = 0; \ + val0_m = LW(psrc_ld_m); \ + val1_m = LW(psrc_ld_m + 4); \ + val_m = (uint64_t)(val1_m); /* NOLINT */ \ + val_m = (uint64_t)((val_m << 32) & 0xFFFFFFFF00000000); /* NOLINT */ \ + val_m = (uint64_t)(val_m | (uint64_t)val0_m); /* NOLINT */ \ + val_m; \ + }) +#endif // (__mips == 64) + +#define SW(val, pdst) \ + ({ \ + uint8_t* pdst_sw_m = (uint8_t*)(pdst); /* NOLINT */ \ + uint32_t val_m = (val); \ + asm volatile("usw %[val_m], %[pdst_sw_m] \n" \ + : [pdst_sw_m] "=m"(*pdst_sw_m) \ + : [val_m] "r"(val_m)); \ + }) + +#define SD(val, pdst) \ + ({ \ + uint8_t* pdst_sd_m = (uint8_t*)(pdst); /* NOLINT */ \ + uint32_t val0_m, val1_m; \ + val0_m = (uint32_t)((val)&0x00000000FFFFFFFF); \ + val1_m = (uint32_t)(((val) >> 32) & 0x00000000FFFFFFFF); \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + }) +#endif // (__mips_isa_rev >= 6) + +// TODO(fbarchard): Consider removing __VAR_ARGS versions. +#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc)) /* NOLINT */ +#define LD_UB(...) LD_B(const v16u8, __VA_ARGS__) + +#define LD_H(RTYPE, psrc) *((RTYPE*)(psrc)) /* NOLINT */ +#define LD_UH(...) LD_H(const v8u16, __VA_ARGS__) + +#define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = (in) /* NOLINT */ +#define ST_UB(...) ST_B(v16u8, __VA_ARGS__) + +#define ST_H(RTYPE, in, pdst) *((RTYPE*)(pdst)) = (in) /* NOLINT */ +#define ST_UH(...) ST_H(v8u16, __VA_ARGS__) + +/* Description : Load two vectors with 16 'byte' sized elements + Arguments : Inputs - psrc, stride + Outputs - out0, out1 + Return Type - as per RTYPE + Details : Load 16 byte elements in 'out0' from (psrc) + Load 16 byte elements in 'out1' from (psrc + stride) +*/ +#define LD_B2(RTYPE, psrc, stride, out0, out1) \ + { \ + out0 = LD_B(RTYPE, (psrc)); \ + out1 = LD_B(RTYPE, (psrc) + stride); \ + } +#define LD_UB2(...) LD_B2(const v16u8, __VA_ARGS__) + +#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) \ + { \ + LD_B2(RTYPE, (psrc), stride, out0, out1); \ + LD_B2(RTYPE, (psrc) + 2 * stride, stride, out2, out3); \ + } +#define LD_UB4(...) LD_B4(const v16u8, __VA_ARGS__) + +/* Description : Store two vectors with stride each having 16 'byte' sized + elements + Arguments : Inputs - in0, in1, pdst, stride + Details : Store 16 byte elements from 'in0' to (pdst) + Store 16 byte elements from 'in1' to (pdst + stride) +*/ +#define ST_B2(RTYPE, in0, in1, pdst, stride) \ + { \ + ST_B(RTYPE, in0, (pdst)); \ + ST_B(RTYPE, in1, (pdst) + stride); \ + } +#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__) + +#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) \ + { \ + ST_B2(RTYPE, in0, in1, (pdst), stride); \ + ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \ + } +#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__) + +/* Description : Store vectors of 8 halfword elements with stride + Arguments : Inputs - in0, in1, pdst, stride + Details : Store 8 halfword elements from 'in0' to (pdst) + Store 8 halfword elements from 'in1' to (pdst + stride) +*/ +#define ST_H2(RTYPE, in0, in1, pdst, stride) \ + { \ + ST_H(RTYPE, in0, (pdst)); \ + ST_H(RTYPE, in1, (pdst) + stride); \ + } +#define ST_UH2(...) ST_H2(v8u16, __VA_ARGS__) + +// TODO(fbarchard): Consider using __msa_vshf_b and __msa_ilvr_b directly. +/* Description : Shuffle byte vector elements as per mask vector + Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 + Outputs - out0, out1 + Return Type - as per RTYPE + Details : Byte elements from 'in0' & 'in1' are copied selectively to + 'out0' as per control vector 'mask0' +*/ +#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) \ + { \ + out0 = (RTYPE)__msa_vshf_b((v16i8)mask0, (v16i8)in1, (v16i8)in0); \ + out1 = (RTYPE)__msa_vshf_b((v16i8)mask1, (v16i8)in3, (v16i8)in2); \ + } +#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__) + +/* Description : Interleave both left and right half of input vectors + Arguments : Inputs - in0, in1 + Outputs - out0, out1 + Return Type - as per RTYPE + Details : Right half of byte elements from 'in0' and 'in1' are + interleaved and written to 'out0' +*/ +#define ILVRL_B2(RTYPE, in0, in1, out0, out1) \ + { \ + out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \ + out1 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \ + } +#define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__) + +#endif /* !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) */ + +#endif // INCLUDE_LIBYUV_MACROS_MSA_H_ diff --git a/thirdparty/include/libyuv/mjpeg_decoder.h b/thirdparty/include/libyuv/mjpeg_decoder.h new file mode 100755 index 0000000000000000000000000000000000000000..275f8d4c18532003248bf4c51d0bce36b737c9a8 --- /dev/null +++ b/thirdparty/include/libyuv/mjpeg_decoder.h @@ -0,0 +1,195 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_MJPEG_DECODER_H_ +#define INCLUDE_LIBYUV_MJPEG_DECODER_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +// NOTE: For a simplified public API use convert.h MJPGToI420(). + +struct jpeg_common_struct; +struct jpeg_decompress_struct; +struct jpeg_source_mgr; + +namespace libyuv { + +#ifdef __cplusplus +extern "C" { +#endif + +LIBYUV_BOOL ValidateJpeg(const uint8_t* sample, size_t sample_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +static const uint32_t kUnknownDataSize = 0xFFFFFFFF; + +enum JpegSubsamplingType { + kJpegYuv420, + kJpegYuv422, + kJpegYuv444, + kJpegYuv400, + kJpegUnknown +}; + +struct Buffer { + const uint8_t* data; + int len; +}; + +struct BufferVector { + Buffer* buffers; + int len; + int pos; +}; + +struct SetJmpErrorMgr; + +// MJPEG ("Motion JPEG") is a pseudo-standard video codec where the frames are +// simply independent JPEG images with a fixed huffman table (which is omitted). +// It is rarely used in video transmission, but is common as a camera capture +// format, especially in Logitech devices. This class implements a decoder for +// MJPEG frames. +// +// See http://tools.ietf.org/html/rfc2435 +class LIBYUV_API MJpegDecoder { + public: + typedef void (*CallbackFunction)(void* opaque, + const uint8_t* const* data, + const int* strides, + int rows); + + static const int kColorSpaceUnknown; + static const int kColorSpaceGrayscale; + static const int kColorSpaceRgb; + static const int kColorSpaceYCbCr; + static const int kColorSpaceCMYK; + static const int kColorSpaceYCCK; + + MJpegDecoder(); + ~MJpegDecoder(); + + // Loads a new frame, reads its headers, and determines the uncompressed + // image format. + // Returns LIBYUV_TRUE if image looks valid and format is supported. + // If return value is LIBYUV_TRUE, then the values for all the following + // getters are populated. + // src_len is the size of the compressed mjpeg frame in bytes. + LIBYUV_BOOL LoadFrame(const uint8_t* src, size_t src_len); + + // Returns width of the last loaded frame in pixels. + int GetWidth(); + + // Returns height of the last loaded frame in pixels. + int GetHeight(); + + // Returns format of the last loaded frame. The return value is one of the + // kColorSpace* constants. + int GetColorSpace(); + + // Number of color components in the color space. + int GetNumComponents(); + + // Sample factors of the n-th component. + int GetHorizSampFactor(int component); + + int GetVertSampFactor(int component); + + int GetHorizSubSampFactor(int component); + + int GetVertSubSampFactor(int component); + + // Public for testability. + int GetImageScanlinesPerImcuRow(); + + // Public for testability. + int GetComponentScanlinesPerImcuRow(int component); + + // Width of a component in bytes. + int GetComponentWidth(int component); + + // Height of a component. + int GetComponentHeight(int component); + + // Width of a component in bytes with padding for DCTSIZE. Public for testing. + int GetComponentStride(int component); + + // Size of a component in bytes. + int GetComponentSize(int component); + + // Call this after LoadFrame() if you decide you don't want to decode it + // after all. + LIBYUV_BOOL UnloadFrame(); + + // Decodes the entire image into a one-buffer-per-color-component format. + // dst_width must match exactly. dst_height must be <= to image height; if + // less, the image is cropped. "planes" must have size equal to at least + // GetNumComponents() and they must point to non-overlapping buffers of size + // at least GetComponentSize(i). The pointers in planes are incremented + // to point to after the end of the written data. + // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. + LIBYUV_BOOL DecodeToBuffers(uint8_t** planes, int dst_width, int dst_height); + + // Decodes the entire image and passes the data via repeated calls to a + // callback function. Each call will get the data for a whole number of + // image scanlines. + // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. + LIBYUV_BOOL DecodeToCallback(CallbackFunction fn, + void* opaque, + int dst_width, + int dst_height); + + // The helper function which recognizes the jpeg sub-sampling type. + static JpegSubsamplingType JpegSubsamplingTypeHelper( + int* subsample_x, + int* subsample_y, + int number_of_components); + + private: + void AllocOutputBuffers(int num_outbufs); + void DestroyOutputBuffers(); + + LIBYUV_BOOL StartDecode(); + LIBYUV_BOOL FinishDecode(); + + void SetScanlinePointers(uint8_t** data); + LIBYUV_BOOL DecodeImcuRow(); + + int GetComponentScanlinePadding(int component); + + // A buffer holding the input data for a frame. + Buffer buf_; + BufferVector buf_vec_; + + jpeg_decompress_struct* decompress_struct_; + jpeg_source_mgr* source_mgr_; + SetJmpErrorMgr* error_mgr_; + + // LIBYUV_TRUE iff at least one component has scanline padding. (i.e., + // GetComponentScanlinePadding() != 0.) + LIBYUV_BOOL has_scanline_padding_; + + // Temporaries used to point to scanline outputs. + int num_outbufs_; // Outermost size of all arrays below. + uint8_t*** scanlines_; + int* scanlines_sizes_; + // Temporary buffer used for decoding when we can't decode directly to the + // output buffers. Large enough for just one iMCU row. + uint8_t** databuf_; + int* databuf_strides_; +}; + +} // namespace libyuv + +#endif // __cplusplus +#endif // INCLUDE_LIBYUV_MJPEG_DECODER_H_ diff --git a/thirdparty/include/libyuv/planar_functions.h b/thirdparty/include/libyuv/planar_functions.h new file mode 100755 index 0000000000000000000000000000000000000000..9e0038f4745a3736c0ca8743f820a2dac5392033 --- /dev/null +++ b/thirdparty/include/libyuv/planar_functions.h @@ -0,0 +1,890 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ +#define INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ + +#include "libyuv/basic_types.h" + +// TODO(fbarchard): Remove the following headers includes. +#include "libyuv/convert.h" +#include "libyuv/convert_argb.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// TODO(fbarchard): Move cpu macros to row.h +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__native_client__) && defined(__x86_64__)) || \ + (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) +#define LIBYUV_DISABLE_X86 +#endif +// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define LIBYUV_DISABLE_X86 +#endif +#endif +// The following are available on all x86 platforms: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) +#define HAS_ARGBAFFINEROW_SSE2 +#endif + +// Copy a plane of data. +LIBYUV_API +void CopyPlane(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +LIBYUV_API +void CopyPlane_16(const uint16_t* src_y, + int src_stride_y, + uint16_t* dst_y, + int dst_stride_y, + int width, + int height); + +LIBYUV_API +void Convert16To8Plane(const uint16_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int scale, // 16384 for 10 bits + int width, + int height); + +LIBYUV_API +void Convert8To16Plane(const uint8_t* src_y, + int src_stride_y, + uint16_t* dst_y, + int dst_stride_y, + int scale, // 1024 for 10 bits + int width, + int height); + +// Set a plane of data to a 32 bit value. +LIBYUV_API +void SetPlane(uint8_t* dst_y, + int dst_stride_y, + int width, + int height, + uint32_t value); + +// Split interleaved UV plane into separate U and V planes. +LIBYUV_API +void SplitUVPlane(const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Merge separate U and V planes into one interleaved UV plane. +LIBYUV_API +void MergeUVPlane(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Scale U and V to half width and height and merge into interleaved UV plane. +// width and height are source size, allowing odd sizes. +// Use for converting I444 or I422 to NV12. +LIBYUV_API +void HalfMergeUVPlane(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Swap U and V channels in interleaved UV plane. +LIBYUV_API +void SwapUVPlane(const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_vu, + int dst_stride_vu, + int width, + int height); + +// Split interleaved RGB plane into separate R, G and B planes. +LIBYUV_API +void SplitRGBPlane(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_r, + int dst_stride_r, + uint8_t* dst_g, + int dst_stride_g, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +// Merge separate R, G and B planes into one interleaved RGB plane. +LIBYUV_API +void MergeRGBPlane(const uint8_t* src_r, + int src_stride_r, + const uint8_t* src_g, + int src_stride_g, + const uint8_t* src_b, + int src_stride_b, + uint8_t* dst_rgb, + int dst_stride_rgb, + int width, + int height); + +// Copy I400. Supports inverting. +LIBYUV_API +int I400ToI400(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +#define J400ToJ400 I400ToI400 + +// Copy I422 to I422. +#define I422ToI422 I422Copy +LIBYUV_API +int I422Copy(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Copy I444 to I444. +#define I444ToI444 I444Copy +LIBYUV_API +int I444Copy(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert YUY2 to I422. +LIBYUV_API +int YUY2ToI422(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Convert UYVY to I422. +LIBYUV_API +int UYVYToI422(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +LIBYUV_API +int YUY2ToNV12(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +LIBYUV_API +int UYVYToNV12(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Convert NV21 to NV12. +LIBYUV_API +int NV21ToNV12(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_vu, + int src_stride_vu, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +LIBYUV_API +int YUY2ToY(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Convert I420 to I400. (calls CopyPlane ignoring u/v). +LIBYUV_API +int I420ToI400(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Alias +#define J420ToJ400 I420ToI400 +#define I420ToI420Mirror I420Mirror + +// I420 mirror. +LIBYUV_API +int I420Mirror(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Alias +#define I400ToI400Mirror I400Mirror + +// I400 mirror. A single plane is mirrored horizontally. +// Pass negative height to achieve 180 degree rotation. +LIBYUV_API +int I400Mirror(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Alias +#define NV12ToNV12Mirror NV12Mirror + +// NV12 mirror. +LIBYUV_API +int NV12Mirror(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Alias +#define ARGBToARGBMirror ARGBMirror + +// ARGB mirror. +LIBYUV_API +int ARGBMirror(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Alias +#define RGB24ToRGB24Mirror RGB24Mirror + +// RGB24 mirror. +LIBYUV_API +int RGB24Mirror(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +// Mirror a plane of data. +LIBYUV_API +void MirrorPlane(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Mirror a plane of UV data. +LIBYUV_API +void MirrorUVPlane(const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_uv, + int dst_stride_uv, + int width, + int height); + +// Alias +#define RGB24ToRAW RAWToRGB24 + +LIBYUV_API +int RAWToRGB24(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_rgb24, + int dst_stride_rgb24, + int width, + int height); + +// Draw a rectangle into I420. +LIBYUV_API +int I420Rect(uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int x, + int y, + int width, + int height, + int value_y, + int value_u, + int value_v); + +// Draw a rectangle into ARGB. +LIBYUV_API +int ARGBRect(uint8_t* dst_argb, + int dst_stride_argb, + int dst_x, + int dst_y, + int width, + int height, + uint32_t value); + +// Convert ARGB to gray scale ARGB. +LIBYUV_API +int ARGBGrayTo(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Make a rectangle of ARGB gray scale. +LIBYUV_API +int ARGBGray(uint8_t* dst_argb, + int dst_stride_argb, + int dst_x, + int dst_y, + int width, + int height); + +// Make a rectangle of ARGB Sepia tone. +LIBYUV_API +int ARGBSepia(uint8_t* dst_argb, + int dst_stride_argb, + int dst_x, + int dst_y, + int width, + int height); + +// Apply a matrix rotation to each ARGB pixel. +// matrix_argb is 4 signed ARGB values. -128 to 127 representing -2 to 2. +// The first 4 coefficients apply to B, G, R, A and produce B of the output. +// The next 4 coefficients apply to B, G, R, A and produce G of the output. +// The next 4 coefficients apply to B, G, R, A and produce R of the output. +// The last 4 coefficients apply to B, G, R, A and produce A of the output. +LIBYUV_API +int ARGBColorMatrix(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + const int8_t* matrix_argb, + int width, + int height); + +// Deprecated. Use ARGBColorMatrix instead. +// Apply a matrix rotation to each ARGB pixel. +// matrix_argb is 3 signed ARGB values. -128 to 127 representing -1 to 1. +// The first 4 coefficients apply to B, G, R, A and produce B of the output. +// The next 4 coefficients apply to B, G, R, A and produce G of the output. +// The last 4 coefficients apply to B, G, R, A and produce R of the output. +LIBYUV_API +int RGBColorMatrix(uint8_t* dst_argb, + int dst_stride_argb, + const int8_t* matrix_rgb, + int dst_x, + int dst_y, + int width, + int height); + +// Apply a color table each ARGB pixel. +// Table contains 256 ARGB values. +LIBYUV_API +int ARGBColorTable(uint8_t* dst_argb, + int dst_stride_argb, + const uint8_t* table_argb, + int dst_x, + int dst_y, + int width, + int height); + +// Apply a color table each ARGB pixel but preserve destination alpha. +// Table contains 256 ARGB values. +LIBYUV_API +int RGBColorTable(uint8_t* dst_argb, + int dst_stride_argb, + const uint8_t* table_argb, + int dst_x, + int dst_y, + int width, + int height); + +// Apply a luma/color table each ARGB pixel but preserve destination alpha. +// Table contains 32768 values indexed by [Y][C] where 7 it 7 bit luma from +// RGB (YJ style) and C is an 8 bit color component (R, G or B). +LIBYUV_API +int ARGBLumaColorTable(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + const uint8_t* luma, + int width, + int height); + +// Apply a 3 term polynomial to ARGB values. +// poly points to a 4x4 matrix. The first row is constants. The 2nd row is +// coefficients for b, g, r and a. The 3rd row is coefficients for b squared, +// g squared, r squared and a squared. The 4rd row is coefficients for b to +// the 3, g to the 3, r to the 3 and a to the 3. The values are summed and +// result clamped to 0 to 255. +// A polynomial approximation can be dirived using software such as 'R'. + +LIBYUV_API +int ARGBPolynomial(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + const float* poly, + int width, + int height); + +// Convert plane of 16 bit shorts to half floats. +// Source values are multiplied by scale before storing as half float. +LIBYUV_API +int HalfFloatPlane(const uint16_t* src_y, + int src_stride_y, + uint16_t* dst_y, + int dst_stride_y, + float scale, + int width, + int height); + +// Convert a buffer of bytes to floats, scale the values and store as floats. +LIBYUV_API +int ByteToFloat(const uint8_t* src_y, float* dst_y, float scale, int width); + +// Quantize a rectangle of ARGB. Alpha unaffected. +// scale is a 16 bit fractional fixed point scaler between 0 and 65535. +// interval_size should be a value between 1 and 255. +// interval_offset should be a value between 0 and 255. +LIBYUV_API +int ARGBQuantize(uint8_t* dst_argb, + int dst_stride_argb, + int scale, + int interval_size, + int interval_offset, + int dst_x, + int dst_y, + int width, + int height); + +// Copy ARGB to ARGB. +LIBYUV_API +int ARGBCopy(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Copy Alpha channel of ARGB to alpha of ARGB. +LIBYUV_API +int ARGBCopyAlpha(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Extract the alpha channel from ARGB. +LIBYUV_API +int ARGBExtractAlpha(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_a, + int dst_stride_a, + int width, + int height); + +// Copy Y channel to Alpha of ARGB. +LIBYUV_API +int ARGBCopyYToAlpha(const uint8_t* src_y, + int src_stride_y, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +typedef void (*ARGBBlendRow)(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); + +// Get function to Alpha Blend ARGB pixels and store to destination. +LIBYUV_API +ARGBBlendRow GetARGBBlend(); + +// Alpha Blend ARGB images and store to destination. +// Source is pre-multiplied by alpha using ARGBAttenuate. +// Alpha of destination is set to 255. +LIBYUV_API +int ARGBBlend(const uint8_t* src_argb0, + int src_stride_argb0, + const uint8_t* src_argb1, + int src_stride_argb1, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Alpha Blend plane and store to destination. +// Source is not pre-multiplied by alpha. +LIBYUV_API +int BlendPlane(const uint8_t* src_y0, + int src_stride_y0, + const uint8_t* src_y1, + int src_stride_y1, + const uint8_t* alpha, + int alpha_stride, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Alpha Blend YUV images and store to destination. +// Source is not pre-multiplied by alpha. +// Alpha is full width x height and subsampled to half size to apply to UV. +LIBYUV_API +int I420Blend(const uint8_t* src_y0, + int src_stride_y0, + const uint8_t* src_u0, + int src_stride_u0, + const uint8_t* src_v0, + int src_stride_v0, + const uint8_t* src_y1, + int src_stride_y1, + const uint8_t* src_u1, + int src_stride_u1, + const uint8_t* src_v1, + int src_stride_v1, + const uint8_t* alpha, + int alpha_stride, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height); + +// Multiply ARGB image by ARGB image. Shifted down by 8. Saturates to 255. +LIBYUV_API +int ARGBMultiply(const uint8_t* src_argb0, + int src_stride_argb0, + const uint8_t* src_argb1, + int src_stride_argb1, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Add ARGB image with ARGB image. Saturates to 255. +LIBYUV_API +int ARGBAdd(const uint8_t* src_argb0, + int src_stride_argb0, + const uint8_t* src_argb1, + int src_stride_argb1, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Subtract ARGB image (argb1) from ARGB image (argb0). Saturates to 0. +LIBYUV_API +int ARGBSubtract(const uint8_t* src_argb0, + int src_stride_argb0, + const uint8_t* src_argb1, + int src_stride_argb1, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert I422 to YUY2. +LIBYUV_API +int I422ToYUY2(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_yuy2, + int dst_stride_yuy2, + int width, + int height); + +// Convert I422 to UYVY. +LIBYUV_API +int I422ToUYVY(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uyvy, + int dst_stride_uyvy, + int width, + int height); + +// Convert unattentuated ARGB to preattenuated ARGB. +LIBYUV_API +int ARGBAttenuate(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Convert preattentuated ARGB to unattenuated ARGB. +LIBYUV_API +int ARGBUnattenuate(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Internal function - do not call directly. +// Computes table of cumulative sum for image where the value is the sum +// of all values above and to the left of the entry. Used by ARGBBlur. +LIBYUV_API +int ARGBComputeCumulativeSum(const uint8_t* src_argb, + int src_stride_argb, + int32_t* dst_cumsum, + int dst_stride32_cumsum, + int width, + int height); + +// Blur ARGB image. +// dst_cumsum table of width * (height + 1) * 16 bytes aligned to +// 16 byte boundary. +// dst_stride32_cumsum is number of ints in a row (width * 4). +// radius is number of pixels around the center. e.g. 1 = 3x3. 2=5x5. +// Blur is optimized for radius of 5 (11x11) or less. +LIBYUV_API +int ARGBBlur(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int32_t* dst_cumsum, + int dst_stride32_cumsum, + int width, + int height, + int radius); + +// Gaussian 5x5 blur a float plane. +// Coefficients of 1, 4, 6, 4, 1. +// Each destination pixel is a blur of the 5x5 +// pixels from the source. +// Source edges are clamped. +LIBYUV_API +int GaussPlane_F32(const float* src, + int src_stride, + float* dst, + int dst_stride, + int width, + int height); + +// Multiply ARGB image by ARGB value. +LIBYUV_API +int ARGBShade(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height, + uint32_t value); + +// Interpolate between two images using specified amount of interpolation +// (0 to 255) and store to destination. +// 'interpolation' is specified as 8 bit fraction where 0 means 100% src0 +// and 255 means 1% src0 and 99% src1. +LIBYUV_API +int InterpolatePlane(const uint8_t* src0, + int src_stride0, + const uint8_t* src1, + int src_stride1, + uint8_t* dst, + int dst_stride, + int width, + int height, + int interpolation); + +// Interpolate between two ARGB images using specified amount of interpolation +// Internally calls InterpolatePlane with width * 4 (bpp). +LIBYUV_API +int ARGBInterpolate(const uint8_t* src_argb0, + int src_stride_argb0, + const uint8_t* src_argb1, + int src_stride_argb1, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height, + int interpolation); + +// Interpolate between two YUV images using specified amount of interpolation +// Internally calls InterpolatePlane on each plane where the U and V planes +// are half width and half height. +LIBYUV_API +int I420Interpolate(const uint8_t* src0_y, + int src0_stride_y, + const uint8_t* src0_u, + int src0_stride_u, + const uint8_t* src0_v, + int src0_stride_v, + const uint8_t* src1_y, + int src1_stride_y, + const uint8_t* src1_u, + int src1_stride_u, + const uint8_t* src1_v, + int src1_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height, + int interpolation); + +// Row function for copying pixels from a source with a slope to a row +// of destination. Useful for scaling, rotation, mirror, texture mapping. +LIBYUV_API +void ARGBAffineRow_C(const uint8_t* src_argb, + int src_argb_stride, + uint8_t* dst_argb, + const float* uv_dudv, + int width); +// TODO(fbarchard): Move ARGBAffineRow_SSE2 to row.h +LIBYUV_API +void ARGBAffineRow_SSE2(const uint8_t* src_argb, + int src_argb_stride, + uint8_t* dst_argb, + const float* uv_dudv, + int width); + +// Shuffle ARGB channel order. e.g. BGRA to ARGB. +// shuffler is 16 bytes and must be aligned. +LIBYUV_API +int ARGBShuffle(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_argb, + int dst_stride_argb, + const uint8_t* shuffler, + int width, + int height); + +// Sobel ARGB effect with planar output. +LIBYUV_API +int ARGBSobelToPlane(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_y, + int dst_stride_y, + int width, + int height); + +// Sobel ARGB effect. +LIBYUV_API +int ARGBSobel(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +// Sobel ARGB effect w/ Sobel X, Sobel, Sobel Y in ARGB. +LIBYUV_API +int ARGBSobelXY(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int width, + int height); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ diff --git a/thirdparty/include/libyuv/rotate.h b/thirdparty/include/libyuv/rotate.h new file mode 100755 index 0000000000000000000000000000000000000000..308882242cb15b8c60c4101c77104e82134fb9a4 --- /dev/null +++ b/thirdparty/include/libyuv/rotate.h @@ -0,0 +1,182 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_ROTATE_H_ +#define INCLUDE_LIBYUV_ROTATE_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Supported rotation. +typedef enum RotationMode { + kRotate0 = 0, // No rotation. + kRotate90 = 90, // Rotate 90 degrees clockwise. + kRotate180 = 180, // Rotate 180 degrees. + kRotate270 = 270, // Rotate 270 degrees clockwise. + + // Deprecated. + kRotateNone = 0, + kRotateClockwise = 90, + kRotateCounterClockwise = 270, +} RotationModeEnum; + +// Rotate I420 frame. +LIBYUV_API +int I420Rotate(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height, + enum RotationMode mode); + +// Rotate I444 frame. +LIBYUV_API +int I444Rotate(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height, + enum RotationMode mode); + +// Rotate NV12 input and store in I420. +LIBYUV_API +int NV12ToI420Rotate(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int width, + int height, + enum RotationMode mode); + +// Rotate a plane by 0, 90, 180, or 270. +LIBYUV_API +int RotatePlane(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height, + enum RotationMode mode); + +// Rotate planes by 90, 180, 270. Deprecated. +LIBYUV_API +void RotatePlane90(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height); + +LIBYUV_API +void RotatePlane180(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height); + +LIBYUV_API +void RotatePlane270(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height); + +// Rotations for when U and V are interleaved. +// These functions take one input pointer and +// split the data into two buffers while +// rotating them. Deprecated. +LIBYUV_API +void RotateUV90(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +LIBYUV_API +void RotateUV180(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +LIBYUV_API +void RotateUV270(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +// The 90 and 270 functions are based on transposes. +// Doing a transpose with reversing the read/write +// order will result in a rotation by +- 90 degrees. +// Deprecated. +LIBYUV_API +void TransposePlane(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height); + +LIBYUV_API +void TransposeUV(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_ROTATE_H_ diff --git a/thirdparty/include/libyuv/rotate_argb.h b/thirdparty/include/libyuv/rotate_argb.h new file mode 100755 index 0000000000000000000000000000000000000000..20432949ab42af56b803cb7ef6ee1c5914cb7434 --- /dev/null +++ b/thirdparty/include/libyuv/rotate_argb.h @@ -0,0 +1,37 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_ +#define INCLUDE_LIBYUV_ROTATE_ARGB_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/rotate.h" // For RotationMode. + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Rotate ARGB frame +LIBYUV_API +int ARGBRotate(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_argb, + int dst_stride_argb, + int src_width, + int src_height, + enum RotationMode mode); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_ diff --git a/thirdparty/include/libyuv/rotate_row.h b/thirdparty/include/libyuv/rotate_row.h new file mode 100755 index 0000000000000000000000000000000000000000..022293eef2c9580c2ca46d94633db8e84b58f9ba --- /dev/null +++ b/thirdparty/include/libyuv/rotate_row.h @@ -0,0 +1,223 @@ +/* + * Copyright 2013 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_ROTATE_ROW_H_ +#define INCLUDE_LIBYUV_ROTATE_ROW_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__native_client__) && defined(__x86_64__)) || \ + (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) +#define LIBYUV_DISABLE_X86 +#endif +#if defined(__native_client__) +#define LIBYUV_DISABLE_NEON +#endif +// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define LIBYUV_DISABLE_X86 +#endif +#endif +// The following are available for Visual C and clangcl 32 bit: +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) +#define HAS_TRANSPOSEWX8_SSSE3 +#define HAS_TRANSPOSEUVWX8_SSE2 +#endif + +// The following are available for GCC 32 or 64 bit: +#if !defined(LIBYUV_DISABLE_X86) && (defined(__i386__) || defined(__x86_64__)) +#define HAS_TRANSPOSEWX8_SSSE3 +#endif + +// The following are available for 64 bit GCC: +#if !defined(LIBYUV_DISABLE_X86) && defined(__x86_64__) +#define HAS_TRANSPOSEWX8_FAST_SSSE3 +#define HAS_TRANSPOSEUVWX8_SSE2 +#endif + +#if !defined(LIBYUV_DISABLE_NEON) && \ + (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) +#define HAS_TRANSPOSEWX8_NEON +#define HAS_TRANSPOSEUVWX8_NEON +#endif + +#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) +#define HAS_TRANSPOSEWX16_MSA +#define HAS_TRANSPOSEUVWX16_MSA +#endif + +#if !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A) +#define HAS_TRANSPOSEWX8_MMI +#define HAS_TRANSPOSEUVWX8_MMI +#endif + +void TransposeWxH_C(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width, + int height); + +void TransposeWx8_C(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx16_C(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_NEON(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_SSSE3(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_MMI(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_Fast_SSSE3(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx16_MSA(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); + +void TransposeWx8_Any_NEON(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_Any_SSSE3(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_Any_MMI(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx8_Fast_Any_SSSE3(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); +void TransposeWx16_Any_MSA(const uint8_t* src, + int src_stride, + uint8_t* dst, + int dst_stride, + int width); + +void TransposeUVWxH_C(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width, + int height); + +void TransposeUVWx8_C(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx16_C(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx8_SSE2(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx8_NEON(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx8_MMI(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx16_MSA(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); + +void TransposeUVWx8_Any_SSE2(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx8_Any_NEON(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx8_Any_MMI(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); +void TransposeUVWx16_Any_MSA(const uint8_t* src, + int src_stride, + uint8_t* dst_a, + int dst_stride_a, + uint8_t* dst_b, + int dst_stride_b, + int width); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_ROTATE_ROW_H_ diff --git a/thirdparty/include/libyuv/row.h b/thirdparty/include/libyuv/row.h new file mode 100755 index 0000000000000000000000000000000000000000..a27788c1f6970650f33022b052f8030a64855391 --- /dev/null +++ b/thirdparty/include/libyuv/row.h @@ -0,0 +1,4384 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_ROW_H_ +#define INCLUDE_LIBYUV_ROW_H_ + +#include // For malloc. + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__native_client__) && defined(__x86_64__)) || \ + (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) +#define LIBYUV_DISABLE_X86 +#endif +#if defined(__native_client__) +#define LIBYUV_DISABLE_NEON +#endif +// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define LIBYUV_DISABLE_X86 +#endif +#endif +// clang >= 3.5.0 required for Arm64. +#if defined(__clang__) && defined(__aarch64__) && !defined(LIBYUV_DISABLE_NEON) +#if (__clang_major__ < 3) || (__clang_major__ == 3 && (__clang_minor__ < 5)) +#define LIBYUV_DISABLE_NEON +#endif // clang >= 3.5 +#endif // __clang__ + +// GCC >= 4.7.0 required for AVX2. +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) +#define GCC_HAS_AVX2 1 +#endif // GNUC >= 4.7 +#endif // __GNUC__ + +// clang >= 3.4.0 required for AVX2. +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) +#define CLANG_HAS_AVX2 1 +#endif // clang >= 3.4 +#endif // __clang__ + +// clang >= 6.0.0 required for AVX512. +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +// clang in xcode follows a different versioning scheme. +// TODO(fbarchard): fix xcode 9 ios b/789. +#if (__clang_major__ >= 7) && !defined(__APPLE__) +#define CLANG_HAS_AVX512 1 +#endif // clang >= 7 +#endif // __clang__ + +// Visual C 2012 required for AVX2. +#if defined(_M_IX86) && !defined(__clang__) && defined(_MSC_VER) && \ + _MSC_VER >= 1700 +#define VISUALC_HAS_AVX2 1 +#endif // VisualStudio >= 2012 + +// The following are available on all x86 platforms: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) +// Conversions: +#define HAS_ABGRTOUVROW_SSSE3 +#define HAS_ABGRTOYROW_SSSE3 +#define HAS_ARGB1555TOARGBROW_SSE2 +#define HAS_ARGB4444TOARGBROW_SSE2 +#define HAS_ARGBEXTRACTALPHAROW_SSE2 +#define HAS_ARGBSETROW_X86 +#define HAS_ARGBSHUFFLEROW_SSSE3 +#define HAS_ARGBTOARGB1555ROW_SSE2 +#define HAS_ARGBTOARGB4444ROW_SSE2 +#define HAS_ARGBTORAWROW_SSSE3 +#define HAS_ARGBTORGB24ROW_SSSE3 +#define HAS_ARGBTORGB565DITHERROW_SSE2 +#define HAS_ARGBTORGB565ROW_SSE2 +#define HAS_ARGBTOUV444ROW_SSSE3 +#define HAS_ARGBTOUVJROW_SSSE3 +#define HAS_ARGBTOUVROW_SSSE3 +#define HAS_ARGBTOYJROW_SSSE3 +#define HAS_ARGBTOYROW_SSSE3 +#define HAS_BGRATOUVROW_SSSE3 +#define HAS_BGRATOYROW_SSSE3 +#define HAS_COPYROW_ERMS +#define HAS_COPYROW_SSE2 +#define HAS_H422TOARGBROW_SSSE3 +#define HAS_HALFFLOATROW_SSE2 +#define HAS_I422TOARGB1555ROW_SSSE3 +#define HAS_I422TOARGB4444ROW_SSSE3 +#define HAS_I422TOARGBROW_SSSE3 +#define HAS_I422TORGB24ROW_SSSE3 +#define HAS_I422TORGB565ROW_SSSE3 +#define HAS_I422TORGBAROW_SSSE3 +#define HAS_I422TOUYVYROW_SSE2 +#define HAS_I422TOYUY2ROW_SSE2 +#define HAS_I444TOARGBROW_SSSE3 +#define HAS_J400TOARGBROW_SSE2 +#define HAS_J422TOARGBROW_SSSE3 +#define HAS_MERGEUVROW_SSE2 +#define HAS_MIRRORROW_SSSE3 +#define HAS_MIRRORSPLITUVROW_SSSE3 +#define HAS_NV12TOARGBROW_SSSE3 +#define HAS_NV12TORGB24ROW_SSSE3 +#define HAS_NV12TORGB565ROW_SSSE3 +#define HAS_NV21TOARGBROW_SSSE3 +#define HAS_NV21TORGB24ROW_SSSE3 +#define HAS_RAWTOARGBROW_SSSE3 +#define HAS_RAWTORGB24ROW_SSSE3 +#define HAS_RAWTOYROW_SSSE3 +#define HAS_RGB24TOARGBROW_SSSE3 +#define HAS_RGB24TOYROW_SSSE3 +#define HAS_RGB24TOYJROW_SSSE3 +#define HAS_RAWTOYJROW_SSSE3 +#define HAS_RGB565TOARGBROW_SSE2 +#define HAS_RGBATOUVROW_SSSE3 +#define HAS_RGBATOYROW_SSSE3 +#define HAS_SETROW_ERMS +#define HAS_SETROW_X86 +#define HAS_SPLITUVROW_SSE2 +#define HAS_UYVYTOARGBROW_SSSE3 +#define HAS_UYVYTOUV422ROW_SSE2 +#define HAS_UYVYTOUVROW_SSE2 +#define HAS_UYVYTOYROW_SSE2 +#define HAS_YUY2TOARGBROW_SSSE3 +#define HAS_YUY2TOUV422ROW_SSE2 +#define HAS_YUY2TOUVROW_SSE2 +#define HAS_YUY2TOYROW_SSE2 + +// Effects: +#define HAS_ARGBADDROW_SSE2 +#define HAS_ARGBAFFINEROW_SSE2 +#define HAS_ARGBATTENUATEROW_SSSE3 +#define HAS_ARGBBLENDROW_SSSE3 +#define HAS_ARGBCOLORMATRIXROW_SSSE3 +#define HAS_ARGBCOLORTABLEROW_X86 +#define HAS_ARGBCOPYALPHAROW_SSE2 +#define HAS_ARGBCOPYYTOALPHAROW_SSE2 +#define HAS_ARGBGRAYROW_SSSE3 +#define HAS_ARGBLUMACOLORTABLEROW_SSSE3 +#define HAS_ARGBMIRRORROW_SSE2 +#define HAS_ARGBMULTIPLYROW_SSE2 +#define HAS_ARGBPOLYNOMIALROW_SSE2 +#define HAS_ARGBQUANTIZEROW_SSE2 +#define HAS_ARGBSEPIAROW_SSSE3 +#define HAS_ARGBSHADEROW_SSE2 +#define HAS_ARGBSUBTRACTROW_SSE2 +#define HAS_ARGBUNATTENUATEROW_SSE2 +#define HAS_BLENDPLANEROW_SSSE3 +#define HAS_COMPUTECUMULATIVESUMROW_SSE2 +#define HAS_CUMULATIVESUMTOAVERAGEROW_SSE2 +#define HAS_INTERPOLATEROW_SSSE3 +#define HAS_RGBCOLORTABLEROW_X86 +#define HAS_SOBELROW_SSE2 +#define HAS_SOBELTOPLANEROW_SSE2 +#define HAS_SOBELXROW_SSE2 +#define HAS_SOBELXYROW_SSE2 +#define HAS_SOBELYROW_SSE2 + +// The following functions fail on gcc/clang 32 bit with fpic and framepointer. +// caveat: clangcl uses row_win.cc which works. +#if defined(__x86_64__) || !defined(__pic__) || defined(__clang__) || \ + defined(_MSC_VER) +// TODO(fbarchard): fix build error on android_full_debug=1 +// https://code.google.com/p/libyuv/issues/detail?id=517 +#define HAS_I422ALPHATOARGBROW_SSSE3 +#endif +#endif + +// The following are available on all x86 platforms, but +// require VS2012, clang 3.4 or gcc 4.7. +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2) || \ + defined(GCC_HAS_AVX2)) +#define HAS_ARGBCOPYALPHAROW_AVX2 +#define HAS_ARGBCOPYYTOALPHAROW_AVX2 +#define HAS_ARGBEXTRACTALPHAROW_AVX2 +#define HAS_ARGBMIRRORROW_AVX2 +#define HAS_ARGBPOLYNOMIALROW_AVX2 +#define HAS_ARGBSHUFFLEROW_AVX2 +#define HAS_ARGBTORGB565DITHERROW_AVX2 +#define HAS_ARGBTOUVJROW_AVX2 +#define HAS_ARGBTOUVROW_AVX2 +#define HAS_ARGBTOYJROW_AVX2 +#define HAS_ARGBTOYROW_AVX2 +#define HAS_RGB24TOYJROW_AVX2 +#define HAS_RAWTOYJROW_AVX2 +#define HAS_COPYROW_AVX +#define HAS_H422TOARGBROW_AVX2 +#define HAS_HALFFLOATROW_AVX2 +// #define HAS_HALFFLOATROW_F16C // Enable to test halffloat cast +#define HAS_I422TOARGB1555ROW_AVX2 +#define HAS_I422TOARGB4444ROW_AVX2 +#define HAS_I422TOARGBROW_AVX2 +#define HAS_I422TORGB24ROW_AVX2 +#define HAS_I422TORGB565ROW_AVX2 +#define HAS_I422TORGBAROW_AVX2 +#define HAS_I444TOARGBROW_AVX2 +#define HAS_INTERPOLATEROW_AVX2 +#define HAS_J422TOARGBROW_AVX2 +#define HAS_MERGEUVROW_AVX2 +#define HAS_MIRRORROW_AVX2 +#define HAS_NV12TOARGBROW_AVX2 +#define HAS_NV12TORGB24ROW_AVX2 +#define HAS_NV12TORGB565ROW_AVX2 +#define HAS_NV21TOARGBROW_AVX2 +#define HAS_NV21TORGB24ROW_AVX2 +#define HAS_SPLITUVROW_AVX2 +#define HAS_UYVYTOARGBROW_AVX2 +#define HAS_UYVYTOUV422ROW_AVX2 +#define HAS_UYVYTOUVROW_AVX2 +#define HAS_UYVYTOYROW_AVX2 +#define HAS_YUY2TOARGBROW_AVX2 +#define HAS_YUY2TOUV422ROW_AVX2 +#define HAS_YUY2TOUVROW_AVX2 +#define HAS_YUY2TOYROW_AVX2 + +// Effects: +#define HAS_ARGBADDROW_AVX2 +#define HAS_ARGBATTENUATEROW_AVX2 +#define HAS_ARGBMULTIPLYROW_AVX2 +#define HAS_ARGBSUBTRACTROW_AVX2 +#define HAS_ARGBUNATTENUATEROW_AVX2 +#define HAS_BLENDPLANEROW_AVX2 + +#if defined(__x86_64__) || !defined(__pic__) || defined(__clang__) || \ + defined(_MSC_VER) +// TODO(fbarchard): fix build error on android_full_debug=1 +// https://code.google.com/p/libyuv/issues/detail?id=517 +#define HAS_I422ALPHATOARGBROW_AVX2 +#endif +#endif + +// The following are available for AVX2 Visual C and clangcl 32 bit: +// TODO(fbarchard): Port to gcc. +#if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) && \ + (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) +#define HAS_ARGB1555TOARGBROW_AVX2 +#define HAS_ARGB4444TOARGBROW_AVX2 +#define HAS_ARGBTOARGB1555ROW_AVX2 +#define HAS_ARGBTOARGB4444ROW_AVX2 +#define HAS_ARGBTORGB565ROW_AVX2 +#define HAS_J400TOARGBROW_AVX2 +#define HAS_RGB565TOARGBROW_AVX2 +#endif + +// The following are also available on x64 Visual C. +#if !defined(LIBYUV_DISABLE_X86) && defined(_MSC_VER) && defined(_M_X64) && \ + (!defined(__clang__) || defined(__SSSE3__)) +#define HAS_I422ALPHATOARGBROW_SSSE3 +#define HAS_I422TOARGBROW_SSSE3 +#endif + +// The following are available for gcc/clang x86 platforms: +// TODO(fbarchard): Port to Visual C +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) +#define HAS_ABGRTOAR30ROW_SSSE3 +#define HAS_ARGBTOAR30ROW_SSSE3 +#define HAS_CONVERT16TO8ROW_SSSE3 +#define HAS_CONVERT8TO16ROW_SSE2 +#define HAS_HALFMERGEUVROW_SSSE3 +#define HAS_I210TOAR30ROW_SSSE3 +#define HAS_I210TOARGBROW_SSSE3 +#define HAS_I400TOARGBROW_SSE2 +#define HAS_I422TOAR30ROW_SSSE3 +#define HAS_MERGERGBROW_SSSE3 +#define HAS_MIRRORUVROW_AVX2 +#define HAS_MIRRORUVROW_SSSE3 +#define HAS_RAWTORGBAROW_SSSE3 +#define HAS_RGB24MIRRORROW_SSSE3 +#define HAS_RGBATOYJROW_SSSE3 +#define HAS_SPLITRGBROW_SSSE3 +#define HAS_SWAPUVROW_SSSE3 +#endif + +// The following are available for AVX2 gcc/clang x86 platforms: +// TODO(fbarchard): Port to Visual C +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) && \ + (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) +#define HAS_ABGRTOAR30ROW_AVX2 +#define HAS_ABGRTOUVROW_AVX2 +#define HAS_ABGRTOYROW_AVX2 +#define HAS_ARGBTOAR30ROW_AVX2 +#define HAS_ARGBTORAWROW_AVX2 +#define HAS_ARGBTORGB24ROW_AVX2 +#define HAS_CONVERT16TO8ROW_AVX2 +#define HAS_CONVERT8TO16ROW_AVX2 +#define HAS_HALFMERGEUVROW_AVX2 +#define HAS_I210TOAR30ROW_AVX2 +#define HAS_I210TOARGBROW_AVX2 +#define HAS_I400TOARGBROW_AVX2 +#define HAS_I422TOAR30ROW_AVX2 +#define HAS_I422TOUYVYROW_AVX2 +#define HAS_I422TOYUY2ROW_AVX2 +#define HAS_MERGEUVROW_16_AVX2 +#define HAS_MULTIPLYROW_16_AVX2 +#define HAS_RGBATOYJROW_AVX2 +#define HAS_SWAPUVROW_AVX2 +// TODO(fbarchard): Fix AVX2 version of YUV24 +// #define HAS_NV21TOYUV24ROW_AVX2 +#endif + +// The following are available for AVX512 clang x86 platforms: +// TODO(fbarchard): Port to GCC and Visual C +// TODO(fbarchard): re-enable HAS_ARGBTORGB24ROW_AVX512VBMI. Issue libyuv:789 +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) && \ + (defined(CLANG_HAS_AVX512)) +#define HAS_ARGBTORGB24ROW_AVX512VBMI +#endif + +// The following are available on Neon platforms: +#if !defined(LIBYUV_DISABLE_NEON) && \ + (defined(__aarch64__) || defined(__ARM_NEON__) || defined(LIBYUV_NEON)) +#define HAS_ABGRTOUVROW_NEON +#define HAS_ABGRTOYROW_NEON +#define HAS_ARGB1555TOARGBROW_NEON +#define HAS_ARGB1555TOUVROW_NEON +#define HAS_ARGB1555TOYROW_NEON +#define HAS_ARGB4444TOARGBROW_NEON +#define HAS_ARGB4444TOUVROW_NEON +#define HAS_ARGB4444TOYROW_NEON +#define HAS_ARGBEXTRACTALPHAROW_NEON +#define HAS_ARGBSETROW_NEON +#define HAS_ARGBTOARGB1555ROW_NEON +#define HAS_ARGBTOARGB4444ROW_NEON +#define HAS_ARGBTORAWROW_NEON +#define HAS_ARGBTORGB24ROW_NEON +#define HAS_ARGBTORGB565DITHERROW_NEON +#define HAS_ARGBTORGB565ROW_NEON +#define HAS_ARGBTOUV444ROW_NEON +#define HAS_ARGBTOUVJROW_NEON +#define HAS_ARGBTOUVROW_NEON +#define HAS_ARGBTOYJROW_NEON +#define HAS_ARGBTOYROW_NEON +#define HAS_AYUVTOUVROW_NEON +#define HAS_AYUVTOVUROW_NEON +#define HAS_AYUVTOYROW_NEON +#define HAS_BGRATOUVROW_NEON +#define HAS_BGRATOYROW_NEON +#define HAS_BYTETOFLOATROW_NEON +#define HAS_COPYROW_NEON +#define HAS_HALFFLOATROW_NEON +#define HAS_HALFMERGEUVROW_NEON +#define HAS_I400TOARGBROW_NEON +#define HAS_I422ALPHATOARGBROW_NEON +#define HAS_I422TOARGB1555ROW_NEON +#define HAS_I422TOARGB4444ROW_NEON +#define HAS_I422TOARGBROW_NEON +#define HAS_I422TORGB24ROW_NEON +#define HAS_I422TORGB565ROW_NEON +#define HAS_I422TORGBAROW_NEON +#define HAS_I422TOUYVYROW_NEON +#define HAS_I422TOYUY2ROW_NEON +#define HAS_I444TOARGBROW_NEON +#define HAS_J400TOARGBROW_NEON +#define HAS_MERGEUVROW_NEON +#define HAS_MIRRORROW_NEON +#define HAS_MIRRORUVROW_NEON +#define HAS_MIRRORSPLITUVROW_NEON +#define HAS_NV12TOARGBROW_NEON +#define HAS_NV12TORGB24ROW_NEON +#define HAS_NV12TORGB565ROW_NEON +#define HAS_NV21TOARGBROW_NEON +#define HAS_NV21TORGB24ROW_NEON +#define HAS_NV21TOYUV24ROW_NEON +#define HAS_RAWTOARGBROW_NEON +#define HAS_RAWTORGB24ROW_NEON +#define HAS_RAWTORGBAROW_NEON +#define HAS_RAWTOUVROW_NEON +#define HAS_RAWTOYJROW_NEON +#define HAS_RAWTOYROW_NEON +#define HAS_RGB24TOARGBROW_NEON +#define HAS_RGB24TOUVROW_NEON +#define HAS_RGB24TOYJROW_NEON +#define HAS_RGB24TOYROW_NEON +#define HAS_RGB565TOARGBROW_NEON +#define HAS_RGB565TOUVROW_NEON +#define HAS_RGB565TOYROW_NEON +#define HAS_RGBATOUVROW_NEON +#define HAS_RGBATOYJROW_NEON +#define HAS_RGBATOYROW_NEON +#define HAS_SETROW_NEON +#define HAS_SPLITRGBROW_NEON +#define HAS_SPLITUVROW_NEON +#define HAS_SWAPUVROW_NEON +#define HAS_UYVYTOARGBROW_NEON +#define HAS_UYVYTOUV422ROW_NEON +#define HAS_UYVYTOUVROW_NEON +#define HAS_UYVYTOYROW_NEON +#define HAS_YUY2TOARGBROW_NEON +#define HAS_YUY2TOUV422ROW_NEON +#define HAS_YUY2TOUVROW_NEON +#define HAS_YUY2TOYROW_NEON + +// Effects: +#define HAS_ARGBADDROW_NEON +#define HAS_ARGBATTENUATEROW_NEON +#define HAS_ARGBBLENDROW_NEON +#define HAS_ARGBCOLORMATRIXROW_NEON +#define HAS_ARGBGRAYROW_NEON +#define HAS_ARGBMIRRORROW_NEON +#define HAS_RGB24MIRRORROW_NEON +#define HAS_ARGBMULTIPLYROW_NEON +#define HAS_ARGBQUANTIZEROW_NEON +#define HAS_ARGBSEPIAROW_NEON +#define HAS_ARGBSHADEROW_NEON +#define HAS_ARGBSHUFFLEROW_NEON +#define HAS_ARGBSUBTRACTROW_NEON +#define HAS_INTERPOLATEROW_NEON +#define HAS_SOBELROW_NEON +#define HAS_SOBELTOPLANEROW_NEON +#define HAS_SOBELXROW_NEON +#define HAS_SOBELXYROW_NEON +#define HAS_SOBELYROW_NEON +#endif + +// The following are available on AArch64 platforms: +#if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__) +#define HAS_SCALESUMSAMPLES_NEON +#define HAS_GAUSSROW_F32_NEON +#define HAS_GAUSSCOL_F32_NEON + +#endif +#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) +#define HAS_ABGRTOUVROW_MSA +#define HAS_ABGRTOYROW_MSA +#define HAS_ARGB1555TOARGBROW_MSA +#define HAS_ARGB1555TOUVROW_MSA +#define HAS_ARGB1555TOYROW_MSA +#define HAS_ARGB4444TOARGBROW_MSA +#define HAS_ARGBADDROW_MSA +#define HAS_ARGBATTENUATEROW_MSA +#define HAS_ARGBBLENDROW_MSA +#define HAS_ARGBCOLORMATRIXROW_MSA +#define HAS_ARGBEXTRACTALPHAROW_MSA +#define HAS_ARGBGRAYROW_MSA +#define HAS_ARGBMIRRORROW_MSA +#define HAS_ARGBMULTIPLYROW_MSA +#define HAS_ARGBQUANTIZEROW_MSA +#define HAS_ARGBSEPIAROW_MSA +#define HAS_ARGBSETROW_MSA +#define HAS_ARGBSHADEROW_MSA +#define HAS_ARGBSHUFFLEROW_MSA +#define HAS_ARGBSUBTRACTROW_MSA +#define HAS_ARGBTOARGB1555ROW_MSA +#define HAS_ARGBTOARGB4444ROW_MSA +#define HAS_ARGBTORAWROW_MSA +#define HAS_ARGBTORGB24ROW_MSA +#define HAS_ARGBTORGB565DITHERROW_MSA +#define HAS_ARGBTORGB565ROW_MSA +#define HAS_ARGBTOUV444ROW_MSA +#define HAS_ARGBTOUVJROW_MSA +#define HAS_ARGBTOUVROW_MSA +#define HAS_ARGBTOYJROW_MSA +#define HAS_ARGBTOYROW_MSA +#define HAS_BGRATOUVROW_MSA +#define HAS_BGRATOYROW_MSA +#define HAS_HALFFLOATROW_MSA +#define HAS_I400TOARGBROW_MSA +#define HAS_I422ALPHATOARGBROW_MSA +#define HAS_I422TOARGBROW_MSA +#define HAS_I422TORGB24ROW_MSA +#define HAS_I422TORGBAROW_MSA +#define HAS_I422TOUYVYROW_MSA +#define HAS_I422TOYUY2ROW_MSA +#define HAS_I444TOARGBROW_MSA +#define HAS_I422TOARGB1555ROW_MSA +#define HAS_I422TORGB565ROW_MSA +#define HAS_INTERPOLATEROW_MSA +#define HAS_J400TOARGBROW_MSA +#define HAS_MERGEUVROW_MSA +#define HAS_MIRRORROW_MSA +#define HAS_MIRRORUVROW_MSA +#define HAS_MIRRORSPLITUVROW_MSA +#define HAS_NV12TOARGBROW_MSA +#define HAS_NV12TORGB565ROW_MSA +#define HAS_NV21TOARGBROW_MSA +#define HAS_RAWTOARGBROW_MSA +#define HAS_RAWTORGB24ROW_MSA +#define HAS_RAWTOUVROW_MSA +#define HAS_RAWTOYROW_MSA +#define HAS_RGB24TOARGBROW_MSA +#define HAS_RGB24TOUVROW_MSA +#define HAS_RGB24TOYROW_MSA +#define HAS_RGB565TOARGBROW_MSA +#define HAS_RGB565TOUVROW_MSA +#define HAS_RGB565TOYROW_MSA +#define HAS_RGBATOUVROW_MSA +#define HAS_RGBATOYROW_MSA +#define HAS_SETROW_MSA +#define HAS_SOBELROW_MSA +#define HAS_SOBELTOPLANEROW_MSA +#define HAS_SOBELXROW_MSA +#define HAS_SOBELXYROW_MSA +#define HAS_SOBELYROW_MSA +#define HAS_SPLITUVROW_MSA +#define HAS_UYVYTOARGBROW_MSA +#define HAS_UYVYTOUVROW_MSA +#define HAS_UYVYTOYROW_MSA +#define HAS_YUY2TOARGBROW_MSA +#define HAS_YUY2TOUV422ROW_MSA +#define HAS_YUY2TOUVROW_MSA +#define HAS_YUY2TOYROW_MSA +#endif + +#if !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A) +#define HAS_ABGRTOUVROW_MMI +#define HAS_ABGRTOYROW_MMI +#define HAS_ARGB1555TOARGBROW_MMI +#define HAS_ARGB1555TOUVROW_MMI +#define HAS_ARGB1555TOYROW_MMI +#define HAS_ARGB4444TOARGBROW_MMI +#define HAS_ARGB4444TOUVROW_MMI +#define HAS_ARGB4444TOYROW_MMI +#define HAS_ARGBADDROW_MMI +#define HAS_ARGBATTENUATEROW_MMI +#define HAS_ARGBBLENDROW_MMI +#define HAS_ARGBCOLORMATRIXROW_MMI +#define HAS_ARGBCOPYALPHAROW_MMI +#define HAS_ARGBCOPYYTOALPHAROW_MMI +#define HAS_ARGBEXTRACTALPHAROW_MMI +#define HAS_ARGBGRAYROW_MMI +#define HAS_ARGBMIRRORROW_MMI +#define HAS_ARGBMULTIPLYROW_MMI +#define HAS_ARGBSEPIAROW_MMI +#define HAS_ARGBSETROW_MMI +#define HAS_ARGBSHADEROW_MMI +#define HAS_ARGBSHUFFLEROW_MMI +#define HAS_ARGBSUBTRACTROW_MMI +#define HAS_ARGBTOARGB1555ROW_MMI +#define HAS_ARGBTOARGB4444ROW_MMI +#define HAS_ARGBTORAWROW_MMI +#define HAS_ARGBTORGB24ROW_MMI +#define HAS_ARGBTORGB565DITHERROW_MMI +#define HAS_ARGBTORGB565ROW_MMI +#define HAS_ARGBTOUV444ROW_MMI +#define HAS_ARGBTOUVJROW_MMI +#define HAS_ARGBTOUVROW_MMI +#define HAS_ARGBTOYJROW_MMI +#define HAS_ARGBTOYROW_MMI +#define HAS_BGRATOUVROW_MMI +#define HAS_BGRATOYROW_MMI +#define HAS_BLENDPLANEROW_MMI +#define HAS_COMPUTECUMULATIVESUMROW_MMI +#define HAS_CUMULATIVESUMTOAVERAGEROW_MMI +#define HAS_HALFFLOATROW_MMI +#define HAS_I400TOARGBROW_MMI +#define HAS_I422TOUYVYROW_MMI +#define HAS_I422TOYUY2ROW_MMI +#define HAS_I422TOARGBROW_MMI +#define HAS_I444TOARGBROW_MMI +#define HAS_INTERPOLATEROW_MMI +#define HAS_J400TOARGBROW_MMI +#define HAS_MERGERGBROW_MMI +#define HAS_MERGEUVROW_MMI +#define HAS_MIRRORROW_MMI +#define HAS_MIRRORSPLITUVROW_MMI +#define HAS_RAWTOARGBROW_MMI +#define HAS_RAWTORGB24ROW_MMI +#define HAS_RAWTOUVROW_MMI +#define HAS_RAWTOYROW_MMI +#define HAS_RGB24TOARGBROW_MMI +#define HAS_RGB24TOUVROW_MMI +#define HAS_RGB24TOYROW_MMI +#define HAS_RGB565TOARGBROW_MMI +#define HAS_RGB565TOUVROW_MMI +#define HAS_RGB565TOYROW_MMI +#define HAS_RGBATOUVROW_MMI +#define HAS_RGBATOYROW_MMI +#define HAS_SOBELROW_MMI +#define HAS_SOBELTOPLANEROW_MMI +#define HAS_SOBELXROW_MMI +#define HAS_SOBELXYROW_MMI +#define HAS_SOBELYROW_MMI +#define HAS_SPLITRGBROW_MMI +#define HAS_SPLITUVROW_MMI +#define HAS_UYVYTOUVROW_MMI +#define HAS_UYVYTOYROW_MMI +#define HAS_YUY2TOUV422ROW_MMI +#define HAS_YUY2TOUVROW_MMI +#define HAS_YUY2TOYROW_MMI +#define HAS_I210TOARGBROW_MMI +#define HAS_I422TOARGB4444ROW_MMI +#define HAS_I422TOARGB1555ROW_MMI +#define HAS_I422TORGB565ROW_MMI +#define HAS_NV21TORGB24ROW_MMI +#define HAS_NV12TORGB24ROW_MMI +#define HAS_I422ALPHATOARGBROW_MMI +#define HAS_I422TORGB24ROW_MMI +#define HAS_NV12TOARGBROW_MMI +#define HAS_NV21TOARGBROW_MMI +#define HAS_NV12TORGB565ROW_MMI +#define HAS_YUY2TOARGBROW_MMI +#define HAS_UYVYTOARGBROW_MMI +#define HAS_I422TORGBAROW_MMI +#endif + +#if defined(_MSC_VER) && !defined(__CLR_VER) && !defined(__clang__) +#if defined(VISUALC_HAS_AVX2) +#define SIMD_ALIGNED(var) __declspec(align(32)) var +#else +#define SIMD_ALIGNED(var) __declspec(align(16)) var +#endif +typedef __declspec(align(16)) int16_t vec16[8]; +typedef __declspec(align(16)) int32_t vec32[4]; +typedef __declspec(align(16)) float vecf32[4]; +typedef __declspec(align(16)) int8_t vec8[16]; +typedef __declspec(align(16)) uint16_t uvec16[8]; +typedef __declspec(align(16)) uint32_t uvec32[4]; +typedef __declspec(align(16)) uint8_t uvec8[16]; +typedef __declspec(align(32)) int16_t lvec16[16]; +typedef __declspec(align(32)) int32_t lvec32[8]; +typedef __declspec(align(32)) int8_t lvec8[32]; +typedef __declspec(align(32)) uint16_t ulvec16[16]; +typedef __declspec(align(32)) uint32_t ulvec32[8]; +typedef __declspec(align(32)) uint8_t ulvec8[32]; +#elif !defined(__pnacl__) && (defined(__GNUC__) || defined(__clang__)) +// Caveat GCC 4.2 to 4.7 have a known issue using vectors with const. +#if defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2) +#define SIMD_ALIGNED(var) var __attribute__((aligned(32))) +#else +#define SIMD_ALIGNED(var) var __attribute__((aligned(16))) +#endif +typedef int16_t __attribute__((vector_size(16))) vec16; +typedef int32_t __attribute__((vector_size(16))) vec32; +typedef float __attribute__((vector_size(16))) vecf32; +typedef int8_t __attribute__((vector_size(16))) vec8; +typedef uint16_t __attribute__((vector_size(16))) uvec16; +typedef uint32_t __attribute__((vector_size(16))) uvec32; +typedef uint8_t __attribute__((vector_size(16))) uvec8; +typedef int16_t __attribute__((vector_size(32))) lvec16; +typedef int32_t __attribute__((vector_size(32))) lvec32; +typedef int8_t __attribute__((vector_size(32))) lvec8; +typedef uint16_t __attribute__((vector_size(32))) ulvec16; +typedef uint32_t __attribute__((vector_size(32))) ulvec32; +typedef uint8_t __attribute__((vector_size(32))) ulvec8; +#else +#define SIMD_ALIGNED(var) var +typedef int16_t vec16[8]; +typedef int32_t vec32[4]; +typedef float vecf32[4]; +typedef int8_t vec8[16]; +typedef uint16_t uvec16[8]; +typedef uint32_t uvec32[4]; +typedef uint8_t uvec8[16]; +typedef int16_t lvec16[16]; +typedef int32_t lvec32[8]; +typedef int8_t lvec8[32]; +typedef uint16_t ulvec16[16]; +typedef uint32_t ulvec32[8]; +typedef uint8_t ulvec8[32]; +#endif + +#if defined(__aarch64__) +// This struct is for Arm64 color conversion. +struct YuvConstants { + uvec16 kUVToRB; + uvec16 kUVToRB2; + uvec16 kUVToG; + uvec16 kUVToG2; + vec16 kUVBiasBGR; + vec32 kYToRgb; +}; +#elif defined(__arm__) +// This struct is for ArmV7 color conversion. +struct YuvConstants { + uvec8 kUVToRB; + uvec8 kUVToG; + vec16 kUVBiasBGR; + vec32 kYToRgb; +}; +#else +// This struct is for Intel color conversion. +struct YuvConstants { + int8_t kUVToB[32]; + int8_t kUVToG[32]; + int8_t kUVToR[32]; + int16_t kUVBiasB[16]; + int16_t kUVBiasG[16]; + int16_t kUVBiasR[16]; + int16_t kYToRgb[16]; + int16_t kYBiasToRgb[16]; +}; + +// Offsets into YuvConstants structure +#define KUVTOB 0 +#define KUVTOG 32 +#define KUVTOR 64 +#define KUVBIASB 96 +#define KUVBIASG 128 +#define KUVBIASR 160 +#define KYTORGB 192 +#define KYBIASTORGB 224 + +#endif + +#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a)-1))) + +#define align_buffer_64(var, size) \ + uint8_t* var##_mem = (uint8_t*)(malloc((size) + 63)); /* NOLINT */ \ + uint8_t* var = (uint8_t*)(((intptr_t)(var##_mem) + 63) & ~63) /* NOLINT */ + +#define free_aligned_buffer_64(var) \ + free(var##_mem); \ + var = 0 + +#if defined(__APPLE__) || defined(__x86_64__) || defined(__llvm__) +#define OMITFP +#else +#define OMITFP __attribute__((optimize("omit-frame-pointer"))) +#endif + +// NaCL macros for GCC x86 and x64. +#if defined(__native_client__) +#define LABELALIGN ".p2align 5\n" +#else +#define LABELALIGN +#endif + +// Intel Code Analizer markers. Insert IACA_START IACA_END around code to be +// measured and then run with iaca -64 libyuv_unittest. +// IACA_ASM_START amd IACA_ASM_END are equivalents that can be used within +// inline assembly blocks. +// example of iaca: +// ~/iaca-lin64/bin/iaca.sh -64 -analysis LATENCY out/Release/libyuv_unittest + +#if defined(__x86_64__) || defined(__i386__) + +#define IACA_ASM_START \ + ".byte 0x0F, 0x0B\n" \ + " movl $111, %%ebx\n" \ + ".byte 0x64, 0x67, 0x90\n" + +#define IACA_ASM_END \ + " movl $222, %%ebx\n" \ + ".byte 0x64, 0x67, 0x90\n" \ + ".byte 0x0F, 0x0B\n" + +#define IACA_SSC_MARK(MARK_ID) \ + __asm__ __volatile__("\n\t movl $" #MARK_ID \ + ", %%ebx" \ + "\n\t .byte 0x64, 0x67, 0x90" \ + : \ + : \ + : "memory"); + +#define IACA_UD_BYTES __asm__ __volatile__("\n\t .byte 0x0F, 0x0B"); + +#else /* Visual C */ +#define IACA_UD_BYTES \ + { __asm _emit 0x0F __asm _emit 0x0B } + +#define IACA_SSC_MARK(x) \ + { __asm mov ebx, x __asm _emit 0x64 __asm _emit 0x67 __asm _emit 0x90 } + +#define IACA_VC64_START __writegsbyte(111, 111); +#define IACA_VC64_END __writegsbyte(222, 222); +#endif + +#define IACA_START \ + { \ + IACA_UD_BYTES \ + IACA_SSC_MARK(111) \ + } +#define IACA_END \ + { \ + IACA_SSC_MARK(222) \ + IACA_UD_BYTES \ + } + +void I444ToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgba, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_NEON(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_NEON(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_NEON(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_NEON(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToYUV24Row_NEON(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_yuv24, + int width); +void YUY2ToARGBRow_NEON(const uint8_t* src_yuy2, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_NEON(const uint8_t* src_uyvy, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); + +void I422ToARGBRow_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_MSA(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_MSA(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_MSA(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_MSA(const uint8_t* src_yuy2, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_MSA(const uint8_t* src_uyvy, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); + +void ARGBToYRow_AVX2(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ARGBToYRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ABGRToYRow_AVX2(const uint8_t* src_abgr, uint8_t* dst_y, int width); +void ABGRToYRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ARGBToYJRow_AVX2(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ARGBToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYJRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYJRow_AVX2(const uint8_t* src_rgba, uint8_t* dst_y, int width); +void RGBAToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYJRow_SSSE3(const uint8_t* src_rgba, uint8_t* dst_y, int width); +void BGRAToYRow_SSSE3(const uint8_t* src_bgra, uint8_t* dst_y, int width); +void ABGRToYRow_SSSE3(const uint8_t* src_abgr, uint8_t* dst_y, int width); +void RGBAToYRow_SSSE3(const uint8_t* src_rgba, uint8_t* dst_y, int width); +void RGB24ToYRow_SSSE3(const uint8_t* src_rgb24, uint8_t* dst_y, int width); +void RGB24ToYJRow_SSSE3(const uint8_t* src_rgb24, uint8_t* dst_y, int width); +void RAWToYRow_SSSE3(const uint8_t* src_raw, uint8_t* dst_y, int width); +void RAWToYJRow_SSSE3(const uint8_t* src_raw, uint8_t* dst_y, int width); +void RGB24ToYJRow_AVX2(const uint8_t* src_rgb24, uint8_t* dst_y, int width); +void RAWToYJRow_AVX2(const uint8_t* src_raw, uint8_t* dst_y, int width); +void ARGBToYRow_NEON(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ARGBToYJRow_NEON(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYJRow_NEON(const uint8_t* src_rgba, uint8_t* dst_y, int width); +void ARGBToYRow_MSA(const uint8_t* src_argb0, uint8_t* dst_y, int width); +void ARGBToYJRow_MSA(const uint8_t* src_argb0, uint8_t* dst_y, int width); +void ARGBToYRow_MMI(const uint8_t* src_argb0, uint8_t* dst_y, int width); +void ARGBToYJRow_MMI(const uint8_t* src_argb0, uint8_t* dst_y, int width); +void ARGBToUV444Row_NEON(const uint8_t* src_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_NEON(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_MSA(const uint8_t* src_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_MSA(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_MMI(const uint8_t* src_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_MMI(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_NEON(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_NEON(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_NEON(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_NEON(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_NEON(const uint8_t* src_rgb24, + int src_stride_rgb24, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_NEON(const uint8_t* src_raw, + int src_stride_raw, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_NEON(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_NEON(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB4444ToUVRow_NEON(const uint8_t* src_argb4444, + int src_stride_argb4444, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_MSA(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_MSA(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_MSA(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_MMI(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_MMI(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_MMI(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB4444ToUVRow_MMI(const uint8_t* src_argb4444, + int src_stride_argb4444, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToYRow_NEON(const uint8_t* src_bgra, uint8_t* dst_y, int width); +void ABGRToYRow_NEON(const uint8_t* src_abgr, uint8_t* dst_y, int width); +void RGBAToYRow_NEON(const uint8_t* src_rgba, uint8_t* dst_y, int width); +void RGB24ToYRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_y, int width); +void RGB24ToYJRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_yj, int width); +void RAWToYRow_NEON(const uint8_t* src_raw, uint8_t* dst_y, int width); +void RAWToYJRow_NEON(const uint8_t* src_raw, uint8_t* dst_yj, int width); +void RGB565ToYRow_NEON(const uint8_t* src_rgb565, uint8_t* dst_y, int width); +void ARGB1555ToYRow_NEON(const uint8_t* src_argb1555, + uint8_t* dst_y, + int width); +void ARGB4444ToYRow_NEON(const uint8_t* src_argb4444, + uint8_t* dst_y, + int width); +void BGRAToYRow_MSA(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ABGRToYRow_MSA(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYRow_MSA(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB24ToYRow_MSA(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RAWToYRow_MSA(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB565ToYRow_MSA(const uint8_t* src_rgb565, uint8_t* dst_y, int width); +void ARGB1555ToYRow_MSA(const uint8_t* src_argb1555, uint8_t* dst_y, int width); +void BGRAToYRow_MMI(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ABGRToYRow_MMI(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYRow_MMI(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB24ToYRow_MMI(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RAWToYRow_MMI(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB565ToYRow_MMI(const uint8_t* src_rgb565, uint8_t* dst_y, int width); +void ARGB1555ToYRow_MMI(const uint8_t* src_argb1555, uint8_t* dst_y, int width); +void ARGB4444ToYRow_MMI(const uint8_t* src_argb4444, uint8_t* dst_y, int width); + +void ARGBToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ARGBToYJRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYJRow_C(const uint8_t* src_argb0, uint8_t* dst_y, int width); +void BGRAToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void ABGRToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGBAToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB24ToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RGB24ToYJRow_C(const uint8_t* src_argb, uint8_t* dst_yj, int width); +void RAWToYRow_C(const uint8_t* src_argb, uint8_t* dst_y, int width); +void RAWToYJRow_C(const uint8_t* src_argb, uint8_t* dst_yj, int width); +void RGB565ToYRow_C(const uint8_t* src_rgb565, uint8_t* dst_y, int width); +void ARGB1555ToYRow_C(const uint8_t* src_argb1555, uint8_t* dst_y, int width); +void ARGB4444ToYRow_C(const uint8_t* src_argb4444, uint8_t* dst_y, int width); +void ARGBToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void BGRAToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ABGRToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYJRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYJRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYJRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void BGRAToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ABGRToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYJRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYJRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB565ToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGB1555ToYRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToYRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void BGRAToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ABGRToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYJRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB565ToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGB1555ToYRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void BGRAToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ABGRToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGBAToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYJRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB24ToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB565ToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGB1555ToYRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToYRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBToUVRow_AVX2(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_AVX2(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_AVX2(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_SSSE3(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_SSSE3(const uint8_t* src_argb, + int src_stride_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_SSSE3(const uint8_t* src_bgra, + int src_stride_bgra, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_SSSE3(const uint8_t* src_abgr, + int src_stride_abgr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_SSSE3(const uint8_t* src_rgba, + int src_stride_rgba, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_Any_AVX2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_Any_AVX2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_Any_AVX2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_Any_SSSE3(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_Any_SSSE3(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_Any_SSSE3(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_Any_SSSE3(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_Any_SSSE3(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB4444ToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB4444ToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUVJRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void BGRAToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ABGRToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGBAToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB24ToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RAWToUVRow_C(const uint8_t* src_rgb, + int src_stride_rgb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void RGB565ToUVRow_C(const uint8_t* src_rgb565, + int src_stride_rgb565, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB1555ToUVRow_C(const uint8_t* src_argb1555, + int src_stride_argb1555, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGB4444ToUVRow_C(const uint8_t* src_argb4444, + int src_stride_argb4444, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void ARGBToUV444Row_SSSE3(const uint8_t* src_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void ARGBToUV444Row_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void ARGBToUV444Row_C(const uint8_t* src_argb, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void MirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_SSSE3(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_MSA(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_MMI(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_C(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorRow_Any_SSE2(const uint8_t* src, uint8_t* dst, int width); +void MirrorRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_uv, int width); +void MirrorUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_uv, int width); +void MirrorUVRow_NEON(const uint8_t* src_uv, uint8_t* dst_uv, int width); +void MirrorUVRow_MSA(const uint8_t* src_uv, uint8_t* dst_uv, int width); +void MirrorUVRow_C(const uint8_t* src_uv, uint8_t* dst_uv, int width); +void MirrorUVRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorUVRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorUVRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void MirrorUVRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); + +void MirrorSplitUVRow_SSSE3(const uint8_t* src, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void MirrorSplitUVRow_NEON(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void MirrorSplitUVRow_MSA(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void MirrorSplitUVRow_MMI(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void MirrorSplitUVRow_C(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void ARGBMirrorRow_AVX2(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_MSA(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_MMI(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_C(const uint8_t* src, uint8_t* dst, int width); +void ARGBMirrorRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBMirrorRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBMirrorRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBMirrorRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBMirrorRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); + +void RGB24MirrorRow_SSSE3(const uint8_t* src, uint8_t* dst, int width); +void RGB24MirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width); +void RGB24MirrorRow_C(const uint8_t* src, uint8_t* dst, int width); +void RGB24MirrorRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB24MirrorRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void SplitUVRow_C(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_SSE2(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_AVX2(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_NEON(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_MSA(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_MMI(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SplitUVRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void MergeUVRow_C(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_SSE2(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_AVX2(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_NEON(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_MSA(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_MMI(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width); +void MergeUVRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void MergeUVRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void MergeUVRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void MergeUVRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void MergeUVRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); + +void HalfMergeUVRow_C(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int width); + +void HalfMergeUVRow_NEON(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int width); + +void HalfMergeUVRow_SSSE3(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int width); + +void HalfMergeUVRow_AVX2(const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint8_t* dst_uv, + int width); + +void SplitRGBRow_C(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_SSSE3(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_NEON(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_MMI(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); +void SplitRGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width); + +void MergeRGBRow_C(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); +void MergeRGBRow_SSSE3(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); +void MergeRGBRow_NEON(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); +void MergeRGBRow_MMI(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); +void MergeRGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void MergeRGBRow_Any_NEON(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); +void MergeRGBRow_Any_MMI(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width); + +void MergeUVRow_16_C(const uint16_t* src_u, + const uint16_t* src_v, + uint16_t* dst_uv, + int scale, /* 64 for 10 bit */ + int width); +void MergeUVRow_16_AVX2(const uint16_t* src_u, + const uint16_t* src_v, + uint16_t* dst_uv, + int scale, + int width); + +void MultiplyRow_16_AVX2(const uint16_t* src_y, + uint16_t* dst_y, + int scale, + int width); +void MultiplyRow_16_C(const uint16_t* src_y, + uint16_t* dst_y, + int scale, + int width); + +void Convert8To16Row_C(const uint8_t* src_y, + uint16_t* dst_y, + int scale, + int width); +void Convert8To16Row_SSE2(const uint8_t* src_y, + uint16_t* dst_y, + int scale, + int width); +void Convert8To16Row_AVX2(const uint8_t* src_y, + uint16_t* dst_y, + int scale, + int width); +void Convert8To16Row_Any_SSE2(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int scale, + int width); +void Convert8To16Row_Any_AVX2(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int scale, + int width); + +void Convert16To8Row_C(const uint16_t* src_y, + uint8_t* dst_y, + int scale, + int width); +void Convert16To8Row_SSSE3(const uint16_t* src_y, + uint8_t* dst_y, + int scale, + int width); +void Convert16To8Row_AVX2(const uint16_t* src_y, + uint8_t* dst_y, + int scale, + int width); +void Convert16To8Row_Any_SSSE3(const uint16_t* src_ptr, + uint8_t* dst_ptr, + int scale, + int width); +void Convert16To8Row_Any_AVX2(const uint16_t* src_ptr, + uint8_t* dst_ptr, + int scale, + int width); + +void CopyRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void CopyRow_AVX(const uint8_t* src, uint8_t* dst, int width); +void CopyRow_ERMS(const uint8_t* src, uint8_t* dst, int width); +void CopyRow_NEON(const uint8_t* src, uint8_t* dst, int width); +void CopyRow_MIPS(const uint8_t* src, uint8_t* dst, int count); +void CopyRow_C(const uint8_t* src, uint8_t* dst, int count); +void CopyRow_Any_SSE2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void CopyRow_Any_AVX(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void CopyRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); + +void CopyRow_16_C(const uint16_t* src, uint16_t* dst, int count); + +void ARGBCopyAlphaRow_C(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyAlphaRow_MMI(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyAlphaRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBCopyAlphaRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBCopyAlphaRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBExtractAlphaRow_C(const uint8_t* src_argb, uint8_t* dst_a, int width); +void ARGBExtractAlphaRow_SSE2(const uint8_t* src_argb, + uint8_t* dst_a, + int width); +void ARGBExtractAlphaRow_AVX2(const uint8_t* src_argb, + uint8_t* dst_a, + int width); +void ARGBExtractAlphaRow_NEON(const uint8_t* src_argb, + uint8_t* dst_a, + int width); +void ARGBExtractAlphaRow_MSA(const uint8_t* src_argb, + uint8_t* dst_a, + int width); +void ARGBExtractAlphaRow_MMI(const uint8_t* src_argb, + uint8_t* dst_a, + int width); +void ARGBExtractAlphaRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBExtractAlphaRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBExtractAlphaRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBExtractAlphaRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBExtractAlphaRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBCopyYToAlphaRow_C(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyYToAlphaRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyYToAlphaRow_AVX2(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyYToAlphaRow_MMI(const uint8_t* src, uint8_t* dst, int width); +void ARGBCopyYToAlphaRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBCopyYToAlphaRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBCopyYToAlphaRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void SetRow_C(uint8_t* dst, uint8_t v8, int width); +void SetRow_MSA(uint8_t* dst, uint8_t v8, int width); +void SetRow_X86(uint8_t* dst, uint8_t v8, int width); +void SetRow_ERMS(uint8_t* dst, uint8_t v8, int width); +void SetRow_NEON(uint8_t* dst, uint8_t v8, int width); +void SetRow_Any_X86(uint8_t* dst_ptr, uint8_t v32, int width); +void SetRow_Any_NEON(uint8_t* dst_ptr, uint8_t v32, int width); + +void ARGBSetRow_C(uint8_t* dst_argb, uint32_t v32, int width); +void ARGBSetRow_X86(uint8_t* dst_argb, uint32_t v32, int width); +void ARGBSetRow_NEON(uint8_t* dst, uint32_t v32, int width); +void ARGBSetRow_Any_NEON(uint8_t* dst_ptr, uint32_t v32, int width); +void ARGBSetRow_MSA(uint8_t* dst_argb, uint32_t v32, int width); +void ARGBSetRow_Any_MSA(uint8_t* dst_ptr, uint32_t v32, int width); +void ARGBSetRow_MMI(uint8_t* dst_argb, uint32_t v32, int width); +void ARGBSetRow_Any_MMI(uint8_t* dst_ptr, uint32_t v32, int width); + +// ARGBShufflers for BGRAToARGB etc. +void ARGBShuffleRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_SSSE3(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_AVX2(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_NEON(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_MSA(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_MMI(const uint8_t* src_argb, + uint8_t* dst_argb, + const uint8_t* shuffler, + int width); +void ARGBShuffleRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint8_t* param, + int width); +void ARGBShuffleRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint8_t* param, + int width); +void ARGBShuffleRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint8_t* param, + int width); +void ARGBShuffleRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint8_t* param, + int width); +void ARGBShuffleRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint8_t* param, + int width); + +void RGB24ToARGBRow_SSSE3(const uint8_t* src_rgb24, + uint8_t* dst_argb, + int width); +void RAWToARGBRow_SSSE3(const uint8_t* src_raw, uint8_t* dst_argb, int width); +void RAWToRGBARow_SSSE3(const uint8_t* src_raw, uint8_t* dst_rgba, int width); +void RAWToRGB24Row_SSSE3(const uint8_t* src_raw, uint8_t* dst_rgb24, int width); +void RGB565ToARGBRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGB1555ToARGBRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGB4444ToARGBRow_SSE2(const uint8_t* src, uint8_t* dst, int width); +void RGB565ToARGBRow_AVX2(const uint8_t* src_rgb565, + uint8_t* dst_argb, + int width); +void ARGB1555ToARGBRow_AVX2(const uint8_t* src_argb1555, + uint8_t* dst_argb, + int width); +void ARGB4444ToARGBRow_AVX2(const uint8_t* src_argb4444, + uint8_t* dst_argb, + int width); + +void RGB24ToARGBRow_NEON(const uint8_t* src_rgb24, + uint8_t* dst_argb, + int width); +void RGB24ToARGBRow_MSA(const uint8_t* src_rgb24, uint8_t* dst_argb, int width); +void RGB24ToARGBRow_MMI(const uint8_t* src_rgb24, uint8_t* dst_argb, int width); +void RAWToARGBRow_NEON(const uint8_t* src_raw, uint8_t* dst_argb, int width); +void RAWToRGBARow_NEON(const uint8_t* src_raw, uint8_t* dst_rgba, int width); +void RAWToARGBRow_MSA(const uint8_t* src_raw, uint8_t* dst_argb, int width); +void RAWToARGBRow_MMI(const uint8_t* src_raw, uint8_t* dst_argb, int width); +void RAWToRGB24Row_NEON(const uint8_t* src_raw, uint8_t* dst_rgb24, int width); +void RAWToRGB24Row_MSA(const uint8_t* src_raw, uint8_t* dst_rgb24, int width); +void RAWToRGB24Row_MMI(const uint8_t* src_raw, uint8_t* dst_rgb24, int width); +void RGB565ToARGBRow_NEON(const uint8_t* src_rgb565, + uint8_t* dst_argb, + int width); +void RGB565ToARGBRow_MSA(const uint8_t* src_rgb565, + uint8_t* dst_argb, + int width); +void RGB565ToARGBRow_MMI(const uint8_t* src_rgb565, + uint8_t* dst_argb, + int width); +void ARGB1555ToARGBRow_NEON(const uint8_t* src_argb1555, + uint8_t* dst_argb, + int width); +void ARGB1555ToARGBRow_MSA(const uint8_t* src_argb1555, + uint8_t* dst_argb, + int width); +void ARGB1555ToARGBRow_MMI(const uint8_t* src_argb1555, + uint8_t* dst_argb, + int width); +void ARGB4444ToARGBRow_NEON(const uint8_t* src_argb4444, + uint8_t* dst_argb, + int width); +void ARGB4444ToARGBRow_MSA(const uint8_t* src_argb4444, + uint8_t* dst_argb, + int width); +void ARGB4444ToARGBRow_MMI(const uint8_t* src_argb4444, + uint8_t* dst_argb, + int width); +void RGB24ToARGBRow_C(const uint8_t* src_rgb24, uint8_t* dst_argb, int width); +void RAWToARGBRow_C(const uint8_t* src_raw, uint8_t* dst_argb, int width); +void RAWToRGBARow_C(const uint8_t* src_raw, uint8_t* dst_rgba, int width); +void RAWToRGB24Row_C(const uint8_t* src_raw, uint8_t* dst_rgb24, int width); +void RGB565ToARGBRow_C(const uint8_t* src_rgb565, uint8_t* dst_argb, int width); +void ARGB1555ToARGBRow_C(const uint8_t* src_argb1555, + uint8_t* dst_argb, + int width); +void ARGB4444ToARGBRow_C(const uint8_t* src_argb4444, + uint8_t* dst_argb, + int width); +void AR30ToARGBRow_C(const uint8_t* src_ar30, uint8_t* dst_argb, int width); +void AR30ToABGRRow_C(const uint8_t* src_ar30, uint8_t* dst_abgr, int width); +void ARGBToAR30Row_C(const uint8_t* src_argb, uint8_t* dst_ar30, int width); +void AR30ToAB30Row_C(const uint8_t* src_ar30, uint8_t* dst_ab30, int width); + +void RGB24ToARGBRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToARGBRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToRGBARow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToRGB24Row_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void RGB565ToARGBRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB1555ToARGBRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToARGBRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB565ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB1555ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void RGB24ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB24ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB24ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToARGBRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToRGBARow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToARGBRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToARGBRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToRGB24Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RAWToRGB24Row_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RAWToRGB24Row_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void RGB565ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB565ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void RGB565ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB1555ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB1555ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB1555ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGB4444ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGB4444ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBToRGB24Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); +void ARGBToRAWRow_SSSE3(const uint8_t* src, uint8_t* dst, int width); +void ARGBToRGB565Row_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGBToARGB1555Row_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ARGBToARGB4444Row_SSE2(const uint8_t* src, uint8_t* dst, int width); +void ABGRToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); +void ARGBToAR30Row_SSSE3(const uint8_t* src, uint8_t* dst, int width); + +void ARGBToRAWRow_AVX2(const uint8_t* src, uint8_t* dst, int width); +void ARGBToRGB24Row_AVX2(const uint8_t* src, uint8_t* dst, int width); + +void ARGBToRGB24Row_AVX512VBMI(const uint8_t* src, uint8_t* dst, int width); + +void ARGBToRGB565DitherRow_C(const uint8_t* src_argb, + uint8_t* dst_rgb, + const uint32_t dither4, + int width); +void ARGBToRGB565DitherRow_SSE2(const uint8_t* src, + uint8_t* dst, + const uint32_t dither4, + int width); +void ARGBToRGB565DitherRow_AVX2(const uint8_t* src, + uint8_t* dst, + const uint32_t dither4, + int width); + +void ARGBToRGB565Row_AVX2(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToARGB1555Row_AVX2(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ARGBToARGB4444Row_AVX2(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ABGRToAR30Row_AVX2(const uint8_t* src, uint8_t* dst, int width); +void ARGBToAR30Row_AVX2(const uint8_t* src, uint8_t* dst, int width); + +void ARGBToRGB24Row_NEON(const uint8_t* src_argb, + uint8_t* dst_rgb24, + int width); +void ARGBToRAWRow_NEON(const uint8_t* src_argb, uint8_t* dst_raw, int width); +void ARGBToRGB565Row_NEON(const uint8_t* src_argb, + uint8_t* dst_rgb565, + int width); +void ARGBToARGB1555Row_NEON(const uint8_t* src_argb, + uint8_t* dst_argb1555, + int width); +void ARGBToARGB4444Row_NEON(const uint8_t* src_argb, + uint8_t* dst_argb4444, + int width); +void ARGBToRGB565DitherRow_NEON(const uint8_t* src_argb, + uint8_t* dst_rgb, + const uint32_t dither4, + int width); +void ARGBToRGB24Row_MSA(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRAWRow_MSA(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRGB565Row_MSA(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToARGB1555Row_MSA(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ARGBToARGB4444Row_MSA(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ARGBToRGB565DitherRow_MSA(const uint8_t* src_argb, + uint8_t* dst_rgb, + const uint32_t dither4, + int width); + +void ARGBToRGB24Row_MMI(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRAWRow_MMI(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRGB565Row_MMI(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToARGB1555Row_MMI(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ARGBToARGB4444Row_MMI(const uint8_t* src_argb, + uint8_t* dst_rgb, + int width); +void ARGBToRGB565DitherRow_MMI(const uint8_t* src_argb, + uint8_t* dst_rgb, + const uint32_t dither4, + int width); + +void ARGBToRGBARow_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRGB24Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRAWRow_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToRGB565Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToARGB1555Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ARGBToARGB4444Row_C(const uint8_t* src_argb, uint8_t* dst_rgb, int width); +void ABGRToAR30Row_C(const uint8_t* src_abgr, uint8_t* dst_ar30, int width); +void ARGBToAR30Row_C(const uint8_t* src_argb, uint8_t* dst_ar30, int width); + +void J400ToARGBRow_SSE2(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_AVX2(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_NEON(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_MSA(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_MMI(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_C(const uint8_t* src_y, uint8_t* dst_argb, int width); +void J400ToARGBRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void J400ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void J400ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void J400ToARGBRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void J400ToARGBRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); + +void I444ToARGBRow_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToAR30Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I210ToAR30Row_C(const uint16_t* src_y, + const uint16_t* src_u, + const uint16_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_C(const uint16_t* src_y, + const uint16_t* src_u, + const uint16_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_C(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_C(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_C(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_C(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_C(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToYUV24Row_C(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_yuv24, + int width); +void YUY2ToARGBRow_C(const uint8_t* src_yuy2, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_C(const uint8_t* src_uyvy, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); + +void I422ToAR30Row_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width); +void I210ToAR30Row_SSSE3(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_SSSE3(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToAR30Row_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_AVX2(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I210ToAR30Row_AVX2(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ar30, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_AVX2(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_AVX2(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToYUV24Row_AVX2(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_yuv24, + int width); +void NV12ToRGB565Row_AVX2(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_SSSE3(const uint8_t* y_buf, + const uint8_t* vu_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_AVX2(const uint8_t* y_buf, + const uint8_t* vu_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_SSSE3(const uint8_t* yuy2_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_SSSE3(const uint8_t* uyvy_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_AVX2(const uint8_t* yuy2_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_AVX2(const uint8_t* uyvy_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_rgba, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_SSSE3(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToAR30Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I210ToAR30Row_Any_SSSE3(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_Any_SSSE3(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToAR30Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_Any_AVX2(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I210ToAR30Row_Any_AVX2(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToYUV24Row_Any_AVX2(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_yuv24, + int width); +void NV12ToRGB565Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); + +void I400ToARGBRow_C(const uint8_t* src_y, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_SSE2(const uint8_t* y_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_AVX2(const uint8_t* y_buf, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_NEON(const uint8_t* src_y, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_MSA(const uint8_t* src_y, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_MMI(const uint8_t* src_y, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I400ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); + +// ARGB preattenuated alpha blend. +void ARGBBlendRow_SSSE3(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBBlendRow_NEON(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBBlendRow_MSA(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBBlendRow_MMI(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBBlendRow_C(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); + +// Unattenuated planar alpha blend. +void BlendPlaneRow_SSSE3(const uint8_t* src0, + const uint8_t* src1, + const uint8_t* alpha, + uint8_t* dst, + int width); +void BlendPlaneRow_Any_SSSE3(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void BlendPlaneRow_AVX2(const uint8_t* src0, + const uint8_t* src1, + const uint8_t* alpha, + uint8_t* dst, + int width); +void BlendPlaneRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void BlendPlaneRow_MMI(const uint8_t* src0, + const uint8_t* src1, + const uint8_t* alpha, + uint8_t* dst, + int width); +void BlendPlaneRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void BlendPlaneRow_C(const uint8_t* src0, + const uint8_t* src1, + const uint8_t* alpha, + uint8_t* dst, + int width); + +// ARGB multiply images. Same API as Blend, but these require +// pointer and width alignment for SSE2. +void ARGBMultiplyRow_C(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_SSE2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBMultiplyRow_AVX2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBMultiplyRow_NEON(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBMultiplyRow_MSA(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBMultiplyRow_MMI(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBMultiplyRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); + +// ARGB add images. +void ARGBAddRow_C(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_SSE2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBAddRow_AVX2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBAddRow_NEON(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBAddRow_MSA(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBAddRow_MMI(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBAddRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); + +// ARGB subtract images. Same API as Blend, but these require +// pointer and width alignment for SSE2. +void ARGBSubtractRow_C(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_SSE2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBSubtractRow_AVX2(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBSubtractRow_NEON(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBSubtractRow_MSA(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void ARGBSubtractRow_MMI(const uint8_t* src_argb0, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width); +void ARGBSubtractRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); + +void ARGBToRGB24Row_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRAWRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB565Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB1555Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB4444Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ABGRToAR30Row_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToAR30Row_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRAWRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToRGB24Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB24Row_Any_AVX512VBMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB565DitherRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint32_t param, + int width); +void ARGBToRGB565DitherRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint32_t param, + int width); + +void ARGBToRGB565Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB1555Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB4444Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ABGRToAR30Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToAR30Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBToRGB24Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRAWRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToRGB565Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB1555Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB4444Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB565DitherRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint32_t param, + int width); +void ARGBToRGB24Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRAWRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToRGB565Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB1555Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB4444Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB565DitherRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint32_t param, + int width); + +void ARGBToRGB24Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRAWRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void ARGBToRGB565Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB1555Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToARGB4444Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBToRGB565DitherRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const uint32_t param, + int width); + +void I444ToARGBRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToYUV24Row_Any_NEON(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_yuv24, + int width); +void NV12ToRGB565Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I444ToARGBRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGBRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); + +void YUY2ToYRow_AVX2(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToUVRow_AVX2(const uint8_t* src_yuy2, + int stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_AVX2(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_SSE2(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToUVRow_SSE2(const uint8_t* src_yuy2, + int stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_SSE2(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_NEON(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToUVRow_NEON(const uint8_t* src_yuy2, + int stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_NEON(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_MSA(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToYRow_MMI(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToUVRow_MSA(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUVRow_MMI(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_MSA(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_MMI(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_C(const uint8_t* src_yuy2, uint8_t* dst_y, int width); +void YUY2ToUVRow_C(const uint8_t* src_yuy2, + int src_stride_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_C(const uint8_t* src_yuy2, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void YUY2ToUVRow_Any_AVX2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_Any_SSE2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void YUY2ToUVRow_Any_SSE2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void YUY2ToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void YUY2ToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void YUY2ToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void YUY2ToUV422Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_AVX2(const uint8_t* src_uyvy, + int stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_SSE2(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_SSE2(const uint8_t* src_uyvy, + int stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_SSE2(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_AVX2(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_AVX2(const uint8_t* src_uyvy, + int stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_AVX2(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_NEON(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_NEON(const uint8_t* src_uyvy, + int stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_NEON(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_MSA(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToYRow_MMI(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_MSA(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUVRow_MMI(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_MSA(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_MMI(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); + +void UYVYToYRow_C(const uint8_t* src_uyvy, uint8_t* dst_y, int width); +void UYVYToUVRow_C(const uint8_t* src_uyvy, + int src_stride_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_C(const uint8_t* src_uyvy, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void UYVYToUVRow_Any_AVX2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_Any_SSE2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void UYVYToUVRow_Any_SSE2(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void UYVYToUVRow_Any_NEON(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToYRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void UYVYToYRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void UYVYToUVRow_Any_MSA(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUVRow_Any_MMI(const uint8_t* src_ptr, + int src_stride_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void UYVYToUV422Row_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_u, + uint8_t* dst_v, + int width); +void SwapUVRow_C(const uint8_t* src_uv, uint8_t* dst_vu, int width); +void SwapUVRow_NEON(const uint8_t* src_uv, uint8_t* dst_vu, int width); +void SwapUVRow_Any_NEON(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void SwapUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_vu, int width); +void SwapUVRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void SwapUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_vu, int width); +void SwapUVRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); +void AYUVToYRow_C(const uint8_t* src_ayuv, uint8_t* dst_y, int width); +void AYUVToUVRow_C(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_uv, + int width); +void AYUVToVURow_C(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_vu, + int width); +void AYUVToYRow_NEON(const uint8_t* src_ayuv, uint8_t* dst_y, int width); +void AYUVToUVRow_NEON(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_uv, + int width); +void AYUVToVURow_NEON(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_vu, + int width); +void AYUVToYRow_Any_NEON(const uint8_t* src_ayuv, uint8_t* dst_y, int width); +void AYUVToUVRow_Any_NEON(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_uv, + int width); +void AYUVToVURow_Any_NEON(const uint8_t* src_ayuv, + int stride_ayuv, + uint8_t* dst_vu, + int width); + +void I422ToYUY2Row_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_frame, + int width); +void I422ToUYVYRow_C(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_frame, + int width); +void I422ToYUY2Row_SSE2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_yuy2, + int width); +void I422ToUYVYRow_SSE2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uyvy, + int width); +void I422ToYUY2Row_Any_SSE2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToUYVYRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToYUY2Row_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_yuy2, + int width); +void I422ToUYVYRow_AVX2(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uyvy, + int width); +void I422ToYUY2Row_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToUYVYRow_Any_AVX2(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToYUY2Row_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_yuy2, + int width); +void I422ToUYVYRow_NEON(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uyvy, + int width); +void I422ToYUY2Row_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToUYVYRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToYUY2Row_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_yuy2, + int width); +void I422ToYUY2Row_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_yuy2, + int width); +void I422ToUYVYRow_MSA(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uyvy, + int width); +void I422ToUYVYRow_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uyvy, + int width); +void I422ToYUY2Row_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToYUY2Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToUYVYRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); +void I422ToUYVYRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + int width); + +// Effects related row functions. +void ARGBAttenuateRow_C(const uint8_t* src_argb, uint8_t* dst_argb, int width); +void ARGBAttenuateRow_SSSE3(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBAttenuateRow_AVX2(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBAttenuateRow_NEON(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBAttenuateRow_MSA(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBAttenuateRow_MMI(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBAttenuateRow_Any_SSSE3(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBAttenuateRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBAttenuateRow_Any_NEON(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBAttenuateRow_Any_MSA(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBAttenuateRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +// Inverse table for unattenuate, shared by C and SSE2. +extern const uint32_t fixed_invtbl8[256]; +void ARGBUnattenuateRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBUnattenuateRow_SSE2(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBUnattenuateRow_AVX2(const uint8_t* src_argb, + uint8_t* dst_argb, + int width); +void ARGBUnattenuateRow_Any_SSE2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); +void ARGBUnattenuateRow_Any_AVX2(const uint8_t* src_ptr, + uint8_t* dst_ptr, + int width); + +void ARGBGrayRow_C(const uint8_t* src_argb, uint8_t* dst_argb, int width); +void ARGBGrayRow_SSSE3(const uint8_t* src_argb, uint8_t* dst_argb, int width); +void ARGBGrayRow_NEON(const uint8_t* src_argb, uint8_t* dst_argb, int width); +void ARGBGrayRow_MSA(const uint8_t* src_argb, uint8_t* dst_argb, int width); +void ARGBGrayRow_MMI(const uint8_t* src_argb, uint8_t* dst_argb, int width); + +void ARGBSepiaRow_C(uint8_t* dst_argb, int width); +void ARGBSepiaRow_SSSE3(uint8_t* dst_argb, int width); +void ARGBSepiaRow_NEON(uint8_t* dst_argb, int width); +void ARGBSepiaRow_MSA(uint8_t* dst_argb, int width); +void ARGBSepiaRow_MMI(uint8_t* dst_argb, int width); + +void ARGBColorMatrixRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + const int8_t* matrix_argb, + int width); +void ARGBColorMatrixRow_SSSE3(const uint8_t* src_argb, + uint8_t* dst_argb, + const int8_t* matrix_argb, + int width); +void ARGBColorMatrixRow_NEON(const uint8_t* src_argb, + uint8_t* dst_argb, + const int8_t* matrix_argb, + int width); +void ARGBColorMatrixRow_MSA(const uint8_t* src_argb, + uint8_t* dst_argb, + const int8_t* matrix_argb, + int width); +void ARGBColorMatrixRow_MMI(const uint8_t* src_argb, + uint8_t* dst_argb, + const int8_t* matrix_argb, + int width); + +void ARGBColorTableRow_C(uint8_t* dst_argb, + const uint8_t* table_argb, + int width); +void ARGBColorTableRow_X86(uint8_t* dst_argb, + const uint8_t* table_argb, + int width); + +void RGBColorTableRow_C(uint8_t* dst_argb, + const uint8_t* table_argb, + int width); +void RGBColorTableRow_X86(uint8_t* dst_argb, + const uint8_t* table_argb, + int width); + +void ARGBQuantizeRow_C(uint8_t* dst_argb, + int scale, + int interval_size, + int interval_offset, + int width); +void ARGBQuantizeRow_SSE2(uint8_t* dst_argb, + int scale, + int interval_size, + int interval_offset, + int width); +void ARGBQuantizeRow_NEON(uint8_t* dst_argb, + int scale, + int interval_size, + int interval_offset, + int width); +void ARGBQuantizeRow_MSA(uint8_t* dst_argb, + int scale, + int interval_size, + int interval_offset, + int width); + +void ARGBShadeRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + uint32_t value); +void ARGBShadeRow_SSE2(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + uint32_t value); +void ARGBShadeRow_NEON(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + uint32_t value); +void ARGBShadeRow_MSA(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + uint32_t value); +void ARGBShadeRow_MMI(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + uint32_t value); + +// Used for blur. +void CumulativeSumToAverageRow_SSE2(const int32_t* topleft, + const int32_t* botleft, + int width, + int area, + uint8_t* dst, + int count); +void ComputeCumulativeSumRow_SSE2(const uint8_t* row, + int32_t* cumsum, + const int32_t* previous_cumsum, + int width); + +void ComputeCumulativeSumRow_MMI(const uint8_t* row, + int32_t* cumsum, + const int32_t* previous_cumsum, + int width); + +void CumulativeSumToAverageRow_C(const int32_t* tl, + const int32_t* bl, + int w, + int area, + uint8_t* dst, + int count); +void ComputeCumulativeSumRow_C(const uint8_t* row, + int32_t* cumsum, + const int32_t* previous_cumsum, + int width); + +LIBYUV_API +void ARGBAffineRow_C(const uint8_t* src_argb, + int src_argb_stride, + uint8_t* dst_argb, + const float* uv_dudv, + int width); +LIBYUV_API +void ARGBAffineRow_SSE2(const uint8_t* src_argb, + int src_argb_stride, + uint8_t* dst_argb, + const float* src_dudv, + int width); + +// Used for I420Scale, ARGBScale, and ARGBInterpolate. +void InterpolateRow_C(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int width, + int source_y_fraction); +void InterpolateRow_SSSE3(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int dst_width, + int source_y_fraction); +void InterpolateRow_AVX2(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int dst_width, + int source_y_fraction); +void InterpolateRow_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int dst_width, + int source_y_fraction); +void InterpolateRow_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int width, + int source_y_fraction); +void InterpolateRow_MMI(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int width, + int source_y_fraction); +void InterpolateRow_Any_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride_ptr, + int width, + int source_y_fraction); +void InterpolateRow_Any_SSSE3(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride_ptr, + int width, + int source_y_fraction); +void InterpolateRow_Any_AVX2(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride_ptr, + int width, + int source_y_fraction); +void InterpolateRow_Any_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride_ptr, + int width, + int source_y_fraction); +void InterpolateRow_Any_MMI(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride_ptr, + int width, + int source_y_fraction); + +void InterpolateRow_16_C(uint16_t* dst_ptr, + const uint16_t* src_ptr, + ptrdiff_t src_stride, + int width, + int source_y_fraction); + +// Sobel images. +void SobelXRow_C(const uint8_t* src_y0, + const uint8_t* src_y1, + const uint8_t* src_y2, + uint8_t* dst_sobelx, + int width); +void SobelXRow_SSE2(const uint8_t* src_y0, + const uint8_t* src_y1, + const uint8_t* src_y2, + uint8_t* dst_sobelx, + int width); +void SobelXRow_NEON(const uint8_t* src_y0, + const uint8_t* src_y1, + const uint8_t* src_y2, + uint8_t* dst_sobelx, + int width); +void SobelXRow_MSA(const uint8_t* src_y0, + const uint8_t* src_y1, + const uint8_t* src_y2, + uint8_t* dst_sobelx, + int width); +void SobelXRow_MMI(const uint8_t* src_y0, + const uint8_t* src_y1, + const uint8_t* src_y2, + uint8_t* dst_sobelx, + int width); +void SobelYRow_C(const uint8_t* src_y0, + const uint8_t* src_y1, + uint8_t* dst_sobely, + int width); +void SobelYRow_SSE2(const uint8_t* src_y0, + const uint8_t* src_y1, + uint8_t* dst_sobely, + int width); +void SobelYRow_NEON(const uint8_t* src_y0, + const uint8_t* src_y1, + uint8_t* dst_sobely, + int width); +void SobelYRow_MSA(const uint8_t* src_y0, + const uint8_t* src_y1, + uint8_t* dst_sobely, + int width); +void SobelYRow_MMI(const uint8_t* src_y0, + const uint8_t* src_y1, + uint8_t* dst_sobely, + int width); +void SobelRow_C(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelRow_SSE2(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelRow_NEON(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelRow_MSA(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelRow_MMI(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelToPlaneRow_C(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_y, + int width); +void SobelToPlaneRow_SSE2(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_y, + int width); +void SobelToPlaneRow_NEON(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_y, + int width); +void SobelToPlaneRow_MSA(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_y, + int width); +void SobelToPlaneRow_MMI(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_y, + int width); +void SobelXYRow_C(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelXYRow_SSE2(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelXYRow_NEON(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelXYRow_MSA(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelXYRow_MMI(const uint8_t* src_sobelx, + const uint8_t* src_sobely, + uint8_t* dst_argb, + int width); +void SobelRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelToPlaneRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelToPlaneRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelToPlaneRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelToPlaneRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelXYRow_Any_SSE2(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelXYRow_Any_NEON(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelXYRow_Any_MSA(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); +void SobelXYRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + int width); + +void ARGBPolynomialRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + const float* poly, + int width); +void ARGBPolynomialRow_SSE2(const uint8_t* src_argb, + uint8_t* dst_argb, + const float* poly, + int width); +void ARGBPolynomialRow_AVX2(const uint8_t* src_argb, + uint8_t* dst_argb, + const float* poly, + int width); + +// Scale and convert to half float. +void HalfFloatRow_C(const uint16_t* src, uint16_t* dst, float scale, int width); +void HalfFloatRow_SSE2(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_Any_SSE2(const uint16_t* src_ptr, + uint16_t* dst_ptr, + float param, + int width); +void HalfFloatRow_AVX2(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_Any_AVX2(const uint16_t* src_ptr, + uint16_t* dst_ptr, + float param, + int width); +void HalfFloatRow_F16C(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_Any_F16C(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloat1Row_F16C(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloat1Row_Any_F16C(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_NEON(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_Any_NEON(const uint16_t* src_ptr, + uint16_t* dst_ptr, + float param, + int width); +void HalfFloat1Row_NEON(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloat1Row_Any_NEON(const uint16_t* src_ptr, + uint16_t* dst_ptr, + float param, + int width); +void HalfFloatRow_MSA(const uint16_t* src, + uint16_t* dst, + float scale, + int width); +void HalfFloatRow_Any_MSA(const uint16_t* src_ptr, + uint16_t* dst_ptr, + float param, + int width); +void ByteToFloatRow_C(const uint8_t* src, float* dst, float scale, int width); +void ByteToFloatRow_NEON(const uint8_t* src, + float* dst, + float scale, + int width); +void ByteToFloatRow_Any_NEON(const uint8_t* src_ptr, + float* dst_ptr, + float param, + int width); + +void ARGBLumaColorTableRow_C(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + const uint8_t* luma, + uint32_t lumacoeff); +void ARGBLumaColorTableRow_SSSE3(const uint8_t* src_argb, + uint8_t* dst_argb, + int width, + const uint8_t* luma, + uint32_t lumacoeff); + +float ScaleMaxSamples_C(const float* src, float* dst, float scale, int width); +float ScaleMaxSamples_NEON(const float* src, + float* dst, + float scale, + int width); +float ScaleSumSamples_C(const float* src, float* dst, float scale, int width); +float ScaleSumSamples_NEON(const float* src, + float* dst, + float scale, + int width); +void ScaleSamples_C(const float* src, float* dst, float scale, int width); +void ScaleSamples_NEON(const float* src, float* dst, float scale, int width); + +void I210ToARGBRow_MMI(const uint16_t* src_y, + const uint16_t* src_u, + const uint16_t* src_v, + uint8_t* rgb_buf, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb4444, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_MMI(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb1555, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_MMI(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_MMI(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb565, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_MMI(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_MMI(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_MMI(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_MMI(const uint8_t* src_yuy2, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_MMI(const uint8_t* src_uyvy, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width); +void I210ToARGBRow_Any_MMI(const uint16_t* y_buf, + const uint16_t* u_buf, + const uint16_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGBARow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422AlphaToARGBRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + const uint8_t* a_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB24Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToRGB565Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB4444Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void I422ToARGB1555Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* u_buf, + const uint8_t* v_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToARGBRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB565Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToARGBRow_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV12ToRGB24Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void NV21ToRGB24Row_Any_MMI(const uint8_t* y_buf, + const uint8_t* uv_buf, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void YUY2ToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); +void UYVYToARGBRow_Any_MMI(const uint8_t* src_ptr, + uint8_t* dst_ptr, + const struct YuvConstants* yuvconstants, + int width); + +void GaussRow_F32_NEON(const float* src, float* dst, int width); +void GaussRow_F32_C(const float* src, float* dst, int width); + +void GaussCol_F32_NEON(const float* src0, + const float* src1, + const float* src2, + const float* src3, + const float* src4, + float* dst, + int width); + +void GaussCol_F32_C(const float* src0, + const float* src1, + const float* src2, + const float* src3, + const float* src4, + float* dst, + int width); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_ROW_H_ diff --git a/thirdparty/include/libyuv/scale.h b/thirdparty/include/libyuv/scale.h new file mode 100755 index 0000000000000000000000000000000000000000..add5a9eb622d2ed29c4245f89e3dc8087032e9ea --- /dev/null +++ b/thirdparty/include/libyuv/scale.h @@ -0,0 +1,204 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_SCALE_H_ +#define INCLUDE_LIBYUV_SCALE_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +// Supported filtering. +typedef enum FilterMode { + kFilterNone = 0, // Point sample; Fastest. + kFilterLinear = 1, // Filter horizontally only. + kFilterBilinear = 2, // Faster than box, but lower quality scaling down. + kFilterBox = 3 // Highest quality. +} FilterModeEnum; + +// Scale a YUV plane. +LIBYUV_API +void ScalePlane(const uint8_t* src, + int src_stride, + int src_width, + int src_height, + uint8_t* dst, + int dst_stride, + int dst_width, + int dst_height, + enum FilterMode filtering); + +LIBYUV_API +void ScalePlane_16(const uint16_t* src, + int src_stride, + int src_width, + int src_height, + uint16_t* dst, + int dst_stride, + int dst_width, + int dst_height, + enum FilterMode filtering); + +// Scales a YUV 4:2:0 image from the src width and height to the +// dst width and height. +// If filtering is kFilterNone, a simple nearest-neighbor algorithm is +// used. This produces basic (blocky) quality at the fastest speed. +// If filtering is kFilterBilinear, interpolation is used to produce a better +// quality image, at the expense of speed. +// If filtering is kFilterBox, averaging is used to produce ever better +// quality image, at further expense of speed. +// Returns 0 if successful. + +LIBYUV_API +int I420Scale(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + +LIBYUV_API +int I420Scale_16(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + +// Scales a YUV 4:4:4 image from the src width and height to the +// dst width and height. +// If filtering is kFilterNone, a simple nearest-neighbor algorithm is +// used. This produces basic (blocky) quality at the fastest speed. +// If filtering is kFilterBilinear, interpolation is used to produce a better +// quality image, at the expense of speed. +// If filtering is kFilterBox, averaging is used to produce ever better +// quality image, at further expense of speed. +// Returns 0 if successful. + +LIBYUV_API +int I444Scale(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_u, + int dst_stride_u, + uint8_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + +LIBYUV_API +int I444Scale_16(const uint16_t* src_y, + int src_stride_y, + const uint16_t* src_u, + int src_stride_u, + const uint16_t* src_v, + int src_stride_v, + int src_width, + int src_height, + uint16_t* dst_y, + int dst_stride_y, + uint16_t* dst_u, + int dst_stride_u, + uint16_t* dst_v, + int dst_stride_v, + int dst_width, + int dst_height, + enum FilterMode filtering); + +// Scales an NV12 image from the src width and height to the +// dst width and height. +// If filtering is kFilterNone, a simple nearest-neighbor algorithm is +// used. This produces basic (blocky) quality at the fastest speed. +// If filtering is kFilterBilinear, interpolation is used to produce a better +// quality image, at the expense of speed. +// kFilterBox is not supported for the UV channel and will be treated as +// bilinear. +// Returns 0 if successful. + +LIBYUV_API +int NV12Scale(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_uv, + int src_stride_uv, + int src_width, + int src_height, + uint8_t* dst_y, + int dst_stride_y, + uint8_t* dst_uv, + int dst_stride_uv, + int dst_width, + int dst_height, + enum FilterMode filtering); + +#ifdef __cplusplus +// Legacy API. Deprecated. +LIBYUV_API +int Scale(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + int src_stride_y, + int src_stride_u, + int src_stride_v, + int src_width, + int src_height, + uint8_t* dst_y, + uint8_t* dst_u, + uint8_t* dst_v, + int dst_stride_y, + int dst_stride_u, + int dst_stride_v, + int dst_width, + int dst_height, + LIBYUV_BOOL interpolate); + +// For testing, allow disabling of specialized scalers. +LIBYUV_API +void SetUseReferenceImpl(LIBYUV_BOOL use); +#endif // __cplusplus + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_SCALE_H_ diff --git a/thirdparty/include/libyuv/scale_argb.h b/thirdparty/include/libyuv/scale_argb.h new file mode 100755 index 0000000000000000000000000000000000000000..7641f18e3416b869172a2f2d46b07ce5d68ecad6 --- /dev/null +++ b/thirdparty/include/libyuv/scale_argb.h @@ -0,0 +1,76 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_ +#define INCLUDE_LIBYUV_SCALE_ARGB_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/scale.h" // For FilterMode + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +LIBYUV_API +int ARGBScale(const uint8_t* src_argb, + int src_stride_argb, + int src_width, + int src_height, + uint8_t* dst_argb, + int dst_stride_argb, + int dst_width, + int dst_height, + enum FilterMode filtering); + +// Clipped scale takes destination rectangle coordinates for clip values. +LIBYUV_API +int ARGBScaleClip(const uint8_t* src_argb, + int src_stride_argb, + int src_width, + int src_height, + uint8_t* dst_argb, + int dst_stride_argb, + int dst_width, + int dst_height, + int clip_x, + int clip_y, + int clip_width, + int clip_height, + enum FilterMode filtering); + +// Scale with YUV conversion to ARGB and clipping. +LIBYUV_API +int YUVToARGBScaleClip(const uint8_t* src_y, + int src_stride_y, + const uint8_t* src_u, + int src_stride_u, + const uint8_t* src_v, + int src_stride_v, + uint32_t src_fourcc, + int src_width, + int src_height, + uint8_t* dst_argb, + int dst_stride_argb, + uint32_t dst_fourcc, + int dst_width, + int dst_height, + int clip_x, + int clip_y, + int clip_width, + int clip_height, + enum FilterMode filtering); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_SCALE_ARGB_H_ diff --git a/thirdparty/include/libyuv/scale_row.h b/thirdparty/include/libyuv/scale_row.h new file mode 100755 index 0000000000000000000000000000000000000000..888582400498855869d5f7daabd8e27c169ebc80 --- /dev/null +++ b/thirdparty/include/libyuv/scale_row.h @@ -0,0 +1,1366 @@ +/* + * Copyright 2013 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_SCALE_ROW_H_ +#define INCLUDE_LIBYUV_SCALE_ROW_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/scale.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +#if defined(__pnacl__) || defined(__CLR_VER) || \ + (defined(__native_client__) && defined(__x86_64__)) || \ + (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) +#define LIBYUV_DISABLE_X86 +#endif +#if defined(__native_client__) +#define LIBYUV_DISABLE_NEON +#endif +// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define LIBYUV_DISABLE_X86 +#endif +#endif +// GCC >= 4.7.0 required for AVX2. +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) +#define GCC_HAS_AVX2 1 +#endif // GNUC >= 4.7 +#endif // __GNUC__ + +// clang >= 3.4.0 required for AVX2. +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) +#if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) +#define CLANG_HAS_AVX2 1 +#endif // clang >= 3.4 +#endif // __clang__ + +// Visual C 2012 required for AVX2. +#if defined(_M_IX86) && !defined(__clang__) && defined(_MSC_VER) && \ + _MSC_VER >= 1700 +#define VISUALC_HAS_AVX2 1 +#endif // VisualStudio >= 2012 + +// The following are available on all x86 platforms: +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) +#define HAS_FIXEDDIV1_X86 +#define HAS_FIXEDDIV_X86 +#define HAS_SCALEADDROW_SSE2 +#define HAS_SCALEARGBCOLS_SSE2 +#define HAS_SCALEARGBCOLSUP2_SSE2 +#define HAS_SCALEARGBFILTERCOLS_SSSE3 +#define HAS_SCALEARGBROWDOWN2_SSE2 +#define HAS_SCALEARGBROWDOWNEVEN_SSE2 +#define HAS_SCALECOLSUP2_SSE2 +#define HAS_SCALEFILTERCOLS_SSSE3 +#define HAS_SCALEROWDOWN2_SSSE3 +#define HAS_SCALEROWDOWN34_SSSE3 +#define HAS_SCALEROWDOWN38_SSSE3 +#define HAS_SCALEROWDOWN4_SSSE3 +#endif + +// The following are available for gcc/clang x86 platforms: +// TODO(fbarchard): Port to Visual C +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || (defined(__i386__) && !defined(_MSC_VER))) +#define HAS_SCALEUVROWDOWN2BOX_SSSE3 +#endif + +// The following are available for gcc/clang x86 platforms, but +// require clang 3.4 or gcc 4.7. +// TODO(fbarchard): Port to Visual C +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(__x86_64__) || defined(__i386__)) && !defined(_MSC_VER) && \ + (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) +#define HAS_SCALEUVROWDOWN2BOX_AVX2 +#endif + +// The following are available on all x86 platforms, but +// require VS2012, clang 3.4 or gcc 4.7. +// The code supports NaCL but requires a new compiler and validator. +#if !defined(LIBYUV_DISABLE_X86) && \ + (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2) || \ + defined(GCC_HAS_AVX2)) +#define HAS_SCALEADDROW_AVX2 +#define HAS_SCALEROWDOWN2_AVX2 +#define HAS_SCALEROWDOWN4_AVX2 +#endif + +// The following are available on Neon platforms: +#if !defined(LIBYUV_DISABLE_NEON) && \ + (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) +#define HAS_SCALEADDROW_NEON +#define HAS_SCALEARGBCOLS_NEON +#define HAS_SCALEARGBFILTERCOLS_NEON +#define HAS_SCALEARGBROWDOWN2_NEON +#define HAS_SCALEARGBROWDOWNEVEN_NEON +#define HAS_SCALEFILTERCOLS_NEON +#define HAS_SCALEROWDOWN2_NEON +#define HAS_SCALEROWDOWN34_NEON +#define HAS_SCALEROWDOWN38_NEON +#define HAS_SCALEROWDOWN4_NEON +#define HAS_SCALEUVROWDOWN2BOX_NEON +#endif + +#if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) +#define HAS_SCALEADDROW_MSA +#define HAS_SCALEARGBCOLS_MSA +#define HAS_SCALEARGBFILTERCOLS_MSA +#define HAS_SCALEARGBROWDOWN2_MSA +#define HAS_SCALEARGBROWDOWNEVEN_MSA +#define HAS_SCALEFILTERCOLS_MSA +#define HAS_SCALEROWDOWN2_MSA +#define HAS_SCALEROWDOWN34_MSA +#define HAS_SCALEROWDOWN38_MSA +#define HAS_SCALEROWDOWN4_MSA +#endif + +#if !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A) +#define HAS_FIXEDDIV1_MIPS +#define HAS_FIXEDDIV_MIPS +#define HAS_SCALEADDROW_16_MMI +#define HAS_SCALEADDROW_MMI +#define HAS_SCALEARGBCOLS_MMI +#define HAS_SCALEARGBCOLSUP2_MMI +#define HAS_SCALEARGBROWDOWN2_MMI +#define HAS_SCALEARGBROWDOWNEVEN_MMI +#define HAS_SCALECOLS_16_MMI +#define HAS_SCALECOLS_MMI +#define HAS_SCALEROWDOWN2_16_MMI +#define HAS_SCALEROWDOWN2_MMI +#define HAS_SCALEROWDOWN4_16_MMI +#define HAS_SCALEROWDOWN4_MMI +#define HAS_SCALEROWDOWN34_MMI +#endif + +// Scale ARGB vertically with bilinear interpolation. +void ScalePlaneVertical(int src_height, + int dst_width, + int dst_height, + int src_stride, + int dst_stride, + const uint8_t* src_argb, + uint8_t* dst_argb, + int x, + int y, + int dy, + int bpp, + enum FilterMode filtering); + +void ScalePlaneVertical_16(int src_height, + int dst_width, + int dst_height, + int src_stride, + int dst_stride, + const uint16_t* src_argb, + uint16_t* dst_argb, + int x, + int y, + int dy, + int wpp, + enum FilterMode filtering); + +// Simplify the filtering based on scale factors. +enum FilterMode ScaleFilterReduce(int src_width, + int src_height, + int dst_width, + int dst_height, + enum FilterMode filtering); + +// Divide num by div and return as 16.16 fixed point result. +int FixedDiv_C(int num, int div); +int FixedDiv_X86(int num, int div); +int FixedDiv_MIPS(int num, int div); +// Divide num - 1 by div - 1 and return as 16.16 fixed point result. +int FixedDiv1_C(int num, int div); +int FixedDiv1_X86(int num, int div); +int FixedDiv1_MIPS(int num, int div); +#ifdef HAS_FIXEDDIV_X86 +#define FixedDiv FixedDiv_X86 +#define FixedDiv1 FixedDiv1_X86 +#elif defined HAS_FIXEDDIV_MIPS +#define FixedDiv FixedDiv_MIPS +#define FixedDiv1 FixedDiv1_MIPS +#else +#define FixedDiv FixedDiv_C +#define FixedDiv1 FixedDiv1_C +#endif + +// Compute slope values for stepping. +void ScaleSlope(int src_width, + int src_height, + int dst_width, + int dst_height, + enum FilterMode filtering, + int* x, + int* y, + int* dx, + int* dy); + +void ScaleRowDown2_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown2Linear_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Linear_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown2Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Box_Odd_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown4_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown4Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown34_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown34_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown34_0_Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* d, + int dst_width); +void ScaleRowDown34_0_Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* d, + int dst_width); +void ScaleRowDown34_1_Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* d, + int dst_width); +void ScaleRowDown34_1_Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* d, + int dst_width); +void ScaleCols_C(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleCols_16_C(uint16_t* dst_ptr, + const uint16_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleColsUp2_C(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int, + int); +void ScaleColsUp2_16_C(uint16_t* dst_ptr, + const uint16_t* src_ptr, + int dst_width, + int, + int); +void ScaleFilterCols_C(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleFilterCols_16_C(uint16_t* dst_ptr, + const uint16_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleFilterCols64_C(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x32, + int dx); +void ScaleFilterCols64_16_C(uint16_t* dst_ptr, + const uint16_t* src_ptr, + int dst_width, + int x32, + int dx); +void ScaleRowDown38_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown38_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown38_3_Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_3_Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst_ptr, + int dst_width); +void ScaleRowDown38_2_Box_C(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_2_Box_16_C(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst_ptr, + int dst_width); +void ScaleAddRow_C(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleAddRow_16_C(const uint16_t* src_ptr, + uint32_t* dst_ptr, + int src_width); +void ScaleARGBRowDown2_C(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Linear_C(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Box_C(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEven_C(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEvenBox_C(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBCols_C(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBCols64_C(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x32, + int dx); +void ScaleARGBColsUp2_C(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int, + int); +void ScaleARGBFilterCols_C(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols64_C(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x32, + int dx); +void ScaleUVRowDown2_C(const uint8_t* src_uv, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Linear_C(const uint8_t* src_uv, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_C(const uint8_t* src_uv, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEven_C(const uint8_t* src_uv, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEvenBox_C(const uint8_t* src_uv, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVCols_C(uint8_t* dst_uv, + const uint8_t* src_uv, + int dst_width, + int x, + int dx); +void ScaleUVCols64_C(uint8_t* dst_uv, + const uint8_t* src_uv, + int dst_width, + int x32, + int dx); +void ScaleUVColsUp2_C(uint8_t* dst_uv, + const uint8_t* src_uv, + int dst_width, + int, + int); +void ScaleUVFilterCols_C(uint8_t* dst_uv, + const uint8_t* src_uv, + int dst_width, + int x, + int dx); +void ScaleUVFilterCols64_C(uint8_t* dst_uv, + const uint8_t* src_uv, + int dst_width, + int x32, + int dx); + +// Specialized scalers for x86. +void ScaleRowDown2_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleRowDown34_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_1_Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_0_Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_3_Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_2_Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Odd_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Odd_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleRowDown34_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_1_Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_0_Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_3_Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_2_Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleAddRow_SSE2(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleAddRow_AVX2(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleAddRow_Any_SSE2(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int src_width); +void ScaleAddRow_Any_AVX2(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int src_width); + +void ScaleFilterCols_SSSE3(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleColsUp2_SSE2(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); + +// ARGB Column functions +void ScaleARGBCols_SSE2(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols_SSSE3(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBColsUp2_SSE2(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols_NEON(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBCols_NEON(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols_Any_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleARGBCols_Any_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols_MSA(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBCols_MSA(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBFilterCols_Any_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleARGBCols_Any_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleARGBCols_MMI(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); +void ScaleARGBCols_Any_MMI(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); + +// ARGB Row functions +void ScaleARGBRowDown2_SSE2(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Linear_SSE2(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Box_SSE2(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleARGBRowDown2Linear_NEON(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleARGBRowDown2_MSA(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Linear_MSA(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Box_MSA(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2_MMI(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Linear_MMI(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2Box_MMI(const uint8_t* src_argb, + ptrdiff_t src_stride, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDown2_Any_SSE2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Linear_Any_SSE2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Box_Any_SSE2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Linear_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Linear_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Linear_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDown2Box_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEven_SSE2(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEvenBox_SSE2(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEven_NEON(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEvenBox_NEON(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEven_MSA(const uint8_t* src_argb, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEvenBox_MSA(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEven_MMI(const uint8_t* src_argb, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEvenBox_MMI(const uint8_t* src_argb, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_argb, + int dst_width); +void ScaleARGBRowDownEven_Any_SSE2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEvenBox_Any_SSE2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEven_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEvenBox_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEven_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEvenBox_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEven_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleARGBRowDownEvenBox_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); + +// UV Row functions +void ScaleUVRowDown2_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Linear_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleUVRowDown2Linear_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleUVRowDown2_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Linear_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Linear_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2Box_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDown2_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Linear_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Box_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Box_Any_AVX2(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Linear_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Linear_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Linear_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDown2Box_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEven_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEvenBox_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEven_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEvenBox_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEven_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEvenBox_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEven_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEvenBox_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_uv, + int dst_width); +void ScaleUVRowDownEven_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEvenBox_Any_SSSE3(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEven_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEvenBox_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEven_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEvenBox_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEven_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int32_t src_stepx, + uint8_t* dst_ptr, + int dst_width); +void ScaleUVRowDownEvenBox_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + int src_stepx, + uint8_t* dst_ptr, + int dst_width); + +// ScaleRowDown2Box also used by planar functions +// NEON downscalers with interpolation. + +// Note - not static due to reuse in convert for 444 to 420. +void ScaleRowDown2_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Linear_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); + +void ScaleRowDown4_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +// Down scale from 4 to 3 pixels. Use the neon multilane read/write +// to load up the every 4th pixel into a 4 different registers. +// Point samples 32 pixels to 24 pixels. +void ScaleRowDown34_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_0_Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_1_Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +// 32 -> 12 +void ScaleRowDown38_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +// 32x3 -> 12x1 +void ScaleRowDown38_3_Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +// 32x2 -> 12x1 +void ScaleRowDown38_2_Box_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleRowDown2_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Odd_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_0_Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_1_Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +// 32 -> 12 +void ScaleRowDown38_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +// 32x3 -> 12x1 +void ScaleRowDown38_3_Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +// 32x2 -> 12x1 +void ScaleRowDown38_2_Box_Any_NEON(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleAddRow_NEON(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleAddRow_Any_NEON(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int src_width); + +void ScaleFilterCols_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); + +void ScaleFilterCols_Any_NEON(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); + +void ScaleRowDown2_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Linear_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown38_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown38_2_Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_3_Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleAddRow_MSA(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleFilterCols_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleRowDown34_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown34_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown34_0_Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* d, + int dst_width); +void ScaleRowDown34_1_Box_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* d, + int dst_width); + +void ScaleRowDown2_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_2_Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown38_3_Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleAddRow_Any_MSA(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int src_width); +void ScaleFilterCols_Any_MSA(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleRowDown34_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_0_Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown34_1_Box_Any_MSA(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); + +void ScaleRowDown2_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2_16_MMI(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown2Linear_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Linear_16_MMI(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown2Box_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown2Box_16_MMI(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown2Box_Odd_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4_16_MMI(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleRowDown4Box_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst, + int dst_width); +void ScaleRowDown4Box_16_MMI(const uint16_t* src_ptr, + ptrdiff_t src_stride, + uint16_t* dst, + int dst_width); +void ScaleAddRow_MMI(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width); +void ScaleAddRow_16_MMI(const uint16_t* src_ptr, + uint32_t* dst_ptr, + int src_width); +void ScaleColsUp2_MMI(uint8_t* dst_ptr, + const uint8_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleColsUp2_16_MMI(uint16_t* dst_ptr, + const uint16_t* src_ptr, + int dst_width, + int x, + int dx); +void ScaleARGBColsUp2_MMI(uint8_t* dst_argb, + const uint8_t* src_argb, + int dst_width, + int x, + int dx); + +void ScaleRowDown2_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Linear_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown2Box_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleRowDown4Box_Any_MMI(const uint8_t* src_ptr, + ptrdiff_t src_stride, + uint8_t* dst_ptr, + int dst_width); +void ScaleAddRow_Any_MMI(const uint8_t* src_ptr, + uint16_t* dst_ptr, + int src_width); +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_SCALE_ROW_H_ diff --git a/thirdparty/include/libyuv/scale_uv.h b/thirdparty/include/libyuv/scale_uv.h new file mode 100755 index 0000000000000000000000000000000000000000..1b6327aaed1b97cb652bb89e8f449c2349e05fc4 --- /dev/null +++ b/thirdparty/include/libyuv/scale_uv.h @@ -0,0 +1,38 @@ +/* + * Copyright 2020 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_SCALE_UV_H_ +#define INCLUDE_LIBYUV_SCALE_UV_H_ + +#include "libyuv/basic_types.h" +#include "libyuv/scale.h" // For FilterMode + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +LIBYUV_API +int UVScale(const uint8_t* src_uv, + int src_stride_uv, + int src_width, + int src_height, + uint8_t* dst_uv, + int dst_stride_uv, + int dst_width, + int dst_height, + enum FilterMode filtering); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_SCALE_UV_H_ diff --git a/thirdparty/include/libyuv/version.h b/thirdparty/include/libyuv/version.h new file mode 100755 index 0000000000000000000000000000000000000000..47fdf8204048fc604c91d047985d13001e8cd4c1 --- /dev/null +++ b/thirdparty/include/libyuv/version.h @@ -0,0 +1,16 @@ +/* + * Copyright 2012 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef INCLUDE_LIBYUV_VERSION_H_ +#define INCLUDE_LIBYUV_VERSION_H_ + +#define LIBYUV_VERSION 1766 + +#endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/thirdparty/include/libyuv/video_common.h b/thirdparty/include/libyuv/video_common.h new file mode 100755 index 0000000000000000000000000000000000000000..b9823d71d0988a17260e2608a804d31d3227b5f2 --- /dev/null +++ b/thirdparty/include/libyuv/video_common.h @@ -0,0 +1,206 @@ +/* + * Copyright 2011 The LibYuv Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Common definitions for video, including fourcc and VideoFormat. + +#ifndef INCLUDE_LIBYUV_VIDEO_COMMON_H_ +#define INCLUDE_LIBYUV_VIDEO_COMMON_H_ + +#include "libyuv/basic_types.h" + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////// +// Definition of FourCC codes +////////////////////////////////////////////////////////////////////////////// + +// Convert four characters to a FourCC code. +// Needs to be a macro otherwise the OS X compiler complains when the kFormat* +// constants are used in a switch. +#ifdef __cplusplus +#define FOURCC(a, b, c, d) \ + ((static_cast(a)) | (static_cast(b) << 8) | \ + (static_cast(c) << 16) | /* NOLINT */ \ + (static_cast(d) << 24)) /* NOLINT */ +#else +#define FOURCC(a, b, c, d) \ + (((uint32_t)(a)) | ((uint32_t)(b) << 8) | /* NOLINT */ \ + ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) /* NOLINT */ +#endif + +// Some pages discussing FourCC codes: +// http://www.fourcc.org/yuv.php +// http://v4l2spec.bytesex.org/spec/book1.htm +// http://developer.apple.com/quicktime/icefloe/dispatch020.html +// http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12 +// http://people.xiph.org/~xiphmont/containers/nut/nut4cc.txt + +// FourCC codes grouped according to implementation efficiency. +// Primary formats should convert in 1 efficient step. +// Secondary formats are converted in 2 steps. +// Auxilliary formats call primary converters. +enum FourCC { + // 10 Primary YUV formats: 5 planar, 2 biplanar, 2 packed. + FOURCC_I420 = FOURCC('I', '4', '2', '0'), + FOURCC_I422 = FOURCC('I', '4', '2', '2'), + FOURCC_I444 = FOURCC('I', '4', '4', '4'), + FOURCC_I400 = FOURCC('I', '4', '0', '0'), + FOURCC_NV21 = FOURCC('N', 'V', '2', '1'), + FOURCC_NV12 = FOURCC('N', 'V', '1', '2'), + FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'), + FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'), + FOURCC_I010 = FOURCC('I', '0', '1', '0'), // bt.601 10 bit 420 + FOURCC_I210 = FOURCC('I', '0', '1', '0'), // bt.601 10 bit 422 + + // 1 Secondary YUV format: row biplanar. deprecated. + FOURCC_M420 = FOURCC('M', '4', '2', '0'), + + // 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc + FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), + FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'), + FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'), + FOURCC_AR30 = FOURCC('A', 'R', '3', '0'), // 10 bit per channel. 2101010. + FOURCC_AB30 = FOURCC('A', 'B', '3', '0'), // ABGR version of 10 bit + FOURCC_24BG = FOURCC('2', '4', 'B', 'G'), + FOURCC_RAW = FOURCC('r', 'a', 'w', ' '), + FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'), + FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE. + FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE. + FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE. + + // 1 Primary Compressed YUV format. + FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'), + + // 14 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias. + FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'), + FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), + FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), + FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. + FOURCC_J420 = + FOURCC('J', '4', '2', '0'), // jpeg (bt.601 full), unofficial fourcc + FOURCC_J422 = + FOURCC('J', '4', '2', '2'), // jpeg (bt.601 full), unofficial fourcc + FOURCC_J444 = + FOURCC('J', '4', '4', '4'), // jpeg (bt.601 full), unofficial fourcc + FOURCC_J400 = + FOURCC('J', '4', '0', '0'), // jpeg (bt.601 full), unofficial fourcc + FOURCC_H420 = FOURCC('H', '4', '2', '0'), // bt.709, unofficial fourcc + FOURCC_H422 = FOURCC('H', '4', '2', '2'), // bt.709, unofficial fourcc + FOURCC_H444 = FOURCC('H', '4', '4', '4'), // bt.709, unofficial fourcc + FOURCC_U420 = FOURCC('U', '4', '2', '0'), // bt.2020, unofficial fourcc + FOURCC_U422 = FOURCC('U', '4', '2', '2'), // bt.2020, unofficial fourcc + FOURCC_U444 = FOURCC('U', '4', '4', '4'), // bt.2020, unofficial fourcc + FOURCC_H010 = FOURCC('H', '0', '1', '0'), // bt.709 10 bit 420 + FOURCC_U010 = FOURCC('U', '0', '1', '0'), // bt.2020 10 bit 420 + FOURCC_H210 = FOURCC('H', '0', '1', '0'), // bt.709 10 bit 422 + FOURCC_U210 = FOURCC('U', '0', '1', '0'), // bt.2020 10 bit 422 + + // 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc. + FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420. + FOURCC_YU16 = FOURCC('Y', 'U', '1', '6'), // Alias for I422. + FOURCC_YU24 = FOURCC('Y', 'U', '2', '4'), // Alias for I444. + FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2. + FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac. + FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY. + FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY on Mac. + FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG. + FOURCC_DMB1 = FOURCC('d', 'm', 'b', '1'), // Alias for MJPG on Mac. + FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR. + FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW. + FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG. + FOURCC_CM32 = FOURCC(0, 0, 0, 32), // Alias for BGRA kCMPixelFormat_32ARGB + FOURCC_CM24 = FOURCC(0, 0, 0, 24), // Alias for RAW kCMPixelFormat_24RGB + FOURCC_L555 = FOURCC('L', '5', '5', '5'), // Alias for RGBO. + FOURCC_L565 = FOURCC('L', '5', '6', '5'), // Alias for RGBP. + FOURCC_5551 = FOURCC('5', '5', '5', '1'), // Alias for RGBO. + + // deprecated formats. Not supported, but defined for backward compatibility. + FOURCC_I411 = FOURCC('I', '4', '1', '1'), + FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), + FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'), + FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'), + FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'), + FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'), + FOURCC_H264 = FOURCC('H', '2', '6', '4'), + + // Match any fourcc. + FOURCC_ANY = -1, +}; + +enum FourCCBpp { + // Canonical fourcc codes used in our code. + FOURCC_BPP_I420 = 12, + FOURCC_BPP_I422 = 16, + FOURCC_BPP_I444 = 24, + FOURCC_BPP_I411 = 12, + FOURCC_BPP_I400 = 8, + FOURCC_BPP_NV21 = 12, + FOURCC_BPP_NV12 = 12, + FOURCC_BPP_YUY2 = 16, + FOURCC_BPP_UYVY = 16, + FOURCC_BPP_M420 = 12, // deprecated + FOURCC_BPP_Q420 = 12, + FOURCC_BPP_ARGB = 32, + FOURCC_BPP_BGRA = 32, + FOURCC_BPP_ABGR = 32, + FOURCC_BPP_RGBA = 32, + FOURCC_BPP_AR30 = 32, + FOURCC_BPP_AB30 = 32, + FOURCC_BPP_24BG = 24, + FOURCC_BPP_RAW = 24, + FOURCC_BPP_RGBP = 16, + FOURCC_BPP_RGBO = 16, + FOURCC_BPP_R444 = 16, + FOURCC_BPP_RGGB = 8, + FOURCC_BPP_BGGR = 8, + FOURCC_BPP_GRBG = 8, + FOURCC_BPP_GBRG = 8, + FOURCC_BPP_YV12 = 12, + FOURCC_BPP_YV16 = 16, + FOURCC_BPP_YV24 = 24, + FOURCC_BPP_YU12 = 12, + FOURCC_BPP_J420 = 12, + FOURCC_BPP_J400 = 8, + FOURCC_BPP_H420 = 12, + FOURCC_BPP_H422 = 16, + FOURCC_BPP_H010 = 24, + FOURCC_BPP_MJPG = 0, // 0 means unknown. + FOURCC_BPP_H264 = 0, + FOURCC_BPP_IYUV = 12, + FOURCC_BPP_YU16 = 16, + FOURCC_BPP_YU24 = 24, + FOURCC_BPP_YUYV = 16, + FOURCC_BPP_YUVS = 16, + FOURCC_BPP_HDYC = 16, + FOURCC_BPP_2VUY = 16, + FOURCC_BPP_JPEG = 1, + FOURCC_BPP_DMB1 = 1, + FOURCC_BPP_BA81 = 8, + FOURCC_BPP_RGB3 = 24, + FOURCC_BPP_BGR3 = 24, + FOURCC_BPP_CM32 = 32, + FOURCC_BPP_CM24 = 24, + + // Match any fourcc. + FOURCC_BPP_ANY = 0, // 0 means unknown. +}; + +// Converts fourcc aliases into canonical ones. +LIBYUV_API uint32_t CanonicalFourCC(uint32_t fourcc); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // INCLUDE_LIBYUV_VIDEO_COMMON_H_ diff --git a/thirdparty/include/lws_config.h b/thirdparty/include/lws_config.h new file mode 100755 index 0000000000000000000000000000000000000000..169667bd7084a9e7624d21791b68ec799f9b26e6 --- /dev/null +++ b/thirdparty/include/lws_config.h @@ -0,0 +1,240 @@ +/* lws_config.h Generated from lws_config.h.in */ + +#ifndef NDEBUG + #ifndef _DEBUG + #define _DEBUG + #endif +#endif + +#define LWS_INSTALL_DATADIR "/usr/local/share" +#define LWS_INSTALL_LIBDIR "/usr/local/lib" +#define LWS_LIBRARY_VERSION_MAJOR 4 +#define LWS_LIBRARY_VERSION_MINOR 3 +#define LWS_LIBRARY_VERSION_PATCH_ELABORATED 0-unknown +#define LWS_LIBRARY_VERSION_PATCH 0 + +/* LWS_LIBRARY_VERSION_NUMBER looks like 1005001 for e.g. version 1.5.1 */ +#define LWS_LIBRARY_VERSION_NUMBER (LWS_LIBRARY_VERSION_MAJOR * 1000000) + \ + (LWS_LIBRARY_VERSION_MINOR * 1000) + \ + LWS_LIBRARY_VERSION_PATCH +#define LWS_MAX_SMP 1 + +/* #undef LWS_ESP_PLATFORM */ +/* #undef LWS_LIBRARY_VERSION_NUMBER */ + +/* #undef LWS_EXT_PTHREAD_LIBRARIES */ + +/* #undef LWS_AVOID_SIGPIPE_IGN */ +#define LWS_BUILD_HASH "unknown" +/* #undef LWS_BUILTIN_GETIFADDRS */ +#define LWS_CLIENT_HTTP_PROXYING +/* #undef LWS_DETECTED_PLAT_IOS */ +/* #undef LWS_FALLBACK_GETHOSTBYNAME */ +#define LWS_HAS_INTPTR_T +#define LWS_HAS_GETOPT_LONG +/* #undef LWS_HAVE__ATOI64 */ +#define LWS_HAVE_ATOLL +#define LWS_HAVE_BN_bn2binpad +#define LWS_HAVE_CLOCK_GETTIME +#define LWS_HAVE_EC_POINT_get_affine_coordinates +#define LWS_HAVE_EC_KEY_new_by_curve_name +#define LWS_HAVE_ECDSA_SIG_set0 +#define LWS_HAVE_EVP_MD_CTX_free +#define LWS_HAVE_EVP_aes_128_wrap +#define LWS_HAVE_EVP_aes_128_cfb8 +#define LWS_HAVE_EVP_aes_128_cfb128 +#define LWS_HAVE_EVP_aes_192_cfb8 +#define LWS_HAVE_EVP_aes_192_cfb128 +#define LWS_HAVE_EVP_aes_256_cfb8 +#define LWS_HAVE_EVP_aes_256_cfb128 +#define LWS_HAVE_EVP_aes_128_ofb +#define LWS_HAVE_EVP_aes_128_xts +#define LWS_HAVE_EVP_aes_128_ctr +#define LWS_HAVE_EVP_aes_128_ecb +#define LWS_HAVE_EVP_PKEY_new_raw_private_key +#define LWS_HAVE_EXECVPE +#define LWS_HAVE_LOCALTIME_R +#define LWS_HAVE_GMTIME_R +#define LWS_HAVE_CTIME_R +#define LWS_HAVE_GETGRGID_R +#define LWS_HAVE_GETGRNAM_R +#define LWS_HAVE_GETPWUID_R +#define LWS_HAVE_GETPWNAM_R +/* #undef LWS_HAVE_LIBCAP */ +#define LWS_HAVE_HMAC_CTX_new +#define LWS_HAVE_MALLOC_H +#define LWS_HAVE_MALLOC_TRIM +#define LWS_HAVE_MALLOC_USABLE_SIZE +/* #undef LWS_HAVE_mbedtls_md_setup */ +/* #undef LWS_HAVE_mbedtls_net_init */ +/* #undef LWS_HAVE_mbedtls_rsa_complete */ +/* #undef LWS_HAVE_mbedtls_internal_aes_encrypt */ +/* #undef LWS_HAVE_mbedtls_ssl_conf_alpn_protocols */ +/* #undef LWS_HAVE_mbedtls_ssl_get_alpn_protocol */ +/* #undef LWS_HAVE_mbedtls_ssl_conf_sni */ +/* #undef LWS_HAVE_mbedtls_ssl_set_hs_ca_chain */ +/* #undef LWS_HAVE_mbedtls_ssl_set_hs_own_cert */ +/* #undef LWS_HAVE_mbedtls_ssl_set_hs_authmode */ +/* #undef LWS_HAVE_mbedtls_ssl_set_verify */ +/* #undef LWS_HAVE_mbedtls_x509_crt_parse_file */ +/* #undef LWS_HAVE_MBEDTLS_NET_SOCKETS */ +/* #undef LWS_HAVE_MBEDTLS_AUTH_KEY_ID */ +/* #undef LWS_HAVE_NEW_UV_VERSION_H */ +#define LWS_HAVE_OPENSSL_ECDH_H +#define LWS_HAVE_OPENSSL_STACK +#define LWS_HAVE_PIPE2 +#define LWS_HAVE_EVENTFD +#define LWS_HAVE_PTHREAD_H +#define LWS_HAVE_RSA_SET0_KEY +/* #undef LWS_HAVE_RSA_verify_pss_mgf1 */ +#define LWS_HAVE_SSL_CTX_get0_certificate +/* #undef LWS_HAVE_SSL_CTX_load_verify_file */ +/* #undef LWS_HAVE_SSL_CTX_load_verify_dir */ +#define LWS_HAVE_SSL_CTX_set1_param +/* #undef LWS_HAVE_SSL_CTX_set_ciphersuites */ +#define LWS_HAVE_SSL_EXTRA_CHAIN_CERTS +#define LWS_HAVE_SSL_get0_alpn_selected +/* #undef LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key */ +#define LWS_HAVE_SSL_set_alpn_protos +#define LWS_HAVE_SSL_SET_INFO_CALLBACK +#define LWS_HAVE_SSL_SESSION_set_time +/* #undef LWS_HAVE_SSL_SESSION_up_ref */ +/* #undef LWS_HAVE__STAT32I64 */ +#define LWS_HAVE_STDINT_H +/* #undef LWS_HAVE_SYS_CAPABILITY_H */ +#define LWS_HAVE_TIMEGM +#define LWS_HAVE_TLS_CLIENT_METHOD +#define LWS_HAVE_TLSV1_2_CLIENT_METHOD +#define LWS_HAVE_SUSECONDS_T +/* #undef LWS_HAVE_UV_VERSION_H */ +#define LWS_HAVE_VFORK +#define LWS_HAVE_X509_get_key_usage +#define LWS_HAVE_X509_VERIFY_PARAM_set1_host +#define LWS_LIBRARY_VERSION "4.3.0-unknown" +#define LWS_LOGGING_BITFIELD_CLEAR 0 +#define LWS_LOGGING_BITFIELD_SET 0 +#define LWS_LOG_TAG_LIFECYCLE +/* #undef LWS_MINGW_SUPPORT */ +/* #undef LWS_NO_CLIENT */ +#define LWS_NO_DAEMONIZE +#define LWS_OPENSSL_CLIENT_CERTS "../share" +#define LWS_OPENSSL_SUPPORT +/* #undef LWS_PLAT_OPTEE */ +#define LWS_PLAT_UNIX +/* #undef LWS_PLAT_FREERTOS */ +/* #undef LWS_ROLE_CGI */ +/* #undef LWS_ROLE_DBUS */ +#define LWS_ROLE_H1 +#define LWS_ROLE_H2 +#define LWS_ROLE_RAW +#define LWS_ROLE_RAW_FILE +/* #undef LWS_ROLE_RAW_PROXY */ +#define LWS_ROLE_WS +/* #undef LWS_ROLE_MQTT */ +/* #undef LWS_SHA1_USE_OPENSSL_NAME */ +#define LWS_SSL_CLIENT_USE_OS_CA_CERTS +/* #undef LWS_SSL_SERVER_WITH_ECDH_CERT */ +#define LWS_SUPPRESS_DEPRECATED_API_WARNINGS +/* #undef LWS_TLS_LOG_PLAINTEXT_RX */ +/* #undef LWS_TLS_LOG_PLAINTEXT_TX */ +/* #undef LWS_WITH_ABSTRACT */ +/* #undef LWS_WITH_ACCESS_LOG */ +/* #undef LWS_WITH_ACME */ +/* #undef LWS_WITH_ALSA */ +/* #undef LWS_WITH_SYS_ASYNC_DNS */ +/* #undef LWS_WITH_BORINGSSL */ +/* #undef LWS_WITH_CGI */ +#define LWS_WITH_CONMON +/* #undef LWS_WITH_COSE */ +#define LWS_WITH_CUSTOM_HEADERS +/* #undef LWS_WITH_DEPRECATED_LWS_DLL */ +/* #undef LWS_WITH_DETAILED_LATENCY */ +#define LWS_WITH_DIR +/* #undef LWS_WITH_DRIVERS */ +/* #undef LWS_WITH_ESP32 */ +/* #undef LWS_HAVE_EVBACKEND_LINUXAIO */ +/* #undef LWS_HAVE_EVBACKEND_IOURING */ +/* #undef LWS_WITH_EXTERNAL_POLL */ +#define LWS_WITH_FILE_OPS +/* #undef LWS_WITH_FSMOUNT */ +/* #undef LWS_WITH_FTS */ +/* #undef LWS_WITH_GENCRYPTO */ +/* #undef LWS_WITH_GENERIC_SESSIONS */ +/* #undef LWS_WITH_GLIB */ +/* #undef LWS_WITH_GTK */ +#define LWS_WITH_HTTP2 +#define LWS_WITH_HTTP_BASIC_AUTH +/* #undef LWS_WITH_HTTP_BROTLI */ +/* #undef LWS_HTTP_HEADERS_ALL */ +/* #undef LWS_WITH_HTTP_PROXY */ +/* #undef LWS_WITH_HTTP_STREAM_COMPRESSION */ +#define LWS_WITH_HTTP_UNCOMMON_HEADERS +/* #undef LWS_WITH_IPV6 */ +/* #undef LWS_WITH_JOSE */ +/* #undef LWS_WITH_CBOR */ +#define LWS_WITH_CBOR_FLOAT +#define LWS_WITH_LEJP +/* #undef LWS_WITH_LIBEV */ +/* #undef LWS_WITH_LIBEVENT */ +/* #undef LWS_WITH_LIBUV */ +/* #undef LWS_WITH_SDEVENT */ +#define LWS_WITH_LWSAC +#define LWS_LOGS_TIMESTAMP +/* #undef LWS_WITH_MBEDTLS */ +/* #undef LWS_WITH_MINIZ */ +#define LWS_WITH_NETLINK +#define LWS_WITH_NETWORK +/* #undef LWS_WITH_NO_LOGS */ +#define LWS_WITH_CACHE_NSCOOKIEJAR +#define LWS_WITH_CLIENT +#define LWS_WITHOUT_EXTENSIONS +#define LWS_WITH_SERVER +/* #undef LWS_WITH_SPAWN */ +/* #undef LWS_WITH_PEER_LIMITS */ +/* #undef LWS_WITH_PLUGINS */ +/* #undef LWS_WITH_PLUGINS_BUILTIN */ +/* #undef LWS_WITH_POLARSSL */ +#define LWS_WITH_POLL +/* #undef LWS_WITH_RANGES */ +/* #undef LWS_WITH_RFC6724 */ +/* #undef LWS_WITH_SECURE_STREAMS */ +/* #undef LWS_WITH_SECURE_STREAMS_CPP */ +/* #undef LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM */ +/* #undef LWS_WITH_SECURE_STREAMS_PROXY_API */ +/* #undef LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY */ +/* #undef LWS_WITH_SECURE_STREAMS_AUTH_SIGV4 */ +/* #undef LWS_WITH_SECURE_STREAMS_BUFFER_DUMP */ +/* #undef LWS_WITH_SS_DIRECT_PROTOCOL_STR */ +/* #undef LWS_WITH_SELFTESTS */ +/* #undef LWS_WITH_SEQUENCER */ +/* #undef LWS_WITH_SERVER_STATUS */ +#define LWS_WITH_SYS_SMD +/* #undef LWS_WITH_SMTP */ +/* #undef LWS_WITH_SOCKS5 */ +/* #undef LWS_WITH_STATEFUL_URLDECODE */ +/* #undef LWS_WITH_STATS */ +/* #undef LWS_WITH_STRUCT_SQLITE3 */ +/* #undef LWS_WITH_STRUCT_JSON */ +/* #undef LWS_WITH_SUL_DEBUGGING */ +/* #undef LWS_WITH_SQLITE3 */ +/* #undef LWS_WITH_SYS_DHCP_CLIENT */ +/* #undef LWS_WITH_SYS_FAULT_INJECTION */ +/* #undef LWS_WITH_SYS_METRICS */ +/* #undef LWS_WITH_SYS_NTPCLIENT */ +#define LWS_WITH_SYS_STATE +/* #undef LWS_WITH_THREADPOOL */ +#define LWS_WITH_TLS +/* #undef LWS_WITH_TLS_JIT_TRUST */ +#define LWS_WITH_TLS_SESSIONS +#define LWS_WITH_UDP +/* #undef LWS_WITH_ULOOP */ +#define LWS_WITH_UNIX_SOCK +/* #undef LWS_WITH_ZIP_FOPS */ +/* #undef USE_OLD_CYASSL */ +/* #undef USE_WOLFSSL */ +/* #undef LWS_WITH_EVENT_LIBS */ +#define LWS_WITH_EVLIB_PLUGINS +/* #undef LWS_WITH_LIBUV_INTERNAL */ +/* #undef LWS_WITH_PLUGINS_API */ +#define LWS_HAVE_RTA_PREF + diff --git a/thirdparty/include/mp4v2/chapter.h b/thirdparty/include/mp4v2/chapter.h new file mode 100755 index 0000000000000000000000000000000000000000..5b493a53916a06c91e51b58982099113681d77bd --- /dev/null +++ b/thirdparty/include/mp4v2/chapter.h @@ -0,0 +1,176 @@ +#ifndef MP4V2_CHAPTER_H +#define MP4V2_CHAPTER_H + +/**************************************************************************//** + * + * @defgroup mp4_chapter MP4v2 Chapter + * @{ + * + *****************************************************************************/ + +/** The maximum length of a QuickTime chapter title (in 8-bit chars) + */ +#define MP4V2_CHAPTER_TITLE_MAX 1023 + +/** Chapter item. + * This item defines various attributes for a chapter. + * @ingroup mp4_chapter + */ +typedef struct MP4Chapter_s { + MP4Duration duration; /**< duration of chapter in milliseconds */ + char title[MP4V2_CHAPTER_TITLE_MAX+1]; /**< title of chapter */ +} MP4Chapter_t; + +/** Known chapter types. + * @ingroup mp4_chapter + */ +typedef enum { + MP4ChapterTypeNone = 0, /**< no chapters found return value */ + MP4ChapterTypeAny = 1, /**< any or all known chapter types */ + MP4ChapterTypeQt = 2, /**< QuickTime chapter type */ + MP4ChapterTypeNero = 4 /**< Nero chapter type */ +} MP4ChapterType; + +/** Add a QuickTime chapter. + * + * This function adds a QuickTime chapter to file hFile. + * + * @param hFile handle of file to add chapter. + * @param chapterTrackId ID of chapter track or #MP4_INVALID_TRACK_ID + * if unknown. + * @param chapterDuration duration (in the timescale of the chapter track). + * @param chapterTitle title text for the chapter or NULL to use default + * title format ("Chapter %03d", n) where n is the chapter number. + */ +MP4V2_EXPORT +void MP4AddChapter( + MP4FileHandle hFile, + MP4TrackId chapterTrackId, + MP4Duration chapterDuration, + const char* chapterTitle DEFAULT(0)); + +/** Add a QuickTime chapter track. + * + * This function adds a chapter (text) track to file hFile. + * The optional parameter timescale may be supplied to give the new + * chapter a specific timescale. Otherwise the chapter track will have + * the same timescale as the reference track defined in parameter refTrackId. + * + * @param hFile handle of file to add chapter track. + * @param refTrackId ID of the track that will reference the chapter track. + * @param timescale the timescale of the chapter track or 0 to use the + * timescale of track specified by refTrackId. + * + * @return ID of the created chapter track. + */ +MP4V2_EXPORT +MP4TrackId MP4AddChapterTextTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId, + uint32_t timescale DEFAULT(0) ); + +/** Add a Nero chapter. + * + * This function adds a Nero chapter to file hFile. + * + * @param hFile handle of file to add chapter. + * @param chapterStart the start time of the chapter in 100 nanosecond units + * @param chapterTitle title text for the chapter or NULL to use default + * title format ("Chapter %03d", n) where n is the chapter number. + */ +MP4V2_EXPORT +void MP4AddNeroChapter( + MP4FileHandle hFile, + MP4Timestamp chapterStart, + const char* chapterTitle DEFAULT(0)); + +/** Convert chapters to another type. + * + * This function converts existing chapters in file hFile + * from one type to another type. + * Conversion from Nero to QuickTime or QuickTime to Nero is supported. + * + * @param hFile handle of file to convert. + * @param toChapterType the chapter type to convert to: + * @li #MP4ChapterTypeQt (convert from Nero to Qt) + * @li #MP4ChapterTypeNero (convert from Qt to Nero) + * + * @return the chapter type before conversion or #MP4ChapterTypeNone + * if the source chapters do not exist + * or invalid toChapterType was specified. + */ +MP4V2_EXPORT +MP4ChapterType MP4ConvertChapters( + MP4FileHandle hFile, + MP4ChapterType toChapterType DEFAULT(MP4ChapterTypeQt)); + +/** Delete chapters. + * + * This function deletes existing chapters in file hFile. + * + * @param hFile handle of file to delete chapters. + * @param chapterType the type of chapters to delete: + * @li #MP4ChapterTypeAny (delete all known chapter types) + * @li #MP4ChapterTypeQt + * @li #MP4ChapterTypeNero + * @param chapterTrackId ID of the chapter track if known, + * or #MP4_INVALID_TRACK_ID. + * Only applies when chapterType=#MP4ChapterTypeQt. + * + * @return the type of deleted chapters + */ +MP4V2_EXPORT +MP4ChapterType MP4DeleteChapters( + MP4FileHandle hFile, + MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt), + MP4TrackId chapterTrackId DEFAULT(MP4_INVALID_TRACK_ID) ); + +/** Get list of chapters. + * + * This function gets a chpter list from file hFile. + * + * @param hFile handle of file to read. + * @param chapterList address receiving array of chapter items. + * If a non-NULL is received the caller is responsible for freeing the + * memory with MP4Free(). + * @param chapterCount address receiving count of items in array. + * @param chapterType the type of chapters to read: + * @li #MP4ChapterTypeAny (any chapters, searched in order of Qt, Nero) + * @li #MP4ChapterTypeQt + * @li #MP4ChapterTypeNero + * + * @result the first type of chapters found. + */ +MP4V2_EXPORT +MP4ChapterType MP4GetChapters( + MP4FileHandle hFile, + MP4Chapter_t** chapterList, + uint32_t* chapterCount, + MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt)); + +/** Set list of chapters OKOK. + * + * This functions sets the complete chapter list in file hFile. + * If any chapters of the same type already exist they will first + * be deleted. + * + * @param hFile handle of file to modify. + * @param chapterList array of chapters items. + * @param chapterCount count of items in array. + * @param chapterType type of chapters to write: + * @li #MP4ChapterTypeAny (chapters of all types are written) + * @li #MP4ChapterTypeQt + * @li #MP4ChapterTypeNero + * + * @return the type of chapters written. + */ +MP4V2_EXPORT +MP4ChapterType MP4SetChapters( + MP4FileHandle hFile, + MP4Chapter_t* chapterList, + uint32_t chapterCount, + MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt)); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_CHAPTER_H */ diff --git a/thirdparty/include/mp4v2/file.h b/thirdparty/include/mp4v2/file.h new file mode 100755 index 0000000000000000000000000000000000000000..fc0c5ef93b6b33fdd5864bb4bf6c0ec8080eebff --- /dev/null +++ b/thirdparty/include/mp4v2/file.h @@ -0,0 +1,362 @@ +#ifndef MP4V2_FILE_H +#define MP4V2_FILE_H + +/**************************************************************************//** + * + * @defgroup mp4_file MP4v2 File I/O + * @{ + * + *****************************************************************************/ + +/** Bit: enable 64-bit data-atoms. */ +#define MP4_CREATE_64BIT_DATA 0x01 +/** Bit: enable 64-bit time-atoms. @note Incompatible with QuickTime. */ +#define MP4_CREATE_64BIT_TIME 0x02 +/** Bit: do not recompute avg/max bitrates on file close. @note See http://code.google.com/p/mp4v2/issues/detail?id=66 */ +#define MP4_CLOSE_DO_NOT_COMPUTE_BITRATE 0x01 + +/** Enumeration of file modes for custom file provider. */ +typedef enum MP4FileMode_e +{ + FILEMODE_UNDEFINED, /**< undefined */ + FILEMODE_READ, /**< file may be read */ + FILEMODE_MODIFY, /**< file may be read/written */ + FILEMODE_CREATE /**< file will be created/truncated for read/write */ +} MP4FileMode; + +/** Structure of functions implementing custom file provider. + * + * Except for open, all the functions must return a true value + * to indicate failure or false on success. The open function must return + * a pointer or handle which represents the open file, otherwise NULL. + * + * maxChunkSize is a hint suggesting what the max size of data should be read + * as in underlying read/write operations. A value of 0 indicates there is no hint. + */ +typedef struct MP4FileProvider_s +{ + void* ( *open )( const char* name, MP4FileMode mode ); + int ( *seek )( void* handle, int64_t pos ); + int ( *read )( void* handle, void* buffer, int64_t size, int64_t* nin, int64_t maxChunkSize ); + int ( *write )( void* handle, const void* buffer, int64_t size, int64_t* nout, int64_t maxChunkSize ); + int ( *close )( void* handle ); +} MP4FileProvider; + +/** Close an mp4 file. + * MP4Close closes a previously opened mp4 file. If the file was opened + * writable with MP4Create() or MP4Modify(), then MP4Close() will write + * out all pending information to disk. + * + * @param hFile handle of file to close. + * @param flags bitmask that allows the user to set extra options for the + * close commands. Valid options include: + * @li #MP4_CLOSE_DO_NOT_COMPUTE_BITRATE + */ +MP4V2_EXPORT +void MP4Close( + MP4FileHandle hFile, + uint32_t flags DEFAULT(0) ); + +/** Create a new mp4 file. + * + * MP4Create is the first call that should be used when you want to create + * a new, empty mp4 file. It is equivalent to opening a file for writing, + * but also involved with creation of necessary mp4 framework structures. + * ie. invoking MP4Create() followed by MP4Close() will result in a file + * with a non-zero size. + * + * @param fileName pathname of the file to be created. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param flags bitmask that allows the user to set 64-bit values for + * data or time atoms. Valid bits may be any combination of: + * @li #MP4_CREATE_64BIT_DATA + * @li #MP4_CREATE_64BIT_TIME + * + * @return On success a handle of the newly created file for use in + * subsequent calls to the library. + * On error, #MP4_INVALID_FILE_HANDLE. + */ +MP4V2_EXPORT +MP4FileHandle MP4Create( + const char* fileName, + uint32_t flags DEFAULT(0) ); + +/** Create a new mp4 file with extended options. + * + * MP4CreateEx is an extended version of MP4Create(). + * + * @param fileName pathname of the file to be created. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param flags bitmask that allows the user to set 64-bit values for + * data or time atoms. Valid bits may be any combination of: + * @li #MP4_CREATE_64BIT_DATA + * @li #MP4_CREATE_64BIT_TIME + * @param add_ftyp if true an ftyp atom is automatically created. + * @param add_iods if true an iods atom is automatically created. + * @param majorBrand ftyp brand identifier. + * @param minorVersion ftyp informative integer for the minor version + * of the major brand. + * @param compatibleBrands ftyp list of compatible brands. + * @param compatibleBrandsCount is the count of items specified in + * compatibleBrands. + * + * @return On success a handle of the newly created file for use in + * subsequent calls to the library. + * On error, #MP4_INVALID_FILE_HANDLE. + */ +MP4V2_EXPORT +MP4FileHandle MP4CreateEx( + const char* fileName, + uint32_t flags DEFAULT(0), + int add_ftyp DEFAULT(1), + int add_iods DEFAULT(1), + char* majorBrand DEFAULT(0), + uint32_t minorVersion DEFAULT(0), + char** compatibleBrands DEFAULT(0), + uint32_t compatibleBrandsCount DEFAULT(0) ); + +/** Dump mp4 file contents as ASCII either to stdout or the + * log callback (@p see MP4SetLogCallback) + * + * Dump is an invaluable debugging tool in that in can reveal all the details + * of the mp4 control structures. However, the output will not make much sense + * until you familiarize yourself with the mp4 specification (or the Quicktime + * File Format specification). + * + + * Note that MP4Dump() will not print the individual values of control tables, + * such as the size of each sample, unless the current log level is at least + * #MP4_LOG_VERBOSE2. @p see MP4LogSetLevel() for how to set this. + * + * @param hFile handle of file to dump. + * @param dumpImplicits prints properties which would not actually be + * written to the mp4 file, but still exist in mp4 control structures. + * ie. they are implicit given the current values of other controlling + * properties. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4Dump( + MP4FileHandle hFile, + bool dumpImplicits DEFAULT(0) ); + +/** Return a textual summary of an mp4 file. + * + * MP4FileInfo provides a string that contains a textual summary of the + * contents of an mp4 file. This includes the track id's, the track type, + * and track specific information. For example, for a video track, media + * encoding, image size, frame rate, and bitrate are summarized. + * + * Note that the returned string is malloc'ed, so it is the caller's + * responsibility to free() the string. Also note that the returned string + * contains newlines and tabs which may or may not be desirable. + * + * The following is an example of the output of MP4Info(): +@verbatim +Track Type Info +1 video MPEG-4 Simple @ L3, 119.625 secs, 1008 kbps, 352x288 @ 24.00 fps +2 audio MPEG-4, 119.327 secs, 128 kbps, 44100 Hz +3 hint Payload MP4V-ES for track 1 +4 hint Payload mpeg4-generic for track 2 +5 od Object Descriptors +6 scene BIFS +@endverbatim + * + * @param fileName pathname to mp4 file to summarize. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param trackId specifies track to summarize. If the value is + * #MP4_INVALID_TRACK_ID, the summary info is created for all + * tracks in the file. + * + * @return On success a malloc'd string containing summary information. + * On failure, NULL. + * + * @see MP4Info(). + */ +MP4V2_EXPORT +char* MP4FileInfo( + const char* fileName, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) ); + +/** Accessor for the filename associated with a file handle + * + * @param hFile a file handle + * + * @return the NUL-terminated, UTF-8 encoded filename + * associated with @p hFile + */ +MP4V2_EXPORT +const char* MP4GetFilename( + MP4FileHandle hFile ); + +/** Return a textual summary of an mp4 file. + * + * MP4FileInfo provides a string that contains a textual summary of the + * contents of an mp4 file. This includes the track id's, the track type, + * and track specific information. For example, for a video track, media + * encoding, image size, frame rate, and bitrate are summarized. + * + * Note that the returned string is malloc'ed, so it is the caller's + * responsibility to free() the string. Also note that the returned string + * contains newlines and tabs which may or may not be desirable. + * + * The following is an example of the output of MP4Info(): +@verbatim +Track Type Info +1 video MPEG-4 Simple @ L3, 119.625 secs, 1008 kbps, 352x288 @ 24.00 fps +2 audio MPEG-4, 119.327 secs, 128 kbps, 44100 Hz +3 hint Payload MP4V-ES for track 1 +4 hint Payload mpeg4-generic for track 2 +5 od Object Descriptors +6 scene BIFS +@endverbatim + * + * @param hFile handle of file to summarize. + * @param trackId specifies track to summarize. If the value is + * #MP4_INVALID_TRACK_ID, the summary info is created for all + * tracks in the file. + * + * @return On success a malloc'd string containing summary information. + * On failure, NULL. + * + * @see MP4FileInfo(). + */ +MP4V2_EXPORT +char* MP4Info( + MP4FileHandle hFile, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) ); + +/** Modify an existing mp4 file. + * + * MP4Modify is the first call that should be used when you want to modify + * an existing mp4 file. It is roughly equivalent to opening a file in + * read/write mode. + * + * Since modifications to an existing mp4 file can result in a sub-optimal + * file layout, you may want to use MP4Optimize() after you have modified + * and closed the mp4 file. + * + * @param fileName pathname of the file to be modified. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param flags currently ignored. + * + * @return On success a handle of the target file for use in subsequent calls + * to the library. + * On error, #MP4_INVALID_FILE_HANDLE. + */ +MP4V2_EXPORT +MP4FileHandle MP4Modify( + const char* fileName, + uint32_t flags DEFAULT(0) ); + +/** Optimize the layout of an mp4 file. + * + * MP4Optimize reads an existing mp4 file and writes a new version of the + * file with the two important changes: + * + * First, the mp4 control information is moved to the beginning of the file. + * (Frequenty it is at the end of the file due to it being constantly + * modified as track samples are added to an mp4 file). This optimization + * is useful in that in allows the mp4 file to be HTTP streamed. + * + * Second, the track samples are interleaved so that the samples for a + * particular instant in time are colocated within the file. This + * eliminates disk seeks during playback of the file which results in + * better performance. + * + * There are also two important side effects of MP4Optimize(): + * + * First, any free blocks within the mp4 file are eliminated. + * + * Second, as a side effect of the sample interleaving process any media + * data chunks that are not actually referenced by the mp4 control + * structures are deleted. This is useful if you have called MP4DeleteTrack() + * which only deletes the control information for a track, and not the + * actual media data. + * + * @param fileName pathname of (existing) file to be optimized. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param newFileName pathname of the new optimized file. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * If NULL a temporary file in the same directory as the + * fileName will be used and fileName + * will be over-written upon successful completion. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4Optimize( + const char* fileName, + const char* newFileName DEFAULT(NULL) ); + + +/** Read an existing mp4 file. + * + * MP4Read is the first call that should be used when you want to just + * read an existing mp4 file. It is equivalent to opening a file for + * reading, but in addition the mp4 file is parsed and the control + * information is loaded into memory. Note that actual track samples are not + * read into memory until MP4ReadSample() is called. + * + * @param fileName pathname of the file to be read. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). +( + * @return On success a handle of the file for use in subsequent calls to + * the library. + * On error, #MP4_INVALID_FILE_HANDLE. + */ +MP4V2_EXPORT +MP4FileHandle MP4Read( + const char* fileName ); + +/** Read an existing mp4 file. + * + * MP4ReadProvider is the first call that should be used when you want to just + * read an existing mp4 file. It is equivalent to opening a file for + * reading, but in addition the mp4 file is parsed and the control + * information is loaded into memory. Note that actual track samples are not + * read into memory until MP4ReadSample() is called. + * + * @param fileName pathname of the file to be read. + * On Windows, this should be a UTF-8 encoded string. + * On other platforms, it should be an 8-bit encoding that is + * appropriate for the platform, locale, file system, etc. + * (prefer to use UTF-8 when possible). + * @param fileProvider custom implementation of file I/O operations. + * All functions in structure must be implemented. + * The structure is immediately copied internally. + * + * @return On success a handle of the file for use in subsequent calls to + * the library. + * On error, #MP4_INVALID_FILE_HANDLE. + */ +MP4V2_EXPORT +MP4FileHandle MP4ReadProvider( + const char* fileName, + const MP4FileProvider* fileProvider DEFAULT(NULL) ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_FILE_H */ diff --git a/thirdparty/include/mp4v2/file_prop.h b/thirdparty/include/mp4v2/file_prop.h new file mode 100755 index 0000000000000000000000000000000000000000..15435e83378804d6db679c2c4687e7969beb34c0 --- /dev/null +++ b/thirdparty/include/mp4v2/file_prop.h @@ -0,0 +1,148 @@ +#ifndef MP4V2_FILE_PROP_H +#define MP4V2_FILE_PROP_H + +/**************************************************************************//** + * + * @defgroup mp4_file_prop MP4v2 File Property + * @{ + * + *****************************************************************************/ + +/* generic props */ + +MP4V2_EXPORT +bool MP4HaveAtom( + MP4FileHandle hFile, + const char* atomName ); + +MP4V2_EXPORT +bool MP4GetIntegerProperty( + MP4FileHandle hFile, + const char* propName, + uint64_t* retval ); + +MP4V2_EXPORT +bool MP4GetFloatProperty( + MP4FileHandle hFile, + const char* propName, + float* retvalue ); + +MP4V2_EXPORT +bool MP4GetStringProperty( + MP4FileHandle hFile, + const char* propName, + const char** retvalue ); + +MP4V2_EXPORT +bool MP4GetBytesProperty( + MP4FileHandle hFile, + const char* propName, + uint8_t** ppValue, + uint32_t* pValueSize ); + +MP4V2_EXPORT +bool MP4SetIntegerProperty( + MP4FileHandle hFile, + const char* propName, + int64_t value ); + +MP4V2_EXPORT +bool MP4SetFloatProperty( + MP4FileHandle hFile, + const char* propName, + float value ); + +MP4V2_EXPORT +bool MP4SetStringProperty( + MP4FileHandle hFile, + const char* propName, + const char* value ); + +MP4V2_EXPORT +bool MP4SetBytesProperty( + MP4FileHandle hFile, + const char* propName, + const uint8_t* pValue, + uint32_t valueSize ); + +/* specific props */ + +MP4V2_EXPORT +MP4Duration MP4GetDuration( MP4FileHandle hFile ); + +/** Get the time scale of the movie (file). + * + * MP4GetTimeScale returns the time scale in units of ticks per second for + * the mp4 file. Caveat: tracks may use the same time scale as the movie + * or may use their own time scale. + * + * @param hFile handle of file for operation. + * + * @return timescale (ticks per second) of the mp4 file. + */ +MP4V2_EXPORT +uint32_t MP4GetTimeScale( MP4FileHandle hFile ); + +/** Set the time scale of the movie (file). + * + * MP4SetTimeScale sets the time scale of the mp4 file. The time scale is + * in the number of clock ticks per second. Caveat: tracks may use the + * same time scale as the movie or may use their own time scale. + * + * @param hFile handle of file for operation. + * @param value desired timescale for the movie. + * + * @return On success, true. On failure, false. + */ +MP4V2_EXPORT +bool MP4SetTimeScale( MP4FileHandle hFile, uint32_t value ); + +/** Change the general timescale of file hFile. + * + * This function changes the general timescale of the file hFile + * to the new timescale value by recalculating all values that depend + * on the timescale in "moov.mvhd". + * + * If the timescale is already equal to value nothing is done. + * + * @param hFile handle of file to change. + * @param value the new timescale. + */ +MP4V2_EXPORT +void MP4ChangeMovieTimeScale( MP4FileHandle hFile, uint32_t value ); + +MP4V2_EXPORT +uint8_t MP4GetODProfileLevel( MP4FileHandle hFile ); + +MP4V2_EXPORT +bool MP4SetODProfileLevel( MP4FileHandle hFile, uint8_t value ); + +MP4V2_EXPORT +uint8_t MP4GetSceneProfileLevel( MP4FileHandle hFile ); + +MP4V2_EXPORT +bool MP4SetSceneProfileLevel( MP4FileHandle hFile, uint8_t value ); + +MP4V2_EXPORT +uint8_t MP4GetVideoProfileLevel( + MP4FileHandle hFile, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +void MP4SetVideoProfileLevel( MP4FileHandle hFile, uint8_t value ); + +MP4V2_EXPORT +uint8_t MP4GetAudioProfileLevel( MP4FileHandle hFile ); + +MP4V2_EXPORT +void MP4SetAudioProfileLevel( MP4FileHandle hFile, uint8_t value ); + +MP4V2_EXPORT +uint8_t MP4GetGraphicsProfileLevel( MP4FileHandle hFile ); + +MP4V2_EXPORT +bool MP4SetGraphicsProfileLevel( MP4FileHandle hFile, uint8_t value ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_FILE_PROP_H */ diff --git a/thirdparty/include/mp4v2/general.h b/thirdparty/include/mp4v2/general.h new file mode 100755 index 0000000000000000000000000000000000000000..f9713bf79366bcd124777bc4b7f29658c7ec70ab --- /dev/null +++ b/thirdparty/include/mp4v2/general.h @@ -0,0 +1,495 @@ +#ifndef MP4V2_GENERAL_H +#define MP4V2_GENERAL_H + +/**************************************************************************//** + * + * @defgroup mp4_general MP4v2 General + * @{ + * + *****************************************************************************/ + +/* MP4 API types */ +typedef void* MP4FileHandle; +typedef uint32_t MP4TrackId; +typedef uint32_t MP4SampleId; +typedef uint64_t MP4Timestamp; +typedef uint64_t MP4Duration; +typedef uint32_t MP4EditId; + +typedef enum { + MP4_LOG_NONE = 0, + MP4_LOG_ERROR = 1, + MP4_LOG_WARNING = 2, + MP4_LOG_INFO = 3, + MP4_LOG_VERBOSE1 = 4, + MP4_LOG_VERBOSE2 = 5, + MP4_LOG_VERBOSE3 = 6, + MP4_LOG_VERBOSE4 = 7 +} MP4LogLevel; + +/*****************************************************************************/ + +typedef void (*MP4LogCallback)( + MP4LogLevel loglevel, + const char* fmt, + va_list ap ); + +/*****************************************************************************/ + +/** Encryption function pointer. + * + * @see MP4EncAndCopySample(). + * @see MP4EncAndCopyTrack(). + */ +typedef uint32_t (*encryptFunc_t)( uint32_t, uint32_t, uint8_t*, uint32_t*, uint8_t** ); + +/*****************************************************************************/ + +#define MP4_INVALID_FILE_HANDLE ((MP4FileHandle)NULL) /**< Constant: invalid MP4FileHandle. */ +#define MP4_INVALID_TRACK_ID ((MP4TrackId)0) /**< Constant: invalid MP4TrackId. */ +#define MP4_INVALID_SAMPLE_ID ((MP4SampleId)0) /**< Constant: invalid MP4SampleId. */ +#define MP4_INVALID_TIMESTAMP ((MP4Timestamp)-1) /**< Constant: invalid MP4Timestamp. */ +#define MP4_INVALID_DURATION ((MP4Duration)-1) /**< Constant: invalid MP4Duration. */ +#define MP4_INVALID_EDIT_ID ((MP4EditId)0) /**< Constant: invalid MP4EditId. */ + +/* Macros to test for API type validity */ +#define MP4_IS_VALID_FILE_HANDLE(x) ((x) != MP4_INVALID_FILE_HANDLE) +#define MP4_IS_VALID_TRACK_ID(x) ((x) != MP4_INVALID_TRACK_ID) +#define MP4_IS_VALID_SAMPLE_ID(x) ((x) != MP4_INVALID_SAMPLE_ID) +#define MP4_IS_VALID_TIMESTAMP(x) ((x) != MP4_INVALID_TIMESTAMP) +#define MP4_IS_VALID_DURATION(x) ((x) != MP4_INVALID_DURATION) +#define MP4_IS_VALID_EDIT_ID(x) ((x) != MP4_INVALID_EDIT_ID) + +/* + * MP4 Known track type names - e.g. MP4GetNumberOfTracks(type) + * + * Note this first group of track types should be created + * via the MP4AddTrack() functions, and not MP4AddTrack(type) + */ +#define MP4_OD_TRACK_TYPE "odsm" /**< Constant: OD track. */ +#define MP4_SCENE_TRACK_TYPE "sdsm" /**< Constant: scene track. */ +#define MP4_AUDIO_TRACK_TYPE "soun" /**< Constant: audio track. */ +#define MP4_VIDEO_TRACK_TYPE "vide" /**< Constant: video track. */ +#define MP4_HINT_TRACK_TYPE "hint" /**< Constant: hint track. */ +#define MP4_CNTL_TRACK_TYPE "cntl" /**< Constant: control track. */ +#define MP4_TEXT_TRACK_TYPE "text" /**< Constant: text track. */ +#define MP4_SUBTITLE_TRACK_TYPE "sbtl" /**< Constant: subtitle track. */ +#define MP4_SUBPIC_TRACK_TYPE "subp" /**< Constant: subpic track. */ +/* + * This second set of track types should be created + * via MP4AddSystemsTrack(type) + */ +#define MP4_CLOCK_TRACK_TYPE "crsm" /**< Constant: clock track. */ +#define MP4_MPEG7_TRACK_TYPE "m7sm" /**< Constant: mpeg7 track. */ +#define MP4_OCI_TRACK_TYPE "ocsm" /**< Constant: OCI track. */ +#define MP4_IPMP_TRACK_TYPE "ipsm" /**< Constant: IPMP track. */ +#define MP4_MPEGJ_TRACK_TYPE "mjsm" /**< Constant: MPEGJ track. */ + +#define MP4_IS_VIDEO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_VIDEO_TRACK_TYPE)) + +#define MP4_IS_AUDIO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_AUDIO_TRACK_TYPE)) + +#define MP4_IS_CNTL_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CNTL_TRACK_TYPE)) + +#define MP4_IS_OD_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_OD_TRACK_TYPE)) + +#define MP4_IS_SCENE_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_SCENE_TRACK_TYPE)) + +#define MP4_IS_HINT_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_HINT_TRACK_TYPE)) + +#define MP4_IS_SYSTEMS_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CLOCK_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEG7_TRACK_TYPE) \ + || !strcasecmp(type, MP4_OCI_TRACK_TYPE) \ + || !strcasecmp(type, MP4_IPMP_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEGJ_TRACK_TYPE)) + +/* MP4 Audio track types - see MP4AddAudioTrack()*/ +#define MP4_INVALID_AUDIO_TYPE 0x00 +#define MP4_MPEG1_AUDIO_TYPE 0x6B +#define MP4_MPEG2_AUDIO_TYPE 0x69 +#define MP4_MP3_AUDIO_TYPE MP4_MPEG2_AUDIO_TYPE +#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE 0x66 +#define MP4_MPEG2_AAC_LC_AUDIO_TYPE 0x67 +#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE 0x68 +#define MP4_MPEG2_AAC_AUDIO_TYPE MP4_MPEG2_AAC_MAIN_AUDIO_TYPE +#define MP4_MPEG4_AUDIO_TYPE 0x40 +#define MP4_PRIVATE_AUDIO_TYPE 0xC0 +#define MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE 0xE0 /* a private definition */ +#define MP4_VORBIS_AUDIO_TYPE 0xE1 /* a private definition */ +#define MP4_AC3_AUDIO_TYPE 0xE2 /* a private definition */ +#define MP4_ALAW_AUDIO_TYPE 0xE3 /* a private definition */ +#define MP4_ULAW_AUDIO_TYPE 0xE4 /* a private definition */ +#define MP4_G723_AUDIO_TYPE 0xE5 /* a private definition */ +#define MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE 0xE6 /* a private definition */ + +/* MP4 MPEG-4 Audio types from 14496-3 Table 1.5.1 */ +#define MP4_MPEG4_INVALID_AUDIO_TYPE 0 +#define MP4_MPEG4_AAC_MAIN_AUDIO_TYPE 1 +#define MP4_MPEG4_AAC_LC_AUDIO_TYPE 2 +#define MP4_MPEG4_AAC_SSR_AUDIO_TYPE 3 +#define MP4_MPEG4_AAC_LTP_AUDIO_TYPE 4 +#define MP4_MPEG4_AAC_HE_AUDIO_TYPE 5 +#define MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE 6 +#define MP4_MPEG4_CELP_AUDIO_TYPE 8 +#define MP4_MPEG4_HVXC_AUDIO_TYPE 9 +#define MP4_MPEG4_TTSI_AUDIO_TYPE 12 +#define MP4_MPEG4_MAIN_SYNTHETIC_AUDIO_TYPE 13 +#define MP4_MPEG4_WAVETABLE_AUDIO_TYPE 14 +#define MP4_MPEG4_MIDI_AUDIO_TYPE 15 +#define MP4_MPEG4_ALGORITHMIC_FX_AUDIO_TYPE 16 +#define MP4_MPEG4_ALS_AUDIO_TYPE 31 +#define MP4_MPEG4_LAYER1_AUDIO_TYPE 32 +#define MP4_MPEG4_LAYER2_AUDIO_TYPE 33 +#define MP4_MPEG4_LAYER3_AUDIO_TYPE 34 +#define MP4_MPEG4_SLS_AUDIO_TYPE 35 + +/* MP4 Audio type utilities following common usage */ +#define MP4_IS_MP3_AUDIO_TYPE(type) \ + ((type) == MP4_MPEG1_AUDIO_TYPE || (type) == MP4_MPEG2_AUDIO_TYPE) + +#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + (((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \ + && (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE)) + +#define MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4Type) \ + (((mpeg4Type) >= MP4_MPEG4_AAC_MAIN_AUDIO_TYPE \ + && (mpeg4Type) <= MP4_MPEG4_AAC_HE_AUDIO_TYPE) \ + || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \ + || (mpeg4Type) == 17) + +#define MP4_IS_AAC_AUDIO_TYPE(type) \ + (MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + || (type) == MP4_MPEG4_AUDIO_TYPE) + +/* MP4 Video track types - see MP4AddVideoTrack() */ +#define MP4_INVALID_VIDEO_TYPE 0x00 +#define MP4_MPEG1_VIDEO_TYPE 0x6A +#define MP4_MPEG2_SIMPLE_VIDEO_TYPE 0x60 +#define MP4_MPEG2_MAIN_VIDEO_TYPE 0x61 +#define MP4_MPEG2_SNR_VIDEO_TYPE 0x62 +#define MP4_MPEG2_SPATIAL_VIDEO_TYPE 0x63 +#define MP4_MPEG2_HIGH_VIDEO_TYPE 0x64 +#define MP4_MPEG2_442_VIDEO_TYPE 0x65 +#define MP4_MPEG2_VIDEO_TYPE MP4_MPEG2_MAIN_VIDEO_TYPE +#define MP4_MPEG4_VIDEO_TYPE 0x20 +#define MP4_JPEG_VIDEO_TYPE 0x6C +#define MP4_PRIVATE_VIDEO_TYPE 0xD0 +#define MP4_YUV12_VIDEO_TYPE 0xF0 /* a private definition */ +#define MP4_H263_VIDEO_TYPE 0xF2 /* a private definition */ +#define MP4_H261_VIDEO_TYPE 0xF3 /* a private definition */ + +/* MP4 Video type utilities */ +#define MP4_IS_MPEG1_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG1_VIDEO_TYPE) + +#define MP4_IS_MPEG2_VIDEO_TYPE(type) \ + (((type) >= MP4_MPEG2_SIMPLE_VIDEO_TYPE \ + && (type) <= MP4_MPEG2_442_VIDEO_TYPE) \ + || MP4_IS_MPEG1_VIDEO_TYPE(type)) + +#define MP4_IS_MPEG4_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG4_VIDEO_TYPE) + +/* Mpeg4 Visual Profile Defines - ISO/IEC 14496-2:2001/Amd.2:2002(E) */ +#define MPEG4_SP_L1 (0x1) +#define MPEG4_SP_L2 (0x2) +#define MPEG4_SP_L3 (0x3) +#define MPEG4_SP_L0 (0x8) +#define MPEG4_SSP_L1 (0x11) +#define MPEG4_SSP_L2 (0x12) +#define MPEG4_CP_L1 (0x21) +#define MPEG4_CP_L2 (0x22) +#define MPEG4_MP_L2 (0x32) +#define MPEG4_MP_L3 (0x33) +#define MPEG4_MP_L4 (0x34) +#define MPEG4_NBP_L2 (0x42) +#define MPEG4_STP_L1 (0x51) +#define MPEG4_SFAP_L1 (0x61) +#define MPEG4_SFAP_L2 (0x62) +#define MPEG4_SFBAP_L1 (0x63) +#define MPEG4_SFBAP_L2 (0x64) +#define MPEG4_BATP_L1 (0x71) +#define MPEG4_BATP_L2 (0x72) +#define MPEG4_HP_L1 (0x81) +#define MPEG4_HP_L2 (0x82) +#define MPEG4_ARTSP_L1 (0x91) +#define MPEG4_ARTSP_L2 (0x92) +#define MPEG4_ARTSP_L3 (0x93) +#define MPEG4_ARTSP_L4 (0x94) +#define MPEG4_CSP_L1 (0xa1) +#define MPEG4_CSP_L2 (0xa2) +#define MPEG4_CSP_L3 (0xa3) +#define MPEG4_ACEP_L1 (0xb1) +#define MPEG4_ACEP_L2 (0xb2) +#define MPEG4_ACEP_L3 (0xb3) +#define MPEG4_ACEP_L4 (0xb4) +#define MPEG4_ACP_L1 (0xc1) +#define MPEG4_ACP_L2 (0xc2) +#define MPEG4_AST_L1 (0xd1) +#define MPEG4_AST_L2 (0xd2) +#define MPEG4_AST_L3 (0xd3) +#define MPEG4_S_STUDIO_P_L1 (0xe1) +#define MPEG4_S_STUDIO_P_L2 (0xe2) +#define MPEG4_S_STUDIO_P_L3 (0xe3) +#define MPEG4_S_STUDIO_P_L4 (0xe4) +#define MPEG4_C_STUDIO_P_L1 (0xe5) +#define MPEG4_C_STUDIO_P_L2 (0xe6) +#define MPEG4_C_STUDIO_P_L3 (0xe7) +#define MPEG4_C_STUDIO_P_L4 (0xe8) +#define MPEG4_ASP_L0 (0xF0) +#define MPEG4_ASP_L1 (0xF1) +#define MPEG4_ASP_L2 (0xF2) +#define MPEG4_ASP_L3 (0xF3) +#define MPEG4_ASP_L4 (0xF4) +#define MPEG4_ASP_L5 (0xF5) +#define MPEG4_ASP_L3B (0xF7) +#define MPEG4_FGSP_L0 (0xf8) +#define MPEG4_FGSP_L1 (0xf9) +#define MPEG4_FGSP_L2 (0xfa) +#define MPEG4_FGSP_L3 (0xfb) +#define MPEG4_FGSP_L4 (0xfc) +#define MPEG4_FGSP_L5 (0xfd) + +/*****************************************************************************/ + +/* 3GP specific utilities */ + +MP4V2_EXPORT +bool MP4Make3GPCompliant( + const char* fileName, + char* majorBrand DEFAULT(0), + uint32_t minorVersion DEFAULT(0), + char** supportedBrands DEFAULT(NULL), + uint32_t supportedBrandsCount DEFAULT(0), + bool deleteIodsAtom DEFAULT(true) ); + +/* NOTE this section of functionality has not yet been fully tested */ + +MP4V2_EXPORT +MP4EditId MP4AddTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID), + MP4Timestamp startTime DEFAULT(0), + MP4Duration duration DEFAULT(0), + bool dwell DEFAULT(false) ); + +MP4V2_EXPORT +bool MP4DeleteTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId ); + +MP4V2_EXPORT +uint32_t MP4GetTrackNumberOfEdits( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +MP4Timestamp MP4GetTrackEditStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId ); + +MP4V2_EXPORT +MP4Duration MP4GetTrackEditTotalDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID) ); + +MP4V2_EXPORT +MP4Timestamp MP4GetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId ); + +MP4V2_EXPORT +bool MP4SetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime ); + +MP4V2_EXPORT +MP4Duration MP4GetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId ); + +MP4V2_EXPORT +bool MP4SetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration ); + +MP4V2_EXPORT +int8_t MP4GetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId ); + +MP4V2_EXPORT +bool MP4SetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + bool dwell ); + +MP4V2_EXPORT +bool MP4ReadSampleFromEditTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + uint8_t** ppBytes, + uint32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL) ); + +MP4V2_EXPORT +MP4SampleId MP4GetSampleIdFromEditTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL) ); + +/* time conversion utilties */ + +/* predefined values for timeScale parameter below */ +#define MP4_SECONDS_TIME_SCALE 1 +#define MP4_MILLISECONDS_TIME_SCALE 1000 +#define MP4_MICROSECONDS_TIME_SCALE 1000000 +#define MP4_NANOSECONDS_TIME_SCALE 1000000000 + +#define MP4_SECS_TIME_SCALE MP4_SECONDS_TIME_SCALE +#define MP4_MSECS_TIME_SCALE MP4_MILLISECONDS_TIME_SCALE +#define MP4_USECS_TIME_SCALE MP4_MICROSECONDS_TIME_SCALE +#define MP4_NSECS_TIME_SCALE MP4_NANOSECONDS_TIME_SCALE + +MP4V2_EXPORT +uint64_t MP4ConvertFromMovieDuration( + MP4FileHandle hFile, + MP4Duration duration, + uint32_t timeScale ); + +MP4V2_EXPORT +uint64_t MP4ConvertFromTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp timeStamp, + uint32_t timeScale ); + +MP4V2_EXPORT +MP4Timestamp MP4ConvertToTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + uint64_t timeStamp, + uint32_t timeScale ); + +/** Convert duration from track time scale to an arbitrary time scale. + * + * MP4ConvertFromTrackDuration converts a duration such as a sample duration + * from the track time scale to another time scale. This can be used by a + * player application to map all track samples to a common time scale. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration value to be converted. + * @param timeScale time scale in ticks per second. + * + * @return On success, the duration in arbitrary time scale units. + * On error, 0. + * + * @see MP4GetSampleDuration(). + * @see MP4ConvertToTrackDuration(). + */ +MP4V2_EXPORT +uint64_t MP4ConvertFromTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration, + uint32_t timeScale ); + +/** Convert duration from arbitrary time scale to track time scale. + * + * MP4ConvertToTrackDuration converts a duration such as a sample duration + * from the specified time scale to the track time scale. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration value to be converted. + * @param timeScale time scale in ticks per second. + * + * @return On success, the duration in track time scale units. + * On error, #MP4_INVALID_DURATION. + * + * @see MP4ConvertFromTrackDuration(). + */ +MP4V2_EXPORT +MP4Duration MP4ConvertToTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + uint64_t duration, + uint32_t timeScale ); + +MP4V2_EXPORT +char* MP4BinaryToBase16( + const uint8_t* pData, + uint32_t dataSize ); + +MP4V2_EXPORT +char* MP4BinaryToBase64( + const uint8_t* pData, + uint32_t dataSize ); + +MP4V2_EXPORT +uint8_t* Base64ToBinary( + const char* pData, + uint32_t decodeSize, + uint32_t* pDataSize ); + +MP4V2_EXPORT +void MP4Free( + void* p ); + +/** Set the function to call in place of default logging behavior + * + * @param cb_func the function to call + */ +MP4V2_EXPORT +void MP4SetLogCallback( + MP4LogCallback cb_func ); +/** @} ***********************************************************************/ + +/** + * Accessor for the maximum level for diagnostic information + * + * @return the maximum level for diagnostic information + * + * @see MP4LogSetLevel() for further details. + */ +MP4V2_EXPORT +MP4LogLevel MP4LogGetLevel( void ); + +/** + * Set the maximum level for diagnostic information + * + * @param verbosity the level to set + */ +MP4V2_EXPORT +void MP4LogSetLevel( MP4LogLevel verbosity ); + +#endif /* MP4V2_GENERAL_H */ diff --git a/thirdparty/include/mp4v2/isma.h b/thirdparty/include/mp4v2/isma.h new file mode 100755 index 0000000000000000000000000000000000000000..074a06e86fafa687ba5b45bc81967b690de048bd --- /dev/null +++ b/thirdparty/include/mp4v2/isma.h @@ -0,0 +1,96 @@ +#ifndef MP4V2_ISMA_H +#define MP4V2_ISMA_H + +/**************************************************************************//** + * + * @defgroup mp4_isma MP4v2 ISMA (Internet Streaming Media Alliance) + * @{ + * + *****************************************************************************/ + +/** something */ +typedef struct mp4v2_ismacryp_session_params { + uint32_t scheme_type; + uint16_t scheme_version; + uint8_t key_ind_len; + uint8_t iv_len; + uint8_t selective_enc; + const char* kms_uri; +} mp4v2_ismacrypParams; + +/* + * API to initialize ismacryp properties to sensible defaults + * if input param is null then mallocs a params struct + */ + +MP4V2_EXPORT +mp4v2_ismacrypParams* MP4DefaultISMACrypParams( mp4v2_ismacrypParams* ptr ); + +MP4V2_EXPORT +MP4TrackId MP4AddEncAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + mp4v2_ismacrypParams* icPp, + uint8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE) ); + +MP4V2_EXPORT +MP4TrackId MP4AddEncVideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + mp4v2_ismacrypParams* icPp, + uint8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE), + const char* oFormat DEFAULT(NULL) ); + +MP4V2_EXPORT +MP4TrackId MP4AddEncH264VideoTrack( + MP4FileHandle dstFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams* icPp ); + +MP4V2_EXPORT +MP4TrackId MP4EncAndCloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams* icPp, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +MP4TrackId MP4EncAndCopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams* icPp, + encryptFunc_t encfcnp, + uint32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +bool MP4MakeIsmaCompliant( + const char* fileName, + bool addIsmaComplianceSdp DEFAULT(true) ); + +MP4V2_EXPORT +char* MP4MakeIsmaSdpIod( + uint8_t videoProfile, + uint32_t videoBitrate, + uint8_t* videoConfig, + uint32_t videoConfigLength, + uint8_t audioProfile, + uint32_t audioBitrate, + uint8_t* audioConfig, + uint32_t audioConfigLength ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_ISMA_H */ diff --git a/thirdparty/include/mp4v2/itmf_generic.h b/thirdparty/include/mp4v2/itmf_generic.h new file mode 100755 index 0000000000000000000000000000000000000000..b780b1ecb945560bb7be834ca87b31eaa01cc11e --- /dev/null +++ b/thirdparty/include/mp4v2/itmf_generic.h @@ -0,0 +1,207 @@ +#ifndef MP4V2_ITMF_GENERIC_H +#define MP4V2_ITMF_GENERIC_H + +/**************************************************************************//** + * + * @defgroup mp4_itmf_generic MP4v2 iTMF (iTunes Metadata Format) Generic + * @{ + * + * This is a low-level API used to manage iTMF metadata. + * + * It provides support for virtually any kind of iTMF metadata item, + * including meaning atoms, sometimes referred to as reverse-DNS meanings. + * Structures are directly modified; ie: there are no fuctions which + * modify values for you. There is little type-safety, logic checks, or + * specifications compliance checks. For these reasons it is recommended + * to use iTMF Tags API when possible. + * + * At the heart of this API is an #MP4ItmfItem which corresponds to an + * iTMF metadata item atom. The item, and any recursive data structures + * contained within require manual memory management. The general + * rule to follow is that you must always check/free a ptr if you intend + * to resize data. In cases where you know the existing data size is + * exactly what is needed, you may overwrite the buffer contents. + * + * Each item always has at least 1 data elements which corresponds to + * a data atom. Additionally, each item has optional mean and + * name values which correspond to mean and name atoms. + * + * Each #MP4ItmfItem has a list of #MP4ItmfData. Similarily, care must + * be taken to manage memory with one key difference; these structures + * also have a valueSize field. If value is NULL then set valueSize=0. + * Otherwise, set valueSize to the size (in bytes) of value buffer. + * + * In rare cases where the number of data elements in a single item + * is > 1, the user must manually free/alloc/copy the elements + * buffer and update size accordingly. + * + * The mp4 file structure is modified only when MP4AddItem(), + * MP4SetItem() and MP4RemoveItem() are used. Simply free'ing + * the item list does not modify the mp4 file. + * + * iTMF Generic read workflow: + * + * @li MP4ItmfGetItems() + * @li inspect each item... + * @li MP4ItmfItemListFree() + * + * iTMF Generic read/modify/remove workflow: + * + * @li MP4ItmfGetItems() + * @li inspect/modify item... + * @li MP4ItmfSetItem() each modified item... + * @li MP4ItmfRemoveItem()... + * @li MP4ItmfItemListFree() + * + * iTMF Generic add workflow: + * + * @li MP4ItmfItemAlloc() + * @li MP4ItmfAddItem() + * @li MP4ItmfItemFree() + * + * @par Warning: + * Care must be taken when using multiple mechanisms to modify an open mp4 + * file as it is not thread-safe, nor does it permit overlapping different + * API workflows which have a begin/end to their workflow. That is to say + * do not interleave an iTMF Generic workflow with an iTMF Tags workflow. + * + *****************************************************************************/ + +/** Basic types of value data as enumerated in spec. */ +typedef enum MP4ItmfBasicType_e +{ + MP4_ITMF_BT_IMPLICIT = 0, /**< for use with tags for which no type needs to be indicated */ + MP4_ITMF_BT_UTF8 = 1, /**< without any count or null terminator */ + MP4_ITMF_BT_UTF16 = 2, /**< also known as UTF-16BE */ + MP4_ITMF_BT_SJIS = 3, /**< deprecated unless it is needed for special Japanese characters */ + MP4_ITMF_BT_HTML = 6, /**< the HTML file header specifies which HTML version */ + MP4_ITMF_BT_XML = 7, /**< the XML header must identify the DTD or schemas */ + MP4_ITMF_BT_UUID = 8, /**< also known as GUID; stored as 16 bytes in binary (valid as an ID) */ + MP4_ITMF_BT_ISRC = 9, /**< stored as UTF-8 text (valid as an ID) */ + MP4_ITMF_BT_MI3P = 10, /**< stored as UTF-8 text (valid as an ID) */ + MP4_ITMF_BT_GIF = 12, /**< (deprecated) a GIF image */ + MP4_ITMF_BT_JPEG = 13, /**< a JPEG image */ + MP4_ITMF_BT_PNG = 14, /**< a PNG image */ + MP4_ITMF_BT_URL = 15, /**< absolute, in UTF-8 characters */ + MP4_ITMF_BT_DURATION = 16, /**< in milliseconds, 32-bit integer */ + MP4_ITMF_BT_DATETIME = 17, /**< in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits */ + MP4_ITMF_BT_GENRES = 18, /**< a list of enumerated values */ + MP4_ITMF_BT_INTEGER = 21, /**< a signed big-endian integer with length one of { 1,2,3,4,8 } bytes */ + MP4_ITMF_BT_RIAA_PA = 24, /**< RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit ingteger */ + MP4_ITMF_BT_UPC = 25, /**< Universal Product Code, in text UTF-8 format (valid as an ID) */ + MP4_ITMF_BT_BMP = 27, /**< Windows bitmap image */ + + MP4_ITMF_BT_UNDEFINED = 255 /**< undefined */ +} MP4ItmfBasicType; + +/** Data structure. + * Models an iTMF data atom contained in an iTMF metadata item atom. + */ +typedef struct MP4ItmfData_s +{ + uint8_t typeSetIdentifier; /**< always zero. */ + MP4ItmfBasicType typeCode; /**< iTMF basic type. */ + uint32_t locale; /**< always zero. */ + uint8_t* value; /**< may be NULL. */ + uint32_t valueSize; /**< value size in bytes. */ +} MP4ItmfData; + +/** List of data. */ +typedef struct MP4ItmfDataList_s +{ + MP4ItmfData* elements; /**< flat array. NULL when size is zero. */ + uint32_t size; /**< number of elements. */ +} MP4ItmfDataList; + +/** Item structure. + * Models an iTMF metadata item atom contained in an ilst atom. + */ +typedef struct MP4ItmfItem_s +{ + void* __handle; /**< internal use only. */ + + char* code; /**< four-char code identifing atom type. NULL-terminated. */ + char* mean; /**< may be NULL. UTF-8 meaning. NULL-terminated. */ + char* name; /**< may be NULL. UTF-8 name. NULL-terminated. */ + MP4ItmfDataList dataList; /**< list of data. can be zero length. */ +} MP4ItmfItem; + +/** List of items. */ +typedef struct MP4ItmfItemList_s +{ + MP4ItmfItem* elements; /**< flat array. NULL when size is zero. */ + uint32_t size; /**< number of elements. */ +} MP4ItmfItemList; + +/** Allocate an item on the heap. + * @param code four-char code identifying atom type. NULL-terminated. + * @param numData number of data elements to allocate. Must be >= 1. + * @return newly allocated item. + */ +MP4V2_EXPORT MP4ItmfItem* +MP4ItmfItemAlloc( const char* code, uint32_t numData ); + +/** Free an item (deep free). + * @param item to be free'd. + */ +MP4V2_EXPORT void +MP4ItmfItemFree( MP4ItmfItem* item ); + +/** Free an item list (deep free). + * @param itemList to be free'd. + */ +MP4V2_EXPORT void +MP4ItmfItemListFree( MP4ItmfItemList* itemList ); + +/** Get list of all items from file. + * @param hFile handle of file to operate on. + * @return On succes, list of items, which must be free'd. On failure, NULL. + */ +MP4V2_EXPORT MP4ItmfItemList* +MP4ItmfGetItems( MP4FileHandle hFile ); + +/** Get list of items by code from file. + * @param hFile handle of file to operate on. + * @param code four-char code identifying atom type. NULL-terminated. + * @return On succes, list of items, which must be free'd. On failure, NULL. + */ +MP4V2_EXPORT MP4ItmfItemList* +MP4ItmfGetItemsByCode( MP4FileHandle hFile, const char* code ); + +/** Get list of items by meaning from file. + * Implicitly only returns atoms of code @b{----}. + * @param hFile handle of file to operate on. + * @param meaning UTF-8 meaning. NULL-terminated. + * @param name may be NULL. UTF-8 name. NULL-terminated. + * @return On succes, list of items, which must be free'd. On failure, NULL. + */ +MP4V2_EXPORT MP4ItmfItemList* +MP4ItmfGetItemsByMeaning( MP4FileHandle hFile, const char* meaning, const char* name ); + +/** Add an item to file. + * @param hFile handle of file to operate on. + * @param item object to add. + * @return true on success, false on failure. + */ +MP4V2_EXPORT bool +MP4ItmfAddItem( MP4FileHandle hFile, const MP4ItmfItem* item ); + +/** Overwrite an existing item in file. + * @param hFile handle of file to operate on. + * @param item object to overwrite. Must have a valid index obtained from prior get. + * @return true on success, false on failure. + */ +MP4V2_EXPORT bool +MP4ItmfSetItem( MP4FileHandle hFile, const MP4ItmfItem* item ); + +/** Remove an existing item from file. + * @param hFile handle of file to operate on. + * @param item object to remove. Must have a valid index obtained from prior get. + * @return true on success, false on failure. + */ +MP4V2_EXPORT bool +MP4ItmfRemoveItem( MP4FileHandle hFile, const MP4ItmfItem* item ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_ITMF_GENERIC_H */ diff --git a/thirdparty/include/mp4v2/itmf_tags.h b/thirdparty/include/mp4v2/itmf_tags.h new file mode 100755 index 0000000000000000000000000000000000000000..3115a3cd931a55e7689a1fb37627cd1cae4c190e --- /dev/null +++ b/thirdparty/include/mp4v2/itmf_tags.h @@ -0,0 +1,289 @@ +#ifndef MP4V2_ITMF_TAGS_H +#define MP4V2_ITMF_TAGS_H + +/**************************************************************************//** + * + * @defgroup mp4_itmf_tags MP4v2 iTMF (iTunes Metadata Format) Tags + * @{ + * + * This is a high-level API used to manage iTMF metadata. + * + * It provides more type-safety and simplified memory management as compared + * to iTMF Generic API. + * + * At the heart of this API is a read-only structure that holds all known + * items and their current values. The value is always a pointer which if + * NULL indicates its corresponding atom does not exist. Thus, one must + * always check if the pointer is non-NULL before attempting to extract + * its value. + * + * The structure may not be directly modified. Instead, set functions + * corresponding to each item are used to modify the backing-store of + * the read-only structure. Setting the value ptr to NULL will effectively + * remove it. Setting the value ptr to real data will immediately make a + * copy of the value in the backing-store and the read-only structure + * will correctly reflect the change. + * + * The hidden data cache memory is automatically managed. Thus the user need + * only guarantee the data is available during the lifetime of the set-function + * call. + * + * iTMF Tags read workflow: + * + * @li MP4TagsAlloc() + * @li MP4TagsFetch() + * @li inspect each tag of interest... + * @li MP4TagsStore() (if modified) + * @li MP4TagsFree() + * + * iTMF Tags read/modify/add/remove workflow: + * + * @li MP4TagsAlloc() + * @li MP4TagsFetch() + * @li inspect each tag of interest... + * @li MP4TagsSetName(), MP4TagsSetArtist()... + * @li MP4TagsStore() + * @li MP4TagsFree() + * + * @par Warning: + * Care must be taken when using multiple mechanisms to modify an open mp4 + * file as it is not thread-safe, nor does it permit overlapping different + * API workflows which have a begin/end to their workflow. That is to say + * do not interleave an iTMF Generic workflow with an iTMF Tags workflow. + * + *****************************************************************************/ + +/** Enumeration of possible MP4TagArtwork::type values. */ +typedef enum MP4TagArtworkType_e +{ + MP4_ART_UNDEFINED = 0, + MP4_ART_BMP = 1, + MP4_ART_GIF = 2, + MP4_ART_JPEG = 3, + MP4_ART_PNG = 4 +} MP4TagArtworkType; + +/** Data object representing a single piece of artwork. */ +typedef struct MP4TagArtwork_s +{ + void* data; /**< raw picture data */ + uint32_t size; /**< data size in bytes */ + MP4TagArtworkType type; /**< data type */ +} MP4TagArtwork; + +typedef struct MP4TagTrack_s +{ + uint16_t index; + uint16_t total; +} MP4TagTrack; + +typedef struct MP4TagDisk_s +{ + uint16_t index; + uint16_t total; +} MP4TagDisk; + +/** Tags convenience structure. + * + * This structure is used in the tags convenience API which allows for + * simplified retrieval and modification of the majority of known tags. + * + * This is a read-only structure and each tag is present if and only if the + * pointer is a non-NULL value. The actual data is backed by a hidden + * data cache which is only updated when the appropriate metadata set + * function is used, or if MP4TagsFetch() is invoked. Thus, if other API + * is used to manipulate relevent atom structure of the MP4 file, the user + * is responsible for re-fetching the data in this structure. + */ +typedef struct MP4Tags_s +{ + void* __handle; /* internal use only */ + + const char* name; + const char* artist; + const char* albumArtist; + const char* album; + const char* grouping; + const char* composer; + const char* comments; + const char* genre; + const uint16_t* genreType; + const char* releaseDate; + const MP4TagTrack* track; + const MP4TagDisk* disk; + const uint16_t* tempo; + const uint8_t* compilation; + + const char* tvShow; + const char* tvNetwork; + const char* tvEpisodeID; + const uint32_t* tvSeason; + const uint32_t* tvEpisode; + + const char* description; + const char* longDescription; + const char* lyrics; + + const char* sortName; + const char* sortArtist; + const char* sortAlbumArtist; + const char* sortAlbum; + const char* sortComposer; + const char* sortTVShow; + + const MP4TagArtwork* artwork; + uint32_t artworkCount; + + const char* copyright; + const char* encodingTool; + const char* encodedBy; + const char* purchaseDate; + + const uint8_t* podcast; + const char* keywords; /* TODO: Needs testing */ + const char* category; + + const uint8_t* hdVideo; + const uint8_t* mediaType; + const uint8_t* contentRating; + const uint8_t* gapless; + + const char* iTunesAccount; + const uint8_t* iTunesAccountType; + const uint32_t* iTunesCountry; + const uint32_t* contentID; + const uint32_t* artistID; + const uint64_t* playlistID; + const uint32_t* genreID; + const uint32_t* composerID; + const char* xid; +} MP4Tags; + +/** Allocate tags convenience structure for reading and settings tags. + * + * This function allocates a new structure which represents a snapshot + * of all the tags therein, tracking if the tag is missing, + * or present and with value. It is the caller's responsibility to free + * the structure with MP4TagsFree(). + * + * @return structure with all tags missing. + */ +MP4V2_EXPORT +const MP4Tags* MP4TagsAlloc( void ); + +/** Fetch data from mp4 file and populate structure. + * + * The tags structure and its hidden data-cache is updated to + * reflect the actual tags values found in the hFile. + * + * @param tags structure to fetch (write) into. + * @param hFile handle of file to fetch data from. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4TagsFetch( const MP4Tags* tags, MP4FileHandle hFile ); + +/** Store data to mp4 file from structure. + * + * The tags structure is pushed out to the mp4 file, + * adding tags if needed, removing tags if needed, and updating + * the values to modified tags. + * + * @param tags structure to store (read) from. + * @param hFile handle of file to store data to. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4TagsStore( const MP4Tags* tags, MP4FileHandle hFile ); + +/** Free tags convenience structure. + * + * This function frees memory associated with the structure. + * + * @param tags structure to destroy. + */ +MP4V2_EXPORT +void MP4TagsFree( const MP4Tags* tags ); + +/** Accessor that indicates whether a tags structure + * contains any metadata + * + * @param tags the structure to inspect + * + * @param hasMetadata populated with false if @p tags + * contains no metadata, true if @p tags contains metadata + * + * @retval false error determining if @p tags contains + * metadata + * + * @retval true successfully determined if @p tags contains + * metadata + */ +MP4V2_EXPORT +bool MP4TagsHasMetadata ( const MP4Tags* tags, bool *hasMetadata ); + +MP4V2_EXPORT bool MP4TagsSetName ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetArtist ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetAlbumArtist ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetAlbum ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetGrouping ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetComposer ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetComments ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetGenre ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetGenreType ( const MP4Tags*, const uint16_t* ); +MP4V2_EXPORT bool MP4TagsSetReleaseDate ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetTrack ( const MP4Tags*, const MP4TagTrack* ); +MP4V2_EXPORT bool MP4TagsSetDisk ( const MP4Tags*, const MP4TagDisk* ); +MP4V2_EXPORT bool MP4TagsSetTempo ( const MP4Tags*, const uint16_t* ); +MP4V2_EXPORT bool MP4TagsSetCompilation ( const MP4Tags*, const uint8_t* ); + +MP4V2_EXPORT bool MP4TagsSetTVShow ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetTVNetwork ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetTVEpisodeID ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetTVSeason ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetTVEpisode ( const MP4Tags*, const uint32_t* ); + +MP4V2_EXPORT bool MP4TagsSetDescription ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetLongDescription ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetLyrics ( const MP4Tags*, const char* ); + +MP4V2_EXPORT bool MP4TagsSetSortName ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetSortArtist ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetSortAlbumArtist ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetSortAlbum ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetSortComposer ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetSortTVShow ( const MP4Tags*, const char* ); + +MP4V2_EXPORT bool MP4TagsAddArtwork ( const MP4Tags*, MP4TagArtwork* ); +MP4V2_EXPORT bool MP4TagsSetArtwork ( const MP4Tags*, uint32_t, MP4TagArtwork* ); +MP4V2_EXPORT bool MP4TagsRemoveArtwork ( const MP4Tags*, uint32_t ); + +MP4V2_EXPORT bool MP4TagsSetCopyright ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetEncodingTool ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetEncodedBy ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetPurchaseDate ( const MP4Tags*, const char* ); + +MP4V2_EXPORT bool MP4TagsSetPodcast ( const MP4Tags*, const uint8_t* ); +MP4V2_EXPORT bool MP4TagsSetKeywords ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetCategory ( const MP4Tags*, const char* ); + +MP4V2_EXPORT bool MP4TagsSetHDVideo ( const MP4Tags*, const uint8_t* ); +MP4V2_EXPORT bool MP4TagsSetMediaType ( const MP4Tags*, const uint8_t* ); +MP4V2_EXPORT bool MP4TagsSetContentRating ( const MP4Tags*, const uint8_t* ); +MP4V2_EXPORT bool MP4TagsSetGapless ( const MP4Tags*, const uint8_t* ); + +MP4V2_EXPORT bool MP4TagsSetITunesAccount ( const MP4Tags*, const char* ); +MP4V2_EXPORT bool MP4TagsSetITunesAccountType ( const MP4Tags*, const uint8_t* ); +MP4V2_EXPORT bool MP4TagsSetITunesCountry ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetContentID ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetArtistID ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetPlaylistID ( const MP4Tags*, const uint64_t* ); +MP4V2_EXPORT bool MP4TagsSetGenreID ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetComposerID ( const MP4Tags*, const uint32_t* ); +MP4V2_EXPORT bool MP4TagsSetXID ( const MP4Tags*, const char* ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_ITMF_TAGS_H */ diff --git a/thirdparty/include/mp4v2/mp4v2.h b/thirdparty/include/mp4v2/mp4v2.h new file mode 100755 index 0000000000000000000000000000000000000000..4d8e80716e4eafd1a363c2fa8b247c48a6d6d8da --- /dev/null +++ b/thirdparty/include/mp4v2/mp4v2.h @@ -0,0 +1,83 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + * Bill May wmay@cisco.com + */ +#ifndef MP4V2_MP4V2_H +#define MP4V2_MP4V2_H + +/*****************************************************************************/ + +#include +#include + +/*****************************************************************************/ + +/* exploit C++ ability of default values for function parameters */ +#if defined( DEFAULT ) +# define __MP4V2_SAVE_DEFAULT DEFAULT +#endif +#undef DEFAULT +#if defined( __cplusplus ) +# define DEFAULT(x) =x +#else +# define DEFAULT(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ + +/* restore macro DEFAULT to state prior to mp4v2 headers */ +#undef DEFAULT +#if defined( __MP4V2_SAVE_DEFAULT ) +# define DEFAULT __MP4V2_SAVE_DEFAULT +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +/*****************************************************************************/ + +#endif /* MP4V2_MP4V2_H */ diff --git a/thirdparty/include/mp4v2/platform.h b/thirdparty/include/mp4v2/platform.h new file mode 100755 index 0000000000000000000000000000000000000000..1583c4e010d26fff51a3409f6ec3c24954590486 --- /dev/null +++ b/thirdparty/include/mp4v2/platform.h @@ -0,0 +1,95 @@ +#ifndef MP4V2_PLATFORM_H +#define MP4V2_PLATFORM_H + +/*****************************************************************************/ + +#include +#include +#include + +// Thanks, MSFT, for making C99 a total PITA. Declare this not to define any stdint stuff; this is useful +// if you're going to be using mp4v2 on windows with some other library that defines its own stdint. +// TODO msft has finally re-included stdint in vs2010, so maybe at some point in the future this won't be needed. +#ifndef MP4V2_NO_STDINT_DEFS + /**#if defined( _WIN32 ) && !defined( __MINGW32__ ) + typedef char int8_t; + typedef short int16_t; + typedef int int32_t; + typedef long long int64_t; + + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + typedef unsigned long long uint64_t; + #else**/ + #include + //#endif +#endif + +#if defined( _WIN32 ) || defined( __MINGW32__ ) +# if defined( MP4V2_EXPORTS ) +# define MP4V2_EXPORT __declspec(dllexport) +# elif defined( MP4V2_USE_DLL_IMPORT ) || !defined( MP4V2_USE_STATIC_LIB ) +# define MP4V2_EXPORT __declspec(dllimport) +# else +# define MP4V2_EXPORT +# endif +#else +# define MP4V2_EXPORT __attribute__((visibility("default"))) +#endif + +#if defined( __GNUC__ ) +# define MP4V2_DEPRECATED __attribute__((deprecated)) +#else +# define MP4V2_DEPRECATED +#endif + +/****************************************************************************** + * + * TODO-KB: cleanup -- absolutely no need for a C-API to fuss with reserved + * C++ keywords. This will involve changing the public interface and current + * plan of action: + * + * typdef enum { + * mp4_false, + * mp4_true, + * } mp4_bool_t; + * + * followed by updating all public signatures and implementation. + */ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#if !defined( __cplusplus ) +#ifndef bool +#if SIZEOF_BOOL == 8 +typedef uint64_t bool; +#else +#if SIZEOF_BOOL == 4 +typedef uint32_t bool; +#else +#if SIZEOF_BOOL == 2 +typedef uint16_t bool; +#else +typedef unsigned char bool; +#endif +#endif +#endif +#ifndef false +#define false FALSE +#endif +#ifndef true +#define true TRUE +#endif +#endif +#endif + +/*****************************************************************************/ + +#endif /* MP4V2_PLATFORM_H */ diff --git a/thirdparty/include/mp4v2/project.h b/thirdparty/include/mp4v2/project.h new file mode 100755 index 0000000000000000000000000000000000000000..8a744d6160527abf7a27fe0e4098662e7790149d --- /dev/null +++ b/thirdparty/include/mp4v2/project.h @@ -0,0 +1,31 @@ +#ifndef MP4V2_PROJECT_H +#define MP4V2_PROJECT_H + +/*****************************************************************************/ + +#define MP4V2_PROJECT_name "MP4v2" +#define MP4V2_PROJECT_name_lower "mp4v2" +#define MP4V2_PROJECT_name_upper "MP4V2" +#define MP4V2_PROJECT_name_formal "MP4v2 2.0.0" +#define MP4V2_PROJECT_url_website "http://code.google.com/p/mp4v2" +#define MP4V2_PROJECT_url_downloads "http://code.google.com/p/mp4v2/downloads/list" +#define MP4V2_PROJECT_url_discussion "http://groups.google.com/group/mp4v2" +#define MP4V2_PROJECT_irc "irc://irc.freenode.net/handbrake" +#define MP4V2_PROJECT_bugreport "" +#define MP4V2_PROJECT_version "2.0.0" +#define MP4V2_PROJECT_version_hex 0x00020000 +#define MP4V2_PROJECT_version_major 2 +#define MP4V2_PROJECT_version_minor 0 +#define MP4V2_PROJECT_version_point 0 +#define MP4V2_PROJECT_repo_url "https://mp4v2.googlecode.com/svn/releases/2.0.0" +#define MP4V2_PROJECT_repo_branch "2.0.0" +#define MP4V2_PROJECT_repo_root "https://mp4v2.googlecode.com/svn" +#define MP4V2_PROJECT_repo_uuid "6e6572fa-98a6-11dd-ad9f-f77439c74b79" +#define MP4V2_PROJECT_repo_rev 493 +#define MP4V2_PROJECT_repo_date "2012-05-20 15:16:54 -0700 (Sun, 20 May 2012)" +#define MP4V2_PROJECT_repo_type "stable" +#define MP4V2_PROJECT_build "Tue Dec 8 17:26:49 CST 2020" + +/*****************************************************************************/ + +#endif /* MP4V2_PROJECT_H */ diff --git a/thirdparty/include/mp4v2/project.h.in b/thirdparty/include/mp4v2/project.h.in new file mode 100755 index 0000000000000000000000000000000000000000..59777c64207bccfd2074f279eb6ea1e2cb5d039f --- /dev/null +++ b/thirdparty/include/mp4v2/project.h.in @@ -0,0 +1,31 @@ +#ifndef MP4V2_PROJECT_H +#define MP4V2_PROJECT_H + +/*****************************************************************************/ + +#define MP4V2_PROJECT_name "@PROJECT_name@" +#define MP4V2_PROJECT_name_lower "@PROJECT_name_lower@" +#define MP4V2_PROJECT_name_upper "@PROJECT_name_upper@" +#define MP4V2_PROJECT_name_formal "@PROJECT_name_formal@" +#define MP4V2_PROJECT_url_website "@PROJECT_url_website@" +#define MP4V2_PROJECT_url_downloads "@PROJECT_url_downloads@" +#define MP4V2_PROJECT_url_discussion "@PROJECT_url_discussion@" +#define MP4V2_PROJECT_irc "@PROJECT_irc@" +#define MP4V2_PROJECT_bugreport "@PROJECT_bugreport@" +#define MP4V2_PROJECT_version "@PROJECT_version@" +#define MP4V2_PROJECT_version_hex @PROJECT_version_hex@ +#define MP4V2_PROJECT_version_major @PROJECT_version_major@ +#define MP4V2_PROJECT_version_minor @PROJECT_version_minor@ +#define MP4V2_PROJECT_version_point @PROJECT_version_point@ +#define MP4V2_PROJECT_repo_url "@PROJECT_repo_url@" +#define MP4V2_PROJECT_repo_branch "@PROJECT_repo_branch@" +#define MP4V2_PROJECT_repo_root "@PROJECT_repo_root@" +#define MP4V2_PROJECT_repo_uuid "@PROJECT_repo_uuid@" +#define MP4V2_PROJECT_repo_rev @PROJECT_repo_rev@ +#define MP4V2_PROJECT_repo_date "@PROJECT_repo_date@" +#define MP4V2_PROJECT_repo_type "@PROJECT_repo_type@" +#define MP4V2_PROJECT_build "@PROJECT_build@" + +/*****************************************************************************/ + +#endif /* MP4V2_PROJECT_H */ diff --git a/thirdparty/include/mp4v2/sample.h b/thirdparty/include/mp4v2/sample.h new file mode 100755 index 0000000000000000000000000000000000000000..ba35a5726170d5fa51f2ce9a90d81f6d2e3a1e81 --- /dev/null +++ b/thirdparty/include/mp4v2/sample.h @@ -0,0 +1,557 @@ +#ifndef MP4V2_SAMPLE_H +#define MP4V2_SAMPLE_H + +/**************************************************************************//** + * + * @defgroup mp4_sample MP4v2 Sample + * @{ + * + *****************************************************************************/ + +/** Sample dependency types. + * + * Bit combinations 0x03, 0x30, 0xc0 are reserved. + */ +typedef enum MP4SampleDependencyType_e { + MP4_SDT_UNKNOWN = 0x00, /**< unknown */ + MP4_SDT_HAS_REDUNDANT_CODING = 0x01, /**< contains redundant coding */ + MP4_SDT_HAS_NO_REDUNDANT_CODING = 0x02, /**< does not contain redundant coding */ + MP4_SDT_HAS_DEPENDENTS = 0x04, /**< referenced by other samples */ + MP4_SDT_HAS_NO_DEPENDENTS = 0x08, /**< not referenced by other samples */ + MP4_SDT_IS_DEPENDENT = 0x10, /**< references other samples */ + MP4_SDT_IS_INDEPENDENT = 0x20, /**< does not reference other samples */ + MP4_SDT_EARLIER_DISPLAY_TIMES_ALLOWED = 0x40, /**< subequent samples in GOP may display earlier */ + _MP4_SDT_RESERVED = 0x80 /**< reserved */ +} MP4SampleDependencyType; + +/** Read a track sample. + * + * MP4ReadSample reads the specified sample from the specified track. + * Typically this sample is then decoded in a codec dependent fashion and + * rendered in an appropriate fashion. + * + * The argument ppBytes allows for two possible approaches for + * buffering: + * + * If the calling application wishes to handle its own buffering it can set + * *ppBytes to the buffer it wishes to use. The calling application is + * responsible for ensuring that the buffer is large enough to hold the + * sample. This can be done by using either MP4GetSampleSize() or + * MP4GetTrackMaxSampleSize() to determine before-hand how large the + * receiving buffer must be. + * + * If the value of *ppBytes is NULL, then an appropriately sized buffer is + * automatically malloc'ed for the sample data and *ppBytes set to this + * pointer. The calling application is responsible for free'ing this + * memory. + * + * The last four arguments are pointers to variables that can receive + * optional sample information. + * + * Typically for audio none of these are needed. MPEG audio such as MP3 or + * AAC has a fixed sample duration and every sample can be accessed at + * random. + * + * For video, all of these optional values could be needed. MPEG video can + * be encoded at a variable frame rate, with only occasional random access + * points, and with "B frames" which cause the rendering (display) order + * of the video frames to differ from the storage/decoding order. + * + * Other media types fall between these two extremes. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId specifies which sample is to be read. + * Caveat: the first sample has id 1 not 0. + * @param ppBytes pointer to the pointer to the sample data. + * @param pNumBytes pointer to variable that will be hold the size in bytes + * of the sample. + * @param pStartTime if non-NULL, pointer to variable that will receive the + * starting timestamp for this sample. Caveat: The timestamp is in + * trackId's timescale. + * @param pDuration if non-NULL, pointer to variable that will receive the + * duration for this sample. Caveat: The duration is in + * trackId's timescale. + * @param pRenderingOffset if non-NULL, pointer to variable that will + * receive the rendering offset for this sample. Currently the only + * media type that needs this feature is MPEG video. Caveat: The offset + * is in trackId's timescale. + * @param pIsSyncSample if non-NULL, pointer to variable that will receive + * the state of the sync/random access flag for this sample. + * + * @return true on success, false on failure. + * + * @see MP4GetSampleSize(). + * @see MP4GetTrackMaxSampleSize(). + */ +MP4V2_EXPORT +bool MP4ReadSample( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + /* input/output parameters */ + uint8_t** ppBytes, + uint32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL) ); + +/** Read a track sample based on a specified time. + * + * MP4ReadSampleFromTime is similar to MP4ReadSample() except the sample + * is specified by using a timestamp instead of sampleId. + * Typically this sample is then decoded in a codec dependent fashion and + * rendered in an appropriate fashion. + * + * The argument ppBytes allows for two possible approaches for + * buffering: + * + * If the calling application wishes to handle its own buffering it can set + * *ppBytes to the buffer it wishes to use. The calling application is + * responsible for ensuring that the buffer is large enough to hold the + * sample. This can be done by using either MP4GetSampleSize() or + * MP4GetTrackMaxSampleSize() to determine before-hand how large the + * receiving buffer must be. + * + * If the value of *ppBytes is NULL, then an appropriately sized buffer is + * automatically malloc'ed for the sample data and *ppBytes set to this + * pointer. The calling application is responsible for free'ing this + * memory. + * + * The last four arguments are pointers to variables that can receive + * optional sample information. + * + * Typically for audio none of these are needed. MPEG audio such as MP3 or + * AAC has a fixed sample duration and every sample can be accessed at + * random. + * + * For video, all of these optional values could be needed. MPEG video can + * be encoded at a variable frame rate, with only occasional random access + * points, and with "B frames" which cause the rendering (display) order + * of the video frames to differ from the storage/decoding order. + * + * Other media types fall between these two extremes. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param when specifies which sample is to be read based on a time in the + * track timeline. See MP4GetSampleIdFromTime() for details. + * @param ppBytes pointer to the pointer to the sample data. + * @param pNumBytes pointer to variable that will be hold the size in bytes + * of the sample. + * @param pStartTime if non-NULL, pointer to variable that will receive the + * starting timestamp for this sample. Caveat: The timestamp is in + * trackId's timescale. + * @param pDuration if non-NULL, pointer to variable that will receive the + * duration for this sample. Caveat: The duration is in + * trackId's timescale. + * @param pRenderingOffset if non-NULL, pointer to variable that will + * receive the rendering offset for this sample. Currently the only + * media type that needs this feature is MPEG video. Caveat: The offset + * is in trackId's timescale. + * @param pIsSyncSample if non-NULL, pointer to variable that will receive + * the state of the sync/random access flag for this sample. + * + * @return true on success, false on failure. + * + * @see MP4ReadSample(). + * @see MP4GetSampleIdFromTime(). + * @see MP4GetSampleSize(). + * @see MP4GetTrackMaxSampleSize(). + */ +MP4V2_EXPORT +bool MP4ReadSampleFromTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + uint8_t** ppBytes, + uint32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL) ); + +/** Write a track sample. + * + * MP4WriteSample writes the given sample at the end of the specified track. + * Currently the library does not support random insertion of samples into + * the track timeline. Note that with mp4 there cannot be any holes or + * overlapping samples in the track timeline. The last three arguments give + * optional sample information. + * + * The value of duration can be given as #MP4_INVALID_DURATION if all samples + * in the track have the same duration. This can be specified with + * MP4AddTrack() and related functions. + * + * Typically for audio none of the optional arguments are needed. MPEG audio + * such as MP3 or AAC has a fixed sample duration and every sample can be + * accessed at random. + * + * For video, all of the optional arguments could be needed. MPEG video + * can be encoded at a variable frame rate, with only occasional random + * access points, and with "B frames" which cause the rendering (display) + * order of the video frames to differ from the storage/decoding order. + * + * Other media types fall between these two extremes. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param pBytes pointer to sample data. + * @param numBytes length of sample data in bytes. + * @param duration sample duration. Caveat: should be in track timescale. + * @param renderingOffset the rendering offset for this sample. + * Currently the only media type that needs this feature is MPEG + * video. Caveat: The offset should be in the track timescale. + * @param isSyncSample the sync/random access flag for this sample. + * + * @return true on success, false on failure. + * + * @see MP4AddTrack(). + */ +MP4V2_EXPORT +bool MP4WriteSample( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pBytes, + uint32_t numBytes, + MP4Duration duration DEFAULT(MP4_INVALID_DURATION), + MP4Duration renderingOffset DEFAULT(0), + bool isSyncSample DEFAULT(true) ); + +/** Write a track sample and supply dependency information. + * + * MP4WriteSampleDependency writes the given sample at the end of the specified track. + * Currently the library does not support random insertion of samples into + * the track timeline. Note that with mp4 there cannot be any holes or + * overlapping samples in the track timeline. The last three arguments give + * optional sample information. + * + * The value of duration can be given as #MP4_INVALID_DURATION if all samples + * in the track have the same duration. This can be specified with + * MP4AddTrack() and related functions. + * + * When this method is used instead of MP4WriteSample() it enables sdtp + * atom to be written out. This atom may be used by advanced players to + * optimize trick-operations such as fast-fwd, reverse or scrubbing. + * + * An sdtp atom will always be written out if this method is used. + * To avoid writing the atom, use MP4WriteSample() instead. + * + * Intermixing use of MP4WriteSampleDependency() and MP4WriteSample() on the + * same track is not permitted. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param pBytes pointer to sample data. + * @param numBytes length of sample data in bytes. + * @param duration sample duration. Caveat: should be in track timescale. + * @param renderingOffset the rendering offset for this sample. + * Currently the only media type that needs this feature is MPEG + * video. Caveat: The offset should be in the track timescale. + * @param isSyncSample the sync/random access flag for this sample. + * @param dependencyFlags bitmask specifying sample dependency characteristics. + * See #MP4SampleDependencyType for bit constants. + * + * @return true on success, false on failure. + * + * @see MP4AddTrack(). + */ +MP4V2_EXPORT +bool MP4WriteSampleDependency( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pBytes, + uint32_t numBytes, + MP4Duration duration, + MP4Duration renderingOffset, + bool isSyncSample, + uint32_t dependencyFlags ); + +/** Make a copy of a sample. + * + * MP4CopySample creates a new sample based on an existing sample. Note that + * another copy of the media sample data is created in the file using this + * function. ie. this call is equivalent to MP4ReadSample() followed by + * MP4WriteSample(). + * + * Note that is the responsibility of the caller to ensure that the copied + * media sample makes sense in the destination track. eg. copying a video + * sample to an audio track is unlikely to result in anything good happening, + * even copying a sample from video track to another requires that the tracks + * use the same encoding and that issues such as image size are addressed. + * + * @param srcFile source sample file handle. + * @param srcTrackId source sample track id. + * @param srcSampleId source sample id. + * @param dstFile destination file handle for new (copied) sample. + * If the value is #MP4_INVALID_FILE_HANDLE, the copy is created in + * the same file as srcFile. + * @param dstTrackId destination track id for new sample. + * If the value is #MP4_INVALID_TRACK_ID, the the copy is created in + * the same track as the srcTrackId. + * @param dstSampleDuration duration in track timescale for new sample. + * If the value is #MP4_INVALID_DURATION, then the duration of + * the source sample is used. + * + * @return On success, thew id of the new sample. + * On error, #MP4_INVALID_SAMPLE_ID. + * + * @see MP4ReadSample(). + * @see MP4WriteSample(). + */ +MP4V2_EXPORT +bool MP4CopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION) ); + +/** Make a copy of a sample. + * + * MP4EncAndCopySample is similar to MP4CopySample() except that it + * offers an encryption hook to the caller. + * + * @param srcFile source sample file handle. + * @param srcTrackId source sample track id. + * @param srcSampleId source sample id. + * @param encfcnp undocumented. + * @param encfcnparam1 undocumented. + * @param dstFile destination file handle for new (copied) sample. + * If the value is #MP4_INVALID_FILE_HANDLE, the copy is created in + * the same file as srcFile. + * @param dstTrackId destination track id for new sample. + * If the value is #MP4_INVALID_TRACK_ID, the the copy is created in + * the same track as the srcTrackId. + * @param dstSampleDuration duration in track timescale for new sample. + * If the value is #MP4_INVALID_DURATION, then the duration of + * the source sample is used. + * + * @return On success, thew id of the new sample. + * On error, #MP4_INVALID_SAMPLE_ID. + * + * @see MP4CopySample(). + */ +MP4V2_EXPORT +bool MP4EncAndCopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + encryptFunc_t encfcnp, + uint32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION) ); + +/** Not implemented. + */ +MP4V2_EXPORT +bool MP4ReferenceSample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION) ); + +/** Get size of a track sample. + * + * MP4GetSampleSize returns the size in bytes of the specified sample from the + * the specified track. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * + * @return On success the sample size in bytes. On error, 0. + */ +MP4V2_EXPORT +uint32_t MP4GetSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +/** Get the maximum sample size of a track. + * + * MP4GetTrackMaxSampleSize returns the maximum size in bytes of all the + * samples in the specified track. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return On success, the maximum sample size in bytes. On error, 0. + * + * @see MP4GetSampleSize(). + */ +MP4V2_EXPORT +uint32_t MP4GetTrackMaxSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Get sample id of a specified time. + * + * MP4GetSampleIdFromTime returns the sample id of the track sample in which + * the specified time occurs. + * + * The specified time should be in the track timescale. + * + * It is wise to use MP4GetSampleTime() with the returned sample id so one + * can adjust for any difference between the specified time and the actual + * start time of the sample. + * + * If the calling application needs a sample that can be accessed randomly + * then the wantSyncSample argument should be set to true. This could + * be the case for a player that is implementing a positioning function and + * needs to be able to start decoding a track from the returned sample id. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param when time in track timescale. + * @param wantSyncSample specifies if the result sample id must correspond + * to a sample whose sync/random access flag is true. + * + * @return On success, the sample id that occurs at the specified time. + * On error, #MP4_INVALID_SAMPLE_ID. + * + * @see MP4ConvertToTrackTimestamp() for how to map a time value to this + * timescale. + */ +MP4V2_EXPORT +MP4SampleId MP4GetSampleIdFromTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + bool wantSyncSample DEFAULT(false) ); + +/** Get start time of track sample. + * + * MP4GetSampleTime returns the start time of the specified sample from + * the specified track in the track timescale units. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * + * @return On success, sample start time in track timescale units. + * On error, #MP4_INVALID_TIMESTAMP. + * + * @see MP4ConvertFromTrackTimestamp() for how to map this value to another + * timescale. + */ +MP4V2_EXPORT +MP4Timestamp MP4GetSampleTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId ); + +/** Get the duration of a track sample. + * + * MP4GetSampleDuration returns the duration of the specified sample from + * the specified track in the track timescale units. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * + * @return On success, the sample duration in track timescale units. + * On error, #MP4_INVALID_DURATION. + * + * @see MP4ConvertFromTrackDuration() for how to map this value to another + * timescale. + */ +MP4V2_EXPORT +MP4Duration MP4GetSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId ); + +/** Get the rendering offset of a track sample. + * + * MP4GetSampleRenderingOffset returns the rendering offset of the specified + * sample from the specified track in the track timescale units. + * + * The sample rendering offset is typically zero for all media types other + * than video. For video, encodings such as those defined by MPEG have + * three types of frames: I, P, and B. To increase coding efficiency B + * frames can depend on I or P frames that should be rendered after the B + * frame. However to decode the B frame the I or P frame must already have + * been decoded. This situation is addressed by placing the frames in + * decoding order in the video track, and then setting the rendering offset + * property to indicate when the video frame should actually be rendered to + * the screen. Hence the start time of a sample indicates when it should be + * decoded, the start time plus the rendering offset indicates when it + * should be rendered. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * + * @return On success, the rendering offset in track timescale units. + * On error, #MP4_INVALID_DURATION. + * + * @see MP4ConvertFromTrackDuration() for how to map this value to another + * timescale. + */ +MP4V2_EXPORT +MP4Duration MP4GetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId ); + +/** Set the rendering offset of a track sample. + * + * MP4SetSampleRenderingOffset sets the rendering offset of the specified + * sample from the specified track in the track timescale units. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * @param renderingOffset new offset value in timescale units. + * + * @return true on success, false on failure. + * + * @see MP4ConvertToTrackDuration() for how to map this value from another + * timescale. + * @see MP4GetSampleRenderingOffset() for a description of this sample + * property. + */ +MP4V2_EXPORT +bool MP4SetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + MP4Duration renderingOffset ); + +/** Get sync/random access state of sample. + * + * MP4GetSampleSync returns the state of the sync/random access flag of + * the specified sample from the specified track. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param sampleId id of sample for operation. Caveat: the first sample has + * id 1, not 0. + * + * @return 1 when true, 0 when false. On error, -1. + */ +MP4V2_EXPORT +int8_t MP4GetSampleSync( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId ); + +/* @} ***********************************************************************/ + +#endif /* MP4V2_SAMPLE_H */ diff --git a/thirdparty/include/mp4v2/streaming.h b/thirdparty/include/mp4v2/streaming.h new file mode 100755 index 0000000000000000000000000000000000000000..36389d60533604d348d53490dd892a7346648ffd --- /dev/null +++ b/thirdparty/include/mp4v2/streaming.h @@ -0,0 +1,163 @@ +#ifndef MP4V2_STREAMING_H +#define MP4V2_STREAMING_H + +/**************************************************************************//** + * + * @defgroup mp4_hint MP4v2 Streaming + * @{ + * + *****************************************************************************/ + +MP4V2_EXPORT +bool MP4GetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + char** ppPayloadName DEFAULT(NULL), + uint8_t* pPayloadNumber DEFAULT(NULL), + uint16_t* pMaxPayloadSize DEFAULT(NULL), + char** ppEncodingParams DEFAULT(NULL) ); + +#define MP4_SET_DYNAMIC_PAYLOAD 0xff + +MP4V2_EXPORT +bool MP4SetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* pPayloadName, + uint8_t* pPayloadNumber, + uint16_t maxPayloadSize DEFAULT(0), + const char * encode_params DEFAULT(NULL), + bool include_rtp_map DEFAULT(true), + bool include_mpeg4_esid DEFAULT(true) ); + +MP4V2_EXPORT +const char* MP4GetSessionSdp( + MP4FileHandle hFile ); + +MP4V2_EXPORT +bool MP4SetSessionSdp( + MP4FileHandle hFile, + const char* sdpString ); + +MP4V2_EXPORT +bool MP4AppendSessionSdp( + MP4FileHandle hFile, + const char* sdpString ); + +MP4V2_EXPORT +const char* MP4GetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +bool MP4SetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString ); + +MP4V2_EXPORT +bool MP4AppendHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString ); + +MP4V2_EXPORT +MP4TrackId MP4GetHintTrackReferenceTrackId( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +bool MP4ReadRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + uint16_t* pNumPackets DEFAULT(NULL) ); + +MP4V2_EXPORT +uint16_t MP4GetRtpHintNumberOfPackets( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +int8_t MP4GetRtpPacketBFrame( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + uint16_t packetIndex ); + +MP4V2_EXPORT +int32_t MP4GetRtpPacketTransmitOffset( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + uint16_t packetIndex ); + +MP4V2_EXPORT +bool MP4ReadRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + uint16_t packetIndex, + uint8_t** ppBytes, + uint32_t* pNumBytes, + uint32_t ssrc DEFAULT(0), + bool includeHeader DEFAULT(true), + bool includePayload DEFAULT(true) ); + +MP4V2_EXPORT +MP4Timestamp MP4GetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +bool MP4SetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Timestamp rtpStart ); + +MP4V2_EXPORT +bool MP4AddRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +bool MP4AddRtpVideoHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool isBframe DEFAULT(false), + uint32_t timestampOffset DEFAULT(0) ); + +MP4V2_EXPORT +bool MP4AddRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool setMbit DEFAULT(false), + int32_t transmitOffset DEFAULT(0) ); + +MP4V2_EXPORT +bool MP4AddRtpImmediateData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const uint8_t* pBytes, + uint32_t numBytes ); + +MP4V2_EXPORT +bool MP4AddRtpSampleData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId sampleId, + uint32_t dataOffset, + uint32_t dataLength ); + +MP4V2_EXPORT +bool MP4AddRtpESConfigurationPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId ); + +MP4V2_EXPORT +bool MP4WriteRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Duration duration, + bool isSyncSample DEFAULT(true) ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_STREAMING_H */ diff --git a/thirdparty/include/mp4v2/track.h b/thirdparty/include/mp4v2/track.h new file mode 100755 index 0000000000000000000000000000000000000000..b5c44bf8b77af61f3f373b27d87154125a3af65b --- /dev/null +++ b/thirdparty/include/mp4v2/track.h @@ -0,0 +1,482 @@ +#ifndef MP4V2_TRACK_H +#define MP4V2_TRACK_H + +/**************************************************************************//** + * + * @defgroup mp4_track MP4v2 Track + * @{ + * + *****************************************************************************/ + +/** Add a user defined track. + * + * MP4AddTrack adds a user defined track to the mp4 file. Care should be + * taken to avoid any of the standardized track type names. A useful + * convention is use only uppercase characters for user defined track types. + * The string should be exactly four characters in length, e.g. "MINE". + * + * Note this should not be used to add any of the known track types defined + * in the MP4 standard (ISO/IEC 14496-1:2001). + * + * @param hFile handle of file for operation. + * @param type specifies the type of track to be added. + * @param timeScale the time scale in ticks per second of the track. Default is 1000. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddTrack( + MP4FileHandle hFile, + const char* type, + uint32_t timeScale DEFAULT(MP4_MSECS_TIME_SCALE) ); + +/** Add an MPEG-4 systems track. + * + * MP4AddSystemsTrack adds an MPEG-4 Systems track to the mp4 file. Note + * this should not be used to add OD or scene tracks, MP4AddODTrack() and + * MP4AddSceneTrack() should be used for those purposes. Other known + * MPEG-4 System track types are: + * @li #MP4_CLOCK_TRACK_TYPE + * @li #MP4_MPEG7_TRACK_TYPE + * @li #MP4_OCI_TRACK_TYPE + * @li #MP4_IPMP_TRACK_TYPE + * @li #MP4_MPEGJ_TRACK_TYPE + * + * @param hFile handle of file for operation. + * @param type specifies the type of track to be added. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddSystemsTrack( + MP4FileHandle hFile, + const char* type ); + +/** Add a object descriptor (OD) track. + * + * MP4AddODTrack adds an object descriptor (aka OD) track to the mp4 file. + * MP4WriteSample() can then be used to add the desired OD commands to the + * track. The burden is currently on the calling application to understand + * OD. + * + * Those wishing to have a simple audio/video scene without understanding + * OD may wish to use MP4MakeIsmaCompliant() to create the minimal OD and + * BIFS information. + * + * @param hFile handle of file for operation. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddODTrack( + MP4FileHandle hFile ); + +/** Add a scene (BIFS) track. + * + * MP4AddSceneTrack adds a scene (aka BIFS) track to the mp4 file. + * MP4WriteSample() can then be used to add the desired BIFS commands to + * the track. The burden is currently on the calling application to + * understand BIFS. + * + * Those wishing to have a simple audio/video scene without understanding + * BIFS may wish to use MP4MakeIsmaCompliant() to create the minimal OD + * and BIFS information. + * + * @param hFile handle of file for operation. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddSceneTrack( + MP4FileHandle hFile ); + +/** Add audio track to mp4 file. + * + * MP4AddAudioTrack adds an audio track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * It is recommended that the time scale be set to the sampling frequency + * (eg. 44100 Hz) of the audio so as to preserve the timing information + * accurately. + * + * If the audio encoding uses a fixed duration for each sample that should + * be specified here. If not then the value #MP4_INVALID_DURATION + * should be given for the sampleDuration argument. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * @param sampleDuration the fixed duration for all track samples. + * Caveat: the value should be in track-timescale units. + * @param audioType the audio encoding type. + * See MP4GetTrackEsdsObjectTypeId() for known values. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE) ); + +/** Add ulaw track to mp4 file. + * + * MP4AddULawAudioTrack adds a ulaw track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. +*/ +MP4V2_EXPORT +MP4TrackId MP4AddULawAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale); + +/** Add alaw track to mp4 file. + * + * MP4AddALawAudioTrack adds a alaw track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. +*/ +MP4V2_EXPORT +MP4TrackId MP4AddALawAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale); + +MP4V2_EXPORT +MP4TrackId MP4AddAC3AudioTrack( + MP4FileHandle hFile, + uint32_t samplingRate, + uint8_t fscod, + uint8_t bsid, + uint8_t bsmod, + uint8_t acmod, + uint8_t lfeon, + uint8_t bit_rate_code ); + +MP4V2_EXPORT +MP4TrackId MP4AddAmrAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale, + uint16_t modeSet, + uint8_t modeChangePeriod, + uint8_t framesPerSample, + bool isAmrWB ); + +MP4V2_EXPORT +void MP4SetAmrVendor( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t vendor ); + +MP4V2_EXPORT +void MP4SetAmrDecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t decoderVersion ); + +MP4V2_EXPORT +void MP4SetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trakId, + uint16_t modeSet ); + +MP4V2_EXPORT +uint16_t MP4GetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddHrefTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + const char* base_url DEFAULT(NULL) ); + +MP4V2_EXPORT +const char* MP4GetHrefTrackBaseUrl( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Add a video track. + * + * MP4AddVideoTrack adds a video track to the mp4 file. MP4WriteSample() + * can then be used to add the desired video samples. + * + * It is recommended that the time scale be set to 90000 so as to preserve + * the timing information accurately for the range of video frame rates + * commonly in use. + * + * If the video frame rate is to be fixed then the sampleDuration argument + * should be give the appropriate fixed value. If the video frame rate is + * to be variable then the value #MP4_INVALID_DURATION should be + * given for the sampleDuration argument. + * + * @param hFile handle of file for operation. + * @param timeScale the timescale in ticks per second of the track. + * @param sampleDuration specifies fixed sample duration for all track + * samples. Caveat: the value should be in track timescale units. + * @param width specifies the video frame width in pixels. + * @param height specifies the video frame height in pixels. + * @param videoType specifies the video encoding type. + * See MP4GetTrackVideoType() for known values. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddVideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE) ); + +MP4V2_EXPORT +MP4TrackId MP4AddH265VideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t isIso); + + + +MP4V2_EXPORT +void MP4AddH265VideoParameterSet (MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen); + +MP4V2_EXPORT +void MP4AddH265SequenceParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen ); + +MP4V2_EXPORT +void MP4AddH265PictureParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen ); + +MP4V2_EXPORT +MP4TrackId MP4AddH264VideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne ); + +MP4V2_EXPORT +void MP4AddH264SequenceParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen ); + +MP4V2_EXPORT +void MP4AddH264PictureParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen ); + +MP4V2_EXPORT +void MP4SetH263Vendor( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t vendor ); + +MP4V2_EXPORT +void MP4SetH263DecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t decoderVersion ); + +MP4V2_EXPORT +void MP4SetH263Bitrates( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t avgBitrate, + uint32_t maxBitrate ); + +MP4V2_EXPORT +MP4TrackId MP4AddH263VideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t h263Level, + uint8_t h263Profile, + uint32_t avgBitrate, + uint32_t maxBitrate ); + +/** Add a hint track. + * + * MP4AddHintTrack adds a hint track to the mp4 file. A hint track is used + * to describe how to send the reference media track over a particular + * network transport. In the case of the IETF RTP protocol, the hint track + * describes how the media data should be placed into packets and any + * media specific protocol headers that should be added. + * + * Typically there is a one to one correspondence between reference media + * track samples and hint track samples. The start time, duration, and + * sync flags are typically the same, however provisions are made for + * deviations from this rule. + * + * The MP4 library provides extensive support for RTP hint tracks. This + * includes a easy to use API to create RTP hint tracks, and read out + * fully constructed RTP packets based on the hint track. + * + * @param hFile handle of file for operation. + * @param refTrackId specifies the reference media track for this hint track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddHintTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddTextTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddSubtitleTrack( + MP4FileHandle hFile, + uint32_t timescale, + uint16_t width, + uint16_t height ); + +MP4V2_EXPORT +MP4TrackId MP4AddSubpicTrack( + MP4FileHandle hFile, + uint32_t timescale, + uint16_t width, + uint16_t height ); + +MP4V2_EXPORT +MP4TrackId MP4AddPixelAspectRatio( + MP4FileHandle hFile, + MP4TrackId refTrackId, + uint32_t hSpacing, + uint32_t vSpacing ); + +MP4V2_EXPORT +MP4TrackId MP4AddColr( + MP4FileHandle hFile, + MP4TrackId refTrackId, + uint16_t primary, + uint16_t transfer, + uint16_t matrix ); + +MP4V2_EXPORT +MP4TrackId MP4CloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +MP4TrackId MP4CopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +bool MP4DeleteTrack( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint32_t MP4GetNumberOfTracks( + MP4FileHandle hFile, + const char* type DEFAULT(NULL), + uint8_t subType DEFAULT(0) ); + +MP4V2_EXPORT +MP4TrackId MP4FindTrackId( + MP4FileHandle hFile, + uint16_t index, + const char* type DEFAULT(NULL), + uint8_t subType DEFAULT(0) ); + +MP4V2_EXPORT +uint16_t MP4FindTrackIndex( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Get maximum duration of chunk. + * + * MP4GetTrackDurationPerChunk gets the maximum duration for each chunk. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration out value of duration in track timescale units. + * + * return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackDurationPerChunk( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration* duration ); + +/** Set maximum duration of chunk. + * + * MP4SetTrackDurationPerChunk sets the maximum duration for each chunk. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration in timescale units. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackDurationPerChunk( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration ); + +/** + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4AddIPodUUID( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_TRACK_H */ diff --git a/thirdparty/include/mp4v2/track.h.orig b/thirdparty/include/mp4v2/track.h.orig new file mode 100755 index 0000000000000000000000000000000000000000..90eb7bc8460950cf86bf3d61b08b00637ba8af2f --- /dev/null +++ b/thirdparty/include/mp4v2/track.h.orig @@ -0,0 +1,451 @@ +#ifndef MP4V2_TRACK_H +#define MP4V2_TRACK_H + +/**************************************************************************//** + * + * @defgroup mp4_track MP4v2 Track + * @{ + * + *****************************************************************************/ + +/** Add a user defined track. + * + * MP4AddTrack adds a user defined track to the mp4 file. Care should be + * taken to avoid any of the standardized track type names. A useful + * convention is use only uppercase characters for user defined track types. + * The string should be exactly four characters in length, e.g. "MINE". + * + * Note this should not be used to add any of the known track types defined + * in the MP4 standard (ISO/IEC 14496-1:2001). + * + * @param hFile handle of file for operation. + * @param type specifies the type of track to be added. + * @param timeScale the time scale in ticks per second of the track. Default is 1000. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddTrack( + MP4FileHandle hFile, + const char* type, + uint32_t timeScale DEFAULT(MP4_MSECS_TIME_SCALE) ); + +/** Add an MPEG-4 systems track. + * + * MP4AddSystemsTrack adds an MPEG-4 Systems track to the mp4 file. Note + * this should not be used to add OD or scene tracks, MP4AddODTrack() and + * MP4AddSceneTrack() should be used for those purposes. Other known + * MPEG-4 System track types are: + * @li #MP4_CLOCK_TRACK_TYPE + * @li #MP4_MPEG7_TRACK_TYPE + * @li #MP4_OCI_TRACK_TYPE + * @li #MP4_IPMP_TRACK_TYPE + * @li #MP4_MPEGJ_TRACK_TYPE + * + * @param hFile handle of file for operation. + * @param type specifies the type of track to be added. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddSystemsTrack( + MP4FileHandle hFile, + const char* type ); + +/** Add a object descriptor (OD) track. + * + * MP4AddODTrack adds an object descriptor (aka OD) track to the mp4 file. + * MP4WriteSample() can then be used to add the desired OD commands to the + * track. The burden is currently on the calling application to understand + * OD. + * + * Those wishing to have a simple audio/video scene without understanding + * OD may wish to use MP4MakeIsmaCompliant() to create the minimal OD and + * BIFS information. + * + * @param hFile handle of file for operation. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddODTrack( + MP4FileHandle hFile ); + +/** Add a scene (BIFS) track. + * + * MP4AddSceneTrack adds a scene (aka BIFS) track to the mp4 file. + * MP4WriteSample() can then be used to add the desired BIFS commands to + * the track. The burden is currently on the calling application to + * understand BIFS. + * + * Those wishing to have a simple audio/video scene without understanding + * BIFS may wish to use MP4MakeIsmaCompliant() to create the minimal OD + * and BIFS information. + * + * @param hFile handle of file for operation. + * + * @return On success, the track-id of new track. + * On failure, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddSceneTrack( + MP4FileHandle hFile ); + +/** Add audio track to mp4 file. + * + * MP4AddAudioTrack adds an audio track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * It is recommended that the time scale be set to the sampling frequency + * (eg. 44100 Hz) of the audio so as to preserve the timing information + * accurately. + * + * If the audio encoding uses a fixed duration for each sample that should + * be specified here. If not then the value #MP4_INVALID_DURATION + * should be given for the sampleDuration argument. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * @param sampleDuration the fixed duration for all track samples. + * Caveat: the value should be in track-timescale units. + * @param audioType the audio encoding type. + * See MP4GetTrackEsdsObjectTypeId() for known values. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE) ); + +/** Add ulaw track to mp4 file. + * + * MP4AddULawAudioTrack adds a ulaw track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. +*/ +MP4V2_EXPORT +MP4TrackId MP4AddULawAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale); + +/** Add alaw track to mp4 file. + * + * MP4AddALawAudioTrack adds a alaw track to the mp4 file. MP4WriteSample() + * can then be used to add the desired audio samples. + * + * @param hFile handle of file for operation. + * @param timeScale the time scale in ticks per second of the track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. +*/ +MP4V2_EXPORT +MP4TrackId MP4AddALawAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale); + +MP4V2_EXPORT +MP4TrackId MP4AddAC3AudioTrack( + MP4FileHandle hFile, + uint32_t samplingRate, + uint8_t fscod, + uint8_t bsid, + uint8_t bsmod, + uint8_t acmod, + uint8_t lfeon, + uint8_t bit_rate_code ); + +MP4V2_EXPORT +MP4TrackId MP4AddAmrAudioTrack( + MP4FileHandle hFile, + uint32_t timeScale, + uint16_t modeSet, + uint8_t modeChangePeriod, + uint8_t framesPerSample, + bool isAmrWB ); + +MP4V2_EXPORT +void MP4SetAmrVendor( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t vendor ); + +MP4V2_EXPORT +void MP4SetAmrDecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t decoderVersion ); + +MP4V2_EXPORT +void MP4SetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trakId, + uint16_t modeSet ); + +MP4V2_EXPORT +uint16_t MP4GetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddHrefTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + const char* base_url DEFAULT(NULL) ); + +MP4V2_EXPORT +const char* MP4GetHrefTrackBaseUrl( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Add a video track. + * + * MP4AddVideoTrack adds a video track to the mp4 file. MP4WriteSample() + * can then be used to add the desired video samples. + * + * It is recommended that the time scale be set to 90000 so as to preserve + * the timing information accurately for the range of video frame rates + * commonly in use. + * + * If the video frame rate is to be fixed then the sampleDuration argument + * should be give the appropriate fixed value. If the video frame rate is + * to be variable then the value #MP4_INVALID_DURATION should be + * given for the sampleDuration argument. + * + * @param hFile handle of file for operation. + * @param timeScale the timescale in ticks per second of the track. + * @param sampleDuration specifies fixed sample duration for all track + * samples. Caveat: the value should be in track timescale units. + * @param width specifies the video frame width in pixels. + * @param height specifies the video frame height in pixels. + * @param videoType specifies the video encoding type. + * See MP4GetTrackVideoType() for known values. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddVideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE) ); + +MP4V2_EXPORT +MP4TrackId MP4AddH264VideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne ); + +MP4V2_EXPORT +void MP4AddH264SequenceParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pSequence, + uint16_t sequenceLen ); + +MP4V2_EXPORT +void MP4AddH264PictureParameterSet( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pPict, + uint16_t pictLen ); + +MP4V2_EXPORT +void MP4SetH263Vendor( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t vendor ); + +MP4V2_EXPORT +void MP4SetH263DecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t decoderVersion ); + +MP4V2_EXPORT +void MP4SetH263Bitrates( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t avgBitrate, + uint32_t maxBitrate ); + +MP4V2_EXPORT +MP4TrackId MP4AddH263VideoTrack( + MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration, + uint16_t width, + uint16_t height, + uint8_t h263Level, + uint8_t h263Profile, + uint32_t avgBitrate, + uint32_t maxBitrate ); + +/** Add a hint track. + * + * MP4AddHintTrack adds a hint track to the mp4 file. A hint track is used + * to describe how to send the reference media track over a particular + * network transport. In the case of the IETF RTP protocol, the hint track + * describes how the media data should be placed into packets and any + * media specific protocol headers that should be added. + * + * Typically there is a one to one correspondence between reference media + * track samples and hint track samples. The start time, duration, and + * sync flags are typically the same, however provisions are made for + * deviations from this rule. + * + * The MP4 library provides extensive support for RTP hint tracks. This + * includes a easy to use API to create RTP hint tracks, and read out + * fully constructed RTP packets based on the hint track. + * + * @param hFile handle of file for operation. + * @param refTrackId specifies the reference media track for this hint track. + * + * @return On success, the track-id of the new track. + * On error, #MP4_INVALID_TRACK_ID. + */ +MP4V2_EXPORT +MP4TrackId MP4AddHintTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddTextTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId ); + +MP4V2_EXPORT +MP4TrackId MP4AddSubtitleTrack( + MP4FileHandle hFile, + uint32_t timescale, + uint16_t width, + uint16_t height ); + +MP4V2_EXPORT +MP4TrackId MP4AddSubpicTrack( + MP4FileHandle hFile, + uint32_t timescale, + uint16_t width, + uint16_t height ); + +MP4V2_EXPORT +MP4TrackId MP4AddPixelAspectRatio( + MP4FileHandle hFile, + MP4TrackId refTrackId, + uint32_t hSpacing, + uint32_t vSpacing ); + +MP4V2_EXPORT +MP4TrackId MP4AddColr( + MP4FileHandle hFile, + MP4TrackId refTrackId, + uint16_t primary, + uint16_t transfer, + uint16_t matrix ); + +MP4V2_EXPORT +MP4TrackId MP4CloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +MP4TrackId MP4CopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) ); + +MP4V2_EXPORT +bool MP4DeleteTrack( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint32_t MP4GetNumberOfTracks( + MP4FileHandle hFile, + const char* type DEFAULT(NULL), + uint8_t subType DEFAULT(0) ); + +MP4V2_EXPORT +MP4TrackId MP4FindTrackId( + MP4FileHandle hFile, + uint16_t index, + const char* type DEFAULT(NULL), + uint8_t subType DEFAULT(0) ); + +MP4V2_EXPORT +uint16_t MP4FindTrackIndex( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Get maximum duration of chunk. + * + * MP4GetTrackDurationPerChunk gets the maximum duration for each chunk. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration out value of duration in track timescale units. + * + * return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackDurationPerChunk( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration* duration ); + +/** Set maximum duration of chunk. + * + * MP4SetTrackDurationPerChunk sets the maximum duration for each chunk. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param duration in timescale units. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackDurationPerChunk( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration ); + +/** + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4AddIPodUUID( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_TRACK_H */ diff --git a/thirdparty/include/mp4v2/track_prop.h b/thirdparty/include/mp4v2/track_prop.h new file mode 100755 index 0000000000000000000000000000000000000000..9c4691f34ef81162126b32d4f858114f60864615 --- /dev/null +++ b/thirdparty/include/mp4v2/track_prop.h @@ -0,0 +1,344 @@ +#ifndef MP4V2_TRACK_PROP_H +#define MP4V2_TRACK_PROP_H + +/**************************************************************************//** + * + * @defgroup mp4_track_prop MP4v2 Track Property + * @{ + * + *****************************************************************************/ + +/* specific track properties */ + +MP4V2_EXPORT +bool MP4HaveTrackAtom( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* atomname ); + +/** Get the track type. + * + * MP4GetTrackType gets the type of the track with the specified track id. + * + * Note: the library does not provide a MP4SetTrackType function, the + * track type needs to be specified when the track is created, e.g. + * MP4AddSystemsTrack(MP4_OCI_TRACK_TYPE). + * + * Known track types are: + * @li #MP4_OD_TRACK_TYPE + * @li #MP4_SCENE_TRACK_TYPE + * @li #MP4_AUDIO_TRACK_TYPE + * @li #MP4_VIDEO_TRACK_TYPE + * @li #MP4_HINT_TRACK_TYPE + * @li #MP4_CNTL_TRACK_TYPE + * @li #MP4_TEXT_TRACK_TYPE + * @li #MP4_CLOCK_TRACK_TYPE + * @li #MP4_MPEG7_TRACK_TYPE + * @li #MP4_OCI_TRACK_TYPE + * @li #MP4_IPMP_TRACK_TYPE + * @li #MP4_MPEGJ_TRACK_TYPE + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return On success, a string indicating track type. On failure, NULL. + */ +MP4V2_EXPORT +const char* MP4GetTrackType( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +const char* MP4GetTrackMediaDataName( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* + * MP4GetTrackMediaDataOriginalFormat is to be used to get the original + * MediaDataName if a track has been encrypted. + */ + +MP4V2_EXPORT +bool MP4GetTrackMediaDataOriginalFormat( + MP4FileHandle hFile, + MP4TrackId trackId, + char* originalFormat, + uint32_t buflen ); + +MP4V2_EXPORT +MP4Duration MP4GetTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Get the time scale of a track. + * + * MP4GetTrackTimeScale returns the time scale of the specified track in + * the mp4 file. The time scale determines the number of clock ticks per + * second for this track. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return timescale (ticks per second) of the track in the mp4 file. + */ +MP4V2_EXPORT +uint32_t MP4GetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Set the time scale of a track. + * + * MP4SetTrackTimeScale sets the time scale of the specified track in the + * mp4 file. The time scale determines the number of clock ticks per + * second for this track. + * + * Typically this value is set once when the track is created. However + * this call can be used to modify the value if that is desired. Since + * track sample durations are expressed in units of the track time scale, + * any change to the time scale value will effect the real time duration + * of the samples. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param timeScale desired time scale for the track. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t value ); + +/** Get ISO-639-2/T language code of a track. + * The language code is a 3-char alpha code consisting of lower-case letters. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param code buffer to hold 3-char+null (4-bytes total). + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackLanguage( + MP4FileHandle hFile, + MP4TrackId trackId, + char* code ); + +/** Set ISO-639-2/T language code of a track. + * The language code is a 3-char alpha code consisting of lower-case letters. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param code 3-char language code. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackLanguage( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* code ); + +/** Get track name. + * + * MP4GetTrackName gets the name of the track via udta.name property. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackName( + MP4FileHandle hFile, + MP4TrackId trackId, + char** name ); + +/** Set track name. + * + * MP4SetTrackName sets the name of the track via udta.name property. + * The udta atom is created if needed. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackName( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* name ); + +MP4V2_EXPORT +uint8_t MP4GetTrackAudioMpeg4Type( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint8_t MP4GetTrackEsdsObjectTypeId( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */ +MP4V2_EXPORT +MP4Duration MP4GetTrackFixedSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint32_t MP4GetTrackBitRate( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +bool MP4GetTrackVideoMetadata( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t** ppConfig, + uint32_t* pConfigSize ); + +MP4V2_EXPORT +bool MP4GetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t** ppConfig, + uint32_t* pConfigSize ); + +MP4V2_EXPORT +bool MP4SetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pConfig, + uint32_t configSize ); + +/* h264 information routines */ +MP4V2_EXPORT +bool MP4GetTrackH264ProfileLevel( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t* pProfile, + uint8_t* pLevel ); + +MP4V2_EXPORT +bool MP4GetTrackH264SeqPictHeaders( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t*** pSeqHeaders, + uint32_t** pSeqHeaderSize, + uint8_t*** pPictHeader, + uint32_t** pPictHeaderSize ); + +MP4V2_EXPORT +bool MP4GetTrackH264LengthSize( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t* pLength ); + +MP4V2_EXPORT +bool MP4GetTrackH265DecoderConfigurationRecord( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t** pConfig, + uint32_t* pLength); + +MP4V2_EXPORT +MP4SampleId MP4GetTrackNumberOfSamples( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint16_t MP4GetTrackVideoWidth( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint16_t MP4GetTrackVideoHeight( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +double MP4GetTrackVideoFrameRate( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +int MP4GetTrackAudioChannels( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +bool MP4IsIsmaCrypMediaTrack( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* generic track properties */ + +MP4V2_EXPORT +bool MP4HaveTrackAtom( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* atomName ); + +MP4V2_EXPORT +bool MP4GetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + uint64_t* retvalue ); + +MP4V2_EXPORT +bool MP4GetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float* ret_value ); + +MP4V2_EXPORT +bool MP4GetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char** retvalue ); + +MP4V2_EXPORT +bool MP4GetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + uint8_t** ppValue, + uint32_t* pValueSize ); + +MP4V2_EXPORT +bool MP4SetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + int64_t value ); + +MP4V2_EXPORT +bool MP4SetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float value ); + +MP4V2_EXPORT +bool MP4SetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char* value ); + +MP4V2_EXPORT +bool MP4SetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const uint8_t* pValue, + uint32_t valueSize); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_TRACK_PROP_H */ diff --git a/thirdparty/include/mp4v2/track_prop.h.orig b/thirdparty/include/mp4v2/track_prop.h.orig new file mode 100755 index 0000000000000000000000000000000000000000..37d76431744711e1b496dfb5c62680e2cccbc699 --- /dev/null +++ b/thirdparty/include/mp4v2/track_prop.h.orig @@ -0,0 +1,337 @@ +#ifndef MP4V2_TRACK_PROP_H +#define MP4V2_TRACK_PROP_H + +/**************************************************************************//** + * + * @defgroup mp4_track_prop MP4v2 Track Property + * @{ + * + *****************************************************************************/ + +/* specific track properties */ + +MP4V2_EXPORT +bool MP4HaveTrackAtom( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* atomname ); + +/** Get the track type. + * + * MP4GetTrackType gets the type of the track with the specified track id. + * + * Note: the library does not provide a MP4SetTrackType function, the + * track type needs to be specified when the track is created, e.g. + * MP4AddSystemsTrack(MP4_OCI_TRACK_TYPE). + * + * Known track types are: + * @li #MP4_OD_TRACK_TYPE + * @li #MP4_SCENE_TRACK_TYPE + * @li #MP4_AUDIO_TRACK_TYPE + * @li #MP4_VIDEO_TRACK_TYPE + * @li #MP4_HINT_TRACK_TYPE + * @li #MP4_CNTL_TRACK_TYPE + * @li #MP4_TEXT_TRACK_TYPE + * @li #MP4_CLOCK_TRACK_TYPE + * @li #MP4_MPEG7_TRACK_TYPE + * @li #MP4_OCI_TRACK_TYPE + * @li #MP4_IPMP_TRACK_TYPE + * @li #MP4_MPEGJ_TRACK_TYPE + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return On success, a string indicating track type. On failure, NULL. + */ +MP4V2_EXPORT +const char* MP4GetTrackType( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +const char* MP4GetTrackMediaDataName( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* + * MP4GetTrackMediaDataOriginalFormat is to be used to get the original + * MediaDataName if a track has been encrypted. + */ + +MP4V2_EXPORT +bool MP4GetTrackMediaDataOriginalFormat( + MP4FileHandle hFile, + MP4TrackId trackId, + char* originalFormat, + uint32_t buflen ); + +MP4V2_EXPORT +MP4Duration MP4GetTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Get the time scale of a track. + * + * MP4GetTrackTimeScale returns the time scale of the specified track in + * the mp4 file. The time scale determines the number of clock ticks per + * second for this track. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return timescale (ticks per second) of the track in the mp4 file. + */ +MP4V2_EXPORT +uint32_t MP4GetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/** Set the time scale of a track. + * + * MP4SetTrackTimeScale sets the time scale of the specified track in the + * mp4 file. The time scale determines the number of clock ticks per + * second for this track. + * + * Typically this value is set once when the track is created. However + * this call can be used to modify the value if that is desired. Since + * track sample durations are expressed in units of the track time scale, + * any change to the time scale value will effect the real time duration + * of the samples. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param timeScale desired time scale for the track. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t value ); + +/** Get ISO-639-2/T language code of a track. + * The language code is a 3-char alpha code consisting of lower-case letters. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param code buffer to hold 3-char+null (4-bytes total). + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackLanguage( + MP4FileHandle hFile, + MP4TrackId trackId, + char* code ); + +/** Set ISO-639-2/T language code of a track. + * The language code is a 3-char alpha code consisting of lower-case letters. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param code 3-char language code. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackLanguage( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* code ); + +/** Get track name. + * + * MP4GetTrackName gets the name of the track via udta.name property. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4GetTrackName( + MP4FileHandle hFile, + MP4TrackId trackId, + char** name ); + +/** Set track name. + * + * MP4SetTrackName sets the name of the track via udta.name property. + * The udta atom is created if needed. + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * + * @return true on success, false on failure. + */ +MP4V2_EXPORT +bool MP4SetTrackName( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* name ); + +MP4V2_EXPORT +uint8_t MP4GetTrackAudioMpeg4Type( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint8_t MP4GetTrackEsdsObjectTypeId( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */ +MP4V2_EXPORT +MP4Duration MP4GetTrackFixedSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint32_t MP4GetTrackBitRate( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +bool MP4GetTrackVideoMetadata( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t** ppConfig, + uint32_t* pConfigSize ); + +MP4V2_EXPORT +bool MP4GetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t** ppConfig, + uint32_t* pConfigSize ); + +MP4V2_EXPORT +bool MP4SetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t* pConfig, + uint32_t configSize ); + +/* h264 information routines */ +MP4V2_EXPORT +bool MP4GetTrackH264ProfileLevel( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t* pProfile, + uint8_t* pLevel ); + +MP4V2_EXPORT +bool MP4GetTrackH264SeqPictHeaders( + MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t*** pSeqHeaders, + uint32_t** pSeqHeaderSize, + uint8_t*** pPictHeader, + uint32_t** pPictHeaderSize ); + +MP4V2_EXPORT +bool MP4GetTrackH264LengthSize( + MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t* pLength ); + +MP4V2_EXPORT +MP4SampleId MP4GetTrackNumberOfSamples( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint16_t MP4GetTrackVideoWidth( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +uint16_t MP4GetTrackVideoHeight( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +double MP4GetTrackVideoFrameRate( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +int MP4GetTrackAudioChannels( + MP4FileHandle hFile, + MP4TrackId trackId ); + +MP4V2_EXPORT +bool MP4IsIsmaCrypMediaTrack( + MP4FileHandle hFile, + MP4TrackId trackId ); + +/* generic track properties */ + +MP4V2_EXPORT +bool MP4HaveTrackAtom( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* atomName ); + +MP4V2_EXPORT +bool MP4GetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + uint64_t* retvalue ); + +MP4V2_EXPORT +bool MP4GetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float* ret_value ); + +MP4V2_EXPORT +bool MP4GetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char** retvalue ); + +MP4V2_EXPORT +bool MP4GetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + uint8_t** ppValue, + uint32_t* pValueSize ); + +MP4V2_EXPORT +bool MP4SetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + int64_t value ); + +MP4V2_EXPORT +bool MP4SetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float value ); + +MP4V2_EXPORT +bool MP4SetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char* value ); + +MP4V2_EXPORT +bool MP4SetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const uint8_t* pValue, + uint32_t valueSize); + +/** @} ***********************************************************************/ + +#endif /* MP4V2_TRACK_PROP_H */ diff --git a/thirdparty/include/neaacdec.h b/thirdparty/include/neaacdec.h new file mode 100755 index 0000000000000000000000000000000000000000..15bbbb9becb44c5193e19c00a9a4edf80f1e9995 --- /dev/null +++ b/thirdparty/include/neaacdec.h @@ -0,0 +1,260 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** 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 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: neaacdec.h,v 1.14 2012/03/02 15:29:47 knik Exp $ +**/ + +#ifndef __NEAACDEC_H__ +#define __NEAACDEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#if 1 +/* MACROS FOR BACKWARDS COMPATIBILITY */ +/* structs */ +#define faacDecHandle NeAACDecHandle +#define faacDecConfiguration NeAACDecConfiguration +#define faacDecConfigurationPtr NeAACDecConfigurationPtr +#define faacDecFrameInfo NeAACDecFrameInfo +/* functions */ +#define faacDecGetErrorMessage NeAACDecGetErrorMessage +#define faacDecSetConfiguration NeAACDecSetConfiguration +#define faacDecGetCurrentConfiguration NeAACDecGetCurrentConfiguration +#define faacDecInit NeAACDecInit +#define faacDecInit2 NeAACDecInit2 +#define faacDecInitDRM NeAACDecInitDRM +#define faacDecPostSeekReset NeAACDecPostSeekReset +#define faacDecOpen NeAACDecOpen +#define faacDecClose NeAACDecClose +#define faacDecDecode NeAACDecDecode +#define AudioSpecificConfig NeAACDecAudioSpecificConfig +#endif + + +#ifdef _WIN32 + #pragma pack(push, 8) + #define NEAACDECAPI __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 + #define NEAACDECAPI __attribute__((visibility("default"))) +#else + #define NEAACDECAPI +#endif + +#define FAAD2_VERSION "unknown" + +/* object types for AAC */ +#define MAIN 1 +#define LC 2 +#define SSR 3 +#define LTP 4 +#define HE_AAC 5 +#define ER_LC 17 +#define ER_LTP 19 +#define LD 23 +#define DRM_ER_LC 27 /* special object type for DRM */ + +/* header types */ +#define RAW 0 +#define ADIF 1 +#define ADTS 2 +#define LATM 3 + +/* SBR signalling */ +#define NO_SBR 0 +#define SBR_UPSAMPLED 1 +#define SBR_DOWNSAMPLED 2 +#define NO_SBR_UPSAMPLED 3 + +/* library output formats */ +#define FAAD_FMT_16BIT 1 +#define FAAD_FMT_24BIT 2 +#define FAAD_FMT_32BIT 3 +#define FAAD_FMT_FLOAT 4 +#define FAAD_FMT_FIXED FAAD_FMT_FLOAT +#define FAAD_FMT_DOUBLE 5 + +/* Capabilities */ +#define LC_DEC_CAP (1<<0) /* Can decode LC */ +#define MAIN_DEC_CAP (1<<1) /* Can decode MAIN */ +#define LTP_DEC_CAP (1<<2) /* Can decode LTP */ +#define LD_DEC_CAP (1<<3) /* Can decode LD */ +#define ERROR_RESILIENCE_CAP (1<<4) /* Can decode ER */ +#define FIXED_POINT_CAP (1<<5) /* Fixed point */ + +/* Channel definitions */ +#define FRONT_CHANNEL_CENTER (1) +#define FRONT_CHANNEL_LEFT (2) +#define FRONT_CHANNEL_RIGHT (3) +#define SIDE_CHANNEL_LEFT (4) +#define SIDE_CHANNEL_RIGHT (5) +#define BACK_CHANNEL_LEFT (6) +#define BACK_CHANNEL_RIGHT (7) +#define BACK_CHANNEL_CENTER (8) +#define LFE_CHANNEL (9) +#define UNKNOWN_CHANNEL (0) + +/* DRM channel definitions */ +#define DRMCH_MONO 1 +#define DRMCH_STEREO 2 +#define DRMCH_SBR_MONO 3 +#define DRMCH_SBR_STEREO 4 +#define DRMCH_SBR_PS_STEREO 5 + + +/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel, + so at least so much bytes per channel should be available in this stream */ +#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */ + + +typedef void *NeAACDecHandle; + +typedef struct mp4AudioSpecificConfig +{ + /* Audio Specific Info */ + unsigned char objectTypeIndex; + unsigned char samplingFrequencyIndex; + unsigned long samplingFrequency; + unsigned char channelsConfiguration; + + /* GA Specific Info */ + unsigned char frameLengthFlag; + unsigned char dependsOnCoreCoder; + unsigned short coreCoderDelay; + unsigned char extensionFlag; + unsigned char aacSectionDataResilienceFlag; + unsigned char aacScalefactorDataResilienceFlag; + unsigned char aacSpectralDataResilienceFlag; + unsigned char epConfig; + + char sbr_present_flag; + char forceUpSampling; + char downSampledSBR; +} mp4AudioSpecificConfig; + +typedef struct NeAACDecConfiguration +{ + unsigned char defObjectType; + unsigned long defSampleRate; + unsigned char outputFormat; + unsigned char downMatrix; + unsigned char useOldADTSFormat; + unsigned char dontUpSampleImplicitSBR; +} NeAACDecConfiguration, *NeAACDecConfigurationPtr; + +typedef struct NeAACDecFrameInfo +{ + unsigned long bytesconsumed; + unsigned long samples; + unsigned char channels; + unsigned char error; + unsigned long samplerate; + + /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ + unsigned char sbr; + + /* MPEG-4 ObjectType */ + unsigned char object_type; + + /* AAC header type; MP4 will be signalled as RAW also */ + unsigned char header_type; + + /* multichannel configuration */ + unsigned char num_front_channels; + unsigned char num_side_channels; + unsigned char num_back_channels; + unsigned char num_lfe_channels; + unsigned char channel_position[64]; + + /* PS: 0: off, 1: on */ + unsigned char ps; +} NeAACDecFrameInfo; + +NEAACDECAPI char* NeAACDecGetErrorMessage(unsigned char errcode); + +NEAACDECAPI unsigned long NeAACDecGetCapabilities(void); + +NEAACDECAPI NeAACDecHandle NeAACDecOpen(void); + +NEAACDECAPI NeAACDecConfigurationPtr NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); + +NEAACDECAPI unsigned char NeAACDecSetConfiguration(NeAACDecHandle hDecoder, + NeAACDecConfigurationPtr config); + +/* Init the library based on info from the AAC file (ADTS/ADIF) */ +NEAACDECAPI long NeAACDecInit(NeAACDecHandle hDecoder, + unsigned char *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + unsigned char *channels); + +/* Init the library using a DecoderSpecificInfo */ +NEAACDECAPI char NeAACDecInit2(NeAACDecHandle hDecoder, + unsigned char *pBuffer, + unsigned long SizeOfDecoderSpecificInfo, + unsigned long *samplerate, + unsigned char *channels); + +/* Init the library for DRM */ +NEAACDECAPI char NeAACDecInitDRM(NeAACDecHandle *hDecoder, unsigned long samplerate, + unsigned char channels); + +NEAACDECAPI void NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame); + +NEAACDECAPI void NeAACDecClose(NeAACDecHandle hDecoder); + +NEAACDECAPI void* NeAACDecDecode(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size); + +NEAACDECAPI void* NeAACDecDecode2(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer, + unsigned long sample_buffer_size); + +NEAACDECAPI char NeAACDecAudioSpecificConfig(unsigned char *pBuffer, + unsigned long buffer_size, + mp4AudioSpecificConfig *mp4ASC); + +/* Get version and copyright strings */ +NEAACDECAPI int NeAACDecGetVersion(char **faad_id_string, + char **faad_copyright_string); + +#ifdef _WIN32 + #pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/thirdparty/include/opus/opus.h b/thirdparty/include/opus/opus.h new file mode 100755 index 0000000000000000000000000000000000000000..d282f21d25a719ff0e443cd332f3c388f4647deb --- /dev/null +++ b/thirdparty/include/opus/opus.h @@ -0,0 +1,981 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus.h + * @brief Opus reference implementation API + */ + +#ifndef OPUS_H +#define OPUS_H + +#include "opus_types.h" +#include "opus_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @mainpage Opus + * + * The Opus codec is designed for interactive speech and audio transmission over the Internet. + * It is designed by the IETF Codec Working Group and incorporates technology from + * Skype's SILK codec and Xiph.Org's CELT codec. + * + * The Opus codec is designed to handle a wide range of interactive audio applications, + * including Voice over IP, videoconferencing, in-game chat, and even remote live music + * performances. It can scale from low bit-rate narrowband speech to very high quality + * stereo music. Its main features are: + + * @li Sampling rates from 8 to 48 kHz + * @li Bit-rates from 6 kb/s to 510 kb/s + * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR) + * @li Audio bandwidth from narrowband to full-band + * @li Support for speech and music + * @li Support for mono and stereo + * @li Support for multichannel (up to 255 channels) + * @li Frame sizes from 2.5 ms to 60 ms + * @li Good loss robustness and packet loss concealment (PLC) + * @li Floating point and fixed-point implementation + * + * Documentation sections: + * @li @ref opus_encoder + * @li @ref opus_decoder + * @li @ref opus_repacketizer + * @li @ref opus_multistream + * @li @ref opus_libinfo + * @li @ref opus_custom + */ + +/** @defgroup opus_encoder Opus Encoder + * @{ + * + * @brief This page describes the process and functions used to encode Opus. + * + * Since Opus is a stateful codec, the encoding process starts with creating an encoder + * state. This can be done with: + * + * @code + * int error; + * OpusEncoder *enc; + * enc = opus_encoder_create(Fs, channels, application, &error); + * @endcode + * + * From this point, @c enc can be used for encoding an audio stream. An encoder state + * @b must @b not be used for more than one stream at the same time. Similarly, the encoder + * state @b must @b not be re-initialized for each frame. + * + * While opus_encoder_create() allocates memory for the state, it's also possible + * to initialize pre-allocated memory: + * + * @code + * int size; + * int error; + * OpusEncoder *enc; + * size = opus_encoder_get_size(channels); + * enc = malloc(size); + * error = opus_encoder_init(enc, Fs, channels, application); + * @endcode + * + * where opus_encoder_get_size() returns the required size for the encoder state. Note that + * future versions of this code may change the size, so no assuptions should be made about it. + * + * The encoder state is always continuous in memory and only a shallow copy is sufficient + * to copy it (e.g. memcpy()) + * + * It is possible to change some of the encoder's settings using the opus_encoder_ctl() + * interface. All these settings already default to the recommended value, so they should + * only be changed when necessary. The most common settings one may want to change are: + * + * @code + * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); + * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); + * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type)); + * @endcode + * + * where + * + * @arg bitrate is in bits per second (b/s) + * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest + * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC + * + * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream. + * + * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data: + * @code + * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet); + * @endcode + * + * where + *
    + *
  • audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
  • + *
  • frame_size is the duration of the frame in samples (per channel)
  • + *
  • packet is the byte array to which the compressed data is written
  • + *
  • max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended). + * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
  • + *
+ * + * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. + * The return value can be negative, which indicates that an error has occurred. If the return value + * is 2 bytes or less, then the packet does not need to be transmitted (DTX). + * + * Once the encoder state if no longer needed, it can be destroyed with + * + * @code + * opus_encoder_destroy(enc); + * @endcode + * + * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(), + * then no action is required aside from potentially freeing the memory that was manually + * allocated for it (calling free(enc) for the example above) + * + */ + +/** Opus encoder state. + * This contains the complete state of an Opus encoder. + * It is position independent and can be freely copied. + * @see opus_encoder_create,opus_encoder_init + */ +typedef struct OpusEncoder OpusEncoder; + +/** Gets the size of an OpusEncoder structure. + * @param[in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); + +/** + */ + +/** Allocates and initializes an encoder state. + * There are three coding modes: + * + * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice + * signals. It enhances the input signal by high-pass filtering and + * emphasizing formants and harmonics. Optionally it includes in-band + * forward error correction to protect against packet loss. Use this + * mode for typical VoIP applications. Because of the enhancement, + * even at high bitrates the output may sound different from the input. + * + * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most + * non-voice signals like music. Use this mode for music and mixed + * (music/voice) content, broadcast, and applications requiring less + * than 15 ms of coding delay. + * + * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that + * disables the speech-optimized mode in exchange for slightly reduced delay. + * This mode can only be set on an newly initialized or freshly reset encoder + * because it changes the codec delay. + * + * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution). + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @param [out] error int*: @ref opus_errorcodes + * @note Regardless of the sampling rate and number channels selected, the Opus encoder + * can switch to a lower audio bandwidth or number of channels if the bitrate + * selected is too low. This also means that it is safe to always use 48 kHz stereo input + * and let the encoder optimize the encoding. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( + opus_int32 Fs, + int channels, + int application, + int *error +); + +/** Initializes a previously allocated encoder state + * The memory pointed to by st must be at least the size returned by opus_encoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_encoder_create(),opus_encoder_get_size() + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_encoder_init( + OpusEncoder *st, + opus_int32 Fs, + int channels, + int application +) OPUS_ARG_NONNULL(1); + +/** Encodes an Opus frame. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( + OpusEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes an Opus frame from floating point input. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. + * Samples with a range beyond +/-1.0 are supported but will + * be clipped by decoders using the integer API and should + * only be used if it is known that the far end supports + * extended dynamic range. + * length is frame_size*channels*sizeof(float) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( + OpusEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusEncoder allocated by opus_encoder_create(). + * @param[in] st OpusEncoder*: State to be freed. + */ +OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); + +/** Perform a CTL function on an Opus encoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusEncoder*: Encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_encoderctls. + * @see opus_genericctls + * @see opus_encoderctls + */ +OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); +/**@}*/ + +/** @defgroup opus_decoder Opus Decoder + * @{ + * + * @brief This page describes the process and functions used to decode Opus. + * + * The decoding process also starts with creating a decoder + * state. This can be done with: + * @code + * int error; + * OpusDecoder *dec; + * dec = opus_decoder_create(Fs, channels, &error); + * @endcode + * where + * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000 + * @li channels is the number of channels (1 or 2) + * @li error will hold the error code in case of failure (or #OPUS_OK on success) + * @li the return value is a newly created decoder state to be used for decoding + * + * While opus_decoder_create() allocates memory for the state, it's also possible + * to initialize pre-allocated memory: + * @code + * int size; + * int error; + * OpusDecoder *dec; + * size = opus_decoder_get_size(channels); + * dec = malloc(size); + * error = opus_decoder_init(dec, Fs, channels); + * @endcode + * where opus_decoder_get_size() returns the required size for the decoder state. Note that + * future versions of this code may change the size, so no assuptions should be made about it. + * + * The decoder state is always continuous in memory and only a shallow copy is sufficient + * to copy it (e.g. memcpy()) + * + * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data: + * @code + * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0); + * @endcode + * where + * + * @li packet is the byte array containing the compressed data + * @li len is the exact number of bytes contained in the packet + * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float()) + * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array + * + * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet. + * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio + * buffer is too small to hold the decoded audio. + * + * Opus is a stateful codec with overlapping blocks and as a result Opus + * packets are not coded independently of each other. Packets must be + * passed into the decoder serially and in the correct order for a correct + * decode. Lost packets can be replaced with loss concealment by calling + * the decoder with a null pointer and zero length for the missing packet. + * + * A single codec state may only be accessed from a single thread at + * a time and any required locking must be performed by the caller. Separate + * streams must be decoded with separate decoder states and can be decoded + * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK + * defined. + * + */ + +/** Opus decoder state. + * This contains the complete state of an Opus decoder. + * It is position independent and can be freely copied. + * @see opus_decoder_create,opus_decoder_init + */ +typedef struct OpusDecoder OpusDecoder; + +/** Gets the size of an OpusDecoder structure. + * @param [in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels); + +/** Allocates and initializes a decoder state. + * @param [in] Fs opus_int32: Sample rate to decode at (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes + * + * Internally Opus stores data at 48000 Hz, so that should be the default + * value for Fs. However, the decoder can efficiently decode to buffers + * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use + * data at the full sample rate, or knows the compressed data doesn't + * use the full frequency range, it can request decoding at a reduced + * rate. Likewise, the decoder is capable of filling in either mono or + * interleaved stereo pcm buffers, at the caller's request. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( + opus_int32 Fs, + int channels, + int *error +); + +/** Initializes a previously allocated decoder state. + * The state must be at least the size returned by opus_decoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusDecoder*: Decoder state. + * @param [in] Fs opus_int32: Sampling rate to decode to (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_decoder_init( + OpusDecoder *st, + opus_int32 Fs, + int channels +) OPUS_ARG_NONNULL(1); + +/** Decode an Opus packet. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload* + * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available, the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode an Opus packet with floating point output. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload + * @param [out] pcm float*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(float) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus decoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusDecoder*: Decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_decoderctls. + * @see opus_genericctls + * @see opus_decoderctls + */ +OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusDecoder allocated by opus_decoder_create(). + * @param[in] st OpusDecoder*: State to be freed. + */ +OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); + +/** Parse an opus packet into one or more frames. + * Opus_decode will perform this operation internally so most applications do + * not need to use this function. + * This function does not copy the frames, the returned pointers are pointers into + * the input packet. + * @param [in] data char*: Opus packet to be parsed + * @param [in] len opus_int32: size of data + * @param [out] out_toc char*: TOC pointer + * @param [out] frames char*[48] encapsulated frames + * @param [out] size opus_int16[48] sizes of the encapsulated frames + * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes) + * @returns number of frames + */ +OPUS_EXPORT int opus_packet_parse( + const unsigned char *data, + opus_int32 len, + unsigned char *out_toc, + const unsigned char *frames[48], + opus_int16 size[48], + int *payload_offset +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5); + +/** Gets the bandwidth of an Opus packet. + * @param [in] data char*: Opus packet + * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass) + * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass) + * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass) + * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass) + * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass) + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples per frame from an Opus packet. + * @param [in] data char*: Opus packet. + * This must contain at least one byte of + * data. + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples per frame. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of channels from an Opus packet. + * @param [in] data char*: Opus packet + * @returns Number of channels + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of frames in an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of frames + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] dec OpusDecoder*: Decoder state + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + +/** Applies soft-clipping to bring a float signal within the [-1,1] range. If + * the signal is already in that range, nothing is done. If there are values + * outside of [-1,1], then the signal is clipped as smoothly as possible to + * both fit in the range and avoid creating excessive distortion in the + * process. + * @param [in,out] pcm float*: Input PCM and modified PCM + * @param [in] frame_size int Number of samples per channel to process + * @param [in] channels int: Number of channels + * @param [in,out] softclip_mem float*: State memory for the soft clipping process (one float per channel, initialized to zero) + */ +OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem); + + +/**@}*/ + +/** @defgroup opus_repacketizer Repacketizer + * @{ + * + * The repacketizer can be used to merge multiple Opus packets into a single + * packet or alternatively to split Opus packets that have previously been + * merged. Splitting valid Opus packets is always guaranteed to succeed, + * whereas merging valid packets only succeeds if all frames have the same + * mode, bandwidth, and frame size, and when the total duration of the merged + * packet is no more than 120 ms. The 120 ms limit comes from the + * specification and limits decoder memory requirements at a point where + * framing overhead becomes negligible. + * + * The repacketizer currently only operates on elementary Opus + * streams. It will not manipualte multistream packets successfully, except in + * the degenerate case where they consist of data from a single stream. + * + * The repacketizing process starts with creating a repacketizer state, either + * by calling opus_repacketizer_create() or by allocating the memory yourself, + * e.g., + * @code + * OpusRepacketizer *rp; + * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size()); + * if (rp != NULL) + * opus_repacketizer_init(rp); + * @endcode + * + * Then the application should submit packets with opus_repacketizer_cat(), + * extract new packets with opus_repacketizer_out() or + * opus_repacketizer_out_range(), and then reset the state for the next set of + * input packets via opus_repacketizer_init(). + * + * For example, to split a sequence of packets into individual frames: + * @code + * unsigned char *data; + * int len; + * while (get_next_packet(&data, &len)) + * { + * unsigned char out[1276]; + * opus_int32 out_len; + * int nb_frames; + * int err; + * int i; + * err = opus_repacketizer_cat(rp, data, len); + * if (err != OPUS_OK) + * { + * release_packet(data); + * return err; + * } + * nb_frames = opus_repacketizer_get_nb_frames(rp); + * for (i = 0; i < nb_frames; i++) + * { + * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packet(data); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * } + * opus_repacketizer_init(rp); + * release_packet(data); + * } + * @endcode + * + * Alternatively, to combine a sequence of frames into packets that each + * contain up to TARGET_DURATION_MS milliseconds of data: + * @code + * // The maximum number of packets with duration TARGET_DURATION_MS occurs + * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5) + * // packets. + * unsigned char *data[(TARGET_DURATION_MS*2/5)+1]; + * opus_int32 len[(TARGET_DURATION_MS*2/5)+1]; + * int nb_packets; + * unsigned char out[1277*(TARGET_DURATION_MS*2/2)]; + * opus_int32 out_len; + * int prev_toc; + * nb_packets = 0; + * while (get_next_packet(data+nb_packets, len+nb_packets)) + * { + * int nb_frames; + * int err; + * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]); + * if (nb_frames < 1) + * { + * release_packets(data, nb_packets+1); + * return nb_frames; + * } + * nb_frames += opus_repacketizer_get_nb_frames(rp); + * // If adding the next packet would exceed our target, or it has an + * // incompatible TOC sequence, output the packets we already have before + * // submitting it. + * // N.B., The nb_packets > 0 check ensures we've submitted at least one + * // packet since the last call to opus_repacketizer_init(). Otherwise a + * // single packet longer than TARGET_DURATION_MS would cause us to try to + * // output an (invalid) empty packet. It also ensures that prev_toc has + * // been set to a valid value. Additionally, len[nb_packets] > 0 is + * // guaranteed by the call to opus_packet_get_nb_frames() above, so the + * // reference to data[nb_packets][0] should be valid. + * if (nb_packets > 0 && ( + * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) || + * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames > + * TARGET_DURATION_MS*48)) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packets(data, nb_packets+1); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * opus_repacketizer_init(rp); + * release_packets(data, nb_packets); + * data[0] = data[nb_packets]; + * len[0] = len[nb_packets]; + * nb_packets = 0; + * } + * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]); + * if (err != OPUS_OK) + * { + * release_packets(data, nb_packets+1); + * return err; + * } + * prev_toc = data[nb_packets][0]; + * nb_packets++; + * } + * // Output the final, partial packet. + * if (nb_packets > 0) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * release_packets(data, nb_packets); + * if (out_len < 0) + * return (int)out_len; + * output_next_packet(out, out_len); + * } + * @endcode + * + * An alternate way of merging packets is to simply call opus_repacketizer_cat() + * unconditionally until it fails. At that point, the merged packet can be + * obtained with opus_repacketizer_out() and the input packet for which + * opus_repacketizer_cat() needs to be re-added to a newly reinitialized + * repacketizer state. + */ + +typedef struct OpusRepacketizer OpusRepacketizer; + +/** Gets the size of an OpusRepacketizer structure. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void); + +/** (Re)initializes a previously allocated repacketizer state. + * The state must be at least the size returned by opus_repacketizer_get_size(). + * This can be used for applications which use their own allocator instead of + * malloc(). + * It must also be called to reset the queue of packets waiting to be + * repacketized, which is necessary if the maximum packet duration of 120 ms + * is reached or if you wish to submit packets with a different Opus + * configuration (coding mode, audio bandwidth, frame size, or channel count). + * Failure to do so will prevent a new packet from being added with + * opus_repacketizer_cat(). + * @see opus_repacketizer_create + * @see opus_repacketizer_get_size + * @see opus_repacketizer_cat + * @param rp OpusRepacketizer*: The repacketizer state to + * (re)initialize. + * @returns A pointer to the same repacketizer state that was passed in. + */ +OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Allocates memory and initializes the new repacketizer with + * opus_repacketizer_init(). + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void); + +/** Frees an OpusRepacketizer allocated by + * opus_repacketizer_create(). + * @param[in] rp OpusRepacketizer*: State to be freed. + */ +OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp); + +/** Add a packet to the current repacketizer state. + * This packet must match the configuration of any packets already submitted + * for repacketization since the last call to opus_repacketizer_init(). + * This means that it must have the same coding mode, audio bandwidth, frame + * size, and channel count. + * This can be checked in advance by examining the top 6 bits of the first + * byte of the packet, and ensuring they match the top 6 bits of the first + * byte of any previously submitted packet. + * The total duration of audio in the repacketizer state also must not exceed + * 120 ms, the maximum duration of a single packet, after adding this packet. + * + * The contents of the current repacketizer state can be extracted into new + * packets using opus_repacketizer_out() or opus_repacketizer_out_range(). + * + * In order to add a packet with a different configuration or to add more + * audio beyond 120 ms, you must clear the repacketizer state by calling + * opus_repacketizer_init(). + * If a packet is too large to add to the current repacketizer state, no part + * of it is added, even if it contains multiple frames, some of which might + * fit. + * If you wish to be able to add parts of such packets, you should first use + * another repacketizer to split the packet into pieces and add them + * individually. + * @see opus_repacketizer_out_range + * @see opus_repacketizer_out + * @see opus_repacketizer_init + * @param rp OpusRepacketizer*: The repacketizer state to which to + * add the packet. + * @param[in] data const unsigned char*: The packet data. + * The application must ensure + * this pointer remains valid + * until the next call to + * opus_repacketizer_init() or + * opus_repacketizer_destroy(). + * @param len opus_int32: The number of bytes in the packet data. + * @returns An error code indicating whether or not the operation succeeded. + * @retval #OPUS_OK The packet's contents have been added to the repacketizer + * state. + * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence, + * the packet's TOC sequence was not compatible + * with previously submitted packets (because + * the coding mode, audio bandwidth, frame size, + * or channel count did not match), or adding + * this packet would increase the total amount of + * audio stored in the repacketizer state to more + * than 120 ms. + */ +OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param begin int: The index of the first frame in the current + * repacketizer state to include in the output. + * @param end int: One past the index of the last frame in the + * current repacketizer state to include in the + * output. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1276 for a single frame, + * or for multiple frames, + * 1277*(end-begin). + * However, 1*(end-begin) plus + * the size of all packet data submitted to + * the repacketizer since the last call to + * opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG [begin,end) was an invalid range of + * frames (begin < 0, begin >= end, or end > + * opus_repacketizer_get_nb_frames()). + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Return the total number of frames contained in packet data submitted to + * the repacketizer state so far via opus_repacketizer_cat() since the last + * call to opus_repacketizer_init() or opus_repacketizer_create(). + * This defines the valid range of packets that can be extracted with + * opus_repacketizer_out_range() or opus_repacketizer_out(). + * @param rp OpusRepacketizer*: The repacketizer state containing the + * frames. + * @returns The total number of frames contained in the packet data submitted + * to the repacketizer state. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * This is a convenience routine that returns all the data submitted so far + * in a single packet. + * It is equivalent to calling + * @code + * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp), + * data, maxlen) + * @endcode + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1277*opus_repacketizer_get_nb_frames(rp). + * However, + * 1*opus_repacketizer_get_nb_frames(rp) + * plus the size of all packet data + * submitted to the repacketizer since the + * last call to opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1); + +/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence). + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to pad. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param new_len opus_int32: The desired size of the packet after padding. + * This must be at least as large as len. + * @returns an error code + * @retval #OPUS_OK \a on success. + * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len); + +/** Remove all padding from a given Opus packet and rewrite the TOC sequence to + * minimize space usage. + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to strip. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @returns The new size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG \a len was less than 1. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len); + +/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence). + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to pad. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param new_len opus_int32: The desired size of the packet after padding. + * This must be at least 1. + * @param nb_streams opus_int32: The number of streams (not channels) in the packet. + * This must be at least as large as len. + * @returns an error code + * @retval #OPUS_OK \a on success. + * @retval #OPUS_BAD_ARG \a len was less than 1. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams); + +/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to + * minimize space usage. + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to strip. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param nb_streams opus_int32: The number of streams (not channels) in the packet. + * This must be at least 1. + * @returns The new size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_H */ diff --git a/thirdparty/include/opus/opus_custom.h b/thirdparty/include/opus/opus_custom.h new file mode 100755 index 0000000000000000000000000000000000000000..2227be011bd2f1a09b34f9cdb58f5cc904e0b2dc --- /dev/null +++ b/thirdparty/include/opus/opus_custom.h @@ -0,0 +1,342 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008-2012 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file opus_custom.h + @brief Opus-Custom reference implementation API + */ + +#ifndef OPUS_CUSTOM_H +#define OPUS_CUSTOM_H + +#include "opus_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CUSTOM_MODES +# define OPUS_CUSTOM_EXPORT OPUS_EXPORT +# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT +#else +# define OPUS_CUSTOM_EXPORT +# ifdef OPUS_BUILD +# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE +# else +# define OPUS_CUSTOM_EXPORT_STATIC +# endif +#endif + +/** @defgroup opus_custom Opus Custom + * @{ + * Opus Custom is an optional part of the Opus specification and + * reference implementation which uses a distinct API from the regular + * API and supports frame sizes that are not normally supported.\ Use + * of Opus Custom is discouraged for all but very special applications + * for which a frame size different from 2.5, 5, 10, or 20 ms is needed + * (for either complexity or latency reasons) and where interoperability + * is less important. + * + * In addition to the interoperability limitations the use of Opus custom + * disables a substantial chunk of the codec and generally lowers the + * quality available at a given bitrate. Normally when an application needs + * a different frame size from the codec it should buffer to match the + * sizes but this adds a small amount of delay which may be important + * in some very low latency applications. Some transports (especially + * constant rate RF transports) may also work best with frames of + * particular durations. + * + * Libopus only supports custom modes if they are enabled at compile time. + * + * The Opus Custom API is similar to the regular API but the + * @ref opus_encoder_create and @ref opus_decoder_create calls take + * an additional mode parameter which is a structure produced by + * a call to @ref opus_custom_mode_create. Both the encoder and decoder + * must create a mode using the same sample rate (fs) and frame size + * (frame size) so these parameters must either be signaled out of band + * or fixed in a particular implementation. + * + * Similar to regular Opus the custom modes support on the fly frame size + * switching, but the sizes available depend on the particular frame size in + * use. For some initial frame sizes on a single on the fly size is available. + */ + +/** Contains the state of an encoder. One encoder state is needed + for each stream. It is initialized once at the beginning of the + stream. Do *not* re-initialize the state for every frame. + @brief Encoder state + */ +typedef struct OpusCustomEncoder OpusCustomEncoder; + +/** State of the decoder. One decoder state is needed for each stream. + It is initialized once at the beginning of the stream. Do *not* + re-initialize the state for every frame. + @brief Decoder state + */ +typedef struct OpusCustomDecoder OpusCustomDecoder; + +/** The mode contains all the information necessary to create an + encoder. Both the encoder and decoder need to be initialized + with exactly the same mode, otherwise the output will be + corrupted. + @brief Mode configuration + */ +typedef struct OpusCustomMode OpusCustomMode; + +/** Creates a new mode struct. This will be passed to an encoder or + * decoder. The mode MUST NOT BE DESTROYED until the encoders and + * decoders that use it are destroyed as well. + * @param [in] Fs int: Sampling rate (8000 to 96000 Hz) + * @param [in] frame_size int: Number of samples (per channel) to encode in each + * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes) + * @param [out] error int*: Returned error code (if NULL, no error will be returned) + * @return A newly created mode + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error); + +/** Destroys a mode struct. Only call this after all encoders and + * decoders using this mode are destroyed as well. + * @param [in] mode OpusCustomMode*: Mode to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode); + + +#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C) + +/* Encoder */ +/** Gets the size of an OpusCustomEncoder structure. + * @param [in] mode OpusCustomMode *: Mode configuration + * @param [in] channels int: Number of channels + * @returns size + */ +OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size( + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1); + +# ifdef CUSTOM_MODES +/** Initializes a previously allocated encoder state + * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size. + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_custom_encoder_create(),opus_custom_encoder_get_size() + * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * decoder) + * @param [in] channels int: Number of channels + * @return OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT int opus_custom_encoder_init( + OpusCustomEncoder *st, + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); +# endif +#endif + + +/** Creates a new encoder state. Each stream needs its own encoder + * state (can't be shared across simultaneous streams). + * @param [in] mode OpusCustomMode*: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * decoder) + * @param [in] channels int: Number of channels + * @param [out] error int*: Returns an error code + * @return Newly created encoder state. +*/ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create( + const OpusCustomMode *mode, + int channels, + int *error +) OPUS_ARG_NONNULL(1); + + +/** Destroys an encoder state. + * @param[in] st OpusCustomEncoder*: State to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st); + +/** Encodes a frame of audio. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] pcm float*: PCM audio in float format, with a normal range of +/-1.0. + * Samples with a range beyond +/-1.0 are supported but will + * be clipped by decoders using the integer API and should + * only be used if it is known that the far end supports + * extended dynamic range. There must be exactly + * frame_size samples per channel. + * @param [in] frame_size int: Number of samples per frame of input signal + * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. + * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame + * (can change from one frame to another) + * @return Number of bytes written to "compressed". + * If negative, an error has occurred (see error codes). It is IMPORTANT that + * the length returned be somehow transmitted to the decoder. Otherwise, no + * decoding is possible. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float( + OpusCustomEncoder *st, + const float *pcm, + int frame_size, + unsigned char *compressed, + int maxCompressedBytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes a frame of audio. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] pcm opus_int16*: PCM audio in signed 16-bit format (native endian). + * There must be exactly frame_size samples per channel. + * @param [in] frame_size int: Number of samples per frame of input signal + * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. + * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame + * (can change from one frame to another) + * @return Number of bytes written to "compressed". + * If negative, an error has occurred (see error codes). It is IMPORTANT that + * the length returned be somehow transmitted to the decoder. Otherwise, no + * decoding is possible. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode( + OpusCustomEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *compressed, + int maxCompressedBytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus custom encoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @see opus_encoderctls + */ +OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); + + +#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C) +/* Decoder */ + +/** Gets the size of an OpusCustomDecoder structure. + * @param [in] mode OpusCustomMode *: Mode configuration + * @param [in] channels int: Number of channels + * @returns size + */ +OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size( + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1); + +/** Initializes a previously allocated decoder state + * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size. + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_custom_decoder_create(),opus_custom_decoder_get_size() + * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * encoder) + * @param [in] channels int: Number of channels + * @return OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init( + OpusCustomDecoder *st, + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + +#endif + + +/** Creates a new decoder state. Each stream needs its own decoder state (can't + * be shared across simultaneous streams). + * @param [in] mode OpusCustomMode: Contains all the information about the characteristics of the + * stream (must be the same characteristics as used for the encoder) + * @param [in] channels int: Number of channels + * @param [out] error int*: Returns an error code + * @return Newly created decoder state. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create( + const OpusCustomMode *mode, + int channels, + int *error +) OPUS_ARG_NONNULL(1); + +/** Destroys a decoder state. + * @param[in] st OpusCustomDecoder*: State to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st); + +/** Decode an opus custom frame with floating point output + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len int: Number of bytes in payload + * @param [out] pcm float*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(float) + * @param [in] frame_size Number of samples per channel of available space in *pcm. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float( + OpusCustomDecoder *st, + const unsigned char *data, + int len, + float *pcm, + int frame_size +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode an opus custom frame + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len int: Number of bytes in payload + * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size Number of samples per channel of available space in *pcm. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode( + OpusCustomDecoder *st, + const unsigned char *data, + int len, + opus_int16 *pcm, + int frame_size +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus custom decoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @see opus_genericctls + */ +OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_CUSTOM_H */ diff --git a/thirdparty/include/opus/opus_defines.h b/thirdparty/include/opus/opus_defines.h new file mode 100755 index 0000000000000000000000000000000000000000..ceee5b840cf5b54bf73c7ba198f4079f5855e6bb --- /dev/null +++ b/thirdparty/include/opus/opus_defines.h @@ -0,0 +1,799 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus_defines.h + * @brief Opus reference implementation constants + */ + +#ifndef OPUS_DEFINES_H +#define OPUS_DEFINES_H + +#include "opus_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup opus_errorcodes Error codes + * @{ + */ +/** No error @hideinitializer*/ +#define OPUS_OK 0 +/** One or more invalid/out of range arguments @hideinitializer*/ +#define OPUS_BAD_ARG -1 +/** Not enough bytes allocated in the buffer @hideinitializer*/ +#define OPUS_BUFFER_TOO_SMALL -2 +/** An internal error was detected @hideinitializer*/ +#define OPUS_INTERNAL_ERROR -3 +/** The compressed data passed is corrupted @hideinitializer*/ +#define OPUS_INVALID_PACKET -4 +/** Invalid/unsupported request number @hideinitializer*/ +#define OPUS_UNIMPLEMENTED -5 +/** An encoder or decoder structure is invalid or already freed @hideinitializer*/ +#define OPUS_INVALID_STATE -6 +/** Memory allocation has failed @hideinitializer*/ +#define OPUS_ALLOC_FAIL -7 +/**@}*/ + +/** @cond OPUS_INTERNAL_DOC */ +/**Export control for opus functions */ + +#ifndef OPUS_EXPORT +# if defined(_WIN32) +# if defined(OPUS_BUILD) && defined(DLL_EXPORT) +# define OPUS_EXPORT __declspec(dllexport) +# else +# define OPUS_EXPORT +# endif +# elif defined(__GNUC__) && defined(OPUS_BUILD) +# define OPUS_EXPORT __attribute__ ((visibility ("default"))) +# else +# define OPUS_EXPORT +# endif +#endif + +# if !defined(OPUS_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OPUS_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OPUS_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if OPUS_GNUC_PREREQ(3,0) +# define OPUS_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define OPUS_RESTRICT __restrict +# else +# define OPUS_RESTRICT +# endif +#else +# define OPUS_RESTRICT restrict +#endif + +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if OPUS_GNUC_PREREQ(2,7) +# define OPUS_INLINE __inline__ +# elif (defined(_MSC_VER)) +# define OPUS_INLINE __inline +# else +# define OPUS_INLINE +# endif +#else +# define OPUS_INLINE inline +#endif + +/**Warning attributes for opus functions + * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out + * some paranoid null checks. */ +#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +#else +# define OPUS_WARN_UNUSED_RESULT +#endif +#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +#else +# define OPUS_ARG_NONNULL(_x) +#endif + +/** These are the actual Encoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +#define OPUS_SET_APPLICATION_REQUEST 4000 +#define OPUS_GET_APPLICATION_REQUEST 4001 +#define OPUS_SET_BITRATE_REQUEST 4002 +#define OPUS_GET_BITRATE_REQUEST 4003 +#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004 +#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005 +#define OPUS_SET_VBR_REQUEST 4006 +#define OPUS_GET_VBR_REQUEST 4007 +#define OPUS_SET_BANDWIDTH_REQUEST 4008 +#define OPUS_GET_BANDWIDTH_REQUEST 4009 +#define OPUS_SET_COMPLEXITY_REQUEST 4010 +#define OPUS_GET_COMPLEXITY_REQUEST 4011 +#define OPUS_SET_INBAND_FEC_REQUEST 4012 +#define OPUS_GET_INBAND_FEC_REQUEST 4013 +#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014 +#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015 +#define OPUS_SET_DTX_REQUEST 4016 +#define OPUS_GET_DTX_REQUEST 4017 +#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020 +#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021 +#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022 +#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023 +#define OPUS_SET_SIGNAL_REQUEST 4024 +#define OPUS_GET_SIGNAL_REQUEST 4025 +#define OPUS_GET_LOOKAHEAD_REQUEST 4027 +/* #define OPUS_RESET_STATE 4028 */ +#define OPUS_GET_SAMPLE_RATE_REQUEST 4029 +#define OPUS_GET_FINAL_RANGE_REQUEST 4031 +#define OPUS_GET_PITCH_REQUEST 4033 +#define OPUS_SET_GAIN_REQUEST 4034 +#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */ +#define OPUS_SET_LSB_DEPTH_REQUEST 4036 +#define OPUS_GET_LSB_DEPTH_REQUEST 4037 +#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039 +#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040 +#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041 +#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042 +#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043 +/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ +#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046 +#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047 +#define OPUS_GET_IN_DTX_REQUEST 4049 + +/** Defines for the presence of extended APIs. */ +#define OPUS_HAVE_OPUS_PROJECTION_H + +/* Macros to trigger compilation errors when the wrong types are provided to a CTL */ +#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x)) +#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) +#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr))) +#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) +/** @endcond */ + +/** @defgroup opus_ctlvalues Pre-defined values for CTL interface + * @see opus_genericctls, opus_encoderctls + * @{ + */ +/* Values for the various encoder CTLs */ +#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive. + * + * @hideinitializer */ +#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x) +/** Gets the encoder's complexity configuration. + * @see OPUS_SET_COMPLEXITY + * @param[out] x opus_int32 *: Returns a value in the range 0-10, + * inclusive. + * @hideinitializer */ +#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x) + +/** Configures the bitrate in the encoder. + * Rates from 500 to 512000 bits per second are meaningful, as well as the + * special values #OPUS_AUTO and #OPUS_BITRATE_MAX. + * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much + * rate as it can, which is useful for controlling the rate by adjusting the + * output buffer size. + * @see OPUS_GET_BITRATE + * @param[in] x opus_int32: Bitrate in bits per second. The default + * is determined based on the number of + * channels and the input sampling rate. + * @hideinitializer */ +#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x) +/** Gets the encoder's bitrate configuration. + * @see OPUS_SET_BITRATE + * @param[out] x opus_int32 *: Returns the bitrate in bits per second. + * The default is determined based on the + * number of channels and the input + * sampling rate. + * @hideinitializer */ +#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables variable bitrate (VBR) in the encoder. + * The configured bitrate may not be met exactly because frames must + * be an integer number of bytes in length. + * @see OPUS_GET_VBR + * @see OPUS_SET_VBR_CONSTRAINT + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Hard CBR. For LPC/hybrid modes at very low bit-rate, this can + * cause noticeable quality degradation.
+ *
1
VBR (default). The exact type of VBR is controlled by + * #OPUS_SET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */ +#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x) +/** Determine if variable bitrate (VBR) is enabled in the encoder. + * @see OPUS_SET_VBR + * @see OPUS_GET_VBR_CONSTRAINT + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Hard CBR.
+ *
1
VBR (default). The exact type of VBR may be retrieved via + * #OPUS_GET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */ +#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables constrained VBR in the encoder. + * This setting is ignored when the encoder is in CBR mode. + * @warning Only the MDCT mode of Opus currently heeds the constraint. + * Speech mode ignores it completely, hybrid mode may fail to obey it + * if the LPC layer uses more bitrate than the constraint would have + * permitted. + * @see OPUS_GET_VBR_CONSTRAINT + * @see OPUS_SET_VBR + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Unconstrained VBR.
+ *
1
Constrained VBR (default). This creates a maximum of one + * frame of buffering delay assuming a transport with a + * serialization speed of the nominal bitrate.
+ *
+ * @hideinitializer */ +#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x) +/** Determine if constrained VBR is enabled in the encoder. + * @see OPUS_SET_VBR_CONSTRAINT + * @see OPUS_GET_VBR + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Unconstrained VBR.
+ *
1
Constrained VBR (default).
+ *
+ * @hideinitializer */ +#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x) + +/** Configures mono/stereo forcing in the encoder. + * This can force the encoder to produce packets encoded as either mono or + * stereo, regardless of the format of the input audio. This is useful when + * the caller knows that the input signal is currently a mono source embedded + * in a stereo stream. + * @see OPUS_GET_FORCE_CHANNELS + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
Not forced (default)
+ *
1
Forced mono
+ *
2
Forced stereo
+ *
+ * @hideinitializer */ +#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x) +/** Gets the encoder's forced channel configuration. + * @see OPUS_SET_FORCE_CHANNELS + * @param[out] x opus_int32 *: + *
+ *
#OPUS_AUTO
Not forced (default)
+ *
1
Forced mono
+ *
2
Forced stereo
+ *
+ * @hideinitializer */ +#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x) + +/** Configures the maximum bandpass that the encoder will select automatically. + * Applications should normally use this instead of #OPUS_SET_BANDWIDTH + * (leaving that set to the default, #OPUS_AUTO). This allows the + * application to set an upper bound based on the type of input it is + * providing, but still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_MAX_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
+ *
OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
+ *
+ * @hideinitializer */ +#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Gets the encoder's configured maximum allowed bandpass. + * @see OPUS_SET_MAX_BANDWIDTH + * @param[out] x opus_int32 *: Allowed values: + *
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
+ *
+ * @hideinitializer */ +#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/** Sets the encoder's bandpass to a specific value. + * This prevents the encoder from automatically selecting the bandpass based + * on the available bitrate. If an application knows the bandpass of the input + * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH + * instead, which still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
+ *
+ * @hideinitializer */ +#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Configures the type of signal being encoded. + * This is a hint which helps the encoder's mode selection. + * @see OPUS_GET_SIGNAL + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
+ *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */ +#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal type. + * @see OPUS_SET_SIGNAL + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
+ *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */ +#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x) + + +/** Configures the encoder's intended application. + * The initial value is a mandatory argument to the encoder_create function. + * @see OPUS_GET_APPLICATION + * @param[in] x opus_int32: Returns one of the following values: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @hideinitializer */ +#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured application. + * @see OPUS_SET_APPLICATION + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @hideinitializer */ +#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x) + +/** Gets the total samples of delay added by the entire codec. + * This can be queried by the encoder and then the provided number of samples can be + * skipped on from the start of the decoder's output to provide time aligned input + * and output. From the perspective of a decoding application the real data begins this many + * samples late. + * + * The decoder contribution to this delay is identical for all decoders, but the + * encoder portion of the delay may vary from implementation to implementation, + * version to version, or even depend on the encoder's initial configuration. + * Applications needing delay compensation should call this CTL rather than + * hard-coding a value. + * @param[out] x opus_int32 *: Number of lookahead samples + * @hideinitializer */ +#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of inband forward error correction (FEC). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_INBAND_FEC + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Disable inband FEC (default).
+ *
1
Enable inband FEC.
+ *
+ * @hideinitializer */ +#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of inband forward error correction. + * @see OPUS_SET_INBAND_FEC + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Inband FEC disabled (default).
+ *
1
Inband FEC enabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's expected packet loss percentage. + * Higher values trigger progressively more loss resistant behavior in the encoder + * at the expense of quality at a given bitrate in the absence of packet loss, but + * greater quality under loss. + * @see OPUS_GET_PACKET_LOSS_PERC + * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured packet loss percentage. + * @see OPUS_SET_PACKET_LOSS_PERC + * @param[out] x opus_int32 *: Returns the configured loss percentage + * in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of discontinuous transmission (DTX). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_DTX + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Disable DTX (default).
+ *
1
Enabled DTX.
+ *
+ * @hideinitializer */ +#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of discontinuous transmission. + * @see OPUS_SET_DTX + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
DTX disabled (default).
+ *
1
DTX enabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x) +/** Configures the depth of signal being encoded. + * + * This is a hint which helps the encoder identify silence and near-silence. + * It represents the number of significant bits of linear intensity below + * which the signal contains ignorable quantization or other noise. + * + * For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting + * for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate + * for 16-bit linear pcm input with opus_encode_float(). + * + * When using opus_encode() instead of opus_encode_float(), or when libopus + * is compiled for fixed-point, the encoder uses the minimum of the value + * set here and the value 16. + * + * @see OPUS_GET_LSB_DEPTH + * @param[in] x opus_int32: Input precision in bits, between 8 and 24 + * (default: 24). + * @hideinitializer */ +#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal depth. + * @see OPUS_SET_LSB_DEPTH + * @param[out] x opus_int32 *: Input precision in bits, between 8 and + * 24 (default: 24). + * @hideinitializer */ +#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of variable duration frames. + * When variable duration is enabled, the encoder is free to use a shorter frame + * size than the one requested in the opus_encode*() call. + * It is then the user's responsibility + * to verify how much audio was encoded by checking the ToC byte of the encoded + * packet. The part of the audio that was not encoded needs to be resent to the + * encoder for the next call. Do not use this option unless you really + * know what you are doing. + * @see OPUS_GET_EXPERT_FRAME_DURATION + * @param[in] x opus_int32: Allowed values: + *
+ *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
+ *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
+ *
OPUS_FRAMESIZE_5_MS
Use 5 ms frames.
+ *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
+ *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
+ *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
+ *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
+ *
OPUS_FRAMESIZE_80_MS
Use 80 ms frames.
+ *
OPUS_FRAMESIZE_100_MS
Use 100 ms frames.
+ *
OPUS_FRAMESIZE_120_MS
Use 120 ms frames.
+ *
+ * @hideinitializer */ +#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured use of variable duration frames. + * @see OPUS_SET_EXPERT_FRAME_DURATION + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
OPUS_FRAMESIZE_ARG
Select frame size from the argument (default).
+ *
OPUS_FRAMESIZE_2_5_MS
Use 2.5 ms frames.
+ *
OPUS_FRAMESIZE_5_MS
Use 5 ms frames.
+ *
OPUS_FRAMESIZE_10_MS
Use 10 ms frames.
+ *
OPUS_FRAMESIZE_20_MS
Use 20 ms frames.
+ *
OPUS_FRAMESIZE_40_MS
Use 40 ms frames.
+ *
OPUS_FRAMESIZE_60_MS
Use 60 ms frames.
+ *
OPUS_FRAMESIZE_80_MS
Use 80 ms frames.
+ *
OPUS_FRAMESIZE_100_MS
Use 100 ms frames.
+ *
OPUS_FRAMESIZE_120_MS
Use 120 ms frames.
+ *
+ * @hideinitializer */ +#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x) + +/** If set to 1, disables almost all use of prediction, making frames almost + * completely independent. This reduces quality. + * @see OPUS_GET_PREDICTION_DISABLED + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Enable prediction (default).
+ *
1
Disable prediction.
+ *
+ * @hideinitializer */ +#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured prediction status. + * @see OPUS_SET_PREDICTION_DISABLED + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Prediction enabled (default).
+ *
1
Prediction disabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_genericctls Generic CTLs + * + * These macros are used with the \c opus_decoder_ctl and + * \c opus_encoder_ctl calls to generate a particular + * request. + * + * When called on an \c OpusDecoder they apply to that + * particular decoder instance. When called on an + * \c OpusEncoder they apply to the corresponding setting + * on that encoder instance, if present. + * + * Some usage examples: + * + * @code + * int ret; + * opus_int32 pitch; + * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch)); + * if (ret == OPUS_OK) return ret; + * + * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE); + * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE); + * + * opus_int32 enc_bw, dec_bw; + * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw)); + * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw)); + * if (enc_bw != dec_bw) { + * printf("packet bandwidth mismatch!\n"); + * } + * @endcode + * + * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls + * @{ + */ + +/** Resets the codec state to be equivalent to a freshly initialized state. + * This should be called when switching streams in order to prevent + * the back to back decoding from giving different results from + * one at a time decoding. + * @hideinitializer */ +#define OPUS_RESET_STATE 4028 + +/** Gets the final state of the codec's entropy coder. + * This is used for testing purposes, + * The encoder and decoder state should be identical after coding a payload + * (assuming no data corruption or software bugs) + * + * @param[out] x opus_uint32 *: Entropy coder state + * + * @hideinitializer */ +#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x) + +/** Gets the encoder's configured bandpass or the decoder's last bandpass. + * @see OPUS_SET_BANDWIDTH + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
+ *
+ * @hideinitializer */ +#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the sampling rate the encoder or decoder was initialized with. + * This simply returns the Fs value passed to opus_encoder_init() + * or opus_decoder_init(). + * @param[out] x opus_int32 *: Sampling rate of encoder or decoder. + * @hideinitializer + */ +#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x) + +/** If set to 1, disables the use of phase inversion for intensity stereo, + * improving the quality of mono downmixes, but slightly reducing normal + * stereo quality. Disabling phase inversion in the decoder does not comply + * with RFC 6716, although it does not cause any interoperability issue and + * is expected to become part of the Opus standard once RFC 6716 is updated + * by draft-ietf-codec-opus-update. + * @see OPUS_GET_PHASE_INVERSION_DISABLED + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Enable phase inversion (default).
+ *
1
Disable phase inversion.
+ *
+ * @hideinitializer */ +#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured phase inversion status. + * @see OPUS_SET_PHASE_INVERSION_DISABLED + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Stereo phase inversion enabled (default).
+ *
1
Stereo phase inversion disabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x) +/** Gets the DTX state of the encoder. + * Returns whether the last encoded frame was either a comfort noise update + * during DTX or not encoded because of DTX. + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
The encoder is not in DTX.
+ *
1
The encoder is in DTX.
+ *
+ * @hideinitializer */ +#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_decoderctls Decoder related CTLs + * @see opus_genericctls, opus_encoderctls, opus_decoder + * @{ + */ + +/** Configures decoder gain adjustment. + * Scales the decoded output by a factor specified in Q8 dB units. + * This has a maximum range of -32768 to 32767 inclusive, and returns + * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment. + * This setting survives decoder reset. + * + * gain = pow(10, x/(20.0*256)) + * + * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x) +/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN + * + * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x) + +/** Gets the duration (in samples) of the last packet successfully decoded or concealed. + * @param[out] x opus_int32 *: Number of samples (at current sampling rate). + * @hideinitializer */ +#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x) + +/** Gets the pitch of the last decoded frame, if available. + * This can be used for any post-processing algorithm requiring the use of pitch, + * e.g. time stretching/shortening. If the last frame was not voiced, or if the + * pitch was not coded in the frame, then zero is returned. + * + * This CTL is only implemented for decoder instances. + * + * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available) + * + * @hideinitializer */ +#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_libinfo Opus library information functions + * @{ + */ + +/** Converts an opus error code into a human readable string. + * + * @param[in] error int: Error number + * @returns Error string + */ +OPUS_EXPORT const char *opus_strerror(int error); + +/** Gets the libopus version string. + * + * Applications may look for the substring "-fixed" in the version string to + * determine whether they have a fixed-point or floating-point build at + * runtime. + * + * @returns Version string + */ +OPUS_EXPORT const char *opus_get_version_string(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_DEFINES_H */ diff --git a/thirdparty/include/opus/opus_multistream.h b/thirdparty/include/opus/opus_multistream.h new file mode 100755 index 0000000000000000000000000000000000000000..babcee6905bf9f70d922eb903d28a9151f053505 --- /dev/null +++ b/thirdparty/include/opus/opus_multistream.h @@ -0,0 +1,660 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus_multistream.h + * @brief Opus reference implementation multistream API + */ + +#ifndef OPUS_MULTISTREAM_H +#define OPUS_MULTISTREAM_H + +#include "opus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond OPUS_INTERNAL_DOC */ + +/** Macros to trigger compilation errors when the wrong types are provided to a + * CTL. */ +/**@{*/ +#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr))) +#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr))) +/**@}*/ + +/** These are the actual encoder and decoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +/**@{*/ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120 +#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122 +/**@}*/ + +/** @endcond */ + +/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs + * + * These are convenience macros that are specific to the + * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl() + * interface. + * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and + * @ref opus_decoderctls may be applied to a multistream encoder or decoder as + * well. + * In addition, you may retrieve the encoder or decoder state for an specific + * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or + * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually. + */ +/**@{*/ + +/** Gets the encoder state for an individual stream of a multistream encoder. + * @param[in] x opus_int32: The index of the stream whose encoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the encoder. + * @param[out] y OpusEncoder**: Returns a pointer to the given + * encoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y) + +/** Gets the decoder state for an individual stream of a multistream decoder. + * @param[in] x opus_int32: The index of the stream whose decoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the decoder. + * @param[out] y OpusDecoder**: Returns a pointer to the given + * decoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y) + +/**@}*/ + +/** @defgroup opus_multistream Opus Multistream API + * @{ + * + * The multistream API allows individual Opus streams to be combined into a + * single packet, enabling support for up to 255 channels. Unlike an + * elementary Opus stream, the encoder and decoder must negotiate the channel + * configuration before the decoder can successfully interpret the data in the + * packets produced by the encoder. Some basic information, such as packet + * duration, can be computed without any special negotiation. + * + * The format for multistream Opus packets is defined in + * RFC 7845 + * and is based on the self-delimited Opus framing described in Appendix B of + * RFC 6716. + * Normal Opus packets are just a degenerate case of multistream Opus packets, + * and can be encoded or decoded with the multistream API by setting + * streams to 1 when initializing the encoder or + * decoder. + * + * Multistream Opus streams can contain up to 255 elementary Opus streams. + * These may be either "uncoupled" or "coupled", indicating that the decoder + * is configured to decode them to either 1 or 2 channels, respectively. + * The streams are ordered so that all coupled streams appear at the + * beginning. + * + * A mapping table defines which decoded channel i + * should be used for each input/output (I/O) channel j. This table is + * typically provided as an unsigned char array. + * Let i = mapping[j] be the index for I/O channel j. + * If i < 2*coupled_streams, then I/O channel j is + * encoded as the left channel of stream (i/2) if i + * is even, or as the right channel of stream (i/2) if + * i is odd. Otherwise, I/O channel j is encoded as + * mono in stream (i - coupled_streams), unless it has the special + * value 255, in which case it is omitted from the encoding entirely (the + * decoder will reproduce it as silence). Each value i must either + * be the special value 255 or be less than streams + coupled_streams. + * + * The output channels specified by the encoder + * should use the + * Vorbis + * channel ordering. A decoder may wish to apply an additional permutation + * to the mapping the encoder used to achieve a different output channel + * order (e.g. for outputing in WAV order). + * + * Each multistream packet contains an Opus packet for each stream, and all of + * the Opus packets in a single multistream packet must have the same + * duration. Therefore the duration of a multistream packet can be extracted + * from the TOC sequence of the first stream, which is located at the + * beginning of the packet, just like an elementary Opus stream: + * + * @code + * int nb_samples; + * int nb_frames; + * nb_frames = opus_packet_get_nb_frames(data, len); + * if (nb_frames < 1) + * return nb_frames; + * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames; + * @endcode + * + * The general encoding and decoding process proceeds exactly the same as in + * the normal @ref opus_encoder and @ref opus_decoder APIs. + * See their documentation for an overview of how to use the corresponding + * multistream functions. + */ + +/** Opus multistream encoder state. + * This contains the complete state of a multistream Opus encoder. + * It is position independent and can be freely copied. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_init + */ +typedef struct OpusMSEncoder OpusMSEncoder; + +/** Opus multistream decoder state. + * This contains the complete state of a multistream Opus decoder. + * It is position independent and can be freely copied. + * @see opus_multistream_decoder_create + * @see opus_multistream_decoder_init + */ +typedef struct OpusMSDecoder OpusMSDecoder; + +/**\name Multistream encoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSEncoder structure. + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( + int streams, + int coupled_streams +); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size( + int channels, + int mapping_family +); + + +/** Allocates and initializes a multistream encoder state. + * Call opus_multistream_encoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(5); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create( + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); + +/** Initialize a previously allocated multistream encoder state. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +OPUS_EXPORT int opus_multistream_surround_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7); + +/** Encodes a multistream Opus frame. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const opus_int16*: The input signal as interleaved + * samples. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode( + OpusMSEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes a multistream Opus frame from floating point input. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const float*: The input signal as interleaved + * samples with a normal range of + * +/-1.0. + * Samples with a range beyond +/-1.0 + * are supported but will be clipped by + * decoders using the integer API and + * should only be used if it is known + * that the far end supports extended + * dynamic range. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float( + OpusMSEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusMSEncoder allocated by + * opus_multistream_encoder_create(). + * @param st OpusMSEncoder*: Multistream encoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st); + +/** Perform a CTL function on a multistream Opus encoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_encoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_encoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/**@}*/ + +/**\name Multistream decoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSDecoder structure. + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( + int streams, + int coupled_streams +); + +/** Allocates and initializes a multistream decoder state. + * Call opus_multistream_decoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int *error +) OPUS_ARG_NONNULL(5); + +/** Intialize a previously allocated decoder state object. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_decoder_create + * @see opus_multistream_deocder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_decoder_init( + OpusMSDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +/** Decode a multistream Opus packet. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode a multistream Opus packet with floating point output. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on a multistream Opus decoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_decoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_decoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusMSDecoder allocated by + * opus_multistream_decoder_create(). + * @param st OpusMSDecoder: Multistream decoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st); + +/**@}*/ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_MULTISTREAM_H */ diff --git a/thirdparty/include/opus/opus_projection.h b/thirdparty/include/opus/opus_projection.h new file mode 100755 index 0000000000000000000000000000000000000000..9dabf4e85cf0be698f3215325bec40c5643b5241 --- /dev/null +++ b/thirdparty/include/opus/opus_projection.h @@ -0,0 +1,568 @@ +/* Copyright (c) 2017 Google Inc. + Written by Andrew Allen */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus_projection.h + * @brief Opus projection reference API + */ + +#ifndef OPUS_PROJECTION_H +#define OPUS_PROJECTION_H + +#include "opus_multistream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond OPUS_INTERNAL_DOC */ + +/** These are the actual encoder and decoder CTL ID numbers. + * They should not be used directly by applications.c + * In general, SETs should be even and GETs should be odd.*/ +/**@{*/ +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001 +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003 +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005 +/**@}*/ + + +/** @endcond */ + +/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs + * + * These are convenience macros that are specific to the + * opus_projection_encoder_ctl() and opus_projection_decoder_ctl() + * interface. + * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, + * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a + * projection encoder or decoder as well. + */ +/**@{*/ + +/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder. + * @param[out] x opus_int32 *: Returns the gain (in dB. S7.8-format) + * of the demixing matrix. + * @hideinitializer + */ +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x) + + +/** Gets the size in bytes of the demixing matrix from the encoder. + * @param[out] x opus_int32 *: Returns the size in bytes of the + * demixing matrix. + * @hideinitializer + */ +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x) + + +/** Copies the demixing matrix to the supplied pointer location. + * @param[out] x unsigned char *: Returns the demixing matrix to the + * supplied pointer location. + * @param y opus_int32: The size in bytes of the reserved memory at the + * pointer location. + * @hideinitializer + */ +#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y) + + +/**@}*/ + +/** Opus projection encoder state. + * This contains the complete state of a projection Opus encoder. + * It is position independent and can be freely copied. + * @see opus_projection_ambisonics_encoder_create + */ +typedef struct OpusProjectionEncoder OpusProjectionEncoder; + + +/** Opus projection decoder state. + * This contains the complete state of a projection Opus decoder. + * It is position independent and can be freely copied. + * @see opus_projection_decoder_create + * @see opus_projection_decoder_init + */ +typedef struct OpusProjectionDecoder OpusProjectionDecoder; + + +/**\name Projection encoder functions */ +/**@{*/ + +/** Gets the size of an OpusProjectionEncoder structure. + * @param channels int: The total number of input channels to encode. + * This must be no more than 255. + * @param mapping_family int: The mapping family to use for selecting + * the appropriate projection. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size( + int channels, + int mapping_family +); + + +/** Allocates and initializes a projection encoder state. + * Call opus_projection_encoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param mapping_family int: The mapping family to use for selecting + * the appropriate projection. + * @param[out] streams int *: The total number of streams that will + * be encoded from the input. + * @param[out] coupled_streams int *: Number of coupled (2 channel) + * streams that will be encoded from the input. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create( + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + int application, + int *error +) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5); + + +/** Initialize a previously allocated projection encoder state. + * The memory pointed to by \a st must be at least the size returned by + * opus_projection_ambisonics_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_projection_ambisonics_encoder_create + * @see opus_projection_ambisonics_encoder_get_size + * @param st OpusProjectionEncoder*: Projection encoder state to initialize. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_projection_ambisonics_encoder_init( + OpusProjectionEncoder *st, + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); + + +/** Encodes a projection Opus frame. + * @param st OpusProjectionEncoder*: Projection encoder state. + * @param[in] pcm const opus_int16*: The input signal as interleaved + * samples. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode( + OpusProjectionEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + + +/** Encodes a projection Opus frame from floating point input. + * @param st OpusProjectionEncoder*: Projection encoder state. + * @param[in] pcm const float*: The input signal as interleaved + * samples with a normal range of + * +/-1.0. + * Samples with a range beyond +/-1.0 + * are supported but will be clipped by + * decoders using the integer API and + * should only be used if it is known + * that the far end supports extended + * dynamic range. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float( + OpusProjectionEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + + +/** Frees an OpusProjectionEncoder allocated by + * opus_projection_ambisonics_encoder_create(). + * @param st OpusProjectionEncoder*: Projection encoder state to be freed. + */ +OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st); + + +/** Perform a CTL function on a projection Opus encoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusProjectionEncoder*: Projection encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_encoderctls, @ref opus_multistream_ctls, or + * @ref opus_projection_ctls + * @see opus_genericctls + * @see opus_encoderctls + * @see opus_multistream_ctls + * @see opus_projection_ctls + */ +OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); + + +/**@}*/ + +/**\name Projection decoder functions */ +/**@{*/ + +/** Gets the size of an OpusProjectionDecoder structure. + * @param channels int: The total number of output channels. + * This must be no more than 255. + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size( + int channels, + int streams, + int coupled_streams +); + + +/** Allocates and initializes a projection decoder state. + * Call opus_projection_decoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix + * that mapping from coded channels to output channels, + * as described in @ref opus_projection and + * @ref opus_projection_ctls. + * @param demixing_matrix_size opus_int32: The size in bytes of the + * demixing matrix, as + * described in @ref + * opus_projection_ctls. + * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + unsigned char *demixing_matrix, + opus_int32 demixing_matrix_size, + int *error +) OPUS_ARG_NONNULL(5); + + +/** Intialize a previously allocated projection decoder state object. + * The memory pointed to by \a st must be at least the size returned by + * opus_projection_decoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_projection_decoder_create + * @see opus_projection_deocder_get_size + * @param st OpusProjectionDecoder*: Projection encoder state to initialize. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] demixing_matrix const unsigned char[demixing_matrix_size]: Demixing matrix + * that mapping from coded channels to output channels, + * as described in @ref opus_projection and + * @ref opus_projection_ctls. + * @param demixing_matrix_size opus_int32: The size in bytes of the + * demixing matrix, as + * described in @ref + * opus_projection_ctls. + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_projection_decoder_init( + OpusProjectionDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + unsigned char *demixing_matrix, + opus_int32 demixing_matrix_size +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + + +/** Decode a projection Opus packet. + * @param st OpusProjectionDecoder*: Projection decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode( + OpusProjectionDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + + +/** Decode a projection Opus packet with floating point output. + * @param st OpusProjectionDecoder*: Projection decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float( + OpusProjectionDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + + +/** Perform a CTL function on a projection Opus decoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusProjectionDecoder*: Projection decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_decoderctls, @ref opus_multistream_ctls, or + * @ref opus_projection_ctls. + * @see opus_genericctls + * @see opus_decoderctls + * @see opus_multistream_ctls + * @see opus_projection_ctls + */ +OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + + +/** Frees an OpusProjectionDecoder allocated by + * opus_projection_decoder_create(). + * @param st OpusProjectionDecoder: Projection decoder state to be freed. + */ +OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st); + + +/**@}*/ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_PROJECTION_H */ diff --git a/thirdparty/include/opus/opus_types.h b/thirdparty/include/opus/opus_types.h new file mode 100755 index 0000000000000000000000000000000000000000..7cf675580ffb0ad9ba7b040a5c03eb2828910486 --- /dev/null +++ b/thirdparty/include/opus/opus_types.h @@ -0,0 +1,166 @@ +/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */ +/* Modified by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* opus_types.h based on ogg_types.h from libogg */ + +/** + @file opus_types.h + @brief Opus reference implementation types +*/ +#ifndef OPUS_TYPES_H +#define OPUS_TYPES_H + +#define opus_int int /* used for counters etc; at least 16 bits */ +#define opus_int64 long long +#define opus_int8 signed char + +#define opus_uint unsigned int /* used for counters etc; at least 16 bits */ +#define opus_uint64 unsigned long long +#define opus_uint8 unsigned char + +/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ +#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) +#include +# undef opus_int64 +# undef opus_int8 +# undef opus_uint64 +# undef opus_uint8 + typedef int8_t opus_int8; + typedef uint8_t opus_uint8; + typedef int16_t opus_int16; + typedef uint16_t opus_uint16; + typedef int32_t opus_int32; + typedef uint32_t opus_uint32; + typedef int64_t opus_int64; + typedef uint64_t opus_uint64; +#elif defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t opus_int32; + typedef _G_uint32_t opus_uint32; + typedef _G_int16 opus_int16; + typedef _G_uint16 opus_uint16; +# elif defined(__MINGW32__) + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; +# elif defined(__MWERKS__) + typedef int opus_int32; + typedef unsigned int opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; +# else + /* MSVC/Borland */ + typedef __int32 opus_int32; + typedef unsigned __int32 opus_uint32; + typedef __int16 opus_int16; + typedef unsigned __int16 opus_uint16; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 opus_int16; + typedef UInt16 opus_uint16; + typedef SInt32 opus_int32; + typedef UInt32 opus_uint32; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t opus_int16; + typedef u_int16_t opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16 opus_int16; + typedef u_int16 opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int opus_int32; + typedef unsigned opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short opus_int16; + typedef unsigned short opus_uint16; + typedef signed int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef long opus_int32; + typedef unsigned long opus_uint32; + +#elif defined(CONFIG_TI_C6X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#else + + /* Give up, take a reasonable guess */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#endif + +#endif /* OPUS_TYPES_H */ diff --git a/thirdparty/include/speex/speex.h b/thirdparty/include/speex/speex.h new file mode 100755 index 0000000000000000000000000000000000000000..28c4b44df83888ca421e6c559c98643cb8753232 --- /dev/null +++ b/thirdparty/include/speex/speex.h @@ -0,0 +1,425 @@ +/* Copyright (C) 2002-2006 Jean-Marc Valin*/ +/** + @file speex.h + @brief Describes the different modes of the codec +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_H +#define SPEEX_H +/** @defgroup Codec Speex encoder and decoder + * This is the Speex codec itself. + * @{ + */ + +#include "speex_types.h" +#include "speex_bits.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Values allowed for *ctl() requests */ + +/** Set enhancement on/off (decoder only) */ +#define SPEEX_SET_ENH 0 +/** Get enhancement state (decoder only) */ +#define SPEEX_GET_ENH 1 + +/*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/ +/** Obtain frame size used by encoder/decoder */ +#define SPEEX_GET_FRAME_SIZE 3 + +/** Set quality value */ +#define SPEEX_SET_QUALITY 4 +/** Get current quality setting */ +/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */ + +/** Set sub-mode to use */ +#define SPEEX_SET_MODE 6 +/** Get current sub-mode in use */ +#define SPEEX_GET_MODE 7 + +/** Set low-band sub-mode to use (wideband only)*/ +#define SPEEX_SET_LOW_MODE 8 +/** Get current low-band mode in use (wideband only)*/ +#define SPEEX_GET_LOW_MODE 9 + +/** Set high-band sub-mode to use (wideband only)*/ +#define SPEEX_SET_HIGH_MODE 10 +/** Get current high-band mode in use (wideband only)*/ +#define SPEEX_GET_HIGH_MODE 11 + +/** Set VBR on (1) or off (0) */ +#define SPEEX_SET_VBR 12 +/** Get VBR status (1 for on, 0 for off) */ +#define SPEEX_GET_VBR 13 + +/** Set quality value for VBR encoding (0-10) */ +#define SPEEX_SET_VBR_QUALITY 14 +/** Get current quality value for VBR encoding (0-10) */ +#define SPEEX_GET_VBR_QUALITY 15 + +/** Set complexity of the encoder (0-10) */ +#define SPEEX_SET_COMPLEXITY 16 +/** Get current complexity of the encoder (0-10) */ +#define SPEEX_GET_COMPLEXITY 17 + +/** Set bit-rate used by the encoder (or lower) */ +#define SPEEX_SET_BITRATE 18 +/** Get current bit-rate used by the encoder or decoder */ +#define SPEEX_GET_BITRATE 19 + +/** Define a handler function for in-band Speex request*/ +#define SPEEX_SET_HANDLER 20 + +/** Define a handler function for in-band user-defined request*/ +#define SPEEX_SET_USER_HANDLER 22 + +/** Set sampling rate used in bit-rate computation */ +#define SPEEX_SET_SAMPLING_RATE 24 +/** Get sampling rate used in bit-rate computation */ +#define SPEEX_GET_SAMPLING_RATE 25 + +/** Reset the encoder/decoder memories to zero*/ +#define SPEEX_RESET_STATE 26 + +/** Get VBR info (mostly used internally) */ +#define SPEEX_GET_RELATIVE_QUALITY 29 + +/** Set VAD status (1 for on, 0 for off) */ +#define SPEEX_SET_VAD 30 + +/** Get VAD status (1 for on, 0 for off) */ +#define SPEEX_GET_VAD 31 + +/** Set Average Bit-Rate (ABR) to n bits per seconds */ +#define SPEEX_SET_ABR 32 +/** Get Average Bit-Rate (ABR) setting (in bps) */ +#define SPEEX_GET_ABR 33 + +/** Set DTX status (1 for on, 0 for off) */ +#define SPEEX_SET_DTX 34 +/** Get DTX status (1 for on, 0 for off) */ +#define SPEEX_GET_DTX 35 + +/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */ +#define SPEEX_SET_SUBMODE_ENCODING 36 +/** Get submode encoding in each frame */ +#define SPEEX_GET_SUBMODE_ENCODING 37 + +/*#define SPEEX_SET_LOOKAHEAD 38*/ +/** Returns the lookahead used by Speex separately for an encoder and a decoder. + * Sum encoder and decoder lookahead values to get the total codec lookahead. */ +#define SPEEX_GET_LOOKAHEAD 39 + +/** Sets tuning for packet-loss concealment (expected loss rate) */ +#define SPEEX_SET_PLC_TUNING 40 +/** Gets tuning for PLC */ +#define SPEEX_GET_PLC_TUNING 41 + +/** Sets the max bit-rate allowed in VBR mode */ +#define SPEEX_SET_VBR_MAX_BITRATE 42 +/** Gets the max bit-rate allowed in VBR mode */ +#define SPEEX_GET_VBR_MAX_BITRATE 43 + +/** Turn on/off input/output high-pass filtering */ +#define SPEEX_SET_HIGHPASS 44 +/** Get status of input/output high-pass filtering */ +#define SPEEX_GET_HIGHPASS 45 + +/** Get "activity level" of the last decoded frame, i.e. + how much damage we cause if we remove the frame */ +#define SPEEX_GET_ACTIVITY 47 + + +/* Preserving compatibility:*/ +/** Equivalent to SPEEX_SET_ENH */ +#define SPEEX_SET_PF 0 +/** Equivalent to SPEEX_GET_ENH */ +#define SPEEX_GET_PF 1 + + + + +/* Values allowed for mode queries */ +/** Query the frame size of a mode */ +#define SPEEX_MODE_FRAME_SIZE 0 + +/** Query the size of an encoded frame for a particular sub-mode */ +#define SPEEX_SUBMODE_BITS_PER_FRAME 1 + + + +/** Get major Speex version */ +#define SPEEX_LIB_GET_MAJOR_VERSION 1 +/** Get minor Speex version */ +#define SPEEX_LIB_GET_MINOR_VERSION 3 +/** Get micro Speex version */ +#define SPEEX_LIB_GET_MICRO_VERSION 5 +/** Get extra Speex version */ +#define SPEEX_LIB_GET_EXTRA_VERSION 7 +/** Get Speex version string */ +#define SPEEX_LIB_GET_VERSION_STRING 9 + +/*#define SPEEX_LIB_SET_ALLOC_FUNC 10 +#define SPEEX_LIB_GET_ALLOC_FUNC 11 +#define SPEEX_LIB_SET_FREE_FUNC 12 +#define SPEEX_LIB_GET_FREE_FUNC 13 + +#define SPEEX_LIB_SET_WARNING_FUNC 14 +#define SPEEX_LIB_GET_WARNING_FUNC 15 +#define SPEEX_LIB_SET_ERROR_FUNC 16 +#define SPEEX_LIB_GET_ERROR_FUNC 17 +*/ + +/** Number of defined modes in Speex */ +#define SPEEX_NB_MODES 3 + +/** modeID for the defined narrowband mode */ +#define SPEEX_MODEID_NB 0 + +/** modeID for the defined wideband mode */ +#define SPEEX_MODEID_WB 1 + +/** modeID for the defined ultra-wideband mode */ +#define SPEEX_MODEID_UWB 2 + +struct SpeexMode; + + +/* Prototypes for mode function pointers */ + +/** Encoder state initialization function */ +typedef void *(*encoder_init_func)(const struct SpeexMode *mode); + +/** Encoder state destruction function */ +typedef void (*encoder_destroy_func)(void *st); + +/** Main encoding function */ +typedef int (*encode_func)(void *state, void *in, SpeexBits *bits); + +/** Function for controlling the encoder options */ +typedef int (*encoder_ctl_func)(void *state, int request, void *ptr); + +/** Decoder state initialization function */ +typedef void *(*decoder_init_func)(const struct SpeexMode *mode); + +/** Decoder state destruction function */ +typedef void (*decoder_destroy_func)(void *st); + +/** Main decoding function */ +typedef int (*decode_func)(void *state, SpeexBits *bits, void *out); + +/** Function for controlling the decoder options */ +typedef int (*decoder_ctl_func)(void *state, int request, void *ptr); + + +/** Query function for a mode */ +typedef int (*mode_query_func)(const void *mode, int request, void *ptr); + +/** Struct defining a Speex mode */ +typedef struct SpeexMode { + /** Pointer to the low-level mode data */ + const void *mode; + + /** Pointer to the mode query function */ + mode_query_func query; + + /** The name of the mode (you should not rely on this to identify the mode)*/ + const char *modeName; + + /**ID of the mode*/ + int modeID; + + /**Version number of the bitstream (incremented every time we break + bitstream compatibility*/ + int bitstream_version; + + /** Pointer to encoder initialization function */ + encoder_init_func enc_init; + + /** Pointer to encoder destruction function */ + encoder_destroy_func enc_destroy; + + /** Pointer to frame encoding function */ + encode_func enc; + + /** Pointer to decoder initialization function */ + decoder_init_func dec_init; + + /** Pointer to decoder destruction function */ + decoder_destroy_func dec_destroy; + + /** Pointer to frame decoding function */ + decode_func dec; + + /** ioctl-like requests for encoder */ + encoder_ctl_func enc_ctl; + + /** ioctl-like requests for decoder */ + decoder_ctl_func dec_ctl; + +} SpeexMode; + +/** + * Returns a handle to a newly created Speex encoder state structure. For now, + * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes + * may be added. Note that for now if you have more than one channels to + * encode, you need one state per channel. + * + * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) + * @return A newly created encoder state or NULL if state allocation fails + */ +void *speex_encoder_init(const SpeexMode *mode); + +/** Frees all resources associated to an existing Speex encoder state. + * @param state Encoder state to be destroyed */ +void speex_encoder_destroy(void *state); + +/** Uses an existing encoder state to encode one frame of speech pointed to by + "in". The encoded bit-stream is saved in "bits". + @param state Encoder state + @param in Frame that will be encoded with a +-2^15 range. This data MAY be + overwritten by the encoder and should be considered uninitialised + after the call. + @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + */ +int speex_encode(void *state, float *in, SpeexBits *bits); + +/** Uses an existing encoder state to encode one frame of speech pointed to by + "in". The encoded bit-stream is saved in "bits". + @param state Encoder state + @param in Frame that will be encoded with a +-2^15 range + @param bits Bit-stream where the data will be written + @return 0 if frame needs not be transmitted (DTX only), 1 otherwise + */ +int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits); + +/** Used like the ioctl function to control the encoder parameters + * + * @param state Encoder state + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_encoder_ctl(void *state, int request, void *ptr); + + +/** Returns a handle to a newly created decoder state structure. For now, + * the mode argument can be &nb_mode or &wb_mode . In the future, more modes + * may be added. Note that for now if you have more than one channels to + * decode, you need one state per channel. + * + * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode) + * @return A newly created decoder state or NULL if state allocation fails + */ +void *speex_decoder_init(const SpeexMode *mode); + +/** Frees all resources associated to an existing decoder state. + * + * @param state State to be destroyed + */ +void speex_decoder_destroy(void *state); + +/** Uses an existing decoder state to decode one frame of speech from + * bit-stream bits. The output speech is saved written to out. + * + * @param state Decoder state + * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) + * @param out Where to write the decoded frame + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) + */ +int speex_decode(void *state, SpeexBits *bits, float *out); + +/** Uses an existing decoder state to decode one frame of speech from + * bit-stream bits. The output speech is saved written to out. + * + * @param state Decoder state + * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) + * @param out Where to write the decoded frame + * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) + */ +int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out); + +/** Used like the ioctl function to control the encoder parameters + * + * @param state Decoder state + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_decoder_ctl(void *state, int request, void *ptr); + + +/** Query function for mode information + * + * @param mode Speex mode + * @param request ioctl-type request (one of the SPEEX_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_mode_query(const SpeexMode *mode, int request, void *ptr); + +/** Functions for controlling the behavior of libspeex + * @param request ioctl-type request (one of the SPEEX_LIB_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter + */ +int speex_lib_ctl(int request, void *ptr); + +/** Default narrowband mode */ +extern const SpeexMode speex_nb_mode; + +/** Default wideband mode */ +extern const SpeexMode speex_wb_mode; + +/** Default "ultra-wideband" mode */ +extern const SpeexMode speex_uwb_mode; + +/** List of all modes available */ +extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES]; + +/** Obtain one of the modes available */ +const SpeexMode * speex_lib_get_mode (int mode); + +#ifndef WIN32 +/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */ +#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode)) +#endif + +#ifdef __cplusplus +} +#endif + +/** @}*/ +#endif diff --git a/thirdparty/include/speex/speex_bits.h b/thirdparty/include/speex/speex_bits.h new file mode 100755 index 0000000000000000000000000000000000000000..f98b8268febf778e05a59ca91945dfedf3544b48 --- /dev/null +++ b/thirdparty/include/speex/speex_bits.h @@ -0,0 +1,174 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_bits.h + @brief Handles bit packing/unpacking +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef BITS_H +#define BITS_H +/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations + * This is the structure that holds the bit-stream when encoding or decoding + * with Speex. It allows some manipulations as well. + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Bit-packing data structure representing (part of) a bit-stream. */ +typedef struct SpeexBits { + char *chars; /**< "raw" data */ + int nbBits; /**< Total number of bits stored in the stream*/ + int charPtr; /**< Position of the byte "cursor" */ + int bitPtr; /**< Position of the bit "cursor" within the current char */ + int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */ + int overflow;/**< Set to one if we try to read past the valid data */ + int buf_size;/**< Allocated size for buffer */ + int reserved1; /**< Reserved for future use */ + void *reserved2; /**< Reserved for future use */ +} SpeexBits; + +/** Initializes and allocates resources for a SpeexBits struct */ +void speex_bits_init(SpeexBits *bits); + +/** Initializes SpeexBits struct using a pre-allocated buffer*/ +void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size); + +/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */ +void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size); + +/** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/ +void speex_bits_destroy(SpeexBits *bits); + +/** Resets bits to initial value (just after initialization, erasing content)*/ +void speex_bits_reset(SpeexBits *bits); + +/** Rewind the bit-stream to the beginning (ready for read) without erasing the content */ +void speex_bits_rewind(SpeexBits *bits); + +/** Initializes the bit-stream from the data in an area of memory */ +void speex_bits_read_from(SpeexBits *bits, const char *bytes, int len); + +/** Append bytes to the bit-stream + * + * @param bits Bit-stream to operate on + * @param bytes pointer to the bytes what will be appended + * @param len Number of bytes of append + */ +void speex_bits_read_whole_bytes(SpeexBits *bits, const char *bytes, int len); + +/** Write the content of a bit-stream to an area of memory + * + * @param bits Bit-stream to operate on + * @param bytes Memory location where to write the bits + * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer) + * @return Number of bytes written to the "bytes" buffer +*/ +int speex_bits_write(SpeexBits *bits, char *bytes, int max_len); + +/** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */ +int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len); + +/** Append bits to the bit-stream + * @param bits Bit-stream to operate on + * @param data Value to append as integer + * @param nbBits number of bits to consider in "data" + */ +void speex_bits_pack(SpeexBits *bits, int data, int nbBits); + +/** Interpret the next bits in the bit-stream as a signed integer + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to interpret + * @return A signed integer represented by the bits read + */ +int speex_bits_unpack_signed(SpeexBits *bits, int nbBits); + +/** Interpret the next bits in the bit-stream as an unsigned integer + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to interpret + * @return An unsigned integer represented by the bits read + */ +unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits); + +/** Returns the number of bytes in the bit-stream, including the last one even if it is not "full" + * + * @param bits Bit-stream to operate on + * @return Number of bytes in the stream + */ +int speex_bits_nbytes(SpeexBits *bits); + +/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position + * + * @param bits Bit-stream to operate on + * @param nbBits Number of bits to look for + * @return Value of the bits peeked, interpreted as unsigned + */ +unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits); + +/** Get the value of the next bit in the stream, without modifying the + * "cursor" position + * + * @param bits Bit-stream to operate on + * @return Value of the bit peeked (one bit only) + */ +int speex_bits_peek(SpeexBits *bits); + +/** Advances the position of the "bit cursor" in the stream + * + * @param bits Bit-stream to operate on + * @param n Number of bits to advance + */ +void speex_bits_advance(SpeexBits *bits, int n); + +/** Returns the number of bits remaining to be read in a stream + * + * @param bits Bit-stream to operate on + * @return Number of bits that can still be read from the stream + */ +int speex_bits_remaining(SpeexBits *bits); + +/** Insert a terminator so that the data can be sent as a packet while auto-detecting + * the number of frames in each packet + * + * @param bits Bit-stream to operate on + */ +void speex_bits_insert_terminator(SpeexBits *bits); + +#ifdef __cplusplus +} +#endif + +/* @} */ +#endif diff --git a/thirdparty/include/speex/speex_callbacks.h b/thirdparty/include/speex/speex_callbacks.h new file mode 100755 index 0000000000000000000000000000000000000000..3928c34fae5f4f21dfec8cf30f25e5cdbb37bcd1 --- /dev/null +++ b/thirdparty/include/speex/speex_callbacks.h @@ -0,0 +1,134 @@ +/* Copyright (C) 2002 Jean-Marc Valin*/ +/** + @file speex_callbacks.h + @brief Describes callback handling and in-band signalling +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_CALLBACKS_H +#define SPEEX_CALLBACKS_H +/** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder. + * @{ + */ + +#include "speex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Total number of callbacks */ +#define SPEEX_MAX_CALLBACKS 16 + +/* Describes all the in-band requests */ + +/*These are 1-bit requests*/ +/** Request for perceptual enhancement (1 for on, 0 for off) */ +#define SPEEX_INBAND_ENH_REQUEST 0 +/** Reserved */ +#define SPEEX_INBAND_RESERVED1 1 + +/*These are 4-bit requests*/ +/** Request for a mode change */ +#define SPEEX_INBAND_MODE_REQUEST 2 +/** Request for a low mode change */ +#define SPEEX_INBAND_LOW_MODE_REQUEST 3 +/** Request for a high mode change */ +#define SPEEX_INBAND_HIGH_MODE_REQUEST 4 +/** Request for VBR (1 on, 0 off) */ +#define SPEEX_INBAND_VBR_QUALITY_REQUEST 5 +/** Request to be sent acknowledge */ +#define SPEEX_INBAND_ACKNOWLEDGE_REQUEST 6 +/** Request for VBR (1 for on, 0 for off) */ +#define SPEEX_INBAND_VBR_REQUEST 7 + +/*These are 8-bit requests*/ +/** Send a character in-band */ +#define SPEEX_INBAND_CHAR 8 +/** Intensity stereo information */ +#define SPEEX_INBAND_STEREO 9 + +/*These are 16-bit requests*/ +/** Transmit max bit-rate allowed */ +#define SPEEX_INBAND_MAX_BITRATE 10 + +/*These are 32-bit requests*/ +/** Acknowledge packet reception */ +#define SPEEX_INBAND_ACKNOWLEDGE 12 + +/** Callback function type */ +typedef int (*speex_callback_func)(SpeexBits *bits, void *state, void *data); + +/** Callback information */ +typedef struct SpeexCallback { + int callback_id; /**< ID associated to the callback */ + speex_callback_func func; /**< Callback handler function */ + void *data; /**< Data that will be sent to the handler */ + void *reserved1; /**< Reserved for future use */ + int reserved2; /**< Reserved for future use */ +} SpeexCallback; + +/** Handle in-band request */ +int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state); + +/** Standard handler for mode request (change mode, no questions asked) */ +int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for high mode request (change high mode, no questions asked) */ +int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for in-band characters (write to stderr) */ +int speex_std_char_handler(SpeexBits *bits, void *state, void *data); + +/** Default handler for user-defined requests: in this case, just ignore */ +int speex_default_user_handler(SpeexBits *bits, void *state, void *data); + + + +/** Standard handler for low mode request (change low mode, no questions asked) */ +int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for VBR request (Set VBR, no questions asked) */ +int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */ +int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data); + +/** Standard handler for VBR quality request (Set VBR quality, no questions asked) */ +int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data); + + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/thirdparty/include/speex/speex_config_types.h b/thirdparty/include/speex/speex_config_types.h new file mode 100755 index 0000000000000000000000000000000000000000..ca1f5a3c20eca99b2f96def9ad18f7c93c63b326 --- /dev/null +++ b/thirdparty/include/speex/speex_config_types.h @@ -0,0 +1,12 @@ +#ifndef __SPEEX_TYPES_H__ +#define __SPEEX_TYPES_H__ + +#include + +typedef int16_t spx_int16_t; +typedef uint16_t spx_uint16_t; +typedef int32_t spx_int32_t; +typedef uint32_t spx_uint32_t; + +#endif + diff --git a/thirdparty/include/speex/speex_echo.h b/thirdparty/include/speex/speex_echo.h new file mode 100755 index 0000000000000000000000000000000000000000..4c1aa5a5f2a43e5aa0eee7148b7bff21cb79d14c --- /dev/null +++ b/thirdparty/include/speex/speex_echo.h @@ -0,0 +1,170 @@ +/* Copyright (C) Jean-Marc Valin */ +/** + @file speex_echo.h + @brief Echo cancellation +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SPEEX_ECHO_H +#define SPEEX_ECHO_H +/** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller + * This is the acoustic echo canceller module. + * @{ + */ +#include "speexdsp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Obtain frame size used by the AEC */ +#define SPEEX_ECHO_GET_FRAME_SIZE 3 + +/** Set sampling rate */ +#define SPEEX_ECHO_SET_SAMPLING_RATE 24 +/** Get sampling rate */ +#define SPEEX_ECHO_GET_SAMPLING_RATE 25 + +/* Can't set window sizes */ +/** Get size of impulse response (int32) */ +#define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27 + +/* Can't set window content */ +/** Get impulse response (int32[]) */ +#define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29 + +/** Internal echo canceller state. Should never be accessed directly. */ +struct SpeexEchoState_; + +/** @class SpeexEchoState + * This holds the state of the echo canceller. You need one per channel. +*/ + +/** Internal echo canceller state. Should never be accessed directly. */ +typedef struct SpeexEchoState_ SpeexEchoState; + +/** Creates a new echo canceller state + * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) + * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) + * @return Newly-created echo canceller state + */ +SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); + +/** Creates a new multi-channel echo canceller state + * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) + * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) + * @param nb_mic Number of microphone channels + * @param nb_speakers Number of speaker channels + * @return Newly-created echo canceller state + */ +SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers); + +/** Destroys an echo canceller state + * @param st Echo canceller state +*/ +void speex_echo_state_destroy(SpeexEchoState *st); + +/** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added + * to playback in this form) + * + * @param st Echo canceller state + * @param rec Signal from the microphone (near end + far end echo) + * @param play Signal played to the speaker (received from far end) + * @param out Returns near-end signal with echo removed + */ +void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); + +/** Performs echo cancellation a frame (deprecated) */ +void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout); + +/** Perform echo cancellation using internal playback buffer, which is delayed by two frames + * to account for the delay introduced by most soundcards (but it could be off!) + * @param st Echo canceller state + * @param rec Signal from the microphone (near end + far end echo) + * @param out Returns near-end signal with echo removed +*/ +void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); + +/** Let the echo canceller know that a frame was just queued to the soundcard + * @param st Echo canceller state + * @param play Signal played to the speaker (received from far end) +*/ +void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play); + +/** Reset the echo canceller to its original state + * @param st Echo canceller state + */ +void speex_echo_state_reset(SpeexEchoState *st); + +/** Used like the ioctl function to control the echo canceller parameters + * + * @param st Echo canceller state + * @param request ioctl-type request (one of the SPEEX_ECHO_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown + */ +int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr); + + + +struct SpeexDecorrState_; + +typedef struct SpeexDecorrState_ SpeexDecorrState; + + +/** Create a state for the channel decorrelation algorithm + This is useful for multi-channel echo cancellation only + * @param rate Sampling rate + * @param channels Number of channels (it's a bit pointless if you don't have at least 2) + * @param frame_size Size of the frame to process at ones (counting samples *per* channel) +*/ +SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size); + +/** Remove correlation between the channels by modifying the phase and possibly + adding noise in a way that is not (or little) perceptible. + * @param st Decorrelator state + * @param in Input audio in interleaved format + * @param out Result of the decorrelation (out *may* alias in) + * @param strength How much alteration of the audio to apply from 0 to 100. +*/ +void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength); + +/** Destroy a Decorrelation state + * @param st State to destroy +*/ +void speex_decorrelate_destroy(SpeexDecorrState *st); + + +#ifdef __cplusplus +} +#endif + + +/** @}*/ +#endif diff --git a/thirdparty/include/speex/speex_header.h b/thirdparty/include/speex/speex_header.h new file mode 100755 index 0000000000000000000000000000000000000000..ffe8c4713767b43ee87d4460154930a25f35a885 --- /dev/null +++ b/thirdparty/include/speex/speex_header.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_header.h + @brief Describes the Speex header +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#ifndef SPEEX_HEADER_H +#define SPEEX_HEADER_H +/** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header + * This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP. + * @{ + */ + +#include "speex_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct SpeexMode; + +/** Length of the Speex header identifier */ +#define SPEEX_HEADER_STRING_LENGTH 8 + +/** Maximum number of characters for encoding the Speex version number in the header */ +#define SPEEX_HEADER_VERSION_LENGTH 20 + +/** Speex header info for file-based formats */ +typedef struct SpeexHeader { + char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */ + char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */ + spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */ + spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + spx_int32_t rate; /**< Sampling rate used */ + spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */ + spx_int32_t nb_channels; /**< Number of channels encoded */ + spx_int32_t bitrate; /**< Bit-rate used */ + spx_int32_t frame_size; /**< Size of frames */ + spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */ + spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */ + spx_int32_t extra_headers; /**< Number of additional headers after the comments */ + spx_int32_t reserved1; /**< Reserved for future use, must be zero */ + spx_int32_t reserved2; /**< Reserved for future use, must be zero */ +} SpeexHeader; + +/** Initializes a SpeexHeader using basic information */ +void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m); + +/** Creates the header packet from the header itself (mostly involves endianness conversion) */ +char *speex_header_to_packet(SpeexHeader *header, int *size); + +/** Creates a SpeexHeader from a packet */ +SpeexHeader *speex_packet_to_header(char *packet, int size); + +/** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */ +void speex_header_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/thirdparty/include/speex/speex_jitter.h b/thirdparty/include/speex/speex_jitter.h new file mode 100755 index 0000000000000000000000000000000000000000..8fc8d7ec66bee31fcfd0bc30e6d9fd6c80213a41 --- /dev/null +++ b/thirdparty/include/speex/speex_jitter.h @@ -0,0 +1,197 @@ +/* Copyright (C) 2002 Jean-Marc Valin */ +/** + @file speex_jitter.h + @brief Adaptive jitter buffer for Speex +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SPEEX_JITTER_H +#define SPEEX_JITTER_H +/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer + * This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size + * to maintain good quality and low latency. + * @{ + */ + +#include "speexdsp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic adaptive jitter buffer state */ +struct JitterBuffer_; + +/** Generic adaptive jitter buffer state */ +typedef struct JitterBuffer_ JitterBuffer; + +/** Definition of an incoming packet */ +typedef struct _JitterBufferPacket JitterBufferPacket; + +/** Definition of an incoming packet */ +struct _JitterBufferPacket { + char *data; /**< Data bytes contained in the packet */ + spx_uint32_t len; /**< Length of the packet in bytes */ + spx_uint32_t timestamp; /**< Timestamp for the packet */ + spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ + spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */ + spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */ +}; + +/** Packet has been retrieved */ +#define JITTER_BUFFER_OK 0 +/** Packet is lost or is late */ +#define JITTER_BUFFER_MISSING 1 +/** A "fake" packet is meant to be inserted here to increase buffering */ +#define JITTER_BUFFER_INSERTION 2 +/** There was an error in the jitter buffer */ +#define JITTER_BUFFER_INTERNAL_ERROR -1 +/** Invalid argument */ +#define JITTER_BUFFER_BAD_ARGUMENT -2 + + +/** Set minimum amount of extra buffering required (margin) */ +#define JITTER_BUFFER_SET_MARGIN 0 +/** Get minimum amount of extra buffering required (margin) */ +#define JITTER_BUFFER_GET_MARGIN 1 +/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ + +/** Get the amount of available packets currently buffered */ +#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 +/** Included because of an early misspelling (will remove in next release) */ +#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 + +/** Assign a function to destroy unused packet. When setting that, the jitter + buffer no longer copies packet data. */ +#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4 +/** */ +#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5 + +/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */ +#define JITTER_BUFFER_SET_DELAY_STEP 6 +/** */ +#define JITTER_BUFFER_GET_DELAY_STEP 7 + +/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */ +#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8 +#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9 + +/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss + should be half of that or less. */ +#define JITTER_BUFFER_SET_MAX_LATE_RATE 10 +#define JITTER_BUFFER_GET_MAX_LATE_RATE 11 + +/** Equivalent cost of one percent late packet in timestamp units */ +#define JITTER_BUFFER_SET_LATE_COST 12 +#define JITTER_BUFFER_GET_LATE_COST 13 + + +/** Initialises jitter buffer + * + * @param step_size Starting value for the size of concleanment packets and delay + adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP + and JITTER_BUFFER_GET_CONCEALMENT_SIZE. + * @return Newly created jitter buffer state + */ +JitterBuffer *jitter_buffer_init(int step_size); + +/** Restores jitter buffer to its original state + * + * @param jitter Jitter buffer state + */ +void jitter_buffer_reset(JitterBuffer *jitter); + +/** Destroys jitter buffer + * + * @param jitter Jitter buffer state + */ +void jitter_buffer_destroy(JitterBuffer *jitter); + +/** Put one packet into the jitter buffer + * + * @param jitter Jitter buffer state + * @param packet Incoming packet +*/ +void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet); + +/** Get one packet from the jitter buffer + * + * @param jitter Jitter buffer state + * @param packet Returned packet + * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee) + * @param current_timestamp Timestamp for the returned packet +*/ +int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset); + +/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp. + * This is mainly useful for media where a single "frame" can be split into several packets. + * + * @param jitter Jitter buffer state + * @param packet Returned packet + */ +int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet); + +/** Get pointer timestamp of jitter buffer + * + * @param jitter Jitter buffer state +*/ +int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter); + +/** Advance by one tick + * + * @param jitter Jitter buffer state +*/ +void jitter_buffer_tick(JitterBuffer *jitter); + +/** Telling the jitter buffer about the remaining data in the application buffer + * @param jitter Jitter buffer state + * @param rem Amount of data buffered by the application (timestamp units) + */ +void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem); + +/** Used like the ioctl function to control the jitter buffer parameters + * + * @param jitter Jitter buffer state + * @param request ioctl-type request (one of the JITTER_BUFFER_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown +*/ +int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr); + +int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/speex/speex_preprocess.h b/thirdparty/include/speex/speex_preprocess.h new file mode 100755 index 0000000000000000000000000000000000000000..a2e1210d41220c1d9fd1d752368a006f8f82c7c1 --- /dev/null +++ b/thirdparty/include/speex/speex_preprocess.h @@ -0,0 +1,219 @@ +/* Copyright (C) 2003 Epic Games + Written by Jean-Marc Valin */ +/** + * @file speex_preprocess.h + * @brief Speex preprocessor. The preprocess can do noise suppression, + * residual echo suppression (after using the echo canceller), automatic + * gain control (AGC) and voice activity detection (VAD). +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SPEEX_PREPROCESS_H +#define SPEEX_PREPROCESS_H +/** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor + * This is the Speex preprocessor. The preprocess can do noise suppression, + * residual echo suppression (after using the echo canceller), automatic + * gain control (AGC) and voice activity detection (VAD). + * @{ + */ + +#include "speexdsp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** State of the preprocessor (one per channel). Should never be accessed directly. */ +struct SpeexPreprocessState_; + +/** State of the preprocessor (one per channel). Should never be accessed directly. */ +typedef struct SpeexPreprocessState_ SpeexPreprocessState; + + +/** Creates a new preprocessing state. You MUST create one state per channel processed. + * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be + * the same value as that used for the echo canceller for residual echo cancellation to work. + * @param sampling_rate Sampling rate used for the input. + * @return Newly created preprocessor state +*/ +SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate); + +/** Destroys a preprocessor state + * @param st Preprocessor state to destroy +*/ +void speex_preprocess_state_destroy(SpeexPreprocessState *st); + +/** Preprocess a frame + * @param st Preprocessor state + * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init(). + * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on. +*/ +int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x); + +/** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/ +int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo); + +/** Update preprocessor state, but do not compute the output + * @param st Preprocessor state + * @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init(). +*/ +void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x); + +/** Used like the ioctl function to control the preprocessor parameters + * @param st Preprocessor state + * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros) + * @param ptr Data exchanged to-from function + * @return 0 if no error, -1 if request in unknown +*/ +int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr); + + + +/** Set preprocessor denoiser state */ +#define SPEEX_PREPROCESS_SET_DENOISE 0 +/** Get preprocessor denoiser state */ +#define SPEEX_PREPROCESS_GET_DENOISE 1 + +/** Set preprocessor Automatic Gain Control state */ +#define SPEEX_PREPROCESS_SET_AGC 2 +/** Get preprocessor Automatic Gain Control state */ +#define SPEEX_PREPROCESS_GET_AGC 3 + +/** Set preprocessor Voice Activity Detection state */ +#define SPEEX_PREPROCESS_SET_VAD 4 +/** Get preprocessor Voice Activity Detection state */ +#define SPEEX_PREPROCESS_GET_VAD 5 + +/** Set preprocessor Automatic Gain Control level (float) */ +#define SPEEX_PREPROCESS_SET_AGC_LEVEL 6 +/** Get preprocessor Automatic Gain Control level (float) */ +#define SPEEX_PREPROCESS_GET_AGC_LEVEL 7 + +/** Set preprocessor dereverb state */ +#define SPEEX_PREPROCESS_SET_DEREVERB 8 +/** Get preprocessor dereverb state */ +#define SPEEX_PREPROCESS_GET_DEREVERB 9 + +/** Set preprocessor dereverb level */ +#define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10 +/** Get preprocessor dereverb level */ +#define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11 + +/** Set preprocessor dereverb decay */ +#define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12 +/** Get preprocessor dereverb decay */ +#define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13 + +/** Set probability required for the VAD to go from silence to voice */ +#define SPEEX_PREPROCESS_SET_PROB_START 14 +/** Get probability required for the VAD to go from silence to voice */ +#define SPEEX_PREPROCESS_GET_PROB_START 15 + +/** Set probability required for the VAD to stay in the voice state (integer percent) */ +#define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16 +/** Get probability required for the VAD to stay in the voice state (integer percent) */ +#define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17 + +/** Set maximum attenuation of the noise in dB (negative number) */ +#define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18 +/** Get maximum attenuation of the noise in dB (negative number) */ +#define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19 + +/** Set maximum attenuation of the residual echo in dB (negative number) */ +#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20 +/** Get maximum attenuation of the residual echo in dB (negative number) */ +#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21 + +/** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */ +#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22 +/** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */ +#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23 + +/** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */ +#define SPEEX_PREPROCESS_SET_ECHO_STATE 24 +/** Get the corresponding echo canceller state */ +#define SPEEX_PREPROCESS_GET_ECHO_STATE 25 + +/** Set maximal gain increase in dB/second (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26 + +/** Get maximal gain increase in dB/second (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27 + +/** Set maximal gain decrease in dB/second (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28 + +/** Get maximal gain decrease in dB/second (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29 + +/** Set maximal gain in dB (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30 + +/** Get maximal gain in dB (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 + +/* Can't set loudness */ +/** Get loudness */ +#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33 + +/* Can't set gain */ +/** Get current gain (int32 percent) */ +#define SPEEX_PREPROCESS_GET_AGC_GAIN 35 + +/* Can't set spectrum size */ +/** Get spectrum size for power spectrum (int32) */ +#define SPEEX_PREPROCESS_GET_PSD_SIZE 37 + +/* Can't set power spectrum */ +/** Get power spectrum (int32[] of squared values) */ +#define SPEEX_PREPROCESS_GET_PSD 39 + +/* Can't set noise size */ +/** Get spectrum size for noise estimate (int32) */ +#define SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE 41 + +/* Can't set noise estimate */ +/** Get noise estimate (int32[] of squared values) */ +#define SPEEX_PREPROCESS_GET_NOISE_PSD 43 + +/* Can't set speech probability */ +/** Get speech probability in last frame (int32). */ +#define SPEEX_PREPROCESS_GET_PROB 45 + +/** Set preprocessor Automatic Gain Control level (int32) */ +#define SPEEX_PREPROCESS_SET_AGC_TARGET 46 +/** Get preprocessor Automatic Gain Control level (int32) */ +#define SPEEX_PREPROCESS_GET_AGC_TARGET 47 + +#ifdef __cplusplus +} +#endif + +/** @}*/ +#endif diff --git a/thirdparty/include/speex/speex_resampler.h b/thirdparty/include/speex/speex_resampler.h new file mode 100755 index 0000000000000000000000000000000000000000..901de37b3dabb38f114e04859bfc2103bfba8189 --- /dev/null +++ b/thirdparty/include/speex/speex_resampler.h @@ -0,0 +1,343 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: speex_resampler.h + Resampling code + + The design goals of this code are: + - Very fast algorithm + - Low memory requirement + - Good *perceptual* quality (and not best SNR) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef SPEEX_RESAMPLER_H +#define SPEEX_RESAMPLER_H + +#ifdef OUTSIDE_SPEEX + +/********* WARNING: MENTAL SANITY ENDS HERE *************/ + +/* If the resampler is defined outside of Speex, we change the symbol names so that + there won't be any clash if linking with Speex later on. */ + +/* #define RANDOM_PREFIX your software name here */ +#ifndef RANDOM_PREFIX +#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" +#endif + +#define CAT_PREFIX2(a,b) a ## b +#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) + +#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) +#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) +#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) +#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) +#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) +#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) +#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) +#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) +#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) +#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) +#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) +#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) +#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) +#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) +#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) +#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) +#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) +#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency) +#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency) +#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) +#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) +#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) + +#define spx_int16_t short +#define spx_int32_t int +#define spx_uint16_t unsigned short +#define spx_uint32_t unsigned int + +#define speex_assert(cond) + +#else /* OUTSIDE_SPEEX */ + +#include "speexdsp_types.h" + +#endif /* OUTSIDE_SPEEX */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPEEX_RESAMPLER_QUALITY_MAX 10 +#define SPEEX_RESAMPLER_QUALITY_MIN 0 +#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 +#define SPEEX_RESAMPLER_QUALITY_VOIP 3 +#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + RESAMPLER_ERR_OVERFLOW = 5, + + RESAMPLER_ERR_MAX_ERROR +}; + +struct SpeexResamplerState_; +typedef struct SpeexResamplerState_ SpeexResamplerState; + +/** Create a new resampler with integer input and output rates. + * @param nb_channels Number of channels to be processed + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Create a new resampler with fractional input/output rates. The sampling + * rate ratio is an arbitrary rational number with both the numerator and + * denominator being 32-bit integers. + * @param nb_channels Number of channels to be processed + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Destroy a resampler state. + * @param st Resampler state + */ +void speex_resampler_destroy(SpeexResamplerState *st); + +/** Resample a float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the + * number of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_int(SpeexResamplerState *st, + spx_uint32_t channel_index, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Resample an interleaved float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an interleaved int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Set (change) the input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + */ +int speex_resampler_set_rate(SpeexResamplerState *st, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz) copied. + * @param out_rate Output sampling rate (integer number of Hz) copied. + */ +void speex_resampler_get_rate(SpeexResamplerState *st, + spx_uint32_t *in_rate, + spx_uint32_t *out_rate); + +/** Set (change) the input/output sampling rates and resampling ratio + * (fractional values in Hz supported). + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + */ +int speex_resampler_set_rate_frac(SpeexResamplerState *st, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current resampling ratio. This will be reduced to the least + * common denominator. + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio copied + * @param ratio_den Denominator of the sampling rate ratio copied + */ +void speex_resampler_get_ratio(SpeexResamplerState *st, + spx_uint32_t *ratio_num, + spx_uint32_t *ratio_den); + +/** Set (change) the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +int speex_resampler_set_quality(SpeexResamplerState *st, + int quality); + +/** Get the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +void speex_resampler_get_quality(SpeexResamplerState *st, + int *quality); + +/** Set (change) the input stride. + * @param st Resampler state + * @param stride Input stride + */ +void speex_resampler_set_input_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the input stride. + * @param st Resampler state + * @param stride Input stride copied + */ +void speex_resampler_get_input_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Set (change) the output stride. + * @param st Resampler state + * @param stride Output stride + */ +void speex_resampler_set_output_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the output stride. + * @param st Resampler state copied + * @param stride Output stride + */ +void speex_resampler_get_output_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Get the latency introduced by the resampler measured in input samples. + * @param st Resampler state + */ +int speex_resampler_get_input_latency(SpeexResamplerState *st); + +/** Get the latency introduced by the resampler measured in output samples. + * @param st Resampler state + */ +int speex_resampler_get_output_latency(SpeexResamplerState *st); + +/** Make sure that the first samples to go out of the resamplers don't have + * leading zeros. This is only useful before starting to use a newly created + * resampler. It is recommended to use that when resampling an audio file, as + * it will generate a file with the same length. For real-time processing, + * it is probably easier not to use this call (so that the output duration + * is the same for the first frame). + * @param st Resampler state + */ +int speex_resampler_skip_zeros(SpeexResamplerState *st); + +/** Reset a resampler so a new (unrelated) stream can be processed. + * @param st Resampler state + */ +int speex_resampler_reset_mem(SpeexResamplerState *st); + +/** Returns the English meaning for an error code + * @param err Error code + * @return English string + */ +const char *speex_resampler_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/speex/speex_stereo.h b/thirdparty/include/speex/speex_stereo.h new file mode 100755 index 0000000000000000000000000000000000000000..5844f5a102460e40de792e4a40354ee4f0d02978 --- /dev/null +++ b/thirdparty/include/speex/speex_stereo.h @@ -0,0 +1,92 @@ +/* Copyright (C) 2002 Jean-Marc Valin*/ +/** + @file speex_stereo.h + @brief Describes the handling for intensity stereo +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef STEREO_H +#define STEREO_H +/** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files + * This describes the Speex intensity stereo encoding/decoding + * @{ + */ + +#include "speex_types.h" +#include "speex_bits.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** If you access any of these fields directly, I'll personally come and bite you */ +typedef struct SpeexStereoState { + float balance; /**< Left/right balance info */ + float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ + float smooth_left; /**< Smoothed left channel gain */ + float smooth_right; /**< Smoothed right channel gain */ + float reserved1; /**< Reserved for future use */ + float reserved2; /**< Reserved for future use */ +} SpeexStereoState; + +/** Deprecated. Use speex_stereo_state_init() instead. */ +#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} + +/** Initialise/create a stereo stereo state */ +SpeexStereoState *speex_stereo_state_init(); + +/** Reset/re-initialise an already allocated stereo state */ +void speex_stereo_state_reset(SpeexStereoState *stereo); + +/** Destroy a stereo stereo state */ +void speex_stereo_state_destroy(SpeexStereoState *stereo); + +/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ +void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); + +/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ +void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits); + +/** Transforms a mono frame into a stereo frame using intensity stereo info */ +void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo); + +/** Transforms a mono frame into a stereo frame using intensity stereo info */ +void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo); + +/** Callback handler for intensity stereo info */ +int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif diff --git a/thirdparty/include/speex/speex_types.h b/thirdparty/include/speex/speex_types.h new file mode 100755 index 0000000000000000000000000000000000000000..bdc63295c41ca0fbba150574c24c603e28ede75b --- /dev/null +++ b/thirdparty/include/speex/speex_types.h @@ -0,0 +1,126 @@ +/* speex_types.h taken from libogg */ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ + + ********************************************************************/ +/** + @file speex_types.h + @brief Speex types +*/ +#ifndef _SPEEX_TYPES_H +#define _SPEEX_TYPES_H + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t spx_int32_t; + typedef _G_uint32_t spx_uint32_t; + typedef _G_int16_t spx_int16_t; + typedef _G_uint16_t spx_uint16_t; +# elif defined(__MINGW32__) + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; +# elif defined(__MWERKS__) + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; +# else + /* MSVC/Borland */ + typedef __int32 spx_int32_t; + typedef unsigned __int32 spx_uint32_t; + typedef __int16 spx_int16_t; + typedef unsigned __int16 spx_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 spx_int16_t; + typedef UInt16 spx_uint16_t; + typedef SInt32 spx_int32_t; + typedef UInt32 spx_uint32_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short spx_int16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int spx_int32_t; + typedef unsigned spx_uint32_t; + typedef short spx_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef signed int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef long spx_int32_t; + typedef unsigned long spx_uint32_t; + +#elif defined(CONFIG_TI_C6X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#else + +#include "speex_config_types.h" + +#endif + +#endif /* _SPEEX_TYPES_H */ diff --git a/thirdparty/include/speex/speexdsp_config_types.h b/thirdparty/include/speex/speexdsp_config_types.h new file mode 100755 index 0000000000000000000000000000000000000000..ca1f5a3c20eca99b2f96def9ad18f7c93c63b326 --- /dev/null +++ b/thirdparty/include/speex/speexdsp_config_types.h @@ -0,0 +1,12 @@ +#ifndef __SPEEX_TYPES_H__ +#define __SPEEX_TYPES_H__ + +#include + +typedef int16_t spx_int16_t; +typedef uint16_t spx_uint16_t; +typedef int32_t spx_int32_t; +typedef uint32_t spx_uint32_t; + +#endif + diff --git a/thirdparty/include/speex/speexdsp_types.h b/thirdparty/include/speex/speexdsp_types.h new file mode 100755 index 0000000000000000000000000000000000000000..4b4a76a474af7f6fdd2f175815529edf951abe74 --- /dev/null +++ b/thirdparty/include/speex/speexdsp_types.h @@ -0,0 +1,126 @@ +/* speexdsp_types.h taken from libogg */ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ + + ********************************************************************/ +/** + @file speexdsp_types.h + @brief Speex types +*/ +#ifndef _SPEEX_TYPES_H +#define _SPEEX_TYPES_H + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t spx_int32_t; + typedef _G_uint32_t spx_uint32_t; + typedef _G_int16_t spx_int16_t; + typedef _G_uint16_t spx_uint16_t; +# elif defined(__MINGW32__) + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; +# elif defined(__MWERKS__) + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; +# else + /* MSVC/Borland */ + typedef __int32 spx_int32_t; + typedef unsigned __int32 spx_uint32_t; + typedef __int16 spx_int16_t; + typedef unsigned __int16 spx_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 spx_int16_t; + typedef UInt16 spx_uint16_t; + typedef SInt32 spx_int32_t; + typedef UInt32 spx_uint32_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t spx_int16_t; + typedef u_int16_t spx_uint16_t; + typedef int32_t spx_int32_t; + typedef u_int32_t spx_uint32_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short spx_int16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int spx_int32_t; + typedef unsigned spx_uint32_t; + typedef short spx_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef signed int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef long spx_int32_t; + typedef unsigned long spx_uint32_t; + +#elif defined(CONFIG_TI_C6X) + + typedef short spx_int16_t; + typedef unsigned short spx_uint16_t; + typedef int spx_int32_t; + typedef unsigned int spx_uint32_t; + +#else + +#include "speexdsp_config_types.h" + +#endif + +#endif /* _SPEEX_TYPES_H */ diff --git a/thirdparty/include/srt/access_control.h b/thirdparty/include/srt/access_control.h new file mode 100755 index 0000000000000000000000000000000000000000..97a1104a83c87c3deda3ba49fad9a22e0c737a8c --- /dev/null +++ b/thirdparty/include/srt/access_control.h @@ -0,0 +1,79 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2020 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_F_ACCESS_CONTROL_H +#define INC_F_ACCESS_CONTROL_H + +// A list of rejection codes that are SRT specific. + +#define SRT_REJX_FALLBACK 1000 // A code used in case when the application wants to report some problem, but can't precisely specify it. +#define SRT_REJX_KEY_NOTSUP 1001 // The key used in the StreamID keyed string is not supported by the service. +#define SRT_REJX_FILEPATH 1002 // The resource type designates a file and the path is either wrong syntax or not found +#define SRT_REJX_HOSTNOTFOUND 1003 // The `h` host specification was not recognized by the service + +// The list of http codes adopted for SRT. +// An example C++ header for HTTP codes can be found at: +// https://github.com/j-ulrich/http-status-codes-cpp + +// Some of the unused code can be revived in the future, if there +// happens to be a good reason for it. + +#define SRT_REJX_BAD_REQUEST 1400 // General syntax error in the SocketID specification (also a fallback code for undefined cases) +#define SRT_REJX_UNAUTHORIZED 1401 // Authentication failed, provided that the user was correctly identified and access to the required resource would be granted +#define SRT_REJX_OVERLOAD 1402 // The server is too heavily loaded, or you have exceeded credits for accessing the service and the resource. +#define SRT_REJX_FORBIDDEN 1403 // Access denied to the resource by any kind of reason. +#define SRT_REJX_NOTFOUND 1404 // Resource not found at this time. +#define SRT_REJX_BAD_MODE 1405 // The mode specified in `m` key in StreamID is not supported for this request. +#define SRT_REJX_UNACCEPTABLE 1406 // The requested parameters specified in SocketID cannot be satisfied for the requested resource. Also when m=publish and the data format is not acceptable. +// CODE NOT IN USE 407: unused: proxy functionality not predicted +// CODE NOT IN USE 408: unused: no timeout predicted for listener callback +#define SRT_REJX_CONFLICT 1409 // The resource being accessed is already locked for modification. This is in case of m=publish and the specified resource is currently read-only. +// CODE NOT IN USE 410: unused: treated as a specific case of 404 +// CODE NOT IN USE 411: unused: no reason to include lenght in the protocol +// CODE NOT IN USE 412: unused: preconditions not predicted in AC +// CODE NOT IN USE 413: unused: AC size is already defined as 512 +// CODE NOT IN USE 414: unused: AC size is already defined as 512 +#define SRT_REJX_NOTSUP_MEDIA 1415 // The media type is not supported by the application. This is the `t` key that specifies the media type as stream, file and auth, possibly extended by the application. +// CODE NOT IN USE 416: unused: no detailed specification defined +// CODE NOT IN USE 417: unused: expectations not supported +// CODE NOT IN USE 418: unused: sharks do not drink tea +// CODE NOT IN USE 419: not defined in HTTP +// CODE NOT IN USE 420: not defined in HTTP +// CODE NOT IN USE 421: unused: misdirection not supported +// CODE NOT IN USE 422: unused: aligned to general 400 +#define SRT_REJX_LOCKED 1423 // The resource being accessed is locked for any access. +#define SRT_REJX_FAILED_DEPEND 1424 // The request failed because it specified a dependent session ID that has been disconnected. +// CODE NOT IN USE 425: unused: replaying not supported +// CODE NOT IN USE 426: unused: tempting, but it requires resend in connected +// CODE NOT IN USE 427: not defined in HTTP +// CODE NOT IN USE 428: unused: renders to 409 +// CODE NOT IN USE 429: unused: renders to 402 +// CODE NOT IN USE 451: unused: renders to 403 +#define SRT_REJX_ISE 1500 // Unexpected internal server error +#define SRT_REJX_UNIMPLEMENTED 1501 // The request was recognized, but the current version doesn't support it. +#define SRT_REJX_GW 1502 // The server acts as a gateway and the target endpoint rejected the connection. +#define SRT_REJX_DOWN 1503 // The service has been temporarily taken over by a stub reporting this error. The real service can be down for maintenance or crashed. +// CODE NOT IN USE 504: unused: timeout not supported +#define SRT_REJX_VERSION 1505 // SRT version not supported. This might be either unsupported backward compatibility, or an upper value of a version. +// CODE NOT IN USE 506: unused: negotiation and references not supported +#define SRT_REJX_NOROOM 1507 // The data stream cannot be archived due to lacking storage space. This is in case when the request type was to send a file or the live stream to be archived. +// CODE NOT IN USE 508: unused: no redirection supported +// CODE NOT IN USE 509: not defined in HTTP +// CODE NOT IN USE 510: unused: extensions not supported +// CODE NOT IN USE 511: unused: intercepting proxies not supported + + + +#endif diff --git a/thirdparty/include/srt/logging_api.h b/thirdparty/include/srt/logging_api.h new file mode 100755 index 0000000000000000000000000000000000000000..4fc3b812bb0fee548b34fb7db106a8cf8ef002b7 --- /dev/null +++ b/thirdparty/include/srt/logging_api.h @@ -0,0 +1,107 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_LOGGING_API_H +#define INC_SRT_LOGGING_API_H + +// These are required for access functions: +// - adding FA (requires set) +// - setting a log stream (requires iostream) +#ifdef __cplusplus +#include +#include +#endif + +#ifdef _WIN32 +#include "win/syslog_defs.h" +#else +#include +#endif + +// Syslog is included so that it provides log level names. +// Haivision log standard requires the same names plus extra one: +#ifndef LOG_DEBUG_TRACE +#define LOG_DEBUG_TRACE 8 +#endif +// It's unused anyway, just for the record. +#define SRT_LOG_LEVEL_MIN LOG_CRIT +#define SRT_LOG_LEVEL_MAX LOG_DEBUG + +// Flags +#define SRT_LOGF_DISABLE_TIME 1 +#define SRT_LOGF_DISABLE_THREADNAME 2 +#define SRT_LOGF_DISABLE_SEVERITY 4 +#define SRT_LOGF_DISABLE_EOL 8 + +// Handler type. +typedef void SRT_LOG_HANDLER_FN(void* opaque, int level, const char* file, int line, const char* area, const char* message); + +#ifdef __cplusplus +namespace srt_logging +{ + + +struct LogFA +{ +private: + int value; +public: + operator int() const { return value; } + + LogFA(int v): value(v) + { + // Generally this was what it has to be used for. + // Unfortunately it couldn't be agreed with the + //logging_fa_all.insert(v); + } +}; + +const LogFA LOGFA_GENERAL = 0; + + + +namespace LogLevel +{ + // There are 3 general levels: + + // A. fatal - this means the application WILL crash. + // B. unexpected: + // - error: this was unexpected for the library + // - warning: this was expected by the library, but may be harmful for the application + // C. expected: + // - note: a significant, but rarely occurring event + // - debug: may occur even very often and enabling it can harm performance + + enum type + { + fatal = LOG_CRIT, + // Fatal vs. Error: with Error, you can still continue. + error = LOG_ERR, + // Error vs. Warning: Warning isn't considered a problem for the library. + warning = LOG_WARNING, + // Warning vs. Note: Note means something unusual, but completely correct behavior. + note = LOG_NOTICE, + // Note vs. Debug: Debug may occur even multiple times in a millisecond. + // (Well, worth noting that Error and Warning potentially also can). + debug = LOG_DEBUG + }; +} + +class Logger; + +} +#endif + +#endif diff --git a/thirdparty/include/srt/platform_sys.h b/thirdparty/include/srt/platform_sys.h new file mode 100755 index 0000000000000000000000000000000000000000..7bdce267dda179ae70f101b58e80b1298ce02eb4 --- /dev/null +++ b/thirdparty/include/srt/platform_sys.h @@ -0,0 +1,107 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ +#ifndef INC_SRT_PLATFORM_SYS_H +#define INC_SRT_PLATFORM_SYS_H + +// INFORMATION +// +// This file collects all required platform-specific declarations +// required to provide everything that the SRT library needs from system. +// +// There's also semi-modular system implemented using SRT_IMPORT_* macros. +// To require a module to be imported, #define SRT_IMPORT_* where * is +// the module name. Currently handled module macros: +// +// SRT_IMPORT_TIME (mach time on Mac, portability gettimeofday on WIN32) +// SRT_IMPORT_EVENT (includes kevent on Mac) + + +#ifdef _WIN32 + #define _CRT_SECURE_NO_WARNINGS 1 // silences windows complaints for sscanf + #include + #include + #include + #include + +#ifndef __MINGW__ + #include +#endif + + #ifdef SRT_IMPORT_TIME + #include + #endif + + #include + #include + #if defined(_MSC_VER) + #pragma warning(disable:4251) + #endif +#else + +#if __APPLE__ +// XXX Check if this condition doesn't require checking of +// also other macros, like TARGET_OS_IOS etc. + +#include "TargetConditionals.h" +#define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ + + +#ifdef SRT_IMPORT_TIME + #include +#endif + +#ifdef SRT_IMPORT_EVENT + #include + #include + #include + #include +#endif + +#endif + +#ifdef LINUX + +#ifdef SRT_IMPORT_EVENT + #include + #include +#endif + +#endif + +#if defined(__ANDROID__) || defined(ANDROID) + +#ifdef SRT_IMPORT_EVENT + #include +#endif + +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +// Headers for errno, string and stdlib are +// included indirectly correct C++ way. +#else +#include +#include +#include +#endif + +#endif + +#endif diff --git a/thirdparty/include/srt/srt.h b/thirdparty/include/srt/srt.h new file mode 100755 index 0000000000000000000000000000000000000000..f3a5becdcced890d2f62ee12007253f89baafbf9 --- /dev/null +++ b/thirdparty/include/srt/srt.h @@ -0,0 +1,995 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRTC_H +#define INC_SRTC_H + +#include "version.h" + +#include "platform_sys.h" + +#include +#include + +#include "logging_api.h" + +//////////////////////////////////////////////////////////////////////////////// + +//if compiling on VC6.0 or pre-WindowsXP systems +//use -DLEGACY_WIN32 + +//if compiling with MinGW, it only works on XP or above +//use -D_WIN32_WINNT=0x0501 + + +#ifdef _WIN32 + #ifndef __MINGW__ + // Explicitly define 32-bit and 64-bit numbers + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + #ifndef LEGACY_WIN32 + typedef unsigned __int64 uint64_t; + #else + // VC 6.0 does not support unsigned __int64: may cause potential problems. + typedef __int64 uint64_t; + #endif + + #ifdef SRT_DYNAMIC + #ifdef SRT_EXPORTS + #define SRT_API __declspec(dllexport) + #else + #define SRT_API __declspec(dllimport) + #endif + #else + #define SRT_API + #endif + #else // __MINGW__ + #define SRT_API + #endif +#else + #define SRT_API __attribute__ ((visibility("default"))) +#endif + + +// For feature tests if you need. +// You can use these constants with SRTO_MINVERSION option. +#define SRT_VERSION_FEAT_HSv5 0x010300 + +#if defined(__cplusplus) && __cplusplus > 201406 +#define SRT_HAVE_CXX17 1 +#else +#define SRT_HAVE_CXX17 0 +#endif + + +// Stadnard attributes + +// When compiling in C++17 mode, use the standard C++17 attributes +// (out of these, only [[deprecated]] is supported in C++14, so +// for all lesser standard use compiler-specific attributes). +#if SRT_HAVE_CXX17 + +// Unused: DO NOT issue a warning if this entity is unused. +#define SRT_ATR_UNUSED [[maybe_unused]] + +// Nodiscard: issue a warning if the return value was discarded. +#define SRT_ATR_NODISCARD [[nodiscard]] + +// GNUG is GNU C/C++; this syntax is also supported by Clang +#elif defined(__GNUC__) +#define SRT_ATR_UNUSED __attribute__((unused)) +#define SRT_ATR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define SRT_ATR_UNUSED __pragma(warning(suppress: 4100 4101)) +#define SRT_ATR_NODISCARD _Check_return_ +#else +#define SRT_ATR_UNUSED +#define SRT_ATR_NODISCARD +#endif + + +// DEPRECATED attributes + +// There's needed DEPRECATED and DEPRECATED_PX, as some compilers require them +// before the entity, others after the entity. +// The *_PX version is the prefix attribute, which applies only +// to functions (Microsoft compilers). + +// When deprecating a function, mark it: +// +// SRT_ATR_DEPRECATED_PX retval function(arguments) SRT_ATR_DEPRECATED; +// + +// When SRT_NO_DEPRECATED defined, do not issue any deprecation warnings. +// Regardless of the compiler type. +#if defined(SRT_NO_DEPRECATED) + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX + +#elif SRT_HAVE_CXX17 + +#define SRT_ATR_DEPRECATED +#define SRT_ATR_DEPRECATED_PX [[deprecated]] + +// GNUG is GNU C/C++; this syntax is also supported by Clang +#elif defined(__GNUC__) +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SRT_ATR_DEPRECATED_PX __declspec(deprecated) +#define SRT_ATR_DEPRECATED // no postfix-type modifier +#else +#define SRT_ATR_DEPRECATED_PX +#define SRT_ATR_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int32_t SRTSOCKET; + +// The most significant bit 31 (sign bit actually) is left unused, +// so that all people who check the value for < 0 instead of -1 +// still get what they want. The bit 30 is reserved for marking +// the "socket group". Most of the API functions should work +// transparently with the socket descriptor designating a single +// socket or a socket group. +static const int32_t SRTGROUP_MASK = (1 << 30); + +#ifdef _WIN32 + #ifndef __MINGW__ + typedef SOCKET SYSSOCKET; + #else + typedef int SYSSOCKET; + #endif +#else + typedef int SYSSOCKET; +#endif + +typedef SYSSOCKET UDPSOCKET; + + +// Values returned by srt_getsockstate() +typedef enum SRT_SOCKSTATUS { + SRTS_INIT = 1, + SRTS_OPENED, + SRTS_LISTENING, + SRTS_CONNECTING, + SRTS_CONNECTED, + SRTS_BROKEN, + SRTS_CLOSING, + SRTS_CLOSED, + SRTS_NONEXIST +} SRT_SOCKSTATUS; + +// This is a duplicate enum. Must be kept in sync with the original UDT enum for +// backward compatibility until all compat is destroyed. +typedef enum SRT_SOCKOPT { + + SRTO_MSS = 0, // the Maximum Transfer Unit + SRTO_SNDSYN = 1, // if sending is blocking + SRTO_RCVSYN = 2, // if receiving is blocking + SRTO_ISN = 3, // Initial Sequence Number (valid only after srt_connect or srt_accept-ed sockets) + SRTO_FC = 4, // Flight flag size (window size) + SRTO_SNDBUF = 5, // maximum buffer in sending queue + SRTO_RCVBUF = 6, // UDT receiving buffer size + SRTO_LINGER = 7, // waiting for unsent data when closing + SRTO_UDP_SNDBUF = 8, // UDP sending buffer size + SRTO_UDP_RCVBUF = 9, // UDP receiving buffer size + // (some space left) + SRTO_RENDEZVOUS = 12, // rendezvous connection mode + SRTO_SNDTIMEO = 13, // send() timeout + SRTO_RCVTIMEO = 14, // recv() timeout + SRTO_REUSEADDR = 15, // reuse an existing port or create a new one + SRTO_MAXBW = 16, // maximum bandwidth (bytes per second) that the connection can use + SRTO_STATE = 17, // current socket state, see UDTSTATUS, read only + SRTO_EVENT = 18, // current available events associated with the socket + SRTO_SNDDATA = 19, // size of data in the sending buffer + SRTO_RCVDATA = 20, // size of data available for recv + SRTO_SENDER = 21, // Sender mode (independent of conn mode), for encryption, tsbpd handshake. + SRTO_TSBPDMODE = 22, // Enable/Disable TsbPd. Enable -> Tx set origin timestamp, Rx deliver packet at origin time + delay + SRTO_LATENCY = 23, // NOT RECOMMENDED. SET: to both SRTO_RCVLATENCY and SRTO_PEERLATENCY. GET: same as SRTO_RCVLATENCY. + SRTO_INPUTBW = 24, // Estimated input stream rate. + SRTO_OHEADBW, // MaxBW ceiling based on % over input stream rate. Applies when UDT_MAXBW=0 (auto). + SRTO_PASSPHRASE = 26, // Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto + SRTO_PBKEYLEN, // Crypto key len in bytes {16,24,32} Default: 16 (128-bit) + SRTO_KMSTATE, // Key Material exchange status (UDT_SRTKmState) + SRTO_IPTTL = 29, // IP Time To Live (passthru for system sockopt IPPROTO_IP/IP_TTL) + SRTO_IPTOS, // IP Type of Service (passthru for system sockopt IPPROTO_IP/IP_TOS) + SRTO_TLPKTDROP = 31, // Enable receiver pkt drop + SRTO_SNDDROPDELAY = 32, // Extra delay towards latency for sender TLPKTDROP decision (-1 to off) + SRTO_NAKREPORT = 33, // Enable receiver to send periodic NAK reports + SRTO_VERSION = 34, // Local SRT Version + SRTO_PEERVERSION, // Peer SRT Version (from SRT Handshake) + SRTO_CONNTIMEO = 36, // Connect timeout in msec. Caller default: 3000, rendezvous (x 10) + SRTO_DRIFTTRACER = 37, // Enable or disable drift tracer + // (some space left) + SRTO_SNDKMSTATE = 40, // (GET) the current state of the encryption at the peer side + SRTO_RCVKMSTATE, // (GET) the current state of the encryption at the agent side + SRTO_LOSSMAXTTL, // Maximum possible packet reorder tolerance (number of packets to receive after loss to send lossreport) + SRTO_RCVLATENCY, // TsbPd receiver delay (mSec) to absorb burst of missed packet retransmission + SRTO_PEERLATENCY, // Minimum value of the TsbPd receiver delay (mSec) for the opposite side (peer) + SRTO_MINVERSION, // Minimum SRT version needed for the peer (peers with less version will get connection reject) + SRTO_STREAMID, // A string set to a socket and passed to the listener's accepted socket + SRTO_CONGESTION, // Congestion controller type selection + SRTO_MESSAGEAPI, // In File mode, use message API (portions of data with boundaries) + SRTO_PAYLOADSIZE, // Maximum payload size sent in one UDP packet (0 if unlimited) + SRTO_TRANSTYPE = 50, // Transmission type (set of options required for given transmission type) + SRTO_KMREFRESHRATE, // After sending how many packets the encryption key should be flipped to the new key + SRTO_KMPREANNOUNCE, // How many packets before key flip the new key is annnounced and after key flip the old one decommissioned + SRTO_ENFORCEDENCRYPTION, // Connection to be rejected or quickly broken when one side encryption set or bad password + SRTO_IPV6ONLY, // IPV6_V6ONLY mode + SRTO_PEERIDLETIMEO, // Peer-idle timeout (max time of silence heard from peer) in [ms] +#if ENABLE_EXPERIMENTAL_BONDING + SRTO_GROUPCONNECT, // Set on a listener to allow group connection + SRTO_GROUPSTABTIMEO, // Stability timeout (backup groups) in [us] + SRTO_GROUPTYPE, // Group type to which an accepted socket is about to be added, available in the handshake +#endif + SRTO_BINDTODEVICE, // Forward the SOL_SOCKET/SO_BINDTODEVICE option on socket (pass packets only from that device) + SRTO_PACKETFILTER = 60, // Add and configure a packet filter + SRTO_RETRANSMITALGO = 61 // An option to select packet retransmission algorithm +} SRT_SOCKOPT; + + +#ifdef __cplusplus + + +#if __cplusplus > 199711L // C++11 + // Newer compilers report error when [[deprecated]] is applied to types, + // and C++11 and higher uses this. + // Note that this doesn't exactly use the 'deprecated' attribute, + // as it's introduced in C++14. What is actually used here is the + // fact that unknown attributes are ignored, but still warned about. + // This should only catch an eye - and that's what it does. +#define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT [[deprecated]])value) +#else + // Older (pre-C++11) compilers use gcc deprecated applied to a typedef + typedef SRT_ATR_DEPRECATED_PX SRT_SOCKOPT SRT_SOCKOPT_DEPRECATED SRT_ATR_DEPRECATED; +#define SRT_DEPRECATED_OPTION(value) ((SRT_SOCKOPT_DEPRECATED)value) +#endif + + +#else + +// deprecated enum labels are supported only since gcc 6, so in C there +// will be a whole deprecated enum type, as it's not an error in C to mix +// enum types +enum SRT_ATR_DEPRECATED SRT_SOCKOPT_DEPRECATED +{ + + // Dummy last option, as every entry ends with a comma + SRTO_DEPRECATED_END = 0 + +}; +#define SRT_DEPRECATED_OPTION(value) ((enum SRT_SOCKOPT_DEPRECATED)value) +#endif + +// Note that there are no deprecated options at the moment, but the mechanism +// stays so that it can be used in future. Example: +// #define SRTO_STRICTENC SRT_DEPRECATED_OPTION(53) + +typedef enum SRT_TRANSTYPE +{ + SRTT_LIVE, + SRTT_FILE, + SRTT_INVALID +} SRT_TRANSTYPE; + +// These sizes should be used for Live mode. In Live mode you should not +// exceed the size that fits in a single MTU. + +// This is for MPEG TS and it's a default SRTO_PAYLOADSIZE for SRTT_LIVE. +static const int SRT_LIVE_DEF_PLSIZE = 1316; // = 188*7, recommended for MPEG TS + +// This is the maximum payload size for Live mode, should you have a different +// payload type than MPEG TS. +static const int SRT_LIVE_MAX_PLSIZE = 1456; // MTU(1500) - UDP.hdr(28) - SRT.hdr(16) + +// Latency for Live transmission: default is 120 +static const int SRT_LIVE_DEF_LATENCY_MS = 120; + +// Importrant note: please add new fields to this structure to the end and don't remove any existing fields +struct CBytePerfMon +{ + // global measurements + int64_t msTimeStamp; // time since the UDT entity is started, in milliseconds + int64_t pktSentTotal; // total number of sent data packets, including retransmissions + int64_t pktRecvTotal; // total number of received packets + int pktSndLossTotal; // total number of lost packets (sender side) + int pktRcvLossTotal; // total number of lost packets (receiver side) + int pktRetransTotal; // total number of retransmitted packets + int pktSentACKTotal; // total number of sent ACK packets + int pktRecvACKTotal; // total number of received ACK packets + int pktSentNAKTotal; // total number of sent NAK packets + int pktRecvNAKTotal; // total number of received NAK packets + int64_t usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive) + //>new + int pktSndDropTotal; // number of too-late-to-send dropped packets + int pktRcvDropTotal; // number of too-late-to play missing packets + int pktRcvUndecryptTotal; // number of undecrypted packets + uint64_t byteSentTotal; // total number of sent data bytes, including retransmissions + uint64_t byteRecvTotal; // total number of received bytes + uint64_t byteRcvLossTotal; // total number of lost bytes + uint64_t byteRetransTotal; // total number of retransmitted bytes + uint64_t byteSndDropTotal; // number of too-late-to-send dropped bytes + uint64_t byteRcvDropTotal; // number of too-late-to play missing bytes (estimate based on average packet size) + uint64_t byteRcvUndecryptTotal; // number of undecrypted bytes + //< + + // local measurements + int64_t pktSent; // number of sent data packets, including retransmissions + int64_t pktRecv; // number of received packets + int pktSndLoss; // number of lost packets (sender side) + int pktRcvLoss; // number of lost packets (receiver side) + int pktRetrans; // number of retransmitted packets + int pktRcvRetrans; // number of retransmitted packets received + int pktSentACK; // number of sent ACK packets + int pktRecvACK; // number of received ACK packets + int pktSentNAK; // number of sent NAK packets + int pktRecvNAK; // number of received NAK packets + double mbpsSendRate; // sending rate in Mb/s + double mbpsRecvRate; // receiving rate in Mb/s + int64_t usSndDuration; // busy sending time (i.e., idle time exclusive) + int pktReorderDistance; // size of order discrepancy in received sequences + double pktRcvAvgBelatedTime; // average time of packet delay for belated packets (packets with sequence past the ACK) + int64_t pktRcvBelated; // number of received AND IGNORED packets due to having come too late + //>new + int pktSndDrop; // number of too-late-to-send dropped packets + int pktRcvDrop; // number of too-late-to play missing packets + int pktRcvUndecrypt; // number of undecrypted packets + uint64_t byteSent; // number of sent data bytes, including retransmissions + uint64_t byteRecv; // number of received bytes + uint64_t byteRcvLoss; // number of retransmitted bytes + uint64_t byteRetrans; // number of retransmitted bytes + uint64_t byteSndDrop; // number of too-late-to-send dropped bytes + uint64_t byteRcvDrop; // number of too-late-to play missing bytes (estimate based on average packet size) + uint64_t byteRcvUndecrypt; // number of undecrypted bytes + //< + + // instant measurements + double usPktSndPeriod; // packet sending period, in microseconds + int pktFlowWindow; // flow window size, in number of packets + int pktCongestionWindow; // congestion window size, in number of packets + int pktFlightSize; // number of packets on flight + double msRTT; // RTT, in milliseconds + double mbpsBandwidth; // estimated bandwidth, in Mb/s + int byteAvailSndBuf; // available UDT sender buffer size + int byteAvailRcvBuf; // available UDT receiver buffer size + //>new + double mbpsMaxBW; // Transmit Bandwidth ceiling (Mbps) + int byteMSS; // MTU + + int pktSndBuf; // UnACKed packets in UDT sender + int byteSndBuf; // UnACKed bytes in UDT sender + int msSndBuf; // UnACKed timespan (msec) of UDT sender + int msSndTsbPdDelay; // Timestamp-based Packet Delivery Delay + + int pktRcvBuf; // Undelivered packets in UDT receiver + int byteRcvBuf; // Undelivered bytes of UDT receiver + int msRcvBuf; // Undelivered timespan (msec) of UDT receiver + int msRcvTsbPdDelay; // Timestamp-based Packet Delivery Delay + + int pktSndFilterExtraTotal; // number of control packets supplied by packet filter + int pktRcvFilterExtraTotal; // number of control packets received and not supplied back + int pktRcvFilterSupplyTotal; // number of packets that the filter supplied extra (e.g. FEC rebuilt) + int pktRcvFilterLossTotal; // number of packet loss not coverable by filter + + int pktSndFilterExtra; // number of control packets supplied by packet filter + int pktRcvFilterExtra; // number of control packets received and not supplied back + int pktRcvFilterSupply; // number of packets that the filter supplied extra (e.g. FEC rebuilt) + int pktRcvFilterLoss; // number of packet loss not coverable by filter + int pktReorderTolerance; // packet reorder tolerance value + //< + + // New stats in 1.5.0 + + // Total + int64_t pktSentUniqueTotal; // total number of data packets sent by the application + int64_t pktRecvUniqueTotal; // total number of packets to be received by the application + uint64_t byteSentUniqueTotal; // total number of data bytes, sent by the application + uint64_t byteRecvUniqueTotal; // total number of data bytes to be received by the application + + // Local + int64_t pktSentUnique; // number of data packets sent by the application + int64_t pktRecvUnique; // number of packets to be received by the application + uint64_t byteSentUnique; // number of data bytes, sent by the application + uint64_t byteRecvUnique; // number of data bytes to be received by the application +}; + +//////////////////////////////////////////////////////////////////////////////// + +// Error codes - define outside the CUDTException class +// because otherwise you'd have to use CUDTException::MJ_SUCCESS etc. +// in all throw CUDTException expressions. +enum CodeMajor +{ + MJ_UNKNOWN = -1, + MJ_SUCCESS = 0, + MJ_SETUP = 1, + MJ_CONNECTION = 2, + MJ_SYSTEMRES = 3, + MJ_FILESYSTEM = 4, + MJ_NOTSUP = 5, + MJ_AGAIN = 6, + MJ_PEERERROR = 7 +}; + +enum CodeMinor +{ + // These are "minor" error codes from various "major" categories + // MJ_SETUP + MN_NONE = 0, + MN_TIMEOUT = 1, + MN_REJECTED = 2, + MN_NORES = 3, + MN_SECURITY = 4, + MN_CLOSED = 5, + // MJ_CONNECTION + MN_CONNLOST = 1, + MN_NOCONN = 2, + // MJ_SYSTEMRES + MN_THREAD = 1, + MN_MEMORY = 2, + MN_OBJECT = 3, + // MJ_FILESYSTEM + MN_SEEKGFAIL = 1, + MN_READFAIL = 2, + MN_SEEKPFAIL = 3, + MN_WRITEFAIL = 4, + // MJ_NOTSUP + MN_ISBOUND = 1, + MN_ISCONNECTED = 2, + MN_INVAL = 3, + MN_SIDINVAL = 4, + MN_ISUNBOUND = 5, + MN_NOLISTEN = 6, + MN_ISRENDEZVOUS = 7, + MN_ISRENDUNBOUND = 8, + MN_INVALMSGAPI = 9, + MN_INVALBUFFERAPI = 10, + MN_BUSY = 11, + MN_XSIZE = 12, + MN_EIDINVAL = 13, + MN_EEMPTY = 14, + // MJ_AGAIN + MN_WRAVAIL = 1, + MN_RDAVAIL = 2, + MN_XMTIMEOUT = 3, + MN_CONGESTION = 4 +}; + + +// Stupid, but effective. This will be #undefined, so don't worry. +#define MJ(major) (1000 * MJ_##major) +#define MN(major, minor) (1000 * MJ_##major + MN_##minor) + +// Some better way to define it, and better for C language. +typedef enum SRT_ERRNO +{ + SRT_EUNKNOWN = -1, + SRT_SUCCESS = MJ_SUCCESS, + + SRT_ECONNSETUP = MJ(SETUP), + SRT_ENOSERVER = MN(SETUP, TIMEOUT), + SRT_ECONNREJ = MN(SETUP, REJECTED), + SRT_ESOCKFAIL = MN(SETUP, NORES), + SRT_ESECFAIL = MN(SETUP, SECURITY), + SRT_ESCLOSED = MN(SETUP, CLOSED), + + SRT_ECONNFAIL = MJ(CONNECTION), + SRT_ECONNLOST = MN(CONNECTION, CONNLOST), + SRT_ENOCONN = MN(CONNECTION, NOCONN), + + SRT_ERESOURCE = MJ(SYSTEMRES), + SRT_ETHREAD = MN(SYSTEMRES, THREAD), + SRT_ENOBUF = MN(SYSTEMRES, MEMORY), + SRT_ESYSOBJ = MN(SYSTEMRES, OBJECT), + + SRT_EFILE = MJ(FILESYSTEM), + SRT_EINVRDOFF = MN(FILESYSTEM, SEEKGFAIL), + SRT_ERDPERM = MN(FILESYSTEM, READFAIL), + SRT_EINVWROFF = MN(FILESYSTEM, SEEKPFAIL), + SRT_EWRPERM = MN(FILESYSTEM, WRITEFAIL), + + SRT_EINVOP = MJ(NOTSUP), + SRT_EBOUNDSOCK = MN(NOTSUP, ISBOUND), + SRT_ECONNSOCK = MN(NOTSUP, ISCONNECTED), + SRT_EINVPARAM = MN(NOTSUP, INVAL), + SRT_EINVSOCK = MN(NOTSUP, SIDINVAL), + SRT_EUNBOUNDSOCK = MN(NOTSUP, ISUNBOUND), + SRT_ENOLISTEN = MN(NOTSUP, NOLISTEN), + SRT_ERDVNOSERV = MN(NOTSUP, ISRENDEZVOUS), + SRT_ERDVUNBOUND = MN(NOTSUP, ISRENDUNBOUND), + SRT_EINVALMSGAPI = MN(NOTSUP, INVALMSGAPI), + SRT_EINVALBUFFERAPI = MN(NOTSUP, INVALBUFFERAPI), + SRT_EDUPLISTEN = MN(NOTSUP, BUSY), + SRT_ELARGEMSG = MN(NOTSUP, XSIZE), + SRT_EINVPOLLID = MN(NOTSUP, EIDINVAL), + SRT_EPOLLEMPTY = MN(NOTSUP, EEMPTY), + + SRT_EASYNCFAIL = MJ(AGAIN), + SRT_EASYNCSND = MN(AGAIN, WRAVAIL), + SRT_EASYNCRCV = MN(AGAIN, RDAVAIL), + SRT_ETIMEOUT = MN(AGAIN, XMTIMEOUT), + SRT_ECONGEST = MN(AGAIN, CONGESTION), + + SRT_EPEERERR = MJ(PEERERROR) +} SRT_ERRNO; + + +#undef MJ +#undef MN + +enum SRT_REJECT_REASON +{ + SRT_REJ_UNKNOWN, // initial set when in progress + SRT_REJ_SYSTEM, // broken due to system function error + SRT_REJ_PEER, // connection was rejected by peer + SRT_REJ_RESOURCE, // internal problem with resource allocation + SRT_REJ_ROGUE, // incorrect data in handshake messages + SRT_REJ_BACKLOG, // listener's backlog exceeded + SRT_REJ_IPE, // internal program error + SRT_REJ_CLOSE, // socket is closing + SRT_REJ_VERSION, // peer is older version than agent's minimum set + SRT_REJ_RDVCOOKIE, // rendezvous cookie collision + SRT_REJ_BADSECRET, // wrong password + SRT_REJ_UNSECURE, // password required or unexpected + SRT_REJ_MESSAGEAPI, // streamapi/messageapi collision + SRT_REJ_CONGESTION, // incompatible congestion-controller type + SRT_REJ_FILTER, // incompatible packet filter + SRT_REJ_GROUP, // incompatible group + SRT_REJ_TIMEOUT, // connection timeout + + SRT_REJ_E_SIZE, +}; + +// XXX This value remains for some time, but it's deprecated +// Planned deprecation removal: rel1.6.0. +#define SRT_REJ__SIZE SRT_REJ_E_SIZE + +// Reject category codes: + +#define SRT_REJC_VALUE(code) (1000 * (code/1000)) +#define SRT_REJC_INTERNAL 0 // Codes from above SRT_REJECT_REASON enum +#define SRT_REJC_PREDEFINED 1000 // Standard server error codes +#define SRT_REJC_USERDEFINED 2000 // User defined error codes + + +// Logging API - specialization for SRT. + +// WARNING: This part is generated. + +// Logger Functional Areas +// Note that 0 is "general". + +// Values 0* - general, unqualified +// Values 1* - control +// Values 2* - receiving +// Values 3* - sending +// Values 4* - management + +// Made by #define so that it's available also for C API. + +// Use ../scripts/generate-logging-defs.tcl to regenerate. + +// SRT_LOGFA BEGIN GENERATED SECTION { + +#define SRT_LOGFA_GENERAL 0 // gglog: General uncategorized log, for serious issues only +#define SRT_LOGFA_SOCKMGMT 1 // smlog: Socket create/open/close/configure activities +#define SRT_LOGFA_CONN 2 // cnlog: Connection establishment and handshake +#define SRT_LOGFA_XTIMER 3 // xtlog: The checkTimer and around activities +#define SRT_LOGFA_TSBPD 4 // tslog: The TsBPD thread +#define SRT_LOGFA_RSRC 5 // rslog: System resource allocation and management + +#define SRT_LOGFA_CONGEST 7 // cclog: Congestion control module +#define SRT_LOGFA_PFILTER 8 // pflog: Packet filter module + +#define SRT_LOGFA_API_CTRL 11 // aclog: API part for socket and library managmenet + +#define SRT_LOGFA_QUE_CTRL 13 // qclog: Queue control activities + +#define SRT_LOGFA_EPOLL_UPD 16 // eilog: EPoll, internal update activities + +#define SRT_LOGFA_API_RECV 21 // arlog: API part for receiving +#define SRT_LOGFA_BUF_RECV 22 // brlog: Buffer, receiving side +#define SRT_LOGFA_QUE_RECV 23 // qrlog: Queue, receiving side +#define SRT_LOGFA_CHN_RECV 24 // krlog: CChannel, receiving side +#define SRT_LOGFA_GRP_RECV 25 // grlog: Group, receiving side + +#define SRT_LOGFA_API_SEND 31 // aslog: API part for sending +#define SRT_LOGFA_BUF_SEND 32 // bslog: Buffer, sending side +#define SRT_LOGFA_QUE_SEND 33 // qslog: Queue, sending side +#define SRT_LOGFA_CHN_SEND 34 // kslog: CChannel, sending side +#define SRT_LOGFA_GRP_SEND 35 // gslog: Group, sending side + +#define SRT_LOGFA_INTERNAL 41 // inlog: Internal activities not connected directly to a socket + +#define SRT_LOGFA_QUE_MGMT 43 // qmlog: Queue, management part +#define SRT_LOGFA_CHN_MGMT 44 // kmlog: CChannel, management part +#define SRT_LOGFA_GRP_MGMT 45 // gmlog: Group, management part +#define SRT_LOGFA_EPOLL_API 46 // ealog: EPoll, API part + +#define SRT_LOGFA_HAICRYPT 6 // hclog: Haicrypt module area +#define SRT_LOGFA_APPLOG 10 // aplog: Applications + +// } SRT_LOGFA END GENERATED SECTION + +// To make a typical int64_t size, although still use std::bitset. +// C API will carry it over. +#define SRT_LOGFA_LASTNONE 63 + +enum SRT_KM_STATE +{ + SRT_KM_S_UNSECURED = 0, //No encryption + SRT_KM_S_SECURING = 1, //Stream encrypted, exchanging Keying Material + SRT_KM_S_SECURED = 2, //Stream encrypted, keying Material exchanged, decrypting ok. + SRT_KM_S_NOSECRET = 3, //Stream encrypted and no secret to decrypt Keying Material + SRT_KM_S_BADSECRET = 4 //Stream encrypted and wrong secret, cannot decrypt Keying Material +}; + +enum SRT_EPOLL_OPT +{ + SRT_EPOLL_OPT_NONE = 0x0, // fallback + + // Values intended to be the same as in ``. + // so that if system values are used by mistake, they should have the same effect + // This applies to: IN, OUT, ERR and ET. + + /// Ready for 'recv' operation: + /// + /// - For stream mode it means that at least 1 byte is available. + /// In this mode the buffer may extract only a part of the packet, + /// leaving next data possible for extraction later. + /// + /// - For message mode it means that there is at least one packet + /// available (this may change in future, as it is desired that + /// one full message should only wake up, not single packet of a + /// not yet extractable message). + /// + /// - For live mode it means that there's at least one packet + /// ready to play. + /// + /// - For listener sockets, this means that there is a new connection + /// waiting for pickup through the `srt_accept()` call, that is, + /// the next call to `srt_accept()` will succeed without blocking + /// (see an alias SRT_EPOLL_ACCEPT below). + SRT_EPOLL_IN = 0x1, + + /// Ready for 'send' operation. + /// + /// - For stream mode it means that there's a free space in the + /// sender buffer for at least 1 byte of data. The next send + /// operation will only allow to send as much data as it is free + /// space in the buffer. + /// + /// - For message mode it means that there's a free space for at + /// least one UDP packet. The edge-triggered mode can be used to + /// pick up updates as the free space in the sender buffer grows. + /// + /// - For live mode it means that there's a free space for at least + /// one UDP packet. On the other hand, no readiness for OUT usually + /// means an extraordinary congestion on the link, meaning also that + /// you should immediately slow down the sending rate or you may get + /// a connection break soon. + /// + /// - For non-blocking sockets used with `srt_connect*` operation, + /// this flag simply means that the connection was established. + SRT_EPOLL_OUT = 0x4, + + /// The socket has encountered an error in the last operation + /// and the next operation on that socket will end up with error. + /// You can retry the operation, but getting the error from it + /// is certain, so you may as well close the socket. + SRT_EPOLL_ERR = 0x8, + + // To avoid confusion in the internal code, the following + // duplicates are introduced to improve clarity. + SRT_EPOLL_CONNECT = SRT_EPOLL_OUT, + SRT_EPOLL_ACCEPT = SRT_EPOLL_IN, + + SRT_EPOLL_UPDATE = 0x10, + SRT_EPOLL_ET = 1u << 31 +}; +// These are actually flags - use a bit container: +typedef int32_t SRT_EPOLL_T; + +// Define which epoll flags determine events. All others are special flags. +#define SRT_EPOLL_EVENTTYPES (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_UPDATE | SRT_EPOLL_ERR) +#define SRT_EPOLL_ETONLY (SRT_EPOLL_UPDATE) + +enum SRT_EPOLL_FLAGS +{ + /// This allows the EID container to be empty when calling the waiting + /// function with infinite time. This means an infinite hangup, although + /// a socket can be added to this EID from a separate thread. + SRT_EPOLL_ENABLE_EMPTY = 1, + + /// This makes the waiting function check if there is output container + /// passed to it, and report an error if it isn't. By default it is allowed + /// that the output container is 0 size or NULL and therefore the readiness + /// state is reported only as a number of ready sockets from return value. + SRT_EPOLL_ENABLE_OUTPUTCHECK = 2 +}; + +#ifdef __cplusplus +// In C++ these enums cannot be treated as int and glued by operator |. +// Unless this operator is defined. +inline SRT_EPOLL_OPT operator|(SRT_EPOLL_OPT a1, SRT_EPOLL_OPT a2) +{ + return SRT_EPOLL_OPT( (int)a1 | (int)a2 ); +} + +#endif + +typedef struct CBytePerfMon SRT_TRACEBSTATS; + +static const SRTSOCKET SRT_INVALID_SOCK = -1; +static const int SRT_ERROR = -1; + +// library initialization +SRT_API int srt_startup(void); +SRT_API int srt_cleanup(void); + +// +// Socket operations +// +// DEPRECATED: srt_socket with 3 arguments. All these arguments are ignored +// and socket creation doesn't need any arguments. Use srt_create_socket(). +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX SRT_API SRTSOCKET srt_socket(int, int, int) SRT_ATR_DEPRECATED; +SRT_API SRTSOCKET srt_create_socket(void); + +// Group management + +// Stubs when off + +typedef struct SRT_SocketGroupData_ SRT_SOCKGROUPDATA; + +#if ENABLE_EXPERIMENTAL_BONDING + +typedef enum SRT_GROUP_TYPE +{ + SRT_GTYPE_UNDEFINED, + SRT_GTYPE_BROADCAST, + SRT_GTYPE_BACKUP, + SRT_GTYPE_BALANCING, + SRT_GTYPE_MULTICAST, + // ... + SRT_GTYPE_E_END +} SRT_GROUP_TYPE; + +// Free-form flags for groups +// Flags may be type-specific! +static const uint32_t SRT_GFLAG_SYNCONMSG = 1; + +typedef enum SRT_MemberStatus +{ + SRT_GST_PENDING, // The socket is created correctly, but not yet ready for getting data. + SRT_GST_IDLE, // The socket is ready to be activated + SRT_GST_RUNNING, // The socket was already activated and is in use + SRT_GST_BROKEN // The last operation broke the socket, it should be closed. +} SRT_MEMBERSTATUS; + +struct SRT_SocketGroupData_ +{ + SRTSOCKET id; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + SRT_SOCKSTATUS sockstate; + uint16_t weight; + SRT_MEMBERSTATUS memberstate; + int result; + int token; +}; + +typedef struct SRT_SocketOptionObject SRT_SOCKOPT_CONFIG; + +typedef struct SRT_GroupMemberConfig_ +{ + SRTSOCKET id; + struct sockaddr_storage srcaddr; + struct sockaddr_storage peeraddr; // Don't want to expose sockaddr_any to public API + uint16_t weight; + SRT_SOCKOPT_CONFIG* config; + int errorcode; + int token; +} SRT_SOCKGROUPCONFIG; + +SRT_API SRTSOCKET srt_create_group (SRT_GROUP_TYPE); +SRT_API int srt_include (SRTSOCKET socket, SRTSOCKET group); +SRT_API int srt_exclude (SRTSOCKET socket); +SRT_API SRTSOCKET srt_groupof (SRTSOCKET socket); +SRT_API int srt_group_data (SRTSOCKET socketgroup, SRT_SOCKGROUPDATA* output, size_t* inoutlen); +SRT_API int srt_group_configure(SRTSOCKET socketgroup, const char* str); + +SRT_API SRT_SOCKOPT_CONFIG* srt_create_config(void); +SRT_API void srt_delete_config(SRT_SOCKOPT_CONFIG* config /*nullable*/); +SRT_API int srt_config_add(SRT_SOCKOPT_CONFIG* config, SRT_SOCKOPT option, const void* contents, int len); + +SRT_API SRT_SOCKGROUPCONFIG srt_prepare_endpoint(const struct sockaddr* src /*nullable*/, const struct sockaddr* adr, int namelen); +SRT_API int srt_connect_group(SRTSOCKET group, SRT_SOCKGROUPCONFIG name [], int arraysize); + +#endif // ENABLE_EXPERIMENTAL_BONDING + +SRT_API int srt_bind (SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int srt_bind_acquire (SRTSOCKET u, UDPSOCKET sys_udp_sock); +// Old name of srt_bind_acquire(), please don't use +// Planned deprecation removal: rel1.6.0 +SRT_ATR_DEPRECATED_PX static inline int srt_bind_peerof(SRTSOCKET u, UDPSOCKET sys_udp_sock) SRT_ATR_DEPRECATED; +static inline int srt_bind_peerof (SRTSOCKET u, UDPSOCKET sys_udp_sock) { return srt_bind_acquire(u, sys_udp_sock); } +SRT_API int srt_listen (SRTSOCKET u, int backlog); +SRT_API SRTSOCKET srt_accept (SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API SRTSOCKET srt_accept_bond (const SRTSOCKET listeners[], int lsize, int64_t msTimeOut); +typedef int srt_listen_callback_fn (void* opaq, SRTSOCKET ns, int hsversion, const struct sockaddr* peeraddr, const char* streamid); +SRT_API int srt_listen_callback(SRTSOCKET lsn, srt_listen_callback_fn* hook_fn, void* hook_opaque); +typedef void srt_connect_callback_fn (void* opaq, SRTSOCKET ns, int errorcode, const struct sockaddr* peeraddr, int token); +SRT_API int srt_connect_callback(SRTSOCKET clr, srt_connect_callback_fn* hook_fn, void* hook_opaque); +SRT_API int srt_connect (SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int srt_connect_debug(SRTSOCKET u, const struct sockaddr* name, int namelen, int forced_isn); +SRT_API int srt_connect_bind (SRTSOCKET u, const struct sockaddr* source, + const struct sockaddr* target, int len); +SRT_API int srt_rendezvous (SRTSOCKET u, const struct sockaddr* local_name, int local_namelen, + const struct sockaddr* remote_name, int remote_namelen); + +SRT_API int srt_close (SRTSOCKET u); +SRT_API int srt_getpeername (SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int srt_getsockname (SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int srt_getsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT optname, void* optval, int* optlen); +SRT_API int srt_setsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT optname, const void* optval, int optlen); +SRT_API int srt_getsockflag (SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen); +SRT_API int srt_setsockflag (SRTSOCKET u, SRT_SOCKOPT opt, const void* optval, int optlen); + +typedef struct SRT_MsgCtrl_ +{ + int flags; // Left for future + int msgttl; // TTL for a message, default -1 (no TTL limitation) + int inorder; // Whether a message is allowed to supersede partially lost one. Unused in stream and live mode. + int boundary; // 0:mid pkt, 1(01b):end of frame, 2(11b):complete frame, 3(10b): start of frame + int64_t srctime; // source time since epoch (usec), 0: use internal time (sender) + int32_t pktseq; // sequence number of the first packet in received message (unused for sending) + int32_t msgno; // message number (output value for both sending and receiving) + SRT_SOCKGROUPDATA* grpdata; + size_t grpdata_size; +} SRT_MSGCTRL; + +// Trap representation for sequence and message numbers +// This value means that this is "unset", and it's never +// a result of an operation made on this number. +static const int32_t SRT_SEQNO_NONE = -1; // -1: no seq (0 is a valid seqno!) +static const int32_t SRT_MSGNO_NONE = -1; // -1: unset +static const int32_t SRT_MSGNO_CONTROL = 0; // 0: control (used by packet filter) + +static const int SRT_MSGTTL_INF = -1; // unlimited TTL specification for message TTL + +// XXX Might be useful also other special uses of -1: +// - -1 as infinity for srt_epoll_wait +// - -1 as a trap index value used in list.cpp + +// You are free to use either of these two methods to set SRT_MSGCTRL object +// to default values: either call srt_msgctrl_init(&obj) or obj = srt_msgctrl_default. +SRT_API void srt_msgctrl_init(SRT_MSGCTRL* mctrl); +SRT_API extern const SRT_MSGCTRL srt_msgctrl_default; + +// The send/receive functions. +// These functions have different names due to different sets of parameters +// to be supplied. Not all of them are needed or make sense in all modes: + +// Plain: supply only the buffer and its size. +// Msg: supply additionally +// - TTL (message is not delivered when exceeded) and +// - INORDER (when false, the message is allowed to be delivered in different +// order than when it was sent, when the later message is earlier ready to +// deliver) +// Msg2: Supply extra parameters in SRT_MSGCTRL. When receiving, these +// parameters will be filled, as needed. NULL is acceptable, in which case +// the defaults are used. + +// +// Sending functions +// +SRT_API int srt_send (SRTSOCKET u, const char* buf, int len); +SRT_API int srt_sendmsg (SRTSOCKET u, const char* buf, int len, int ttl/* = -1*/, int inorder/* = false*/); +SRT_API int srt_sendmsg2(SRTSOCKET u, const char* buf, int len, SRT_MSGCTRL *mctrl); + +// +// Receiving functions +// +SRT_API int srt_recv (SRTSOCKET u, char* buf, int len); + +// srt_recvmsg is actually an alias to srt_recv, it stays under the old name for compat reasons. +SRT_API int srt_recvmsg (SRTSOCKET u, char* buf, int len); +SRT_API int srt_recvmsg2(SRTSOCKET u, char *buf, int len, SRT_MSGCTRL *mctrl); + + +// Special send/receive functions for files only. +#define SRT_DEFAULT_SENDFILE_BLOCK 364000 +#define SRT_DEFAULT_RECVFILE_BLOCK 7280000 +SRT_API int64_t srt_sendfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); +SRT_API int64_t srt_recvfile(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block); + + +// last error detection +SRT_API const char* srt_getlasterror_str(void); +SRT_API int srt_getlasterror(int* errno_loc); +SRT_API const char* srt_strerror(int code, int errnoval); +SRT_API void srt_clearlasterror(void); + +// Performance tracking +// Performance monitor with Byte counters for better bitrate estimation. +SRT_API int srt_bstats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear); +// Performance monitor with Byte counters and instantaneous stats instead of moving averages for Snd/Rcvbuffer sizes. +SRT_API int srt_bistats(SRTSOCKET u, SRT_TRACEBSTATS * perf, int clear, int instantaneous); + +// Socket Status (for problem tracking) +SRT_API SRT_SOCKSTATUS srt_getsockstate(SRTSOCKET u); + +SRT_API int srt_epoll_create(void); +SRT_API int srt_epoll_clear_usocks(int eid); +SRT_API int srt_epoll_add_usock(int eid, SRTSOCKET u, const int* events); +SRT_API int srt_epoll_add_ssock(int eid, SYSSOCKET s, const int* events); +SRT_API int srt_epoll_remove_usock(int eid, SRTSOCKET u); +SRT_API int srt_epoll_remove_ssock(int eid, SYSSOCKET s); +SRT_API int srt_epoll_update_usock(int eid, SRTSOCKET u, const int* events); +SRT_API int srt_epoll_update_ssock(int eid, SYSSOCKET s, const int* events); + +SRT_API int srt_epoll_wait(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, + SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum); +typedef struct SRT_EPOLL_EVENT_STR +{ + SRTSOCKET fd; + int events; // SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR +#ifdef __cplusplus + SRT_EPOLL_EVENT_STR(SRTSOCKET s, int ev): fd(s), events(ev) {} + SRT_EPOLL_EVENT_STR() {} // NOTE: allows singular values, no init. +#endif +} SRT_EPOLL_EVENT; +SRT_API int srt_epoll_uwait(int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); + +SRT_API int32_t srt_epoll_set(int eid, int32_t flags); +SRT_API int srt_epoll_release(int eid); + +// Logging control + +SRT_API void srt_setloglevel(int ll); +SRT_API void srt_addlogfa(int fa); +SRT_API void srt_dellogfa(int fa); +SRT_API void srt_resetlogfa(const int* fara, size_t fara_size); +// This isn't predicted, will be only available in SRT C++ API. +// For the time being, until this API is ready, use UDT::setlogstream. +// SRT_API void srt_setlogstream(std::ostream& stream); +SRT_API void srt_setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +SRT_API void srt_setlogflags(int flags); + + +SRT_API int srt_getsndbuffer(SRTSOCKET sock, size_t* blocks, size_t* bytes); + +SRT_API int srt_getrejectreason(SRTSOCKET sock); +SRT_API int srt_setrejectreason(SRTSOCKET sock, int value); +SRT_API extern const char* const srt_rejectreason_msg []; +const char* srt_rejectreason_str(int id); + +SRT_API uint32_t srt_getversion(void); + +SRT_API int64_t srt_time_now(void); + +SRT_API int64_t srt_connection_time(SRTSOCKET sock); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/srt/udt.h b/thirdparty/include/srt/udt.h new file mode 100755 index 0000000000000000000000000000000000000000..1bcc889cadf1769fd6eb86741639f8c3ccb71c5b --- /dev/null +++ b/thirdparty/include/srt/udt.h @@ -0,0 +1,282 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the University of Illinois + nor the names of its contributors may be used to + endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +/***************************************************************************** +written by + Yunhong Gu, last updated 01/18/2011 +modified by + Haivision Systems Inc. +*****************************************************************************/ + +/* WARNING!!! + * Since now this file is a "C and C++ header". + * It should be then able to be interpreted by C compiler, so + * all C++-oriented things must be ifdef'd-out by __cplusplus. + * + * Mind also comments - to prevent any portability problems, + * B/C++ comments (// -> EOL) should not be used unless the + * area is under __cplusplus condition already. + * + * NOTE: this file contains _STRUCTURES_ that are common to C and C++, + * plus some functions and other functionalities ONLY FOR C++. This + * file doesn't contain _FUNCTIONS_ predicted to be used in C - see udtc.h + */ + +#ifndef INC_SRT_UDT_H +#define INC_SRT_UDT_H + +#include "srt.h" + +/* +* SRT_ENABLE_THREADCHECK (THIS IS SET IN MAKEFILE NOT HERE) +*/ +#if defined(SRT_ENABLE_THREADCHECK) +#include +#else +#define THREAD_STATE_INIT(name) +#define THREAD_EXIT() +#define THREAD_PAUSED() +#define THREAD_RESUMED() +#define INCREMENT_THREAD_ITERATIONS() +#endif + +/* Obsolete way to define MINGW */ +#ifndef __MINGW__ +#if defined(__MINGW32__) || defined(__MINGW64__) +#define __MINGW__ 1 +#endif +#endif + +#ifdef __cplusplus +#include +#include +#include +#include +#endif + + +//////////////////////////////////////////////////////////////////////////////// + +//if compiling on VC6.0 or pre-WindowsXP systems +//use -DLEGACY_WIN32 + +//if compiling with MinGW, it only works on XP or above +//use -D_WIN32_WINNT=0x0501 + +//////////////////////////////////////////////////////////////////////////////// + +struct CPerfMon +{ + // global measurements + int64_t msTimeStamp; // time since the UDT entity is started, in milliseconds + int64_t pktSentTotal; // total number of sent data packets, including retransmissions + int64_t pktRecvTotal; // total number of received packets + int pktSndLossTotal; // total number of lost packets (sender side) + int pktRcvLossTotal; // total number of lost packets (receiver side) + int pktRetransTotal; // total number of retransmitted packets + int pktRcvRetransTotal; // total number of retransmitted packets received + int pktSentACKTotal; // total number of sent ACK packets + int pktRecvACKTotal; // total number of received ACK packets + int pktSentNAKTotal; // total number of sent NAK packets + int pktRecvNAKTotal; // total number of received NAK packets + int64_t usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive) + + // local measurements + int64_t pktSent; // number of sent data packets, including retransmissions + int64_t pktRecv; // number of received packets + int pktSndLoss; // number of lost packets (sender side) + int pktRcvLoss; // number of lost packets (receiver side) + int pktRetrans; // number of retransmitted packets + int pktRcvRetrans; // number of retransmitted packets received + int pktSentACK; // number of sent ACK packets + int pktRecvACK; // number of received ACK packets + int pktSentNAK; // number of sent NAK packets + int pktRecvNAK; // number of received NAK packets + double mbpsSendRate; // sending rate in Mb/s + double mbpsRecvRate; // receiving rate in Mb/s + int64_t usSndDuration; // busy sending time (i.e., idle time exclusive) + int pktReorderDistance; // size of order discrepancy in received sequences + double pktRcvAvgBelatedTime; // average time of packet delay for belated packets (packets with sequence past the ACK) + int64_t pktRcvBelated; // number of received AND IGNORED packets due to having come too late + + // instant measurements + double usPktSndPeriod; // packet sending period, in microseconds + int pktFlowWindow; // flow window size, in number of packets + int pktCongestionWindow; // congestion window size, in number of packets + int pktFlightSize; // number of packets on flight + double msRTT; // RTT, in milliseconds + double mbpsBandwidth; // estimated bandwidth, in Mb/s + int byteAvailSndBuf; // available UDT sender buffer size + int byteAvailRcvBuf; // available UDT receiver buffer size +}; + +typedef SRTSOCKET UDTSOCKET; //legacy alias + +#ifdef __cplusplus + +class CUDTException; + +namespace UDT +{ + +typedef CUDTException ERRORINFO; +typedef CPerfMon TRACEINFO; + +// This facility is used only for select() function. +// This is considered obsolete and the epoll() functionality rather should be used. +typedef std::set UDSET; +#define UD_CLR(u, uset) ((uset)->erase(u)) +#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) +#define UD_SET(u, uset) ((uset)->insert(u)) +#define UD_ZERO(uset) ((uset)->clear()) + +SRT_API extern const SRTSOCKET INVALID_SOCK; +#undef ERROR +SRT_API extern const int ERROR; + +SRT_API int startup(); +SRT_API int cleanup(); +SRT_API SRTSOCKET socket(); +inline SRTSOCKET socket(int , int , int ) { return socket(); } +SRT_API int bind(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int bind2(SRTSOCKET u, UDPSOCKET udpsock); +SRT_API int listen(SRTSOCKET u, int backlog); +SRT_API SRTSOCKET accept(SRTSOCKET u, struct sockaddr* addr, int* addrlen); +SRT_API int connect(SRTSOCKET u, const struct sockaddr* name, int namelen); +SRT_API int close(SRTSOCKET u); +SRT_API int getpeername(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockname(SRTSOCKET u, struct sockaddr* name, int* namelen); +SRT_API int getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen); +SRT_API int setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen); +SRT_API int send(SRTSOCKET u, const char* buf, int len, int flags); +SRT_API int recv(SRTSOCKET u, char* buf, int len, int flags); + +SRT_API int sendmsg(SRTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false, int64_t srctime = 0); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len, uint64_t& srctime); +SRT_API int recvmsg(SRTSOCKET u, char* buf, int len); + +SRT_API int64_t sendfile(SRTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile(SRTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); +SRT_API int64_t sendfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); +SRT_API int64_t recvfile2(SRTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); + +// select and selectEX are DEPRECATED; please use epoll. +SRT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); +SRT_API int selectEx(const std::vector& fds, std::vector* readfds, + std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); + +SRT_API int epoll_create(); +SRT_API int epoll_add_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_remove_usock(int eid, SRTSOCKET u); +SRT_API int epoll_remove_ssock(int eid, SYSSOCKET s); +SRT_API int epoll_update_usock(int eid, SRTSOCKET u, const int* events = NULL); +SRT_API int epoll_update_ssock(int eid, SYSSOCKET s, const int* events = NULL); +SRT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, + std::set* lrfds = NULL, std::set* wrfds = NULL); +SRT_API int epoll_wait2(int eid, SRTSOCKET* readfds, int* rnum, SRTSOCKET* writefds, int* wnum, int64_t msTimeOut, + SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL); +SRT_API int epoll_uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut); +SRT_API int epoll_release(int eid); +SRT_API ERRORINFO& getlasterror(); +SRT_API int getlasterror_code(); +SRT_API const char* getlasterror_desc(); +SRT_API int bstats(SRTSOCKET u, SRT_TRACEBSTATS* perf, bool clear = true); +SRT_API SRT_SOCKSTATUS getsockstate(SRTSOCKET u); + +} // namespace UDT + +// This is a log configuration used inside SRT. +// Applications using SRT, if they want to use the logging mechanism +// are free to create their own logger configuration objects for their +// own logger FA objects, or create their own. The object of this type +// is required to initialize the logger FA object. +namespace srt_logging { struct LogConfig; } +SRT_API extern srt_logging::LogConfig srt_logger_config; + +namespace srt +{ + +// This is a C++ SRT API extension. This is not a part of legacy UDT API. +SRT_API void setloglevel(srt_logging::LogLevel::type ll); +SRT_API void addlogfa(srt_logging::LogFA fa); +SRT_API void dellogfa(srt_logging::LogFA fa); +SRT_API void resetlogfa(std::set fas); +SRT_API void resetlogfa(const int* fara, size_t fara_size); +SRT_API void setlogstream(std::ostream& stream); +SRT_API void setloghandler(void* opaque, SRT_LOG_HANDLER_FN* handler); +SRT_API void setlogflags(int flags); + +SRT_API bool setstreamid(SRTSOCKET u, const std::string& sid); +SRT_API std::string getstreamid(SRTSOCKET u); + +// Namespace alias +namespace logging { + using namespace srt_logging; +} + +} + +// Planned deprecated removal: rel1.6.0 +// There's also no portable way possible to enforce a deprecation +// compiler warning, so leaving as is. +namespace UDT +{ + // Backward-compatible aliases, just for a case someone was using it. + using srt::setloglevel; + using srt::addlogfa; + using srt::dellogfa; + using srt::resetlogfa; + using srt::setlogstream; + using srt::setloghandler; + using srt::setlogflags; + using srt::setstreamid; + using srt::getstreamid; +} + + +#endif /* __cplusplus */ + +#endif diff --git a/thirdparty/include/srt/version.h b/thirdparty/include/srt/version.h new file mode 100755 index 0000000000000000000000000000000000000000..68f1e6a7bfff1d26723e51d6150cc30fe7e4b867 --- /dev/null +++ b/thirdparty/include/srt/version.h @@ -0,0 +1,34 @@ +/* + * SRT - Secure, Reliable, Transport + * Copyright (c) 2018 Haivision Systems Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +/***************************************************************************** +written by + Haivision Systems Inc. + *****************************************************************************/ + +#ifndef INC_SRT_VERSION_H +#define INC_SRT_VERSION_H + +// To construct version value +#define SRT_MAKE_VERSION(major, minor, patch) \ + ((patch) + ((minor)*0x100) + ((major)*0x10000)) +#define SRT_MAKE_VERSION_VALUE SRT_MAKE_VERSION + +#define SRT_VERSION_MAJOR 1 +#define SRT_VERSION_MINOR 4 +#define SRT_VERSION_PATCH 2 +/* #undef SRT_VERSION_BUILD */ + +#define SRT_VERSION_STRING "1.4.2" +#define SRT_VERSION_VALUE \ + SRT_MAKE_VERSION_VALUE( \ + SRT_VERSION_MAJOR, SRT_VERSION_MINOR, SRT_VERSION_PATCH ) + +#endif // INC_SRT_VERSION_H diff --git a/thirdparty/include/srt/win/syslog_defs.h b/thirdparty/include/srt/win/syslog_defs.h new file mode 100755 index 0000000000000000000000000000000000000000..7d83126412fc3e46a92c153256e3e0c86d5d6116 --- /dev/null +++ b/thirdparty/include/srt/win/syslog_defs.h @@ -0,0 +1,45 @@ +#ifndef INC_SRT_WINDOWS_SYSLOG_DEFS_H +#define INC_SRT_WINDOWS_SYSLOG_DEFS_H + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_PRIMASK 0x07 + +#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) + +#define LOG_KERN (0<<3) +#define LOG_USER (1<<3) +#define LOG_MAIL (2<<3) +#define LOG_DAEMON (3<<3) +#define LOG_AUTH (4<<3) +#define LOG_SYSLOG (5<<3) +#define LOG_LPR (6<<3) +#define LOG_NEWS (7<<3) +#define LOG_UUCP (8<<3) +#define LOG_CRON (9<<3) +#define LOG_AUTHPRIV (10<<3) +#define LOG_FTP (11<<3) + +/* Codes through 15 are reserved for system use */ +#define LOG_LOCAL0 (16<<3) +#define LOG_LOCAL1 (17<<3) +#define LOG_LOCAL2 (18<<3) +#define LOG_LOCAL3 (19<<3) +#define LOG_LOCAL4 (20<<3) +#define LOG_LOCAL5 (21<<3) +#define LOG_LOCAL6 (22<<3) +#define LOG_LOCAL7 (23<<3) + +#define LOG_NFACILITIES 24 +#define LOG_FACMASK 0x03f8 +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#endif diff --git a/thirdparty/include/srt/win/unistd.h b/thirdparty/include/srt/win/unistd.h new file mode 100755 index 0000000000000000000000000000000000000000..9c61cad8aa1d5ec306db4b8101bbe703e4f87ba1 --- /dev/null +++ b/thirdparty/include/srt/win/unistd.h @@ -0,0 +1,52 @@ +#ifndef _UNISTD_H +#define _UNISTD_H 1 + +/* This file intended to serve as a drop-in replacement for + * unistd.h on Windows + * Please add functionality as neeeded + */ + +#include +#include +//#include /* getopt at: https://gist.github.com/ashelly/7776712*/ +#include /* for getpid() and the exec..() family */ +#include /* for _getcwd() and _chdir() */ + +#define srandom srand +#define random rand + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +//#define X_OK 1 /* execute permission - unsupported in windows*/ +#define F_OK 0 /* Test for existence. */ + +#define access _access +#define dup2 _dup2 +#define execve _execve +#define ftruncate _chsize +#define unlink _unlink +#define fileno _fileno +#define getcwd _getcwd +#define chdir _chdir +#define isatty _isatty +#define lseek _lseek +/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ + +#define ssize_t int + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +/* should be in some equivalent to */ +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#endif /* unistd.h */ diff --git a/thirdparty/include/srt/win/wintime.h b/thirdparty/include/srt/win/wintime.h new file mode 100755 index 0000000000000000000000000000000000000000..ff1bc65de63573a120b45130f929695b567c055d --- /dev/null +++ b/thirdparty/include/srt/win/wintime.h @@ -0,0 +1,55 @@ +#ifndef INC_SRT_WIN_WINTIME +#define INC_SRT_WIN_WINTIME + +#include +#include +// HACK: This include is a workaround for a bug in the MinGW headers +// where pthread.h, which defines _POSIX_THREAD_SAFE_FUNCTIONS, +// has to be included before time.h so that time.h defines +// localtime_r correctly +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_MSC_VER) + #define SRTCOMPAT_WINTIME_STATIC_INLINE_DECL static inline +#else + // NOTE: MVC Does not like static inline for C functions in some versions. + // so just use static for MVC. + #define SRTCOMPAT_WINTIME_STATIC_INLINE_DECL static +#endif + +#ifndef _TIMEZONE_DEFINED /* also in sys/time.h */ +#define _TIMEZONE_DEFINED +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#endif + +void SRTCompat_timeradd( + struct timeval *a, struct timeval *b, struct timeval *result); +SRTCOMPAT_WINTIME_STATIC_INLINE_DECL void timeradd( + struct timeval *a, struct timeval *b, struct timeval *result) +{ + SRTCompat_timeradd(a, b, result); +} + +int SRTCompat_gettimeofday( + struct timeval* tp, struct timezone* tz); +SRTCOMPAT_WINTIME_STATIC_INLINE_DECL int gettimeofday( + struct timeval* tp, struct timezone* tz) +{ + return SRTCompat_gettimeofday(tp, tz); +} + +#undef SRTCOMPAT_WINTIME_STATIC_INLINE_DECL + +#ifdef __cplusplus +} +#endif + +#endif // INC_SRT_WIN_WINTIME diff --git a/thirdparty/include/uWebSockets/App.h b/thirdparty/include/uWebSockets/App.h new file mode 100644 index 0000000000000000000000000000000000000000..4da74e1d56973cc4ab1c6c10f2d3bab2f500900e --- /dev/null +++ b/thirdparty/include/uWebSockets/App.h @@ -0,0 +1,486 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_APP_H +#define UWS_APP_H + +#include + +namespace uWS { + /* Type queued up when publishing */ + struct TopicTreeMessage { + std::string message; + /*OpCode*/ int opCode; + bool compress; + }; + struct TopicTreeBigMessage { + std::string_view message; + /*OpCode*/ int opCode; + bool compress; + }; +} + +/* An app is a convenience wrapper of some of the most used fuctionalities and allows a + * builder-pattern kind of init. Apps operate on the implicit thread local Loop */ + +#include "HttpContext.h" +#include "HttpResponse.h" +#include "WebSocketContext.h" +#include "WebSocket.h" +#include "PerMessageDeflate.h" + +namespace uWS { + + /* This one matches us_socket_context_options_t but has default values */ + struct SocketContextOptions { + const char *key_file_name = nullptr; + const char *cert_file_name = nullptr; + const char *passphrase = nullptr; + const char *dh_params_file_name = nullptr; + const char *ca_file_name = nullptr; + int ssl_prefer_low_memory_usage = 0; + + /* Conversion operator used internally */ + operator struct us_socket_context_options_t() const { + struct us_socket_context_options_t socket_context_options; + memcpy(&socket_context_options, this, sizeof(SocketContextOptions)); + return socket_context_options; + } + }; + + static_assert(sizeof(struct us_socket_context_options_t) == sizeof(SocketContextOptions), "Mismatching uSockets/uWebSockets ABI"); + +template +struct TemplatedApp { +private: + /* The app always owns at least one http context, but creates websocket contexts on demand */ + HttpContext *httpContext; + /* WebSocketContexts are of differing type, but we as owners and creators must delete them correctly */ + std::vector> webSocketContextDeleters; + +public: + + TopicTree *topicTree = nullptr; + + /* Server name */ + TemplatedApp &&addServerName(std::string hostname_pattern, SocketContextOptions options = {}) { + + us_socket_context_add_server_name(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str(), options); + return std::move(*this); + } + + TemplatedApp &&removeServerName(std::string hostname_pattern) { + + us_socket_context_remove_server_name(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str()); + return std::move(*this); + } + + TemplatedApp &&missingServerName(MoveOnlyFunction handler) { + + if (!constructorFailed()) { + httpContext->getSocketContextData()->missingServerNameHandler = std::move(handler); + + us_socket_context_on_server_name(SSL, (struct us_socket_context_t *) httpContext, [](struct us_socket_context_t *context, const char *hostname) { + + /* This is the only requirements of being friends with HttpContextData */ + HttpContext *httpContext = (HttpContext *) context; + httpContext->getSocketContextData()->missingServerNameHandler(hostname); + }); + } + + return std::move(*this); + } + + /* Returns the SSL_CTX of this app, or nullptr. */ + void *getNativeHandle() { + return us_socket_context_get_native_handle(SSL, (struct us_socket_context_t *) httpContext); + } + + /* Attaches a "filter" function to track socket connections/disconnections */ + void filter(MoveOnlyFunction *, int)> &&filterHandler) { + httpContext->filter(std::move(filterHandler)); + } + + /* Publishes a message to all websocket contexts - conceptually as if publishing to the one single + * TopicTree of this app (technically there are many TopicTrees, however the concept is that one + * app has one conceptual Topic tree) */ + bool publish(std::string_view topic, std::string_view message, OpCode opCode, bool compress = false) { + /* Anything big bypasses corking efforts */ + if (message.length() >= LoopData::CORK_BUFFER_SIZE) { + return topicTree->publishBig(nullptr, topic, {message, opCode, compress}, [](Subscriber *s, TopicTreeBigMessage &message) { + auto *ws = (WebSocket *) s->user; + + /* Send will drain if needed */ + ws->send(message.message, (OpCode)message.opCode, message.compress); + }); + } else { + return topicTree->publish(nullptr, topic, {std::string(message), opCode, compress}); + } + } + + /* Returns number of subscribers for this topic, or 0 for failure. + * This function should probably be optimized a lot in future releases, + * it could be O(1) with a hash map of fullnames and their counts. */ + unsigned int numSubscribers(std::string_view topic) { + Topic *t = topicTree->lookupTopic(topic); + if (t) { + return (unsigned int) t->size(); + } + + return 0; + } + + ~TemplatedApp() { + /* Let's just put everything here */ + if (httpContext) { + httpContext->free(); + + /* Free all our webSocketContexts in a type less way */ + for (auto &webSocketContextDeleter : webSocketContextDeleters) { + webSocketContextDeleter(); + } + } + + /* Delete TopicTree */ + if (topicTree) { + delete topicTree; + + /* And unregister loop callbacks */ + /* We must unregister any loop post handler here */ + Loop::get()->removePostHandler(topicTree); + Loop::get()->removePreHandler(topicTree); + } + } + + /* Disallow copying, only move */ + TemplatedApp(const TemplatedApp &other) = delete; + + TemplatedApp(TemplatedApp &&other) { + /* Move HttpContext */ + httpContext = other.httpContext; + other.httpContext = nullptr; + + /* Move webSocketContextDeleters */ + webSocketContextDeleters = std::move(other.webSocketContextDeleters); + + /* Move TopicTree */ + topicTree = other.topicTree; + other.topicTree = nullptr; + } + + TemplatedApp(SocketContextOptions options = {}) { + httpContext = HttpContext::create(Loop::get(), options); + } + + bool constructorFailed() { + return !httpContext; + } + + template + struct WebSocketBehavior { + /* Disabled compression by default - probably a bad default */ + CompressOptions compression = DISABLED; + /* Maximum message size we can receive */ + unsigned int maxPayloadLength = 16 * 1024; + /* 2 minutes timeout is good */ + unsigned short idleTimeout = 120; + /* 64kb backpressure is probably good */ + unsigned int maxBackpressure = 64 * 1024; + bool closeOnBackpressureLimit = false; + /* This one depends on kernel timeouts and is a bad default */ + bool resetIdleTimeoutOnSend = false; + /* A good default, esp. for newcomers */ + bool sendPingsAutomatically = true; + /* Maximum socket lifetime in seconds before forced closure (defaults to disabled) */ + unsigned short maxLifetime = 0; + MoveOnlyFunction *, HttpRequest *, struct us_socket_context_t *)> upgrade = nullptr; + MoveOnlyFunction *)> open = nullptr; + MoveOnlyFunction *, std::string_view, OpCode)> message = nullptr; + MoveOnlyFunction *)> drain = nullptr; + MoveOnlyFunction *, std::string_view)> ping = nullptr; + MoveOnlyFunction *, std::string_view)> pong = nullptr; + MoveOnlyFunction *, int, std::string_view)> close = nullptr; + }; + + template + TemplatedApp &&ws(std::string pattern, WebSocketBehavior &&behavior) { + /* Don't compile if alignment rules cannot be satisfied */ + static_assert(alignof(UserData) <= LIBUS_EXT_ALIGNMENT, + "µWebSockets cannot satisfy UserData alignment requirements. You need to recompile µSockets with LIBUS_EXT_ALIGNMENT adjusted accordingly."); + + if (!httpContext) { + return std::move(*this); + } + + /* Terminate on misleading idleTimeout values */ + if (behavior.idleTimeout && behavior.idleTimeout < 8) { + std::cerr << "Error: idleTimeout must be either 0 or greater than 8!" << std::endl; + std::terminate(); + } + + if (behavior.idleTimeout % 4) { + std::cerr << "Warning: idleTimeout should be a multiple of 4!" << std::endl; + } + + /* If we don't have a TopicTree yet, create one now */ + if (!topicTree) { + + bool needsUncork = false; + topicTree = new TopicTree([needsUncork](Subscriber *s, TopicTreeMessage &message, TopicTree::IteratorFlags flags) mutable { + /* Subscriber's user is the socket */ + /* Unfortunately we need to cast is to PerSocketData = int + * since many different WebSocketContexts use the same + * TopicTree now */ + auto *ws = (WebSocket *) s->user; + + /* If this is the first message we try and cork */ + if (flags & TopicTree::IteratorFlags::FIRST) { + if (ws->canCork() && !ws->isCorked()) { + ((AsyncSocket *)ws)->cork(); + needsUncork = true; + } + } + + /* If we ever overstep maxBackpresure, exit immediately */ + if (WebSocket::SendStatus::DROPPED == ws->send(message.message, (OpCode)message.opCode, message.compress)) { + if (needsUncork) { + ((AsyncSocket *)ws)->uncork(); + needsUncork = false; + } + /* Stop draining */ + return true; + } + + /* If this is the last message we uncork if we are corked */ + if (flags & TopicTree::IteratorFlags::LAST) { + /* We should not uncork in all cases? */ + if (needsUncork) { + ((AsyncSocket *)ws)->uncork(); + } + } + + /* Success */ + return false; + }); + + /* And hook it up with the loop */ + /* We empty for both pre and post just to make sure */ + Loop::get()->addPostHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) { + /* Commit pub/sub batches every loop iteration */ + topicTree->drain(); + }); + + Loop::get()->addPreHandler(topicTree, [topicTree = topicTree](Loop */*loop*/) { + /* Commit pub/sub batches every loop iteration */ + topicTree->drain(); + }); + } + + /* Every route has its own websocket context with its own behavior and user data type */ + auto *webSocketContext = WebSocketContext::create(Loop::get(), (us_socket_context_t *) httpContext, topicTree); + + /* We need to clear this later on */ + webSocketContextDeleters.push_back([webSocketContext]() { + webSocketContext->free(); + }); + + /* Quick fix to disable any compression if set */ +#ifdef UWS_NO_ZLIB + behavior.compression = DISABLED; +#endif + + /* If we are the first one to use compression, initialize it */ + if (behavior.compression) { + LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, webSocketContext->getSocketContext())); + + /* Initialize loop's deflate inflate streams */ + if (!loopData->zlibContext) { + loopData->zlibContext = new ZlibContext; + loopData->inflationStream = new InflationStream; + loopData->deflationStream = new DeflationStream(CompressOptions::DEDICATED_COMPRESSOR); + } + } + + /* Copy all handlers */ + webSocketContext->getExt()->openHandler = std::move(behavior.open); + webSocketContext->getExt()->messageHandler = std::move(behavior.message); + webSocketContext->getExt()->drainHandler = std::move(behavior.drain); + webSocketContext->getExt()->closeHandler = std::move([closeHandler = std::move(behavior.close)](WebSocket *ws, int code, std::string_view message) mutable { + if (closeHandler) { + closeHandler(ws, code, message); + } + + /* Destruct user data after returning from close handler */ + ((UserData *) ws->getUserData())->~UserData(); + }); + webSocketContext->getExt()->pingHandler = std::move(behavior.ping); + webSocketContext->getExt()->pongHandler = std::move(behavior.pong); + + /* Copy settings */ + webSocketContext->getExt()->maxPayloadLength = behavior.maxPayloadLength; + webSocketContext->getExt()->maxBackpressure = behavior.maxBackpressure; + webSocketContext->getExt()->closeOnBackpressureLimit = behavior.closeOnBackpressureLimit; + webSocketContext->getExt()->resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend; + webSocketContext->getExt()->sendPingsAutomatically = behavior.sendPingsAutomatically; + webSocketContext->getExt()->compression = behavior.compression; + + /* Calculate idleTimeoutCompnents */ + webSocketContext->getExt()->calculateIdleTimeoutCompnents(behavior.idleTimeout); + + httpContext->onHttp("get", pattern, [webSocketContext, behavior = std::move(behavior)](auto *res, auto *req) mutable { + + /* If we have this header set, it's a websocket */ + std::string_view secWebSocketKey = req->getHeader("sec-websocket-key"); + if (secWebSocketKey.length() == 24) { + + /* Emit upgrade handler */ + if (behavior.upgrade) { + behavior.upgrade(res, req, (struct us_socket_context_t *) webSocketContext); + } else { + /* Default handler upgrades to WebSocket */ + std::string_view secWebSocketProtocol = req->getHeader("sec-websocket-protocol"); + std::string_view secWebSocketExtensions = req->getHeader("sec-websocket-extensions"); + + res->template upgrade({}, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, (struct us_socket_context_t *) webSocketContext); + } + + /* We are going to get uncorked by the Http get return */ + + /* We do not need to check for any close or shutdown here as we immediately return from get handler */ + + } else { + /* Tell the router that we did not handle this request */ + req->setYield(true); + } + }, true); + return std::move(*this); + } + + TemplatedApp &&get(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("get", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&post(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("post", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&options(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("options", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&del(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("delete", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&patch(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("patch", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&put(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("put", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&head(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("head", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&connect(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("connect", pattern, std::move(handler)); + } + return std::move(*this); + } + + TemplatedApp &&trace(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("trace", pattern, std::move(handler)); + } + return std::move(*this); + } + + /* This one catches any method */ + TemplatedApp &&any(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + if (httpContext) { + httpContext->onHttp("*", pattern, std::move(handler)); + } + return std::move(*this); + } + + /* Host, port, callback */ + TemplatedApp &&listen(std::string host, int port, MoveOnlyFunction &&handler) { + if (!host.length()) { + return listen(port, std::move(handler)); + } + handler(httpContext ? httpContext->listen(host.c_str(), port, 0) : nullptr); + return std::move(*this); + } + + /* Host, port, options, callback */ + TemplatedApp &&listen(std::string host, int port, int options, MoveOnlyFunction &&handler) { + if (!host.length()) { + return listen(port, options, std::move(handler)); + } + handler(httpContext ? httpContext->listen(host.c_str(), port, options) : nullptr); + return std::move(*this); + } + + /* Port, callback */ + TemplatedApp &&listen(int port, MoveOnlyFunction &&handler) { + handler(httpContext ? httpContext->listen(nullptr, port, 0) : nullptr); + return std::move(*this); + } + + /* Port, options, callback */ + TemplatedApp &&listen(int port, int options, MoveOnlyFunction &&handler) { + handler(httpContext ? httpContext->listen(nullptr, port, options) : nullptr); + return std::move(*this); + } + + TemplatedApp &&run() { + uWS::run(); + return std::move(*this); + } + +}; + +typedef TemplatedApp App; +typedef TemplatedApp SSLApp; + +} + +#endif // UWS_APP_H diff --git a/thirdparty/include/uWebSockets/AsyncSocket.h b/thirdparty/include/uWebSockets/AsyncSocket.h new file mode 100644 index 0000000000000000000000000000000000000000..c1fddd91915b1f7dbbc540d08a0fee0d7cecd3c5 --- /dev/null +++ b/thirdparty/include/uWebSockets/AsyncSocket.h @@ -0,0 +1,313 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_ASYNCSOCKET_H +#define UWS_ASYNCSOCKET_H + +/* This class implements async socket memory management strategies */ + +/* NOTE: Many unsigned/signed conversion warnings could be solved by moving from int length + * to unsigned length for everything to/from uSockets - this would however remove the opportunity + * to signal error with -1 (which is how the entire UNIX syscalling is built). */ + +#include +#include + +#include "libusockets.h" + +#include "LoopData.h" +#include "AsyncSocketData.h" + +namespace uWS { + + enum SendBufferAttribute { + NEEDS_NOTHING, + NEEDS_DRAIN, + NEEDS_UNCORK + }; + + template struct WebSocketContext; + +template +struct AsyncSocket { + /* This guy is promiscuous */ + template friend struct HttpContext; + template friend struct WebSocketContext; + template friend struct TemplatedApp; + template friend struct WebSocketContextData; + template friend struct TopicTree; + +protected: + /* Returns SSL pointer or FD as pointer */ + void *getNativeHandle() { + return us_socket_get_native_handle(SSL, (us_socket_t *) this); + } + + /* Get loop data for socket */ + LoopData *getLoopData() { + return (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) this))); + } + + /* Get socket extension */ + AsyncSocketData *getAsyncSocketData() { + return (AsyncSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + } + + /* Socket timeout */ + void timeout(unsigned int seconds) { + us_socket_timeout(SSL, (us_socket_t *) this, seconds); + } + + /* Shutdown socket without any automatic drainage */ + void shutdown() { + us_socket_shutdown(SSL, (us_socket_t *) this); + } + + /* Immediately close socket */ + us_socket_t *close() { + return us_socket_close(SSL, (us_socket_t *) this, 0, nullptr); + } + + void corkUnchecked() { + /* What if another socket is corked? */ + getLoopData()->corkedSocket = this; + } + + /* Cork this socket. Only one socket may ever be corked per-loop at any given time */ + void cork() { + /* Extra check for invalid corking of others */ + if (getLoopData()->corkOffset && getLoopData()->corkedSocket != this) { + std::cerr << "Error: Cork buffer must not be acquired without checking canCork!" << std::endl; + std::terminate(); + } + + /* What if another socket is corked? */ + getLoopData()->corkedSocket = this; + } + + /* Returns wheter we are corked or not */ + bool isCorked() { + return getLoopData()->corkedSocket == this; + } + + /* Returns whether we could cork (it is free) */ + bool canCork() { + return getLoopData()->corkedSocket == nullptr; + } + + /* Returns a suitable buffer for temporary assemblation of send data */ + std::pair getSendBuffer(size_t size) { + /* First step is to determine if we already have backpressure or not */ + LoopData *loopData = getLoopData(); + BackPressure &backPressure = getAsyncSocketData()->buffer; + size_t existingBackpressure = backPressure.length(); + if ((!existingBackpressure) && (isCorked() || canCork()) && (loopData->corkOffset + size < LoopData::CORK_BUFFER_SIZE)) { + /* Cork automatically if we can */ + if (isCorked()) { + char *sendBuffer = loopData->corkBuffer + loopData->corkOffset; + loopData->corkOffset += (unsigned int) size; + return {sendBuffer, SendBufferAttribute::NEEDS_NOTHING}; + } else { + cork(); + char *sendBuffer = loopData->corkBuffer + loopData->corkOffset; + loopData->corkOffset += (unsigned int) size; + return {sendBuffer, SendBufferAttribute::NEEDS_UNCORK}; + } + } else { + + /* If we are corked and there is already data in the cork buffer, + mark how much is ours and reset it */ + unsigned int ourCorkOffset = 0; + if (isCorked() && loopData->corkOffset) { + ourCorkOffset = loopData->corkOffset; + loopData->corkOffset = 0; + } + + /* Fallback is to use the backpressure as buffer */ + backPressure.resize(ourCorkOffset + existingBackpressure + size); + + /* And copy corkbuffer in front */ + memcpy((char *) backPressure.data() + existingBackpressure, loopData->corkBuffer, ourCorkOffset); + + return {(char *) backPressure.data() + ourCorkOffset + existingBackpressure, SendBufferAttribute::NEEDS_DRAIN}; + } + } + + /* Returns the user space backpressure. */ + unsigned int getBufferedAmount() { + /* We return the actual amount of bytes in backbuffer, including pendingRemoval */ + return (unsigned int) getAsyncSocketData()->buffer.totalLength(); + } + + /* Returns the text representation of an IPv4 or IPv6 address */ + std::string_view addressAsText(std::string_view binary) { + static thread_local char buf[64]; + int ipLength = 0; + + if (!binary.length()) { + return {}; + } + + unsigned char *b = (unsigned char *) binary.data(); + + if (binary.length() == 4) { + ipLength = sprintf(buf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]); + } else { + ipLength = sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], + b[12], b[13], b[14], b[15]); + } + + return {buf, (unsigned int) ipLength}; + } + + /* Returns the remote IP address or empty string on failure */ + std::string_view getRemoteAddress() { + static thread_local char buf[16]; + int ipLength = 16; + us_socket_remote_address(SSL, (us_socket_t *) this, buf, &ipLength); + return std::string_view(buf, (unsigned int) ipLength); + } + + /* Returns the text representation of IP */ + std::string_view getRemoteAddressAsText() { + return addressAsText(getRemoteAddress()); + } + + /* Write in three levels of prioritization: cork-buffer, syscall, socket-buffer. Always drain if possible. + * Returns pair of bytes written (anywhere) and wheter or not this call resulted in the polling for + * writable (or we are in a state that implies polling for writable). */ + std::pair write(const char *src, int length, bool optionally = false, int nextLength = 0) { + /* Fake success if closed, simple fix to allow uncork of closed socket to succeed */ + if (us_socket_is_closed(SSL, (us_socket_t *) this)) { + return {length, false}; + } + + LoopData *loopData = getLoopData(); + AsyncSocketData *asyncSocketData = getAsyncSocketData(); + + /* We are limited if we have a per-socket buffer */ + if (asyncSocketData->buffer.length()) { + /* Write off as much as we can */ + int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), (int) asyncSocketData->buffer.length(), /*nextLength != 0 | */length); + + /* On failure return, otherwise continue down the function */ + if ((unsigned int) written < asyncSocketData->buffer.length()) { + + /* Update buffering (todo: we can do better here if we keep track of what happens to this guy later on) */ + asyncSocketData->buffer.erase((unsigned int) written); + + if (optionally) { + /* Thankfully we can exit early here */ + return {0, true}; + } else { + /* This path is horrible and points towards erroneous usage */ + asyncSocketData->buffer.append(src, (unsigned int) length); + + return {length, true}; + } + } + + /* At this point we simply have no buffer and can continue as normal */ + asyncSocketData->buffer.clear(); + } + + if (length) { + if (loopData->corkedSocket == this) { + /* We are corked */ + if (LoopData::CORK_BUFFER_SIZE - loopData->corkOffset >= (unsigned int) length) { + /* If the entire chunk fits in cork buffer */ + memcpy(loopData->corkBuffer + loopData->corkOffset, src, (unsigned int) length); + loopData->corkOffset += (unsigned int) length; + /* Fall through to default return */ + } else { + /* Strategy differences between SSL and non-SSL regarding syscall minimizing */ + if constexpr (SSL) { + /* Cork up as much as we can */ + unsigned int stripped = LoopData::CORK_BUFFER_SIZE - loopData->corkOffset; + memcpy(loopData->corkBuffer + loopData->corkOffset, src, stripped); + loopData->corkOffset = LoopData::CORK_BUFFER_SIZE; + + auto [written, failed] = uncork(src + stripped, length - (int) stripped, optionally); + return {written + (int) stripped, failed}; + } + + /* For non-SSL we take the penalty of two syscalls */ + return uncork(src, length, optionally); + } + } else { + /* We are not corked */ + int written = us_socket_write(SSL, (us_socket_t *) this, src, length, nextLength != 0); + + /* Did we fail? */ + if (written < length) { + /* If the write was optional then just bail out */ + if (optionally) { + return {written, true}; + } + + /* Fall back to worst possible case (should be very rare for HTTP) */ + /* At least we can reserve room for next chunk if we know it up front */ + if (nextLength) { + asyncSocketData->buffer.reserve(asyncSocketData->buffer.length() + (size_t) (length - written + nextLength)); + } + + /* Buffer this chunk */ + asyncSocketData->buffer.append(src + written, (size_t) (length - written)); + + /* Return the failure */ + return {length, true}; + } + /* Fall through to default return */ + } + } + + /* Default fall through return */ + return {length, false}; + } + + /* Uncork this socket and flush or buffer any corked and/or passed data. It is essential to remember doing this. */ + /* It does NOT count bytes written from cork buffer (they are already accounted for in the write call responsible for its corking)! */ + std::pair uncork(const char *src = nullptr, int length = 0, bool optionally = false) { + LoopData *loopData = getLoopData(); + + if (loopData->corkedSocket == this) { + loopData->corkedSocket = nullptr; + + if (loopData->corkOffset) { + /* Corked data is already accounted for via its write call */ + auto [written, failed] = write(loopData->corkBuffer, (int) loopData->corkOffset, false, length); + loopData->corkOffset = 0; + + if (failed) { + /* We do not need to care for buffering here, write does that */ + return {0, true}; + } + } + + /* We should only return with new writes, not things written to cork already */ + return write(src, length, optionally, 0); + } else { + /* We are not even corked! */ + return {0, false}; + } + } +}; + +} + +#endif // UWS_ASYNCSOCKET_H diff --git a/thirdparty/include/uWebSockets/AsyncSocketData.h b/thirdparty/include/uWebSockets/AsyncSocketData.h new file mode 100644 index 0000000000000000000000000000000000000000..b72b2c1015022c9fadee8eb40a24a61a45802f14 --- /dev/null +++ b/thirdparty/include/uWebSockets/AsyncSocketData.h @@ -0,0 +1,87 @@ +/* + * Authored by Alex Hultman, 2018-2021. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_ASYNCSOCKETDATA_H +#define UWS_ASYNCSOCKETDATA_H + +#include + +namespace uWS { + +struct BackPressure { + std::string buffer; + unsigned int pendingRemoval = 0; + BackPressure(BackPressure &&other) { + buffer = std::move(other.buffer); + pendingRemoval = other.pendingRemoval; + } + BackPressure() = default; + void append(const char *data, size_t length) { + buffer.append(data, length); + } + void erase(unsigned int length) { + pendingRemoval += length; + /* Always erase a minimum of 1/32th the current backpressure */ + if (pendingRemoval > (buffer.length() >> 5)) { + buffer.erase(0, pendingRemoval); + pendingRemoval = 0; + } + } + size_t length() { + return buffer.length() - pendingRemoval; + } + void clear() { + pendingRemoval = 0; + buffer.clear(); + } + void reserve(size_t length) { + buffer.reserve(length + pendingRemoval); + } + void resize(size_t length) { + buffer.resize(length + pendingRemoval); + } + const char *data() { + return buffer.data() + pendingRemoval; + } + size_t size() { + return length(); + } + /* The total length, incuding pending removal */ + size_t totalLength() { + return buffer.length(); + } +}; + +/* Depending on how we want AsyncSocket to function, this will need to change */ + +template +struct AsyncSocketData { + /* This will do for now */ + BackPressure buffer; + + /* Allow move constructing us */ + AsyncSocketData(BackPressure &&backpressure) : buffer(std::move(backpressure)) { + + } + + /* Or emppty */ + AsyncSocketData() = default; +}; + +} + +#endif // UWS_ASYNCSOCKETDATA_H diff --git a/thirdparty/include/uWebSockets/BloomFilter.h b/thirdparty/include/uWebSockets/BloomFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..95ced77d70df77324514bcdba8715e88172dc378 --- /dev/null +++ b/thirdparty/include/uWebSockets/BloomFilter.h @@ -0,0 +1,65 @@ +/* + * Authored by Alex Hultman, 2018-2019. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_BLOOMFILTER_H +#define UWS_BLOOMFILTER_H + +/* This filter has a decently low amount of false positives for the + * standard and non-standard common request headers */ + +#include +#include + +namespace uWS { + +struct BloomFilter { +private: + std::bitset<512> filter; + + unsigned int hash1(std::string_view key) { + return ((size_t)key[key.length() - 1] - (key.length() << 3)) & 511; + } + + unsigned int hash2(std::string_view key) { + return (((size_t)key[0] + (key.length() << 4)) & 511); + } + + unsigned int hash3(std::string_view key) { + return ((unsigned int)key[key.length() - 2] - 97 - (key.length() << 5)) & 511; + } + +public: + bool mightHave(std::string_view key) { + return filter.test(hash1(key)) && filter.test(hash2(key)) && (key.length() < 2 || filter.test(hash3(key))); + } + + void add(std::string_view key) { + filter.set(hash1(key)); + filter.set(hash2(key)); + if (key.length() >= 2) { + filter.set(hash3(key)); + } + } + + void reset() { + filter.reset(); + } +}; + +} + +#endif // UWS_BLOOMFILTER_H \ No newline at end of file diff --git a/thirdparty/include/uWebSockets/HttpContext.h b/thirdparty/include/uWebSockets/HttpContext.h new file mode 100644 index 0000000000000000000000000000000000000000..70a74e1e16339b09bb258a5bd819a363850b8150 --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpContext.h @@ -0,0 +1,435 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPCONTEXT_H +#define UWS_HTTPCONTEXT_H + +/* This class defines the main behavior of HTTP and emits various events */ + +#include "Loop.h" +#include "HttpContextData.h" +#include "HttpResponseData.h" +#include "AsyncSocket.h" +#include "WebSocketData.h" + +#include +#include +#include "MoveOnlyFunction.h" + +namespace uWS { +template struct HttpResponse; + +template +struct HttpContext { + template friend struct TemplatedApp; + template friend struct HttpResponse; +private: + HttpContext() = delete; + + /* Maximum delay allowed until an HTTP connection is terminated due to outstanding request or rejected data (slow loris protection) */ + static const int HTTP_IDLE_TIMEOUT_S = 10; + + us_socket_context_t *getSocketContext() { + return (us_socket_context_t *) this; + } + + static us_socket_context_t *getSocketContext(us_socket_t *s) { + return (us_socket_context_t *) us_socket_context(SSL, s); + } + + HttpContextData *getSocketContextData() { + return (HttpContextData *) us_socket_context_ext(SSL, getSocketContext()); + } + + static HttpContextData *getSocketContextDataS(us_socket_t *s) { + return (HttpContextData *) us_socket_context_ext(SSL, getSocketContext(s)); + } + + /* Init the HttpContext by registering libusockets event handlers */ + HttpContext *init() { + /* Handle socket connections */ + us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int /*is_client*/, char */*ip*/, int /*ip_length*/) { + /* Any connected socket should timeout until it has a request */ + us_socket_timeout(SSL, s, HTTP_IDLE_TIMEOUT_S); + + /* Init socket ext */ + new (us_socket_ext(SSL, s)) HttpResponseData; + + /* Call filter */ + HttpContextData *httpContextData = getSocketContextDataS(s); + for (auto &f : httpContextData->filterHandlers) { + f((HttpResponse *) s, 1); + } + + return s; + }); + + /* Handle socket disconnections */ + us_socket_context_on_close(SSL, getSocketContext(), [](us_socket_t *s, int /*code*/, void */*reason*/) { + /* Get socket ext */ + HttpResponseData *httpResponseData = (HttpResponseData *) us_socket_ext(SSL, s); + + /* Call filter */ + HttpContextData *httpContextData = getSocketContextDataS(s); + for (auto &f : httpContextData->filterHandlers) { + f((HttpResponse *) s, -1); + } + + /* Signal broken HTTP request only if we have a pending request */ + if (httpResponseData->onAborted) { + httpResponseData->onAborted(); + } + + /* Destruct socket ext */ + httpResponseData->~HttpResponseData(); + + return s; + }); + + /* Handle HTTP data streams */ + us_socket_context_on_data(SSL, getSocketContext(), [](us_socket_t *s, char *data, int length) { + + // total overhead is about 210k down to 180k + // ~210k req/sec is the original perf with write in data + // ~200k req/sec is with cork and formatting + // ~190k req/sec is with http parsing + // ~180k - 190k req/sec is with varying routing + + HttpContextData *httpContextData = getSocketContextDataS(s); + + /* Do not accept any data while in shutdown state */ + if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) { + return s; + } + + HttpResponseData *httpResponseData = (HttpResponseData *) us_socket_ext(SSL, s); + + /* Cork this socket */ + ((AsyncSocket *) s)->cork(); + + /* Mark that we are inside the parser now */ + httpContextData->isParsingHttp = true; + + // clients need to know the cursor after http parse, not servers! + // how far did we read then? we need to know to continue with websocket parsing data? or? + + void *proxyParser = nullptr; +#ifdef UWS_WITH_PROXY + proxyParser = &httpResponseData->proxyParser; +#endif + + /* The return value is entirely up to us to interpret. The HttpParser only care for whether the returned value is DIFFERENT or not from passed user */ + void *returnedSocket = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * { + /* For every request we reset the timeout and hang until user makes action */ + /* Warning: if we are in shutdown state, resetting the timer is a security issue! */ + us_socket_timeout(SSL, (us_socket_t *) s, 0); + + /* Reset httpResponse */ + HttpResponseData *httpResponseData = (HttpResponseData *) us_socket_ext(SSL, (us_socket_t *) s); + httpResponseData->offset = 0; + + /* Are we not ready for another request yet? Terminate the connection. */ + if (httpResponseData->state & HttpResponseData::HTTP_RESPONSE_PENDING) { + us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); + return nullptr; + } + + /* Mark pending request and emit it */ + httpResponseData->state = HttpResponseData::HTTP_RESPONSE_PENDING; + + /* Mark this response as connectionClose if ancient or connection: close */ + if (httpRequest->isAncient() || httpRequest->getHeader("connection").length() == 5) { + httpResponseData->state |= HttpResponseData::HTTP_CONNECTION_CLOSE; + } + + /* Route the method and URL */ + httpContextData->router.getUserData() = {(HttpResponse *) s, httpRequest}; + if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) { + /* We have to force close this socket as we have no handler for it */ + us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); + return nullptr; + } + + /* First of all we need to check if this socket was deleted due to upgrade */ + if (httpContextData->upgradedWebSocket) { + /* We differ between closed and upgraded below */ + return nullptr; + } + + /* Was the socket closed? */ + if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) { + return nullptr; + } + + /* We absolutely have to terminate parsing if shutdown */ + if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) { + return nullptr; + } + + /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */ + if (!((HttpResponse *) s)->hasResponded() && !httpResponseData->onAborted) { + /* Throw exception here? */ + std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl; + std::terminate(); + } + + /* If we have not responded and we have a data handler, we need to timeout to enfore client sending the data */ + if (!((HttpResponse *) s)->hasResponded() && httpResponseData->inStream) { + us_socket_timeout(SSL, (us_socket_t *) s, HTTP_IDLE_TIMEOUT_S); + } + + /* Continue parsing */ + return s; + + }, [httpResponseData](void *user, std::string_view data, bool fin) -> void * { + /* We always get an empty chunk even if there is no data */ + if (httpResponseData->inStream) { + + /* Todo: can this handle timeout for non-post as well? */ + if (fin) { + /* If we just got the last chunk (or empty chunk), disable timeout */ + us_socket_timeout(SSL, (struct us_socket_t *) user, 0); + } else { + /* We still have some more data coming in later, so reset timeout */ + us_socket_timeout(SSL, (struct us_socket_t *) user, HTTP_IDLE_TIMEOUT_S); + } + + /* We might respond in the handler, so do not change timeout after this */ + httpResponseData->inStream(data, fin); + + /* Was the socket closed? */ + if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) { + return nullptr; + } + + /* We absolutely have to terminate parsing if shutdown */ + if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) { + return nullptr; + } + + /* If we were given the last data chunk, reset data handler to ensure following + * requests on the same socket won't trigger any previously registered behavior */ + if (fin) { + httpResponseData->inStream = nullptr; + } + } + return user; + }, [](void *user) { + /* Close any socket on HTTP errors */ + us_socket_close(SSL, (us_socket_t *) user, 0, nullptr); + return nullptr; + }); + + /* Mark that we are no longer parsing Http */ + httpContextData->isParsingHttp = false; + + /* We need to uncork in all cases, except for nullptr (closed socket, or upgraded socket) */ + if (returnedSocket != nullptr) { + /* Timeout on uncork failure */ + auto [written, failed] = ((AsyncSocket *) returnedSocket)->uncork(); + if (failed) { + /* All Http sockets timeout by this, and this behavior match the one in HttpResponse::cork */ + /* Warning: both HTTP_IDLE_TIMEOUT_S and HTTP_TIMEOUT_S are 10 seconds and both are used the same */ + ((AsyncSocket *) s)->timeout(HTTP_IDLE_TIMEOUT_S); + } + + /* We need to check if we should close this socket here now */ + if (httpResponseData->state & HttpResponseData::HTTP_CONNECTION_CLOSE) { + if ((httpResponseData->state & HttpResponseData::HTTP_RESPONSE_PENDING) == 0) { + if (((AsyncSocket *) s)->getBufferedAmount() == 0) { + ((AsyncSocket *) s)->shutdown(); + /* We need to force close after sending FIN since we want to hinder + * clients from keeping to send their huge data */ + ((AsyncSocket *) s)->close(); + } + } + } + + return (us_socket_t *) returnedSocket; + } + + /* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */ + if (httpContextData->upgradedWebSocket) { + /* This path is only for upgraded websockets */ + AsyncSocket *asyncSocket = (AsyncSocket *) httpContextData->upgradedWebSocket; + + /* Uncork here as well (note: what if we failed to uncork and we then pub/sub before we even upgraded?) */ + auto [written, failed] = asyncSocket->uncork(); + + /* If we succeeded in uncorking, check if we have sent WebSocket FIN */ + if (!failed) { + WebSocketData *webSocketData = (WebSocketData *) asyncSocket->getAsyncSocketData(); + if (webSocketData->isShuttingDown) { + /* In that case, also send TCP FIN (this is similar to what we have in ws drain handler) */ + asyncSocket->shutdown(); + } + } + + /* Reset upgradedWebSocket before we return */ + httpContextData->upgradedWebSocket = nullptr; + + /* Return the new upgraded websocket */ + return (us_socket_t *) asyncSocket; + } + + /* It is okay to uncork a closed socket and we need to */ + ((AsyncSocket *) s)->uncork(); + + /* We cannot return nullptr to the underlying stack in any case */ + return s; + }); + + /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */ + us_socket_context_on_writable(SSL, getSocketContext(), [](us_socket_t *s) { + + AsyncSocket *asyncSocket = (AsyncSocket *) s; + HttpResponseData *httpResponseData = (HttpResponseData *) asyncSocket->getAsyncSocketData(); + + /* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */ + if (httpResponseData->onWritable) { + /* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */ + us_socket_timeout(SSL, s, 0); + + /* We expect the developer to return whether or not write was successful (true). + * If write was never called, the developer should still return true so that we may drain. */ + bool success = httpResponseData->onWritable(httpResponseData->offset); + + /* The developer indicated that their onWritable failed. */ + if (!success) { + /* Skip testing if we can drain anything since that might perform an extra syscall */ + return s; + } + + /* We don't want to fall through since we don't want to mess with timeout. + * It makes little sense to drain any backpressure when the user has registered onWritable. */ + return s; + } + + /* Drain any socket buffer, this might empty our backpressure and thus finish the request */ + /*auto [written, failed] = */asyncSocket->write(nullptr, 0, true, 0); + + /* Should we close this connection after a response - and is this response really done? */ + if (httpResponseData->state & HttpResponseData::HTTP_CONNECTION_CLOSE) { + if ((httpResponseData->state & HttpResponseData::HTTP_RESPONSE_PENDING) == 0) { + if (asyncSocket->getBufferedAmount() == 0) { + asyncSocket->shutdown(); + /* We need to force close after sending FIN since we want to hinder + * clients from keeping to send their huge data */ + asyncSocket->close(); + } + } + } + + /* Expect another writable event, or another request within the timeout */ + asyncSocket->timeout(HTTP_IDLE_TIMEOUT_S); + + return s; + }); + + /* Handle FIN, HTTP does not support half-closed sockets, so simply close */ + us_socket_context_on_end(SSL, getSocketContext(), [](us_socket_t *s) { + + /* We do not care for half closed sockets */ + AsyncSocket *asyncSocket = (AsyncSocket *) s; + return asyncSocket->close(); + + }); + + /* Handle socket timeouts, simply close them so to not confuse client with FIN */ + us_socket_context_on_timeout(SSL, getSocketContext(), [](us_socket_t *s) { + + /* Force close rather than gracefully shutdown and risk confusing the client with a complete download */ + AsyncSocket *asyncSocket = (AsyncSocket *) s; + return asyncSocket->close(); + + }); + + return this; + } + +public: + /* Construct a new HttpContext using specified loop */ + static HttpContext *create(Loop *loop, us_socket_context_options_t options = {}) { + HttpContext *httpContext; + + httpContext = (HttpContext *) us_create_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData), options); + + if (!httpContext) { + return nullptr; + } + + /* Init socket context data */ + new ((HttpContextData *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData(); + return httpContext->init(); + } + + /* Destruct the HttpContext, it does not follow RAII */ + void free() { + /* Destruct socket context data */ + HttpContextData *httpContextData = getSocketContextData(); + httpContextData->~HttpContextData(); + + /* Free the socket context in whole */ + us_socket_context_free(SSL, getSocketContext()); + } + + void filter(MoveOnlyFunction *, int)> &&filterHandler) { + getSocketContextData()->filterHandlers.emplace_back(std::move(filterHandler)); + } + + /* Register an HTTP route handler acording to URL pattern */ + void onHttp(std::string method, std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler, bool upgrade = false) { + HttpContextData *httpContextData = getSocketContextData(); + + /* Todo: This is ugly, fix */ + std::vector methods; + if (method == "*") { + methods = httpContextData->router.methods; + } else { + methods = {method}; + } + + httpContextData->router.add(methods, pattern, [handler = std::move(handler)](auto *r) mutable { + auto user = r->getUserData(); + user.httpRequest->setYield(false); + user.httpRequest->setParameters(r->getParameters()); + + /* Middleware? Automatically respond to expectations */ + std::string_view expect = user.httpRequest->getHeader("expect"); + if (expect.length() && expect == "100-continue") { + user.httpResponse->writeContinue(); + } + + handler(user.httpResponse, user.httpRequest); + + /* If any handler yielded, the router will keep looking for a suitable handler. */ + if (user.httpRequest->getYield()) { + return false; + } + return true; + }, method == "*" ? httpContextData->router.LOW_PRIORITY : (upgrade ? httpContextData->router.HIGH_PRIORITY : httpContextData->router.MEDIUM_PRIORITY)); + } + + /* Listen to port using this HttpContext */ + us_listen_socket_t *listen(const char *host, int port, int options) { + return us_socket_context_listen(SSL, getSocketContext(), host, port, options, sizeof(HttpResponseData)); + } +}; + +} + +#endif // UWS_HTTPCONTEXT_H diff --git a/thirdparty/include/uWebSockets/HttpContextData.h b/thirdparty/include/uWebSockets/HttpContextData.h new file mode 100644 index 0000000000000000000000000000000000000000..9375994ba688746f6384d17732c32b76cc32b6ed --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpContextData.h @@ -0,0 +1,52 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPCONTEXTDATA_H +#define UWS_HTTPCONTEXTDATA_H + +#include "HttpRouter.h" + +#include +#include "MoveOnlyFunction.h" + +namespace uWS { +template struct HttpResponse; +struct HttpRequest; + +template +struct alignas(16) HttpContextData { + template friend struct HttpContext; + template friend struct HttpResponse; + template friend struct TemplatedApp; +private: + std::vector *, int)>> filterHandlers; + + MoveOnlyFunction missingServerNameHandler; + + struct RouterData { + HttpResponse *httpResponse; + HttpRequest *httpRequest; + }; + + HttpRouter router; + void *upgradedWebSocket = nullptr; + bool isParsingHttp = false; +}; + +} + +#endif // UWS_HTTPCONTEXTDATA_H diff --git a/thirdparty/include/uWebSockets/HttpParser.h b/thirdparty/include/uWebSockets/HttpParser.h new file mode 100644 index 0000000000000000000000000000000000000000..8e3333583c32dd538eda8bb57488c999f5168c63 --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpParser.h @@ -0,0 +1,391 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPPARSER_H +#define UWS_HTTPPARSER_H + +// todo: HttpParser is in need of a few clean-ups and refactorings + +/* The HTTP parser is an independent module subject to unit testing / fuzz testing */ + +#include +#include +#include +#include "MoveOnlyFunction.h" + +#include "BloomFilter.h" +#include "ProxyParser.h" +#include "QueryParser.h" + +namespace uWS { + +/* We require at least this much post padding */ +static const unsigned int MINIMUM_HTTP_POST_PADDING = 32; + +struct HttpRequest { + + friend struct HttpParser; + +private: + const static int MAX_HEADERS = 50; + struct Header { + std::string_view key, value; + } headers[MAX_HEADERS]; + bool ancientHttp; + unsigned int querySeparator; + bool didYield; + BloomFilter bf; + std::pair currentParameters; + +public: + bool isAncient() { + return ancientHttp; + } + + bool getYield() { + return didYield; + } + + /* Iteration over headers (key, value) */ + struct HeaderIterator { + Header *ptr; + + bool operator!=(const HeaderIterator &other) const { + /* Comparison with end is a special case */ + if (ptr != other.ptr) { + return other.ptr || ptr->key.length(); + } + return false; + } + + HeaderIterator &operator++() { + ptr++; + return *this; + } + + std::pair operator*() const { + return {ptr->key, ptr->value}; + } + }; + + HeaderIterator begin() { + return {headers + 1}; + } + + HeaderIterator end() { + return {nullptr}; + } + + /* If you do not want to handle this route */ + void setYield(bool yield) { + didYield = yield; + } + + std::string_view getHeader(std::string_view lowerCasedHeader) { + if (bf.mightHave(lowerCasedHeader)) { + for (Header *h = headers; (++h)->key.length(); ) { + if (h->key.length() == lowerCasedHeader.length() && !strncmp(h->key.data(), lowerCasedHeader.data(), lowerCasedHeader.length())) { + return h->value; + } + } + } + return std::string_view(nullptr, 0); + } + + std::string_view getUrl() { + return std::string_view(headers->value.data(), querySeparator); + } + + std::string_view getMethod() { + return std::string_view(headers->key.data(), headers->key.length()); + } + + /* Returns the raw querystring as a whole, still encoded */ + std::string_view getQuery() { + if (querySeparator < headers->value.length()) { + /* Strip the initial ? */ + return std::string_view(headers->value.data() + querySeparator + 1, headers->value.length() - querySeparator - 1); + } else { + return std::string_view(nullptr, 0); + } + } + + /* Finds and decodes the URI component. */ + std::string_view getQuery(std::string_view key) { + /* Raw querystring including initial '?' sign */ + std::string_view queryString = std::string_view(headers->value.data() + querySeparator, headers->value.length() - querySeparator); + + return getDecodedQueryValue(key, queryString); + } + + void setParameters(std::pair parameters) { + currentParameters = parameters; + } + + std::string_view getParameter(unsigned short index) { + if (currentParameters.first < (int) index) { + return {}; + } else { + return currentParameters.second[index]; + } + } + +}; + +struct HttpParser { + +private: + std::string fallback; + unsigned int remainingStreamingBytes = 0; + + const size_t MAX_FALLBACK_SIZE = 1024 * 4; + + static unsigned int toUnsignedInteger(std::string_view str) { + unsigned int unsignedIntegerValue = 0; + for (char c : str) { + unsignedIntegerValue = unsignedIntegerValue * 10u + ((unsigned int) c - (unsigned int) '0'); + } + return unsignedIntegerValue; + } + + static unsigned int getHeaders(char *postPaddedBuffer, char *end, struct HttpRequest::Header *headers, void *reserved) { + char *preliminaryKey, *preliminaryValue, *start = postPaddedBuffer; + + #ifdef UWS_WITH_PROXY + /* ProxyParser is passed as reserved parameter */ + ProxyParser *pp = (ProxyParser *) reserved; + + /* Parse PROXY protocol */ + auto [done, offset] = pp->parse({start, (size_t) (end - postPaddedBuffer)}); + if (!done) { + /* We do not reset the ProxyParser (on filure) since it is tied to this + * connection, which is really only supposed to ever get one PROXY frame + * anyways. We do however allow multiple PROXY frames to be sent (overwrites former). */ + return 0; + } else { + /* We have consumed this data so skip it */ + start += offset; + } + #else + /* This one is unused */ + (void) reserved; + #endif + + /* It is critical for fallback buffering logic that we only return with success + * if we managed to parse a complete HTTP request (minus data). Returning success + * for PROXY means we can end up succeeding, yet leaving bytes in the fallback buffer + * which is then removed, and our counters to flip due to overflow and we end up with a crash */ + + for (unsigned int i = 0; i < HttpRequest::MAX_HEADERS; i++) { + for (preliminaryKey = postPaddedBuffer; (*postPaddedBuffer != ':') & (*postPaddedBuffer > 32); *(postPaddedBuffer++) |= 32); + if (*postPaddedBuffer == '\r') { + if ((postPaddedBuffer != end) & (postPaddedBuffer[1] == '\n') & (i > 0)) { + headers->key = std::string_view(nullptr, 0); + return (unsigned int) ((postPaddedBuffer + 2) - start); + } else { + return 0; + } + } else { + headers->key = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey)); + for (postPaddedBuffer++; (*postPaddedBuffer == ':' || *postPaddedBuffer < 33) && *postPaddedBuffer != '\r'; postPaddedBuffer++); + preliminaryValue = postPaddedBuffer; + postPaddedBuffer = (char *) memchr(postPaddedBuffer, '\r', (size_t) (end - postPaddedBuffer)); + if (postPaddedBuffer && postPaddedBuffer[1] == '\n') { + headers->value = std::string_view(preliminaryValue, (size_t) (postPaddedBuffer - preliminaryValue)); + postPaddedBuffer += 2; + headers++; + } else { + return 0; + } + } + } + return 0; + } + + // the only caller of getHeaders + template + std::pair fenceAndConsumePostPadded(char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction &requestHandler, MoveOnlyFunction &dataHandler) { + + /* How much data we CONSUMED (to throw away) */ + unsigned int consumedTotal = 0; + + /* Fence one byte past end of our buffer (buffer has post padded margins) */ + data[length] = '\r'; + + for (unsigned int consumed; length && (consumed = getHeaders(data, data + length, req->headers, reserved)); ) { + data += consumed; + length -= consumed; + consumedTotal += consumed; + + /* Store HTTP version (ancient 1.0 or 1.1) */ + req->ancientHttp = req->headers->value.length() && (req->headers->value[req->headers->value.length() - 1] == '0'); + + /* Strip away tail of first "header value" aka URL */ + req->headers->value = std::string_view(req->headers->value.data(), (size_t) std::max(0, (int) req->headers->value.length() - 9)); + + /* Add all headers to bloom filter */ + req->bf.reset(); + for (HttpRequest::Header *h = req->headers; (++h)->key.length(); ) { + req->bf.add(h->key); + } + + /* Parse query */ + const char *querySeparatorPtr = (const char *) memchr(req->headers->value.data(), '?', req->headers->value.length()); + req->querySeparator = (unsigned int) ((querySeparatorPtr ? querySeparatorPtr : req->headers->value.data() + req->headers->value.length()) - req->headers->value.data()); + + /* If returned socket is not what we put in we need + * to break here as we either have upgraded to + * WebSockets or otherwise closed the socket. */ + void *returnedUser = requestHandler(user, req); + if (returnedUser != user) { + /* We are upgraded to WebSocket or otherwise broken */ + return {consumedTotal, returnedUser}; + } + + // todo: do not check this for GET (get should not have a body) + // todo: also support reading chunked streams + std::string_view contentLengthString = req->getHeader("content-length"); + if (contentLengthString.length()) { + remainingStreamingBytes = toUnsignedInteger(contentLengthString); + + if (!CONSUME_MINIMALLY) { + unsigned int emittable = std::min(remainingStreamingBytes, length); + dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes); + remainingStreamingBytes -= emittable; + + data += emittable; + length -= emittable; + consumedTotal += emittable; + } + } else { + /* Still emit an empty data chunk to signal no data */ + dataHandler(user, {}, true); + } + + if (CONSUME_MINIMALLY) { + break; + } + } + return {consumedTotal, user}; + } + +public: + void *consumePostPadded(char *data, unsigned int length, void *user, void *reserved, MoveOnlyFunction &&requestHandler, MoveOnlyFunction &&dataHandler, MoveOnlyFunction &&errorHandler) { + + /* This resets BloomFilter by construction, but later we also reset it again. + * Optimize this to skip resetting twice (req could be made global) */ + HttpRequest req; + + if (remainingStreamingBytes) { + + // this is exactly the same as below! + // todo: refactor this + if (remainingStreamingBytes >= length) { + void *returnedUser = dataHandler(user, std::string_view(data, length), remainingStreamingBytes == length); + remainingStreamingBytes -= length; + return returnedUser; + } else { + void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true); + + data += remainingStreamingBytes; + length -= remainingStreamingBytes; + + remainingStreamingBytes = 0; + + if (returnedUser != user) { + return returnedUser; + } + } + + } else if (fallback.length()) { + unsigned int had = (unsigned int) fallback.length(); + + size_t maxCopyDistance = std::min(MAX_FALLBACK_SIZE - fallback.length(), (size_t) length); + + /* We don't want fallback to be short string optimized, since we want to move it */ + fallback.reserve(fallback.length() + maxCopyDistance + std::max(MINIMUM_HTTP_POST_PADDING, sizeof(std::string))); + fallback.append(data, maxCopyDistance); + + // break here on break + std::pair consumed = fenceAndConsumePostPadded(fallback.data(), (unsigned int) fallback.length(), user, reserved, &req, requestHandler, dataHandler); + if (consumed.second != user) { + return consumed.second; + } + + if (consumed.first) { + + /* This logic assumes that we consumed everything in fallback buffer. + * This is critically important, as we will get an integer overflow in case + * of "had" being larger than what we consumed, and that we would drop data */ + fallback.clear(); + data += consumed.first - had; + length -= consumed.first - had; + + if (remainingStreamingBytes) { + // this is exactly the same as above! + if (remainingStreamingBytes >= (unsigned int) length) { + void *returnedUser = dataHandler(user, std::string_view(data, length), remainingStreamingBytes == (unsigned int) length); + remainingStreamingBytes -= length; + return returnedUser; + } else { + void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true); + + data += remainingStreamingBytes; + length -= remainingStreamingBytes; + + remainingStreamingBytes = 0; + + if (returnedUser != user) { + return returnedUser; + } + } + } + + } else { + if (fallback.length() == MAX_FALLBACK_SIZE) { + // note: you don't really need error handler, just return something strange! + // we could have it return a constant pointer to denote error! + return errorHandler(user); + } + return user; + } + } + + std::pair consumed = fenceAndConsumePostPadded(data, length, user, reserved, &req, requestHandler, dataHandler); + if (consumed.second != user) { + return consumed.second; + } + + data += consumed.first; + length -= consumed.first; + + if (length) { + if (length < MAX_FALLBACK_SIZE) { + fallback.append(data, length); + } else { + return errorHandler(user); + } + } + + // added for now + return user; + } +}; + +} + +#endif // UWS_HTTPPARSER_H diff --git a/thirdparty/include/uWebSockets/HttpResponse.h b/thirdparty/include/uWebSockets/HttpResponse.h new file mode 100644 index 0000000000000000000000000000000000000000..fd3e74ce4f564c3b2c20cde5472f38530b40f1dc --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpResponse.h @@ -0,0 +1,479 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPRESPONSE_H +#define UWS_HTTPRESPONSE_H + +/* An HttpResponse is the channel on which you send back a response */ + +#include "AsyncSocket.h" +#include "HttpResponseData.h" +#include "HttpContext.h" +#include "HttpContextData.h" +#include "Utilities.h" + +#include "WebSocketExtensions.h" +#include "WebSocketHandshake.h" +#include "WebSocket.h" +#include "WebSocketContextData.h" + +#include "MoveOnlyFunction.h" + +/* todo: tryWrite is missing currently, only send smaller segments with write */ + +namespace uWS { + +/* Some pre-defined status constants to use with writeStatus */ +static const char *HTTP_200_OK = "200 OK"; + +/* The general timeout for HTTP sockets */ +static const int HTTP_TIMEOUT_S = 10; + +template +struct HttpResponse : public AsyncSocket { + /* Solely used for getHttpResponseData() */ + template friend struct TemplatedApp; + typedef AsyncSocket Super; +private: + HttpResponseData *getHttpResponseData() { + return (HttpResponseData *) Super::getAsyncSocketData(); + } + + /* Write an unsigned 32-bit integer in hex */ + void writeUnsignedHex(unsigned int value) { + char buf[10]; + int length = utils::u32toaHex(value, buf); + + /* For now we do this copy */ + Super::write(buf, length); + } + + /* Write an unsigned 64-bit integer */ + void writeUnsigned64(uint64_t value) { + char buf[20]; + int length = utils::u64toa(value, buf); + + /* For now we do this copy */ + Super::write(buf, length); + } + + /* When we are done with a response we mark it like so */ + void markDone(HttpResponseData *httpResponseData) { + httpResponseData->onAborted = nullptr; + /* Also remove onWritable so that we do not emit when draining behind the scenes. */ + httpResponseData->onWritable = nullptr; + + /* We are done with this request */ + httpResponseData->state &= ~HttpResponseData::HTTP_RESPONSE_PENDING; + } + + /* Called only once per request */ + void writeMark() { + /* You can disable this altogether */ +#ifndef UWS_HTTPRESPONSE_NO_WRITEMARK + if (!Super::getLoopData()->noMark) { + /* We only expose major version */ + writeHeader("uWebSockets", "20"); + } +#endif + } + + /* Returns true on success, indicating that it might be feasible to write more data. + * Will start timeout if stream reaches totalSize or write failure. */ + bool internalEnd(std::string_view data, uintmax_t totalSize, bool optional, bool allowContentLength = true, bool closeConnection = false) { + /* Write status if not already done */ + writeStatus(HTTP_200_OK); + + /* If no total size given then assume this chunk is everything */ + if (!totalSize) { + totalSize = data.length(); + } + + HttpResponseData *httpResponseData = getHttpResponseData(); + + /* In some cases, such as when refusing huge data we want to close the connection when drained */ + if (closeConnection) { + + /* HTTP 1.1 must send this back unless the client already sent it to us. + * It is a connection close when either of the two parties say so but the + * one party must tell the other one so. + * + * This check also serves to limit writing the header only once. */ + if ((httpResponseData->state & HttpResponseData::HTTP_CONNECTION_CLOSE) == 0) { + writeHeader("Connection", "close"); + } + + httpResponseData->state |= HttpResponseData::HTTP_CONNECTION_CLOSE; + } + + if (httpResponseData->state & HttpResponseData::HTTP_WRITE_CALLED) { + + /* We do not have tryWrite-like functionalities, so ignore optional in this path */ + + /* Do not allow sending 0 chunk here */ + if (data.length()) { + Super::write("\r\n", 2); + writeUnsignedHex((unsigned int) data.length()); + Super::write("\r\n", 2); + + /* Ignoring optional for now */ + Super::write(data.data(), (int) data.length()); + } + + /* Terminating 0 chunk */ + Super::write("\r\n0\r\n\r\n", 7); + + markDone(httpResponseData); + + /* tryEnd can never fail when in chunked mode, since we do not have tryWrite (yet), only write */ + Super::timeout(HTTP_TIMEOUT_S); + return true; + } else { + /* Write content-length on first call */ + if (!(httpResponseData->state & HttpResponseData::HTTP_END_CALLED)) { + /* Write mark, this propagates to WebSockets too */ + writeMark(); + + /* WebSocket upgrades does not allow content-length */ + if (allowContentLength) { + /* Even zero is a valid content-length */ + Super::write("Content-Length: ", 16); + writeUnsigned64(totalSize); + Super::write("\r\n\r\n", 4); + } else { + Super::write("\r\n", 2); + } + + /* Mark end called */ + httpResponseData->state |= HttpResponseData::HTTP_END_CALLED; + } + + /* Even if we supply no new data to write, its failed boolean is useful to know + * if it failed to drain any prior failed header writes */ + + /* Write as much as possible without causing backpressure */ + size_t written = 0; + bool failed = false; + while (written < data.length() && !failed) { + /* uSockets only deals with int sizes, so pass chunks of max signed int size */ + auto writtenFailed = Super::write(data.data() + written, (int) std::min(data.length() - written, INT_MAX), optional); + + written += (size_t) writtenFailed.first; + failed = writtenFailed.second; + } + + httpResponseData->offset += written; + + /* Success is when we wrote the entire thing without any failures */ + bool success = written == data.length() && !failed; + + /* If we are now at the end, start a timeout. Also start a timeout if we failed. */ + if (!success || httpResponseData->offset == totalSize) { + Super::timeout(HTTP_TIMEOUT_S); + } + + /* Remove onAborted function if we reach the end */ + if (httpResponseData->offset == totalSize) { + markDone(httpResponseData); + } + + return success; + } + } + +public: + /* If we have proxy support; returns the proxed source address as reported by the proxy. */ +#ifdef UWS_WITH_PROXY + std::string_view getProxiedRemoteAddress() { + return getHttpResponseData()->proxyParser.getSourceAddress(); + } + + std::string_view getProxiedRemoteAddressAsText() { + return Super::addressAsText(getProxiedRemoteAddress()); + } +#endif + + /* Manually upgrade to WebSocket. Typically called in upgrade handler. Immediately calls open handler. + * NOTE: Will invalidate 'this' as socket might change location in memory. Throw away aftert use. */ + template + void upgrade(UserData &&userData, std::string_view secWebSocketKey, std::string_view secWebSocketProtocol, + std::string_view secWebSocketExtensions, + struct us_socket_context_t *webSocketContext) { + + /* Extract needed parameters from WebSocketContextData */ + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, webSocketContext); + + /* Note: OpenSSL can be used here to speed this up somewhat */ + char secWebSocketAccept[29] = {}; + WebSocketHandshake::generate(secWebSocketKey.data(), secWebSocketAccept); + + writeStatus("101 Switching Protocols") + ->writeHeader("Upgrade", "websocket") + ->writeHeader("Connection", "Upgrade") + ->writeHeader("Sec-WebSocket-Accept", secWebSocketAccept); + + /* Select first subprotocol if present */ + if (secWebSocketProtocol.length()) { + writeHeader("Sec-WebSocket-Protocol", secWebSocketProtocol.substr(0, secWebSocketProtocol.find(','))); + } + + /* Negotiate compression */ + bool perMessageDeflate = false; + CompressOptions compressOptions = CompressOptions::DISABLED; + if (secWebSocketExtensions.length() && webSocketContextData->compression != DISABLED) { + + /* We always want shared inflation, (or the full 15) */ + int wantedInflationWindow = 0; + if (webSocketContextData->compression & DEDICATED_DECOMPRESSOR) { + wantedInflationWindow = 15; + } + + /* Map from selected compressor */ + int wantedCompressionWindow = (webSocketContextData->compression & 0xFF00) >> 8; + + auto [negCompression, negCompressionWindow, negInflationWindow, negResponse] = + negotiateCompression(true, wantedCompressionWindow, wantedInflationWindow, + secWebSocketExtensions); + + if (negCompression) { + perMessageDeflate = true; + + /* Map from windowBits to compressor */ + if (negCompressionWindow == 0) { + compressOptions = CompressOptions::SHARED_COMPRESSOR; + } else { + compressOptions = (CompressOptions) ((uint32_t) (negCompressionWindow << 8) + | (uint32_t) (negCompressionWindow - 7)); + + /* If we are dedicated and have the 3kb then correct any 4kb to 3kb, + * (they both share the windowBits = 9) */ + if (webSocketContextData->compression == DEDICATED_COMPRESSOR_3KB) { + compressOptions = DEDICATED_COMPRESSOR_3KB; + } + } + + writeHeader("Sec-WebSocket-Extensions", negResponse); + } + } + + internalEnd({nullptr, 0}, 0, false, false); + + /* Grab the httpContext from res */ + HttpContext *httpContext = (HttpContext *) us_socket_context(SSL, (struct us_socket_t *) this); + + /* Move any backpressure out of HttpResponse */ + BackPressure backpressure(std::move(((AsyncSocketData *) getHttpResponseData())->buffer)); + + /* Destroy HttpResponseData */ + getHttpResponseData()->~HttpResponseData(); + + /* Before we adopt and potentially change socket, check if we are corked */ + bool wasCorked = Super::isCorked(); + + /* Adopting a socket invalidates it, do not rely on it directly to carry any data */ + WebSocket *webSocket = (WebSocket *) us_socket_context_adopt_socket(SSL, + (us_socket_context_t *) webSocketContext, (us_socket_t *) this, sizeof(WebSocketData) + sizeof(UserData)); + + /* For whatever reason we were corked, update cork to the new socket */ + if (wasCorked) { + webSocket->AsyncSocket::corkUnchecked(); + } + + /* Initialize websocket with any moved backpressure intact */ + webSocket->init(perMessageDeflate, compressOptions, std::move(backpressure)); + + /* We should only mark this if inside the parser; if upgrading "async" we cannot set this */ + HttpContextData *httpContextData = httpContext->getSocketContextData(); + if (httpContextData->isParsingHttp) { + /* We need to tell the Http parser that we changed socket */ + httpContextData->upgradedWebSocket = webSocket; + } + + /* Arm idleTimeout */ + us_socket_timeout(SSL, (us_socket_t *) webSocket, webSocketContextData->idleTimeoutComponents.first); + + /* Move construct the UserData right before calling open handler */ + new (webSocket->getUserData()) UserData(std::move(userData)); + + /* Emit open event and start the timeout */ + if (webSocketContextData->openHandler) { + webSocketContextData->openHandler(webSocket); + } + } + + /* Immediately terminate this Http response */ + using Super::close; + + /* See AsyncSocket */ + using Super::getRemoteAddress; + using Super::getRemoteAddressAsText; + using Super::getNativeHandle; + + /* Note: Headers are not checked in regards to timeout. + * We only check when you actively push data or end the request */ + + /* Write 100 Continue, can be done any amount of times */ + HttpResponse *writeContinue() { + Super::write("HTTP/1.1 100 Continue\r\n\r\n", 25); + return this; + } + + /* Write the HTTP status */ + HttpResponse *writeStatus(std::string_view status) { + HttpResponseData *httpResponseData = getHttpResponseData(); + + /* Do not allow writing more than one status */ + if (httpResponseData->state & HttpResponseData::HTTP_STATUS_CALLED) { + return this; + } + + /* Update status */ + httpResponseData->state |= HttpResponseData::HTTP_STATUS_CALLED; + + Super::write("HTTP/1.1 ", 9); + Super::write(status.data(), (int) status.length()); + Super::write("\r\n", 2); + return this; + } + + /* Write an HTTP header with string value */ + HttpResponse *writeHeader(std::string_view key, std::string_view value) { + writeStatus(HTTP_200_OK); + + Super::write(key.data(), (int) key.length()); + Super::write(": ", 2); + Super::write(value.data(), (int) value.length()); + Super::write("\r\n", 2); + return this; + } + + /* Write an HTTP header with unsigned int value */ + HttpResponse *writeHeader(std::string_view key, uint64_t value) { + writeStatus(HTTP_200_OK); + + Super::write(key.data(), (int) key.length()); + Super::write(": ", 2); + writeUnsigned64(value); + Super::write("\r\n", 2); + return this; + } + + /* End the response with an optional data chunk. Always starts a timeout. */ + void end(std::string_view data = {}, bool closeConnection = false) { + internalEnd(data, data.length(), false, true, closeConnection); + } + + /* Try and end the response. Returns [true, true] on success. + * Starts a timeout in some cases. Returns [ok, hasResponded] */ + std::pair tryEnd(std::string_view data, uintmax_t totalSize = 0) { + return {internalEnd(data, totalSize, true), hasResponded()}; + } + + /* Write parts of the response in chunking fashion. Starts timeout if failed. */ + bool write(std::string_view data) { + writeStatus(HTTP_200_OK); + + /* Do not allow sending 0 chunks, they mark end of response */ + if (!data.length()) { + /* If you called us, then according to you it was fine to call us so it's fine to still call us */ + return true; + } + + HttpResponseData *httpResponseData = getHttpResponseData(); + + if (!(httpResponseData->state & HttpResponseData::HTTP_WRITE_CALLED)) { + /* Write mark on first call to write */ + writeMark(); + + writeHeader("Transfer-Encoding", "chunked"); + httpResponseData->state |= HttpResponseData::HTTP_WRITE_CALLED; + } + + Super::write("\r\n", 2); + writeUnsignedHex((unsigned int) data.length()); + Super::write("\r\n", 2); + + auto [written, failed] = Super::write(data.data(), (int) data.length()); + if (failed) { + Super::timeout(HTTP_TIMEOUT_S); + } + + /* If we did not fail the write, accept more */ + return !failed; + } + + /* Get the current byte write offset for this Http response */ + uintmax_t getWriteOffset() { + HttpResponseData *httpResponseData = getHttpResponseData(); + + return httpResponseData->offset; + } + + /* Checking if we have fully responded and are ready for another request */ + bool hasResponded() { + HttpResponseData *httpResponseData = getHttpResponseData(); + + return !(httpResponseData->state & HttpResponseData::HTTP_RESPONSE_PENDING); + } + + /* Corks the response if possible. Leaves already corked socket be. */ + HttpResponse *cork(MoveOnlyFunction &&handler) { + if (!Super::isCorked() && Super::canCork()) { + Super::cork(); + handler(); + + /* Timeout on uncork failure, since most writes will succeed while corked */ + auto [written, failed] = Super::uncork(); + if (failed) { + /* For now we only have one single timeout so let's use it */ + /* This behavior should equal the behavior in HttpContext when uncorking fails */ + Super::timeout(HTTP_TIMEOUT_S); + } + } else { + /* We are already corked, or can't cork so let's just call the handler */ + handler(); + } + + return this; + } + + /* Attach handler for writable HTTP response */ + HttpResponse *onWritable(MoveOnlyFunction &&handler) { + HttpResponseData *httpResponseData = getHttpResponseData(); + + httpResponseData->onWritable = std::move(handler); + return this; + } + + /* Attach handler for aborted HTTP request */ + HttpResponse *onAborted(MoveOnlyFunction &&handler) { + HttpResponseData *httpResponseData = getHttpResponseData(); + + httpResponseData->onAborted = std::move(handler); + return this; + } + + /* Attach a read handler for data sent. Will be called with FIN set true if last segment. */ + void onData(MoveOnlyFunction &&handler) { + HttpResponseData *data = getHttpResponseData(); + data->inStream = std::move(handler); + } +}; + +} + +#endif // UWS_HTTPRESPONSE_H diff --git a/thirdparty/include/uWebSockets/HttpResponseData.h b/thirdparty/include/uWebSockets/HttpResponseData.h new file mode 100644 index 0000000000000000000000000000000000000000..ca17dc6881d075dfb2c34010a3bb8b64ab4374b6 --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpResponseData.h @@ -0,0 +1,62 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPRESPONSEDATA_H +#define UWS_HTTPRESPONSEDATA_H + +/* This data belongs to the HttpResponse */ + +#include "HttpParser.h" +#include "AsyncSocketData.h" +#include "ProxyParser.h" + +#include "MoveOnlyFunction.h" + +namespace uWS { + +template +struct HttpResponseData : AsyncSocketData, HttpParser { + template friend struct HttpResponse; + template friend struct HttpContext; +private: + /* Bits of status */ + enum { + HTTP_STATUS_CALLED = 1, // used + HTTP_WRITE_CALLED = 2, // used + HTTP_END_CALLED = 4, // used + HTTP_RESPONSE_PENDING = 8, // used + HTTP_CONNECTION_CLOSE = 16 // used + }; + + /* Per socket event handlers */ + MoveOnlyFunction onWritable; + MoveOnlyFunction onAborted; + MoveOnlyFunction inStream; // onData + /* Outgoing offset */ + uintmax_t offset = 0; + + /* Current state (content-length sent, status sent, write called, etc */ + int state = 0; + +#ifdef UWS_WITH_PROXY + ProxyParser proxyParser; +#endif +}; + +} + +#endif // UWS_HTTPRESPONSEDATA_H diff --git a/thirdparty/include/uWebSockets/HttpRouter.h b/thirdparty/include/uWebSockets/HttpRouter.h new file mode 100644 index 0000000000000000000000000000000000000000..ef83654b4b1f9cf3670afb6ff90c62d3338f75e7 --- /dev/null +++ b/thirdparty/include/uWebSockets/HttpRouter.h @@ -0,0 +1,252 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_HTTPROUTER_HPP +#define UWS_HTTPROUTER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MoveOnlyFunction.h" + +namespace uWS { + +template +struct HttpRouter { + /* These are public for now */ + std::vector methods = {"get", "post", "head", "put", "delete", "connect", "options", "trace", "patch"}; + static const uint32_t HIGH_PRIORITY = 0xd0000000, MEDIUM_PRIORITY = 0xe0000000, LOW_PRIORITY = 0xf0000000; + +private: + USERDATA userData; + static const unsigned int MAX_URL_SEGMENTS = 100; + + /* Handler ids are 32-bit */ + static const uint32_t HANDLER_MASK = 0x0fffffff; + + /* Methods and their respective priority */ + std::map priority; + + /* List of handlers */ + std::vector> handlers; + + /* Current URL cache */ + std::string_view currentUrl; + std::string_view urlSegmentVector[MAX_URL_SEGMENTS]; + int urlSegmentTop; + + /* The matching tree */ + struct Node { + std::string name; + std::vector> children; + std::vector handlers; + bool isHighPriority; + + Node(std::string name) : name(name) {} + } root = {"rootNode"}; + + /* Advance from parent to child, adding child if necessary */ + Node *getNode(Node *parent, std::string child, bool isHighPriority) { + for (std::unique_ptr &node : parent->children) { + if (node->name == child && node->isHighPriority == isHighPriority) { + return node.get(); + } + } + + /* Insert sorted, but keep order if parent is root (we sort methods by priority elsewhere) */ + std::unique_ptr newNode(new Node(child)); + newNode->isHighPriority = isHighPriority; + return parent->children.emplace(std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) { + + if (a->isHighPriority != b->isHighPriority) { + return a->isHighPriority; + } + + return b->name.length() && (parent != &root) && (b->name < a->name); + }), std::move(newNode))->get(); + } + + /* Basically a pre-allocated stack */ + struct RouteParameters { + friend struct HttpRouter; + private: + std::string_view params[MAX_URL_SEGMENTS]; + int paramsTop; + + void reset() { + paramsTop = -1; + } + + void push(std::string_view param) { + /* We check these bounds indirectly via the urlSegments limit */ + params[++paramsTop] = param; + } + + void pop() { + /* Same here, we cannot pop outside */ + paramsTop--; + } + } routeParameters; + + /* Set URL for router. Will reset any URL cache */ + inline void setUrl(std::string_view url) { + + /* Todo: URL may also start with "http://domain/" or "*", not only "/" */ + + /* We expect to stand on a slash */ + currentUrl = url; + urlSegmentTop = -1; + } + + /* Lazily parse or read from cache */ + inline std::pair getUrlSegment(int urlSegment) { + if (urlSegment > urlSegmentTop) { + /* Signal as STOP when we have no more URL or stack space */ + if (!currentUrl.length() || urlSegment > 99) { + return {{}, true}; + } + + /* We always stand on a slash here, so step over it */ + currentUrl.remove_prefix(1); + + auto segmentLength = currentUrl.find('/'); + if (segmentLength == std::string::npos) { + segmentLength = currentUrl.length(); + + /* Push to url segment vector */ + urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength); + urlSegmentTop++; + + /* Update currentUrl */ + currentUrl = currentUrl.substr(segmentLength); + } else { + /* Push to url segment vector */ + urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength); + urlSegmentTop++; + + /* Update currentUrl */ + currentUrl = currentUrl.substr(segmentLength); + } + } + /* In any case we return it */ + return {urlSegmentVector[urlSegment], false}; + } + + /* Executes as many handlers it can */ + bool executeHandlers(Node *parent, int urlSegment, USERDATA &userData) { + + auto [segment, isStop] = getUrlSegment(urlSegment); + + /* If we are on STOP, return where we may stand */ + if (isStop) { + /* We have reached accross the entire URL with no stoppage, execute */ + for (uint32_t handler : parent->handlers) { + if (handlers[handler & HANDLER_MASK](this)) { + return true; + } + } + /* We reached the end, so go back */ + return false; + } + + for (auto &p : parent->children) { + if (p->name.length() && p->name[0] == '*') { + /* Wildcard match (can be seen as a shortcut) */ + for (uint32_t handler : p->handlers) { + if (handlers[handler & HANDLER_MASK](this)) { + return true; + } + } + } else if (p->name.length() && p->name[0] == ':' && segment.length()) { + /* Parameter match */ + routeParameters.push(segment); + if (executeHandlers(p.get(), urlSegment + 1, userData)) { + return true; + } + routeParameters.pop(); + } else if (p->name == segment) { + /* Static match */ + if (executeHandlers(p.get(), urlSegment + 1, userData)) { + return true; + } + } + } + return false; + } + +public: + HttpRouter() { + int p = 0; + for (std::string &method : methods) { + priority[method] = p++; + } + } + + std::pair getParameters() { + return {routeParameters.paramsTop, routeParameters.params}; + } + + USERDATA &getUserData() { + return userData; + } + + /* Fast path */ + bool route(std::string_view method, std::string_view url) { + /* Reset url parsing cache */ + setUrl(url); + routeParameters.reset(); + + /* Begin by finding the method node */ + for (auto &p : root.children) { + if (p->name == method) { + /* Then route the url */ + return executeHandlers(p.get(), 0, userData); + } + } + + /* We did not find any handler for this method and url */ + return false; + } + + /* Adds the corresponding entires in matching tree and handler list */ + void add(std::vector methods, std::string pattern, MoveOnlyFunction &&handler, uint32_t priority = MEDIUM_PRIORITY) { + for (std::string method : methods) { + /* Lookup method */ + Node *node = getNode(&root, method, false); + /* Iterate over all segments */ + setUrl(pattern); + for (int i = 0; !getUrlSegment(i).second; i++) { + node = getNode(node, std::string(getUrlSegment(i).first), priority == HIGH_PRIORITY); + } + /* Insert handler in order sorted by priority (most significant 1 byte) */ + node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), (uint32_t) (priority | handlers.size())), (uint32_t) (priority | handlers.size())); + } + + /* Alloate this handler */ + handlers.emplace_back(std::move(handler)); + } +}; + +} + +#endif // UWS_HTTPROUTER_HPP diff --git a/thirdparty/include/uWebSockets/Loop.h b/thirdparty/include/uWebSockets/Loop.h new file mode 100644 index 0000000000000000000000000000000000000000..da3023b10e546b6b305b5fc284a8a18897336aac --- /dev/null +++ b/thirdparty/include/uWebSockets/Loop.h @@ -0,0 +1,188 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_LOOP_H +#define UWS_LOOP_H + +/* The loop is lazily created per-thread and run with run() */ + +#include "LoopData.h" +#include +#include + +namespace uWS { +struct Loop { +private: + static void wakeupCb(us_loop_t *loop) { + LoopData *loopData = (LoopData *) us_loop_ext(loop); + + /* Swap current deferQueue */ + loopData->deferMutex.lock(); + int oldDeferQueue = loopData->currentDeferQueue; + loopData->currentDeferQueue = (loopData->currentDeferQueue + 1) % 2; + loopData->deferMutex.unlock(); + + /* Drain the queue */ + for (auto &x : loopData->deferQueues[oldDeferQueue]) { + x(); + } + loopData->deferQueues[oldDeferQueue].clear(); + } + + static void preCb(us_loop_t *loop) { + LoopData *loopData = (LoopData *) us_loop_ext(loop); + + for (auto &p : loopData->preHandlers) { + p.second((Loop *) loop); + } + } + + static void postCb(us_loop_t *loop) { + LoopData *loopData = (LoopData *) us_loop_ext(loop); + + for (auto &p : loopData->postHandlers) { + p.second((Loop *) loop); + } + + /* After every event loop iteration, we must not hold the cork buffer */ + if (loopData->corkedSocket) { + std::cerr << "Error: Cork buffer must not be held across event loop iterations!" << std::endl; + std::terminate(); + } + } + + Loop() = delete; + ~Loop() = default; + + Loop *init() { + new (us_loop_ext((us_loop_t *) this)) LoopData; + return this; + } + + static Loop *create(void *hint) { + return ((Loop *) us_create_loop(hint, wakeupCb, preCb, postCb, sizeof(LoopData)))->init(); + } + + /* What to do with loops created with existingNativeLoop? */ + struct LoopCleaner { + ~LoopCleaner() { + if(loop && cleanMe) { + loop->free(); + } + } + Loop *loop = nullptr; + bool cleanMe = false; + }; + + static LoopCleaner &getLazyLoop() { + static thread_local LoopCleaner lazyLoop; + return lazyLoop; + } + +public: + /* Lazily initializes a per-thread loop and returns it. + * Will automatically free all initialized loops at exit. */ + static Loop *get(void *existingNativeLoop = nullptr) { + if (!getLazyLoop().loop) { + /* If we are given a native loop pointer we pass that to uSockets and let it deal with it */ + if (existingNativeLoop) { + /* Todo: here we want to pass the pointer, not a boolean */ + getLazyLoop().loop = create(existingNativeLoop); + /* We cannot register automatic free here, must be manually done */ + } else { + getLazyLoop().loop = create(nullptr); + getLazyLoop().cleanMe = true; + } + } + + return getLazyLoop().loop; + } + + /* Freeing the default loop should be done once */ + void free() { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + loopData->~LoopData(); + /* uSockets will track whether this loop is owned by us or a borrowed alien loop */ + us_loop_free((us_loop_t *) this); + + /* Reset lazyLoop */ + getLazyLoop().loop = nullptr; + } + + void addPostHandler(void *key, MoveOnlyFunction &&handler) { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + + loopData->postHandlers.emplace(key, std::move(handler)); + } + + /* Bug: what if you remove a handler while iterating them? */ + void removePostHandler(void *key) { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + + loopData->postHandlers.erase(key); + } + + void addPreHandler(void *key, MoveOnlyFunction &&handler) { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + + loopData->preHandlers.emplace(key, std::move(handler)); + } + + /* Bug: what if you remove a handler while iterating them? */ + void removePreHandler(void *key) { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + + loopData->preHandlers.erase(key); + } + + /* Defer this callback on Loop's thread of execution */ + void defer(MoveOnlyFunction &&cb) { + LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); + + //if (std::thread::get_id() == ) // todo: add fast path for same thread id + loopData->deferMutex.lock(); + loopData->deferQueues[loopData->currentDeferQueue].emplace_back(std::move(cb)); + loopData->deferMutex.unlock(); + + us_wakeup_loop((us_loop_t *) this); + } + + /* Actively block and run this loop */ + void run() { + us_loop_run((us_loop_t *) this); + } + + /* Passively integrate with the underlying default loop */ + /* Used to seamlessly integrate with third parties such as Node.js */ + void integrate() { + us_loop_integrate((us_loop_t *) this); + } + + /* Dynamically change this */ + void setSilent(bool silent) { + ((LoopData *) us_loop_ext((us_loop_t *) this))->noMark = silent; + } +}; + +/* Can be called from any thread to run the thread local loop */ +inline void run() { + Loop::get()->run(); +} + +} + +#endif // UWS_LOOP_H diff --git a/thirdparty/include/uWebSockets/LoopData.h b/thirdparty/include/uWebSockets/LoopData.h new file mode 100644 index 0000000000000000000000000000000000000000..b4cac2930a40671845989312cfc515df889769bb --- /dev/null +++ b/thirdparty/include/uWebSockets/LoopData.h @@ -0,0 +1,75 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_LOOPDATA_H +#define UWS_LOOPDATA_H + +#include +#include +#include +#include +#include + +#include "PerMessageDeflate.h" + +#include "MoveOnlyFunction.h" + +namespace uWS { + +struct Loop; + +struct alignas(16) LoopData { + friend struct Loop; +private: + std::mutex deferMutex; + int currentDeferQueue = 0; + std::vector> deferQueues[2]; + + /* Map from void ptr to handler */ + std::map> postHandlers, preHandlers; + +public: + ~LoopData() { + /* If we have had App.ws called with compression we need to clear this */ + if (zlibContext) { + delete zlibContext; + delete inflationStream; + delete deflationStream; + } + delete [] corkBuffer; + } + + /* Be silent */ + bool noMark = false; + + /* Good 16k for SSL perf. */ + static const unsigned int CORK_BUFFER_SIZE = 16 * 1024; + + /* Cork data */ + char *corkBuffer = new char[CORK_BUFFER_SIZE]; + unsigned int corkOffset = 0; + void *corkedSocket = nullptr; + + /* Per message deflate data */ + ZlibContext *zlibContext = nullptr; + InflationStream *inflationStream = nullptr; + DeflationStream *deflationStream = nullptr; +}; + +} + +#endif // UWS_LOOPDATA_H diff --git a/thirdparty/include/uWebSockets/MessageParser.h b/thirdparty/include/uWebSockets/MessageParser.h new file mode 100644 index 0000000000000000000000000000000000000000..aa8d45572fb28beaf6a8e37779510e0ba7826b74 --- /dev/null +++ b/thirdparty/include/uWebSockets/MessageParser.h @@ -0,0 +1,64 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Implements the common parser (RFC 822) used in both HTTP and Multipart parsing */ + +#ifndef UWS_MESSAGE_PARSER_H +#define UWS_MESSAGE_PARSER_H + +#include +#include +#include + +/* For now we have this one here */ +#define MAX_HEADERS 10 + +namespace uWS { + + // should be templated on whether it needs at lest one header (http), or not (multipart) + static inline unsigned int getHeaders(char *postPaddedBuffer, char *end, std::pair *headers) { + char *preliminaryKey, *preliminaryValue, *start = postPaddedBuffer; + + for (unsigned int i = 0; i < MAX_HEADERS; i++) { + for (preliminaryKey = postPaddedBuffer; (*postPaddedBuffer != ':') & (*postPaddedBuffer > 32); *(postPaddedBuffer++) |= 32); + if (*postPaddedBuffer == '\r') { + if ((postPaddedBuffer != end) & (postPaddedBuffer[1] == '\n') /* & (i > 0) */) { // multipart does not require any headers like http does + headers->first = std::string_view(nullptr, 0); + return (unsigned int) ((postPaddedBuffer + 2) - start); + } else { + return 0; + } + } else { + headers->first = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey)); + for (postPaddedBuffer++; (*postPaddedBuffer == ':' || *postPaddedBuffer < 33) && *postPaddedBuffer != '\r'; postPaddedBuffer++); + preliminaryValue = postPaddedBuffer; + postPaddedBuffer = (char *) memchr(postPaddedBuffer, '\r', end - postPaddedBuffer); + if (postPaddedBuffer && postPaddedBuffer[1] == '\n') { + headers->second = std::string_view(preliminaryValue, (size_t) (postPaddedBuffer - preliminaryValue)); + postPaddedBuffer += 2; + headers++; + } else { + return 0; + } + } + } + return 0; + } + +} + +#endif \ No newline at end of file diff --git a/thirdparty/include/uWebSockets/MoveOnlyFunction.h b/thirdparty/include/uWebSockets/MoveOnlyFunction.h new file mode 100644 index 0000000000000000000000000000000000000000..b1ae785e22b648c43c0ca3be9bc8c965a03e0993 --- /dev/null +++ b/thirdparty/include/uWebSockets/MoveOnlyFunction.h @@ -0,0 +1,377 @@ +/* +MIT License + +Copyright (c) 2020 Oleg Fatkhiev + +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. +*/ + +/* Sources fetched from https://github.com/ofats/any_invocable on 2021-02-19. */ + +#ifndef _ANY_INVOKABLE_H_ +#define _ANY_INVOKABLE_H_ + +#include +#include +#include + +// clang-format off +/* +namespace std { + template class any_invocable; // never defined + + template + class any_invocable { + public: + using result_type = R; + + // SECTION.3, construct/copy/destroy + any_invocable() noexcept; + any_invocable(nullptr_t) noexcept; + any_invocable(any_invocable&&) noexcept; + template any_invocable(F&&); + + template + explicit any_invocable(in_place_type_t, Args&&...); + template + explicit any_invocable(in_place_type_t, initializer_list, Args&&...); + + any_invocable& operator=(any_invocable&&) noexcept; + any_invocable& operator=(nullptr_t) noexcept; + template any_invocable& operator=(F&&); + template any_invocable& operator=(reference_wrapper) noexcept; + + ~any_invocable(); + + // SECTION.4, any_invocable modifiers + void swap(any_invocable&) noexcept; + + // SECTION.5, any_invocable capacity + explicit operator bool() const noexcept; + + // SECTION.6, any_invocable invocation + R operator()(ArgTypes...) cv ref noexcept(noex); + + // SECTION.7, null pointer comparisons + friend bool operator==(const any_invocable&, nullptr_t) noexcept; + + // SECTION.8, specialized algorithms + friend void swap(any_invocable&, any_invocable&) noexcept; + }; +} +*/ +// clang-format on + +namespace ofats { + +namespace any_detail { + +using buffer = std::aligned_storage_t; + +template +inline constexpr bool is_small_object_v = + sizeof(T) <= sizeof(buffer) && alignof(buffer) % alignof(T) == 0 && + std::is_nothrow_move_constructible_v; + +union storage { + void* ptr_ = nullptr; + buffer buf_; +}; + +enum class action { destroy, move }; + +template +struct handler_traits { + template + struct handler_base { + static void handle(action act, storage* current, storage* other = nullptr) { + switch (act) { + case (action::destroy): + Derived::destroy(*current); + break; + case (action::move): + Derived::move(*current, *other); + break; + } + } + }; + + template + struct small_handler : handler_base> { + template + static void create(storage& s, Args&&... args) { + new (static_cast(&s.buf_)) T(std::forward(args)...); + } + + static void destroy(storage& s) noexcept { + T& value = *static_cast(static_cast(&s.buf_)); + value.~T(); + } + + static void move(storage& dst, storage& src) noexcept { + create(dst, std::move(*static_cast(static_cast(&src.buf_)))); + destroy(src); + } + + static R call(storage& s, ArgTypes... args) { + return std::invoke(*static_cast(static_cast(&s.buf_)), + std::forward(args)...); + } + }; + + template + struct large_handler : handler_base> { + template + static void create(storage& s, Args&&... args) { + s.ptr_ = new T(std::forward(args)...); + } + + static void destroy(storage& s) noexcept { delete static_cast(s.ptr_); } + + static void move(storage& dst, storage& src) noexcept { + dst.ptr_ = src.ptr_; + } + + static R call(storage& s, ArgTypes... args) { + return std::invoke(*static_cast(s.ptr_), + std::forward(args)...); + } + }; + + template + using handler = std::conditional_t, small_handler, + large_handler>; +}; + +template +struct is_in_place_type : std::false_type {}; + +template +struct is_in_place_type> : std::true_type {}; + +template +inline constexpr auto is_in_place_type_v = is_in_place_type::value; + +template +class any_invocable_impl { + template + using handler = + typename any_detail::handler_traits::template handler; + + using storage = any_detail::storage; + using action = any_detail::action; + using handle_func = void (*)(any_detail::action, any_detail::storage*, + any_detail::storage*); + using call_func = R (*)(any_detail::storage&, ArgTypes...); + + public: + using result_type = R; + + any_invocable_impl() noexcept = default; + any_invocable_impl(std::nullptr_t) noexcept {} + any_invocable_impl(any_invocable_impl&& rhs) noexcept { + if (rhs.handle_) { + handle_ = rhs.handle_; + handle_(action::move, &storage_, &rhs.storage_); + call_ = rhs.call_; + rhs.handle_ = nullptr; + } + } + + any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept { + any_invocable_impl{std::move(rhs)}.swap(*this); + return *this; + } + any_invocable_impl& operator=(std::nullptr_t) noexcept { + destroy(); + return *this; + } + + ~any_invocable_impl() { destroy(); } + + void swap(any_invocable_impl& rhs) noexcept { + if (handle_) { + if (rhs.handle_) { + storage tmp; + handle_(action::move, &tmp, &storage_); + rhs.handle_(action::move, &storage_, &rhs.storage_); + handle_(action::move, &rhs.storage_, &tmp); + std::swap(handle_, rhs.handle_); + std::swap(call_, rhs.call_); + } else { + rhs.swap(*this); + } + } else if (rhs.handle_) { + rhs.handle_(action::move, &storage_, &rhs.storage_); + handle_ = rhs.handle_; + call_ = rhs.call_; + rhs.handle_ = nullptr; + } + } + + explicit operator bool() const noexcept { return handle_ != nullptr; } + + protected: + template + void create(Args&&... args) { + using hdl = handler; + hdl::create(storage_, std::forward(args)...); + handle_ = &hdl::handle; + call_ = &hdl::call; + } + + void destroy() noexcept { + if (handle_) { + handle_(action::destroy, &storage_, nullptr); + handle_ = nullptr; + } + } + + R call(ArgTypes... args) noexcept(is_noexcept) { + return call_(storage_, std::forward(args)...); + } + + friend bool operator==(const any_invocable_impl& f, std::nullptr_t) noexcept { + return !f; + } + friend bool operator==(std::nullptr_t, const any_invocable_impl& f) noexcept { + return !f; + } + friend bool operator!=(const any_invocable_impl& f, std::nullptr_t) noexcept { + return static_cast(f); + } + friend bool operator!=(std::nullptr_t, const any_invocable_impl& f) noexcept { + return static_cast(f); + } + + friend void swap(any_invocable_impl& lhs, any_invocable_impl& rhs) noexcept { + lhs.swap(rhs); + } + + private: + storage storage_; + handle_func handle_ = nullptr; + call_func call_; +}; + +template +using remove_cvref_t = std::remove_cv_t>; + +template +using can_convert = std::conjunction< + std::negation, AI>>, + std::negation>>, + std::is_invocable_r, + std::bool_constant<(!noex || + std::is_nothrow_invocable_r_v)>, + std::is_constructible, F>>; + +} // namespace any_detail + +template +class any_invocable; + +#define __OFATS_ANY_INVOCABLE(cv, ref, noex, inv_quals) \ + template \ + class any_invocable \ + : public any_detail::any_invocable_impl { \ + using base_type = any_detail::any_invocable_impl; \ + \ + public: \ + using base_type::base_type; \ + \ + template < \ + class F, \ + class = std::enable_if_t::value>> \ + any_invocable(F&& f) { \ + base_type::template create>(std::forward(f)); \ + } \ + \ + template , \ + class = std::enable_if_t< \ + std::is_move_constructible_v && \ + std::is_constructible_v && \ + std::is_invocable_r_v && \ + (!noex || std::is_nothrow_invocable_r_v)>> \ + explicit any_invocable(std::in_place_type_t, Args&&... args) { \ + base_type::template create(std::forward(args)...); \ + } \ + \ + template < \ + class T, class U, class... Args, class VT = std::decay_t, \ + class = std::enable_if_t< \ + std::is_move_constructible_v && \ + std::is_constructible_v&, Args...> && \ + std::is_invocable_r_v && \ + (!noex || \ + std::is_nothrow_invocable_r_v)>> \ + explicit any_invocable(std::in_place_type_t, \ + std::initializer_list il, Args&&... args) { \ + base_type::template create(il, std::forward(args)...); \ + } \ + \ + template > \ + std::enable_if_t && \ + std::is_move_constructible_v, \ + any_invocable&> \ + operator=(F&& f) { \ + any_invocable{std::forward(f)}.swap(*this); \ + return *this; \ + } \ + template \ + any_invocable& operator=(std::reference_wrapper f) { \ + any_invocable{f}.swap(*this); \ + return *this; \ + } \ + \ + R operator()(ArgTypes... args) cv ref noexcept(noex) { \ + return base_type::call(std::forward(args)...); \ + } \ + }; + +// cv -> {`empty`, const} +// ref -> {`empty`, &, &&} +// noex -> {true, false} +// inv_quals -> (is_empty(ref) ? & : ref) +__OFATS_ANY_INVOCABLE(, , false, &) // 000 +__OFATS_ANY_INVOCABLE(, , true, &) // 001 +__OFATS_ANY_INVOCABLE(, &, false, &) // 010 +__OFATS_ANY_INVOCABLE(, &, true, &) // 011 +__OFATS_ANY_INVOCABLE(, &&, false, &&) // 020 +__OFATS_ANY_INVOCABLE(, &&, true, &&) // 021 +__OFATS_ANY_INVOCABLE(const, , false, const&) // 100 +__OFATS_ANY_INVOCABLE(const, , true, const&) // 101 +__OFATS_ANY_INVOCABLE(const, &, false, const&) // 110 +__OFATS_ANY_INVOCABLE(const, &, true, const&) // 111 +__OFATS_ANY_INVOCABLE(const, &&, false, const&&) // 120 +__OFATS_ANY_INVOCABLE(const, &&, true, const&&) // 121 + +#undef __OFATS_ANY_INVOCABLE + +} // namespace ofats + +/* We, uWebSockets define our own type */ +namespace uWS { + template + using MoveOnlyFunction = ofats::any_invocable; +} + +#endif // _ANY_INVOKABLE_H_ diff --git a/thirdparty/include/uWebSockets/Multipart.h b/thirdparty/include/uWebSockets/Multipart.h new file mode 100644 index 0000000000000000000000000000000000000000..8538d642e29e9f13ee27c945258749325630ee4c --- /dev/null +++ b/thirdparty/include/uWebSockets/Multipart.h @@ -0,0 +1,231 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Implements the multipart protocol. Builds atop parts of our common http parser (not yet refactored that way). */ +/* https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html */ + +#ifndef UWS_MULTIPART_H +#define UWS_MULTIPART_H + +#include "MessageParser.h" + +#include +#include +#include +#include +#include + +namespace uWS { + + /* This one could possibly be shared with ExtensionsParser to some degree */ + struct ParameterParser { + + /* Takes the line, commonly given as content-disposition header in the multipart */ + ParameterParser(std::string_view line) { + remainingLine = line; + } + + /* Returns next key/value where value can simply be empty. + * If key (first) is empty then we are at the end */ + std::pair getKeyValue() { + auto key = getToken(); + auto op = getToken(); + + if (!op.length()) { + return {key, ""}; + } + + if (op[0] != ';') { + auto value = getToken(); + /* Strip ; or if at end, nothing */ + getToken(); + return {key, value}; + } + + return {key, ""}; + } + + private: + std::string_view remainingLine; + + /* Consumes a token from the line. Will "unquote" strings */ + std::string_view getToken() { + /* Strip whitespace */ + while (remainingLine.length() && isspace(remainingLine[0])) { + remainingLine.remove_prefix(1); + } + + if (!remainingLine.length()) { + /* All we had was space */ + return {}; + } else { + /* Are we at an operator? */ + if (remainingLine[0] == ';' || remainingLine[0] == '=') { + auto op = remainingLine.substr(0, 1); + remainingLine.remove_prefix(1); + return op; + } else { + /* Are we at a quoted string? */ + if (remainingLine[0] == '\"') { + /* Remove first quote and start counting */ + remainingLine.remove_prefix(1); + auto quote = remainingLine; + int quoteLength = 0; + + /* Read anything until other double quote appears */ + while (remainingLine.length() && remainingLine[0] != '\"') { + remainingLine.remove_prefix(1); + quoteLength++; + } + + /* We can't remove_prefix if we have nothing to remove */ + if (!remainingLine.length()) { + return {}; + } + + remainingLine.remove_prefix(1); + return quote.substr(0, quoteLength); + } else { + /* Read anything until ; = space or end */ + std::string_view token = remainingLine; + + int tokenLength = 0; + while (remainingLine.length() && remainingLine[0] != ';' && remainingLine[0] != '=' && !isspace(remainingLine[0])) { + remainingLine.remove_prefix(1); + tokenLength++; + } + + return token.substr(0, tokenLength); + } + } + } + + /* Nothing */ + return ""; + } + }; + + struct MultipartParser { + + /* 2 chars of hyphen + 1 - 70 chars of boundary */ + char prependedBoundaryBuffer[72]; + std::string_view prependedBoundary; + std::string_view remainingBody; + bool first = true; + + /* I think it is more than sane to limit this to 10 per part */ + //static const int MAX_HEADERS = 10; + + /* Construct the parser based on contentType (reads boundary) */ + MultipartParser(std::string_view contentType) { + + /* We expect the form "multipart/something;somethingboundary=something" */ + if (contentType.length() < 10 || contentType.substr(0, 10) != "multipart/") { + return; + } + + /* For now we simply guess boundary will lie between = and end. This is not entirely + * standards compliant as boundary may be expressed with or without " and spaces */ + auto equalToken = contentType.find('=', 10); + if (equalToken != std::string_view::npos) { + + /* Boundary must be less than or equal to 70 chars yet 1 char or longer */ + std::string_view boundary = contentType.substr(equalToken + 1); + if (!boundary.length() || boundary.length() > 70) { + /* Invalid size */ + return; + } + + /* Prepend it with two hyphens */ + prependedBoundaryBuffer[0] = prependedBoundaryBuffer[1] = '-'; + memcpy(&prependedBoundaryBuffer[2], boundary.data(), boundary.length()); + + prependedBoundary = {prependedBoundaryBuffer, boundary.length() + 2}; + } + } + + /* Is this even a valid multipart request? */ + bool isValid() { + return prependedBoundary.length() != 0; + } + + /* Set the body once, before getting any parts */ + void setBody(std::string_view body) { + remainingBody = body; + } + + /* Parse out the next part's data, filling the headers. Returns nullopt on end or error. */ + std::optional getNextPart(std::pair *headers) { + + /* The remaining two hyphens should be shorter than the boundary */ + if (remainingBody.length() < prependedBoundary.length()) { + /* We are done now */ + return std::nullopt; + } + + if (first) { + auto nextBoundary = remainingBody.find(prependedBoundary); + if (nextBoundary == std::string_view::npos) { + /* Cannot parse */ + return std::nullopt; + } + + /* Toss away boundary and anything before it */ + remainingBody.remove_prefix(nextBoundary + prependedBoundary.length()); + first = false; + } + + auto nextEndBoundary = remainingBody.find(prependedBoundary); + if (nextEndBoundary == std::string_view::npos) { + /* Cannot parse (or simply done) */ + return std::nullopt; + } + + std::string_view part = remainingBody.substr(0, nextEndBoundary); + remainingBody.remove_prefix(nextEndBoundary + prependedBoundary.length()); + + /* Also strip rn before and rn after the part */ + if (part.length() < 4) { + /* Cannot strip */ + return std::nullopt; + } + part.remove_prefix(2); + part.remove_suffix(2); + + /* We are allowed to post pad like this because we know the boundary is at least 2 bytes */ + /* This makes parsing a second pass invalid, so you can only iterate over parts once */ + memset((char *) part.data() + part.length(), '\r', 1); + + /* For this to be a valid part, we need to consume at least 4 bytes (\r\n\r\n) */ + int consumed = getHeaders((char *) part.data(), (char *) part.data() + part.length(), headers); + + if (!consumed) { + /* This is an invalid part */ + return std::nullopt; + } + + /* Strip away the headers from the part body data */ + part.remove_prefix(consumed); + + /* Now pass whatever is remaining of the part */ + return part; + } + }; + +} + +#endif diff --git a/thirdparty/include/uWebSockets/PerMessageDeflate.h b/thirdparty/include/uWebSockets/PerMessageDeflate.h new file mode 100644 index 0000000000000000000000000000000000000000..8f338e4e51e86baf25f8d9ed78a5eab89069a5c5 --- /dev/null +++ b/thirdparty/include/uWebSockets/PerMessageDeflate.h @@ -0,0 +1,282 @@ +/* + * Authored by Alex Hultman, 2018-2021. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This standalone module implements deflate / inflate streams */ + +#ifndef UWS_PERMESSAGEDEFLATE_H +#define UWS_PERMESSAGEDEFLATE_H + +#include + +/* We always define these options no matter if ZLIB is enabled or not */ +namespace uWS { + /* Compressor mode is 16 low bit where HIGH8(windowBits), LOW8(memLevel) */ + enum CompressOptions : uint32_t { + DISABLED = 0, + /* Highest bit is shared compressor */ + SHARED_COMPRESSOR = (uint32_t)1 << (uint32_t)31, + /* Second highest bit is DEDICATED_DECOMPRESSOR */ + DEDICATED_DECOMPRESSOR = (uint32_t)1 << (uint32_t)30, + /* Lowest 16 bit describe compressor */ + DEDICATED_COMPRESSOR_3KB = 9 << 8 | 1, + DEDICATED_COMPRESSOR_4KB = 9 << 8 | 2, + DEDICATED_COMPRESSOR_8KB = 10 << 8 | 3, + DEDICATED_COMPRESSOR_16KB = 11 << 8 | 4, + DEDICATED_COMPRESSOR_32KB = 12 << 8 | 5, + DEDICATED_COMPRESSOR_64KB = 13 << 8 | 6, + DEDICATED_COMPRESSOR_128KB = 14 << 8 | 7, + DEDICATED_COMPRESSOR_256KB = 15 << 8 | 8, + /* Same as 256kb */ + DEDICATED_COMPRESSOR = 15 << 8 | 8 + }; +} + +#if !defined(UWS_NO_ZLIB) && !defined(UWS_MOCK_ZLIB) +#include +#endif + +#include +#include + +#ifdef UWS_USE_LIBDEFLATE +#include "libdeflate.h" +#include +#endif + +namespace uWS { + +/* Do not compile this module if we don't want it */ +#if defined(UWS_NO_ZLIB) || defined(UWS_MOCK_ZLIB) +struct ZlibContext {}; +struct InflationStream { + std::optional inflate(ZlibContext * /*zlibContext*/, std::string_view compressed, size_t maxPayloadLength, bool /*reset*/) { + return compressed.substr(0, std::min(maxPayloadLength, compressed.length())); + } +}; +struct DeflationStream { + std::string_view deflate(ZlibContext * /*zlibContext*/, std::string_view raw, bool /*reset*/) { + return raw; + } + DeflationStream(CompressOptions /*compressOptions*/) { + } +}; +#else + +#define LARGE_BUFFER_SIZE 1024 * 16 // todo: fix this + +struct ZlibContext { + /* Any returned data is valid until next same-class call. + * We need to have two classes to allow inflation followed + * by many deflations without modifying the inflation */ + std::string dynamicDeflationBuffer; + std::string dynamicInflationBuffer; + char *deflationBuffer; + char *inflationBuffer; + +#ifdef UWS_USE_LIBDEFLATE + libdeflate_decompressor *decompressor; + libdeflate_compressor *compressor; +#endif + + ZlibContext() { + deflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE); + inflationBuffer = (char *) malloc(LARGE_BUFFER_SIZE); + +#ifdef UWS_USE_LIBDEFLATE + decompressor = libdeflate_alloc_decompressor(); + compressor = libdeflate_alloc_compressor(6); +#endif + } + + ~ZlibContext() { + free(deflationBuffer); + free(inflationBuffer); + +#ifdef UWS_USE_LIBDEFLATE + libdeflate_free_decompressor(decompressor); + libdeflate_free_compressor(compressor); +#endif + } +}; + +struct DeflationStream { + z_stream deflationStream = {}; + + DeflationStream(CompressOptions compressOptions) { + + /* Sliding inflator should be about 44kb by default, less than compressor */ + + /* Memory usage is given by 2 ^ (windowBits + 2) + 2 ^ (memLevel + 9) */ + int windowBits = -(int) ((compressOptions & 0xFF00) >> 8), memLevel = compressOptions & 0x00FF; + + //printf("windowBits: %d, memLevel: %d\n", windowBits, memLevel); + + deflateInit2(&deflationStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY); + } + + /* Deflate and optionally reset. You must not deflate an empty string. */ + std::string_view deflate(ZlibContext *zlibContext, std::string_view raw, bool reset) { + +#ifdef UWS_USE_LIBDEFLATE + /* Run a fast path in case of shared_compressor */ + if (reset) { + size_t written = 0; + static unsigned char buf[1024 + 1]; + + written = libdeflate_deflate_compress(zlibContext->compressor, raw.data(), raw.length(), buf, 1024); + + if (written) { + memcpy(&buf[written], "\x00", 1); + return std::string_view((char *) buf, written + 1); + } + } +#endif + + /* Odd place to clear this one, fix */ + zlibContext->dynamicDeflationBuffer.clear(); + + deflationStream.next_in = (Bytef *) raw.data(); + deflationStream.avail_in = (unsigned int) raw.length(); + + /* This buffer size has to be at least 6 bytes for Z_SYNC_FLUSH to work */ + const int DEFLATE_OUTPUT_CHUNK = LARGE_BUFFER_SIZE; + + int err; + do { + deflationStream.next_out = (Bytef *) zlibContext->deflationBuffer; + deflationStream.avail_out = DEFLATE_OUTPUT_CHUNK; + + err = ::deflate(&deflationStream, Z_SYNC_FLUSH); + if (Z_OK == err && deflationStream.avail_out == 0) { + zlibContext->dynamicDeflationBuffer.append(zlibContext->deflationBuffer, DEFLATE_OUTPUT_CHUNK - deflationStream.avail_out); + continue; + } else { + break; + } + } while (true); + + /* This must not change avail_out */ + if (reset) { + deflateReset(&deflationStream); + } + + if (zlibContext->dynamicDeflationBuffer.length()) { + zlibContext->dynamicDeflationBuffer.append(zlibContext->deflationBuffer, DEFLATE_OUTPUT_CHUNK - deflationStream.avail_out); + + return std::string_view((char *) zlibContext->dynamicDeflationBuffer.data(), zlibContext->dynamicDeflationBuffer.length() - 4); + } + + /* Note: We will get an interger overflow resulting in heap buffer overflow if Z_BUF_ERROR is returned + * from passing 0 as avail_in. Therefore we must not deflate an empty string */ + return { + zlibContext->deflationBuffer, + DEFLATE_OUTPUT_CHUNK - deflationStream.avail_out - 4 + }; + } + + ~DeflationStream() { + deflateEnd(&deflationStream); + } +}; + +struct InflationStream { + z_stream inflationStream = {}; + + InflationStream() { + inflateInit2(&inflationStream, -15); + } + + ~InflationStream() { + inflateEnd(&inflationStream); + } + + /* Zero length inflates are possible and valid */ + std::optional inflate(ZlibContext *zlibContext, std::string_view compressed, size_t maxPayloadLength, bool reset) { + +#ifdef UWS_USE_LIBDEFLATE + /* Try fast path first */ + size_t written = 0; + static char buf[1024]; + + /* We have to pad 9 bytes and restore those bytes when done since 9 is more than 6 of next WebSocket message */ + char tmp[9]; + memcpy(tmp, (char *) compressed.data() + compressed.length(), 9); + memcpy((char *) compressed.data() + compressed.length(), "\x00\x00\xff\xff\x01\x00\x00\xff\xff", 9); + libdeflate_result res = libdeflate_deflate_decompress(zlibContext->decompressor, compressed.data(), compressed.length() + 9, buf, 1024, &written); + memcpy((char *) compressed.data() + compressed.length(), tmp, 9); + + if (res == 0) { + /* Fast path wins */ + return std::string_view(buf, written); + } +#endif + + /* We clear this one here, could be done better */ + zlibContext->dynamicInflationBuffer.clear(); + + inflationStream.next_in = (Bytef *) compressed.data(); + inflationStream.avail_in = (unsigned int) compressed.length(); + + int err; + do { + inflationStream.next_out = (Bytef *) zlibContext->inflationBuffer; + inflationStream.avail_out = LARGE_BUFFER_SIZE; + + err = ::inflate(&inflationStream, Z_SYNC_FLUSH); + if (err == Z_OK && inflationStream.avail_out) { + break; + } + + zlibContext->dynamicInflationBuffer.append(zlibContext->inflationBuffer, LARGE_BUFFER_SIZE - inflationStream.avail_out); + + + } while (inflationStream.avail_out == 0 && zlibContext->dynamicInflationBuffer.length() <= maxPayloadLength); + + if (reset) { + inflateReset(&inflationStream); + } + + if ((err != Z_BUF_ERROR && err != Z_OK) || zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) { + return std::nullopt; + } + + if (zlibContext->dynamicInflationBuffer.length()) { + zlibContext->dynamicInflationBuffer.append(zlibContext->inflationBuffer, LARGE_BUFFER_SIZE - inflationStream.avail_out); + + /* Let's be strict about the max size */ + if (zlibContext->dynamicInflationBuffer.length() > maxPayloadLength) { + return std::nullopt; + } + + return std::string_view(zlibContext->dynamicInflationBuffer.data(), zlibContext->dynamicInflationBuffer.length()); + } + + /* Let's be strict about the max size */ + if ((LARGE_BUFFER_SIZE - inflationStream.avail_out) > maxPayloadLength) { + return std::nullopt; + } + + return std::string_view(zlibContext->inflationBuffer, LARGE_BUFFER_SIZE - inflationStream.avail_out); + } + +}; + +#endif + +} + +#endif // UWS_PERMESSAGEDEFLATE_H diff --git a/thirdparty/include/uWebSockets/ProxyParser.h b/thirdparty/include/uWebSockets/ProxyParser.h new file mode 100644 index 0000000000000000000000000000000000000000..95ee3d11971c35654ab5b1a2ff2c7ab7cb0f0e82 --- /dev/null +++ b/thirdparty/include/uWebSockets/ProxyParser.h @@ -0,0 +1,163 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This module implements The PROXY Protocol v2 */ + +#ifndef UWS_PROXY_PARSER_H +#define UWS_PROXY_PARSER_H + +#ifdef UWS_WITH_PROXY + +namespace uWS { + +struct proxy_hdr_v2 { + uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */ + uint8_t ver_cmd; /* protocol version and command */ + uint8_t fam; /* protocol family and address */ + uint16_t len; /* number of following bytes part of the header */ +}; + +union proxy_addr { + struct { /* for TCP/UDP over IPv4, len = 12 */ + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; + } ipv4_addr; + struct { /* for TCP/UDP over IPv6, len = 36 */ + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; + } ipv6_addr; +}; + +/* Byte swap for little-endian systems */ +/* Todo: This functions should be shared with the one in WebSocketProtocol.h! */ +template +T _cond_byte_swap(T value) { + uint32_t endian_test = 1; + if (*((char *)&endian_test)) { + union { + T i; + uint8_t b[sizeof(T)]; + } src = { value }, dst; + + for (unsigned int i = 0; i < sizeof(value); i++) { + dst.b[i] = src.b[sizeof(value) - 1 - i]; + } + + return dst.i; + } + return value; +} + +struct ProxyParser { +private: + union proxy_addr addr; + + /* Default family of 0 signals no proxy address */ + uint8_t family = 0; + +public: + /* Returns 4 or 16 bytes source address */ + std::string_view getSourceAddress() { + + // UNSPEC family and protocol + if (family == 0) { + return {}; + } + + if ((family & 0xf0) >> 4 == 1) { + /* Family 1 is INET4 */ + return {(char *) &addr.ipv4_addr.src_addr, 4}; + } else { + /* Family 2 is INET6 */ + return {(char *) &addr.ipv6_addr.src_addr, 16}; + } + } + + /* Returns [done, consumed] where done = false on failure */ + std::pair parse(std::string_view data) { + + /* We require at least four bytes to determine protocol */ + if (data.length() < 4) { + return {false, 0}; + } + + /* HTTP can never start with "\r\n\r\n", but PROXY always does */ + if (memcmp(data.data(), "\r\n\r\n", 4)) { + /* This is HTTP, so be done */ + return {true, 0}; + } + + /* We assume we are parsing PROXY V2 here */ + + /* We require 16 bytes here */ + if (data.length() < 16) { + return {false, 0}; + } + + /* Header is 16 bytes */ + struct proxy_hdr_v2 header; + memcpy(&header, data.data(), 16); + + if (memcmp(header.sig, "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", 12)) { + /* This is not PROXY protocol at all */ + return {false, 0}; + } + + /* We only support version 2 */ + if ((header.ver_cmd & 0xf0) >> 4 != 2) { + return {false, 0}; + } + + //printf("Version: %d\n", (header.ver_cmd & 0xf0) >> 4); + //printf("Command: %d\n", (header.ver_cmd & 0x0f)); + + /* We get length in network byte order (todo: share this function with the rest) */ + uint16_t hostLength = _cond_byte_swap(header.len); + + /* We must have all the data available */ + if (data.length() < 16u + hostLength) { + return {false, 0}; + } + + /* Payload cannot be more than sizeof proxy_addr */ + if (sizeof(proxy_addr) < hostLength) { + return {false, 0}; + } + + //printf("Family: %d\n", (header.fam & 0xf0) >> 4); + //printf("Transport: %d\n", (header.fam & 0x0f)); + + /* We have 0 family by default, and UNSPEC is 0 as well */ + family = header.fam; + + /* Copy payload */ + memcpy(&addr, data.data() + 16, hostLength); + + /* We consumed everything */ + return {true, 16 + hostLength}; + } +}; + +} + +#endif + +#endif // UWS_PROXY_PARSER_H \ No newline at end of file diff --git a/thirdparty/include/uWebSockets/QueryParser.h b/thirdparty/include/uWebSockets/QueryParser.h new file mode 100644 index 0000000000000000000000000000000000000000..552bb56e7af059f5e32c68c95d10de9ed1231074 --- /dev/null +++ b/thirdparty/include/uWebSockets/QueryParser.h @@ -0,0 +1,120 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This module implements URI query parsing and retrieval of value given key */ + +#ifndef UWS_QUERYPARSER_H +#define UWS_QUERYPARSER_H + +#include + +namespace uWS { + + /* Takes raw query including initial '?' sign. Will inplace decode, so input will mutate */ + static inline std::string_view getDecodedQueryValue(std::string_view key, std::string_view rawQuery) { + + /* Can't have a value without a key */ + if (!key.length()) { + return {}; + } + + /* Start with the whole querystring including initial '?' */ + std::string_view queryString = rawQuery; + + /* List of key, value could be cached for repeated fetches similar to how headers are, todo! */ + while (queryString.length()) { + /* Find boundaries of this statement */ + std::string_view statement = queryString.substr(1, queryString.find('&', 1) - 1); + + /* Only bother if first char of key match (early exit) */ + if (statement.length() && statement[0] == key[0]) { + /* Equal sign must be present and not in the end of statement */ + auto equality = statement.find('='); + if (equality != std::string_view::npos && equality != statement.length() - 1) { + + std::string_view statementKey = statement.substr(0, equality); + std::string_view statementValue = statement.substr(equality + 1); + + /* String comparison */ + if (key == statementKey) { + + /* Decode value inplace, put null at end if before length of original */ + char *in = (char *) statementValue.data(); + + /* Write offset */ + unsigned int out = 0; + + /* Walk over all chars until end or null char, decoding in place */ + for (unsigned int i = 0; i < statementValue.length() && in[i]; i++) { + /* Only bother with '%' */ + if (in[i] == '%') { + /* Do we have enough data for two bytes hex? */ + if (i + 2 >= statementValue.length()) { + return {}; + } + + /* Two bytes hex */ + int hex1 = in[i + 1] - '0'; + if (hex1 > 9) { + hex1 &= 223; + hex1 -= 7; + } + + int hex2 = in[i + 2] - '0'; + if (hex2 > 9) { + hex2 &= 223; + hex2 -= 7; + } + + *((unsigned char *) &in[out]) = (unsigned char) (hex1 * 16 + hex2); + i += 2; + } else { + /* Is this even a rule? */ + if (in[i] == '+') { + in[out] = ' '; + } else { + in[out] = in[i]; + } + } + + /* We always only write one char */ + out++; + } + + /* If decoded string is shorter than original, put null char to stop next read */ + if (out < statementValue.length()) { + in[out] = 0; + } + + return statementValue.substr(0, out); + } + } else { + /* This querystring is invalid, cannot parse it */ + return {}; + } + } + + queryString.remove_prefix(statement.length() + 1); + } + + /* Nothing found */ + return {}; + } + +} + +#endif diff --git a/thirdparty/include/uWebSockets/TopicTree.h b/thirdparty/include/uWebSockets/TopicTree.h new file mode 100644 index 0000000000000000000000000000000000000000..94edfb55186cffc20965a21c3afff8a33e2cb2bd --- /dev/null +++ b/thirdparty/include/uWebSockets/TopicTree.h @@ -0,0 +1,360 @@ +/* + * Authored by Alex Hultman, 2018-2021. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_TOPICTREE_H +#define UWS_TOPICTREE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uWS { + +struct Subscriber; + +struct Topic : std::unordered_set { + + Topic(std::string_view topic) : name(topic) { + + } + + std::string name; +}; + +struct Subscriber { + + template friend struct TopicTree; + +private: + /* We use a factory */ + Subscriber() = default; + + /* State of prev, next does not matter unless we are needsDrainage() since we are not in the list */ + Subscriber *prev, *next; + + /* Any one subscriber can be part of at most 32 publishes before it needs a drain, + * or whatever encoding of runs or whatever we might do in the future */ + uint16_t messageIndices[32]; + + /* This one matters the most, if it is 0 we are not in the list of drainableSubscribers */ + unsigned char numMessageIndices = 0; + +public: + + /* We have a list of topics we subscribe to (read by WebSocket::iterateTopics) */ + std::set topics; + + /* User data */ + void *user; + + bool needsDrainage() { + return numMessageIndices; + } +}; + +template +struct TopicTree { + + enum IteratorFlags { + LAST = 1, + FIRST = 2 + }; + + /* Whomever is iterating this topic is locked to not modify its own list */ + Subscriber *iteratingSubscriber = nullptr; + +private: + + /* The drain callback must not publish, unsubscribe or subscribe. + * It must only cork, uncork, send, write */ + std::function cb; + + /* The topics */ + std::unordered_map> topics; + + /* List of subscribers that needs drainage */ + Subscriber *drainableSubscribers = nullptr; + + /* Palette of outgoing messages, up to 64k */ + std::vector outgoingMessages; + + void checkIteratingSubscriber(Subscriber *s) { + /* Notify user that they are doing something wrong here */ + if (iteratingSubscriber == s) { + std::cerr << "Error: WebSocket must not subscribe or unsubscribe to topics while iterating its topics!" << std::endl; + std::terminate(); + } + } + + /* Warning: does NOT unlink from drainableSubscribers or modify next, prev. */ + void drainImpl(Subscriber *s) { + /* Before we call cb we need to make sure this subscriber will not report needsDrainage() + * since WebSocket::send will call drain from within the cb in that case.*/ + int numMessageIndices = s->numMessageIndices; + s->numMessageIndices = 0; + + /* Then we emit cb */ + for (int i = 0; i < numMessageIndices; i++) { + T &outgoingMessage = outgoingMessages[s->messageIndices[i]]; + + int flags = (i == numMessageIndices - 1) ? LAST : 0; + + /* Returning true will stop drainage short (such as when backpressure is too high) */ + if (cb(s, outgoingMessage, (IteratorFlags)(flags | (i == 0 ? FIRST : 0)))) { + break; + } + } + } + + void unlinkDrainableSubscriber(Subscriber *s) { + if (s->prev) { + s->prev->next = s->next; + } + if (s->next) { + s->next->prev = s->prev; + } + /* If we are the head, then we also need to reset the head */ + if (drainableSubscribers == s) { + drainableSubscribers = s->next; + } + } + +public: + + TopicTree(std::function cb) : cb(cb) { + + } + + /* Returns nullptr if not found */ + Topic *lookupTopic(std::string_view topic) { + auto it = topics.find(topic); + if (it == topics.end()) { + return nullptr; + } + return it->second.get(); + } + + /* Subscribe fails if we already are subscribed */ + bool subscribe(Subscriber *s, std::string_view topic) { + /* Notify user that they are doing something wrong here */ + checkIteratingSubscriber(s); + + /* Lookup or create new topic */ + Topic *topicPtr = lookupTopic(topic); + if (!topicPtr) { + Topic *newTopic = new Topic(topic); + topics.insert({std::string_view(newTopic->name.data(), newTopic->name.length()), std::unique_ptr(newTopic)}); + topicPtr = newTopic; + } + + /* Insert us in topic, insert topic in us */ + auto [it, inserted] = s->topics.insert(topicPtr); + if (!inserted) { + return false; + } + topicPtr->insert(s); + + /* Success */ + return true; + } + + /* Returns ok, last */ + std::pair unsubscribe(Subscriber *s, std::string_view topic) { + /* Notify user that they are doing something wrong here */ + checkIteratingSubscriber(s); + + /* Lookup topic */ + Topic *topicPtr = lookupTopic(topic); + if (!topicPtr) { + /* If the topic doesn't exist we are assumed to still be subscribers of something */ + return {false, false}; + } + + /* Erase from our list first */ + if (s->topics.erase(topicPtr) == 0) { + return {false, false}; + } + + /* Remove us from topic */ + topicPtr->erase(s); + + /* If there is no subscriber to this topic, remove it */ + if (!topicPtr->size()) { + /* Unique_ptr deletes the topic */ + topics.erase(topic); + } + + /* If we don't hold any topics we are to be freed altogether */ + return {true, topics.size() == 0}; + } + + /* Factory function for creating a Subscriber */ + Subscriber *createSubscriber() { + return new Subscriber(); + } + + /* This is used to end a Subscriber, before freeing it */ + void freeSubscriber(Subscriber *s) { + + /* I guess we call this one even if we are not subscribers */ + if (!s) { + return; + } + + /* For all topics, unsubscribe */ + for (Topic *topicPtr : s->topics) { + /* If we are the last subscriber, simply remove the whole topic */ + if (topicPtr->size() == 1) { + topics.erase(topicPtr->name); + } else { + /* Otherwise just remove us */ + topicPtr->erase(s); + } + } + + /* We also need to unlink us */ + if (s->needsDrainage()) { + unlinkDrainableSubscriber(s); + } + + delete s; + } + + /* Mainly used by WebSocket::send to drain one socket before sending */ + void drain(Subscriber *s) { + /* The list is undefined and cannot be touched unless needsDrainage(). */ + if (s->needsDrainage()) { + /* This function differs from drainImpl by properly unlinking + * the subscriber from drainableSubscribers. drainImpl does not. */ + unlinkDrainableSubscriber(s); + + /* This one always resets needsDrainage before it calls any cb's. + * Otherwise we would stackoverflow when sending after publish but before drain. */ + drainImpl(s); + + /* If we drained last subscriber, also clear outgoingMessages */ + if (!drainableSubscribers) { + outgoingMessages.clear(); + } + } + } + + /* Called everytime we call send, to drain published messages so to sync outgoing messages */ + void drain() { + if (drainableSubscribers) { + /* Drain one socket a time */ + for (Subscriber *s = drainableSubscribers; s; s = s->next) { + /* Instead of unlinking every single subscriber, we just leave the list undefined + * and reset drainableSubscribers ptr below. */ + drainImpl(s); + } + /* Drain always clears drainableSubscribers and outgoingMessages */ + drainableSubscribers = nullptr; + outgoingMessages.clear(); + } + } + + /* Big messages bypass all buffering and land directly in backpressure */ + template + bool publishBig(Subscriber *sender, std::string_view topic, B &&bigMessage, F cb) { + /* Do we even have this topic? */ + auto it = topics.find(topic); + if (it == topics.end()) { + return false; + } + + /* For all subscribers in topic */ + for (Subscriber *s : *it->second) { + + /* If we are sender then ignore us */ + if (sender != s) { + cb(s, bigMessage); + } + } + + return true; + } + + /* Linear in number of affected subscribers */ + bool publish(Subscriber *sender, std::string_view topic, T &&message) { + /* Do we even have this topic? */ + auto it = topics.find(topic); + if (it == topics.end()) { + return false; + } + + /* If we have more than 65k messages we need to drain every socket. */ + if (outgoingMessages.size() == UINT16_MAX) { + /* If there is a socket that is currently corked, this will be ugly as all sockets will drain + * to their own backpressure */ + drain(); + } + + /* If nobody references this message, don't buffer it */ + bool referencedMessage = false; + + /* For all subscribers in topic */ + for (Subscriber *s : *it->second) { + + /* If we are sender then ignore us */ + if (sender != s) { + + /* At least one subscriber wants this message */ + referencedMessage = true; + + /* If we already have too many outgoing messages on this subscriber, drain it now */ + if (s->numMessageIndices == 32) { + /* This one does not need to check needsDrainage here but still does. */ + drain(s); + } + + /* Finally we can continue */ + s->messageIndices[s->numMessageIndices++] = (uint16_t)outgoingMessages.size(); + /* First message adds subscriber to list of drainable subscribers */ + if (s->numMessageIndices == 1) { + /* Insert us in the head of drainable subscribers */ + s->next = drainableSubscribers; + s->prev = nullptr; + if (s->next) { + s->next->prev = s; + } + drainableSubscribers = s; + } + } + } + + /* Push this message and return with success */ + if (referencedMessage) { + outgoingMessages.emplace_back(message); + } + + /* Success if someone wants it */ + return referencedMessage; + } +}; + +} + +#endif diff --git a/thirdparty/include/uWebSockets/Utilities.h b/thirdparty/include/uWebSockets/Utilities.h new file mode 100644 index 0000000000000000000000000000000000000000..2fbea326a81903ea9477f1a5e42c9e8fb4cc691d --- /dev/null +++ b/thirdparty/include/uWebSockets/Utilities.h @@ -0,0 +1,66 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_UTILITIES_H +#define UWS_UTILITIES_H + +/* Various common utilities */ + +#include + +namespace uWS { +namespace utils { + +inline int u32toaHex(uint32_t value, char *dst) { + char palette[] = "0123456789abcdef"; + char temp[10]; + char *p = temp; + do { + *p++ = palette[value % 16]; + value /= 16; + } while (value > 0); + + int ret = (int) (p - temp); + + do { + *dst++ = *--p; + } while (p != temp); + + return ret; +} + +inline int u64toa(uint64_t value, char *dst) { + char temp[20]; + char *p = temp; + do { + *p++ = (char) ((value % 10) + '0'); + value /= 10; + } while (value > 0); + + int ret = (int) (p - temp); + + do { + *dst++ = *--p; + } while (p != temp); + + return ret; +} + +} +} + +#endif // UWS_UTILITIES_H diff --git a/thirdparty/include/uWebSockets/WebSocket.h b/thirdparty/include/uWebSockets/WebSocket.h new file mode 100644 index 0000000000000000000000000000000000000000..ed9c508c12ac6185b32178de88458cbac2e8a6b0 --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocket.h @@ -0,0 +1,321 @@ +/* + * Authored by Alex Hultman, 2018-2021. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKET_H +#define UWS_WEBSOCKET_H + +#include "WebSocketData.h" +#include "WebSocketProtocol.h" +#include "AsyncSocket.h" +#include "WebSocketContextData.h" + +#include + +namespace uWS { + +template +struct WebSocket : AsyncSocket { + template friend struct TemplatedApp; + template friend struct HttpResponse; +private: + typedef AsyncSocket Super; + + void *init(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) { + new (us_socket_ext(SSL, (us_socket_t *) this)) WebSocketData(perMessageDeflate, compressOptions, std::move(backpressure)); + return this; + } +public: + + /* Returns pointer to the per socket user data */ + USERDATA *getUserData() { + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + /* We just have it overallocated by sizeof type */ + return (USERDATA *) (webSocketData + 1); + } + + /* See AsyncSocket */ + using Super::getBufferedAmount; + using Super::getRemoteAddress; + using Super::getRemoteAddressAsText; + using Super::getNativeHandle; + + /* WebSocket close cannot be an alias to AsyncSocket::close since + * we need to check first if it was shut down by remote peer */ + us_socket_t *close() { + if (us_socket_is_closed(SSL, (us_socket_t *) this)) { + return nullptr; + } + WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData(); + if (webSocketData->isShuttingDown) { + return nullptr; + } + + return us_socket_close(SSL, (us_socket_t *) this, 0, nullptr); + } + + enum SendStatus : int { + BACKPRESSURE, + SUCCESS, + DROPPED + }; + + /* Send or buffer a WebSocket frame, compressed or not. Returns BACKPRESSURE on increased user space backpressure, + * DROPPED on dropped message (due to backpressure) or SUCCCESS if you are free to send even more now. */ + SendStatus send(std::string_view message, OpCode opCode = OpCode::BINARY, bool compress = false) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + /* Skip sending and report success if we are over the limit of maxBackpressure */ + if (webSocketContextData->maxBackpressure && webSocketContextData->maxBackpressure < getBufferedAmount()) { + /* Also defer a close if we should */ + if (webSocketContextData->closeOnBackpressureLimit) { + us_socket_shutdown_read(SSL, (us_socket_t *) this); + } + return DROPPED; + } + + /* If we are subscribers and have messages to drain we need to drain them here to stay synced */ + WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData(); + if (webSocketData->subscriber) { + /* This will call back into us, send. */ + webSocketContextData->topicTree->drain(webSocketData->subscriber); + } + + /* Transform the message to compressed domain if requested */ + if (compress) { + WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData(); + + /* Check and correct the compress hint. It is never valid to compress 0 bytes */ + if (message.length() && opCode < 3 && webSocketData->compressionStatus == WebSocketData::ENABLED) { + LoopData *loopData = Super::getLoopData(); + /* Compress using either shared or dedicated deflationStream */ + if (webSocketData->deflationStream) { + message = webSocketData->deflationStream->deflate(loopData->zlibContext, message, false); + } else { + message = loopData->deflationStream->deflate(loopData->zlibContext, message, true); + } + } else { + compress = false; + } + } + + /* Get size, allocate size, write if needed */ + size_t messageFrameSize = protocol::messageFrameSize(message.length()); + auto [sendBuffer, sendBufferAttribute] = Super::getSendBuffer(messageFrameSize); + protocol::formatMessage(sendBuffer, message.data(), message.length(), opCode, message.length(), compress); + + /* Depending on size of message we have different paths */ + if (sendBufferAttribute == SendBufferAttribute::NEEDS_DRAIN) { + /* This is a drain */ + auto[written, failed] = Super::write(nullptr, 0); + if (failed) { + /* Return false for failure, skipping to reset the timeout below */ + return BACKPRESSURE; + } + } else if (sendBufferAttribute == SendBufferAttribute::NEEDS_UNCORK) { + /* Uncork if we came here uncorked */ + auto [written, failed] = Super::uncork(); + if (failed) { + return BACKPRESSURE; + } + } + + /* Every successful send resets the timeout */ + if (webSocketContextData->resetIdleTimeoutOnSend) { + Super::timeout(webSocketContextData->idleTimeoutComponents.first); + WebSocketData *webSocketData = (WebSocketData *) Super::getAsyncSocketData(); + webSocketData->hasTimedOut = false; + } + + /* Return success */ + return SUCCESS; + } + + /* Send websocket close frame, emit close event, send FIN if successful. + * Will not append a close reason if code is 0 or 1005. */ + void end(int code = 0, std::string_view message = {}) { + /* Check if we already called this one */ + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + if (webSocketData->isShuttingDown) { + return; + } + + /* We postpone any FIN sending to either drainage or uncorking */ + webSocketData->isShuttingDown = true; + + /* Format and send the close frame */ + static const int MAX_CLOSE_PAYLOAD = 123; + size_t length = std::min(MAX_CLOSE_PAYLOAD, message.length()); + char closePayload[MAX_CLOSE_PAYLOAD + 2]; + size_t closePayloadLength = protocol::formatClosePayload(closePayload, (uint16_t) code, message.data(), length); + bool ok = send(std::string_view(closePayload, closePayloadLength), OpCode::CLOSE); + + /* FIN if we are ok and not corked */ + if (!this->isCorked()) { + if (ok) { + /* If we are not corked, and we just sent off everything, we need to FIN right here. + * In all other cases, we need to fin either if uncork was successful, or when drainage is complete. */ + this->shutdown(); + } + } + + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + /* Set shorter timeout (use ping-timeout) to avoid long hanging sockets after end() on broken connections */ + Super::timeout(webSocketContextData->idleTimeoutComponents.second); + + /* Emit close event */ + if (webSocketContextData->closeHandler) { + webSocketContextData->closeHandler(this, code, message); + } + + /* Make sure to unsubscribe from any pub/sub node at exit */ + webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber); + webSocketData->subscriber = nullptr; + } + + /* Corks the response if possible. Leaves already corked socket be. */ + void cork(MoveOnlyFunction &&handler) { + if (!Super::isCorked() && Super::canCork()) { + Super::cork(); + handler(); + + /* There is no timeout when failing to uncork for WebSockets, + * as that is handled by idleTimeout */ + auto [written, failed] = Super::uncork(); + } else { + /* We are already corked, or can't cork so let's just call the handler */ + handler(); + } + } + + /* Subscribe to a topic according to MQTT rules and syntax. Returns success */ + bool subscribe(std::string_view topic, bool = false) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + /* Make us a subscriber if we aren't yet */ + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + if (!webSocketData->subscriber) { + webSocketData->subscriber = webSocketContextData->topicTree->createSubscriber(); + webSocketData->subscriber->user = this; + } + + /* Cannot return numSubscribers as this is only for this particular websocket context */ + webSocketContextData->topicTree->subscribe(webSocketData->subscriber, topic); + + /* Subscribe always succeeds */ + return true; + } + + /* Unsubscribe from a topic, returns true if we were subscribed. */ + bool unsubscribe(std::string_view topic, bool = false) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + + /* Cannot return numSubscribers as this is only for this particular websocket context */ + auto [ok, last] = webSocketContextData->topicTree->unsubscribe(webSocketData->subscriber, topic); + + /* Free us as subscribers if we unsubscribed from our last topic */ + if (ok && last) { + webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber); + webSocketData->subscriber = nullptr; + } + + return ok; + } + + /* Returns whether this socket is subscribed to the specified topic */ + bool isSubscribed(std::string_view topic) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + if (!webSocketData->subscriber) { + return false; + } + + Topic *topicPtr = webSocketContextData->topicTree->lookupTopic(topic); + if (!topicPtr) { + return false; + } + + return topicPtr->count(webSocketData->subscriber); + } + + /* Iterates all topics of this WebSocket. Every topic is represented by its full name. + * Can be called in close handler. It is possible to modify the subscription list while + * inside the callback ONLY IF not modifying the topic passed to the callback. + * Topic names are valid only for the duration of the callback. */ + void iterateTopics(MoveOnlyFunction cb) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + if (webSocketData->subscriber) { + /* Lock this subscriber for unsubscription / subscription */ + webSocketContextData->topicTree->iteratingSubscriber = webSocketData->subscriber; + + for (Topic *topicPtr : webSocketData->subscriber->topics) { + cb({topicPtr->name.data(), topicPtr->name.length()}); + } + + /* Unlock subscriber */ + webSocketContextData->topicTree->iteratingSubscriber = nullptr; + } + } + + /* Publish a message to a topic according to MQTT rules and syntax. Returns success. + * We, the WebSocket, must be subscribed to the topic itself and if so - no message will be sent to ourselves. + * Use App::publish for an unconditional publish that simply publishes to whomever might be subscribed. */ + bool publish(std::string_view topic, std::string_view message, OpCode opCode = OpCode::TEXT, bool compress = false) { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, + (us_socket_context_t *) us_socket_context(SSL, (us_socket_t *) this) + ); + + /* We cannot be a subscriber of this topic if we are not a subscriber of anything */ + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) this); + if (!webSocketData->subscriber) { + /* Failure, but still do return the number of subscribers */ + return false; + } + + /* Publish as sender, does not receive its own messages even if subscribed to relevant topics */ + if (message.length() >= LoopData::CORK_BUFFER_SIZE) { + return webSocketContextData->topicTree->publishBig(webSocketData->subscriber, topic, {message, opCode, compress}, [](Subscriber *s, TopicTreeBigMessage &message) { + auto *ws = (WebSocket *) s->user; + + ws->send(message.message, (OpCode)message.opCode, message.compress); + }); + } else { + return webSocketContextData->topicTree->publish(webSocketData->subscriber, topic, {std::string(message), opCode, compress}); + } + } +}; + +} + +#endif // UWS_WEBSOCKET_H diff --git a/thirdparty/include/uWebSockets/WebSocketContext.h b/thirdparty/include/uWebSockets/WebSocketContext.h new file mode 100644 index 0000000000000000000000000000000000000000..f9fad2662cef6f97010dfd8132177b32043e1732 --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketContext.h @@ -0,0 +1,421 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKETCONTEXT_H +#define UWS_WEBSOCKETCONTEXT_H + +#include "WebSocketContextData.h" +#include "WebSocketProtocol.h" +#include "WebSocketData.h" +#include "WebSocket.h" + +namespace uWS { + +template +struct WebSocketContext { + template friend struct TemplatedApp; + template friend struct WebSocketProtocol; +private: + WebSocketContext() = delete; + + us_socket_context_t *getSocketContext() { + return (us_socket_context_t *) this; + } + + WebSocketContextData *getExt() { + return (WebSocketContextData *) us_socket_context_ext(SSL, (us_socket_context_t *) this); + } + + /* If we have negotiated compression, set this frame compressed */ + static bool setCompressed(WebSocketState */*wState*/, void *s) { + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s); + + if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::ENABLED) { + webSocketData->compressionStatus = WebSocketData::CompressionStatus::COMPRESSED_FRAME; + return true; + } else { + return false; + } + } + + static void forceClose(WebSocketState */*wState*/, void *s, std::string_view reason = {}) { + us_socket_close(SSL, (us_socket_t *) s, (int) reason.length(), (void *) reason.data()); + } + + /* Returns true on breakage */ + static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, WebSocketState *webSocketState, void *s) { + /* WebSocketData and WebSocketContextData */ + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + WebSocketData *webSocketData = (WebSocketData *) us_socket_ext(SSL, (us_socket_t *) s); + + /* Is this a non-control frame? */ + if (opCode < 3) { + /* Did we get everything in one go? */ + if (!remainingBytes && fin && !webSocketData->fragmentBuffer.length()) { + + /* Handle compressed frame */ + if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) { + webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED; + + LoopData *loopData = (LoopData *) us_loop_ext(us_socket_context_loop(SSL, us_socket_context(SSL, (us_socket_t *) s))); + /* Decompress using shared or dedicated decompressor */ + std::optional inflatedFrame; + if (webSocketData->inflationStream) { + inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, false); + } else { + inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {data, length}, webSocketContextData->maxPayloadLength, true); + } + + if (!inflatedFrame.has_value()) { + forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION); + return true; + } else { + data = (char *) inflatedFrame->data(); + length = inflatedFrame->length(); + } + } + + /* Check text messages for Utf-8 validity */ + if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) { + forceClose(webSocketState, s, ERR_INVALID_TEXT); + return true; + } + + /* Emit message event & break if we are closed or shut down when returning */ + if (webSocketContextData->messageHandler) { + webSocketContextData->messageHandler((WebSocket *) s, std::string_view(data, length), (OpCode) opCode); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + } else { + /* Allocate fragment buffer up front first time */ + if (!webSocketData->fragmentBuffer.length()) { + webSocketData->fragmentBuffer.reserve(length + remainingBytes); + } + /* Fragments forming a big message are not caught until appending them */ + if (refusePayloadLength(length + webSocketData->fragmentBuffer.length(), webSocketState, s)) { + forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE); + return true; + } + webSocketData->fragmentBuffer.append(data, length); + + /* Are we done now? */ + // todo: what if we don't have any remaining bytes yet we are not fin? forceclose! + if (!remainingBytes && fin) { + + /* Handle compression */ + if (webSocketData->compressionStatus == WebSocketData::CompressionStatus::COMPRESSED_FRAME) { + webSocketData->compressionStatus = WebSocketData::CompressionStatus::ENABLED; + + /* 9 bytes of padding for libdeflate */ + webSocketData->fragmentBuffer.append("123456789"); + + LoopData *loopData = (LoopData *) us_loop_ext( + us_socket_context_loop(SSL, + us_socket_context(SSL, (us_socket_t *) s) + ) + ); + + /* Decompress using shared or dedicated decompressor */ + std::optional inflatedFrame; + if (webSocketData->inflationStream) { + inflatedFrame = webSocketData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, false); + } else { + inflatedFrame = loopData->inflationStream->inflate(loopData->zlibContext, {webSocketData->fragmentBuffer.data(), webSocketData->fragmentBuffer.length() - 9}, webSocketContextData->maxPayloadLength, true); + } + + if (!inflatedFrame.has_value()) { + forceClose(webSocketState, s, ERR_TOO_BIG_MESSAGE_INFLATION); + return true; + } else { + data = (char *) inflatedFrame->data(); + length = inflatedFrame->length(); + } + + + } else { + // reset length and data ptrs + length = webSocketData->fragmentBuffer.length(); + data = webSocketData->fragmentBuffer.data(); + } + + /* Check text messages for Utf-8 validity */ + if (opCode == 1 && !protocol::isValidUtf8((unsigned char *) data, length)) { + forceClose(webSocketState, s, ERR_INVALID_TEXT); + return true; + } + + /* Emit message and check for shutdown or close */ + if (webSocketContextData->messageHandler) { + webSocketContextData->messageHandler((WebSocket *) s, std::string_view(data, length), (OpCode) opCode); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + + /* If we shutdown or closed, this will be taken care of elsewhere */ + webSocketData->fragmentBuffer.clear(); + } + } + } else { + /* Control frames need the websocket to send pings, pongs and close */ + WebSocket *webSocket = (WebSocket *) s; + + if (!remainingBytes && fin && !webSocketData->controlTipLength) { + if (opCode == CLOSE) { + auto closeFrame = protocol::parseClosePayload(data, length); + webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length)); + return true; + } else { + if (opCode == PING) { + webSocket->send(std::string_view(data, length), (OpCode) OpCode::PONG); + if (webSocketContextData->pingHandler) { + webSocketContextData->pingHandler(webSocket, {data, length}); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + } else if (opCode == PONG) { + if (webSocketContextData->pongHandler) { + webSocketContextData->pongHandler(webSocket, {data, length}); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + } + } + } else { + /* Here we never mind any size optimizations as we are in the worst possible path */ + webSocketData->fragmentBuffer.append(data, length); + webSocketData->controlTipLength += (unsigned int) length; + + if (!remainingBytes && fin) { + char *controlBuffer = (char *) webSocketData->fragmentBuffer.data() + webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength; + if (opCode == CLOSE) { + protocol::CloseFrame closeFrame = protocol::parseClosePayload(controlBuffer, webSocketData->controlTipLength); + webSocket->end(closeFrame.code, std::string_view(closeFrame.message, closeFrame.length)); + return true; + } else { + if (opCode == PING) { + webSocket->send(std::string_view(controlBuffer, webSocketData->controlTipLength), (OpCode) OpCode::PONG); + if (webSocketContextData->pingHandler) { + webSocketContextData->pingHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength)); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + } else if (opCode == PONG) { + if (webSocketContextData->pongHandler) { + webSocketContextData->pongHandler(webSocket, std::string_view(controlBuffer, webSocketData->controlTipLength)); + if (us_socket_is_closed(SSL, (us_socket_t *) s) || webSocketData->isShuttingDown) { + return true; + } + } + } + } + + /* Same here, we do not care for any particular smart allocation scheme */ + webSocketData->fragmentBuffer.resize(webSocketData->fragmentBuffer.length() - webSocketData->controlTipLength); + webSocketData->controlTipLength = 0; + } + } + } + return false; + } + + static bool refusePayloadLength(uint64_t length, WebSocketState */*wState*/, void *s) { + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + + /* Return true for refuse, false for accept */ + return webSocketContextData->maxPayloadLength < length; + } + + WebSocketContext *init() { + /* Adopting a socket does not trigger open event. + * We arreive as WebSocket with timeout set and + * any backpressure from HTTP state kept. */ + + /* Handle socket disconnections */ + us_socket_context_on_close(SSL, getSocketContext(), [](auto *s, int code, void *reason) { + /* For whatever reason, if we already have emitted close event, do not emit it again */ + WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s)); + if (!webSocketData->isShuttingDown) { + /* Emit close event */ + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + + if (webSocketContextData->closeHandler) { + webSocketContextData->closeHandler((WebSocket *) s, 1006, {(char *) reason, (size_t) code}); + } + + /* Make sure to unsubscribe from any pub/sub node at exit */ + webSocketContextData->topicTree->freeSubscriber(webSocketData->subscriber); + webSocketData->subscriber = nullptr; + } + + /* Destruct in-placed data struct */ + webSocketData->~WebSocketData(); + + return s; + }); + + /* Handle WebSocket data streams */ + us_socket_context_on_data(SSL, getSocketContext(), [](auto *s, char *data, int length) { + + /* We need the websocket data */ + WebSocketData *webSocketData = (WebSocketData *) (us_socket_ext(SSL, s)); + + /* When in websocket shutdown mode, we do not care for ANY message, whether responding close frame or not. + * We only care for the TCP FIN really, not emitting any message after closing is key */ + if (webSocketData->isShuttingDown) { + return s; + } + + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + auto *asyncSocket = (AsyncSocket *) s; + + /* Every time we get data and not in shutdown state we simply reset the timeout */ + asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first); + webSocketData->hasTimedOut = false; + + /* We always cork on data */ + asyncSocket->cork(); + + /* This parser has virtually no overhead */ + WebSocketProtocol>::consume(data, (unsigned int) length, (WebSocketState *) webSocketData, s); + + /* Uncorking a closed socekt is fine, in fact it is needed */ + asyncSocket->uncork(); + + /* If uncorking was successful and we are in shutdown state then send TCP FIN */ + if (asyncSocket->getBufferedAmount() == 0) { + /* We can now be in shutdown state */ + if (webSocketData->isShuttingDown) { + /* Shutting down a closed socket is handled by uSockets and just fine */ + asyncSocket->shutdown(); + } + } + + return s; + }); + + /* Handle HTTP write out (note: SSL_read may trigger this spuriously, the app need to handle spurious calls) */ + us_socket_context_on_writable(SSL, getSocketContext(), [](auto *s) { + + /* NOTE: Are we called here corked? If so, the below write code is broken, since + * we will have 0 as getBufferedAmount due to writing to cork buffer, then sending TCP FIN before + * we actually uncorked and sent off things */ + + /* It makes sense to check for us_is_shut_down here and return if so, to avoid shutting down twice */ + if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) { + return s; + } + + AsyncSocket *asyncSocket = (AsyncSocket *) s; + WebSocketData *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s)); + + /* We store old backpressure since it is unclear whether write drained anything, + * however, in case of coming here with 0 backpressure we still need to emit drain event */ + unsigned int backpressure = asyncSocket->getBufferedAmount(); + + /* Drain as much as possible */ + asyncSocket->write(nullptr, 0); + + /* Behavior: if we actively drain backpressure, always reset timeout (even if we are in shutdown) */ + /* Also reset timeout if we came here with 0 backpressure */ + if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) { + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + asyncSocket->timeout(webSocketContextData->idleTimeoutComponents.first); + webSocketData->hasTimedOut = false; + } + + /* Are we in (WebSocket) shutdown mode? */ + if (webSocketData->isShuttingDown) { + /* Check if we just now drained completely */ + if (asyncSocket->getBufferedAmount() == 0) { + /* Now perform the actual TCP/TLS shutdown which was postponed due to backpressure */ + asyncSocket->shutdown(); + } + } else if (!backpressure || backpressure > asyncSocket->getBufferedAmount()) { + /* Only call drain if we actually drained backpressure or if we came here with 0 backpressure */ + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + if (webSocketContextData->drainHandler) { + webSocketContextData->drainHandler((WebSocket *) s); + } + /* No need to check for closed here as we leave the handler immediately*/ + } + + return s; + }); + + /* Handle FIN, HTTP does not support half-closed sockets, so simply close */ + us_socket_context_on_end(SSL, getSocketContext(), [](auto *s) { + + /* If we get a fin, we just close I guess */ + us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); + + return s; + }); + + /* Handle socket timeouts, simply close them so to not confuse client with FIN */ + us_socket_context_on_timeout(SSL, getSocketContext(), [](auto *s) { + + auto *webSocketData = (WebSocketData *)(us_socket_ext(SSL, s)); + auto *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, us_socket_context(SSL, (us_socket_t *) s)); + + if (webSocketContextData->sendPingsAutomatically && !webSocketData->isShuttingDown && !webSocketData->hasTimedOut) { + webSocketData->hasTimedOut = true; + us_socket_timeout(SSL, s, webSocketContextData->idleTimeoutComponents.second); + /* Send ping without being corked */ + ((AsyncSocket *) s)->write("\x89\x00", 2); + return s; + } + + /* Timeout is very simple; we just close it */ + /* Warning: we happen to know forceClose will not use first parameter so pass nullptr here */ + forceClose(nullptr, s, ERR_WEBSOCKET_TIMEOUT); + + return s; + }); + + return this; + } + + void free() { + WebSocketContextData *webSocketContextData = (WebSocketContextData *) us_socket_context_ext(SSL, (us_socket_context_t *) this); + webSocketContextData->~WebSocketContextData(); + + us_socket_context_free(SSL, (us_socket_context_t *) this); + } + +public: + /* WebSocket contexts are always child contexts to a HTTP context so no SSL options are needed as they are inherited */ + static WebSocketContext *create(Loop */*loop*/, us_socket_context_t *parentSocketContext, TopicTree *topicTree) { + WebSocketContext *webSocketContext = (WebSocketContext *) us_create_child_socket_context(SSL, parentSocketContext, sizeof(WebSocketContextData)); + if (!webSocketContext) { + return nullptr; + } + + /* Init socket context data */ + new ((WebSocketContextData *) us_socket_context_ext(SSL, (us_socket_context_t *)webSocketContext)) WebSocketContextData(topicTree); + return webSocketContext->init(); + } +}; + +} + +#endif // UWS_WEBSOCKETCONTEXT_H diff --git a/thirdparty/include/uWebSockets/WebSocketContextData.h b/thirdparty/include/uWebSockets/WebSocketContextData.h new file mode 100644 index 0000000000000000000000000000000000000000..ccd1530e214666206f07b6de6554ea52ecbd0e2b --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketContextData.h @@ -0,0 +1,95 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKETCONTEXTDATA_H +#define UWS_WEBSOCKETCONTEXTDATA_H + +#include "Loop.h" +#include "AsyncSocket.h" + +#include "MoveOnlyFunction.h" +#include +#include + +#include "WebSocketProtocol.h" +#include "TopicTree.h" +#include "WebSocketData.h" + +namespace uWS { + +template struct WebSocket; + +/* todo: this looks identical to WebSocketBehavior, why not just std::move that entire thing in? */ + +template +struct WebSocketContextData { +private: + +public: + + /* This one points to the App's shared topicTree */ + TopicTree *topicTree; + + /* The callbacks for this context */ + MoveOnlyFunction *)> openHandler = nullptr; + MoveOnlyFunction *, std::string_view, OpCode)> messageHandler = nullptr; + MoveOnlyFunction *)> drainHandler = nullptr; + MoveOnlyFunction *, int, std::string_view)> closeHandler = nullptr; + /* Todo: these should take message also; breaking change for v0.18 */ + MoveOnlyFunction *, std::string_view)> pingHandler = nullptr; + MoveOnlyFunction *, std::string_view)> pongHandler = nullptr; + + /* Settings for this context */ + size_t maxPayloadLength = 0; + + /* We do need these for async upgrade */ + CompressOptions compression; + + /* There needs to be a maxBackpressure which will force close everything over that limit */ + size_t maxBackpressure = 0; + bool closeOnBackpressureLimit; + bool resetIdleTimeoutOnSend; + bool sendPingsAutomatically; + + /* These are calculated on creation */ + std::pair idleTimeoutComponents; + + /* This is run once on start-up */ + void calculateIdleTimeoutCompnents(unsigned short idleTimeout) { + unsigned short margin = 4; + /* 4, 8 or 16 seconds margin based on idleTimeout */ + while ((int) idleTimeout - margin * 2 >= margin * 2 && margin < 16) { + margin = (unsigned short) (margin << 1); + } + idleTimeoutComponents = { + idleTimeout - (sendPingsAutomatically ? margin : 0), /* reduce normal idleTimeout if it is extended by ping-timeout */ + margin /* ping-timeout - also used for end() timeout */ + }; + } + + ~WebSocketContextData() { + + } + + WebSocketContextData(TopicTree *topicTree) : topicTree(topicTree) { + + } +}; + +} + +#endif // UWS_WEBSOCKETCONTEXTDATA_H diff --git a/thirdparty/include/uWebSockets/WebSocketData.h b/thirdparty/include/uWebSockets/WebSocketData.h new file mode 100644 index 0000000000000000000000000000000000000000..1506a51c92c8c4003a229da4be3ecbf14c1822de --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketData.h @@ -0,0 +1,85 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKETDATA_H +#define UWS_WEBSOCKETDATA_H + +#include "WebSocketProtocol.h" +#include "AsyncSocketData.h" +#include "PerMessageDeflate.h" +#include "TopicTree.h" + +#include + +namespace uWS { + +struct WebSocketData : AsyncSocketData, WebSocketState { + /* This guy has a lot of friends - why? */ + template friend struct WebSocketContext; + template friend struct WebSocketContextData; + template friend struct WebSocket; + template friend struct HttpContext; +private: + std::string fragmentBuffer; + unsigned int controlTipLength = 0; + bool isShuttingDown = 0; + bool hasTimedOut = false; + enum CompressionStatus : char { + DISABLED, + ENABLED, + COMPRESSED_FRAME + } compressionStatus; + + /* We might have a dedicated compressor */ + DeflationStream *deflationStream = nullptr; + /* And / or a dedicated decompressor */ + InflationStream *inflationStream = nullptr; + + /* We could be a subscriber */ + Subscriber *subscriber = nullptr; +public: + WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) : AsyncSocketData(std::move(backpressure)), WebSocketState() { + compressionStatus = perMessageDeflate ? ENABLED : DISABLED; + + /* Initialize the dedicated sliding window(s) */ + if (perMessageDeflate && (0 == (compressOptions & CompressOptions::SHARED_COMPRESSOR))) { + deflationStream = new DeflationStream(compressOptions); + } + + if (perMessageDeflate && (compressOptions & CompressOptions::DEDICATED_DECOMPRESSOR)) { + inflationStream = new InflationStream(); + } + } + + ~WebSocketData() { + if (deflationStream) { + delete deflationStream; + } + + if (inflationStream) { + delete inflationStream; + } + + if (subscriber) { + delete subscriber; + } + } +}; + +} + +#endif // UWS_WEBSOCKETDATA_H diff --git a/thirdparty/include/uWebSockets/WebSocketExtensions.h b/thirdparty/include/uWebSockets/WebSocketExtensions.h new file mode 100644 index 0000000000000000000000000000000000000000..93fd5df7fdab6172329a99915add9e705080542e --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketExtensions.h @@ -0,0 +1,256 @@ +/* + * Authored by Alex Hultman, 2018-2021. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKETEXTENSIONS_H +#define UWS_WEBSOCKETEXTENSIONS_H + +/* There is a new, huge bug scenario that needs to be fixed: + * pub/sub does not support being in DEDICATED_COMPRESSOR-mode while having + * some clients downgraded to SHARED_COMPRESSOR - we cannot allow the client to + * demand a downgrade to SHARED_COMPRESSOR (yet) until we fix that scenario in pub/sub */ +// #define UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX + +/* We forbid negotiating 8 windowBits since Zlib has a bug with this */ +// #define UWS_ALLOW_8_WINDOW_BITS + +#include +#include +#include +#include +#include + +namespace uWS { + +enum ExtensionTokens { + /* Standard permessage-deflate tokens */ + TOK_PERMESSAGE_DEFLATE = 1838, + TOK_SERVER_NO_CONTEXT_TAKEOVER = 2807, + TOK_CLIENT_NO_CONTEXT_TAKEOVER = 2783, + TOK_SERVER_MAX_WINDOW_BITS = 2372, + TOK_CLIENT_MAX_WINDOW_BITS = 2348, + /* Non-standard alias for Safari */ + TOK_X_WEBKIT_DEFLATE_FRAME = 2149, + TOK_NO_CONTEXT_TAKEOVER = 2049, + TOK_MAX_WINDOW_BITS = 1614 + +}; + +struct ExtensionsParser { +private: + int *lastInteger = nullptr; + +public: + /* Standard */ + bool perMessageDeflate = false; + bool serverNoContextTakeover = false; + bool clientNoContextTakeover = false; + int serverMaxWindowBits = 0; + int clientMaxWindowBits = 0; + + /* Non-standard Safari */ + bool xWebKitDeflateFrame = false; + bool noContextTakeover = false; + int maxWindowBits = 0; + + int getToken(const char *&in, const char *stop) { + while (in != stop && !isalnum(*in)) { + in++; + } + + /* Don't care more than this for now */ + static_assert(SHRT_MIN > INT_MIN, "Integer overflow fix is invalid for this platform, report this as a bug!"); + + int hashedToken = 0; + while (in != stop && (isalnum(*in) || *in == '-' || *in == '_')) { + if (isdigit(*in)) { + /* This check is a quick and incorrect fix for integer overflow + * in oss-fuzz but we don't care as it doesn't matter either way */ + if (hashedToken > SHRT_MIN && hashedToken < SHRT_MAX) { + hashedToken = hashedToken * 10 - (*in - '0'); + } + } else { + hashedToken += *in; + } + in++; + } + return hashedToken; + } + + ExtensionsParser(const char *data, size_t length) { + const char *stop = data + length; + int token = 1; + + /* Ignore anything before permessage-deflate or x-webkit-deflate-frame */ + for (; token && token != TOK_PERMESSAGE_DEFLATE && token != TOK_X_WEBKIT_DEFLATE_FRAME; token = getToken(data, stop)); + + /* What protocol are we going to use? */ + perMessageDeflate = (token == TOK_PERMESSAGE_DEFLATE); + xWebKitDeflateFrame = (token == TOK_X_WEBKIT_DEFLATE_FRAME); + + while ((token = getToken(data, stop))) { + switch (token) { + case TOK_X_WEBKIT_DEFLATE_FRAME: + /* Duplicates not allowed/supported */ + return; + case TOK_NO_CONTEXT_TAKEOVER: + noContextTakeover = true; + break; + case TOK_MAX_WINDOW_BITS: + maxWindowBits = 1; + lastInteger = &maxWindowBits; + break; + case TOK_PERMESSAGE_DEFLATE: + /* Duplicates not allowed/supported */ + return; + case TOK_SERVER_NO_CONTEXT_TAKEOVER: + serverNoContextTakeover = true; + break; + case TOK_CLIENT_NO_CONTEXT_TAKEOVER: + clientNoContextTakeover = true; + break; + case TOK_SERVER_MAX_WINDOW_BITS: + serverMaxWindowBits = 1; + lastInteger = &serverMaxWindowBits; + break; + case TOK_CLIENT_MAX_WINDOW_BITS: + clientMaxWindowBits = 1; + lastInteger = &clientMaxWindowBits; + break; + default: + if (token < 0 && lastInteger) { + *lastInteger = -token; + } + break; + } + } + } +}; + +/* Takes what we (the server) wants, returns what we got */ +static inline std::tuple negotiateCompression(bool wantCompression, int wantedCompressionWindow, int wantedInflationWindow, std::string_view offer) { + + /* If we don't want compression then we are done here */ + if (!wantCompression) { + return {false, 0, 0, ""}; + } + + ExtensionsParser ep(offer.data(), offer.length()); + + static thread_local std::string response; + response = ""; + + int compressionWindow = wantedCompressionWindow; + int inflationWindow = wantedInflationWindow; + bool compression = false; + + if (ep.xWebKitDeflateFrame) { + /* We now have compression */ + compression = true; + response = "x-webkit-deflate-frame"; + + /* If the other peer has DEMANDED us no sliding window, + * we cannot compress with anything other than shared compressor */ + if (ep.noContextTakeover) { + /* We must fail here right now (fix pub/sub) */ +#ifndef UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX + if (wantedCompressionWindow != 0) { + return {false, 0, 0, ""}; + } +#endif + + compressionWindow = 0; + } + + /* If the other peer has DEMANDED us to use a limited sliding window, + * we have to limit out compression sliding window */ + if (ep.maxWindowBits && ep.maxWindowBits < compressionWindow) { + compressionWindow = ep.maxWindowBits; +#ifndef UWS_ALLOW_8_WINDOW_BITS + /* We cannot really deny this, so we have to disable compression in this case */ + if (compressionWindow == 8) { + return {false, 0, 0, ""}; + } +#endif + } + + /* We decide our own inflation sliding window (and their compression sliding window) */ + if (wantedInflationWindow < 15) { + if (!wantedInflationWindow) { + response += "; no_context_takeover"; + } else { + response += "; max_window_bits=" + std::to_string(wantedInflationWindow); + } + } + } else if (ep.perMessageDeflate) { + /* We now have compression */ + compression = true; + response = "permessage-deflate"; + + if (ep.clientNoContextTakeover) { + inflationWindow = 0; + } else if (ep.clientMaxWindowBits && ep.clientMaxWindowBits != 1) { + inflationWindow = std::min(ep.clientMaxWindowBits, inflationWindow); + } + + /* Whatever we have now, write */ + if (inflationWindow < 15) { + if (!inflationWindow || !ep.clientMaxWindowBits) { + response += "; client_no_context_takeover"; + inflationWindow = 0; + } else { + response += "; client_max_window_bits=" + std::to_string(inflationWindow); + } + } + + /* This block basically lets the client lower it */ + if (ep.serverNoContextTakeover) { + /* This is an important (temporary) fix since we haven't allowed + * these two modes to mix, and pub/sub will not handle this case (yet) */ +#ifdef UWS_ALLOW_SHARED_AND_DEDICATED_COMPRESSOR_MIX + compressionWindow = 0; +#endif + } else if (ep.serverMaxWindowBits) { + compressionWindow = std::min(ep.serverMaxWindowBits, compressionWindow); +#ifndef UWS_ALLOW_8_WINDOW_BITS + /* Zlib cannot do windowBits=8, memLevel=1 so we raise it up to 9 minimum */ + if (compressionWindow == 8) { + compressionWindow = 9; + } +#endif + } + + /* Whatever we have now, write */ + if (compressionWindow < 15) { + if (!compressionWindow) { + response += "; server_no_context_takeover"; + } else { + response += "; server_max_window_bits=" + std::to_string(compressionWindow); + } + } + } + + /* A final sanity check (this check does not actually catch too high values!) */ + if ((compressionWindow && compressionWindow < 8) || compressionWindow > 15 || (inflationWindow && inflationWindow < 8) || inflationWindow > 15) { + return {false, 0, 0, ""}; + } + + return {compression, compressionWindow, inflationWindow, response}; +} + +} + +#endif // UWS_WEBSOCKETEXTENSIONS_H diff --git a/thirdparty/include/uWebSockets/WebSocketHandshake.h b/thirdparty/include/uWebSockets/WebSocketHandshake.h new file mode 100644 index 0000000000000000000000000000000000000000..808415e4ab0ae3e2c19123a38e40e471fd024587 --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketHandshake.h @@ -0,0 +1,145 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#ifndef UWS_WEBSOCKETHANDSHAKE_H +#define UWS_WEBSOCKETHANDSHAKE_H + +#include +#include + +namespace uWS { + +struct WebSocketHandshake { + template + struct static_for { + void operator()(uint32_t *a, uint32_t *b) { + static_for()(a, b); + T::template f(a, b); + } + }; + + template + struct static_for<0, T> { + void operator()(uint32_t */*a*/, uint32_t */*hash*/) {} + }; + + static inline uint32_t rol(uint32_t value, size_t bits) {return (value << bits) | (value >> (32 - bits));} + static inline uint32_t blk(uint32_t b[16], size_t i) { + return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ b[i], 1); + } + + struct Sha1Loop1 { + template + static inline void f(uint32_t *a, uint32_t *b) { + a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + } + }; + struct Sha1Loop2 { + template + static inline void f(uint32_t *a, uint32_t *b) { + b[i] = blk(b, i); + a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5); + a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30); + } + }; + struct Sha1Loop3 { + template + static inline void f(uint32_t *a, uint32_t *b) { + b[(i + 4) % 16] = blk(b, (i + 4) % 16); + a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + } + }; + struct Sha1Loop4 { + template + static inline void f(uint32_t *a, uint32_t *b) { + b[(i + 8) % 16] = blk(b, (i + 8) % 16); + a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + } + }; + struct Sha1Loop5 { + template + static inline void f(uint32_t *a, uint32_t *b) { + b[(i + 12) % 16] = blk(b, (i + 12) % 16); + a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + } + }; + struct Sha1Loop6 { + template + static inline void f(uint32_t *a, uint32_t *b) { + b[i] += a[4 - i]; + } + }; + + static inline void sha1(uint32_t hash[5], uint32_t b[16]) { + uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]}; + static_for<16, Sha1Loop1>()(a, b); + static_for<4, Sha1Loop2>()(a, b); + static_for<20, Sha1Loop3>()(a, b); + static_for<20, Sha1Loop4>()(a, b); + static_for<20, Sha1Loop5>()(a, b); + static_for<5, Sha1Loop6>()(a, hash); + } + + static inline void base64(unsigned char *src, char *dst) { + const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (int i = 0; i < 18; i += 3) { + *dst++ = b64[(src[i] >> 2) & 63]; + *dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)]; + *dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)]; + *dst++ = b64[src[i + 2] & 63]; + } + *dst++ = b64[(src[18] >> 2) & 63]; + *dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)]; + *dst++ = b64[((src[19] & 15) << 2)]; + *dst++ = '='; + } + +public: + static inline void generate(const char input[24], char output[28]) { + uint32_t b_output[5] = { + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 + }; + uint32_t b_input[16] = { + 0, 0, 0, 0, 0, 0, 0x32353845, 0x41464135, 0x2d453931, 0x342d3437, 0x44412d39, + 0x3543412d, 0x43354142, 0x30444338, 0x35423131, 0x80000000 + }; + + for (int i = 0; i < 6; i++) { + b_input[i] = (uint32_t) ((input[4 * i + 3] & 0xff) | (input[4 * i + 2] & 0xff) << 8 | (input[4 * i + 1] & 0xff) << 16 | (input[4 * i + 0] & 0xff) << 24); + } + sha1(b_output, b_input); + uint32_t last_b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480}; + sha1(b_output, last_b); + for (int i = 0; i < 5; i++) { + uint32_t tmp = b_output[i]; + char *bytes = (char *) &b_output[i]; + bytes[3] = (char) (tmp & 0xff); + bytes[2] = (char) ((tmp >> 8) & 0xff); + bytes[1] = (char) ((tmp >> 16) & 0xff); + bytes[0] = (char) ((tmp >> 24) & 0xff); + } + base64((unsigned char *) b_output, output); + } +}; + +} + +#endif // UWS_WEBSOCKETHANDSHAKE_H diff --git a/thirdparty/include/uWebSockets/WebSocketProtocol.h b/thirdparty/include/uWebSockets/WebSocketProtocol.h new file mode 100644 index 0000000000000000000000000000000000000000..0d8790f001ae81d36c4043225fe14d3e0c972478 --- /dev/null +++ b/thirdparty/include/uWebSockets/WebSocketProtocol.h @@ -0,0 +1,456 @@ +/* + * Authored by Alex Hultman, 2018-2020. + * Intellectual property of third-party. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UWS_WEBSOCKETPROTOCOL_H +#define UWS_WEBSOCKETPROTOCOL_H + +#include + +#include +#include +#include +#include + +namespace uWS { + +/* We should not overcomplicate these */ +const std::string_view ERR_TOO_BIG_MESSAGE("Received too big message"); +const std::string_view ERR_WEBSOCKET_TIMEOUT("WebSocket timed out from inactivity"); +const std::string_view ERR_INVALID_TEXT("Received invalid UTF-8"); +const std::string_view ERR_TOO_BIG_MESSAGE_INFLATION("Received too big message, or other inflation error"); +const std::string_view ERR_INVALID_CLOSE_PAYLOAD("Received invalid close payload"); + +enum OpCode : unsigned char { + TEXT = 1, + BINARY = 2, + CLOSE = 8, + PING = 9, + PONG = 10 +}; + +enum { + CLIENT, + SERVER +}; + +// 24 bytes perfectly +template +struct WebSocketState { +public: + static const unsigned int SHORT_MESSAGE_HEADER = isServer ? 6 : 2; + static const unsigned int MEDIUM_MESSAGE_HEADER = isServer ? 8 : 4; + static const unsigned int LONG_MESSAGE_HEADER = isServer ? 14 : 10; + + // 16 bytes + struct State { + unsigned int wantsHead : 1; + unsigned int spillLength : 4; + signed int opStack : 2; // -1, 0, 1 + unsigned int lastFin : 1; + + // 15 bytes + unsigned char spill[LONG_MESSAGE_HEADER - 1]; + OpCode opCode[2]; + + State() { + wantsHead = true; + spillLength = 0; + opStack = -1; + lastFin = true; + } + + } state; + + // 8 bytes + unsigned int remainingBytes = 0; + char mask[isServer ? 4 : 1]; +}; + +namespace protocol { + +template +T bit_cast(char *c) { + T val; + memcpy(&val, c, sizeof(T)); + return val; +} + +/* Byte swap for little-endian systems */ +template +T cond_byte_swap(T value) { + uint32_t endian_test = 1; + if (*((char *)&endian_test)) { + union { + T i; + uint8_t b[sizeof(T)]; + } src = { value }, dst; + + for (unsigned int i = 0; i < sizeof(value); i++) { + dst.b[i] = src.b[sizeof(value) - 1 - i]; + } + + return dst.i; + } + return value; +} + +// Based on utf8_check.c by Markus Kuhn, 2005 +// https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c +// Optimized for predominantly 7-bit content by Alex Hultman, 2016 +// Licensed as Zlib, like the rest of this project +static bool isValidUtf8(unsigned char *s, size_t length) +{ + for (unsigned char *e = s + length; s != e; ) { + if (s + 4 <= e) { + uint32_t tmp; + memcpy(&tmp, s, 4); + if ((tmp & 0x80808080) == 0) { + s += 4; + continue; + } + } + + while (!(*s & 0x80)) { + if (++s == e) { + return true; + } + } + + if ((s[0] & 0x60) == 0x40) { + if (s + 1 >= e || (s[1] & 0xc0) != 0x80 || (s[0] & 0xfe) == 0xc0) { + return false; + } + s += 2; + } else if ((s[0] & 0xf0) == 0xe0) { + if (s + 2 >= e || (s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || + (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || (s[0] == 0xed && (s[1] & 0xe0) == 0xa0)) { + return false; + } + s += 3; + } else if ((s[0] & 0xf8) == 0xf0) { + if (s + 3 >= e || (s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || (s[3] & 0xc0) != 0x80 || + (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) { + return false; + } + s += 4; + } else { + return false; + } + } + return true; +} + +struct CloseFrame { + uint16_t code; + char *message; + size_t length; +}; + +static inline CloseFrame parseClosePayload(char *src, size_t length) { + /* If we get no code or message, default to reporting 1005 no status code present */ + CloseFrame cf = {1005, nullptr, 0}; + if (length >= 2) { + memcpy(&cf.code, src, 2); + cf = {cond_byte_swap(cf.code), src + 2, length - 2}; + if (cf.code < 1000 || cf.code > 4999 || (cf.code > 1011 && cf.code < 4000) || + (cf.code >= 1004 && cf.code <= 1006) || !isValidUtf8((unsigned char *) cf.message, cf.length)) { + /* Even though we got a WebSocket close frame, it in itself is abnormal */ + return {1006, nullptr, 0}; + } + } + return cf; +} + +static inline size_t formatClosePayload(char *dst, uint16_t code, const char *message, size_t length) { + /* We could have more strict checks here, but never append code 0 or 1005 or 1006 */ + if (code && code != 1005 && code != 1006) { + code = cond_byte_swap(code); + memcpy(dst, &code, 2); + /* It is invalid to pass nullptr to memcpy, even though length is 0 */ + if (message) { + memcpy(dst + 2, message, length); + } + return length + 2; + } + return 0; +} + +static inline size_t messageFrameSize(size_t messageSize) { + if (messageSize < 126) { + return 2 + messageSize; + } else if (messageSize <= UINT16_MAX) { + return 4 + messageSize; + } + return 10 + messageSize; +} + +enum { + SND_CONTINUATION = 1, + SND_NO_FIN = 2, + SND_COMPRESSED = 64 +}; + +template +static inline size_t formatMessage(char *dst, const char *src, size_t length, OpCode opCode, size_t reportedLength, bool compressed) { + size_t messageLength; + size_t headerLength; + if (reportedLength < 126) { + headerLength = 2; + dst[1] = (char) reportedLength; + } else if (reportedLength <= UINT16_MAX) { + headerLength = 4; + dst[1] = 126; + uint16_t tmp = cond_byte_swap((uint16_t) reportedLength); + memcpy(&dst[2], &tmp, sizeof(uint16_t)); + } else { + headerLength = 10; + dst[1] = 127; + uint64_t tmp = cond_byte_swap((uint64_t) reportedLength); + memcpy(&dst[2], &tmp, sizeof(uint64_t)); + } + + int flags = 0; + dst[0] = (char) ((flags & SND_NO_FIN ? 0 : 128) | (compressed ? SND_COMPRESSED : 0)); + if (!(flags & SND_CONTINUATION)) { + dst[0] |= (char) opCode; + } + + char mask[4]; + if (!isServer) { + dst[1] |= 0x80; + uint32_t random = (uint32_t) rand(); + memcpy(mask, &random, 4); + memcpy(dst + headerLength, &random, 4); + headerLength += 4; + } + + messageLength = headerLength + length; + memcpy(dst + headerLength, src, length); + + if (!isServer) { + + // overwrites up to 3 bytes outside of the given buffer! + //WebSocketProtocol::unmaskInplace(dst + headerLength, dst + headerLength + length, mask); + + // this is not optimal + char *start = dst + headerLength; + char *stop = start + length; + int i = 0; + while (start != stop) { + (*start++) ^= mask[i++ % 4]; + } + } + return messageLength; +} + +} + +// essentially this is only a parser +template +struct WIN32_EXPORT WebSocketProtocol { +public: + static const unsigned int SHORT_MESSAGE_HEADER = isServer ? 6 : 2; + static const unsigned int MEDIUM_MESSAGE_HEADER = isServer ? 8 : 4; + static const unsigned int LONG_MESSAGE_HEADER = isServer ? 14 : 10; + +protected: + static inline bool isFin(char *frame) {return *((unsigned char *) frame) & 128;} + static inline unsigned char getOpCode(char *frame) {return *((unsigned char *) frame) & 15;} + static inline unsigned char payloadLength(char *frame) {return ((unsigned char *) frame)[1] & 127;} + static inline bool rsv23(char *frame) {return *((unsigned char *) frame) & 48;} + static inline bool rsv1(char *frame) {return *((unsigned char *) frame) & 64;} + + static inline void unmaskImprecise(char *dst, char *src, char *mask, unsigned int length) { + for (unsigned int n = (length >> 2) + 1; n; n--) { + *(dst++) = *(src++) ^ mask[0]; + *(dst++) = *(src++) ^ mask[1]; + *(dst++) = *(src++) ^ mask[2]; + *(dst++) = *(src++) ^ mask[3]; + } + } + + static inline void unmaskImpreciseCopyMask(char *dst, char *src, char *maskPtr, unsigned int length) { + char mask[4] = {maskPtr[0], maskPtr[1], maskPtr[2], maskPtr[3]}; + unmaskImprecise(dst, src, mask, length); + } + + static inline void rotateMask(unsigned int offset, char *mask) { + char originalMask[4] = {mask[0], mask[1], mask[2], mask[3]}; + mask[(0 + offset) % 4] = originalMask[0]; + mask[(1 + offset) % 4] = originalMask[1]; + mask[(2 + offset) % 4] = originalMask[2]; + mask[(3 + offset) % 4] = originalMask[3]; + } + + static inline void unmaskInplace(char *data, char *stop, char *mask) { + while (data < stop) { + *(data++) ^= mask[0]; + *(data++) ^= mask[1]; + *(data++) ^= mask[2]; + *(data++) ^= mask[3]; + } + } + + template + static inline bool consumeMessage(T payLength, char *&src, unsigned int &length, WebSocketState *wState, void *user) { + if (getOpCode(src)) { + if (wState->state.opStack == 1 || (!wState->state.lastFin && getOpCode(src) < 2)) { + Impl::forceClose(wState, user); + return true; + } + wState->state.opCode[++wState->state.opStack] = (OpCode) getOpCode(src); + } else if (wState->state.opStack == -1) { + Impl::forceClose(wState, user); + return true; + } + wState->state.lastFin = isFin(src); + + if (Impl::refusePayloadLength(payLength, wState, user)) { + Impl::forceClose(wState, user, ERR_TOO_BIG_MESSAGE); + return true; + } + + if (payLength + MESSAGE_HEADER <= length) { + if (isServer) { + unmaskImpreciseCopyMask(src + MESSAGE_HEADER - 4, src + MESSAGE_HEADER, src + MESSAGE_HEADER - 4, (unsigned int) payLength); + if (Impl::handleFragment(src + MESSAGE_HEADER - 4, payLength, 0, wState->state.opCode[wState->state.opStack], isFin(src), wState, user)) { + return true; + } + } else { + if (Impl::handleFragment(src + MESSAGE_HEADER, payLength, 0, wState->state.opCode[wState->state.opStack], isFin(src), wState, user)) { + return true; + } + } + + if (isFin(src)) { + wState->state.opStack--; + } + + src += payLength + MESSAGE_HEADER; + length -= (unsigned int) (payLength + MESSAGE_HEADER); + wState->state.spillLength = 0; + return false; + } else { + wState->state.spillLength = 0; + wState->state.wantsHead = false; + wState->remainingBytes = (unsigned int) (payLength - length + MESSAGE_HEADER); + bool fin = isFin(src); + if (isServer) { + memcpy(wState->mask, src + MESSAGE_HEADER - 4, 4); + unmaskImprecise(src, src + MESSAGE_HEADER, wState->mask, length - MESSAGE_HEADER); + rotateMask(4 - (length - MESSAGE_HEADER) % 4, wState->mask); + } else { + src += MESSAGE_HEADER; + } + Impl::handleFragment(src, length - MESSAGE_HEADER, wState->remainingBytes, wState->state.opCode[wState->state.opStack], fin, wState, user); + return true; + } + } + + static inline bool consumeContinuation(char *&src, unsigned int &length, WebSocketState *wState, void *user) { + if (wState->remainingBytes <= length) { + if (isServer) { + unsigned int n = wState->remainingBytes >> 2; + unmaskInplace(src, src + n * 4, wState->mask); + for (unsigned int i = 0, s = wState->remainingBytes % 4; i < s; i++) { + src[n * 4 + i] ^= wState->mask[i]; + } + } + + if (Impl::handleFragment(src, wState->remainingBytes, 0, wState->state.opCode[wState->state.opStack], wState->state.lastFin, wState, user)) { + return false; + } + + if (wState->state.lastFin) { + wState->state.opStack--; + } + + src += wState->remainingBytes; + length -= wState->remainingBytes; + wState->state.wantsHead = true; + return true; + } else { + if (isServer) { + unmaskInplace(src, src + ((length >> 2) + 1) * 4, wState->mask); + } + + wState->remainingBytes -= length; + if (Impl::handleFragment(src, length, wState->remainingBytes, wState->state.opCode[wState->state.opStack], wState->state.lastFin, wState, user)) { + return false; + } + + if (isServer && length % 4) { + rotateMask(4 - (length % 4), wState->mask); + } + return false; + } + } + +public: + WebSocketProtocol() { + + } + + static inline void consume(char *src, unsigned int length, WebSocketState *wState, void *user) { + if (wState->state.spillLength) { + src -= wState->state.spillLength; + length += wState->state.spillLength; + memcpy(src, wState->state.spill, wState->state.spillLength); + } + if (wState->state.wantsHead) { + parseNext: + while (length >= SHORT_MESSAGE_HEADER) { + + // invalid reserved bits / invalid opcodes / invalid control frames / set compressed frame + if ((rsv1(src) && !Impl::setCompressed(wState, user)) || rsv23(src) || (getOpCode(src) > 2 && getOpCode(src) < 8) || + getOpCode(src) > 10 || (getOpCode(src) > 2 && (!isFin(src) || payloadLength(src) > 125))) { + Impl::forceClose(wState, user); + return; + } + + if (payloadLength(src) < 126) { + if (consumeMessage(payloadLength(src), src, length, wState, user)) { + return; + } + } else if (payloadLength(src) == 126) { + if (length < MEDIUM_MESSAGE_HEADER) { + break; + } else if(consumeMessage(protocol::cond_byte_swap(protocol::bit_cast(src + 2)), src, length, wState, user)) { + return; + } + } else if (length < LONG_MESSAGE_HEADER) { + break; + } else if (consumeMessage(protocol::cond_byte_swap(protocol::bit_cast(src + 2)), src, length, wState, user)) { + return; + } + } + if (length) { + memcpy(wState->state.spill, src, length); + wState->state.spillLength = length & 0xf; + } + } else if (consumeContinuation(src, length, wState, user)) { + goto parseNext; + } + } + + static const int CONSUME_POST_PADDING = 4; + static const int CONSUME_PRE_PADDING = LONG_MESSAGE_HEADER - 1; +}; + +} + +#endif // UWS_WEBSOCKETPROTOCOL_H diff --git a/thirdparty/include/win/include/pthread.h b/thirdparty/include/win/include/pthread.h new file mode 100755 index 0000000000000000000000000000000000000000..436ea8b6b1f24618ee60fe2c3d4fd653c99602aa --- /dev/null +++ b/thirdparty/include/win/include/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,9,1,0 +#define PTW32_VERSION_STRING "2, 9, 1, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#if !defined(RC_INVOKED) + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if defined(_UWIN) +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_PTW32_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#if defined(PTW32_INCLUDE_WINDOWS_H) +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +typedef unsigned long ULONG_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if defined(HAVE_PTW32_CONFIG_H) +#include "config.h" +#endif /* HAVE_PTW32_CONFIG_H */ + +#if !defined(NEED_FTIME) +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if defined(HAVE_SIGNAL_H) +#include +#endif /* HAVE_SIGNAL_H */ + +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#if !defined(ENOTSUP) +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#if !defined(ETIMEDOUT) +# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */ +#endif + +#if !defined(ENOSYS) +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#if !defined(EDEADLK) +# if defined(EDEADLOCK) +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +/* POSIX 2008 - related to robust mutexes */ +#if !defined(EOWNERDEAD) +# define EOWNERDEAD 43 +#endif +#if !defined(ENOTRECOVERABLE) +# define ENOTRECOVERABLE 44 +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#if !defined(PTW32_INCLUDE_WINDOWS_H) +#if !defined(HANDLE) +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#if !defined(DWORD) +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#if !defined(HAVE_STRUCT_TIMESPEC) +#define HAVE_STRUCT_TIMESPEC +#if !defined(_TIMESPEC_DEFINED) +#define _TIMESPEC_DEFINED +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif /* _TIMESPEC_DEFINED */ +#endif /* HAVE_STRUCT_TIMESPEC */ + +#if !defined(SIG_BLOCK) +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#if !defined(SIG_UNBLOCK) +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#if !defined(SIG_SETMASK) +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200809L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200809L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200809L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200809L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200809L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if defined(__GNUC__) && !defined(__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_mutexattr_{get,set}robust + */ + PTHREAD_MUTEX_STALLED = 0, /* Default */ + PTHREAD_MUTEX_ROBUST = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *)(size_t) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#if defined(__CLEANUP_SEH) + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#if defined(__CLEANUP_C) + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#if defined(__CLEANUP_CXX) + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(PTW32_CDECL *start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (PTW32_CDECL *init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + ptw32_cleanup_callback_t routine, + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (PTW32_CDECL *destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust( + pthread_mutexattr_t *attr, + int robust); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust( + const pthread_mutexattr_t * attr, + int * robust); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); +PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); +/* + * Returns the win32 thread ID for POSIX thread. + */ +PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#if !defined(_UWIN) +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# if !defined(errno) +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#if defined(__cplusplus) + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if !defined(PTW32_BUILD) + +#if defined(__CLEANUP_SEH) + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#if defined(__CLEANUP_CXX) + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#if defined(_MSC_VER) + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#if !defined(PtW32NoCatchWarn) + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #if defined(PtW32CatchAll)") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#if defined(PTW32__HANDLE_DEF) +# undef HANDLE +#endif +#if defined(PTW32__DWORD_DEF) +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/thirdparty/include/win/include/qedit.h b/thirdparty/include/win/include/qedit.h new file mode 100755 index 0000000000000000000000000000000000000000..36dd323a9bcde3d6e5927e578b0bf8566d971173 --- /dev/null +++ b/thirdparty/include/win/include/qedit.h @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////////// +#include +#ifndef __qedit_h__ +#define __qedit_h__ + +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +/////////////////////////////////////////////////////////////////////////////////// + +interface +ISampleGrabberCB +: + public IUnknown +{ + virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0; + virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +interface +ISampleGrabber +: + public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_VideoEffects1Category = { 0xcc7bfb42, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_VideoEffects2Category = { 0xcc7bfb43, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_AudioEffects1Category = { 0xcc7bfb44, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_AudioEffects2Category = { 0xcc7bfb45, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +#endif + +/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/thirdparty/include/win/include/sched.h b/thirdparty/include/win/include/sched.h new file mode 100755 index 0000000000000000000000000000000000000000..f36a97a66be55bfbfdf79525ae316df1c690f854 --- /dev/null +++ b/thirdparty/include/win/include/sched.h @@ -0,0 +1,183 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(_SCHED_H) +#define _SCHED_H + +#undef PTW32_SCHED_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_SCHED_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_SCHED_LEVEL_MAX 3 + +#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) +#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX +/* Include everything */ +#endif + + +#if defined(__GNUC__) && !defined(__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ + +#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) +# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +# else + typedef int pid_t; +# endif +#else + typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_SCHED_LEVEL +#undef PTW32_SCHED_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/thirdparty/include/win/include/semaphore.h b/thirdparty/include/win/include/semaphore.h new file mode 100755 index 0000000000000000000000000000000000000000..c6e9407e25bcae999512b9bdf20370fe37aed82a --- /dev/null +++ b/thirdparty/include/win/include/semaphore.h @@ -0,0 +1,169 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_SEMAPHORE_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_SEMAPHORE_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_SEMAPHORE_LEVEL +#define PTW32_SEMAPHORE_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_SEMAPHORE_LEVEL +#define PTW32_SEMAPHORE_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_SEMAPHORE_LEVEL_MAX 3 + +#if !defined(PTW32_SEMAPHORE_LEVEL) +#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX +/* Include everything */ +#endif + +#if defined(__GNUC__) && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +#if !defined(HAVE_MODE_T) +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_SEMAPHORE_LEVEL +#undef PTW32_SEMAPHORE_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/thirdparty/include/x264.h b/thirdparty/include/x264.h new file mode 100755 index 0000000000000000000000000000000000000000..5f7294e3a7149fc4e555501f9a9a504c1c9d592d --- /dev/null +++ b/thirdparty/include/x264.h @@ -0,0 +1,965 @@ +/***************************************************************************** + * x264.h: x264 public header + ***************************************************************************** + * Copyright (C) 2003-2018 x264 project + * + * Authors: Laurent Aimar + * Loren Merritt + * Fiona Glaser + * + * 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 of the License, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at licensing@x264.com. + *****************************************************************************/ + +#ifndef X264_X264_H +#define X264_X264_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_STDINT_H) && !defined(_STDINT_H_) && !defined(_STDINT_H_INCLUDED) && !defined(_STDINT) &&\ + !defined(_SYS_STDINT_H_) && !defined(_INTTYPES_H) && !defined(_INTTYPES_H_) && !defined(_INTTYPES) +# ifdef _MSC_VER +# pragma message("You must include stdint.h or inttypes.h before x264.h") +# else +# warning You must include stdint.h or inttypes.h before x264.h +# endif +#endif + +#include + +#include "x264_config.h" + +#define X264_BUILD 157 + +/* Application developers planning to link against a shared library version of + * libx264 from a Microsoft Visual Studio or similar development environment + * will need to define X264_API_IMPORTS before including this header. + * This clause does not apply to MinGW, similar development environments, or non + * Windows platforms. */ +#ifdef X264_API_IMPORTS +#define X264_API __declspec(dllimport) +#else +#define X264_API +#endif + +/* x264_t: + * opaque handler for encoder */ +typedef struct x264_t x264_t; + +/**************************************************************************** + * NAL structure and functions + ****************************************************************************/ + +enum nal_unit_type_e +{ + NAL_UNKNOWN = 0, + NAL_SLICE = 1, + NAL_SLICE_DPA = 2, + NAL_SLICE_DPB = 3, + NAL_SLICE_DPC = 4, + NAL_SLICE_IDR = 5, /* ref_idc != 0 */ + NAL_SEI = 6, /* ref_idc == 0 */ + NAL_SPS = 7, + NAL_PPS = 8, + NAL_AUD = 9, + NAL_FILLER = 12, + /* ref_idc == 0 for 6,9,10,11,12 */ +}; +enum nal_priority_e +{ + NAL_PRIORITY_DISPOSABLE = 0, + NAL_PRIORITY_LOW = 1, + NAL_PRIORITY_HIGH = 2, + NAL_PRIORITY_HIGHEST = 3, +}; + +/* The data within the payload is already NAL-encapsulated; the ref_idc and type + * are merely in the struct for easy access by the calling application. + * All data returned in an x264_nal_t, including the data in p_payload, is no longer + * valid after the next call to x264_encoder_encode. Thus it must be used or copied + * before calling x264_encoder_encode or x264_encoder_headers again. */ +typedef struct x264_nal_t +{ + int i_ref_idc; /* nal_priority_e */ + int i_type; /* nal_unit_type_e */ + int b_long_startcode; + int i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */ + int i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */ + + /* Size of payload (including any padding) in bytes. */ + int i_payload; + /* If param->b_annexb is set, Annex-B bytestream with startcode. + * Otherwise, startcode is replaced with a 4-byte size. + * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */ + uint8_t *p_payload; + + /* Size of padding in bytes. */ + int i_padding; +} x264_nal_t; + +/**************************************************************************** + * Encoder parameters + ****************************************************************************/ +/* CPU flags */ + +/* x86 */ +#define X264_CPU_MMX (1<<0) +#define X264_CPU_MMX2 (1<<1) /* MMX2 aka MMXEXT aka ISSE */ +#define X264_CPU_MMXEXT X264_CPU_MMX2 +#define X264_CPU_SSE (1<<2) +#define X264_CPU_SSE2 (1<<3) +#define X264_CPU_LZCNT (1<<4) +#define X264_CPU_SSE3 (1<<5) +#define X264_CPU_SSSE3 (1<<6) +#define X264_CPU_SSE4 (1<<7) /* SSE4.1 */ +#define X264_CPU_SSE42 (1<<8) /* SSE4.2 */ +#define X264_CPU_AVX (1<<9) /* Requires OS support even if YMM registers aren't used */ +#define X264_CPU_XOP (1<<10) /* AMD XOP */ +#define X264_CPU_FMA4 (1<<11) /* AMD FMA4 */ +#define X264_CPU_FMA3 (1<<12) +#define X264_CPU_BMI1 (1<<13) +#define X264_CPU_BMI2 (1<<14) +#define X264_CPU_AVX2 (1<<15) +#define X264_CPU_AVX512 (1<<16) /* AVX-512 {F, CD, BW, DQ, VL}, requires OS support */ +/* x86 modifiers */ +#define X264_CPU_CACHELINE_32 (1<<17) /* avoid memory loads that span the border between two cachelines */ +#define X264_CPU_CACHELINE_64 (1<<18) /* 32/64 is the size of a cacheline in bytes */ +#define X264_CPU_SSE2_IS_SLOW (1<<19) /* avoid most SSE2 functions on Athlon64 */ +#define X264_CPU_SSE2_IS_FAST (1<<20) /* a few functions are only faster on Core2 and Phenom */ +#define X264_CPU_SLOW_SHUFFLE (1<<21) /* The Conroe has a slow shuffle unit (relative to overall SSE performance) */ +#define X264_CPU_STACK_MOD4 (1<<22) /* if stack is only mod4 and not mod16 */ +#define X264_CPU_SLOW_ATOM (1<<23) /* The Atom is terrible: slow SSE unaligned loads, slow + * SIMD multiplies, slow SIMD variable shifts, slow pshufb, + * cacheline split penalties -- gather everything here that + * isn't shared by other CPUs to avoid making half a dozen + * new SLOW flags. */ +#define X264_CPU_SLOW_PSHUFB (1<<24) /* such as on the Intel Atom */ +#define X264_CPU_SLOW_PALIGNR (1<<25) /* such as on the AMD Bobcat */ + +/* PowerPC */ +#define X264_CPU_ALTIVEC 0x0000001 + +/* ARM and AArch64 */ +#define X264_CPU_ARMV6 0x0000001 +#define X264_CPU_NEON 0x0000002 /* ARM NEON */ +#define X264_CPU_FAST_NEON_MRC 0x0000004 /* Transfer from NEON to ARM register is fast (Cortex-A9) */ +#define X264_CPU_ARMV8 0x0000008 + +/* MIPS */ +#define X264_CPU_MSA 0x0000001 /* MIPS MSA */ + +/* Analyse flags */ +#define X264_ANALYSE_I4x4 0x0001 /* Analyse i4x4 */ +#define X264_ANALYSE_I8x8 0x0002 /* Analyse i8x8 (requires 8x8 transform) */ +#define X264_ANALYSE_PSUB16x16 0x0010 /* Analyse p16x8, p8x16 and p8x8 */ +#define X264_ANALYSE_PSUB8x8 0x0020 /* Analyse p8x4, p4x8, p4x4 */ +#define X264_ANALYSE_BSUB16x16 0x0100 /* Analyse b16x8, b8x16 and b8x8 */ + +#define X264_DIRECT_PRED_NONE 0 +#define X264_DIRECT_PRED_SPATIAL 1 +#define X264_DIRECT_PRED_TEMPORAL 2 +#define X264_DIRECT_PRED_AUTO 3 +#define X264_ME_DIA 0 +#define X264_ME_HEX 1 +#define X264_ME_UMH 2 +#define X264_ME_ESA 3 +#define X264_ME_TESA 4 +#define X264_CQM_FLAT 0 +#define X264_CQM_JVT 1 +#define X264_CQM_CUSTOM 2 +#define X264_RC_CQP 0 +#define X264_RC_CRF 1 +#define X264_RC_ABR 2 +#define X264_QP_AUTO 0 +#define X264_AQ_NONE 0 +#define X264_AQ_VARIANCE 1 +#define X264_AQ_AUTOVARIANCE 2 +#define X264_AQ_AUTOVARIANCE_BIASED 3 +#define X264_B_ADAPT_NONE 0 +#define X264_B_ADAPT_FAST 1 +#define X264_B_ADAPT_TRELLIS 2 +#define X264_WEIGHTP_NONE 0 +#define X264_WEIGHTP_SIMPLE 1 +#define X264_WEIGHTP_SMART 2 +#define X264_B_PYRAMID_NONE 0 +#define X264_B_PYRAMID_STRICT 1 +#define X264_B_PYRAMID_NORMAL 2 +#define X264_KEYINT_MIN_AUTO 0 +#define X264_KEYINT_MAX_INFINITE (1<<30) + +/* AVC-Intra flavors */ +#define X264_AVCINTRA_FLAVOR_PANASONIC 0 +#define X264_AVCINTRA_FLAVOR_SONY 1 + +static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 }; +static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 }; +static const char * const x264_b_pyramid_names[] = { "none", "strict", "normal", 0 }; +static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 }; +static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 }; +static const char * const x264_fullrange_names[] = { "off", "on", 0 }; +static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020", "smpte428", + "smpte431", "smpte432", 0 }; +static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", + "iec61966-2-4", "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", "smpte2084", "smpte428", "arib-std-b67", 0 }; +static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", "bt2020nc", "bt2020c", + "smpte2085", "chroma-derived-nc", "chroma-derived-c", "ICtCp", 0 }; +static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 }; +static const char * const x264_avcintra_flavor_names[] = { "panasonic", "sony", 0 }; + +/* Colorspace type */ +#define X264_CSP_MASK 0x00ff /* */ +#define X264_CSP_NONE 0x0000 /* Invalid mode */ +#define X264_CSP_I400 0x0001 /* monochrome 4:0:0 */ +#define X264_CSP_I420 0x0002 /* yuv 4:2:0 planar */ +#define X264_CSP_YV12 0x0003 /* yvu 4:2:0 planar */ +#define X264_CSP_NV12 0x0004 /* yuv 4:2:0, with one y plane and one packed u+v */ +#define X264_CSP_NV21 0x0005 /* yuv 4:2:0, with one y plane and one packed v+u */ +#define X264_CSP_I422 0x0006 /* yuv 4:2:2 planar */ +#define X264_CSP_YV16 0x0007 /* yvu 4:2:2 planar */ +#define X264_CSP_NV16 0x0008 /* yuv 4:2:2, with one y plane and one packed u+v */ +#define X264_CSP_YUYV 0x0009 /* yuyv 4:2:2 packed */ +#define X264_CSP_UYVY 0x000a /* uyvy 4:2:2 packed */ +#define X264_CSP_V210 0x000b /* 10-bit yuv 4:2:2 packed in 32 */ +#define X264_CSP_I444 0x000c /* yuv 4:4:4 planar */ +#define X264_CSP_YV24 0x000d /* yvu 4:4:4 planar */ +#define X264_CSP_BGR 0x000e /* packed bgr 24bits */ +#define X264_CSP_BGRA 0x000f /* packed bgr 32bits */ +#define X264_CSP_RGB 0x0010 /* packed rgb 24bits */ +#define X264_CSP_MAX 0x0011 /* end of list */ +#define X264_CSP_VFLIP 0x1000 /* the csp is vertically flipped */ +#define X264_CSP_HIGH_DEPTH 0x2000 /* the csp has a depth of 16 bits per pixel component */ + +/* Slice type */ +#define X264_TYPE_AUTO 0x0000 /* Let x264 choose the right type */ +#define X264_TYPE_IDR 0x0001 +#define X264_TYPE_I 0x0002 +#define X264_TYPE_P 0x0003 +#define X264_TYPE_BREF 0x0004 /* Non-disposable B-frame */ +#define X264_TYPE_B 0x0005 +#define X264_TYPE_KEYFRAME 0x0006 /* IDR or I depending on b_open_gop option */ +#define IS_X264_TYPE_I(x) ((x)==X264_TYPE_I || (x)==X264_TYPE_IDR || (x)==X264_TYPE_KEYFRAME) +#define IS_X264_TYPE_B(x) ((x)==X264_TYPE_B || (x)==X264_TYPE_BREF) + +/* Log level */ +#define X264_LOG_NONE (-1) +#define X264_LOG_ERROR 0 +#define X264_LOG_WARNING 1 +#define X264_LOG_INFO 2 +#define X264_LOG_DEBUG 3 + +/* Threading */ +#define X264_THREADS_AUTO 0 /* Automatically select optimal number of threads */ +#define X264_SYNC_LOOKAHEAD_AUTO (-1) /* Automatically select optimal lookahead thread buffer size */ + +/* HRD */ +#define X264_NAL_HRD_NONE 0 +#define X264_NAL_HRD_VBR 1 +#define X264_NAL_HRD_CBR 2 + +/* Zones: override ratecontrol or other options for specific sections of the video. + * See x264_encoder_reconfig() for which options can be changed. + * If zones overlap, whichever comes later in the list takes precedence. */ +typedef struct x264_zone_t +{ + int i_start, i_end; /* range of frame numbers */ + int b_force_qp; /* whether to use qp vs bitrate factor */ + int i_qp; + float f_bitrate_factor; + struct x264_param_t *param; +} x264_zone_t; + +typedef struct x264_param_t +{ + /* CPU flags */ + unsigned int cpu; + int i_threads; /* encode multiple frames in parallel */ + int i_lookahead_threads; /* multiple threads for lookahead analysis */ + int b_sliced_threads; /* Whether to use slice-based threading. */ + int b_deterministic; /* whether to allow non-deterministic optimizations when threaded */ + int b_cpu_independent; /* force canonical behavior rather than cpu-dependent optimal algorithms */ + int i_sync_lookahead; /* threaded lookahead buffer */ + + /* Video Properties */ + int i_width; + int i_height; + int i_csp; /* CSP of encoded bitstream */ + int i_bitdepth; + int i_level_idc; + int i_frame_total; /* number of frames to encode if known, else 0 */ + + /* NAL HRD + * Uses Buffering and Picture Timing SEIs to signal HRD + * The HRD in H.264 was not designed with VFR in mind. + * It is therefore not recommendeded to use NAL HRD with VFR. + * Furthermore, reconfiguring the VBV (via x264_encoder_reconfig) + * will currently generate invalid HRD. */ + int i_nal_hrd; + + struct + { + /* they will be reduced to be 0 < x <= 65535 and prime */ + int i_sar_height; + int i_sar_width; + + int i_overscan; /* 0=undef, 1=no overscan, 2=overscan */ + + /* see h264 annex E for the values of the following */ + int i_vidformat; + int b_fullrange; + int i_colorprim; + int i_transfer; + int i_colmatrix; + int i_chroma_loc; /* both top & bottom */ + } vui; + + /* Bitstream parameters */ + int i_frame_reference; /* Maximum number of reference frames */ + int i_dpb_size; /* Force a DPB size larger than that implied by B-frames and reference frames. + * Useful in combination with interactive error resilience. */ + int i_keyint_max; /* Force an IDR keyframe at this interval */ + int i_keyint_min; /* Scenecuts closer together than this are coded as I, not IDR. */ + int i_scenecut_threshold; /* how aggressively to insert extra I frames */ + int b_intra_refresh; /* Whether or not to use periodic intra refresh instead of IDR frames. */ + + int i_bframe; /* how many b-frame between 2 references pictures */ + int i_bframe_adaptive; + int i_bframe_bias; + int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */ + int b_open_gop; + int b_bluray_compat; + int i_avcintra_class; + int i_avcintra_flavor; + + int b_deblocking_filter; + int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */ + int i_deblocking_filter_beta; /* [-6, 6] idem */ + + int b_cabac; + int i_cabac_init_idc; + + int b_interlaced; + int b_constrained_intra; + + int i_cqm_preset; + char *psz_cqm_file; /* filename (in UTF-8) of CQM file, JM format */ + uint8_t cqm_4iy[16]; /* used only if i_cqm_preset == X264_CQM_CUSTOM */ + uint8_t cqm_4py[16]; + uint8_t cqm_4ic[16]; + uint8_t cqm_4pc[16]; + uint8_t cqm_8iy[64]; + uint8_t cqm_8py[64]; + uint8_t cqm_8ic[64]; + uint8_t cqm_8pc[64]; + + /* Log */ + void (*pf_log)( void *, int i_level, const char *psz, va_list ); + void *p_log_private; + int i_log_level; + int b_full_recon; /* fully reconstruct frames, even when not necessary for encoding. Implied by psz_dump_yuv */ + char *psz_dump_yuv; /* filename (in UTF-8) for reconstructed frames */ + + /* Encoder analyser parameters */ + struct + { + unsigned int intra; /* intra partitions */ + unsigned int inter; /* inter partitions */ + + int b_transform_8x8; + int i_weighted_pred; /* weighting for P-frames */ + int b_weighted_bipred; /* implicit weighting for B-frames */ + int i_direct_mv_pred; /* spatial vs temporal mv prediction */ + int i_chroma_qp_offset; + + int i_me_method; /* motion estimation algorithm to use (X264_ME_*) */ + int i_me_range; /* integer pixel motion estimation search range (from predicted mv) */ + int i_mv_range; /* maximum length of a mv (in pixels). -1 = auto, based on level */ + int i_mv_range_thread; /* minimum space between threads. -1 = auto, based on number of threads. */ + int i_subpel_refine; /* subpixel motion estimation quality */ + int b_chroma_me; /* chroma ME for subpel and mode decision in P-frames */ + int b_mixed_references; /* allow each mb partition to have its own reference number */ + int i_trellis; /* trellis RD quantization */ + int b_fast_pskip; /* early SKIP detection on P-frames */ + int b_dct_decimate; /* transform coefficient thresholding on P-frames */ + int i_noise_reduction; /* adaptive pseudo-deadzone */ + float f_psy_rd; /* Psy RD strength */ + float f_psy_trellis; /* Psy trellis strength */ + int b_psy; /* Toggle all psy optimizations */ + + int b_mb_info; /* Use input mb_info data in x264_picture_t */ + int b_mb_info_update; /* Update the values in mb_info according to the results of encoding. */ + + /* the deadzone size that will be used in luma quantization */ + int i_luma_deadzone[2]; /* {inter, intra} */ + + int b_psnr; /* compute and print PSNR stats */ + int b_ssim; /* compute and print SSIM stats */ + } analyse; + + /* Rate control parameters */ + struct + { + int i_rc_method; /* X264_RC_* */ + + int i_qp_constant; /* 0=lossless */ + int i_qp_min; /* min allowed QP value */ + int i_qp_max; /* max allowed QP value */ + int i_qp_step; /* max QP step between frames */ + + int i_bitrate; + float f_rf_constant; /* 1pass VBR, nominal QP */ + float f_rf_constant_max; /* In CRF mode, maximum CRF as caused by VBV */ + float f_rate_tolerance; + int i_vbv_max_bitrate; + int i_vbv_buffer_size; + float f_vbv_buffer_init; /* <=1: fraction of buffer_size. >1: kbit */ + float f_ip_factor; + float f_pb_factor; + + /* VBV filler: force CBR VBV and use filler bytes to ensure hard-CBR. + * Implied by NAL-HRD CBR. */ + int b_filler; + + int i_aq_mode; /* psy adaptive QP. (X264_AQ_*) */ + float f_aq_strength; + int b_mb_tree; /* Macroblock-tree ratecontrol. */ + int i_lookahead; + + /* 2pass */ + int b_stat_write; /* Enable stat writing in psz_stat_out */ + char *psz_stat_out; /* output filename (in UTF-8) of the 2pass stats file */ + int b_stat_read; /* Read stat from psz_stat_in and use it */ + char *psz_stat_in; /* input filename (in UTF-8) of the 2pass stats file */ + + /* 2pass params (same as ffmpeg ones) */ + float f_qcompress; /* 0.0 => cbr, 1.0 => constant qp */ + float f_qblur; /* temporally blur quants */ + float f_complexity_blur; /* temporally blur complexity */ + x264_zone_t *zones; /* ratecontrol overrides */ + int i_zones; /* number of zone_t's */ + char *psz_zones; /* alternate method of specifying zones */ + } rc; + + /* Cropping Rectangle parameters: added to those implicitly defined by + non-mod16 video resolutions. */ + struct + { + unsigned int i_left; + unsigned int i_top; + unsigned int i_right; + unsigned int i_bottom; + } crop_rect; + + /* frame packing arrangement flag */ + int i_frame_packing; + + /* alternative transfer SEI */ + int i_alternative_transfer; + + /* Muxing parameters */ + int b_aud; /* generate access unit delimiters */ + int b_repeat_headers; /* put SPS/PPS before each keyframe */ + int b_annexb; /* if set, place start codes (4 bytes) before NAL units, + * otherwise place size (4 bytes) before NAL units. */ + int i_sps_id; /* SPS and PPS id number */ + int b_vfr_input; /* VFR input. If 1, use timebase and timestamps for ratecontrol purposes. + * If 0, use fps only. */ + int b_pulldown; /* use explicity set timebase for CFR */ + uint32_t i_fps_num; + uint32_t i_fps_den; + uint32_t i_timebase_num; /* Timebase numerator */ + uint32_t i_timebase_den; /* Timebase denominator */ + + int b_tff; + + /* Pulldown: + * The correct pic_struct must be passed with each input frame. + * The input timebase should be the timebase corresponding to the output framerate. This should be constant. + * e.g. for 3:2 pulldown timebase should be 1001/30000 + * The PTS passed with each frame must be the PTS of the frame after pulldown is applied. + * Frame doubling and tripling require b_vfr_input set to zero (see H.264 Table D-1) + * + * Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this. + */ + + int b_pic_struct; + + /* Fake Interlaced. + * + * Used only when b_interlaced=0. Setting this flag makes it possible to flag the stream as PAFF interlaced yet + * encode all frames progessively. It is useful for encoding 25p and 30p Blu-Ray streams. + */ + + int b_fake_interlaced; + + /* Don't optimize header parameters based on video content, e.g. ensure that splitting an input video, compressing + * each part, and stitching them back together will result in identical SPS/PPS. This is necessary for stitching + * with container formats that don't allow multiple SPS/PPS. */ + int b_stitchable; + + int b_opencl; /* use OpenCL when available */ + int i_opencl_device; /* specify count of GPU devices to skip, for CLI users */ + void *opencl_device_id; /* pass explicit cl_device_id as void*, for API users */ + char *psz_clbin_file; /* filename (in UTF-8) of the compiled OpenCL kernel cache file */ + + /* Slicing parameters */ + int i_slice_max_size; /* Max size per slice in bytes; includes estimated NAL overhead. */ + int i_slice_max_mbs; /* Max number of MBs per slice; overrides i_slice_count. */ + int i_slice_min_mbs; /* Min number of MBs per slice */ + int i_slice_count; /* Number of slices per frame: forces rectangular slices. */ + int i_slice_count_max; /* Absolute cap on slices per frame; stops applying slice-max-size + * and slice-max-mbs if this is reached. */ + + /* Optional callback for freeing this x264_param_t when it is done being used. + * Only used when the x264_param_t sits in memory for an indefinite period of time, + * i.e. when an x264_param_t is passed to x264_t in an x264_picture_t or in zones. + * Not used when x264_encoder_reconfig is called directly. */ + void (*param_free)( void* ); + + /* Optional low-level callback for low-latency encoding. Called for each output NAL unit + * immediately after the NAL unit is finished encoding. This allows the calling application + * to begin processing video data (e.g. by sending packets over a network) before the frame + * is done encoding. + * + * This callback MUST do the following in order to work correctly: + * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 64. + * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer. + * After these steps, the content of nal is valid and can be used in the same way as if + * the NAL unit were output by x264_encoder_encode. + * + * This does not need to be synchronous with the encoding process: the data pointed to + * by nal (both before and after x264_nal_encode) will remain valid until the next + * x264_encoder_encode call. The callback must be re-entrant. + * + * This callback does not work with frame-based threads; threads must be disabled + * or sliced-threads enabled. This callback also does not work as one would expect + * with HRD -- since the buffering period SEI cannot be calculated until the frame + * is finished encoding, it will not be sent via this callback. + * + * Note also that the NALs are not necessarily returned in order when sliced threads is + * enabled. Accordingly, the variable i_first_mb and i_last_mb are available in + * x264_nal_t to help the calling application reorder the slices if necessary. + * + * When this callback is enabled, x264_encoder_encode does not return valid NALs; + * the calling application is expected to acquire all output NALs through the callback. + * + * It is generally sensible to combine this callback with a use of slice-max-mbs or + * slice-max-size. + * + * The opaque pointer is the opaque pointer from the input frame associated with this + * NAL unit. This helps distinguish between nalu_process calls from different sources, + * e.g. if doing multiple encodes in one process. + */ + void (*nalu_process)( x264_t *h, x264_nal_t *nal, void *opaque ); +} x264_param_t; + +void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal ); + +/**************************************************************************** + * H.264 level restriction information + ****************************************************************************/ + +typedef struct x264_level_t +{ + uint8_t level_idc; + uint32_t mbps; /* max macroblock processing rate (macroblocks/sec) */ + uint32_t frame_size; /* max frame size (macroblocks) */ + uint32_t dpb; /* max decoded picture buffer (mbs) */ + uint32_t bitrate; /* max bitrate (kbit/sec) */ + uint32_t cpb; /* max vbv buffer (kbit) */ + uint16_t mv_range; /* max vertical mv component range (pixels) */ + uint8_t mvs_per_2mb; /* max mvs per 2 consecutive mbs. */ + uint8_t slice_rate; /* ?? */ + uint8_t mincr; /* min compression ratio */ + uint8_t bipred8x8; /* limit bipred to >=8x8 */ + uint8_t direct8x8; /* limit b_direct to >=8x8 */ + uint8_t frame_only; /* forbid interlacing */ +} x264_level_t; + +/* all of the levels defined in the standard, terminated by .level_idc=0 */ +X264_API extern const x264_level_t x264_levels[]; + +/**************************************************************************** + * Basic parameter handling functions + ****************************************************************************/ + +/* x264_param_default: + * fill x264_param_t with default values and do CPU detection */ +void x264_param_default( x264_param_t * ); + +/* x264_param_parse: + * set one parameter by name. + * returns 0 on success, or returns one of the following errors. + * note: BAD_VALUE occurs only if it can't even parse the value, + * numerical range is not checked until x264_encoder_open() or + * x264_encoder_reconfig(). + * value=NULL means "true" for boolean options, but is a BAD_VALUE for non-booleans. */ +#define X264_PARAM_BAD_NAME (-1) +#define X264_PARAM_BAD_VALUE (-2) +int x264_param_parse( x264_param_t *, const char *name, const char *value ); + +/**************************************************************************** + * Advanced parameter handling functions + ****************************************************************************/ + +/* These functions expose the full power of x264's preset-tune-profile system for + * easy adjustment of large numbers of internal parameters. + * + * In order to replicate x264CLI's option handling, these functions MUST be called + * in the following order: + * 1) x264_param_default_preset + * 2) Custom user options (via param_parse or directly assigned variables) + * 3) x264_param_apply_fastfirstpass + * 4) x264_param_apply_profile + * + * Additionally, x264CLI does not apply step 3 if the preset chosen is "placebo" + * or --slow-firstpass is set. */ + +/* x264_param_default_preset: + * The same as x264_param_default, but also use the passed preset and tune + * to modify the default settings. + * (either can be NULL, which implies no preset or no tune, respectively) + * + * Currently available presets are, ordered from fastest to slowest: */ +static const char * const x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 }; + +/* The presets can also be indexed numerically, as in: + * x264_param_default_preset( ¶m, "3", ... ) + * with ultrafast mapping to "0" and placebo mapping to "9". This mapping may + * of course change if new presets are added in between, but will always be + * ordered from fastest to slowest. + * + * Warning: the speed of these presets scales dramatically. Ultrafast is a full + * 100 times faster than placebo! + * + * Currently available tunings are: */ +static const char * const x264_tune_names[] = { "film", "animation", "grain", "stillimage", "psnr", "ssim", "fastdecode", "zerolatency", 0 }; + +/* Multiple tunings can be used if separated by a delimiter in ",./-+", + * however multiple psy tunings cannot be used. + * film, animation, grain, stillimage, psnr, and ssim are psy tunings. + * + * returns 0 on success, negative on failure (e.g. invalid preset/tune name). */ +int x264_param_default_preset( x264_param_t *, const char *preset, const char *tune ); + +/* x264_param_apply_fastfirstpass: + * If first-pass mode is set (rc.b_stat_read == 0, rc.b_stat_write == 1), + * modify the encoder settings to disable options generally not useful on + * the first pass. */ +void x264_param_apply_fastfirstpass( x264_param_t * ); + +/* x264_param_apply_profile: + * Applies the restrictions of the given profile. + * Currently available profiles are, from most to least restrictive: */ +static const char * const x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 }; + +/* (can be NULL, in which case the function will do nothing) + * + * Does NOT guarantee that the given profile will be used: if the restrictions + * of "High" are applied to settings that are already Baseline-compatible, the + * stream will remain baseline. In short, it does not increase settings, only + * decrease them. + * + * returns 0 on success, negative on failure (e.g. invalid profile name). */ +int x264_param_apply_profile( x264_param_t *, const char *profile ); + +/**************************************************************************** + * Picture structures and functions + ****************************************************************************/ + +/* x264_chroma_format: + * Specifies the chroma formats that x264 supports encoding. When this + * value is non-zero, then it represents a X264_CSP_* that is the only + * chroma format that x264 supports encoding. If the value is 0 then + * there are no restrictions. */ +X264_API extern const int x264_chroma_format; + +enum pic_struct_e +{ + PIC_STRUCT_AUTO = 0, // automatically decide (default) + PIC_STRUCT_PROGRESSIVE = 1, // progressive frame + // "TOP" and "BOTTOM" are not supported in x264 (PAFF only) + PIC_STRUCT_TOP_BOTTOM = 4, // top field followed by bottom + PIC_STRUCT_BOTTOM_TOP = 5, // bottom field followed by top + PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field repeated + PIC_STRUCT_BOTTOM_TOP_BOTTOM = 7, // bottom field, top field, bottom field repeated + PIC_STRUCT_DOUBLE = 8, // double frame + PIC_STRUCT_TRIPLE = 9, // triple frame +}; + +typedef struct x264_hrd_t +{ + double cpb_initial_arrival_time; + double cpb_final_arrival_time; + double cpb_removal_time; + + double dpb_output_time; +} x264_hrd_t; + +/* Arbitrary user SEI: + * Payload size is in bytes and the payload pointer must be valid. + * Payload types and syntax can be found in Annex D of the H.264 Specification. + * SEI payload alignment bits as described in Annex D must be included at the + * end of the payload if needed. + * The payload should not be NAL-encapsulated. + * Payloads are written first in order of input, apart from in the case when HRD + * is enabled where payloads are written after the Buffering Period SEI. */ + +typedef struct x264_sei_payload_t +{ + int payload_size; + int payload_type; + uint8_t *payload; +} x264_sei_payload_t; + +typedef struct x264_sei_t +{ + int num_payloads; + x264_sei_payload_t *payloads; + /* In: optional callback to free each payload AND x264_sei_payload_t when used. */ + void (*sei_free)( void* ); +} x264_sei_t; + +typedef struct x264_image_t +{ + int i_csp; /* Colorspace */ + int i_plane; /* Number of image planes */ + int i_stride[4]; /* Strides for each plane */ + uint8_t *plane[4]; /* Pointers to each plane */ +} x264_image_t; + +typedef struct x264_image_properties_t +{ + /* All arrays of data here are ordered as follows: + * each array contains one offset per macroblock, in raster scan order. In interlaced + * mode, top-field MBs and bottom-field MBs are interleaved at the row level. + * Macroblocks are 16x16 blocks of pixels (with respect to the luma plane). For the + * purposes of calculating the number of macroblocks, width and height are rounded up to + * the nearest 16. If in interlaced mode, height is rounded up to the nearest 32 instead. */ + + /* In: an array of quantizer offsets to be applied to this image during encoding. + * These are added on top of the decisions made by x264. + * Offsets can be fractional; they are added before QPs are rounded to integer. + * Adaptive quantization must be enabled to use this feature. Behavior if quant + * offsets differ between encoding passes is undefined. */ + float *quant_offsets; + /* In: optional callback to free quant_offsets when used. + * Useful if one wants to use a different quant_offset array for each frame. */ + void (*quant_offsets_free)( void* ); + + /* In: optional array of flags for each macroblock. + * Allows specifying additional information for the encoder such as which macroblocks + * remain unchanged. Usable flags are listed below. + * x264_param_t.analyse.b_mb_info must be set to use this, since x264 needs to track + * extra data internally to make full use of this information. + * + * Out: if b_mb_info_update is set, x264 will update this array as a result of encoding. + * + * For "MBINFO_CONSTANT", it will remove this flag on any macroblock whose decoded + * pixels have changed. This can be useful for e.g. noting which areas of the + * frame need to actually be blitted. Note: this intentionally ignores the effects + * of deblocking for the current frame, which should be fine unless one needs exact + * pixel-perfect accuracy. + * + * Results for MBINFO_CONSTANT are currently only set for P-frames, and are not + * guaranteed to enumerate all blocks which haven't changed. (There may be false + * negatives, but no false positives.) + */ + uint8_t *mb_info; + /* In: optional callback to free mb_info when used. */ + void (*mb_info_free)( void* ); + + /* The macroblock is constant and remains unchanged from the previous frame. */ + #define X264_MBINFO_CONSTANT (1<<0) + /* More flags may be added in the future. */ + + /* Out: SSIM of the the frame luma (if x264_param_t.b_ssim is set) */ + double f_ssim; + /* Out: Average PSNR of the frame (if x264_param_t.b_psnr is set) */ + double f_psnr_avg; + /* Out: PSNR of Y, U, and V (if x264_param_t.b_psnr is set) */ + double f_psnr[3]; + + /* Out: Average effective CRF of the encoded frame */ + double f_crf_avg; +} x264_image_properties_t; + +typedef struct x264_picture_t +{ + /* In: force picture type (if not auto) + * If x264 encoding parameters are violated in the forcing of picture types, + * x264 will correct the input picture type and log a warning. + * Out: type of the picture encoded */ + int i_type; + /* In: force quantizer for != X264_QP_AUTO */ + int i_qpplus1; + /* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_struct=1. + * use pic_struct_e for pic_struct inputs + * Out: pic_struct element associated with frame */ + int i_pic_struct; + /* Out: whether this frame is a keyframe. Important when using modes that result in + * SEI recovery points being used instead of IDR frames. */ + int b_keyframe; + /* In: user pts, Out: pts of encoded picture (user)*/ + int64_t i_pts; + /* Out: frame dts. When the pts of the first frame is close to zero, + * initial frames may have a negative dts which must be dealt with by any muxer */ + int64_t i_dts; + /* In: custom encoding parameters to be set from this frame forwards + (in coded order, not display order). If NULL, continue using + parameters from the previous frame. Some parameters, such as + aspect ratio, can only be changed per-GOP due to the limitations + of H.264 itself; in this case, the caller must force an IDR frame + if it needs the changed parameter to apply immediately. */ + x264_param_t *param; + /* In: raw image data */ + /* Out: reconstructed image data. x264 may skip part of the reconstruction process, + e.g. deblocking, in frames where it isn't necessary. To force complete + reconstruction, at a small speed cost, set b_full_recon. */ + x264_image_t img; + /* In: optional information to modify encoder decisions for this frame + * Out: information about the encoded frame */ + x264_image_properties_t prop; + /* Out: HRD timing information. Output only when i_nal_hrd is set. */ + x264_hrd_t hrd_timing; + /* In: arbitrary user SEI (e.g subtitles, AFDs) */ + x264_sei_t extra_sei; + /* private user data. copied from input to output frames. */ + void *opaque; +} x264_picture_t; + +/* x264_picture_init: + * initialize an x264_picture_t. Needs to be done if the calling application + * allocates its own x264_picture_t as opposed to using x264_picture_alloc. */ +void x264_picture_init( x264_picture_t *pic ); + +/* x264_picture_alloc: + * alloc data for a picture. You must call x264_picture_clean on it. + * returns 0 on success, or -1 on malloc failure or invalid colorspace. */ +int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height ); + +/* x264_picture_clean: + * free associated resource for a x264_picture_t allocated with + * x264_picture_alloc ONLY */ +void x264_picture_clean( x264_picture_t *pic ); + +/**************************************************************************** + * Encoder functions + ****************************************************************************/ + +/* Force a link error in the case of linking against an incompatible API version. + * Glue #defines exist to force correct macro expansion; the final output of the macro + * is x264_encoder_open_##X264_BUILD (for purposes of dlopen). */ +#define x264_encoder_glue1(x,y) x##y +#define x264_encoder_glue2(x,y) x264_encoder_glue1(x,y) +#define x264_encoder_open x264_encoder_glue2(x264_encoder_open_,X264_BUILD) + +/* x264_encoder_open: + * create a new encoder handler, all parameters from x264_param_t are copied */ +x264_t *x264_encoder_open( x264_param_t * ); + +/* x264_encoder_reconfig: + * various parameters from x264_param_t are copied. + * this takes effect immediately, on whichever frame is encoded next; + * due to delay, this may not be the next frame passed to encoder_encode. + * if the change should apply to some particular frame, use x264_picture_t->param instead. + * returns 0 on success, negative on parameter validation error. + * not all parameters can be changed; see the actual function for a detailed breakdown. + * + * since not all parameters can be changed, moving from preset to preset may not always + * fully copy all relevant parameters, but should still work usably in practice. however, + * more so than for other presets, many of the speed shortcuts used in ultrafast cannot be + * switched out of; using reconfig to switch between ultrafast and other presets is not + * recommended without a more fine-grained breakdown of parameters to take this into account. */ +int x264_encoder_reconfig( x264_t *, x264_param_t * ); +/* x264_encoder_parameters: + * copies the current internal set of parameters to the pointer provided + * by the caller. useful when the calling application needs to know + * how x264_encoder_open has changed the parameters, or the current state + * of the encoder after multiple x264_encoder_reconfig calls. + * note that the data accessible through pointers in the returned param struct + * (e.g. filenames) should not be modified by the calling application. */ +void x264_encoder_parameters( x264_t *, x264_param_t * ); +/* x264_encoder_headers: + * return the SPS and PPS that will be used for the whole stream. + * *pi_nal is the number of NAL units outputted in pp_nal. + * returns the number of bytes in the returned NALs. + * returns negative on error. + * the payloads of all output NALs are guaranteed to be sequential in memory. */ +int x264_encoder_headers( x264_t *, x264_nal_t **pp_nal, int *pi_nal ); +/* x264_encoder_encode: + * encode one picture. + * *pi_nal is the number of NAL units outputted in pp_nal. + * returns the number of bytes in the returned NALs. + * returns negative on error and zero if no NAL units returned. + * the payloads of all output NALs are guaranteed to be sequential in memory. */ +int x264_encoder_encode( x264_t *, x264_nal_t **pp_nal, int *pi_nal, x264_picture_t *pic_in, x264_picture_t *pic_out ); +/* x264_encoder_close: + * close an encoder handler */ +void x264_encoder_close( x264_t * ); +/* x264_encoder_delayed_frames: + * return the number of currently delayed (buffered) frames + * this should be used at the end of the stream, to know when you have all the encoded frames. */ +int x264_encoder_delayed_frames( x264_t * ); +/* x264_encoder_maximum_delayed_frames( x264_t * ): + * return the maximum number of delayed (buffered) frames that can occur with the current + * parameters. */ +int x264_encoder_maximum_delayed_frames( x264_t * ); +/* x264_encoder_intra_refresh: + * If an intra refresh is not in progress, begin one with the next P-frame. + * If an intra refresh is in progress, begin one as soon as the current one finishes. + * Requires that b_intra_refresh be set. + * + * Useful for interactive streaming where the client can tell the server that packet loss has + * occurred. In this case, keyint can be set to an extremely high value so that intra refreshes + * only occur when calling x264_encoder_intra_refresh. + * + * In multi-pass encoding, if x264_encoder_intra_refresh is called differently in each pass, + * behavior is undefined. + * + * Should not be called during an x264_encoder_encode. */ +void x264_encoder_intra_refresh( x264_t * ); +/* x264_encoder_invalidate_reference: + * An interactive error resilience tool, designed for use in a low-latency one-encoder-few-clients + * system. When the client has packet loss or otherwise incorrectly decodes a frame, the encoder + * can be told with this command to "forget" the frame and all frames that depend on it, referencing + * only frames that occurred before the loss. This will force a keyframe if no frames are left to + * reference after the aforementioned "forgetting". + * + * It is strongly recommended to use a large i_dpb_size in this case, which allows the encoder to + * keep around extra, older frames to fall back on in case more recent frames are all invalidated. + * Unlike increasing i_frame_reference, this does not increase the number of frames used for motion + * estimation and thus has no speed impact. It is also recommended to set a very large keyframe + * interval, so that keyframes are not used except as necessary for error recovery. + * + * x264_encoder_invalidate_reference is not currently compatible with the use of B-frames or intra + * refresh. + * + * In multi-pass encoding, if x264_encoder_invalidate_reference is called differently in each pass, + * behavior is undefined. + * + * Should not be called during an x264_encoder_encode, but multiple calls can be made simultaneously. + * + * Returns 0 on success, negative on failure. */ +int x264_encoder_invalidate_reference( x264_t *, int64_t pts ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/include/x264_config.h b/thirdparty/include/x264_config.h new file mode 100755 index 0000000000000000000000000000000000000000..ca3d7d66eb581df5f3c3feef50e188f7591ab71b --- /dev/null +++ b/thirdparty/include/x264_config.h @@ -0,0 +1,6 @@ +#define X264_GPL 1 +#define X264_INTERLACED 1 +#define X264_BIT_DEPTH 0 +#define X264_CHROMA_FORMAT 0 +#define X264_VERSION "" +#define X264_POINTVER "0.157.x" diff --git a/thirdparty/include/x265.h b/thirdparty/include/x265.h new file mode 100755 index 0000000000000000000000000000000000000000..2e62fe60f4f12cb2e38efaee7746c8146db8ff2e --- /dev/null +++ b/thirdparty/include/x265.h @@ -0,0 +1,2312 @@ +/***************************************************************************** + * Copyright (C) 2013-2020 MulticoreWare, Inc + * + * Authors: Steve Borho + * Min Chen + * + * 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 of the License, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at license @ x265.com. + *****************************************************************************/ + +#ifndef X265_H +#define X265_H +#include +#include +#include "x265_config.h" +#ifdef __cplusplus +extern "C" { +#endif + +#if _MSC_VER +#pragma warning(disable: 4201) // non-standard extension used (nameless struct/union) +#endif + +/* x265_encoder: + * opaque handler for encoder */ +typedef struct x265_encoder x265_encoder; + +/* x265_picyuv: + * opaque handler for PicYuv */ +typedef struct x265_picyuv x265_picyuv; + +/* Application developers planning to link against a shared library version of + * libx265 from a Microsoft Visual Studio or similar development environment + * will need to define X265_API_IMPORTS before including this header. + * This clause does not apply to MinGW, similar development environments, or non + * Windows platforms. */ +#ifdef X265_API_IMPORTS +#define X265_API __declspec(dllimport) +#else +#define X265_API +#endif + +typedef enum +{ + NAL_UNIT_CODED_SLICE_TRAIL_N = 0, + NAL_UNIT_CODED_SLICE_TRAIL_R, + NAL_UNIT_CODED_SLICE_TSA_N, + NAL_UNIT_CODED_SLICE_TLA_R, + NAL_UNIT_CODED_SLICE_STSA_N, + NAL_UNIT_CODED_SLICE_STSA_R, + NAL_UNIT_CODED_SLICE_RADL_N, + NAL_UNIT_CODED_SLICE_RADL_R, + NAL_UNIT_CODED_SLICE_RASL_N, + NAL_UNIT_CODED_SLICE_RASL_R, + NAL_UNIT_CODED_SLICE_BLA_W_LP = 16, + NAL_UNIT_CODED_SLICE_BLA_W_RADL, + NAL_UNIT_CODED_SLICE_BLA_N_LP, + NAL_UNIT_CODED_SLICE_IDR_W_RADL, + NAL_UNIT_CODED_SLICE_IDR_N_LP, + NAL_UNIT_CODED_SLICE_CRA, + NAL_UNIT_VPS = 32, + NAL_UNIT_SPS, + NAL_UNIT_PPS, + NAL_UNIT_ACCESS_UNIT_DELIMITER, + NAL_UNIT_EOS, + NAL_UNIT_EOB, + NAL_UNIT_FILLER_DATA, + NAL_UNIT_PREFIX_SEI, + NAL_UNIT_SUFFIX_SEI, + NAL_UNIT_UNSPECIFIED = 62, + NAL_UNIT_INVALID = 64, +} NalUnitType; + +/* The data within the payload is already NAL-encapsulated; the type is merely + * in the struct for easy access by the calling application. All data returned + * in an x265_nal, including the data in payload, is no longer valid after the + * next call to x265_encoder_encode. Thus it must be used or copied before + * calling x265_encoder_encode again. */ +typedef struct x265_nal +{ + uint32_t type; /* NalUnitType */ + uint32_t sizeBytes; /* size in bytes */ + uint8_t* payload; +} x265_nal; + +#define X265_LOOKAHEAD_MAX 250 + +typedef struct x265_lookahead_data +{ + int64_t plannedSatd[X265_LOOKAHEAD_MAX + 1]; + uint32_t *vbvCost; + uint32_t *intraVbvCost; + uint32_t *satdForVbv; + uint32_t *intraSatdForVbv; + int keyframe; + int lastMiniGopBFrame; + int plannedType[X265_LOOKAHEAD_MAX + 1]; + int64_t dts; + int64_t reorderedPts; +} x265_lookahead_data; + +typedef struct x265_analysis_validate +{ + int maxNumReferences; + int analysisReuseLevel; + int sourceWidth; + int sourceHeight; + int keyframeMax; + int keyframeMin; + int openGOP; + int bframes; + int bPyramid; + int maxCUSize; + int minCUSize; + int intraRefresh; + int lookaheadDepth; + int chunkStart; + int chunkEnd; + int cuTree; + int ctuDistortionRefine; + int rightOffset; + int bottomOffset; + int frameDuplication; +}x265_analysis_validate; + +/* Stores intra analysis data for a single frame. This struct needs better packing */ +typedef struct x265_analysis_intra_data +{ + uint8_t* depth; + uint8_t* modes; + char* partSizes; + uint8_t* chromaModes; + int8_t* cuQPOff; +}x265_analysis_intra_data; + +typedef struct x265_analysis_MV +{ + union{ + struct { int32_t x, y; }; + + int64_t word; + }; +}x265_analysis_MV; + +/* Stores inter analysis data for a single frame */ +typedef struct x265_analysis_inter_data +{ + int32_t* ref; + uint8_t* depth; + uint8_t* modes; + uint8_t* partSize; + uint8_t* mergeFlag; + uint8_t* interDir; + uint8_t* mvpIdx[2]; + int8_t* refIdx[2]; + x265_analysis_MV* mv[2]; + int64_t* sadCost; + int8_t* cuQPOff; +}x265_analysis_inter_data; + +typedef struct x265_weight_param +{ + uint32_t log2WeightDenom; + int inputWeight; + int inputOffset; + int wtPresent; +}x265_weight_param; + +#if X265_DEPTH < 10 +typedef uint32_t sse_t; +#else +typedef uint64_t sse_t; +#endif + +#define CTU_DISTORTION_OFF 0 +#define CTU_DISTORTION_INTERNAL 1 +#define CTU_DISTORTION_EXTERNAL 2 + +typedef struct x265_analysis_distortion_data +{ + sse_t* ctuDistortion; + double* scaledDistortion; + double averageDistortion; + double sdDistortion; + uint32_t highDistortionCtuCount; + uint32_t lowDistortionCtuCount; + double* offset; + double* threshold; + +}x265_analysis_distortion_data; + +#define MAX_NUM_REF 16 +/* Stores all analysis data for a single frame */ +typedef struct x265_analysis_data +{ + int64_t satdCost; + uint32_t frameRecordSize; + uint32_t poc; + uint32_t sliceType; + uint32_t numCUsInFrame; + uint32_t numPartitions; + uint32_t depthBytes; + int bScenecut; + x265_weight_param* wt; + x265_analysis_inter_data* interData; + x265_analysis_intra_data* intraData; + uint32_t numCuInHeight; + x265_lookahead_data lookahead; + uint8_t* modeFlag[2]; + x265_analysis_validate saveParam; + x265_analysis_distortion_data* distortionData; + uint64_t frameBits; + int list0POC[MAX_NUM_REF]; + int list1POC[MAX_NUM_REF]; + double totalIntraPercent; +} x265_analysis_data; + +/* cu statistics */ +typedef struct x265_cu_stats +{ + double percentSkipCu[4]; // Percentage of skip cu in all depths + double percentMergeCu[4]; // Percentage of merge cu in all depths + double percentIntraDistribution[4][3]; // Percentage of DC, Planar, Angular intra modes in all depths + double percentInterDistribution[4][3]; // Percentage of 2Nx2N inter, rect and amp in all depths + double percentIntraNxN; // Percentage of 4x4 cu + + /* All the above values will add up to 100%. */ +} x265_cu_stats; + + +/* pu statistics */ +typedef struct x265_pu_stats +{ + double percentSkipPu[4]; // Percentage of skip cu in all depths + double percentIntraPu[4]; // Percentage of intra modes in all depths + double percentAmpPu[4]; // Percentage of amp modes in all depths + double percentInterPu[4][3]; // Percentage of inter 2nx2n, 2nxn and nx2n in all depths + double percentMergePu[4][3]; // Percentage of merge 2nx2n, 2nxn and nx2n in all depth + double percentNxN; + + /* All the above values will add up to 100%. */ +} x265_pu_stats; + +/* Frame level statistics */ +typedef struct x265_frame_stats +{ + double qp; + double rateFactor; + double psnrY; + double psnrU; + double psnrV; + double psnr; + double ssim; + double decideWaitTime; + double row0WaitTime; + double wallTime; + double refWaitWallTime; + double totalCTUTime; + double stallTime; + double avgWPP; + double avgLumaDistortion; + double avgChromaDistortion; + double avgPsyEnergy; + double avgResEnergy; + double avgLumaLevel; + double bufferFill; + uint64_t bits; + int encoderOrder; + int poc; + int countRowBlocks; + int list0POC[MAX_NUM_REF]; + int list1POC[MAX_NUM_REF]; + uint16_t maxLumaLevel; + uint16_t minLumaLevel; + + uint16_t maxChromaULevel; + uint16_t minChromaULevel; + double avgChromaULevel; + + + uint16_t maxChromaVLevel; + uint16_t minChromaVLevel; + double avgChromaVLevel; + + char sliceType; + int bScenecut; + double ipCostRatio; + int frameLatency; + x265_cu_stats cuStats; + x265_pu_stats puStats; + double totalFrameTime; + double vmafFrameScore; + double bufferFillFinal; + double unclippedBufferFillFinal; +} x265_frame_stats; + +typedef struct x265_ctu_info_t +{ + int32_t ctuAddress; + int32_t ctuPartitions[64]; + void* ctuInfo; +} x265_ctu_info_t; + +typedef enum +{ + NO_CTU_INFO = 0, + HAS_CTU_INFO = 1, + CTU_INFO_CHANGE = 2, +}CTUInfo; + +typedef enum +{ + DEFAULT = 0, + AVC_INFO = 1, + HEVC_INFO = 2, +}AnalysisRefineType; + +/* Arbitrary User SEI + * Payload size is in bytes and the payload pointer must be non-NULL. + * Payload types and syntax can be found in Annex D of the H.265 Specification. + * SEI Payload Alignment bits as described in Annex D must be included at the + * end of the payload if needed. The payload should not be NAL-encapsulated. + * Payloads are written in the order of input */ + +typedef enum +{ + BUFFERING_PERIOD = 0, + PICTURE_TIMING = 1, + PAN_SCAN_RECT = 2, + FILLER_PAYLOAD = 3, + USER_DATA_REGISTERED_ITU_T_T35 = 4, + USER_DATA_UNREGISTERED = 5, + RECOVERY_POINT = 6, + SCENE_INFO = 9, + FULL_FRAME_SNAPSHOT = 15, + PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, + PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, + FILM_GRAIN_CHARACTERISTICS = 19, + POST_FILTER_HINT = 22, + TONE_MAPPING_INFO = 23, + FRAME_PACKING = 45, + DISPLAY_ORIENTATION = 47, + SOP_DESCRIPTION = 128, + ACTIVE_PARAMETER_SETS = 129, + DECODING_UNIT_INFO = 130, + TEMPORAL_LEVEL0_INDEX = 131, + DECODED_PICTURE_HASH = 132, + SCALABLE_NESTING = 133, + REGION_REFRESH_INFO = 134, + MASTERING_DISPLAY_INFO = 137, + CONTENT_LIGHT_LEVEL_INFO = 144, + ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, +} SEIPayloadType; + +typedef struct x265_sei_payload +{ + int payloadSize; + SEIPayloadType payloadType; + uint8_t* payload; +} x265_sei_payload; + +typedef struct x265_sei +{ + int numPayloads; + x265_sei_payload *payloads; +} x265_sei; + +typedef struct x265_dolby_vision_rpu +{ + int payloadSize; + uint8_t* payload; +}x265_dolby_vision_rpu; + +/* Used to pass pictures into the encoder, and to get picture data back out of + * the encoder. The input and output semantics are different */ +typedef struct x265_picture +{ + /* presentation time stamp: user-specified, returned on output */ + int64_t pts; + + /* display time stamp: ignored on input, copied from reordered pts. Returned + * on output */ + int64_t dts; + + /* force quantizer for != X265_QP_AUTO */ + /* The value provided on input is returned with the same picture (POC) on + * output */ + void* userData; + + /* Must be specified on input pictures, the number of planes is determined + * by the colorSpace value */ + void* planes[3]; + + /* Stride is the number of bytes between row starts */ + int stride[3]; + + /* Must be specified on input pictures. x265_picture_init() will set it to + * the encoder's internal bit depth, but this field must describe the depth + * of the input pictures. Must be between 8 and 16. Values larger than 8 + * imply 16bits per input sample. If input bit depth is larger than the + * internal bit depth, the encoder will down-shift pixels. Input samples + * larger than 8bits will be masked to internal bit depth. On output the + * bitDepth will be the internal encoder bit depth */ + int bitDepth; + + /* Must be specified on input pictures: X265_TYPE_AUTO or other. + * x265_picture_init() sets this to auto, returned on output */ + int sliceType; + + /* Ignored on input, set to picture count, returned on output */ + int poc; + + /* Must be specified on input pictures: X265_CSP_I420 or other. It must + * match the internal color space of the encoder. x265_picture_init() will + * initialize this value to the internal color space */ + int colorSpace; + + /* Force the slice base QP for this picture within the encoder. Set to 0 + * to allow the encoder to determine base QP */ + int forceqp; + + /* If param.analysisLoad and param.analysisSave are disabled, this field is + * ignored on input and output. Else the user must call x265_alloc_analysis_data() + * to allocate analysis buffers for every picture passed to the encoder. + * + * On input when param.analysisLoad is enabled and analysisData + * member pointers are valid, the encoder will use the data stored here to + * reduce encoder work. + * + * On output when param.analysisSave is enabled and analysisData + * member pointers are valid, the encoder will write output analysis into + * this data structure */ + x265_analysis_data analysisData; + + /* An array of quantizer offsets to be applied to this image during encoding. + * These are added on top of the decisions made by rateControl. + * Adaptive quantization must be enabled to use this feature. These quantizer + * offsets should be given for each 16x16 block (8x8 block, when qg-size is 8). + * Behavior if quant offsets differ between encoding passes is undefined. */ + float *quantOffsets; + + /* Frame level statistics */ + x265_frame_stats frameData; + + /* User defined SEI */ + x265_sei userSEI; + + /* Ratecontrol statistics for collecting the ratecontrol information. + * It is not used for collecting the last pass ratecontrol data in + * multi pass ratecontrol mode. */ + void* rcData; + + size_t framesize; + + int height; + + // pts is reordered in the order of encoding. + int64_t reorderedPts; + + //Dolby Vision RPU metadata + x265_dolby_vision_rpu rpu; + + int fieldNum; + + //SEI picture structure message + uint32_t picStruct; + + int width; +} x265_picture; + +typedef enum +{ + X265_DIA_SEARCH, + X265_HEX_SEARCH, + X265_UMH_SEARCH, + X265_STAR_SEARCH, + X265_SEA, + X265_FULL_SEARCH +} X265_ME_METHODS; + +/* CPU flags */ + +/* x86 */ +#define X265_CPU_MMX (1 << 0) +#define X265_CPU_MMX2 (1 << 1) /* MMX2 aka MMXEXT aka ISSE */ +#define X265_CPU_MMXEXT X265_CPU_MMX2 +#define X265_CPU_SSE (1 << 2) +#define X265_CPU_SSE2 (1 << 3) +#define X265_CPU_LZCNT (1 << 4) +#define X265_CPU_SSE3 (1 << 5) +#define X265_CPU_SSSE3 (1 << 6) +#define X265_CPU_SSE4 (1 << 7) /* SSE4.1 */ +#define X265_CPU_SSE42 (1 << 8) /* SSE4.2 */ +#define X265_CPU_AVX (1 << 9) /* Requires OS support even if YMM registers aren't used. */ +#define X265_CPU_XOP (1 << 10) /* AMD XOP */ +#define X265_CPU_FMA4 (1 << 11) /* AMD FMA4 */ +#define X265_CPU_FMA3 (1 << 12) /* Intel FMA3 */ +#define X265_CPU_BMI1 (1 << 13) /* BMI1 */ +#define X265_CPU_BMI2 (1 << 14) /* BMI2 */ +#define X265_CPU_AVX2 (1 << 15) /* AVX2 */ +#define X265_CPU_AVX512 (1 << 16) /* AVX-512 {F, CD, BW, DQ, VL}, requires OS support */ +/* x86 modifiers */ +#define X265_CPU_CACHELINE_32 (1 << 17) /* avoid memory loads that span the border between two cachelines */ +#define X265_CPU_CACHELINE_64 (1 << 18) /* 32/64 is the size of a cacheline in bytes */ +#define X265_CPU_SSE2_IS_SLOW (1 << 19) /* avoid most SSE2 functions on Athlon64 */ +#define X265_CPU_SSE2_IS_FAST (1 << 20) /* a few functions are only faster on Core2 and Phenom */ +#define X265_CPU_SLOW_SHUFFLE (1 << 21) /* The Conroe has a slow shuffle unit (relative to overall SSE performance) */ +#define X265_CPU_STACK_MOD4 (1 << 22) /* if stack is only mod4 and not mod16 */ +#define X265_CPU_SLOW_ATOM (1 << 23) /* The Atom is terrible: slow SSE unaligned loads, slow + * SIMD multiplies, slow SIMD variable shifts, slow pshufb, + * cacheline split penalties -- gather everything here that + * isn't shared by other CPUs to avoid making half a dozen + * new SLOW flags. */ +#define X265_CPU_SLOW_PSHUFB (1 << 24) /* such as on the Intel Atom */ +#define X265_CPU_SLOW_PALIGNR (1 << 25) /* such as on the AMD Bobcat */ + +/* ARM */ +#define X265_CPU_ARMV6 0x0000001 +#define X265_CPU_NEON 0x0000002 /* ARM NEON */ +#define X265_CPU_FAST_NEON_MRC 0x0000004 /* Transfer from NEON to ARM register is fast (Cortex-A9) */ + +/* IBM Power8 */ +#define X265_CPU_ALTIVEC 0x0000001 + +#define X265_MAX_SUBPEL_LEVEL 7 + +/* Log level */ +#define X265_LOG_NONE (-1) +#define X265_LOG_ERROR 0 +#define X265_LOG_WARNING 1 +#define X265_LOG_INFO 2 +#define X265_LOG_DEBUG 3 +#define X265_LOG_FULL 4 + +#define X265_B_ADAPT_NONE 0 +#define X265_B_ADAPT_FAST 1 +#define X265_B_ADAPT_TRELLIS 2 + +#define X265_REF_LIMIT_DEPTH 1 +#define X265_REF_LIMIT_CU 2 + +#define X265_TU_LIMIT_BFS 1 +#define X265_TU_LIMIT_DFS 2 +#define X265_TU_LIMIT_NEIGH 4 + +#define X265_BFRAME_MAX 16 +#define X265_MAX_FRAME_THREADS 16 + +#define X265_TYPE_AUTO 0x0000 /* Let x265 choose the right type */ +#define X265_TYPE_IDR 0x0001 +#define X265_TYPE_I 0x0002 +#define X265_TYPE_P 0x0003 +#define X265_TYPE_BREF 0x0004 /* Non-disposable B-frame */ +#define X265_TYPE_B 0x0005 +#define IS_X265_TYPE_I(x) ((x) == X265_TYPE_I || (x) == X265_TYPE_IDR) +#define IS_X265_TYPE_B(x) ((x) == X265_TYPE_B || (x) == X265_TYPE_BREF) + +#define X265_QP_AUTO 0 + +#define X265_AQ_NONE 0 +#define X265_AQ_VARIANCE 1 +#define X265_AQ_AUTO_VARIANCE 2 +#define X265_AQ_AUTO_VARIANCE_BIASED 3 +#define X265_AQ_EDGE 4 +#define x265_ADAPT_RD_STRENGTH 4 +#define X265_REFINE_INTER_LEVELS 3 +/* NOTE! For this release only X265_CSP_I420 and X265_CSP_I444 are supported */ +/* Supported internal color space types (according to semantics of chroma_format_idc) */ +#define X265_CSP_I400 0 /* yuv 4:0:0 planar */ +#define X265_CSP_I420 1 /* yuv 4:2:0 planar */ +#define X265_CSP_I422 2 /* yuv 4:2:2 planar */ +#define X265_CSP_I444 3 /* yuv 4:4:4 planar */ +#define X265_CSP_COUNT 4 /* Number of supported internal color spaces */ + +/* These color spaces will eventually be supported as input pictures. The pictures will + * be converted to the appropriate planar color spaces at ingest */ +#define X265_CSP_NV12 4 /* yuv 4:2:0, with one y plane and one packed u+v */ +#define X265_CSP_NV16 5 /* yuv 4:2:2, with one y plane and one packed u+v */ + +/* Interleaved color-spaces may eventually be supported as input pictures */ +#define X265_CSP_BGR 6 /* packed bgr 24bits */ +#define X265_CSP_BGRA 7 /* packed bgr 32bits */ +#define X265_CSP_RGB 8 /* packed rgb 24bits */ +#define X265_CSP_MAX 9 /* end of list */ +#define X265_EXTENDED_SAR 255 /* aspect ratio explicitly specified as width:height */ +/* Analysis options */ +#define X265_ANALYSIS_OFF 0 +#define X265_ANALYSIS_SAVE 1 +#define X265_ANALYSIS_LOAD 2 + +typedef struct x265_cli_csp +{ + int planes; + int width[3]; + int height[3]; +} x265_cli_csp; + +static const x265_cli_csp x265_cli_csps[] = +{ + { 1, { 0, 0, 0 }, { 0, 0, 0 } }, /* i400 */ + { 3, { 0, 1, 1 }, { 0, 1, 1 } }, /* i420 */ + { 3, { 0, 1, 1 }, { 0, 0, 0 } }, /* i422 */ + { 3, { 0, 0, 0 }, { 0, 0, 0 } }, /* i444 */ + { 2, { 0, 0 }, { 0, 1 } }, /* nv12 */ + { 2, { 0, 0 }, { 0, 0 } }, /* nv16 */ +}; + +/* rate tolerance method */ +typedef enum +{ + X265_RC_ABR, + X265_RC_CQP, + X265_RC_CRF +} X265_RC_METHODS; + +/* slice type statistics */ +typedef struct x265_sliceType_stats +{ + double avgQp; + double bitrate; + double psnrY; + double psnrU; + double psnrV; + double ssim; + uint32_t numPics; +} x265_sliceType_stats; + +/* Output statistics from encoder */ +typedef struct x265_stats +{ + double globalPsnrY; + double globalPsnrU; + double globalPsnrV; + double globalPsnr; + double globalSsim; + double elapsedEncodeTime; /* wall time since encoder was opened */ + double elapsedVideoTime; /* encoded picture count / frame rate */ + double bitrate; /* accBits / elapsed video time */ + double aggregateVmafScore; /* aggregate VMAF score for input video*/ + uint64_t accBits; /* total bits output thus far */ + uint32_t encodedPictureCount; /* number of output pictures thus far */ + uint32_t totalWPFrames; /* number of uni-directional weighted frames used */ + x265_sliceType_stats statsI; /* statistics of I slice */ + x265_sliceType_stats statsP; /* statistics of P slice */ + x265_sliceType_stats statsB; /* statistics of B slice */ + uint16_t maxCLL; /* maximum content light level */ + uint16_t maxFALL; /* maximum frame average light level */ +} x265_stats; + +/* String values accepted by x265_param_parse() (and CLI) for various parameters */ +static const char * const x265_motion_est_names[] = { "dia", "hex", "umh", "star", "sea", "full", 0 }; +static const char * const x265_source_csp_names[] = { "i400", "i420", "i422", "i444", "nv12", "nv16", 0 }; +static const char * const x265_video_format_names[] = { "component", "pal", "ntsc", "secam", "mac", "unknown", 0 }; +static const char * const x265_fullrange_names[] = { "limited", "full", 0 }; +static const char * const x265_colorprim_names[] = { "reserved", "bt709", "unknown", "reserved", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020", "smpte428", "smpte431", "smpte432", 0 }; +static const char * const x265_transfer_names[] = { "reserved", "bt709", "unknown", "reserved", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", + "log316", "iec61966-2-4", "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", + "smpte2084", "smpte428", "arib-std-b67", 0 }; +static const char * const x265_colmatrix_names[] = { "gbr", "bt709", "unknown", "", "fcc", "bt470bg", "smpte170m", "smpte240m", + "ycgco", "bt2020nc", "bt2020c", "smpte2085", "chroma-derived-nc", "chroma-derived-c", "ictcp", 0 }; +static const char * const x265_sar_names[] = { "unknown", "1:1", "12:11", "10:11", "16:11", "40:33", "24:11", "20:11", + "32:11", "80:33", "18:11", "15:11", "64:33", "160:99", "4:3", "3:2", "2:1", 0 }; +static const char * const x265_interlace_names[] = { "prog", "tff", "bff", 0 }; +static const char * const x265_analysis_names[] = { "off", "save", "load", 0 }; + +struct x265_zone; +struct x265_param; +/* Zones: override ratecontrol for specific sections of the video. + * If zones overlap, whichever comes later in the list takes precedence. */ +typedef struct x265_zone +{ + int startFrame, endFrame; /* range of frame numbers */ + int bForceQp; /* whether to use qp vs bitrate factor */ + int qp; + float bitrateFactor; + struct x265_param* zoneParam; + double* relativeComplexity; +} x265_zone; + +/* data to calculate aggregate VMAF score */ +typedef struct x265_vmaf_data +{ + int width; + int height; + size_t offset; + int internalBitDepth; + FILE *reference_file; /* FILE pointer for input file */ + FILE *distorted_file; /* FILE pointer for recon file generated*/ +}x265_vmaf_data; + +/* data to calculate frame level VMAF score */ +typedef struct x265_vmaf_framedata +{ + int width; + int height; + int frame_set; + int internalBitDepth; + void *reference_frame; /* points to fenc of particular frame */ + void *distorted_frame; /* points to recon of particular frame */ +}x265_vmaf_framedata; + +/* common data needed to calculate both frame level and video level VMAF scores */ +typedef struct x265_vmaf_commondata +{ + char *format; + char *model_path; + char *log_path; + char *log_fmt; + int disable_clip; + int disable_avx; + int enable_transform; + int phone_model; + int psnr; + int ssim; + int ms_ssim; + char *pool; + int thread; + int subsample; + int enable_conf_interval; +}x265_vmaf_commondata; + +static const x265_vmaf_commondata vcd[] = { { NULL, (char *)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 1, 0 } }; + +/* x265 input parameters + * + * For version safety you may use x265_param_alloc/free() to manage the + * allocation of x265_param instances, and x265_param_parse() to assign values + * by name. By never dereferencing param fields in your own code you can treat + * x265_param as an opaque data structure */ +typedef struct x265_param +{ + /* x265_param_default() will auto-detect this cpu capability bitmap. it is + * recommended to not change this value unless you know the cpu detection is + * somehow flawed on your target hardware. The asm function tables are + * process global, the first encoder configures them for all encoders */ + int cpuid; + /*== Parallelism Features ==*/ + + /* Number of concurrently encoded frames between 1 and X265_MAX_FRAME_THREADS + * or 0 for auto-detection. By default x265 will use a number of frame + * threads empirically determined to be optimal for your CPU core count, + * between 2 and 6. Using more than one frame thread causes motion search + * in the down direction to be clamped but otherwise encode behavior is + * unaffected. With CQP rate control the output bitstream is deterministic + * for all values of frameNumThreads greater than 1. All other forms of + * rate-control can be negatively impacted by increases to the number of + * frame threads because the extra concurrency adds uncertainty to the + * bitrate estimations. Frame parallelism is generally limited by the the + * is generally limited by the the number of CU rows + * + * When thread pools are used, each frame thread is assigned to a single + * pool and the frame thread itself is given the node affinity of its pool. + * But when no thread pools are used no node affinity is assigned. */ + int frameNumThreads; + + /* Comma seperated list of threads per NUMA node. If "none", then no worker + * pools are created and only frame parallelism is possible. If NULL or "" + * (default) x265 will use all available threads on each NUMA node. + * + * '+' is a special value indicating all cores detected on the node + * '*' is a special value indicating all cores detected on the node and all + * remaining nodes. + * '-' is a special value indicating no cores on the node, same as '0' + * + * example strings for a 4-node system: + * "" - default, unspecified, all numa nodes are used for thread pools + * "*" - same as default + * "none" - no thread pools are created, only frame parallelism possible + * "-" - same as "none" + * "10" - allocate one pool, using up to 10 cores on node 0 + * "-,+" - allocate one pool, using all cores on node 1 + * "+,-,+" - allocate two pools, using all cores on nodes 0 and 2 + * "+,-,+,-" - allocate two pools, using all cores on nodes 0 and 2 + * "-,*" - allocate three pools, using all cores on nodes 1, 2 and 3 + * "8,8,8,8" - allocate four pools with up to 8 threads in each pool + * + * The total number of threads will be determined by the number of threads + * assigned to all nodes. The worker threads will each be given affinity for + * their node, they will not be allowed to migrate between nodes, but they + * will be allowed to move between CPU cores within their node. + * + * If the three pool features: bEnableWavefront, bDistributeModeAnalysis and + * bDistributeMotionEstimation are all disabled, then numaPools is ignored + * and no thread pools are created. + * + * If "none" is specified, then all three of the thread pool features are + * implicitly disabled. + * + * Multiple thread pools will be allocated for any NUMA node with more than + * 64 logical CPU cores. But any given thread pool will always use at most + * one NUMA node. + * + * Frame encoders are distributed between the available thread pools, and + * the encoder will never generate more thread pools than frameNumThreads */ + const char* numaPools; + + /* Enable wavefront parallel processing, greatly increases parallelism for + * less than 1% compression efficiency loss. Requires a thread pool, enabled + * by default */ + int bEnableWavefront; + + /* Use multiple threads to measure CU mode costs. Recommended for many core + * CPUs. On RD levels less than 5, it may not offload enough work to warrant + * the overhead. It is useful with the slow preset since it has the + * rectangular predictions enabled. At RD level 5 and 6 (preset slower and + * below), this feature should be an unambiguous win if you have CPU + * cores available for work. Default disabled */ + int bDistributeModeAnalysis; + + /* Use multiple threads to perform motion estimation to (ME to one reference + * per thread). Recommended for many core CPUs. The more references the more + * motion searches there will be to distribute. This option is often not a + * win, particularly in video sequences with low motion. Default disabled */ + int bDistributeMotionEstimation; + + /*== Logging Features ==*/ + + /* Enable analysis and logging distribution of CUs. Now deprecated */ + int bLogCuStats; + + /* Enable the measurement and reporting of PSNR. Default is enabled */ + int bEnablePsnr; + + /* Enable the measurement and reporting of SSIM. Default is disabled */ + int bEnableSsim; + + /* The level of logging detail emitted by the encoder. X265_LOG_NONE to + * X265_LOG_FULL, default is X265_LOG_INFO */ + int logLevel; + + /* Level of csv logging. 0 is summary, 1 is frame level logging, + * 2 is frame level logging with performance statistics */ + int csvLogLevel; + + /* filename of CSV log. If csvLogLevel is non-zero, the encoder will emit + * per-slice statistics to this log file in encode order. Otherwise the + * encoder will emit per-stream statistics into the log file when + * x265_encoder_log is called (presumably at the end of the encode) */ + const char* csvfn; + + /*== Internal Picture Specification ==*/ + + /* Internal encoder bit depth. If x265 was compiled to use 8bit pixels + * (HIGH_BIT_DEPTH=0), this field must be 8, else this field must be 10. + * Future builds may support 12bit pixels. */ + int internalBitDepth; + + /* Color space of internal pictures, must match color space of input + * pictures */ + int internalCsp; + + /* Numerator and denominator of frame rate */ + uint32_t fpsNum; + uint32_t fpsDenom; + + /* Width (in pixels) of the source pictures. If this width is not an even + * multiple of 4, the encoder will pad the pictures internally to meet this + * minimum requirement. All valid HEVC widths are supported */ + int sourceWidth; + + /* Height (in pixels) of the source pictures. If this height is not an even + * multiple of 4, the encoder will pad the pictures internally to meet this + * minimum requirement. All valid HEVC heights are supported */ + int sourceHeight; + + /* Interlace type of source pictures. 0 - progressive pictures (default). + * 1 - top field first, 2 - bottom field first. HEVC encodes interlaced + * content as fields, they must be provided to the encoder in the correct + * temporal order */ + int interlaceMode; + + /* Total Number of frames to be encoded, calculated from the user input + * (--frames) and (--seek). In case, the input is read from a pipe, this can + * remain as 0. It is later used in 2 pass RateControl, hence storing the + * value in param */ + int totalFrames; + + /*== Profile / Tier / Level ==*/ + + /* Note: the profile is specified by x265_param_apply_profile() */ + + /* Minimum decoder requirement level. Defaults to 0, which implies auto- + * detection by the encoder. If specified, the encoder will attempt to bring + * the encode specifications within that specified level. If the encoder is + * unable to reach the level it issues a warning and emits the actual + * decoder requirement. If the requested requirement level is higher than + * the actual level, the actual requirement level is signaled. The value is + * an specified as an integer with the level times 10, for example level + * "5.1" is specified as 51, and level "5.0" is specified as 50. */ + int levelIdc; + + /* if levelIdc is specified (non-zero) this flag will differentiate between + * Main (0) and High (1) tier. Default is Main tier (0) */ + int bHighTier; + + /* Enable UHD Blu-ray compatibility support. If specified, the encoder will + * attempt to modify/set the encode specifications. If the encoder is unable + * to do so, this option will be turned OFF. */ + int uhdBluray; + + /* The maximum number of L0 references a P or B slice may use. This + * influences the size of the decoded picture buffer. The higher this + * number, the more reference frames there will be available for motion + * search, improving compression efficiency of most video at a cost of + * performance. Value must be between 1 and 16, default is 3 */ + int maxNumReferences; + + /* Allow libx265 to emit HEVC bitstreams which do not meet strict level + * requirements. Defaults to false */ + int bAllowNonConformance; + + /*== Bitstream Options ==*/ + + /* Flag indicating whether VPS, SPS and PPS headers should be output with + * each keyframe. Default false */ + int bRepeatHeaders; + + /* Flag indicating whether the encoder should generate start codes (Annex B + * format) or length (file format) before NAL units. Default true, Annex B. + * Muxers should set this to the correct value */ + int bAnnexB; + + /* Flag indicating whether the encoder should emit an Access Unit Delimiter + * NAL at the start of every access unit. Default false */ + int bEnableAccessUnitDelimiters; + + /* Enables the buffering period SEI and picture timing SEI to signal the HRD + * parameters. Default is disabled */ + int bEmitHRDSEI; + + /* Enables the emission of a user data SEI with the stream headers which + * describes the encoder version, build info, and parameters. This is + * very helpful for debugging, but may interfere with regression tests. + * Default enabled */ + int bEmitInfoSEI; + + /* Enable the generation of SEI messages for each encoded frame containing + * the hashes of the three reconstructed picture planes. Most decoders will + * validate those hashes against the reconstructed images it generates and + * report any mismatches. This is essentially a debugging feature. Hash + * types are MD5(1), CRC(2), Checksum(3). Default is 0, none */ + int decodedPictureHashSEI; + + /* Enable Temporal Sub Layers while encoding, signals NAL units of coded + * slices with their temporalId. Output bitstreams can be extracted either + * at the base temporal layer (layer 0) with roughly half the frame rate or + * at a higher temporal layer (layer 1) that decodes all the frames in the + * sequence. */ + int bEnableTemporalSubLayers; + + /*== GOP structure and slice type decisions (lookahead) ==*/ + + /* Enable open GOP - meaning I slices are not necessarily IDR and thus frames + * encoded after an I slice may reference frames encoded prior to the I + * frame which have remained in the decoded picture buffer. Open GOP + * generally has better compression efficiency and negligible encoder + * performance impact, but the use case may preclude it. Default true */ + int bOpenGOP; + + /* Scene cuts closer together than this are coded as I, not IDR. */ + int keyframeMin; + + /* Maximum keyframe distance or intra period in number of frames. If 0 or 1, + * all frames are I frames. A negative value is casted to MAX_INT internally + * which effectively makes frame 0 the only I frame. Default is 250 */ + int keyframeMax; + + /* Maximum consecutive B frames that can be emitted by the lookahead. When + * b-adapt is 0 and keyframMax is greater than bframes, the lookahead emits + * a fixed pattern of `bframes` B frames between each P. With b-adapt 1 the + * lookahead ignores the value of bframes for the most part. With b-adapt 2 + * the value of bframes determines the search (POC) distance performed in + * both directions, quadratically increasing the compute load of the + * lookahead. The higher the value, the more B frames the lookahead may + * possibly use consecutively, usually improving compression. Default is 3, + * maximum is 16 */ + int bframes; + + /* Sets the operating mode of the lookahead. With b-adapt 0, the GOP + * structure is fixed based on the values of keyframeMax and bframes. + * With b-adapt 1 a light lookahead is used to chose B frame placement. + * With b-adapt 2 (trellis) a viterbi B path selection is performed */ + int bFrameAdaptive; + + /* When enabled, the encoder will use the B frame in the middle of each + * mini-GOP larger than 2 B frames as a motion reference for the surrounding + * B frames. This improves compression efficiency for a small performance + * penalty. Referenced B frames are treated somewhere between a B and a P + * frame by rate control. Default is enabled. */ + int bBPyramid; + + /* A value which is added to the cost estimate of B frames in the lookahead. + * It may be a positive value (making B frames appear less expensive, which + * biases the lookahead to choose more B frames) or negative, which makes the + * lookahead choose more P frames. Default is 0, there are no limits */ + int bFrameBias; + + /* The number of frames that must be queued in the lookahead before it may + * make slice decisions. Increasing this value directly increases the encode + * latency. The longer the queue the more optimally the lookahead may make + * slice decisions, particularly with b-adapt 2. When cu-tree is enabled, + * the length of the queue linearly increases the effectiveness of the + * cu-tree analysis. Default is 40 frames, maximum is 250 */ + int lookaheadDepth; + + /* Use multiple worker threads to measure the estimated cost of each frame + * within the lookahead. When bFrameAdaptive is 2, most frame cost estimates + * will be performed in batch mode, many cost estimates at the same time, + * and lookaheadSlices is ignored for batched estimates. The effect on + * performance can be quite small. The higher this parameter, the less + * accurate the frame costs will be (since context is lost across slice + * boundaries) which will result in less accurate B-frame and scene-cut + * decisions. Default is 0 - disabled. 1 is the same as 0. Max 16 */ + int lookaheadSlices; + + /* An arbitrary threshold which determines how aggressively the lookahead + * should detect scene cuts for cost based scenecut detection. + * The default (40) is recommended. */ + int scenecutThreshold; + + /* Replace keyframes by using a column of intra blocks that move across the video + * from one side to the other, thereby "refreshing" the image. In effect, instead of a + * big keyframe, the keyframe is "spread" over many frames. */ + int bIntraRefresh; + + /*== Coding Unit (CU) definitions ==*/ + + /* Maximum CU width and height in pixels. The size must be 64, 32, or 16. + * The higher the size, the more efficiently x265 can encode areas of low + * complexity, greatly improving compression efficiency at large + * resolutions. The smaller the size, the more effective wavefront and + * frame parallelism will become because of the increase in rows. default 64 + * All encoders within the same process must use the same maxCUSize, until + * all encoders are closed and x265_cleanup() is called to reset the value. */ + uint32_t maxCUSize; + + /* Minimum CU width and height in pixels. The size must be 64, 32, 16, or + * 8. Default 8. All encoders within the same process must use the same + * minCUSize. */ + uint32_t minCUSize; + + /* Enable rectangular motion prediction partitions (vertical and + * horizontal), available at all CU depths from 64x64 to 8x8. Default is + * disabled */ + int bEnableRectInter; + + /* Enable asymmetrical motion predictions. At CU depths 64, 32, and 16, it + * is possible to use 25%/75% split partitions in the up, down, right, left + * directions. For some material this can improve compression efficiency at + * the cost of extra analysis. bEnableRectInter must be enabled for this + * feature to be used. Default disabled */ + int bEnableAMP; + + /*== Residual Quadtree Transform Unit (TU) definitions ==*/ + + /* Maximum TU width and height in pixels. The size must be 32, 16, 8 or 4. + * The larger the size the more efficiently the residual can be compressed + * by the DCT transforms, at the expense of more computation */ + uint32_t maxTUSize; + + /* The additional depth the residual quad-tree is allowed to recurse beyond + * the coding quad-tree, for inter coded blocks. This must be between 1 and + * 4. The higher the value the more efficiently the residual can be + * compressed by the DCT transforms, at the expense of much more compute */ + uint32_t tuQTMaxInterDepth; + + /* The additional depth the residual quad-tree is allowed to recurse beyond + * the coding quad-tree, for intra coded blocks. This must be between 1 and + * 4. The higher the value the more efficiently the residual can be + * compressed by the DCT transforms, at the expense of much more compute */ + uint32_t tuQTMaxIntraDepth; + + /* Enable early exit decisions for inter coded blocks to avoid recursing to + * higher TU depths. Default: 0 */ + uint32_t limitTU; + + /* Set the amount of rate-distortion analysis to use within quant. 0 implies + * no rate-distortion optimization. At level 1 rate-distortion cost is used to + * find optimal rounding values for each level (and allows psy-rdoq to be + * enabled). At level 2 rate-distortion cost is used to make decimate decisions + * on each 4x4 coding group (including the cost of signaling the group within + * the group bitmap). Psy-rdoq is less effective at preserving energy when + * RDOQ is at level 2. Default: 0 */ + int rdoqLevel; + + /* Enable the implicit signaling of the sign bit of the last coefficient of + * each transform unit. This saves one bit per TU at the expense of figuring + * out which coefficient can be toggled with the least distortion. + * Default is enabled */ + int bEnableSignHiding; + + /* Allow intra coded blocks to be encoded directly as residual without the + * DCT transform, when this improves efficiency. Checking whether the block + * will benefit from this option incurs a performance penalty. Default is + * disabled */ + int bEnableTransformSkip; + + /* An integer value in range of 0 to 2000, which denotes strength of noise + * reduction in intra CUs. 0 means disabled */ + int noiseReductionIntra; + + /* An integer value in range of 0 to 2000, which denotes strength of noise + * reduction in inter CUs. 0 means disabled */ + int noiseReductionInter; + + /* Quantization scaling lists. HEVC supports 6 quantization scaling lists to + * be defined; one each for Y, Cb, Cr for intra prediction and one each for + * inter prediction. + * + * - NULL and "off" will disable quant scaling (default) + * - "default" will enable the HEVC default scaling lists, which + * do not need to be signaled since they are specified + * - all other strings indicate a filename containing custom scaling lists + * in the HM format. The encode will fail if the file is not parsed + * correctly. Custom lists must be signaled in the SPS. */ + const char *scalingLists; + + /*== Intra Coding Tools ==*/ + + /* Enable constrained intra prediction. This causes intra prediction to + * input samples that were inter predicted. For some use cases this is + * believed to me more robust to stream errors, but it has a compression + * penalty on P and (particularly) B slices. Defaults to disabled */ + int bEnableConstrainedIntra; + + /* Enable strong intra smoothing for 32x32 blocks where the reference + * samples are flat. It may or may not improve compression efficiency, + * depending on your source material. Defaults to disabled */ + int bEnableStrongIntraSmoothing; + + /*== Inter Coding Tools ==*/ + + /* The maximum number of merge candidates that are considered during inter + * analysis. This number (between 1 and 5) is signaled in the stream + * headers and determines the number of bits required to signal a merge so + * it can have significant trade-offs. The smaller this number the higher + * the performance but the less compression efficiency. Default is 3 */ + uint32_t maxNumMergeCand; + + /* Limit the motion references used for each search based on the results of + * previous motion searches already performed for the same CU: If 0 all + * references are always searched. If X265_REF_LIMIT_CU all motion searches + * will restrict themselves to the references selected by the 2Nx2N search + * at the same depth. If X265_REF_LIMIT_DEPTH the 2Nx2N motion search will + * only use references that were selected by the best motion searches of the + * 4 split CUs at the next lower CU depth. The two flags may be combined */ + uint32_t limitReferences; + + /* Limit modes analyzed for each CU using cost metrics from the 4 sub-CUs */ + uint32_t limitModes; + + /* ME search method (DIA, HEX, UMH, STAR, SEA, FULL). The search patterns + * (methods) are sorted in increasing complexity, with diamond being the + * simplest and fastest and full being the slowest. DIA, HEX, UMH and SEA were + * adapted from x264 directly. STAR is an adaption of the HEVC reference + * encoder's three step search, while full is a naive exhaustive search. The + * default is the star search, it has a good balance of performance and + * compression efficiency */ + int searchMethod; + + /* A value between 0 and X265_MAX_SUBPEL_LEVEL which adjusts the amount of + * effort performed during sub-pel refine. Default is 5 */ + int subpelRefine; + + /* The maximum distance from the motion prediction that the full pel motion + * search is allowed to progress before terminating. This value can have an + * effect on frame parallelism, as referenced frames must be at least this + * many rows of reconstructed pixels ahead of the referencee at all times. + * (When considering reference lag, the motion prediction must be ignored + * because it cannot be known ahead of time). Default is 60, which is the + * default max CU size (64) minus the luma HPEL half-filter length (4). If a + * smaller CU size is used, the search range should be similarly reduced */ + int searchRange; + + /* Enable availability of temporal motion vector for AMVP, default is enabled */ + int bEnableTemporalMvp; + + /* Enable 3-level Hierarchical motion estimation at One-Sixteenth, Quarter and Full resolution. + * Default is disabled */ + int bEnableHME; + + /* Enable HME search method (DIA, HEX, UMH, STAR, SEA, FULL) for level 0, 1 and 2. + * Default is hex, umh, umh for L0, L1 and L2 respectively. */ + int hmeSearchMethod[3]; + + /* Enable weighted prediction in P slices. This enables weighting analysis + * in the lookahead, which influences slice decisions, and enables weighting + * analysis in the main encoder which allows P reference samples to have a + * weight function applied to them prior to using them for motion + * compensation. In video which has lighting changes, it can give a large + * improvement in compression efficiency. Default is enabled */ + int bEnableWeightedPred; + + /* Enable weighted prediction in B slices. Default is disabled */ + int bEnableWeightedBiPred; + /* Enable source pixels in motion estimation. Default is disabled */ + int bSourceReferenceEstimation; + /*== Loop Filters ==*/ + /* Enable the deblocking loop filter, which improves visual quality by + * reducing blocking effects at block edges, particularly at lower bitrates + * or higher QP. When enabled it adds another CU row of reference lag, + * reducing frame parallelism effectiveness. Default is enabled */ + int bEnableLoopFilter; + + /* deblocking filter tC offset [-6, 6] -6 light filter, 6 strong. + * This is the coded div2 value, actual offset is doubled at use */ + int deblockingFilterTCOffset; + + /* deblocking filter Beta offset [-6, 6] -6 light filter, 6 strong + * This is the coded div2 value, actual offset is doubled at use */ + int deblockingFilterBetaOffset; + + /* Enable the Sample Adaptive Offset loop filter, which reduces distortion + * effects by adjusting reconstructed sample values based on histogram + * analysis to better approximate the original samples. When enabled it adds + * a CU row of reference lag, reducing frame parallelism effectiveness. + * Default is enabled */ + int bEnableSAO; + + /* Note: when deblocking and SAO are both enabled, the loop filter CU lag is + * only one row, as they operate in series on the same row. */ + + /* Select the method in which SAO deals with deblocking boundary pixels. If + * disabled the right and bottom boundary areas are skipped. If enabled, + * non-deblocked pixels are used entirely. Default is disabled */ + int bSaoNonDeblocked; + + /* Select tune rate in which SAO has to be applied. + 1 - Filtering applied only on I-frames(I) [Light tune] + 2 - No Filtering on B frames (I, P) [Medium tune] + 3 - No Filtering on non-ref b frames (I, P, B) [Strong tune] */ + int selectiveSAO; + + /*== Analysis tools ==*/ + + /* A value between 1 and 6 (both inclusive) which determines the level of + * rate distortion optimizations to perform during mode and depth decisions. + * The more RDO the better the compression efficiency at a major cost of + * performance. Default is 3 */ + int rdLevel; + + /* Enable early skip decisions to avoid analysing additional modes in likely + * skip blocks. Default is disabled */ + int bEnableEarlySkip; + + /* Enable early CU size decisions to avoid recursing to higher depths. + * Default is enabled */ + int recursionSkipMode; + + /* Use a faster search method to find the best intra mode. Default is 0 */ + int bEnableFastIntra; + + /* Enable a faster determination of whether skipping the DCT transform will + * be beneficial. Slight performance gain for some compression loss. Default + * is enabled */ + int bEnableTSkipFast; + + /* The CU Lossless flag, when enabled, compares the rate-distortion costs + * for normal and lossless encoding, and chooses the best mode for each CU. + * If lossless mode is chosen, the cu-transquant-bypass flag is set for that + * CU */ + int bCULossless; + + /* Specify whether to attempt to encode intra modes in B frames. By default + * enabled, but only applicable for the presets which use rdLevel 5 or 6 + * (veryslow and placebo). All other presets will not try intra in B frames + * regardless of this setting */ + int bIntraInBFrames; + + /* Apply an optional penalty to the estimated cost of 32x32 intra blocks in + * non-intra slices. 0 is disabled, 1 enables a small penalty, and 2 enables + * a full penalty. This favors inter-coding and its low bitrate over + * potential increases in distortion, but usually improves performance. + * Default is 0 */ + int rdPenalty; + + /* Psycho-visual rate-distortion strength. Only has an effect in presets + * which use RDO. It makes mode decision favor options which preserve the + * energy of the source, at the cost of lost compression. The value must + * be between 0 and 5.0, 1.0 is typical. Default 2.0 */ + double psyRd; + + /* Strength of psycho-visual optimizations in quantization. Only has an + * effect when RDOQ is enabled (presets slow, slower and veryslow). The + * value must be between 0 and 50, 1.0 is typical. Default 0 */ + double psyRdoq; + + /* Perform quantisation parameter based RD refinement. RD cost is calculated + * on the best CU partitions, chosen after the CU analysis, for a range of QPs + * to find the optimal rounding effect. Only effective at rd-levels 5 and 6. + * Default disabled */ + int bEnableRdRefine; + + /* If save, write per-frame analysis information into analysis buffers. + * If load, read analysis information into analysis buffer and use this + * analysis information to reduce the amount of work the encoder must perform. + * Default disabled. Now deprecated*/ + int analysisReuseMode; + + /* Filename for multi-pass-opt-analysis/distortion. Default name is "x265_analysis.dat" */ + const char* analysisReuseFileName; + + /*== Rate Control ==*/ + + /* The lossless flag enables true lossless coding, bypassing scaling, + * transform, quantization and in-loop filter processes. This is used for + * ultra-high bitrates with zero loss of quality. It implies no rate control */ + int bLossless; + + /* Generally a small signed integer which offsets the QP used to quantize + * the Cb chroma residual (delta from luma QP specified by rate-control). + * Default is 0, which is recommended */ + int cbQpOffset; + + /* Generally a small signed integer which offsets the QP used to quantize + * the Cr chroma residual (delta from luma QP specified by rate-control). + * Default is 0, which is recommended */ + int crQpOffset; + + /* Specifies the preferred transfer characteristics syntax element in the + * alternative transfer characteristics SEI message (see. D.2.38 and D.3.38 of + * JCTVC-W1005 http://phenix.it-sudparis.eu/jct/doc_end_user/documents/23_San%20Diego/wg11/JCTVC-W1005-v4.zip + * */ + int preferredTransferCharacteristics; + + /* + * Specifies the value for the pic_struc syntax element of the picture timing SEI message (See D2.3 and D3.3) + * of the HEVC spec. for a detailed explanation + * */ + int pictureStructure; + + struct + { + /* Explicit mode of rate-control, necessary for API users. It must + * be one of the X265_RC_METHODS enum values. */ + int rateControlMode; + + /* Base QP to use for Constant QP rate control. Adaptive QP may alter + * the QP used for each block. If a QP is specified on the command line + * CQP rate control is implied. Default: 32 */ + int qp; + + /* target bitrate for Average BitRate (ABR) rate control. If a non- zero + * bitrate is specified on the command line, ABR is implied. Default 0 */ + int bitrate; + + /* qComp sets the quantizer curve compression factor. It weights the frame + * quantizer based on the complexity of residual (measured by lookahead). + * Default value is 0.6. Increasing it to 1 will effectively generate CQP */ + double qCompress; + + /* QP offset between I/P and P/B frames. Default ipfactor: 1.4 + * Default pbFactor: 1.3 */ + double ipFactor; + double pbFactor; + + /* Ratefactor constant: targets a certain constant "quality". + * Acceptable values between 0 and 51. Default value: 28 */ + double rfConstant; + + /* Max QP difference between frames. Default: 4 */ + int qpStep; + + /* Enable adaptive quantization. This mode distributes available bits between all + * CTUs of a frame, assigning more bits to low complexity areas. Turning + * this ON will usually affect PSNR negatively, however SSIM and visual quality + * generally improves. Default: X265_AQ_AUTO_VARIANCE */ + int aqMode; + + /* + * Enable adaptive quantization. + * It scales the quantization step size according to the spatial activity of one + * coding unit relative to frame average spatial activity. This AQ method utilizes + * the minimum variance of sub-unit in each coding unit to represent the coding + * unit’s spatial complexity. */ + int hevcAq; + + /* Sets the strength of AQ bias towards low detail CTUs. Valid only if + * AQ is enabled. Default value: 1.0. Acceptable values between 0.0 and 3.0 */ + double aqStrength; + + /* Delta QP range by QP adaptation based on a psycho-visual model. + * Acceptable values between 1.0 to 6.0 */ + double qpAdaptationRange; + + /* Sets the maximum rate the VBV buffer should be assumed to refill at + * Default is zero */ + int vbvMaxBitrate; + + /* Sets the size of the VBV buffer in kilobits. Default is zero */ + int vbvBufferSize; + + /* Sets how full the VBV buffer must be before playback starts. If it is less than + * 1, then the initial fill is vbv-init * vbvBufferSize. Otherwise, it is + * interpreted as the initial fill in kbits. Default is 0.9 */ + double vbvBufferInit; + + /* Enable CUTree rate-control. This keeps track of the CUs that propagate temporally + * across frames and assigns more bits to these CUs. Improves encode efficiency. + * Default: enabled */ + int cuTree; + + /* In CRF mode, maximum CRF as caused by VBV. 0 implies no limit */ + double rfConstantMax; + + /* In CRF mode, minimum CRF as caused by VBV */ + double rfConstantMin; + + /* Multi-pass encoding */ + /* Enable writing the stats in a multi-pass encode to the stat output file */ + int bStatWrite; + + /* Enable loading data from the stat input file in a multi pass encode */ + int bStatRead; + + /* Filename of the 2pass output/input stats file, if unspecified the + * encoder will default to using x265_2pass.log */ + const char* statFileName; + + /* temporally blur quants */ + double qblur; + + /* temporally blur complexity */ + double complexityBlur; + + /* Enable slow and a more detailed first pass encode in multi pass rate control */ + int bEnableSlowFirstPass; + + /* rate-control overrides */ + int zoneCount; + x265_zone* zones; + + /* number of zones in zone-file*/ + int zonefileCount; + + /* specify a text file which contains MAX_MAX_QP + 1 floating point + * values to be copied into x265_lambda_tab and a second set of + * MAX_MAX_QP + 1 floating point values for x265_lambda2_tab. All values + * are separated by comma, space or newline. Text after a hash (#) is + * ignored. The lambda tables are process-global, so these new lambda + * values will affect all encoders in the same process */ + const char* lambdaFileName; + + /* Enable stricter conditions to check bitrate deviations in CBR mode. May compromise + * quality to maintain bitrate adherence */ + int bStrictCbr; + + /* Enable adaptive quantization at CU granularity. This parameter specifies + * the minimum CU size at which QP can be adjusted, i.e. Quantization Group + * (QG) size. Allowed values are 64, 32, 16, 8 provided it falls within the + * inclusuve range [maxCUSize, minCUSize]. Experimental, default: maxCUSize */ + uint32_t qgSize; + + /* internally enable if tune grain is set */ + int bEnableGrain; + + /* sets a hard upper limit on QP */ + int qpMax; + + /* sets a hard lower limit on QP */ + int qpMin; + + /* internally enable if tune grain is set */ + int bEnableConstVbv; + + } rc; + + /*== Video Usability Information ==*/ + struct + { + /* Aspect ratio idc to be added to the VUI. The default is 0 indicating + * the apsect ratio is unspecified. If set to X265_EXTENDED_SAR then + * sarWidth and sarHeight must also be set */ + int aspectRatioIdc; + + /* Sample Aspect Ratio width in arbitrary units to be added to the VUI + * only if aspectRatioIdc is set to X265_EXTENDED_SAR. This is the width + * of an individual pixel. If this is set then sarHeight must also be set */ + int sarWidth; + + /* Sample Aspect Ratio height in arbitrary units to be added to the VUI. + * only if aspectRatioIdc is set to X265_EXTENDED_SAR. This is the width + * of an individual pixel. If this is set then sarWidth must also be set */ + int sarHeight; + + /* Enable overscan info present flag in the VUI. If this is set then + * bEnabledOverscanAppropriateFlag will be added to the VUI. The default + * is false */ + int bEnableOverscanInfoPresentFlag; + + /* Enable overscan appropriate flag. The status of this flag is added + * to the VUI only if bEnableOverscanInfoPresentFlag is set. If this + * flag is set then cropped decoded pictures may be output for display. + * The default is false */ + int bEnableOverscanAppropriateFlag; + + /* Video signal type present flag of the VUI. If this is set then + * videoFormat, bEnableVideoFullRangeFlag and + * bEnableColorDescriptionPresentFlag will be added to the VUI. The + * default is false */ + int bEnableVideoSignalTypePresentFlag; + + /* Video format of the source video. 0 = component, 1 = PAL, 2 = NTSC, + * 3 = SECAM, 4 = MAC, 5 = unspecified video format is the default */ + int videoFormat; + + /* Video full range flag indicates the black level and range of the luma + * and chroma signals as derived from E′Y, E′PB, and E′PR or E′R, E′G, + * and E′B real-valued component signals. The default is false */ + int bEnableVideoFullRangeFlag; + + /* Color description present flag in the VUI. If this is set then + * color_primaries, transfer_characteristics and matrix_coeffs are to be + * added to the VUI. The default is false */ + int bEnableColorDescriptionPresentFlag; + + /* Color primaries holds the chromacity coordinates of the source + * primaries. The default is 2 */ + int colorPrimaries; + + /* Transfer characteristics indicates the opto-electronic transfer + * characteristic of the source picture. The default is 2 */ + int transferCharacteristics; + + /* Matrix coefficients used to derive the luma and chroma signals from + * the red, blue and green primaries. The default is 2 */ + int matrixCoeffs; + + /* Chroma location info present flag adds chroma_sample_loc_type_top_field and + * chroma_sample_loc_type_bottom_field to the VUI. The default is false */ + int bEnableChromaLocInfoPresentFlag; + + /* Chroma sample location type top field holds the chroma location in + * the top field. The default is 0 */ + int chromaSampleLocTypeTopField; + + /* Chroma sample location type bottom field holds the chroma location in + * the bottom field. The default is 0 */ + int chromaSampleLocTypeBottomField; + + /* Default display window flag adds def_disp_win_left_offset, + * def_disp_win_right_offset, def_disp_win_top_offset and + * def_disp_win_bottom_offset to the VUI. The default is false */ + int bEnableDefaultDisplayWindowFlag; + + /* Default display window left offset holds the left offset with the + * conformance cropping window to further crop the displayed window */ + int defDispWinLeftOffset; + + /* Default display window right offset holds the right offset with the + * conformance cropping window to further crop the displayed window */ + int defDispWinRightOffset; + + /* Default display window top offset holds the top offset with the + * conformance cropping window to further crop the displayed window */ + int defDispWinTopOffset; + + /* Default display window bottom offset holds the bottom offset with the + * conformance cropping window to further crop the displayed window */ + int defDispWinBottomOffset; + } vui; + + /* SMPTE ST 2086 mastering display color volume SEI info, specified as a + * string which is parsed when the stream header SEI are emitted. The string + * format is "G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)" where %hu + * are unsigned 16bit integers and %u are unsigned 32bit integers. The SEI + * includes X,Y display primaries for RGB channels, white point X,Y and + * max,min luminance values. */ + const char* masteringDisplayColorVolume; + + /* Maximum Content light level(MaxCLL), specified as integer that indicates the + * maximum pixel intensity level in units of 1 candela per square metre of the + * bitstream. x265 will also calculate MaxCLL programmatically from the input + * pixel values and set in the Content light level info SEI */ + uint16_t maxCLL; + + /* Maximum Frame Average Light Level(MaxFALL), specified as integer that indicates + * the maximum frame average intensity level in units of 1 candela per square + * metre of the bitstream. x265 will also calculate MaxFALL programmatically + * from the input pixel values and set in the Content light level info SEI */ + uint16_t maxFALL; + + /* Minimum luma level of input source picture, specified as a integer which + * would automatically increase any luma values below the specified --min-luma + * value to that value. */ + uint16_t minLuma; + + /* Maximum luma level of input source picture, specified as a integer which + * would automatically decrease any luma values above the specified --max-luma + * value to that value. */ + uint16_t maxLuma; + + /* Maximum of the picture order count */ + int log2MaxPocLsb; + + /* Emit VUI Timing info, an optional VUI field */ + int bEmitVUITimingInfo; + + /* Emit HRD Timing info */ + int bEmitVUIHRDInfo; + + /* Maximum count of Slices of picture, the value range is [1, maximum rows] */ + unsigned int maxSlices; + + /* Optimize QP in PPS based on statistics from prevvious GOP*/ + int bOptQpPPS; + + /* Opitmize ref list length in PPS based on stats from previous GOP*/ + int bOptRefListLengthPPS; + + /* Enable storing commonly RPS in SPS in multi pass mode */ + int bMultiPassOptRPS; + /* This value represents the percentage difference between the inter cost and + * intra cost of a frame used in scenecut detection. Default 5. */ + double scenecutBias; + /* Use multiple worker threads dedicated to doing only lookahead instead of sharing + * the worker threads with Frame Encoders. A dedicated lookahead threadpool is created with the + * specified number of worker threads. This can range from 0 upto half the + * hardware threads available for encoding. Using too many threads for lookahead can starve + * resources for frame Encoder and can harm performance. Default is 0 - disabled. */ + int lookaheadThreads; + /* Optimize CU level QPs to signal consistent deltaQPs in frame for rd level > 4 */ + int bOptCUDeltaQP; + /* Refine analysis in multipass ratecontrol based on analysis information stored */ + int analysisMultiPassRefine; + /* Refine analysis in multipass ratecontrol based on distortion data stored */ + int analysisMultiPassDistortion; + /* Adaptive Quantization based on relative motion */ + int bAQMotion; + /* SSIM based RDO, based on residual divisive normalization scheme. Used for mode + * selection during analysis of CTUs, can achieve significant gain in terms of + * objective quality metrics SSIM and PSNR */ + int bSsimRd; + + /* Increase RD at points where bitrate drops due to vbv. Default 0 */ + double dynamicRd; + + /* Enables the emitting of HDR SEI packets which contains HDR-specific params. + * Auto-enabled when max-cll, max-fall, or mastering display info is specified. + * Default is disabled. Now deprecated.*/ + int bEmitHDRSEI; + + /* Enable luma and chroma offsets for HDR/WCG content. + * Default is disabled. Now deprecated.*/ + int bHDROpt; + + /* A value between 1 and 10 (both inclusive) determines the level of + * information stored/reused in analysis save/load. Higher the refine + * level higher the information stored/reused. Default is 5. Now deprecated. */ + int analysisReuseLevel; + + /* Limit Sample Adaptive Offset filter computation by early terminating SAO + * process based on inter prediction mode, CTU spatial-domain correlations, + * and relations between luma and chroma */ + int bLimitSAO; + + /* File containing the tone mapping information */ + const char* toneMapFile; + + /* Insert tone mapping information only for IDR frames and when the + * tone mapping information changes. */ + int bDhdr10opt; + + /* Determine how x265 react to the content information recieved through the API */ + int bCTUInfo; + + /* Use ratecontrol statistics from pic_in, if available*/ + int bUseRcStats; + + /* Factor by which input video is scaled down for analysis save mode. Default is 0 */ + int scaleFactor; + + /* Enable intra refinement in load mode*/ + int intraRefine; + + /* Enable inter refinement in load mode*/ + int interRefine; + + /* Enable motion vector refinement in load mode*/ + int mvRefine; + + /* Log of maximum CTU size */ + uint32_t maxLog2CUSize; + + /* Actual CU depth with respect to config depth */ + uint32_t maxCUDepth; + + /* CU depth with respect to maximum transform size */ + uint32_t unitSizeDepth; + + /* Number of 4x4 units in maximum CU size */ + uint32_t num4x4Partitions; + + /* Specify if analysis mode uses file for data reuse */ + int bUseAnalysisFile; + + /* File pointer for csv log */ + FILE* csvfpt; + + /* Force flushing the frames from encoder */ + int forceFlush; + + /* Enable skipping split RD analysis when sum of split CU rdCost larger than none split CU rdCost for Intra CU */ + int bEnableSplitRdSkip; + + /* Disable lookahead */ + int bDisableLookahead; + + /* Use low-pass subband dct approximation + * This DCT approximation is less computational intensive and gives results close to standard DCT */ + int bLowPassDct; + + /* Sets the portion of the decode buffer that must be available after all the + * specified frames have been inserted into the decode buffer. If it is less + * than 1, then the final buffer available is vbv-end * vbvBufferSize. Otherwise, + * it is interpreted as the final buffer available in kbits. Default 0 (disabled) */ + double vbvBufferEnd; + + /* Frame from which qp has to be adjusted to hit final decode buffer emptiness. + * Specified as a fraction of the total frames. Default 0 */ + double vbvEndFrameAdjust; + + /* Reuse MV information obtained through API */ + int bAnalysisType; + /* Allow the encoder to have a copy of the planes of x265_picture in Frame */ + int bCopyPicToFrame; + + /*Number of frames for GOP boundary decision lookahead.If a scenecut frame is found + * within this from the gop boundary set by keyint, the GOP will be extented until such a point, + * otherwise the GOP will be terminated as set by keyint*/ + int gopLookahead; + + /*Write per-frame analysis information into analysis buffers. Default disabled. */ + const char* analysisSave; + + /* Read analysis information into analysis buffer and use this analysis information + * to reduce the amount of work the encoder must perform. Default disabled. */ + const char* analysisLoad; + + /*Number of RADL pictures allowed in front of IDR*/ + int radl; + + /* This value controls the maximum AU size defined in specification + * It represents the percentage of maximum AU size used. + * Default is 1 (which is 100%). Range is 0.5 to 1. */ + double maxAUSizeFactor; + + /* Enables the emission of a Recovery Point SEI with the stream headers + * at each IDR frame describing poc of the recovery point, exact matching flag + * and broken link flag. Default is disabled. */ + int bEmitIDRRecoverySEI; + + /* Dynamically change refine-inter at block level*/ + int bDynamicRefine; + + /* Enable writing all SEI messgaes in one single NAL instead of mul*/ + int bSingleSeiNal; + + + /* First frame of the chunk. Frames preceeding this in display order will + * be encoded, however, they will be discarded in the bitstream. + * Default 0 (disabled). */ + int chunkStart; + + /* Last frame of the chunk. Frames following this in display order will be + * used in taking lookahead decisions, but, they will not be encoded. + * Default 0 (disabled). */ + int chunkEnd; + /* File containing base64 encoded SEI messages in POC order */ + const char* naluFile; + + /* Generate bitstreams confirming to the specified dolby vision profile, + * note that 0x7C01 makes RPU appear to be an unspecified NAL type in + * HEVC stream. if BL is backward compatible, Dolby Vision single + * layer VES will be equivalent to a backward compatible BL VES on legacy + * device as RPU will be ignored. Default 0 (disabled) */ + int dolbyProfile; + + /* Set concantenation flag for the first keyframe in the HRD buffering period SEI. */ + int bEnableHRDConcatFlag; + + + /* Store/normalize ctu distortion in analysis-save/load. Ranges from 0 - 1. + * 0 - Disabled. 1 - Save/Load ctu distortion to/from the file specified + * analysis-save/load. Default 0. */ + int ctuDistortionRefine; + + /* Enable SVT HEVC Encoder */ + int bEnableSvtHevc; + + /* SVT-HEVC param structure. For internal use when SVT HEVC encoder is enabled */ + void* svtHevcParam; + + /* Detect fade-in regions. Enforces I-slice for the brightest point. + Re-init RC history at that point in ABR mode. Default is disabled. */ + int bEnableFades; + + /* Enable field coding */ + int bField; + + /*Emit content light level info SEI*/ + int bEmitCLL; + + /* + * Signals picture structure SEI timing message for every frame + * picture structure 7 is signalled for frame doubling + * picture structure 8 is signalled for frame tripling + * */ + int bEnableFrameDuplication; + + /* + * For adaptive frame duplication, a threshold is set above which the frames are similar. + * User can set a variable threshold. Default 70. + * */ + int dupThreshold; + + /*Input sequence bit depth. It can be either 8bit, 10bit or 12bit.*/ + int sourceBitDepth; + + /*Size of the zone to be reconfigured in frames. Default 0. API only. */ + uint32_t reconfigWindowSize; + + /*Flag to indicate if rate-control history has to be reset during zone reconfiguration. + Default 1 (Enabled). API only. */ + int bResetZoneConfig; + + /* Enables a ratecontrol algorithm for reducing the bits spent on the inter-frames + * within the scenecutWindow after a scenecut by increasing their QP without + * any deterioration in visual quality. It also increases the quality of scenecut I-Frames by reducing their QP. + * Default is disabled. */ + int bEnableSceneCutAwareQp; + + /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames after a scenecut + * by increasing their QP, when bEnableSceneCutAwareQp is set. Default is 500ms.*/ + int scenecutWindow; + + /* The offset by which QP is incremented for inter-frames when bEnableSceneCutAwareQp is set. + * Default is +5. */ + int maxQpDelta; + + /* A genuine threshold used for histogram based scene cut detection. + * This threshold determines whether a frame is a scenecut or not + * when compared against the edge and chroma histogram sad values. + * Default 0.01. Range: Real number in the interval (0,2). */ + double edgeTransitionThreshold; + + /* Enables histogram based scenecut detection algorithm to detect scenecuts. Default disabled */ + int bHistBasedSceneCut; + + /* Enable HME search ranges for L0, L1 and L2 respectively. */ + int hmeRange[3]; + + /* Block-level QP optimization for HDR10 content. Default is disabled.*/ + int bHDR10Opt; + + /* Enables the emitting of HDR10 SEI packets which contains HDR10-specific params. + * Auto-enabled when max-cll, max-fall, or mastering display info is specified. + * Default is disabled */ + int bEmitHDR10SEI; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information stored in analysis-save. Higher the refine level higher + * the information stored. Default is 5 */ + int analysisSaveReuseLevel; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information reused in analysis-load. Higher the refine level higher + * the information reused. Default is 5 */ + int analysisLoadReuseLevel; + + /* Conformance window right offset specifies the padding offset to the + * right side of the internal copy of the input pictures in the library. + * The decoded picture will be cropped based on conformance window right offset + * signaled in the SPS before output. Default is 0. + * Recommended to set this during non-file based analysis-load. + * This is to inform the encoder about the conformace window right offset + * to be added to match the number of CUs across the width for which analysis + * info is available from the corresponding analysis-save. */ + + int confWinRightOffset; + + /* Conformance window bottom offset specifies the padding offset to the + * bottom side of the internal copy of the input pictures in the library. + * The decoded picture will be cropped based on conformance window bottom offset + * signaled in the SPS before output. Default is 0. + * Recommended to set this during non-file based analysis-load. + * This is to inform the encoder about the conformace window bottom offset + * to be added to match the number of CUs across the height for which analysis + * info is available from the corresponding analysis-save. */ + + int confWinBottomOffset; + + /* Edge variance threshold for quad tree establishment. */ + float edgeVarThreshold; + + /* Maxrate that could be signaled to the decoder. Default 0. API only. */ + int decoderVbvMaxRate; +} x265_param; + +/* x265_param_alloc: + * Allocates an x265_param instance. The returned param structure is not + * special in any way, but using this method together with x265_param_free() + * and x265_param_parse() to set values by name allows the application to treat + * x265_param as an opaque data struct for version safety */ +x265_param *x265_param_alloc(void); + +/* x265_param_free: + * Use x265_param_free() to release storage for an x265_param instance + * allocated by x265_param_alloc() */ +void x265_param_free(x265_param *); + +/* x265_param_default: + * Initialize an x265_param structure to default values */ +void x265_param_default(x265_param *param); + +/* x265_param_parse: + * set one parameter by name. + * returns 0 on success, or returns one of the following errors. + * note: BAD_VALUE occurs only if it can't even parse the value, + * numerical range is not checked until x265_encoder_open(). + * value=NULL means "true" for boolean options, but is a BAD_VALUE for non-booleans. */ +#define X265_PARAM_BAD_NAME (-1) +#define X265_PARAM_BAD_VALUE (-2) +int x265_param_parse(x265_param *p, const char *name, const char *value); + +x265_zone *x265_zone_alloc(int zoneCount, int isZoneFile); + +void x265_zone_free(x265_param *param); + +int x265_zone_param_parse(x265_param* p, const char* name, const char* value); + +static const char * const x265_profile_names[] = { + /* HEVC v1 */ + "main", "main10", "mainstillpicture", /* alias */ "msp", + + /* HEVC v2 (Range Extensions) */ + "main-intra", "main10-intra", + "main444-8", "main444-intra", "main444-stillpicture", + + "main422-10", "main422-10-intra", + "main444-10", "main444-10-intra", + + "main12", "main12-intra", + "main422-12", "main422-12-intra", + "main444-12", "main444-12-intra", + + "main444-16-intra", "main444-16-stillpicture", /* Not Supported! */ + 0 +}; + +/* x265_param_apply_profile: + * Applies the restrictions of the given profile. (one of x265_profile_names) + * (can be NULL, in which case the function will do nothing) + * Note: the detected profile can be lower than the one specified to this + * function. This function will force the encoder parameters to fit within + * the specified profile, or fail if that is impossible. + * returns 0 on success, negative on failure (e.g. invalid profile name). */ +int x265_param_apply_profile(x265_param *, const char *profile); + +/* x265_param_default_preset: + * The same as x265_param_default, but also use the passed preset and tune + * to modify the default settings. + * (either can be NULL, which implies no preset or no tune, respectively) + * + * Currently available presets are, ordered from fastest to slowest: */ +static const char * const x265_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 }; + +/* The presets can also be indexed numerically, as in: + * x265_param_default_preset( ¶m, "3", ... ) + * with ultrafast mapping to "0" and placebo mapping to "9". This mapping may + * of course change if new presets are added in between, but will always be + * ordered from fastest to slowest. + * + * Warning: the speed of these presets scales dramatically. Ultrafast is a full + * 100 times faster than placebo! + * + * Currently available tunings are: */ +static const char * const x265_tune_names[] = { "psnr", "ssim", "grain", "zerolatency", "fastdecode", "animation", 0 }; + +/* returns 0 on success, negative on failure (e.g. invalid preset/tune name). */ +int x265_param_default_preset(x265_param *, const char *preset, const char *tune); + +/* x265_picture_alloc: + * Allocates an x265_picture instance. The returned picture structure is not + * special in any way, but using this method together with x265_picture_free() + * and x265_picture_init() allows some version safety. New picture fields will + * always be added to the end of x265_picture */ +x265_picture *x265_picture_alloc(void); + +/* x265_picture_free: + * Use x265_picture_free() to release storage for an x265_picture instance + * allocated by x265_picture_alloc() */ +void x265_picture_free(x265_picture *); + +/* x265_picture_init: + * Initialize an x265_picture structure to default values. It sets the pixel + * depth and color space to the encoder's internal values and sets the slice + * type to auto - so the lookahead will determine slice type. */ +void x265_picture_init(x265_param *param, x265_picture *pic); + +/* x265_max_bit_depth: + * Specifies the numer of bits per pixel that x265 uses internally to + * represent a pixel, and the bit depth of the output bitstream. + * param->internalBitDepth must be set to this value. x265_max_bit_depth + * will be 8 for default builds, 10 for HIGH_BIT_DEPTH builds. */ +X265_API extern const int x265_max_bit_depth; + +/* x265_version_str: + * A static string containing the version of this compiled x265 library */ +X265_API extern const char *x265_version_str; + +/* x265_build_info: + * A static string describing the compiler and target architecture */ +X265_API extern const char *x265_build_info_str; + +/* x265_alloc_analysis_data: +* Allocate memory for the x265_analysis_data object's internal structures. */ +void x265_alloc_analysis_data(x265_param *param, x265_analysis_data* analysis); + +/* +* Free the allocated memory for x265_analysis_data object's internal structures. */ +void x265_free_analysis_data(x265_param *param, x265_analysis_data* analysis); + +/* Force a link error in the case of linking against an incompatible API version. + * Glue #defines exist to force correct macro expansion; the final output of the macro + * is x265_encoder_open_##X265_BUILD (for purposes of dlopen). */ +#define x265_encoder_glue1(x, y) x ## y +#define x265_encoder_glue2(x, y) x265_encoder_glue1(x, y) +#define x265_encoder_open x265_encoder_glue2(x265_encoder_open_, X265_BUILD) + +/* x265_encoder_open: + * create a new encoder handler, all parameters from x265_param are copied */ +x265_encoder* x265_encoder_open(x265_param *); + +/* x265_encoder_parameters: + * copies the current internal set of parameters to the pointer provided + * by the caller. useful when the calling application needs to know + * how x265_encoder_open has changed the parameters. + * note that the data accessible through pointers in the returned param struct + * (e.g. filenames) should not be modified by the calling application. */ +void x265_encoder_parameters(x265_encoder *, x265_param *); + +/* x265_encoder_headers: + * return the SPS and PPS that will be used for the whole stream. + * *pi_nal is the number of NAL units outputted in pp_nal. + * returns negative on error, total byte size of payload data on success + * the payloads of all output NALs are guaranteed to be sequential in memory. */ +int x265_encoder_headers(x265_encoder *, x265_nal **pp_nal, uint32_t *pi_nal); + +/* x265_encoder_encode: + * encode one picture. + * *pi_nal is the number of NAL units outputted in pp_nal. + * returns negative on error, 1 if a picture and access unit were output, + * or zero if the encoder pipeline is still filling or is empty after flushing. + * the payloads of all output NALs are guaranteed to be sequential in memory. + * To flush the encoder and retrieve delayed output pictures, pass pic_in as NULL. + * Once flushing has begun, all subsequent calls must pass pic_in as NULL. */ +int x265_encoder_encode(x265_encoder *encoder, x265_nal **pp_nal, uint32_t *pi_nal, x265_picture *pic_in, x265_picture *pic_out); + +/* x265_encoder_reconfig: + * various parameters from x265_param are copied. + * this takes effect immediately, on whichever frame is encoded next; + * returns 0 on success, negative on parameter validation error. + * + * not all parameters can be changed; see the actual function for a + * detailed breakdown. since not all parameters can be changed, moving + * from preset to preset may not always fully copy all relevant parameters, + * but should still work usably in practice. however, more so than for + * other presets, many of the speed shortcuts used in ultrafast cannot be + * switched out of; using reconfig to switch between ultrafast and other + * presets is not recommended without a more fine-grained breakdown of + * parameters to take this into account. */ +int x265_encoder_reconfig(x265_encoder *, x265_param *); + +/* x265_encoder_reconfig_zone: +* zone settings are copied to the encoder's param. +* Properties of the zone will be used only to re-configure rate-control settings +* of the zone mid-encode. Returns 0 on success on successful copy, negative on failure.*/ +int x265_encoder_reconfig_zone(x265_encoder *, x265_zone *); + +/* x265_encoder_get_stats: + * returns encoder statistics */ +void x265_encoder_get_stats(x265_encoder *encoder, x265_stats *, uint32_t statsSizeBytes); + +/* x265_encoder_log: + * write a line to the configured CSV file. If a CSV filename was not + * configured, or file open failed, this function will perform no write. */ +void x265_encoder_log(x265_encoder *encoder, int argc, char **argv); + +/* x265_encoder_close: + * close an encoder handler */ +void x265_encoder_close(x265_encoder *); + +/* x265_encoder_intra_refresh: + * If an intra refresh is not in progress, begin one with the next P-frame. + * If an intra refresh is in progress, begin one as soon as the current one finishes. + * Requires bIntraRefresh to be set. + * + * Useful for interactive streaming where the client can tell the server that packet loss has + * occurred. In this case, keyint can be set to an extremely high value so that intra refreshes + * occur only when calling x265_encoder_intra_refresh. + * + * In multi-pass encoding, if x265_encoder_intra_refresh is called differently in each pass, + * behavior is undefined. + * + * Should not be called during an x265_encoder_encode. */ + +int x265_encoder_intra_refresh(x265_encoder *); + +/* x265_encoder_ctu_info: + * Copy CTU information such as ctu address and ctu partition structure of all + * CTUs in each frame. The function is invoked only if "--ctu-info" is enabled and + * the encoder will wait for this copy to complete if enabled. + */ +int x265_encoder_ctu_info(x265_encoder *, int poc, x265_ctu_info_t** ctu); + +/* x265_get_slicetype_poc_and_scenecut: + * get the slice type, poc and scene cut information for the current frame, + * returns negative on error, 0 when access unit were output. + * This API must be called after(poc >= lookaheadDepth + bframes + 2) condition check */ +int x265_get_slicetype_poc_and_scenecut(x265_encoder *encoder, int *slicetype, int *poc, int* sceneCut); + +/* x265_get_ref_frame_list: + * returns negative on error, 0 when access unit were output. + * This API must be called after(poc >= lookaheadDepth + bframes + 2) condition check */ +int x265_get_ref_frame_list(x265_encoder *encoder, x265_picyuv**, x265_picyuv**, int, int, int*, int*); + +/* x265_set_analysis_data: + * set the analysis data. The incoming analysis_data structure is assumed to be AVC-sized blocks. + * returns negative on error, 0 access unit were output. */ +int x265_set_analysis_data(x265_encoder *encoder, x265_analysis_data *analysis_data, int poc, uint32_t cuBytes); + +/* x265_cleanup: + * release library static allocations, reset configured CTU size */ +void x265_cleanup(void); + +/* Open a CSV log file. On success it returns a file handle which must be passed + * to x265_csvlog_frame() and/or x265_csvlog_encode(). The file handle must be + * closed by the caller using fclose(). If csv-loglevel is 0, then no frame logging + * header is written to the file. This function will return NULL if it is unable + * to open the file for write or if it detects a structure size skew */ +FILE* x265_csvlog_open(const x265_param *); + +/* Log frame statistics to the CSV file handle. csv-loglevel should have been non-zero + * in the call to x265_csvlog_open() if this function is called. */ +void x265_csvlog_frame(const x265_param *, const x265_picture *); + +/* Log final encode statistics to the CSV file handle. 'argc' and 'argv' are + * intended to be command line arguments passed to the encoder. padx and pady are + * padding offsets for conformance and can be given from sps settings. Encode + * statistics should be queried from the encoder just prior to closing it. */ +void x265_csvlog_encode(const x265_param*, const x265_stats *, int padx, int pady, int argc, char** argv); + +/* In-place downshift from a bit-depth greater than 8 to a bit-depth of 8, using + * the residual bits to dither each row. */ +void x265_dither_image(x265_picture *, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth); +#if ENABLE_LIBVMAF +/* x265_calculate_vmafScore: + * returns VMAF score for the input video. + * This api must be called only after encoding was done. */ +double x265_calculate_vmafscore(x265_param*, x265_vmaf_data*); + +/* x265_calculate_vmaf_framelevelscore: + * returns VMAF score for each frame in a given input video. */ +double x265_calculate_vmaf_framelevelscore(x265_vmaf_framedata*); +/* x265_vmaf_encoder_log: + * write a line to the configured CSV file. If a CSV filename was not + * configured, or file open failed, this function will perform no write. + * This api will be called only when ENABLE_LIBVMAF cmake option is set */ +void x265_vmaf_encoder_log(x265_encoder *encoder, int argc, char **argv, x265_param*, x265_vmaf_data*); + +#endif + +#define X265_MAJOR_VERSION 1 + +/* === Multi-lib API === + * By using this method to gain access to the libx265 interfaces, you allow run- + * time selection between various available libx265 libraries based on the + * encoder parameters. The most likely use case is to choose between Main and + * Main10 builds of libx265. */ + +typedef struct x265_api +{ + int api_major_version; /* X265_MAJOR_VERSION */ + int api_build_number; /* X265_BUILD (soname) */ + int sizeof_param; /* sizeof(x265_param) */ + int sizeof_picture; /* sizeof(x265_picture) */ + int sizeof_analysis_data; /* sizeof(x265_analysis_data) */ + int sizeof_zone; /* sizeof(x265_zone) */ + int sizeof_stats; /* sizeof(x265_stats) */ + + int bit_depth; + const char* version_str; + const char* build_info_str; + + /* libx265 public API functions, documented above with x265_ prefixes */ + x265_param* (*param_alloc)(void); + void (*param_free)(x265_param*); + void (*param_default)(x265_param*); + int (*param_parse)(x265_param*, const char*, const char*); + int (*param_apply_profile)(x265_param*, const char*); + int (*param_default_preset)(x265_param*, const char*, const char *); + x265_picture* (*picture_alloc)(void); + void (*picture_free)(x265_picture*); + void (*picture_init)(x265_param*, x265_picture*); + x265_encoder* (*encoder_open)(x265_param*); + void (*encoder_parameters)(x265_encoder*, x265_param*); + int (*encoder_reconfig)(x265_encoder*, x265_param*); + int (*encoder_reconfig_zone)(x265_encoder*, x265_zone*); + int (*encoder_headers)(x265_encoder*, x265_nal**, uint32_t*); + int (*encoder_encode)(x265_encoder*, x265_nal**, uint32_t*, x265_picture*, x265_picture*); + void (*encoder_get_stats)(x265_encoder*, x265_stats*, uint32_t); + void (*encoder_log)(x265_encoder*, int, char**); + void (*encoder_close)(x265_encoder*); + void (*cleanup)(void); + + int sizeof_frame_stats; /* sizeof(x265_frame_stats) */ + int (*encoder_intra_refresh)(x265_encoder*); + int (*encoder_ctu_info)(x265_encoder*, int, x265_ctu_info_t**); + int (*get_slicetype_poc_and_scenecut)(x265_encoder*, int*, int*, int*); + int (*get_ref_frame_list)(x265_encoder*, x265_picyuv**, x265_picyuv**, int, int, int*, int*); + FILE* (*csvlog_open)(const x265_param*); + void (*csvlog_frame)(const x265_param*, const x265_picture*); + void (*csvlog_encode)(const x265_param*, const x265_stats *, int, int, int, char**); + void (*dither_image)(x265_picture*, int, int, int16_t*, int); + int (*set_analysis_data)(x265_encoder *encoder, x265_analysis_data *analysis_data, int poc, uint32_t cuBytes); +#if ENABLE_LIBVMAF + double (*calculate_vmafscore)(x265_param *, x265_vmaf_data *); + double (*calculate_vmaf_framelevelscore)(x265_vmaf_framedata *); + void (*vmaf_encoder_log)(x265_encoder*, int, char**, x265_param *, x265_vmaf_data *); +#endif + int (*zone_param_parse)(x265_param*, const char*, const char*); + /* add new pointers to the end, or increment X265_MAJOR_VERSION */ +} x265_api; + +/* Force a link error in the case of linking against an incompatible API version. + * Glue #defines exist to force correct macro expansion; the final output of the macro + * is x265_api_get_##X265_BUILD (for purposes of dlopen). */ +#define x265_api_glue1(x, y) x ## y +#define x265_api_glue2(x, y) x265_api_glue1(x, y) +#define x265_api_get x265_api_glue2(x265_api_get_, X265_BUILD) + +/* x265_api_get: + * Retrieve the programming interface for a linked x265 library. + * May return NULL if no library is available that supports the + * requested bit depth. If bitDepth is 0 the function is guarunteed + * to return a non-NULL x265_api pointer, from the linked libx265. + * + * If the requested bitDepth is not supported by the linked libx265, + * it will attempt to dynamically bind x265_api_get() from a shared + * library with an appropriate name: + * 8bit: libx265_main.so + * 10bit: libx265_main10.so + * Obviously the shared library file extension is platform specific */ +const x265_api* x265_api_get(int bitDepth); + +/* x265_api_query: + * Retrieve the programming interface for a linked x265 library, like + * x265_api_get(), except this function accepts X265_BUILD as the second + * argument rather than using the build number as part of the function name. + * Applications which dynamically link to libx265 can use this interface to + * query the library API and achieve a relative amount of version skew + * flexibility. The function may return NULL if the library determines that + * the apiVersion that your application was compiled against is not compatible + * with the library you have linked with. + * + * api_major_version will be incremented any time non-backward compatible + * changes are made to any public structures or functions. If + * api_major_version does not match X265_MAJOR_VERSION from the x265.h your + * application compiled against, your application must not use the returned + * x265_api pointer. + * + * Users of this API *must* also validate the sizes of any structures which + * are not treated as opaque in application code. For instance, if your + * application dereferences a x265_param pointer, then it must check that + * api->sizeof_param matches the sizeof(x265_param) that your application + * compiled with. */ +const x265_api* x265_api_query(int bitDepth, int apiVersion, int* err); + +#define X265_API_QUERY_ERR_NONE 0 /* returned API pointer is non-NULL */ +#define X265_API_QUERY_ERR_VER_REFUSED 1 /* incompatible version skew */ +#define X265_API_QUERY_ERR_LIB_NOT_FOUND 2 /* libx265_main10 not found, for ex */ +#define X265_API_QUERY_ERR_FUNC_NOT_FOUND 3 /* unable to bind x265_api_query */ +#define X265_API_QUERY_ERR_WRONG_BITDEPTH 4 /* libx265_main10 not 10bit, for ex */ + +static const char * const x265_api_query_errnames[] = { + "api queried from libx265", + "libx265 version is not compatible with this application", + "unable to bind a libx265 with requested bit depth", + "unable to bind x265_api_query from libx265", + "libx265 has an invalid bitdepth" +}; + +#ifdef __cplusplus +} +#endif + +#endif // X265_H diff --git a/thirdparty/include/x265_config.h b/thirdparty/include/x265_config.h new file mode 100755 index 0000000000000000000000000000000000000000..903e75fdf71fb81357b5697ba97608fa1c5910dd --- /dev/null +++ b/thirdparty/include/x265_config.h @@ -0,0 +1,34 @@ +/***************************************************************************** + * Copyright (C) 2013-2020 MulticoreWare, Inc + * + * Authors: Steve Borho + * + * 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 of the License, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at license @ x265.com. + *****************************************************************************/ + +#ifndef X265_CONFIG_H +#define X265_CONFIG_H + +/* Defines generated at build time */ + +/* Incremented each time public API is changed, X265_BUILD is used as + * the shared library SONAME on platforms which support it. It also + * prevents linking against a different version of the static lib */ +#define X265_BUILD 192 + +#endif diff --git a/thirdparty/user_include/ffmpeg/libavcodec/ac3_parser.h b/thirdparty/user_include/ffmpeg/libavcodec/ac3_parser.h new file mode 100755 index 0000000000000000000000000000000000000000..ff8cc4cf093116dd677a010aa1407ce6af81a25d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/ac3_parser.h @@ -0,0 +1,36 @@ +/* + * AC-3 parser prototypes + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 Michael Niedermayer + * + * 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 + */ + +#ifndef AVCODEC_AC3_PARSER_H +#define AVCODEC_AC3_PARSER_H + +#include +#include + +/** + * Extract the bitstream ID and the frame size from AC-3 data. + */ +int av_ac3_parse_header(const uint8_t *buf, size_t size, + uint8_t *bitstream_id, uint16_t *frame_size); + + +#endif /* AVCODEC_AC3_PARSER_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/adts_parser.h b/thirdparty/user_include/ffmpeg/libavcodec/adts_parser.h new file mode 100755 index 0000000000000000000000000000000000000000..f85becd13138e4e80032097286bd3c5a294f8a6a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/adts_parser.h @@ -0,0 +1,37 @@ +/* + * 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 + */ + +#ifndef AVCODEC_ADTS_PARSER_H +#define AVCODEC_ADTS_PARSER_H + +#include +#include + +#define AV_AAC_ADTS_HEADER_SIZE 7 + +/** + * Extract the number of samples and frames from AAC data. + * @param[in] buf pointer to AAC data buffer + * @param[out] samples Pointer to where number of samples is written + * @param[out] frames Pointer to where number of frames is written + * @return Returns 0 on success, error code on failure. + */ +int av_adts_header_parse(const uint8_t *buf, uint32_t *samples, + uint8_t *frames); + +#endif /* AVCODEC_ADTS_PARSER_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/avcodec.h b/thirdparty/user_include/ffmpeg/libavcodec/avcodec.h new file mode 100755 index 0000000000000000000000000000000000000000..d234271c5b82d3264d4136c73a0b40a5aac699ab --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/avcodec.h @@ -0,0 +1,6228 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * @ingroup libavc + * Libavcodec external API header + */ + +#include +#include "libavutil/samplefmt.h" +#include "libavutil/attributes.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/cpu.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "version.h" + +/** + * @defgroup libavc libavcodec + * Encoding/Decoding Library + * + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + */ + +/** + * @ingroup libavc + * @defgroup lavc_encdec send/receive encoding and decoding API overview + * @{ + * + * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/ + * avcodec_receive_packet() functions provide an encode/decode API, which + * decouples input and output. + * + * The API is very similar for encoding/decoding and audio/video, and works as + * follows: + * - Set up and open the AVCodecContext as usual. + * - Send valid input: + * - For decoding, call avcodec_send_packet() to give the decoder raw + * compressed data in an AVPacket. + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame + * containing uncompressed audio or video. + * In both cases, it is recommended that AVPackets and AVFrames are + * refcounted, or libavcodec might have to copy the input data. (libavformat + * always returns refcounted AVPackets, and av_frame_get_buffer() allocates + * refcounted AVFrames.) + * - Receive output in a loop. Periodically call one of the avcodec_receive_*() + * functions and process their output: + * - For decoding, call avcodec_receive_frame(). On success, it will return + * an AVFrame containing uncompressed audio or video data. + * - For encoding, call avcodec_receive_packet(). On success, it will return + * an AVPacket with a compressed frame. + * Repeat this call until it returns AVERROR(EAGAIN) or an error. The + * AVERROR(EAGAIN) return value means that new input data is required to + * return new output. In this case, continue with sending input. For each + * input frame/packet, the codec will typically return 1 output frame/packet, + * but it can also be 0 or more than 1. + * + * At the beginning of decoding or encoding, the codec might accept multiple + * input frames/packets without returning a frame, until its internal buffers + * are filled. This situation is handled transparently if you follow the steps + * outlined above. + * + * In theory, sending input can result in EAGAIN - this should happen only if + * not all output was received. You can use this to structure alternative decode + * or encode loops other than the one suggested above. For example, you could + * try sending new input on each iteration, and try to receive output if that + * returns EAGAIN. + * + * End of stream situations. These require "flushing" (aka draining) the codec, + * as the codec might buffer multiple frames or packets internally for + * performance or out of necessity (consider B-frames). + * This is handled as follows: + * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding) + * or avcodec_send_frame() (encoding) functions. This will enter draining + * mode. + * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() + * (encoding) in a loop until AVERROR_EOF is returned. The functions will + * not return AVERROR(EAGAIN), unless you forgot to enter draining mode. + * - Before decoding can be resumed again, the codec has to be reset with + * avcodec_flush_buffers(). + * + * Using the API as outlined above is highly recommended. But it is also + * possible to call functions outside of this rigid schema. For example, you can + * call avcodec_send_packet() repeatedly without calling + * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed + * until the codec's internal buffer has been filled up (which is typically of + * size 1 per output frame, after initial input), and then reject input with + * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to + * read at least some output. + * + * Not all codecs will follow a rigid and predictable dataflow; the only + * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on + * one end implies that a receive/send call on the other end will succeed, or + * at least will not fail with AVERROR(EAGAIN). In general, no codec will + * permit unlimited buffering of input or output. + * + * This API replaces the following legacy functions: + * - avcodec_decode_video2() and avcodec_decode_audio4(): + * Use avcodec_send_packet() to feed input to the decoder, then use + * avcodec_receive_frame() to receive decoded frames after each packet. + * Unlike with the old video decoding API, multiple frames might result from + * a packet. For audio, splitting the input packet into frames by partially + * decoding packets becomes transparent to the API user. You never need to + * feed an AVPacket to the API twice (unless it is rejected with AVERROR(EAGAIN) - then + * no data was read from the packet). + * Additionally, sending a flush/draining packet is required only once. + * - avcodec_encode_video2()/avcodec_encode_audio2(): + * Use avcodec_send_frame() to feed input to the encoder, then use + * avcodec_receive_packet() to receive encoded packets. + * Providing user-allocated buffers for avcodec_receive_packet() is not + * possible. + * - The new API does not handle subtitles yet. + * + * Mixing new and old function calls on the same AVCodecContext is not allowed, + * and will result in undefined behavior. + * + * Some codecs might require using the new API; using the old API will return + * an error when calling it. All codecs support the new API. + * + * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This + * would be an invalid state, which could put the codec user into an endless + * loop. The API has no concept of time either: it cannot happen that trying to + * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second + * later accepts the packet (with no other receive/flush API calls involved). + * The API is a strict state machine, and the passage of time is not supposed + * to influence it. Some timing-dependent behavior might still be deemed + * acceptable in certain cases. But it must never result in both send/receive + * returning EAGAIN at the same time at any point. It must also absolutely be + * avoided that the current state is "unstable" and can "flip-flop" between + * the send/receive APIs allowing progress. For example, it's not allowed that + * the codec randomly decides that it actually wants to consume a packet now + * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an + * avcodec_send_packet() call. + * @} + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + + AV_CODEC_ID_Y41P = 0x8000, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_AYUV, + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + + AV_CODEC_ID_PCM_S64LE = 0x10800, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + + AV_CODEC_ID_ADPCM_AFC = 0x11800, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + + AV_CODEC_ID_SDX2_DPCM = 0x14800, + AV_CODEC_ID_GREMLIN_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + + AV_CODEC_ID_FFWAVESYNTH = 0x15800, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + + AV_CODEC_ID_MICRODVD = 0x17800, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_BINTEXT = 0x18800, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket +}; + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with FF_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define AV_INPUT_BUFFER_MIN_SIZE 16384 + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONINTRA= 24, ///< discard all non intra frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +/** + * Allow decoders to produce frames with data planes that are not aligned + * to CPU requirements (e.g. due to cropping). + */ +#define AV_CODEC_FLAG_UNALIGNED (1 << 0) +/** + * Use fixed qscale. + */ +#define AV_CODEC_FLAG_QSCALE (1 << 1) +/** + * 4 MV per MB allowed / advanced prediction for H.263. + */ +#define AV_CODEC_FLAG_4MV (1 << 2) +/** + * Output even those frames that might be corrupted. + */ +#define AV_CODEC_FLAG_OUTPUT_CORRUPT (1 << 3) +/** + * Use qpel MC. + */ +#define AV_CODEC_FLAG_QPEL (1 << 4) +/** + * Don't output frames whose parameters differ from first + * decoded frame in stream. + */ +#define AV_CODEC_FLAG_DROPCHANGED (1 << 5) +/** + * Use internal 2pass ratecontrol in first pass mode. + */ +#define AV_CODEC_FLAG_PASS1 (1 << 9) +/** + * Use internal 2pass ratecontrol in second pass mode. + */ +#define AV_CODEC_FLAG_PASS2 (1 << 10) +/** + * loop filter. + */ +#define AV_CODEC_FLAG_LOOP_FILTER (1 << 11) +/** + * Only decode/encode grayscale. + */ +#define AV_CODEC_FLAG_GRAY (1 << 13) +/** + * error[?] variables will be set during encoding. + */ +#define AV_CODEC_FLAG_PSNR (1 << 15) +/** + * Input bitstream might be truncated at a random location + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG_TRUNCATED (1 << 16) +/** + * Use interlaced DCT. + */ +#define AV_CODEC_FLAG_INTERLACED_DCT (1 << 18) +/** + * Force low delay. + */ +#define AV_CODEC_FLAG_LOW_DELAY (1 << 19) +/** + * Place global headers in extradata instead of every keyframe. + */ +#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) +/** + * Use only bitexact stuff (except (I)DCT). + */ +#define AV_CODEC_FLAG_BITEXACT (1 << 23) +/* Fx : Flag for H.263+ extra options */ +/** + * H.263 advanced intra coding / MPEG-4 AC prediction + */ +#define AV_CODEC_FLAG_AC_PRED (1 << 24) +/** + * interlaced motion estimation + */ +#define AV_CODEC_FLAG_INTERLACED_ME (1 << 29) +#define AV_CODEC_FLAG_CLOSED_GOP (1U << 31) + +/** + * Allow non spec compliant speedup tricks. + */ +#define AV_CODEC_FLAG2_FAST (1 << 0) +/** + * Skip bitstream encoding. + */ +#define AV_CODEC_FLAG2_NO_OUTPUT (1 << 2) +/** + * Place global headers at every keyframe instead of in extradata. + */ +#define AV_CODEC_FLAG2_LOCAL_HEADER (1 << 3) + +/** + * timecode is in drop frame format. DEPRECATED!!!! + */ +#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13) + +/** + * Input bitstream might be truncated at a packet boundaries + * instead of only at frame boundaries. + */ +#define AV_CODEC_FLAG2_CHUNKS (1 << 15) +/** + * Discard cropping information from SPS. + */ +#define AV_CODEC_FLAG2_IGNORE_CROP (1 << 16) + +/** + * Show all frames before the first keyframe + */ +#define AV_CODEC_FLAG2_SHOW_ALL (1 << 22) +/** + * Export motion vectors through frame side data + */ +#define AV_CODEC_FLAG2_EXPORT_MVS (1 << 28) +/** + * Do not skip samples and export skip information as frame side data + */ +#define AV_CODEC_FLAG2_SKIP_MANUAL (1 << 29) +/** + * Do not reset ASS ReadOrder field on flush (subtitles decoding) + */ +#define AV_CODEC_FLAG2_RO_FLUSH_NOOP (1 << 30) + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() for allocating buffers and supports custom allocators. + * If not set, it might not use get_buffer() at all or use operations that + * assume the buffer was allocated by avcodec_default_get_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +#define AV_CODEC_CAP_TRUNCATED (1 << 3) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports avctx->thread_count == 0 (auto). + */ +#define AV_CODEC_CAP_AUTO_THREADS (1 << 15) +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) +/** + * Codec is intra only. + */ +#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Codec is lossless. + */ +#define AV_CODEC_CAP_LOSSLESS 0x80000000 + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This codec takes the reordered_opaque field from input AVFrames + * and returns it in the corresponding field in AVCodecContext after + * encoding. + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan { + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +} AVPanScan; + +/** + * This structure describes the bitrate properties of an encoded bitstream. It + * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD + * parameters for H.264/HEVC. + */ +typedef struct AVCPBProperties { + /** + * Maximum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int max_bitrate; +#else + int64_t max_bitrate; +#endif + /** + * Minimum bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int min_bitrate; +#else + int64_t min_bitrate; +#endif + /** + * Average bitrate of the stream, in bits per second. + * Zero if unknown or unspecified. + */ +#if FF_API_UNSANITIZED_BITRATES + int avg_bitrate; +#else + int64_t avg_bitrate; +#endif + + /** + * The size of the buffer to which the ratecontrol is applied, in bits. + * Zero if unknown or unspecified. + */ + int buffer_size; + + /** + * The delay between the time the packet this structure is associated with + * is received and the time when it should be decoded, in periods of a 27MHz + * clock. + * + * UINT64_MAX when unknown or unspecified. + */ + uint64_t vbv_delay; +} AVCPBProperties; + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +typedef struct AVPacketSideData { + uint8_t *data; + int size; + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * AVPacket is one of the few structs in FFmpeg, whose size is a part of public + * ABI. Thus it may be allocated on stack and no new fields can be added to it + * without libavcodec and libavformat major bump. + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + +#if FF_API_CONVERGENCE_DURATION + /** + * @deprecated Same as the duration field, but as int64_t. This was required + * for Matroska subtitles, whose duration values could overflow when the + * duration field was still an int. + */ + attribute_deprecated + int64_t convergence_duration; +#endif +} AVPacket; +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; +/** + * @} + */ + +struct AVCodecInternal; + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * The name string for AVOptions options matches the associated command line + * parameter name and can be found in libavcodec/options_table.h + * The AVOption/command line parameter names differ in some cases from the C + * structure field names for historic reasons or brevity. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by user, may be overwritten by libavcodec + * if this info is available in the stream + */ + int64_t bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * AV_CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * AV_CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * MJPEG: Huffman tables + * rv10: additional flags + * MPEG-4: global headers (they can be in the bitstream or here) + * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid problems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * Must be allocated with the av_malloc() family of functions. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * This often, but not always is the inverse of the frame rate or field rate + * for video. 1/time_base is not the average frame rate if the frame rate is not + * constant. + * + * Like containers, elementary streams also can store timestamps, 1/time_base + * is the unit in which these timestamps are specified. + * As example of such codec time base see ISO/IEC 14496-2:2001(E) + * vop_time_increment_resolution and fixed_vop_rate + * (fixed_vop_rate == 0 implies that it is different from the framerate) + * + * - encoding: MUST be set by user. + * - decoding: the use of this field for decoding is deprecated. + * Use framerate instead. + */ + AVRational time_base; + + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this field is unused (see initial_padding). + * + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * + * @note Those fields may not match the values of the last + * AVFrame output by avcodec_decode_video2 due frame + * reordering. + * + * - encoding: MUST be set by user. + * - decoding: May be set by the user before opening the decoder if known e.g. + * from the container. Some decoders will require the dimensions + * to be set by the caller. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height e.g. when + * the decoded frame is cropped before being output or lowres is enabled. + * + * @note Those field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: unused + * - decoding: May be set by the user before opening the decoder if known + * e.g. from the container. During decoding, the decoder may + * overwrite those values as required while parsing the data. + */ + int coded_width, coded_height; + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * + * @note This field may not match the value of the last + * AVFrame output by avcodec_receive_frame() due frame + * reordering. + * + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec while + * parsing the data. + */ + enum AVPixelFormat pix_fmt; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * callback to negotiate the pixelFormat + * @param fmt is the list of formats which are supported by the codec, + * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. + * The first is always the native one. + * @note The callback may be called again immediately if initialization for + * the selected (hardware-accelerated) pixel format failed. + * @warning Behavior is undefined if the callback returns a value not + * in the fmt list of formats. + * @return the chosen format + * - encoding: unused + * - decoding: Set by user, if not set the native format will be chosen. + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int b_frame_strategy; +#endif + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int mpeg_quant; +#endif + + /** + * qscale factor between P- and I-frames + * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 +#endif + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_MEDIAN_SAD 15 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int pre_me; +#endif + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * Must be allocated with the av_malloc() family of functions, and will be freed in + * avcodec_free_context(). + * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL. + * - decoding: Set/allocated/freed by libavcodec. + */ + uint16_t *inter_matrix; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int scenechange_threshold; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int noise_reduction; +#endif + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: Set by libavcodec + */ + int intra_dc_precision; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * minimum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB Lagrange multiplier + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + +#if FF_API_PRIVATE_OPT + /** + * @deprecated use encoder private options instead + */ + attribute_deprecated + int me_penalty_compensation; +#endif + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int brd_scale; +#endif + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int chromaoffset; +#endif + + /** + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int b_sensitivity; +#endif + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + int channels; ///< number of audio channels + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int frame_number; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + */ + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + */ + uint64_t request_channel_layout; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. What + * this means is, you may set however many entries in buf[] you feel necessary. + * Each buffer must be reference-counted using the AVBuffer API (see description + * of buf[] below). + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise extended_data must point to data + * - buf[] must contain one or more pointers to AVBufferRef structures. Each of + * the frame's data and extended_data pointers must be contained in these. That + * is, one AVBufferRef for each allocated chunk of memory, not necessarily one + * AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * Some decoders do not support linesizes changing between frames. + * + * If frame multithreading is used and thread_safe_callbacks is set, + * this callback may be called from a different thread, but not from more + * than one at once. Does not need to be reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /** + * If non-zero, the decoded audio and video frames returned from + * avcodec_decode_video2() and avcodec_decode_audio4() are reference-counted + * and are valid indefinitely. The caller must free them with + * av_frame_unref() when they are not needed anymore. + * Otherwise, the decoded frames must not be freed by the caller and are + * only valid until the next decode call. + * + * This is always automatically enabled if avcodec_receive_frame() is used. + * + * - encoding: unused + * - decoding: set by the caller before avcodec_open2(). + */ + attribute_deprecated + int refcounted_frames; + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: unused + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: Set by user, may be overwritten by libavcodec. + */ + int64_t rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int64_t rc_min_rate; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + +#if FF_API_CODER_TYPE +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 +#define FF_CODER_TYPE_RAW 2 +#define FF_CODER_TYPE_RLE 3 + /** + * @deprecated use encoder private options instead + */ + attribute_deprecated + int coder_type; +#endif /* FF_API_CODER_TYPE */ + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int context_model; +#endif + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_threshold; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_factor; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_exp; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int frame_skip_cmp; +#endif /* FF_API_PRIVATE_OPT */ + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int min_prediction_order; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int max_prediction_order; + + /** @deprecated use encoder private options instead */ + attribute_deprecated + int64_t timecode_frame_start; +#endif + +#if FF_API_RTP_CALLBACK + /** + * @deprecated unused + */ + /* The RTP callback: This function is called */ + /* every time the encoder has a packet to send. */ + /* It depends on the encoder if the data starts */ + /* with a Start Code (it should). H.263 does. */ + /* mb_nb contains the number of macroblocks */ + /* encoded in the RTP payload. */ + attribute_deprecated + void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); +#endif + +#if FF_API_PRIVATE_OPT + /** @deprecated use encoder private options instead */ + attribute_deprecated + int rtp_payload_size; /* The size of the RTP payload: the coder will */ + /* do its best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263. */ + /* This doesn't take account of any particular */ + /* headers inside the transmitted RTP payload. */ +#endif + +#if FF_API_STAT_BITS + /* statistics, used for 2-pass encoding */ + attribute_deprecated + int mv_bits; + attribute_deprecated + int header_bits; + attribute_deprecated + int i_tex_bits; + attribute_deprecated + int p_tex_bits; + attribute_deprecated + int i_count; + attribute_deprecated + int p_count; + attribute_deprecated + int skip_count; + attribute_deprecated + int misc_bits; + + /** @deprecated this field is unused */ + attribute_deprecated + int frame_bits; +#endif + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 +#define FF_BUG_IEDGE 32768 + + /** + * strictly follow the standard (MPEG-4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 +#define FF_EC_FAVOR_INTER 256 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#if FF_API_DEBUG_MV +/** + * @deprecated this option does nothing + */ +#define FF_DEBUG_MV 32 +#endif +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#if FF_API_DEBUG_MV +#define FF_DEBUG_VIS_QP 0x00002000 +#define FF_DEBUG_VIS_MB_TYPE 0x00004000 +#endif +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 +#define FF_DEBUG_GREEN_MD 0x00800000 +#define FF_DEBUG_NOMC 0x01000000 + +#if FF_API_DEBUG_MV + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 // visualize forward predicted MVs of P-frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 // visualize forward predicted MVs of B-frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 // visualize backward predicted MVs of B-frames +#endif + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + int err_recognition; + +/** + * Verify checksums embedded in the bitstream (could be of either encoded or + * decoded data, depending on the codec) and print an error message on mismatch. + * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the + * decoder returning an error. + */ +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) ///< detect bitstream specification deviations +#define AV_EF_BUFFER (1<<2) ///< detect improper bitstream length +#define AV_EF_EXPLODE (1<<3) ///< abort decoding on minor error detection + +#define AV_EF_IGNORE_ERR (1<<15) ///< ignore errors and continue +#define AV_EF_CAREFUL (1<<16) ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors +#define AV_EF_COMPLIANT (1<<17) ///< consider all spec non compliances as errors +#define AV_EF_AGGRESSIVE (1<<18) ///< consider things that a sane encoder should not do as an error + + + /** + * opaque 64-bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * - encoding: Set by libavcodec to the reordered_opaque of the input + * frame corresponding to the last returned packet. Only + * supported by encoders with the + * AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability. + * - decoding: Set by user. + */ + int64_t reordered_opaque; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + const struct AVHWAccel *hwaccel; + + /** + * Hardware accelerator context. + * For some hardware accelerators, a global context needs to be + * provided by the user. In that case, this holds display-dependent + * data FFmpeg cannot instantiate itself. Please refer to the + * FFmpeg HW accelerator documentation to know how to fill this + * is. e.g. for VA API, this is a struct vaapi_context. + * - encoding: unused + * - decoding: Set by user + */ + void *hwaccel_context; + + /** + * error + * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_XVID 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_NONE 24 /* Used by XvMC to extract IDCT coefficients with FF_IDCT_PERM_NONE */ +#define FF_IDCT_SIMPLEAUTO 128 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + +#if FF_API_LOWRES + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; +#endif + +#if FF_API_CODED_FRAME + /** + * the picture in the bitstream + * - encoding: Set by libavcodec. + * - decoding: unused + * + * @deprecated use the quality factor packet side data instead + */ + attribute_deprecated AVFrame *coded_frame; +#endif + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * Set by the client if its custom get_buffer() callback can be called + * synchronously from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_safe_callbacks; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * noise vs. sse weight for the nsse comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 +#define FF_PROFILE_MPEG2_AAC_LOW 128 +#define FF_PROFILE_MPEG2_AAC_HE 131 + +#define FF_PROFILE_DNXHD 0 +#define FF_PROFILE_DNXHR_LB 1 +#define FF_PROFILE_DNXHR_SQ 2 +#define FF_PROFILE_DNXHR_HQ 3 +#define FF_PROFILE_DNXHR_HQX 4 +#define FF_PROFILE_DNXHR_444 5 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 +#define FF_PROFILE_DTS_EXPRESS 70 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_MULTIVIEW_HIGH 118 +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_STEREO_HIGH 128 +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 1 +#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 2 +#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION 32768 +#define FF_PROFILE_JPEG2000_DCINEMA_2K 3 +#define FF_PROFILE_JPEG2000_DCINEMA_4K 4 + +#define FF_PROFILE_VP9_0 0 +#define FF_PROFILE_VP9_1 1 +#define FF_PROFILE_VP9_2 2 +#define FF_PROFILE_VP9_3 3 + +#define FF_PROFILE_HEVC_MAIN 1 +#define FF_PROFILE_HEVC_MAIN_10 2 +#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 + +#define FF_PROFILE_AV1_MAIN 0 +#define FF_PROFILE_AV1_HIGH 1 +#define FF_PROFILE_AV1_PROFESSIONAL 2 + +#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT 0xc0 +#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1 +#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT 0xc2 +#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS 0xc3 +#define FF_PROFILE_MJPEG_JPEG_LS 0xf7 + +#define FF_PROFILE_SBC_MSBC 1 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 +#define FF_PROFILE_PRORES_4444 4 +#define FF_PROFILE_PRORES_XQ 5 + +#define FF_PROFILE_ARIB_PROFILE_A 0 +#define FF_PROFILE_ARIB_PROFILE_C 1 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + +#if FF_API_VBV_DELAY + /** + * VBV delay coded in the last frame (in periods of a 27 MHz clock). + * Used for compliant TS muxing. + * - encoding: Set by libavcodec. + * - decoding: unused. + * @deprecated this value is now exported as a part of + * AV_PKT_DATA_CPB_PROPERTIES packet side data + */ + attribute_deprecated + uint64_t vbv_delay; +#endif + +#if FF_API_SIDEDATA_ONLY_PKT + /** + * Encoding only and set by default. Allow encoders to output packets + * that do not contain any encoded data, only side data. + * + * Some encoders need to output such packets, e.g. to update some stream + * parameters at the end of encoding. + * + * @deprecated this field disables the default behaviour and + * it is kept only for compatibility. + */ + attribute_deprecated + int side_data_only_packets; +#endif + + /** + * Audio only. The number of "priming" samples (padding) inserted by the + * encoder at the beginning of the audio. I.e. this number of leading + * decoded samples must be discarded by the caller to get the original audio + * without leading padding. + * + * - decoding: unused + * - encoding: Set by libavcodec. The timestamps on the output packets are + * adjusted by the encoder so that they always refer to the + * first sample of the data actually contained in the packet, + * including any added padding. E.g. if the timebase is + * 1/samplerate and the timestamp of the first input sample is + * 0, the timestamp of the first output packet will be + * -initial_padding. + */ + int initial_padding; + + /** + * - decoding: For codecs that store a framerate value in the compressed + * bitstream, the decoder may export it here. { 0, 1} when + * unknown. + * - encoding: May be used to signal the framerate of CFR content to an + * encoder. + */ + AVRational framerate; + + /** + * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx. + * - encoding: unused. + * - decoding: Set by libavcodec before calling get_format() + */ + enum AVPixelFormat sw_pix_fmt; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. + * - encoding unused. + * - decoding set by user. + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const AVCodecDescriptor *codec_descriptor; + +#if !FF_API_LOWRES + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; +#endif + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +#define FF_SUB_CHARENC_MODE_IGNORE 2 ///< neither convert the subtitles, nor check them for valid UTF-8 + + /** + * Skip processing alpha if supported by codec. + * Note that if the format uses pre-multiplied alpha (common with VP6, + * and recommended due to better video quality/compression) + * the image will look as if alpha-blended onto a black background. + * However for formats that do not use pre-multiplied alpha + * there might be serious artefacts (though e.g. libswscale currently + * assumes pre-multiplied alpha anyway). + * + * - decoding: set by user + * - encoding: unused + */ + int skip_alpha; + + /** + * Number of samples to skip after a discontinuity + * - decoding: unused + * - encoding: set by libavcodec + */ + int seek_preroll; + +#if !FF_API_DEBUG_MV + /** + * debug motion vectors + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames +#endif + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: unused. + */ + uint16_t *chroma_intra_matrix; + + /** + * dump format separator. + * can be ", " or "\n " or anything else + * - encoding: Set by user. + * - decoding: Set by user. + */ + uint8_t *dump_separator; + + /** + * ',' separated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user + */ + char *codec_whitelist; + + /** + * Properties of the stream that gets decoded + * - encoding: unused + * - decoding: set by libavcodec + */ + unsigned properties; +#define FF_CODEC_PROPERTY_LOSSLESS 0x00000001 +#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002 + + /** + * Additional data associated with the entire coded stream. + * + * - decoding: unused + * - encoding: may be set by libavcodec after avcodec_open2(). + */ + AVPacketSideData *coded_side_data; + int nb_coded_side_data; + + /** + * A reference to the AVHWFramesContext describing the input (for encoding) + * or output (decoding) frames. The reference is set by the caller and + * afterwards owned (and freed) by libavcodec - it should never be read by + * the caller after being set. + * + * - decoding: This field should be set by the caller from the get_format() + * callback. The previous reference (if any) will always be + * unreffed by libavcodec before the get_format() call. + * + * If the default get_buffer2() is used with a hwaccel pixel + * format, then this AVHWFramesContext will be used for + * allocating the frame buffers. + * + * - encoding: For hardware encoders configured to use a hwaccel pixel + * format, this field should be set by the caller to a reference + * to the AVHWFramesContext describing input frames. + * AVHWFramesContext.format must be equal to + * AVCodecContext.pix_fmt. + * + * This field should be set before avcodec_open2() is called. + */ + AVBufferRef *hw_frames_ctx; + + /** + * Control the form of AVSubtitle.rects[N]->ass + * - decoding: set by user + * - encoding: unused + */ + int sub_text_format; +#define FF_SUB_TEXT_FMT_ASS 0 +#if FF_API_ASS_TIMING +#define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1 +#endif + + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + * + * - decoding: unused + * - encoding: unused + */ + int trailing_padding; + + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + + /** + * A reference to the AVHWDeviceContext describing the device which will + * be used by a hardware encoder/decoder. The reference is set by the + * caller and afterwards owned (and freed) by libavcodec. + * + * This should be used if either the codec device does not require + * hardware frames or any that are used are to be allocated internally by + * libavcodec. If the user wishes to supply any of the frames used as + * encoder input or decoder output then hw_frames_ctx should be used + * instead. When hw_frames_ctx is set in get_format() for a decoder, this + * field will be ignored while decoding the associated stream segment, but + * may again be used on a following one after another get_format() call. + * + * For both encoders and decoders this field should be set before + * avcodec_open2() is called and must not be written to thereafter. + * + * Note that some decoders may require this field to be set initially in + * order to support hw_frames_ctx at all - in that case, all frames + * contexts used must be created on the same device. + */ + AVBufferRef *hw_device_ctx; + + /** + * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated + * decoding (if active). + * - encoding: unused + * - decoding: Set by user (either before avcodec_open2(), or in the + * AVCodecContext.get_format callback) + */ + int hwaccel_flags; + + /** + * Video decoding only. Certain video codecs support cropping, meaning that + * only a sub-rectangle of the decoded frame is intended for display. This + * option controls how cropping is handled by libavcodec. + * + * When set to 1 (the default), libavcodec will apply cropping internally. + * I.e. it will modify the output frame width/height fields and offset the + * data pointers (only by as much as possible while preserving alignment, or + * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that + * the frames output by the decoder refer only to the cropped area. The + * crop_* fields of the output frames will be zero. + * + * When set to 0, the width/height fields of the output frames will be set + * to the coded dimensions and the crop_* fields will describe the cropping + * rectangle. Applying the cropping is left to the caller. + * + * @warning When hardware acceleration with opaque output frames is used, + * libavcodec is unable to apply cropping from the top/left border. + * + * @note when this option is set to zero, the width/height fields of the + * AVCodecContext and output AVFrames have different meanings. The codec + * context fields store display dimensions (with the coded dimensions in + * coded_width/height), while the frame fields store the coded dimensions + * (with the display dimensions being determined by the crop_* fields). + */ + int apply_cropping; + + /* + * Video decoding only. Sets the number of extra hardware frames which + * the decoder will allocate for use by the caller. This must be set + * before avcodec_open2() is called. + * + * Some hardware decoders require all frames that they will use for + * output to be defined in advance before decoding starts. For such + * decoders, the hardware frame pool must therefore be of a fixed size. + * The extra frames set here are on top of any number that the decoder + * needs internally in order to operate normally (for example, frames + * used as reference pictures). + */ + int extra_hw_frames; + + /** + * The percentage of damaged samples to discard a frame. + * + * - decoding: set by user + * - encoding: unused + */ + int discard_damaged_percentage; +} AVCodecContext; + +#if FF_API_CODEC_GET_SET +/** + * Accessors for some AVCodecContext fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); + +attribute_deprecated +const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); + +attribute_deprecated +unsigned av_codec_get_codec_properties(const AVCodecContext *avctx); + +#if FF_API_LOWRES +attribute_deprecated +int av_codec_get_lowres(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_lowres(AVCodecContext *avctx, int val); +#endif + +attribute_deprecated +int av_codec_get_seek_preroll(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_seek_preroll(AVCodecContext *avctx, int val); + +attribute_deprecated +uint16_t *av_codec_get_chroma_intra_matrix(const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_chroma_intra_matrix(AVCodecContext *avctx, uint16_t *val); +#endif + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * A hardware pixel format which the codec can use. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +typedef struct AVCodecDefault AVCodecDefault; + +struct AVSubtitle; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; + struct AVCodec *next; + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * If defined, called on thread contexts when they are created. + * If the codec allocates writable tables in init(), re-allocate them here. + * priv_data will be set to a copy of the original. + */ + int (*init_thread_copy)(AVCodecContext *); + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from avcodec_register(). + * + * This is not intended for time consuming operations as it is + * run for every codec regardless of that codec being used. + */ + void (*init_static_data)(struct AVCodec *codec); + + int (*init)(AVCodecContext *); + int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, + const struct AVSubtitle *sub); + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket (may contain a user-provided buffer) + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, + int *got_packet_ptr); + int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); + int (*close)(AVCodecContext *); + /** + * Encode API with decoupled packet/frame dataflow. The API is the + * same as the avcodec_ prefixed APIs (avcodec_send_frame() etc.), except + * that: + * - never called if the codec is closed or the wrong type, + * - if AV_CODEC_CAP_DELAY is not set, drain frames are never sent, + * - only one drain frame is ever passed down, + */ + int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame); + int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt); + + /** + * Decode API with decoupled packet/frame dataflow. This function is called + * to get one output frame. It should call ff_decode_get_packet() to obtain + * input data. + */ + int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame); + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(AVCodecContext *); + /** + * Internal codec capabilities. + * See FF_CODEC_CAP_* in internal.h + */ + int caps_internal; + + /** + * Decoding only, a comma-separated list of bitstream filters to apply to + * packets before decoding. + */ + const char *bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal **hw_configs; +} AVCodec; + +#if FF_API_CODEC_GET_SET +attribute_deprecated +int av_codec_get_max_lowres(const AVCodec *codec); +#endif + +struct MpegEncContext; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @defgroup lavc_hwaccel AVHWAccel + * + * @note Nothing in this structure should be accessed by the user. At some + * point in future it will not be externally visible at all. + * + * @{ + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see AV_HWACCEL_CODEC_CAP_* + */ + int capabilities; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + /** + * Allocate a custom buffer + */ + int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); + + /** + * Called at the beginning of each frame or field picture. + * + * Meaningful frame information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * Note that buf can be NULL along with buf_size set to 0. + * Otherwise, this means the whole frame is available at this point. + * + * @param avctx the codec context + * @param buf the frame data buffer base + * @param buf_size the size of the frame in bytes + * @return zero if successful, a negative value otherwise + */ + int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for parameter data (SPS/PPS/VPS etc). + * + * Useful for hardware decoders which keep persistent state about the + * video parameters, and need to receive any changes to update that state. + * + * @param avctx the codec context + * @param type the nal unit type + * @param buf the nal unit data buffer + * @param buf_size the size of the nal unit in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for each slice. + * + * Meaningful slice information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * The only exception is XvMC, that works on MB level. + * + * @param avctx the codec context + * @param buf the slice data buffer base + * @param buf_size the size of the slice in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Called at the end of each frame or field picture. + * + * The whole picture is parsed at this point and can now be sent + * to the hardware accelerator. This function is mandatory. + * + * @param avctx the codec context + * @return zero if successful, a negative value otherwise + */ + int (*end_frame)(AVCodecContext *avctx); + + /** + * Size of per-frame hardware accelerator private data. + * + * Private data is allocated with av_mallocz() before + * AVCodecContext.get_buffer() and deallocated after + * AVCodecContext.release_buffer(). + */ + int frame_priv_data_size; + + /** + * Called for every Macroblock in a slice. + * + * XvMC uses it to replace the ff_mpv_reconstruct_mb(). + * Instead of decoding to raw picture, MB parameters are + * stored in an array provided by the video driver. + * + * @param s the mpeg context + */ + void (*decode_mb)(struct MpegEncContext *s); + + /** + * Initialize the hwaccel private data. + * + * This will be called from ff_get_format(), after hwaccel and + * hwaccel_context are set and the hwaccel private data in AVCodecInternal + * is allocated. + */ + int (*init)(AVCodecContext *avctx); + + /** + * Uninitialize the hwaccel private data. + * + * This will be called from get_format() or avcodec_close(), after hwaccel + * and hwaccel_context are already uninitialized. + */ + int (*uninit)(AVCodecContext *avctx); + + /** + * Size of the private data to allocate in + * AVCodecInternal.hwaccel_priv_data. + */ + int priv_data_size; + + /** + * Internal hwaccel capabilities. + */ + int caps_internal; + + /** + * Fill the given hw_frames context with current codec parameters. Called + * from get_format. Refer to avcodec_get_hw_frames_parameters() for + * details. + * + * This CAN be called before AVHWAccel.init is called, and you must assume + * that avctx->hwaccel_priv_data is invalid. + */ + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); +} AVHWAccel; + +/** + * HWAccel is experimental and is thus avoided in favor of non experimental + * codecs + */ +#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200 + +/** + * Hardware acceleration should be used for decoding even if the codec level + * used is unknown or higher than the maximum supported level reported by the + * hardware driver. + * + * It's generally a good idea to pass this flag unless you have a specific + * reason not to, as hardware tends to under-report supported levels. + */ +#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0) + +/** + * Hardware acceleration can output YUV pixel formats with a different chroma + * sampling than 4:2:0 and/or other than 8 bits per component. + */ +#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1) + +/** + * Hardware acceleration should still be attempted for decoding when the + * codec profile does not match the reported capabilities of the hardware. + * + * For example, this can be used to try to decode baseline profile H.264 + * streams in hardware - it will often succeed, because many streams marked + * as baseline profile actually conform to constrained baseline profile. + * + * @warning If the stream is actually not supported then the behaviour is + * undefined, and may include returning entirely incorrect output + * while indicating success. + */ +#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2) + +/** + * @} + */ + +#if FF_API_AVPICTURE +/** + * @defgroup lavc_picture AVPicture + * + * Functions for working with AVPicture + * @{ + */ + +/** + * Picture data structure. + * + * Up to four components can be stored into it, the last component is + * alpha. + * @deprecated use AVFrame or imgutils functions instead + */ +typedef struct AVPicture { + attribute_deprecated + uint8_t *data[AV_NUM_DATA_POINTERS]; ///< pointers to the image data planes + attribute_deprecated + int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line +} AVPicture; + +/** + * @} + */ +#endif + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + +#if FF_API_AVPICTURE + /** + * @deprecated unused + */ + attribute_deprecated + AVPicture pict; +#endif + /** + * data+linesize for the bitmap of this subtitle. + * Can be set for text/ass as well once they are rendered. + */ + uint8_t *data[4]; + int linesize[4]; + + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; + + int flags; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + */ + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + */ + int channels; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; +} AVCodecParameters; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +#if FF_API_NEXT +/** + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. + */ +attribute_deprecated +AVCodec *av_codec_next(const AVCodec *c); +#endif + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +#if FF_API_NEXT +/** + * Register the codec codec and initialize libavcodec. + * + * @warning either this function or avcodec_register_all() must be called + * before any other libavcodec functions. + * + * @see avcodec_register_all() + */ +attribute_deprecated +void avcodec_register(AVCodec *codec); + +/** + * Register all the codecs, parsers and bitstream filters which were enabled at + * configuration time. If you do not call this function you can select exactly + * which formats you want to support, by using the individual registration + * functions. + * + * @see avcodec_register + * @see av_register_codec_parser + * @see av_register_bitstream_filter + */ +attribute_deprecated +void avcodec_register_all(void); +#endif + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct should be freed with avcodec_free_context(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Free the codec context and everything associated with it and write NULL to + * the provided pointer. + */ +void avcodec_free_context(AVCodecContext **avctx); + +#if FF_API_GET_CONTEXT_DEFAULTS +/** + * @deprecated This function should not be used, as closing and opening a codec + * context multiple time is not supported. A new codec context should be + * allocated for each new use. + */ +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); +#endif + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +#if FF_API_COPY_CONTEXT +/** + * Get the AVClass for AVFrame. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_frame_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open2() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context3(NULL), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + * + * @deprecated The semantics of this function are ill-defined and it should not + * be used. If you need to transfer the stream parameters from one codec context + * to another, use an intermediate AVCodecParameters instance and the + * avcodec_parameters_from_context() / avcodec_parameters_to_context() + * functions. + */ +attribute_deprecated +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); +#endif + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + +/** + * Fill the parameters struct based on the values from the supplied codec + * context. Any allocated fields in par are freed and replaced with duplicates + * of the corresponding fields in codec. + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec); + +/** + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par); + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @code + * avcodec_register_all(); + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. + * + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. + */ +int avcodec_close(AVCodecContext *avctx); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_packet + * @{ + */ + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + */ +void av_init_packet(AVPacket *pkt); + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +#if FF_API_AVPACKET_OLD_API +/** + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + * + * @deprecated Use av_packet_ref or av_packet_make_refcounted + */ +attribute_deprecated +int av_dup_packet(AVPacket *pkt); +/** + * Copy packet, including contents + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_ref + */ +attribute_deprecated +int av_copy_packet(AVPacket *dst, const AVPacket *src); + +/** + * Copy packet side data + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_copy_props + */ +attribute_deprecated +int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src); + +/** + * Free a packet. + * + * @deprecated Use av_packet_unref + * + * @param pkt packet to free + */ +attribute_deprecated +void av_free_packet(AVPacket *pkt); +#endif +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, + int *size); + +#if FF_API_MERGE_SD_API +attribute_deprecated +int av_packet_merge_side_data(AVPacket *pkt); + +attribute_deprecated +int av_packet_split_side_data(AVPacket *pkt); +#endif + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size); +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict); + + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +/** + * Converts AVChromaLocation to swscale x/y chroma position. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +int avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos); + +/** + * Converts swscale x/y chroma position to AVChromaLocation. + * + * The positions represent the chroma (0,0) position in a coordinates system + * with luma (0,0) representing the origin and luma(1,1) representing 256,256 + * + * @param xpos horizontal chroma sample position + * @param ypos vertical chroma sample position + */ +enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); + +/** + * Decode the audio frame of size avpkt->size from avpkt->data into frame. + * + * Some decoders may support multiple frames in a single AVPacket. Such + * decoders would then just decode the first frame and the return value would be + * less than the packet size. In this case, avcodec_decode_audio4 has to be + * called again with an AVPacket containing the remaining data in order to + * decode the second frame, etc... Even if no frames are returned, the packet + * needs to be fed to the decoder with remaining data until it is completely + * consumed or an error occurs. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning samples. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no samples will be returned. + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] frame The AVFrame in which to store decoded audio samples. + * The decoder will allocate a buffer for the decoded frame by + * calling the AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing or flushing the + * decoder. The caller may not write to it. + * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is + * non-zero. Note that this field being set to zero + * does not mean that an error has occurred. For + * decoders with AV_CODEC_CAP_DELAY set, no given decode + * call is guaranteed to produce a frame. + * @param[in] avpkt The input AVPacket containing the input buffer. + * At least avpkt->data and avpkt->size should be set. Some + * decoders might also require additional fields to be set. + * @return A negative error code is returned if an error occurred during + * decoding, otherwise the number of bytes consumed from the input + * AVPacket is returned. + * +* @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). + */ +attribute_deprecated +int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, const AVPacket *avpkt); + +/** + * Decode the video frame of size avpkt->size from avpkt->data into picture. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. + * + * @warning The input buffer must be AV_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer buf should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @note Codecs which have the AV_CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] picture The AVFrame in which the decoded video frame will be stored. + * Use av_frame_alloc() to get an AVFrame. The codec will + * allocate memory for the actual bitmap by calling the + * AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing or flushing the + * decoder. The caller may not write to it. + * + * @param[in] avpkt The input AVPacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields like + * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least + * fields possible. + * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame could be decompressed. + * + * @deprecated Use avcodec_send_packet() and avcodec_receive_frame(). + */ +attribute_deprecated +int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expect to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input + * and output. This means that for some packets they will not immediately + * produce decoded output and need to be flushed at the end of decoding to get + * all the decoded data. Flushing is done by calling this function with packets + * with avpkt->data set to NULL and avpkt->size set to 0 until it stops + * returning subtitles. It is safe to flush even those decoders that are not + * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx the codec context + * @param[out] sub The Preallocated AVSubtitle in which the decoded subtitle will be stored, + * must be freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * Supply raw packet data as input to a decoder. + * + * Internally, this call will copy relevant AVCodecContext fields, which can + * influence decoding per-packet, and apply them when the packet is actually + * decoded. (For example AVCodecContext.skip_frame, which might direct the + * decoder to drop the frame contained by the packet sent with this function.) + * + * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @warning Do not mix this API with the legacy API (like avcodec_decode_video2()) + * on the same AVCodecContext. It will return unexpected results now + * or in future libavcodec versions. + * + * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() + * before packets may be fed to the decoder. + * + * @param avctx codec context + * @param[in] avpkt The input AVPacket. Usually, this will be a single video + * frame, or several complete audio frames. + * Ownership of the packet remains with the caller, and the + * decoder will not write to the packet. The decoder may create + * a reference to the packet data (or copy it if the packet is + * not reference-counted). + * Unlike with older APIs, the packet is always fully consumed, + * and if it contains multiple frames (e.g. some audio codecs), + * will require you to call avcodec_receive_frame() multiple + * times afterwards before you can send a new packet. + * It can be NULL (or an AVPacket with data set to NULL and + * size set to 0); in this case, it is considered a flush + * packet, which signals the end of the stream. Sending the + * first flush packet will return success. Subsequent ones are + * unnecessary and will return AVERROR_EOF. If the decoder + * still has frames buffered, it will return them after sending + * a flush packet. + * + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_frame() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the decoder has been flushed, and no new packets can + * be sent to it (also returned if more than 1 flush + * packet is sent) + * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); + +/** + * Return decoded output data from a decoder. + * + * @param avctx codec context + * @param frame This will be set to a reference-counted video or audio + * frame (depending on the decoder type) allocated by the + * decoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * + * @return + * 0: success, a frame was returned + * AVERROR(EAGAIN): output is not available in this state - user must try + * to send new input + * AVERROR_EOF: the decoder has been fully flushed, and there will be + * no more output frames + * AVERROR(EINVAL): codec not opened, or it is an encoder + * AVERROR_INPUT_CHANGED: current decoded frame has changed parameters + * with respect to first decoded frame. Applicable + * when flag AV_CODEC_FLAG_DROPCHANGED is set. + * other negative values: legitimate decoding errors + */ +int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet() + * to retrieve buffered output packets. + * + * @param avctx codec context + * @param[in] frame AVFrame containing the raw audio or video frame to be encoded. + * Ownership of the frame remains with the caller, and the + * encoder will not write to the frame. The encoder may create + * a reference to the frame data (or copy it if the frame is + * not reference-counted). + * It can be NULL, in which case it is considered a flush + * packet. This signals the end of the stream. If the encoder + * still has packets buffered, it will return them after this + * call. Once flushing mode has been entered, additional flush + * packets are ignored, and sending frames will return + * AVERROR_EOF. + * + * For audio: + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): input is not accepted in the current state - user + * must read output with avcodec_receive_packet() (once + * all output is read, the packet should be resent, and + * the call will not fail with EAGAIN). + * AVERROR_EOF: the encoder has been flushed, and no new frames can + * be sent to it + * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a + * decoder, or requires flush + * AVERROR(ENOMEM): failed to add packet to internal queue, or similar + * other errors: legitimate decoding errors + */ +int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); + +/** + * Read encoded data from the encoder. + * + * @param avctx codec context + * @param avpkt This will be set to a reference-counted packet allocated by the + * encoder. Note that the function will always call + * av_frame_unref(frame) before doing anything else. + * @return 0 on success, otherwise negative error code: + * AVERROR(EAGAIN): output is not available in the current state - user + * must try to send input + * AVERROR_EOF: the encoder has been fully flushed, and there will be + * no more output packets + * AVERROR(EINVAL): codec not opened, or it is an encoder + * other errors: legitimate decoding errors + */ +int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); + +/** + * Create and return a AVHWFramesContext with values adequate for hardware + * decoding. This is meant to get called from the get_format callback, and is + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. + * This API is for decoding with certain hardware acceleration modes/APIs only. + * + * The returned AVHWFramesContext is not initialized. The caller must do this + * with av_hwframe_ctx_init(). + * + * Calling this function is not a requirement, but makes it simpler to avoid + * codec or hardware API specific details when manually allocating frames. + * + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes + * it unnecessary to call this function or having to care about + * AVHWFramesContext initialization at all. + * + * There are a number of requirements for calling this function: + * + * - It must be called from get_format with the same avctx parameter that was + * passed to get_format. Calling it outside of get_format is not allowed, and + * can trigger undefined behavior. + * - The function is not always supported (see description of return values). + * Even if this function returns successfully, hwaccel initialization could + * fail later. (The degree to which implementations check whether the stream + * is actually supported varies. Some do this check only after the user's + * get_format callback returns.) + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the + * user decides to use a AVHWFramesContext prepared with this API function, + * the user must return the same hw_pix_fmt from get_format. + * - The device_ref passed to this function must support the given hw_pix_fmt. + * - After calling this API function, it is the user's responsibility to + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done + * before returning from get_format (this is implied by the normal + * AVCodecContext.hw_frames_ctx API rules). + * - The AVHWFramesContext parameters may change every time time get_format is + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So + * you are inherently required to go through this process again on every + * get_format call. + * - It is perfectly possible to call this function without actually using + * the resulting AVHWFramesContext. One use-case might be trying to reuse a + * previously initialized AVHWFramesContext, and calling this API function + * only to test whether the required frame parameters have changed. + * - Fields that use dynamically allocated values of any kind must not be set + * by the user unless setting them is explicitly allowed by the documentation. + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, + * the new free callback must call the potentially set previous free callback. + * This API call may set any dynamically allocated fields, including the free + * callback. + * + * The function will set at least the following fields on AVHWFramesContext + * (potentially more, depending on hwaccel API): + * + * - All fields set by av_hwframe_ctx_alloc(). + * - Set the format field to hw_pix_fmt. + * - Set the sw_format field to the most suited and most versatile format. (An + * implication is that this will prefer generic formats over opaque formats + * with arbitrary restrictions, if possible.) + * - Set the width/height fields to the coded frame size, rounded up to the + * API-specific minimum alignment. + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size + * field to the number of maximum reference surfaces possible with the codec, + * plus 1 surface for the user to work (meaning the user can safely reference + * at most 1 decoded surface at a time), plus additional buffering introduced + * by frame threading. If the hwaccel does not require pre-allocation, the + * field is left to 0, and the decoder will allocate new surfaces on demand + * during decoding. + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying + * hardware API. + * + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but + * with basic frame parameters set. + * + * The function is stateless, and does not change the AVCodecContext or the + * device_ref AVHWDeviceContext. + * + * @param avctx The context which is currently calling get_format, and which + * implicitly contains all state needed for filling the returned + * AVHWFramesContext properly. + * @param device_ref A reference to the AVHWDeviceContext describing the device + * which will be used by the hardware decoder. + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. + * @param out_frames_ref On success, set to a reference to an _uninitialized_ + * AVHWFramesContext, created from the given device_ref. + * Fields will be set to values required for decoding. + * Not changed if an error is returned. + * @return zero on success, a negative value on error. The following error codes + * have special semantics: + * AVERROR(ENOENT): the decoder does not support this functionality. Setup + * is always manual, or it is a decoder which does not + * support setting AVCodecContext.hw_frames_ctx at all, + * or it is a software format. + * AVERROR(EINVAL): it is known that hardware decoding is not supported for + * this configuration, or the device_ref is not supported + * for the hwaccel referenced by hw_pix_fmt. + */ +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, + AVBufferRef *device_ref, + enum AVPixelFormat hw_pix_fmt, + AVBufferRef **out_frames_ref); + + + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +enum AVPictureStructure { + AV_PICTURE_STRUCTURE_UNKNOWN, //< unknown + AV_PICTURE_STRUCTURE_TOP_FIELD, //< coded as top field + AV_PICTURE_STRUCTURE_BOTTOM_FIELD, //< coded as bottom field + AV_PICTURE_STRUCTURE_FRAME, //< coded as frame +}; + +typedef struct AVCodecParserContext { + void *priv_data; + struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + +#if FF_API_CONVERGENCE_DURATION + /** + * @deprecated unused + */ + attribute_deprecated + int64_t convergence_duration; +#endif + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; + + enum AVFieldOrder field_order; + + /** + * Indicate whether a picture is coded as a frame, top field or bottom field. + * + * For example, H.264 field_pic_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag + * equal to 1 and bottom_field_flag equal to 0 corresponds to + * AV_PICTURE_STRUCTURE_TOP_FIELD. + */ + enum AVPictureStructure picture_structure; + + /** + * Picture number incremented in presentation or output order. + * This field may be reinitialized at the first picture of a new sequence. + * + * For example, this corresponds to H.264 PicOrderCnt. + */ + int output_picture_number; + + /** + * Dimensions of the decoded video intended for presentation. + */ + int width; + int height; + + /** + * Dimensions of the coded video. + */ + int coded_width; + int coded_height; + + /** + * The format of the coded data, corresponds to enum AVPixelFormat for video + * and for enum AVSampleFormat for audio. + * + * Note that a decoder can have considerable freedom in how exactly it + * decodes the data, so the format reported here might be different from the + * one returned by a decoder. + */ + int format; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[5]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + /* This callback never returns an error, a negative value means that + * the frame start was in a previous packet. */ + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); + struct AVCodecParser *next; +} AVCodecParser; + +/** + * Iterate over all registered codec parsers. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec parser or NULL when the iteration is + * finished + */ +const AVCodecParser *av_parser_iterate(void **opaque); + +attribute_deprecated +AVCodecParser *av_parser_next(const AVCodecParser *c); + +attribute_deprecated +void av_register_codec_parser(AVCodecParser *parser); +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size buffer size in bytes without the padding. I.e. the full buffer + size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. + To signal EOF, this should be 0 (so that the last frame + can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +/** + * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed + * @deprecated use AVBitStreamFilter + */ +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); + +/** + * Encode a frame of audio. + * + * Takes input samples from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay, split, and combine input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. If avpkt->data and + * avpkt->size are set, avpkt->destruct must also be set. All + * other AVPacket fields will be reset by the encoder using + * av_init_packet(). If avpkt->data is NULL, the encoder will + * allocate it. The encoder will set avpkt->size to the size + * of the output packet. + * + * If this function fails or produces no output, avpkt will be + * freed using av_packet_unref(). + * @param[in] frame AVFrame containing the raw audio data to be encoded. + * May be NULL when flushing an encoder that has the + * AV_CODEC_CAP_DELAY capability set. + * If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead + */ +attribute_deprecated +int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +/** + * Encode a frame of video. + * + * Takes input raw video data from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay and reorder input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. All other AVPacket fields + * will be reset by the encoder using av_init_packet(). If + * avpkt->data is NULL, the encoder will allocate it. + * The encoder will set avpkt->size to the size of the + * output packet. The returned data (if any) belongs to the + * caller, he is responsible for freeing it. + * + * If this function fails or produces no output, avpkt will be + * freed using av_packet_unref(). + * @param[in] frame AVFrame containing the raw video data to be encoded. + * May be NULL when flushing an encoder that has the + * AV_CODEC_CAP_DELAY capability set. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + * + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead + */ +attribute_deprecated +int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +#if FF_API_AVPICTURE +/** + * @addtogroup lavc_picture + * @{ + */ + +/** + * @deprecated unused + */ +attribute_deprecated +int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated unused + */ +attribute_deprecated +void avpicture_free(AVPicture *picture); + +/** + * @deprecated use av_image_fill_arrays() instead. + */ +attribute_deprecated +int avpicture_fill(AVPicture *picture, const uint8_t *ptr, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated use av_image_copy_to_buffer() instead. + */ +attribute_deprecated +int avpicture_layout(const AVPicture *src, enum AVPixelFormat pix_fmt, + int width, int height, + unsigned char *dest, int dest_size); + +/** + * @deprecated use av_image_get_buffer_size() instead. + */ +attribute_deprecated +int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated av_image_copy() instead. + */ +attribute_deprecated +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * @deprecated unused + */ +attribute_deprecated +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int top_band, int left_band); + +/** + * @deprecated unused + */ +attribute_deprecated +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt, + int padtop, int padbottom, int padleft, int padright, int *color); + +/** + * @} + */ +#endif + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +#if FF_API_GETCHROMA +/** + * @deprecated Use av_pix_fmt_get_chroma_sub_sample + */ + +attribute_deprecated +void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift); +#endif + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +/** + * @deprecated see av_get_pix_fmt_loss() + */ +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +/** + * @deprecated see av_find_best_pix_fmt_of_2() + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +attribute_deprecated +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +#if FF_API_TAG_STRING +/** + * Put a string representing the codec tag codec_tag in buf. + * + * @param buf buffer to place codec tag in + * @param buf_size size in bytes of buf + * @param codec_tag codec tag to assign + * @return the length of the string that would have been generated if + * enough space had been available, excluding the trailing null + * + * @deprecated see av_fourcc_make_string() and av_fourcc2str(). + */ +attribute_deprecated +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag); +#endif + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +/** + * Return a name for the specified profile, if available. + * + * @param codec_id the ID of the codec to which the requested profile belongs + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + * + * @note unlike av_get_profile_name(), which searches a list of profiles + * supported by a specific decoder or encoder implementation, this + * function searches the list of profiles from the AVCodecDescriptor + */ +const char *avcodec_profile_name(enum AVCodecID codec_id, int profile); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Reset the internal decoder state / flush internal buffers. Should be called + * e.g. when seeking or when switching to a different stream. + * + * @note when refcounted frames are not used (i.e. avctx->refcounted_frames is 0), + * this invalidates the frames previously returned from the decoder. When + * refcounted frames are used, the decoder just releases any references it might + * keep internally, but the caller's reference remains valid. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + +/** + * This function is the same as av_get_audio_frame_duration(), except it works + * with AVCodecParameters instead of an AVCodecContext. + */ +int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); + +#if FF_API_OLD_BSF +typedef struct AVBitStreamFilterContext { + void *priv_data; + const struct AVBitStreamFilter *filter; + AVCodecParserContext *parser; + struct AVBitStreamFilterContext *next; + /** + * Internal default arguments, used if NULL is passed to av_bitstream_filter_filter(). + * Not for access by library users. + */ + char *args; +} AVBitStreamFilterContext; +#endif + +typedef struct AVBSFInternal AVBSFInternal; + +/** + * The bitstream filter state. + * + * This struct must be allocated with av_bsf_alloc() and freed with + * av_bsf_free(). + * + * The fields in the struct will only be changed (by the caller or by the + * filter) as described in their documentation, and are to be considered + * immutable otherwise. + */ +typedef struct AVBSFContext { + /** + * A class for logging and AVOptions + */ + const AVClass *av_class; + + /** + * The bitstream filter this context is an instance of. + */ + const struct AVBitStreamFilter *filter; + + /** + * Opaque libavcodec internal data. Must not be touched by the caller in any + * way. + */ + AVBSFInternal *internal; + + /** + * Opaque filter-specific private data. If filter->priv_class is non-NULL, + * this is an AVOptions-enabled struct. + */ + void *priv_data; + + /** + * Parameters of the input stream. This field is allocated in + * av_bsf_alloc(), it needs to be filled by the caller before + * av_bsf_init(). + */ + AVCodecParameters *par_in; + + /** + * Parameters of the output stream. This field is allocated in + * av_bsf_alloc(), it is set by the filter in av_bsf_init(). + */ + AVCodecParameters *par_out; + + /** + * The timebase used for the timestamps of the input packets. Set by the + * caller before av_bsf_init(). + */ + AVRational time_base_in; + + /** + * The timebase used for the timestamps of the output packets. Set by the + * filter in av_bsf_init(). + */ + AVRational time_base_out; +} AVBSFContext; + +typedef struct AVBitStreamFilter { + const char *name; + + /** + * A list of codec ids supported by the filter, terminated by + * AV_CODEC_ID_NONE. + * May be NULL, in that case the bitstream filter works with any codec id. + */ + const enum AVCodecID *codec_ids; + + /** + * A class for the private data, used to declare bitstream filter private + * AVOptions. This field is NULL for bitstream filters that do not declare + * any options. + * + * If this field is non-NULL, the first member of the filter private data + * must be a pointer to AVClass, which will be set by libavcodec generic + * code to this class. + */ + const AVClass *priv_class; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + int priv_data_size; + int (*init)(AVBSFContext *ctx); + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); + void (*close)(AVBSFContext *ctx); + void (*flush)(AVBSFContext *ctx); +} AVBitStreamFilter; + +#if FF_API_OLD_BSF +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use the new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +void av_register_bitstream_filter(AVBitStreamFilter *bsf); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_get_by_name(), av_bsf_alloc(), and av_bsf_init() + * from the new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_send_packet() and av_bsf_receive_packet() from the + * new bitstream filtering API (using AVBSFContext). + */ +attribute_deprecated +int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_free() from the new bitstream filtering API (using + * AVBSFContext). + */ +attribute_deprecated +void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); +/** + * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) + * is deprecated. Use av_bsf_iterate() from the new bitstream filtering API (using + * AVBSFContext). + */ +attribute_deprecated +const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); +#endif + +/** + * @return a bitstream filter with the specified name or NULL if no such + * bitstream filter exists. + */ +const AVBitStreamFilter *av_bsf_get_by_name(const char *name); + +/** + * Iterate over all registered bitstream filters. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered bitstream filter or NULL when the iteration is + * finished + */ +const AVBitStreamFilter *av_bsf_iterate(void **opaque); +#if FF_API_NEXT +attribute_deprecated +const AVBitStreamFilter *av_bsf_next(void **opaque); +#endif + +/** + * Allocate a context for a given bitstream filter. The caller must fill in the + * context parameters as described in the documentation and then call + * av_bsf_init() before sending any data to the filter. + * + * @param filter the filter for which to allocate an instance. + * @param ctx a pointer into which the pointer to the newly-allocated context + * will be written. It must be freed with av_bsf_free() after the + * filtering is done. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); + +/** + * Prepare the filter for use, after all the parameters and options have been + * set. + */ +int av_bsf_init(AVBSFContext *ctx); + +/** + * Submit a packet for filtering. + * + * After sending each packet, the filter must be completely drained by calling + * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or + * AVERROR_EOF. + * + * @param pkt the packet to filter. The bitstream filter will take ownership of + * the packet and reset the contents of pkt. pkt is not touched if an error occurs. + * This parameter may be NULL, which signals the end of the stream (i.e. no more + * packets will be sent). That will cause the filter to output any packets it + * may have buffered internally. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Retrieve a filtered packet. + * + * @param[out] pkt this struct will be filled with the contents of the filtered + * packet. It is owned by the caller and must be freed using + * av_packet_unref() when it is no longer needed. + * This parameter should be "clean" (i.e. freshly allocated + * with av_packet_alloc() or unreffed with av_packet_unref()) + * when this function is called. If this function returns + * successfully, the contents of pkt will be completely + * overwritten by the returned data. On failure, pkt is not + * touched. + * + * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the + * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there + * will be no further output from the filter. Another negative AVERROR value if + * an error occurs. + * + * @note one input packet may result in several output packets, so after sending + * a packet with av_bsf_send_packet(), this function needs to be called + * repeatedly until it stops returning 0. It is also possible for a filter to + * output fewer packets than were sent to it, so this function may return + * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. + */ +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Reset the internal bitstream filter state / flush internal buffers. + */ +void av_bsf_flush(AVBSFContext *ctx); + +/** + * Free a bitstream filter context and everything associated with it; write NULL + * into the supplied pointer. + */ +void av_bsf_free(AVBSFContext **ctx); + +/** + * Get the AVClass for AVBSFContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_bsf_get_class(void); + +/** + * Structure for chain/list of bitstream filters. + * Empty list can be allocated by av_bsf_list_alloc(). + */ +typedef struct AVBSFList AVBSFList; + +/** + * Allocate empty list of bitstream filters. + * The list must be later freed by av_bsf_list_free() + * or finalized by av_bsf_list_finalize(). + * + * @return Pointer to @ref AVBSFList on success, NULL in case of failure + */ +AVBSFList *av_bsf_list_alloc(void); + +/** + * Free list of bitstream filters. + * + * @param lst Pointer to pointer returned by av_bsf_list_alloc() + */ +void av_bsf_list_free(AVBSFList **lst); + +/** + * Append bitstream filter to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf Filter context to be appended + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf); + +/** + * Construct new bitstream filter context given it's name and options + * and append it to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf_name Name of the bitstream filter + * @param options Options for the bitstream filter, can be set to NULL + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options); +/** + * Finalize list of bitstream filters. + * + * This function will transform @ref AVBSFList to single @ref AVBSFContext, + * so the whole chain of bitstream filters can be treated as single filter + * freshly allocated by av_bsf_alloc(). + * If the call is successful, @ref AVBSFList structure is freed and lst + * will be set to NULL. In case of failure, caller is responsible for + * freeing the structure by av_bsf_list_free() + * + * @param lst Filter list structure to be transformed + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf); + +/** + * Parse string describing list of bitstream filters and create single + * @ref AVBSFContext describing the whole chain of bitstream filters. + * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly + * allocated by av_bsf_alloc(). + * + * @param str String describing chain of bitstream filters in format + * `bsf1[=opt1=val1:opt2=val2][,bsf2]` + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf); + +/** + * Get null/pass-through bitstream filter. + * + * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter + * + * @return + */ +int av_bsf_get_null_filter(AVBSFContext **bsf); + +/* memory */ + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#if FF_API_USER_VISIBLE_AVHWACCEL +/** + * Register the hardware accelerator hwaccel. + * + * @deprecated This function doesn't do anything. + */ +attribute_deprecated +void av_register_hwaccel(AVHWAccel *hwaccel); + +/** + * If hwaccel is NULL, returns the first registered hardware accelerator, + * if hwaccel is non-NULL, returns the next registered hardware accelerator + * after hwaccel, or NULL if hwaccel is the last one. + * + * @deprecated AVHWaccel structures contain no user-serviceable parts, so + * this function should not be used. + */ +attribute_deprecated +AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel); +#endif + +#if FF_API_LOCKMGR +/** + * Lock operation used by lockmgr + * + * @deprecated Deprecated together with av_lockmgr_register(). + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. The "mutex" argument to the function points + * to a (void *) where the lockmgr should store/get a pointer to a user + * allocated mutex. It is NULL upon AV_LOCK_CREATE and equal to the + * value left by the last call for all other ops. If the lock manager is + * unable to perform the op then it should leave the mutex in the same + * state as when it was called and return a non-zero value. However, + * when called with AV_LOCK_DESTROY the mutex will always be assumed to + * have been successfully destroyed. If av_lockmgr_register succeeds + * it will return a non-negative value, if it fails it will return a + * negative value and destroy all mutex and unregister all callbacks. + * av_lockmgr_register is not thread-safe, it must be called from a + * single thread before any calls which make use of locking are used. + * + * @param cb User defined callback. av_lockmgr_register invokes calls + * to this callback and the previously registered callback. + * The callback will be used to create more than one mutex + * each of which must be backed by its own underlying locking + * mechanism (i.e. do not use a single static object to + * implement your lock manager). If cb is set to NULL the + * lockmgr will be unregistered. + * + * @deprecated This function does nothing, and always returns 0. Be sure to + * build with thread support to get basic thread safety. + */ +attribute_deprecated +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); +#endif + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * Allocate a CPB properties structure and initialize its fields to default + * values. + * + * @param size if non-NULL, the size of the allocated struct will be written + * here. This is useful for embedding it in side data. + * + * @return the newly allocated struct or NULL on failure + */ +AVCPBProperties *av_cpb_properties_alloc(size_t *size); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/avdct.h b/thirdparty/user_include/ffmpeg/libavcodec/avdct.h new file mode 100755 index 0000000000000000000000000000000000000000..272422e44c91c8f5feae396900f79e38146abde3 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/avdct.h @@ -0,0 +1,84 @@ +/* + * 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 + */ + +#ifndef AVCODEC_AVDCT_H +#define AVCODEC_AVDCT_H + +#include "libavutil/opt.h" + +/** + * AVDCT context. + * @note function pointers can be NULL if the specific features have been + * disabled at build time. + */ +typedef struct AVDCT { + const AVClass *av_class; + + void (*idct)(int16_t *block /* align 16 */); + + /** + * IDCT input permutation. + * Several optimized IDCTs need a permutated input (relative to the + * normal order of the reference IDCT). + * This permutation must be performed before the idct_put/add. + * Note, normally this can be merged with the zigzag/alternate scan
+ * An example to avoid confusion: + * - (->decode coeffs -> zigzag reorder -> dequant -> reference IDCT -> ...) + * - (x -> reference DCT -> reference IDCT -> x) + * - (x -> reference DCT -> simple_mmx_perm = idct_permutation + * -> simple_idct_mmx -> x) + * - (-> decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant + * -> simple_idct_mmx -> ...) + */ + uint8_t idct_permutation[64]; + + void (*fdct)(int16_t *block /* align 16 */); + + + /** + * DCT algorithm. + * must use AVOptions to set this field. + */ + int dct_algo; + + /** + * IDCT algorithm. + * must use AVOptions to set this field. + */ + int idct_algo; + + void (*get_pixels)(int16_t *block /* align 16 */, + const uint8_t *pixels /* align 8 */, + ptrdiff_t line_size); + + int bits_per_sample; +} AVDCT; + +/** + * Allocates a AVDCT context. + * This needs to be initialized with avcodec_dct_init() after optionally + * configuring it with AVOptions. + * + * To free it use av_free() + */ +AVDCT *avcodec_dct_alloc(void); +int avcodec_dct_init(AVDCT *); + +const AVClass *avcodec_dct_get_class(void); + +#endif /* AVCODEC_AVDCT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/avfft.h b/thirdparty/user_include/ffmpeg/libavcodec/avfft.h new file mode 100755 index 0000000000000000000000000000000000000000..0c0f9b8d8dae13c14a8cd91a1c4234b07821e916 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/avfft.h @@ -0,0 +1,118 @@ +/* + * 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 + */ + +#ifndef AVCODEC_AVFFT_H +#define AVCODEC_AVFFT_H + +/** + * @file + * @ingroup lavc_fft + * FFT functions + */ + +/** + * @defgroup lavc_fft FFT functions + * @ingroup lavc_misc + * + * @{ + */ + +typedef float FFTSample; + +typedef struct FFTComplex { + FFTSample re, im; +} FFTComplex; + +typedef struct FFTContext FFTContext; + +/** + * Set up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +FFTContext *av_fft_init(int nbits, int inverse); + +/** + * Do the permutation needed BEFORE calling ff_fft_calc(). + */ +void av_fft_permute(FFTContext *s, FFTComplex *z); + +/** + * Do a complex FFT with the parameters defined in av_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ +void av_fft_calc(FFTContext *s, FFTComplex *z); + +void av_fft_end(FFTContext *s); + +FFTContext *av_mdct_init(int nbits, int inverse, double scale); +void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_end(FFTContext *s); + +/* Real Discrete Fourier Transform */ + +enum RDFTransformType { + DFT_R2C, + IDFT_C2R, + IDFT_R2C, + DFT_C2R, +}; + +typedef struct RDFTContext RDFTContext; + +/** + * Set up a real FFT. + * @param nbits log2 of the length of the input array + * @param trans the type of transform + */ +RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans); +void av_rdft_calc(RDFTContext *s, FFTSample *data); +void av_rdft_end(RDFTContext *s); + +/* Discrete Cosine Transform */ + +typedef struct DCTContext DCTContext; + +enum DCTTransformType { + DCT_II = 0, + DCT_III, + DCT_I, + DST_I, +}; + +/** + * Set up DCT. + * + * @param nbits size of the input array: + * (1 << nbits) for DCT-II, DCT-III and DST-I + * (1 << nbits) + 1 for DCT-I + * @param type the type of transform + * + * @note the first element of the input of DST-I is ignored + */ +DCTContext *av_dct_init(int nbits, enum DCTTransformType type); +void av_dct_calc(DCTContext *s, FFTSample *data); +void av_dct_end (DCTContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVFFT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/d3d11va.h b/thirdparty/user_include/ffmpeg/libavcodec/d3d11va.h new file mode 100755 index 0000000000000000000000000000000000000000..6816b6c1e68494bc6d6f0b14cbd232bbcc714a05 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/d3d11va.h @@ -0,0 +1,112 @@ +/* + * Direct3D11 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * copyright (c) 2015 Steve Lhomme + * + * 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 + */ + +#ifndef AVCODEC_D3D11VA_H +#define AVCODEC_D3D11VA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_d3d11va + * Public libavcodec D3D11VA header. + */ + +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + +#include +#include + +/** + * @defgroup lavc_codec_hwaccel_d3d11va Direct3D11 + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards +#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface + +/** + * This structure is used to provides the necessary configurations and data + * to the Direct3D11 FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + * + * Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext. + */ +typedef struct AVD3D11VAContext { + /** + * D3D11 decoder object + */ + ID3D11VideoDecoder *decoder; + + /** + * D3D11 VideoContext + */ + ID3D11VideoContext *video_context; + + /** + * D3D11 configuration used to create the decoder + */ + D3D11_VIDEO_DECODER_CONFIG *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + ID3D11VideoDecoderOutputView **surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the FFmpeg AVHWAccel implementation + */ + unsigned report_id; + + /** + * Mutex to access video_context + */ + HANDLE context_mutex; +} AVD3D11VAContext; + +/** + * Allocate an AVD3D11VAContext. + * + * @return Newly-allocated AVD3D11VAContext or NULL on failure. + */ +AVD3D11VAContext *av_d3d11va_alloc_context(void); + +/** + * @} + */ + +#endif /* AVCODEC_D3D11VA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/dirac.h b/thirdparty/user_include/ffmpeg/libavcodec/dirac.h new file mode 100755 index 0000000000000000000000000000000000000000..e6d9d346d9cc13c23092f5e1f4501d20157e1def --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/dirac.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * Copyright (C) 2011 Jordi Ortiz + * + * 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 + */ + +#ifndef AVCODEC_DIRAC_H +#define AVCODEC_DIRAC_H + +/** + * @file + * Interface to Dirac Decoder/Encoder + * @author Marco Gerards + * @author David Conrad + * @author Jordi Ortiz + */ + +#include "avcodec.h" + +/** + * The spec limits the number of wavelet decompositions to 4 for both + * level 1 (VC-2) and 128 (long-gop default). + * 5 decompositions is the maximum before >16-bit buffers are needed. + * Schroedinger allows this for DD 9,7 and 13,7 wavelets only, limiting + * the others to 4 decompositions (or 3 for the fidelity filter). + * + * We use this instead of MAX_DECOMPOSITIONS to save some memory. + */ +#define MAX_DWT_LEVELS 5 + +/** + * Parse code values: + * + * Dirac Specification -> + * 9.6.1 Table 9.1 + * + * VC-2 Specification -> + * 10.4.1 Table 10.1 + */ + +enum DiracParseCodes { + DIRAC_PCODE_SEQ_HEADER = 0x00, + DIRAC_PCODE_END_SEQ = 0x10, + DIRAC_PCODE_AUX = 0x20, + DIRAC_PCODE_PAD = 0x30, + DIRAC_PCODE_PICTURE_CODED = 0x08, + DIRAC_PCODE_PICTURE_RAW = 0x48, + DIRAC_PCODE_PICTURE_LOW_DEL = 0xC8, + DIRAC_PCODE_PICTURE_HQ = 0xE8, + DIRAC_PCODE_INTER_NOREF_CO1 = 0x0A, + DIRAC_PCODE_INTER_NOREF_CO2 = 0x09, + DIRAC_PCODE_INTER_REF_CO1 = 0x0D, + DIRAC_PCODE_INTER_REF_CO2 = 0x0E, + DIRAC_PCODE_INTRA_REF_CO = 0x0C, + DIRAC_PCODE_INTRA_REF_RAW = 0x4C, + DIRAC_PCODE_INTRA_REF_PICT = 0xCC, + DIRAC_PCODE_MAGIC = 0x42424344, +}; + +typedef struct DiracVersionInfo { + int major; + int minor; +} DiracVersionInfo; + +typedef struct AVDiracSeqHeader { + unsigned width; + unsigned height; + uint8_t chroma_format; ///< 0: 444 1: 422 2: 420 + + uint8_t interlaced; + uint8_t top_field_first; + + uint8_t frame_rate_index; ///< index into dirac_frame_rate[] + uint8_t aspect_ratio_index; ///< index into dirac_aspect_ratio[] + + uint16_t clean_width; + uint16_t clean_height; + uint16_t clean_left_offset; + uint16_t clean_right_offset; + + uint8_t pixel_range_index; ///< index into dirac_pixel_range_presets[] + uint8_t color_spec_index; ///< index into dirac_color_spec_presets[] + + int profile; + int level; + + AVRational framerate; + AVRational sample_aspect_ratio; + + enum AVPixelFormat pix_fmt; + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; + + DiracVersionInfo version; + int bit_depth; +} AVDiracSeqHeader; + +/** + * Parse a Dirac sequence header. + * + * @param dsh this function will allocate and fill an AVDiracSeqHeader struct + * and write it into this pointer. The caller must free it with + * av_free(). + * @param buf the data buffer + * @param buf_size the size of the data buffer in bytes + * @param log_ctx if non-NULL, this function will log errors here + * @return 0 on success, a negative AVERROR code on failure + */ +int av_dirac_parse_sequence_header(AVDiracSeqHeader **dsh, + const uint8_t *buf, size_t buf_size, + void *log_ctx); + +#endif /* AVCODEC_DIRAC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/dv_profile.h b/thirdparty/user_include/ffmpeg/libavcodec/dv_profile.h new file mode 100755 index 0000000000000000000000000000000000000000..9380a66f0705024c7f83d4ee8cc3d24d7c69df2a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/dv_profile.h @@ -0,0 +1,83 @@ +/* + * 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 + */ + +#ifndef AVCODEC_DV_PROFILE_H +#define AVCODEC_DV_PROFILE_H + +#include + +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "avcodec.h" + +/* minimum number of bytes to read from a DV stream in order to + * determine the profile */ +#define DV_PROFILE_BYTES (6 * 80) /* 6 DIF blocks */ + + +/* + * AVDVProfile is used to express the differences between various + * DV flavors. For now it's primarily used for differentiating + * 525/60 and 625/50, but the plans are to use it for various + * DV specs as well (e.g. SMPTE314M vs. IEC 61834). + */ +typedef struct AVDVProfile { + int dsf; /* value of the dsf in the DV header */ + int video_stype; /* stype for VAUX source pack */ + int frame_size; /* total size of one frame in bytes */ + int difseg_size; /* number of DIF segments per DIF channel */ + int n_difchan; /* number of DIF channels per frame */ + AVRational time_base; /* 1/framerate */ + int ltc_divisor; /* FPS from the LTS standpoint */ + int height; /* picture height in pixels */ + int width; /* picture width in pixels */ + AVRational sar[2]; /* sample aspect ratios for 4:3 and 16:9 */ + enum AVPixelFormat pix_fmt; /* picture pixel format */ + int bpm; /* blocks per macroblock */ + const uint8_t *block_sizes; /* AC block sizes, in bits */ + int audio_stride; /* size of audio_shuffle table */ + int audio_min_samples[3]; /* min amount of audio samples */ + /* for 48kHz, 44.1kHz and 32kHz */ + int audio_samples_dist[5]; /* how many samples are supposed to be */ + /* in each frame in a 5 frames window */ + const uint8_t (*audio_shuffle)[9]; /* PCM shuffling table */ +} AVDVProfile; + +/** + * Get a DV profile for the provided compressed frame. + * + * @param sys the profile used for the previous frame, may be NULL + * @param frame the compressed data buffer + * @param buf_size size of the buffer in bytes + * @return the DV profile for the supplied data or NULL on failure + */ +const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys, + const uint8_t *frame, unsigned buf_size); + +/** + * Get a DV profile for the provided stream parameters. + */ +const AVDVProfile *av_dv_codec_profile(int width, int height, enum AVPixelFormat pix_fmt); + +/** + * Get a DV profile for the provided stream parameters. + * The frame rate is used as a best-effort parameter. + */ +const AVDVProfile *av_dv_codec_profile2(int width, int height, enum AVPixelFormat pix_fmt, AVRational frame_rate); + +#endif /* AVCODEC_DV_PROFILE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/dxva2.h b/thirdparty/user_include/ffmpeg/libavcodec/dxva2.h new file mode 100755 index 0000000000000000000000000000000000000000..22c93992f22284c7e2ac92c5bf23faa3df6e6272 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/dxva2.h @@ -0,0 +1,93 @@ +/* + * DXVA2 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * + * 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 + */ + +#ifndef AVCODEC_DXVA2_H +#define AVCODEC_DXVA2_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_dxva2 + * Public libavcodec DXVA2 header. + */ + +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + +#include +#include +#include + +/** + * @defgroup lavc_codec_hwaccel_dxva2 DXVA2 + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards +#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface + +/** + * This structure is used to provides the necessary configurations and data + * to the DXVA2 FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct dxva_context { + /** + * DXVA2 decoder object + */ + IDirectXVideoDecoder *decoder; + + /** + * DXVA2 configuration used to create the decoder + */ + const DXVA2_ConfigPictureDecode *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + LPDIRECT3DSURFACE9 *surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the FFmpeg AVHWAccel implementation + */ + unsigned report_id; +}; + +/** + * @} + */ + +#endif /* AVCODEC_DXVA2_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/jni.h b/thirdparty/user_include/ffmpeg/libavcodec/jni.h new file mode 100755 index 0000000000000000000000000000000000000000..dd99e92611322b5ac590daea689d920b358b272c --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/jni.h @@ -0,0 +1,46 @@ +/* + * JNI public API functions + * + * Copyright (c) 2015-2016 Matthieu Bouron + * + * 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 + */ + +#ifndef AVCODEC_JNI_H +#define AVCODEC_JNI_H + +/* + * Manually set a Java virtual machine which will be used to retrieve the JNI + * environment. Once a Java VM is set it cannot be changed afterwards, meaning + * you can call multiple times av_jni_set_java_vm with the same Java VM pointer + * however it will error out if you try to set a different Java VM. + * + * @param vm Java virtual machine + * @param log_ctx context used for logging, can be NULL + * @return 0 on success, < 0 otherwise + */ +int av_jni_set_java_vm(void *vm, void *log_ctx); + +/* + * Get the Java virtual machine which has been set with av_jni_set_java_vm. + * + * @param vm Java virtual machine + * @return a pointer to the Java virtual machine + */ +void *av_jni_get_java_vm(void *log_ctx); + +#endif /* AVCODEC_JNI_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/mediacodec.h b/thirdparty/user_include/ffmpeg/libavcodec/mediacodec.h new file mode 100755 index 0000000000000000000000000000000000000000..4c8545df03109a80da77976209d187e046a5e801 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/mediacodec.h @@ -0,0 +1,101 @@ +/* + * Android MediaCodec public API + * + * Copyright (c) 2016 Matthieu Bouron + * + * 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 + */ + +#ifndef AVCODEC_MEDIACODEC_H +#define AVCODEC_MEDIACODEC_H + +#include "libavcodec/avcodec.h" + +/** + * This structure holds a reference to a android/view/Surface object that will + * be used as output by the decoder. + * + */ +typedef struct AVMediaCodecContext { + + /** + * android/view/Surface object reference. + */ + void *surface; + +} AVMediaCodecContext; + +/** + * Allocate and initialize a MediaCodec context. + * + * When decoding with MediaCodec is finished, the caller must free the + * MediaCodec context with av_mediacodec_default_free. + * + * @return a pointer to a newly allocated AVMediaCodecContext on success, NULL otherwise + */ +AVMediaCodecContext *av_mediacodec_alloc_context(void); + +/** + * Convenience function that sets up the MediaCodec context. + * + * @param avctx codec context + * @param ctx MediaCodec context to initialize + * @param surface reference to an android/view/Surface + * @return 0 on success, < 0 otherwise + */ +int av_mediacodec_default_init(AVCodecContext *avctx, AVMediaCodecContext *ctx, void *surface); + +/** + * This function must be called to free the MediaCodec context initialized with + * av_mediacodec_default_init(). + * + * @param avctx codec context + */ +void av_mediacodec_default_free(AVCodecContext *avctx); + +/** + * Opaque structure representing a MediaCodec buffer to render. + */ +typedef struct MediaCodecBuffer AVMediaCodecBuffer; + +/** + * Release a MediaCodec buffer and render it to the surface that is associated + * with the decoder. This function should only be called once on a given + * buffer, once released the underlying buffer returns to the codec, thus + * subsequent calls to this function will have no effect. + * + * @param buffer the buffer to render + * @param render 1 to release and render the buffer to the surface or 0 to + * discard the buffer + * @return 0 on success, < 0 otherwise + */ +int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render); + +/** + * Release a MediaCodec buffer and render it at the given time to the surface + * that is associated with the decoder. The timestamp must be within one second + * of the current java/lang/System#nanoTime() (which is implemented using + * CLOCK_MONOTONIC on Android). See the Android MediaCodec documentation + * of android/media/MediaCodec#releaseOutputBuffer(int,long) for more details. + * + * @param buffer the buffer to render + * @param time timestamp in nanoseconds of when to render the buffer + * @return 0 on success, < 0 otherwise + */ +int av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time); + +#endif /* AVCODEC_MEDIACODEC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/qsv.h b/thirdparty/user_include/ffmpeg/libavcodec/qsv.h new file mode 100755 index 0000000000000000000000000000000000000000..b77158ec262920cfee3346de1f0f1cbce9157bfa --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/qsv.h @@ -0,0 +1,107 @@ +/* + * Intel MediaSDK QSV public API + * + * 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 + */ + +#ifndef AVCODEC_QSV_H +#define AVCODEC_QSV_H + +#include + +#include "libavutil/buffer.h" + +/** + * This struct is used for communicating QSV parameters between libavcodec and + * the caller. It is managed by the caller and must be assigned to + * AVCodecContext.hwaccel_context. + * - decoding: hwaccel_context must be set on return from the get_format() + * callback + * - encoding: hwaccel_context must be set before avcodec_open2() + */ +typedef struct AVQSVContext { + /** + * If non-NULL, the session to use for encoding or decoding. + * Otherwise, libavcodec will try to create an internal session. + */ + mfxSession session; + + /** + * The IO pattern to use. + */ + int iopattern; + + /** + * Extra buffers to pass to encoder or decoder initialization. + */ + mfxExtBuffer **ext_buffers; + int nb_ext_buffers; + + /** + * Encoding only. If this field is set to non-zero by the caller, libavcodec + * will create an mfxExtOpaqueSurfaceAlloc extended buffer and pass it to + * the encoder initialization. This only makes sense if iopattern is also + * set to MFX_IOPATTERN_IN_OPAQUE_MEMORY. + * + * The number of allocated opaque surfaces will be the sum of the number + * required by the encoder and the user-provided value nb_opaque_surfaces. + * The array of the opaque surfaces will be exported to the caller through + * the opaque_surfaces field. + */ + int opaque_alloc; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. Before + * calling avcodec_open2(), the caller should set this field to the number + * of extra opaque surfaces to allocate beyond what is required by the + * encoder. + * + * On return from avcodec_open2(), this field will be set by libavcodec to + * the total number of allocated opaque surfaces. + */ + int nb_opaque_surfaces; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. On return + * from avcodec_open2(), this field will be used by libavcodec to export the + * array of the allocated opaque surfaces to the caller, so they can be + * passed to other parts of the pipeline. + * + * The buffer reference exported here is owned and managed by libavcodec, + * the callers should make their own reference with av_buffer_ref() and free + * it with av_buffer_unref() when it is no longer needed. + * + * The buffer data is an nb_opaque_surfaces-sized array of mfxFrameSurface1. + */ + AVBufferRef *opaque_surfaces; + + /** + * Encoding only, and only if opaque_alloc is set to non-zero. On return + * from avcodec_open2(), this field will be set to the surface type used in + * the opaque allocation request. + */ + int opaque_alloc_type; +} AVQSVContext; + +/** + * Allocate a new context. + * + * It must be freed by the caller with av_free(). + */ +AVQSVContext *av_qsv_alloc_context(void); + +#endif /* AVCODEC_QSV_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/vaapi.h b/thirdparty/user_include/ffmpeg/libavcodec/vaapi.h new file mode 100755 index 0000000000000000000000000000000000000000..2cf7da5889ab4760e2da34bf56c1afc59f5ac0b2 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/vaapi.h @@ -0,0 +1,86 @@ +/* + * Video Acceleration API (shared data between FFmpeg and the video player) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 + */ + +#ifndef AVCODEC_VAAPI_H +#define AVCODEC_VAAPI_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vaapi + * Public libavcodec VA API header. + */ + +#include +#include "libavutil/attributes.h" +#include "version.h" + +#if FF_API_STRUCT_VAAPI_CONTEXT + +/** + * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding + * @ingroup lavc_codec_hwaccel + * @{ + */ + +/** + * This structure is used to share data between the FFmpeg library and + * the client video application. + * This shall be zero-allocated and available as + * AVCodecContext.hwaccel_context. All user members can be set once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + * + * Deprecated: use AVCodecContext.hw_frames_ctx instead. + */ +struct attribute_deprecated vaapi_context { + /** + * Window system dependent data + * + * - encoding: unused + * - decoding: Set by user + */ + void *display; + + /** + * Configuration ID + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t config_id; + + /** + * Context ID (video decode pipeline) + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t context_id; +}; + +/* @} */ + +#endif /* FF_API_STRUCT_VAAPI_CONTEXT */ + +#endif /* AVCODEC_VAAPI_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/vdpau.h b/thirdparty/user_include/ffmpeg/libavcodec/vdpau.h new file mode 100755 index 0000000000000000000000000000000000000000..4d9994336911865d839731c6d360102e9eaa27cc --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/vdpau.h @@ -0,0 +1,176 @@ +/* + * The Video Decode and Presentation API for UNIX (VDPAU) is used for + * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1. + * + * Copyright (C) 2008 NVIDIA + * + * 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 + */ + +#ifndef AVCODEC_VDPAU_H +#define AVCODEC_VDPAU_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vdpau + * Public libavcodec VDPAU header. + */ + + +/** + * @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer + * @ingroup lavc_codec_hwaccel + * + * VDPAU hardware acceleration has two modules + * - VDPAU decoding + * - VDPAU presentation + * + * The VDPAU decoding module parses all headers using FFmpeg + * parsing mechanisms and uses VDPAU for the actual decoding. + * + * As per the current implementation, the actual decoding + * and rendering (API calls) are done as part of the VDPAU + * presentation (vo_vdpau.c) module. + * + * @{ + */ + +#include + +#include "libavutil/avconfig.h" +#include "libavutil/attributes.h" + +#include "avcodec.h" +#include "version.h" + +struct AVCodecContext; +struct AVFrame; + +typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *, + const VdpPictureInfo *, uint32_t, + const VdpBitstreamBuffer *); + +/** + * This structure is used to share data between the libavcodec library and + * the client video application. + * The user shall allocate the structure via the av_alloc_vdpau_hwaccel + * function and make it available as + * AVCodecContext.hwaccel_context. Members can be set by the user once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + * + * The size of this structure is not a part of the public ABI and must not + * be used outside of libavcodec. Use av_vdpau_alloc_context() to allocate an + * AVVDPAUContext. + */ +typedef struct AVVDPAUContext { + /** + * VDPAU decoder handle + * + * Set by user. + */ + VdpDecoder decoder; + + /** + * VDPAU decoder render callback + * + * Set by the user. + */ + VdpDecoderRender *render; + + AVVDPAU_Render2 render2; +} AVVDPAUContext; + +/** + * @brief allocation function for AVVDPAUContext + * + * Allows extending the struct without breaking API/ABI + */ +AVVDPAUContext *av_alloc_vdpaucontext(void); + +AVVDPAU_Render2 av_vdpau_hwaccel_get_render2(const AVVDPAUContext *); +void av_vdpau_hwaccel_set_render2(AVVDPAUContext *, AVVDPAU_Render2); + +/** + * Associate a VDPAU device with a codec context for hardware acceleration. + * This function is meant to be called from the get_format() codec callback, + * or earlier. It can also be called after avcodec_flush_buffers() to change + * the underlying VDPAU device mid-stream (e.g. to recover from non-transparent + * display preemption). + * + * @note get_format() must return AV_PIX_FMT_VDPAU if this function completes + * successfully. + * + * @param avctx decoding context whose get_format() callback is invoked + * @param device VDPAU device handle to use for hardware acceleration + * @param get_proc_address VDPAU device driver + * @param flags zero of more OR'd AV_HWACCEL_FLAG_* flags + * + * @return 0 on success, an AVERROR code on failure. + */ +int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device, + VdpGetProcAddress *get_proc_address, unsigned flags); + +/** + * Gets the parameters to create an adequate VDPAU video surface for the codec + * context using VDPAU hardware decoding acceleration. + * + * @note Behavior is undefined if the context was not successfully bound to a + * VDPAU device using av_vdpau_bind_context(). + * + * @param avctx the codec context being used for decoding the stream + * @param type storage space for the VDPAU video surface chroma type + * (or NULL to ignore) + * @param width storage space for the VDPAU video surface pixel width + * (or NULL to ignore) + * @param height storage space for the VDPAU video surface pixel height + * (or NULL to ignore) + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type, + uint32_t *width, uint32_t *height); + +/** + * Allocate an AVVDPAUContext. + * + * @return Newly-allocated AVVDPAUContext or NULL on failure. + */ +AVVDPAUContext *av_vdpau_alloc_context(void); + +#if FF_API_VDPAU_PROFILE +/** + * Get a decoder profile that should be used for initializing a VDPAU decoder. + * Should be called from the AVCodecContext.get_format() callback. + * + * @deprecated Use av_vdpau_bind_context() instead. + * + * @param avctx the codec context being used for decoding the stream + * @param profile a pointer into which the result will be written on success. + * The contents of profile are undefined if this function returns + * an error. + * + * @return 0 on success (non-negative), a negative AVERROR on failure. + */ +attribute_deprecated +int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile); +#endif + +/* @}*/ + +#endif /* AVCODEC_VDPAU_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/version.h b/thirdparty/user_include/ffmpeg/libavcodec/version.h new file mode 100755 index 0000000000000000000000000000000000000000..3331d473001a982e8b48bbdeea83b4daba7c270b --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/version.h @@ -0,0 +1,140 @@ +/* + * 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 + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/version.h" + +#define LIBAVCODEC_VERSION_MAJOR 58 +#define LIBAVCODEC_VERSION_MINOR 54 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#ifndef FF_API_LOWRES +#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_DEBUG_MV +#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) +#endif +#ifndef FF_API_AVCTX_TIMEBASE +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODED_FRAME +#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_SIDEDATA_ONLY_PKT +#define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VDPAU_PROFILE +#define FF_API_VDPAU_PROFILE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CONVERGENCE_DURATION +#define FF_API_CONVERGENCE_DURATION (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPICTURE +#define FF_API_AVPICTURE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPACKET_OLD_API +#define FF_API_AVPACKET_OLD_API (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_RTP_CALLBACK +#define FF_API_RTP_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_VBV_DELAY +#define FF_API_VBV_DELAY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODER_TYPE +#define FF_API_CODER_TYPE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STAT_BITS +#define FF_API_STAT_BITS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_PRIVATE_OPT +#define FF_API_PRIVATE_OPT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_ASS_TIMING +#define FF_API_ASS_TIMING (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_BSF +#define FF_API_OLD_BSF (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_COPY_CONTEXT +#define FF_API_COPY_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_GET_CONTEXT_DEFAULTS +#define FF_API_GET_CONTEXT_DEFAULTS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NVENC_OLD_NAME +#define FF_API_NVENC_OLD_NAME (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_STRUCT_VAAPI_CONTEXT +#define FF_API_STRUCT_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MERGE_SD_API +#define FF_API_MERGE_SD_API (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_TAG_STRING +#define FF_API_TAG_STRING (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_GETCHROMA +#define FF_API_GETCHROMA (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CODEC_GET_SET +#define FF_API_CODEC_GET_SET (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_USER_VISIBLE_AVHWACCEL +#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LOCKMGR +#define FF_API_LOCKMGR (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_NEXT +#define FF_API_NEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_UNSANITIZED_BITRATES +#define FF_API_UNSANITIZED_BITRATES (LIBAVCODEC_VERSION_MAJOR < 59) +#endif + + +#endif /* AVCODEC_VERSION_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/videotoolbox.h b/thirdparty/user_include/ffmpeg/libavcodec/videotoolbox.h new file mode 100755 index 0000000000000000000000000000000000000000..af2db0d580932f1e2c04606e2f1a856468bafbf8 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/videotoolbox.h @@ -0,0 +1,127 @@ +/* + * Videotoolbox hardware acceleration + * + * copyright (c) 2012 Sebastien Zwickert + * + * 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 + */ + +#ifndef AVCODEC_VIDEOTOOLBOX_H +#define AVCODEC_VIDEOTOOLBOX_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_videotoolbox + * Public libavcodec Videotoolbox header. + */ + +#include + +#define Picture QuickdrawPicture +#include +#undef Picture + +#include "libavcodec/avcodec.h" + +/** + * This struct holds all the information that needs to be passed + * between the caller and libavcodec for initializing Videotoolbox decoding. + * Its size is not a part of the public ABI, it must be allocated with + * av_videotoolbox_alloc_context() and freed with av_free(). + */ +typedef struct AVVideotoolboxContext { + /** + * Videotoolbox decompression session object. + * Created and freed the caller. + */ + VTDecompressionSessionRef session; + + /** + * The output callback that must be passed to the session. + * Set by av_videottoolbox_default_init() + */ + VTDecompressionOutputCallback output_callback; + + /** + * CVPixelBuffer Format Type that Videotoolbox will use for decoded frames. + * set by the caller. If this is set to 0, then no specific format is + * requested from the decoder, and its native format is output. + */ + OSType cv_pix_fmt_type; + + /** + * CoreMedia Format Description that Videotoolbox will use to create the decompression session. + * Set by the caller. + */ + CMVideoFormatDescriptionRef cm_fmt_desc; + + /** + * CoreMedia codec type that Videotoolbox will use to create the decompression session. + * Set by the caller. + */ + int cm_codec_type; +} AVVideotoolboxContext; + +/** + * Allocate and initialize a Videotoolbox context. + * + * This function should be called from the get_format() callback when the caller + * selects the AV_PIX_FMT_VIDETOOLBOX format. The caller must then create + * the decoder object (using the output callback provided by libavcodec) that + * will be used for Videotoolbox-accelerated decoding. + * + * When decoding with Videotoolbox is finished, the caller must destroy the decoder + * object and free the Videotoolbox context using av_free(). + * + * @return the newly allocated context or NULL on failure + */ +AVVideotoolboxContext *av_videotoolbox_alloc_context(void); + +/** + * This is a convenience function that creates and sets up the Videotoolbox context using + * an internal implementation. + * + * @param avctx the corresponding codec context + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int av_videotoolbox_default_init(AVCodecContext *avctx); + +/** + * This is a convenience function that creates and sets up the Videotoolbox context using + * an internal implementation. + * + * @param avctx the corresponding codec context + * @param vtctx the Videotoolbox context to use + * + * @return >= 0 on success, a negative AVERROR code on failure + */ +int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx); + +/** + * This function must be called to free the Videotoolbox context initialized with + * av_videotoolbox_default_init(). + * + * @param avctx the corresponding codec context + */ +void av_videotoolbox_default_free(AVCodecContext *avctx); + +/** + * @} + */ + +#endif /* AVCODEC_VIDEOTOOLBOX_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/vorbis_parser.h b/thirdparty/user_include/ffmpeg/libavcodec/vorbis_parser.h new file mode 100755 index 0000000000000000000000000000000000000000..789932ac4922de0d0754226604802b0d1a8045c1 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/vorbis_parser.h @@ -0,0 +1,74 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * A public API for Vorbis parsing + * + * Determines the duration for each packet. + */ + +#ifndef AVCODEC_VORBIS_PARSER_H +#define AVCODEC_VORBIS_PARSER_H + +#include + +typedef struct AVVorbisParseContext AVVorbisParseContext; + +/** + * Allocate and initialize the Vorbis parser using headers in the extradata. + */ +AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata, + int extradata_size); + +/** + * Free the parser and everything associated with it. + */ +void av_vorbis_parse_free(AVVorbisParseContext **s); + +#define VORBIS_FLAG_HEADER 0x00000001 +#define VORBIS_FLAG_COMMENT 0x00000002 +#define VORBIS_FLAG_SETUP 0x00000004 + +/** + * Get the duration for a Vorbis packet. + * + * If @p flags is @c NULL, + * special frames are considered invalid. + * + * @param s Vorbis parser context + * @param buf buffer containing a Vorbis frame + * @param buf_size size of the buffer + * @param flags flags for special frames + */ +int av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size, int *flags); + +/** + * Get the duration for a Vorbis packet. + * + * @param s Vorbis parser context + * @param buf buffer containing a Vorbis frame + * @param buf_size size of the buffer + */ +int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf, + int buf_size); + +void av_vorbis_parse_reset(AVVorbisParseContext *s); + +#endif /* AVCODEC_VORBIS_PARSER_H */ diff --git a/thirdparty/user_include/ffmpeg/libavcodec/xvmc.h b/thirdparty/user_include/ffmpeg/libavcodec/xvmc.h new file mode 100755 index 0000000000000000000000000000000000000000..465ee78d6e5562360b4364bb37a623f32e450f2f --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavcodec/xvmc.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2003 Ivan Kalvachev + * + * 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 + */ + +#ifndef AVCODEC_XVMC_H +#define AVCODEC_XVMC_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_xvmc + * Public libavcodec XvMC header. + */ + +#include + +#include "libavutil/attributes.h" +#include "version.h" +#include "avcodec.h" + +/** + * @defgroup lavc_codec_hwaccel_xvmc XvMC + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct + the number is 1337 speak for the letters IDCT MCo (motion compensation) */ + +struct attribute_deprecated xvmc_pix_fmt { + /** The field contains the special constant value AV_XVMC_ID. + It is used as a test that the application correctly uses the API, + and that there is no corruption caused by pixel routines. + - application - set during initialization + - libavcodec - unchanged + */ + int xvmc_id; + + /** Pointer to the block array allocated by XvMCCreateBlocks(). + The array has to be freed by XvMCDestroyBlocks(). + Each group of 64 values represents one data block of differential + pixel information (in MoCo mode) or coefficients for IDCT. + - application - set the pointer during initialization + - libavcodec - fills coefficients/pixel data into the array + */ + short* data_blocks; + + /** Pointer to the macroblock description array allocated by + XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks(). + - application - set the pointer during initialization + - libavcodec - fills description data into the array + */ + XvMCMacroBlock* mv_blocks; + + /** Number of macroblock descriptions that can be stored in the mv_blocks + array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_mv_blocks; + + /** Number of blocks that can be stored at once in the data_blocks array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_data_blocks; + + /** Indicate that the hardware would interpret data_blocks as IDCT + coefficients and perform IDCT on them. + - application - set during initialization + - libavcodec - unchanged + */ + int idct; + + /** In MoCo mode it indicates that intra macroblocks are assumed to be in + unsigned format; same as the XVMC_INTRA_UNSIGNED flag. + - application - set during initialization + - libavcodec - unchanged + */ + int unsigned_intra; + + /** Pointer to the surface allocated by XvMCCreateSurface(). + It has to be freed by XvMCDestroySurface() on application exit. + It identifies the frame and its state on the video hardware. + - application - set during initialization + - libavcodec - unchanged + */ + XvMCSurface* p_surface; + +/** Set by the decoder before calling ff_draw_horiz_band(), + needed by the XvMCRenderSurface function. */ +//@{ + /** Pointer to the surface used as past reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_past_surface; + + /** Pointer to the surface used as future reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_future_surface; + + /** top/bottom field or frame + - application - unchanged + - libavcodec - set + */ + unsigned int picture_structure; + + /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence + - application - unchanged + - libavcodec - set + */ + unsigned int flags; +//}@ + + /** Number of macroblock descriptions in the mv_blocks array + that have already been passed to the hardware. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may increment it + with filled_mb_block_num or zero both. + - libavcodec - unchanged + */ + int start_mv_blocks_num; + + /** Number of new macroblock descriptions in the mv_blocks array (after + start_mv_blocks_num) that are filled by libavcodec and have to be + passed to the hardware. + - application - zeroes it on get_buffer() or after successful + ff_draw_horiz_band(). + - libavcodec - increment with one of each stored MB + */ + int filled_mv_blocks_num; + + /** Number of the next free data block; one data block consists of + 64 short values in the data_blocks array. + All blocks before this one have already been claimed by placing their + position into the corresponding block description structure field, + that are part of the mv_blocks array. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may zero it together + with start_mb_blocks_num. + - libavcodec - each decoded macroblock increases it by the number + of coded blocks it contains. + */ + int next_free_data_block_num; +}; + +/** + * @} + */ + +#endif /* AVCODEC_XVMC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/adler32.h b/thirdparty/user_include/ffmpeg/libavutil/adler32.h new file mode 100755 index 0000000000000000000000000000000000000000..a1f035b7340f8b7d0fd6327e3a9b65189c4e93a4 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/adler32.h @@ -0,0 +1,60 @@ +/* + * copyright (c) 2006 Mans Rullgard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_adler32 + * Public header for Adler-32 hash function implementation. + */ + +#ifndef AVUTIL_ADLER32_H +#define AVUTIL_ADLER32_H + +#include +#include "attributes.h" + +/** + * @defgroup lavu_adler32 Adler-32 + * @ingroup lavu_hash + * Adler-32 hash function implementation. + * + * @{ + */ + +/** + * Calculate the Adler32 checksum of a buffer. + * + * Passing the return value to a subsequent av_adler32_update() call + * allows the checksum of multiple buffers to be calculated as though + * they were concatenated. + * + * @param adler initial checksum value + * @param buf pointer to input buffer + * @param len size of input buffer + * @return updated checksum + */ +unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf, + unsigned int len) av_pure; + +/** + * @} + */ + +#endif /* AVUTIL_ADLER32_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/aes.h b/thirdparty/user_include/ffmpeg/libavutil/aes.h new file mode 100755 index 0000000000000000000000000000000000000000..09efbda107397777617d10847a1ad3c966873775 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/aes.h @@ -0,0 +1,65 @@ +/* + * copyright (c) 2007 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_AES_H +#define AVUTIL_AES_H + +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_aes AES + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_aes_size; + +struct AVAES; + +/** + * Allocate an AVAES context. + */ +struct AVAES *av_aes_alloc(void); + +/** + * Initialize an AVAES context. + * @param key_bits 128, 192 or 256 + * @param decrypt 0 for encryption, 1 for decryption + */ +int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * @param count number of 16 byte blocks + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_AES_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/aes_ctr.h b/thirdparty/user_include/ffmpeg/libavutil/aes_ctr.h new file mode 100755 index 0000000000000000000000000000000000000000..e4aae126a764be2b7bbf8f4106a3990344db1a5a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/aes_ctr.h @@ -0,0 +1,88 @@ +/* + * AES-CTR cipher + * Copyright (c) 2015 Eran Kornblau + * + * 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 + */ + +#ifndef AVUTIL_AES_CTR_H +#define AVUTIL_AES_CTR_H + +#include + +#include "attributes.h" +#include "version.h" + +#define AES_CTR_KEY_SIZE (16) +#define AES_CTR_IV_SIZE (8) + +struct AVAESCTR; + +/** + * Allocate an AVAESCTR context. + */ +struct AVAESCTR *av_aes_ctr_alloc(void); + +/** + * Initialize an AVAESCTR context. + * @param key encryption key, must have a length of AES_CTR_KEY_SIZE + */ +int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key); + +/** + * Release an AVAESCTR context. + */ +void av_aes_ctr_free(struct AVAESCTR *a); + +/** + * Process a buffer using a previously initialized context. + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param size the size of src and dst + */ +void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int size); + +/** + * Get the current iv + */ +const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a); + +/** + * Generate a random iv + */ +void av_aes_ctr_set_random_iv(struct AVAESCTR *a); + +/** + * Forcefully change the 8-byte iv + */ +void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv); + +/** + * Forcefully change the "full" 16-byte iv, including the counter + */ +void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv); + +/** + * Increment the top 64 bit of the iv (performed after each frame) + */ +void av_aes_ctr_increment_iv(struct AVAESCTR *a); + +/** + * @} + */ + +#endif /* AVUTIL_AES_CTR_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/attributes.h b/thirdparty/user_include/ffmpeg/libavutil/attributes.h new file mode 100755 index 0000000000000000000000000000000000000000..ced108aa2c75afdf467f91a3faa1cb05af6e9726 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/attributes.h @@ -0,0 +1,167 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Macro definitions for various function/variable attributes + */ + +#ifndef AVUTIL_ATTRIBUTES_H +#define AVUTIL_ATTRIBUTES_H + +#ifdef __GNUC__ +# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y)) +#else +# define AV_GCC_VERSION_AT_LEAST(x,y) 0 +# define AV_GCC_VERSION_AT_MOST(x,y) 0 +#endif + +#ifndef av_always_inline +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_always_inline __attribute__((always_inline)) inline +#elif defined(_MSC_VER) +# define av_always_inline __forceinline +#else +# define av_always_inline inline +#endif +#endif + +#ifndef av_extern_inline +#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__) +# define av_extern_inline extern inline +#else +# define av_extern_inline inline +#endif +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,4) +# define av_warn_unused_result __attribute__((warn_unused_result)) +#else +# define av_warn_unused_result +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define av_noinline __attribute__((noinline)) +#elif defined(_MSC_VER) +# define av_noinline __declspec(noinline) +#else +# define av_noinline +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_pure __attribute__((pure)) +#else +# define av_pure +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__) +# define av_const __attribute__((const)) +#else +# define av_const +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__) +# define av_cold __attribute__((cold)) +#else +# define av_cold +#endif + +#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__) +# define av_flatten __attribute__((flatten)) +#else +# define av_flatten +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,1) +# define attribute_deprecated __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define attribute_deprecated __declspec(deprecated) +#else +# define attribute_deprecated +#endif + +/** + * Disable warnings about deprecated features + * This is useful for sections of code kept for backward compatibility and + * scheduled for removal. + */ +#ifndef AV_NOWARN_DEPRECATED +#if AV_GCC_VERSION_AT_LEAST(4,6) +# define AV_NOWARN_DEPRECATED(code) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + code \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define AV_NOWARN_DEPRECATED(code) \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) \ + code; \ + __pragma(warning(pop)) +#else +# define AV_NOWARN_DEPRECATED(code) code +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_unused __attribute__((unused)) +#else +# define av_unused +#endif + +/** + * Mark a variable as used and prevent the compiler from optimizing it + * away. This is useful for variables accessed only from inline + * assembler without the compiler being aware. + */ +#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__) +# define av_used __attribute__((used)) +#else +# define av_used +#endif + +#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__) +# define av_alias __attribute__((may_alias)) +#else +# define av_alias +#endif + +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) +# define av_uninit(x) x=x +#else +# define av_uninit(x) x +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define av_builtin_constant_p __builtin_constant_p +# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos))) +#else +# define av_builtin_constant_p(x) 0 +# define av_printf_format(fmtpos, attrpos) +#endif + +#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__) +# define av_noreturn __attribute__((noreturn)) +#else +# define av_noreturn +#endif + +#endif /* AVUTIL_ATTRIBUTES_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/audio_fifo.h b/thirdparty/user_include/ffmpeg/libavutil/audio_fifo.h new file mode 100755 index 0000000000000000000000000000000000000000..d8a9194a8d30dc1cdc53c07f0c17d27665a5683d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/audio_fifo.h @@ -0,0 +1,187 @@ +/* + * Audio FIFO + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Audio FIFO Buffer + */ + +#ifndef AVUTIL_AUDIO_FIFO_H +#define AVUTIL_AUDIO_FIFO_H + +#include "avutil.h" +#include "fifo.h" +#include "samplefmt.h" + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_audiofifo Audio FIFO Buffer + * @{ + */ + +/** + * Context for an Audio FIFO Buffer. + * + * - Operates at the sample level rather than the byte level. + * - Supports multiple channels with either planar or packed sample format. + * - Automatic reallocation when writing to a full buffer. + */ +typedef struct AVAudioFifo AVAudioFifo; + +/** + * Free an AVAudioFifo. + * + * @param af AVAudioFifo to free + */ +void av_audio_fifo_free(AVAudioFifo *af); + +/** + * Allocate an AVAudioFifo. + * + * @param sample_fmt sample format + * @param channels number of channels + * @param nb_samples initial allocation size, in samples + * @return newly allocated AVAudioFifo, or NULL on error + */ +AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, + int nb_samples); + +/** + * Reallocate an AVAudioFifo. + * + * @param af AVAudioFifo to reallocate + * @param nb_samples new allocation size, in samples + * @return 0 if OK, or negative AVERROR code on failure + */ +av_warn_unused_result +int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples); + +/** + * Write data to an AVAudioFifo. + * + * The AVAudioFifo will be reallocated automatically if the available space + * is less than nb_samples. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to write to + * @param data audio data plane pointers + * @param nb_samples number of samples to write + * @return number of samples actually written, or negative AVERROR + * code on failure. If successful, the number of samples + * actually written will always be nb_samples. + */ +int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples); + +/** + * Peek data from an AVAudioFifo. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to read from + * @param data audio data plane pointers + * @param nb_samples number of samples to peek + * @return number of samples actually peek, or negative AVERROR code + * on failure. The number of samples actually peek will not + * be greater than nb_samples, and will only be less than + * nb_samples if av_audio_fifo_size is less than nb_samples. + */ +int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples); + +/** + * Peek data from an AVAudioFifo. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to read from + * @param data audio data plane pointers + * @param nb_samples number of samples to peek + * @param offset offset from current read position + * @return number of samples actually peek, or negative AVERROR code + * on failure. The number of samples actually peek will not + * be greater than nb_samples, and will only be less than + * nb_samples if av_audio_fifo_size is less than nb_samples. + */ +int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset); + +/** + * Read data from an AVAudioFifo. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param af AVAudioFifo to read from + * @param data audio data plane pointers + * @param nb_samples number of samples to read + * @return number of samples actually read, or negative AVERROR code + * on failure. The number of samples actually read will not + * be greater than nb_samples, and will only be less than + * nb_samples if av_audio_fifo_size is less than nb_samples. + */ +int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples); + +/** + * Drain data from an AVAudioFifo. + * + * Removes the data without reading it. + * + * @param af AVAudioFifo to drain + * @param nb_samples number of samples to drain + * @return 0 if OK, or negative AVERROR code on failure + */ +int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples); + +/** + * Reset the AVAudioFifo buffer. + * + * This empties all data in the buffer. + * + * @param af AVAudioFifo to reset + */ +void av_audio_fifo_reset(AVAudioFifo *af); + +/** + * Get the current number of samples in the AVAudioFifo available for reading. + * + * @param af the AVAudioFifo to query + * @return number of samples available for reading + */ +int av_audio_fifo_size(AVAudioFifo *af); + +/** + * Get the current number of samples in the AVAudioFifo available for writing. + * + * @param af the AVAudioFifo to query + * @return number of samples available for writing + */ +int av_audio_fifo_space(AVAudioFifo *af); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_AUDIO_FIFO_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/avassert.h b/thirdparty/user_include/ffmpeg/libavutil/avassert.h new file mode 100755 index 0000000000000000000000000000000000000000..9abeadea4a2319832491e57d6b4ab16da2e738f5 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/avassert.h @@ -0,0 +1,75 @@ +/* + * copyright (c) 2010 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple assert() macros that are a bit more flexible than ISO C assert(). + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_AVASSERT_H +#define AVUTIL_AVASSERT_H + +#include +#include "avutil.h" +#include "log.h" + +/** + * assert() equivalent, that is always enabled. + */ +#define av_assert0(cond) do { \ + if (!(cond)) { \ + av_log(NULL, AV_LOG_PANIC, "Assertion %s failed at %s:%d\n", \ + AV_STRINGIFY(cond), __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) + + +/** + * assert() equivalent, that does not lie in speed critical code. + * These asserts() thus can be enabled without fearing speed loss. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0 +#define av_assert1(cond) av_assert0(cond) +#else +#define av_assert1(cond) ((void)0) +#endif + + +/** + * assert() equivalent, that does lie in speed critical code. + */ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 +#define av_assert2(cond) av_assert0(cond) +#define av_assert2_fpu() av_assert0_fpu() +#else +#define av_assert2(cond) ((void)0) +#define av_assert2_fpu() ((void)0) +#endif + +/** + * Assert that floating point operations can be executed. + * + * This will av_assert0() that the cpu is not in MMX state on X86 + */ +void av_assert0_fpu(void); + +#endif /* AVUTIL_AVASSERT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/avconfig.h b/thirdparty/user_include/ffmpeg/libavutil/avconfig.h new file mode 100755 index 0000000000000000000000000000000000000000..c289fbb551c1f89b72e8090b81139d8fb745af08 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/avconfig.h @@ -0,0 +1,6 @@ +/* Generated by ffmpeg configure */ +#ifndef AVUTIL_AVCONFIG_H +#define AVUTIL_AVCONFIG_H +#define AV_HAVE_BIGENDIAN 0 +#define AV_HAVE_FAST_UNALIGNED 1 +#endif /* AVUTIL_AVCONFIG_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/avstring.h b/thirdparty/user_include/ffmpeg/libavutil/avstring.h new file mode 100755 index 0000000000000000000000000000000000000000..37dd4e2da0fc8b63ccffd4731ca486e7ca1ccda6 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/avstring.h @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2007 Mans Rullgard + * + * 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 + */ + +#ifndef AVUTIL_AVSTRING_H +#define AVUTIL_AVSTRING_H + +#include +#include +#include "attributes.h" + +/** + * @addtogroup lavu_string + * @{ + */ + +/** + * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to + * the address of the first character in str after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_strstart(const char *str, const char *pfx, const char **ptr); + +/** + * Return non-zero if pfx is a prefix of str independent of case. If + * it is, *ptr is set to the address of the first character in str + * after the prefix. + * + * @param str input string + * @param pfx prefix to test + * @param ptr updated if the prefix is matched inside str + * @return non-zero if the prefix matches, zero otherwise + */ +int av_stristart(const char *str, const char *pfx, const char **ptr); + +/** + * Locate the first case-independent occurrence in the string haystack + * of the string needle. A zero-length string needle is considered to + * match at the start of haystack. + * + * This function is a case-insensitive version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_stristr(const char *haystack, const char *needle); + +/** + * Locate the first occurrence of the string needle in the string haystack + * where not more than hay_length characters are searched. A zero-length + * string needle is considered to match at the start of haystack. + * + * This function is a length-limited version of the standard strstr(). + * + * @param haystack string to search in + * @param needle string to search for + * @param hay_length length of string to search in + * @return pointer to the located match within haystack + * or a null pointer if no match + */ +char *av_strnstr(const char *haystack, const char *needle, size_t hay_length); + +/** + * Copy the string src to dst, but no more than size - 1 bytes, and + * null-terminate dst. + * + * This function is the same as BSD strlcpy(). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the length of src + * + * @warning since the return value is the length of src, src absolutely + * _must_ be a properly 0-terminated string, otherwise this will read beyond + * the end of the buffer and possibly crash. + */ +size_t av_strlcpy(char *dst, const char *src, size_t size); + +/** + * Append the string src to the string dst, but to a total length of + * no more than size - 1 bytes, and null-terminate dst. + * + * This function is similar to BSD strlcat(), but differs when + * size <= strlen(dst). + * + * @param dst destination buffer + * @param src source string + * @param size size of destination buffer + * @return the total length of src and dst + * + * @warning since the return value use the length of src and dst, these + * absolutely _must_ be a properly 0-terminated strings, otherwise this + * will read beyond the end of the buffer and possibly crash. + */ +size_t av_strlcat(char *dst, const char *src, size_t size); + +/** + * Append output to a string, according to a format. Never write out of + * the destination buffer, and always put a terminating 0 within + * the buffer. + * @param dst destination buffer (string to which the output is + * appended) + * @param size total size of the destination buffer + * @param fmt printf-compatible format string, specifying how the + * following parameters are used + * @return the length of the string that would have been generated + * if enough space had been available + */ +size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4); + +/** + * Get the count of continuous non zero chars starting from the beginning. + * + * @param len maximum number of characters to check in the string, that + * is the maximum value which is returned by the function + */ +static inline size_t av_strnlen(const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len && s[i]; i++) + ; + return i; +} + +/** + * Print arguments following specified format into a large enough auto + * allocated buffer. It is similar to GNU asprintf(). + * @param fmt printf-compatible format string, specifying how the + * following parameters are used. + * @return the allocated string + * @note You have to free the string yourself with av_free(). + */ +char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); + +/** + * Convert a number to an av_malloced string. + */ +char *av_d2str(double d); + +/** + * Unescape the given string until a non escaped terminating char, + * and return the token corresponding to the unescaped string. + * + * The normal \ and ' escaping is supported. Leading and trailing + * whitespaces are removed, unless they are escaped with '\' or are + * enclosed between ''. + * + * @param buf the buffer to parse, buf will be updated to point to the + * terminating char + * @param term a 0-terminated list of terminating chars + * @return the malloced unescaped string, which must be av_freed by + * the user, NULL in case of allocation failure + */ +char *av_get_token(const char **buf, const char *term); + +/** + * Split the string into several tokens which can be accessed by + * successive calls to av_strtok(). + * + * A token is defined as a sequence of characters not belonging to the + * set specified in delim. + * + * On the first call to av_strtok(), s should point to the string to + * parse, and the value of saveptr is ignored. In subsequent calls, s + * should be NULL, and saveptr should be unchanged since the previous + * call. + * + * This function is similar to strtok_r() defined in POSIX.1. + * + * @param s the string to parse, may be NULL + * @param delim 0-terminated list of token delimiters, must be non-NULL + * @param saveptr user-provided pointer which points to stored + * information necessary for av_strtok() to continue scanning the same + * string. saveptr is updated to point to the next character after the + * first delimiter found, or to NULL if the string was terminated + * @return the found token, or NULL when no token is found + */ +char *av_strtok(char *s, const char *delim, char **saveptr); + +/** + * Locale-independent conversion of ASCII isdigit. + */ +static inline av_const int av_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +/** + * Locale-independent conversion of ASCII isgraph. + */ +static inline av_const int av_isgraph(int c) +{ + return c > 32 && c < 127; +} + +/** + * Locale-independent conversion of ASCII isspace. + */ +static inline av_const int av_isspace(int c) +{ + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || + c == '\v'; +} + +/** + * Locale-independent conversion of ASCII characters to uppercase. + */ +static inline av_const int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII characters to lowercase. + */ +static inline av_const int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + +/** + * Locale-independent conversion of ASCII isxdigit. + */ +static inline av_const int av_isxdigit(int c) +{ + c = av_tolower(c); + return av_isdigit(c) || (c >= 'a' && c <= 'f'); +} + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strcasecmp(const char *a, const char *b); + +/** + * Locale-independent case-insensitive compare. + * @note This means only ASCII-range characters are case-insensitive + */ +int av_strncasecmp(const char *a, const char *b, size_t n); + +/** + * Locale-independent strings replace. + * @note This means only ASCII-range characters are replace + */ +char *av_strireplace(const char *str, const char *from, const char *to); + +/** + * Thread safe basename. + * @param path the path, on DOS both \ and / are considered separators. + * @return pointer to the basename substring. + */ +const char *av_basename(const char *path); + +/** + * Thread safe dirname. + * @param path the path, on DOS both \ and / are considered separators. + * @return the path with the separator replaced by the string terminator or ".". + * @note the function may change the input string. + */ +const char *av_dirname(char *path); + +/** + * Match instances of a name in a comma-separated list of names. + * List entries are checked from the start to the end of the names list, + * the first match ends further processing. If an entry prefixed with '-' + * matches, then 0 is returned. The "ALL" list entry is considered to + * match all names. + * + * @param name Name to look for. + * @param names List of names. + * @return 1 on match, 0 otherwise. + */ +int av_match_name(const char *name, const char *names); + +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0) + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT (1 << 1) + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +av_warn_unused_result +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF +#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF +#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes +#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML + +#define AV_UTF8_FLAG_ACCEPT_ALL \ + AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES + +/** + * Read and decode a single UTF-8 code point (character) from the + * buffer in *buf, and update *buf to point to the next byte to + * decode. + * + * In case of an invalid byte sequence, the pointer will be updated to + * the next byte after the invalid sequence and the function will + * return an error code. + * + * Depending on the specified flags, the function will also fail in + * case the decoded code point does not belong to a valid range. + * + * @note For speed-relevant code a carefully implemented use of + * GET_UTF8() may be preferred. + * + * @param codep pointer used to return the parsed code in case of success. + * The value in *codep is set even in case the range check fails. + * @param bufp pointer to the address the first byte of the sequence + * to decode, updated by the function to point to the + * byte next after the decoded sequence + * @param buf_end pointer to the end of the buffer, points to the next + * byte past the last in the buffer. This is used to + * avoid buffer overreads (in case of an unfinished + * UTF-8 sequence towards the end of the buffer). + * @param flags a collection of AV_UTF8_FLAG_* flags + * @return >= 0 in case a sequence was successfully read, a negative + * value in case of invalid sequence + */ +av_warn_unused_result +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + +/** + * Check if a name is in a list. + * @returns 0 if not found, or the 1 based index where it has been found in the + * list. + */ +int av_match_list(const char *name, const char *list, char separator); + +/** + * See libc sscanf manual for more information. + * Locale-independent sscanf implementation. + */ +int av_sscanf(const char *string, const char *format, ...); + +/** + * @} + */ + +#endif /* AVUTIL_AVSTRING_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/avutil.h b/thirdparty/user_include/ffmpeg/libavutil/avutil.h new file mode 100755 index 0000000000000000000000000000000000000000..4d633156d14df32518281d0a9750de52bf0c69fb --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/avutil.h @@ -0,0 +1,365 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_AVUTIL_H +#define AVUTIL_AVUTIL_H + +/** + * @file + * @ingroup lavu + * Convenience header that includes @ref lavu "libavutil"'s core. + */ + +/** + * @mainpage + * + * @section ffmpeg_intro Introduction + * + * This document describes the usage of the different libraries + * provided by FFmpeg. + * + * @li @ref libavc "libavcodec" encoding/decoding library + * @li @ref lavfi "libavfilter" graph-based frame editing library + * @li @ref libavf "libavformat" I/O and muxing/demuxing library + * @li @ref lavd "libavdevice" special devices muxing/demuxing library + * @li @ref lavu "libavutil" common utility library + * @li @ref lswr "libswresample" audio resampling, format conversion and mixing + * @li @ref lpp "libpostproc" post processing library + * @li @ref libsws "libswscale" color conversion and scaling library + * + * @section ffmpeg_versioning Versioning and compatibility + * + * Each of the FFmpeg libraries contains a version.h header, which defines a + * major, minor and micro version number with the + * LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO} macros. The major version + * number is incremented with backward incompatible changes - e.g. removing + * parts of the public API, reordering public struct members, etc. The minor + * version number is incremented for backward compatible API changes or major + * new features - e.g. adding a new public function or a new decoder. The micro + * version number is incremented for smaller changes that a calling program + * might still want to check for - e.g. changing behavior in a previously + * unspecified situation. + * + * FFmpeg guarantees backward API and ABI compatibility for each library as long + * as its major version number is unchanged. This means that no public symbols + * will be removed or renamed. Types and names of the public struct members and + * values of public macros and enums will remain the same (unless they were + * explicitly declared as not part of the public API). Documented behavior will + * not change. + * + * In other words, any correct program that works with a given FFmpeg snapshot + * should work just as well without any changes with any later snapshot with the + * same major versions. This applies to both rebuilding the program against new + * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program + * links against. + * + * However, new public symbols may be added and new members may be appended to + * public structs whose size is not part of public ABI (most public structs in + * FFmpeg). New macros and enum values may be added. Behavior in undocumented + * situations may change slightly (and be documented). All those are accompanied + * by an entry in doc/APIchanges and incrementing either the minor or micro + * version number. + */ + +/** + * @defgroup lavu libavutil + * Common code shared across all FFmpeg libraries. + * + * @note + * libavutil is designed to be modular. In most cases, in order to use the + * functions provided by one component of libavutil you must explicitly include + * the specific header containing that feature. If you are only using + * media-related components, you could simply include libavutil/avutil.h, which + * brings in most of the "core" components. + * + * @{ + * + * @defgroup lavu_crypto Crypto and Hashing + * + * @{ + * @} + * + * @defgroup lavu_math Mathematics + * @{ + * + * @} + * + * @defgroup lavu_string String Manipulation + * + * @{ + * + * @} + * + * @defgroup lavu_mem Memory Management + * + * @{ + * + * @} + * + * @defgroup lavu_data Data Structures + * @{ + * + * @} + * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * + * @defgroup lavu_audio Audio related + * + * @{ + * + * @} + * + * @defgroup lavu_error Error Codes + * + * @{ + * + * @} + * + * @defgroup lavu_log Logging Facility + * + * @{ + * + * @} + * + * @defgroup lavu_misc Other + * + * @{ + * + * @defgroup preproc_misc Preprocessor String Macros + * + * @{ + * + * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} + */ + + +/** + * @addtogroup lavu_ver + * @{ + */ + +/** + * Return the LIBAVUTIL_VERSION_INT constant. + */ +unsigned avutil_version(void); + +/** + * Return an informative version string. This usually is the actual release + * version number or a git commit description. This string has no fixed format + * and can change any time. It should never be parsed by code. + */ +const char *av_version_info(void); + +/** + * Return the libavutil build-time configuration. + */ +const char *avutil_configuration(void); + +/** + * Return the libavutil license. + */ +const char *avutil_license(void); + +/** + * @} + */ + +/** + * @addtogroup lavu_media Media Type + * @brief Media Type + */ + +enum AVMediaType { + AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA + AVMEDIA_TYPE_VIDEO, + AVMEDIA_TYPE_AUDIO, + AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous + AVMEDIA_TYPE_SUBTITLE, + AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse + AVMEDIA_TYPE_NB +}; + +/** + * Return a string describing the media_type enum, NULL if media_type + * is unknown. + */ +const char *av_get_media_type_string(enum AVMediaType media_type); + +/** + * @defgroup lavu_const Constants + * @{ + * + * @defgroup lavu_enc Encoding specific + * + * @note those definition should move to avcodec + * @{ + */ + +#define FF_LAMBDA_SHIFT 7 +#define FF_LAMBDA_SCALE (1< + +/** + * @defgroup lavu_base64 Base64 + * @ingroup lavu_crypto + * @{ + */ + +/** + * 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, that is AV_BASE64_DECODE_SIZE(strlen(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); + +/** + * Calculate the output size in bytes needed to decode a base64 string + * with length x to a data buffer. + */ +#define AV_BASE64_DECODE_SIZE(x) ((x) * 3LL / 4) + +/** + * Encode data to base64 and null-terminate. + * + * @param out buffer for encoded data + * @param out_size size in bytes of the out buffer (including the + * null terminator), must be at least AV_BASE64_SIZE(in_size) + * @param in input buffer containing the data to encode + * @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 to a + * null-terminated string. + */ +#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1) + + /** + * @} + */ + +#endif /* AVUTIL_BASE64_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/blowfish.h b/thirdparty/user_include/ffmpeg/libavutil/blowfish.h new file mode 100755 index 0000000000000000000000000000000000000000..9e289a40dabe535dc151a2345f49a753f3f640e2 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/blowfish.h @@ -0,0 +1,82 @@ +/* + * Blowfish algorithm + * Copyright (c) 2012 Samuel Pitoiset + * + * 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 + */ + +#ifndef AVUTIL_BLOWFISH_H +#define AVUTIL_BLOWFISH_H + +#include + +/** + * @defgroup lavu_blowfish Blowfish + * @ingroup lavu_crypto + * @{ + */ + +#define AV_BF_ROUNDS 16 + +typedef struct AVBlowfish { + uint32_t p[AV_BF_ROUNDS + 2]; + uint32_t s[4][256]; +} AVBlowfish; + +/** + * Allocate an AVBlowfish context. + */ +AVBlowfish *av_blowfish_alloc(void); + +/** + * Initialize an AVBlowfish context. + * + * @param ctx an AVBlowfish context + * @param key a key + * @param key_len length of the key + */ +void av_blowfish_init(struct AVBlowfish *ctx, const uint8_t *key, int key_len); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVBlowfish context + * @param xl left four bytes halves of input to be encrypted + * @param xr right four bytes halves of input to be encrypted + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_blowfish_crypt_ecb(struct AVBlowfish *ctx, uint32_t *xl, uint32_t *xr, + int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVBlowfish context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_blowfish_crypt(struct AVBlowfish *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_BLOWFISH_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/bprint.h b/thirdparty/user_include/ffmpeg/libavutil/bprint.h new file mode 100755 index 0000000000000000000000000000000000000000..c09b1ac1e1aa77686780694e7f45c4ad59b7dc5d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/bprint.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2012 Nicolas George + * + * 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 + */ + +#ifndef AVUTIL_BPRINT_H +#define AVUTIL_BPRINT_H + +#include + +#include "attributes.h" +#include "avstring.h" + +/** + * Define a structure with extra padding to a fixed size + * This helps ensuring binary compatibility with future versions. + */ + +#define FF_PAD_STRUCTURE(name, size, ...) \ +struct ff_pad_helper_##name { __VA_ARGS__ }; \ +typedef struct name { \ + __VA_ARGS__ \ + char reserved_padding[size - sizeof(struct ff_pad_helper_##name)]; \ +} name; + +/** + * Buffer to print data progressively + * + * The string buffer grows as necessary and is always 0-terminated. + * The content of the string is never accessed, and thus is + * encoding-agnostic and can even hold binary data. + * + * Small buffers are kept in the structure itself, and thus require no + * memory allocation at all (unless the contents of the buffer is needed + * after the structure goes out of scope). This is almost as lightweight as + * declaring a local "char buf[512]". + * + * The length of the string can go beyond the allocated size: the buffer is + * then truncated, but the functions still keep account of the actual total + * length. + * + * In other words, buf->len can be greater than buf->size and records the + * total length of what would have been to the buffer if there had been + * enough memory. + * + * Append operations do not need to be tested for failure: if a memory + * allocation fails, data stop being appended to the buffer, but the length + * is still updated. This situation can be tested with + * av_bprint_is_complete(). + * + * The size_max field determines several possible behaviours: + * + * size_max = -1 (= UINT_MAX) or any large value will let the buffer be + * reallocated as necessary, with an amortized linear cost. + * + * size_max = 0 prevents writing anything to the buffer: only the total + * length is computed. The write operations can then possibly be repeated in + * a buffer with exactly the necessary size + * (using size_init = size_max = len + 1). + * + * size_max = 1 is automatically replaced by the exact size available in the + * structure itself, thus ensuring no dynamic memory allocation. The + * internal buffer is large enough to hold a reasonable paragraph of text, + * such as the current paragraph. + */ + +FF_PAD_STRUCTURE(AVBPrint, 1024, + char *str; /**< string so far */ + unsigned len; /**< length so far */ + unsigned size; /**< allocated memory */ + unsigned size_max; /**< maximum allocated memory */ + char reserved_internal_buffer[1]; +) + +/** + * Convenience macros for special values for av_bprint_init() size_max + * parameter. + */ +#define AV_BPRINT_SIZE_UNLIMITED ((unsigned)-1) +#define AV_BPRINT_SIZE_AUTOMATIC 1 +#define AV_BPRINT_SIZE_COUNT_ONLY 0 + +/** + * Init a print buffer. + * + * @param buf buffer to init + * @param size_init initial size (including the final 0) + * @param size_max maximum size; + * 0 means do not write anything, just count the length; + * 1 is replaced by the maximum value for automatic storage; + * any large value means that the internal buffer will be + * reallocated as needed up to that limit; -1 is converted to + * UINT_MAX, the largest limit possible. + * Check also AV_BPRINT_SIZE_* macros. + */ +void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max); + +/** + * Init a print buffer using a pre-existing buffer. + * + * The buffer will not be reallocated. + * + * @param buf buffer structure to init + * @param buffer byte buffer to use for the string data + * @param size size of buffer + */ +void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size); + +/** + * Append a formatted string to a print buffer. + */ +void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3); + +/** + * Append a formatted string to a print buffer. + */ +void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg); + +/** + * Append char c n times to a print buffer. + */ +void av_bprint_chars(AVBPrint *buf, char c, unsigned n); + +/** + * Append data to a print buffer. + * + * param buf bprint buffer to use + * param data pointer to data + * param size size of data + */ +void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size); + +struct tm; +/** + * Append a formatted date and time to a print buffer. + * + * param buf bprint buffer to use + * param fmt date and time format string, see strftime() + * param tm broken-down time structure to translate + * + * @note due to poor design of the standard strftime function, it may + * produce poor results if the format string expands to a very long text and + * the bprint buffer is near the limit stated by the size_max option. + */ +void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm); + +/** + * Allocate bytes in the buffer for external use. + * + * @param[in] buf buffer structure + * @param[in] size required size + * @param[out] mem pointer to the memory area + * @param[out] actual_size size of the memory area after allocation; + * can be larger or smaller than size + */ +void av_bprint_get_buffer(AVBPrint *buf, unsigned size, + unsigned char **mem, unsigned *actual_size); + +/** + * Reset the string to "" but keep internal allocated data. + */ +void av_bprint_clear(AVBPrint *buf); + +/** + * Test if the print buffer is complete (not truncated). + * + * It may have been truncated due to a memory allocation failure + * or the size_max limit (compare size and size_max if necessary). + */ +static inline int av_bprint_is_complete(const AVBPrint *buf) +{ + return buf->len < buf->size; +} + +/** + * Finalize a print buffer. + * + * The print buffer can no longer be used afterwards, + * but the len and size fields are still valid. + * + * @arg[out] ret_str if not NULL, used to return a permanent copy of the + * buffer contents, or NULL if memory allocation fails; + * if NULL, the buffer is discarded and freed + * @return 0 for success or error code (probably AVERROR(ENOMEM)) + */ +int av_bprint_finalize(AVBPrint *buf, char **ret_str); + +/** + * Escape the content in src and append it to dstbuf. + * + * @param dstbuf already inited destination bprint buffer + * @param src string containing the text to escape + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_* macros + */ +void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + +#endif /* AVUTIL_BPRINT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/bswap.h b/thirdparty/user_include/ffmpeg/libavutil/bswap.h new file mode 100755 index 0000000000000000000000000000000000000000..91cb79538dc2fb5979df88ce5e8279ec80170600 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/bswap.h @@ -0,0 +1,109 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * byte swapping routines + */ + +#ifndef AVUTIL_BSWAP_H +#define AVUTIL_BSWAP_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_AARCH64 +# include "aarch64/bswap.h" +#elif ARCH_ARM +# include "arm/bswap.h" +#elif ARCH_AVR32 +# include "avr32/bswap.h" +#elif ARCH_SH4 +# include "sh4/bswap.h" +#elif ARCH_X86 +# include "x86/bswap.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff)) +#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16)) +#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32)) + +#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x) + +#ifndef av_bswap16 +static av_always_inline av_const uint16_t av_bswap16(uint16_t x) +{ + x= (x>>8) | (x<<8); + return x; +} +#endif + +#ifndef av_bswap32 +static av_always_inline av_const uint32_t av_bswap32(uint32_t x) +{ + return AV_BSWAP32C(x); +} +#endif + +#ifndef av_bswap64 +static inline uint64_t av_const av_bswap64(uint64_t x) +{ + return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32); +} +#endif + +// be2ne ... big-endian to native-endian +// le2ne ... little-endian to native-endian + +#if AV_HAVE_BIGENDIAN +#define av_be2ne16(x) (x) +#define av_be2ne32(x) (x) +#define av_be2ne64(x) (x) +#define av_le2ne16(x) av_bswap16(x) +#define av_le2ne32(x) av_bswap32(x) +#define av_le2ne64(x) av_bswap64(x) +#define AV_BE2NEC(s, x) (x) +#define AV_LE2NEC(s, x) AV_BSWAPC(s, x) +#else +#define av_be2ne16(x) av_bswap16(x) +#define av_be2ne32(x) av_bswap32(x) +#define av_be2ne64(x) av_bswap64(x) +#define av_le2ne16(x) (x) +#define av_le2ne32(x) (x) +#define av_le2ne64(x) (x) +#define AV_BE2NEC(s, x) AV_BSWAPC(s, x) +#define AV_LE2NEC(s, x) (x) +#endif + +#define AV_BE2NE16C(x) AV_BE2NEC(16, x) +#define AV_BE2NE32C(x) AV_BE2NEC(32, x) +#define AV_BE2NE64C(x) AV_BE2NEC(64, x) +#define AV_LE2NE16C(x) AV_LE2NEC(16, x) +#define AV_LE2NE32C(x) AV_LE2NEC(32, x) +#define AV_LE2NE64C(x) AV_LE2NEC(64, x) + +#endif /* AVUTIL_BSWAP_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/buffer.h b/thirdparty/user_include/ffmpeg/libavutil/buffer.h new file mode 100755 index 0000000000000000000000000000000000000000..73b6bd0b148e6e6018845a0df928d8d20cef115a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/buffer.h @@ -0,0 +1,291 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_buffer + * refcounted data buffer API + */ + +#ifndef AVUTIL_BUFFER_H +#define AVUTIL_BUFFER_H + +#include + +/** + * @defgroup lavu_buffer AVBuffer + * @ingroup lavu_data + * + * @{ + * AVBuffer is an API for reference-counted data buffers. + * + * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer + * represents the data buffer itself; it is opaque and not meant to be accessed + * by the caller directly, but only through AVBufferRef. However, the caller may + * e.g. compare two AVBuffer pointers to check whether two different references + * are describing the same data buffer. AVBufferRef represents a single + * reference to an AVBuffer and it is the object that may be manipulated by the + * caller directly. + * + * There are two functions provided for creating a new AVBuffer with a single + * reference -- av_buffer_alloc() to just allocate a new buffer, and + * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing + * reference, additional references may be created with av_buffer_ref(). + * Use av_buffer_unref() to free a reference (this will automatically free the + * data once all the references are freed). + * + * The convention throughout this API and the rest of FFmpeg is such that the + * buffer is considered writable if there exists only one reference to it (and + * it has not been marked as read-only). The av_buffer_is_writable() function is + * provided to check whether this is true and av_buffer_make_writable() will + * automatically create a new writable buffer when necessary. + * Of course nothing prevents the calling code from violating this convention, + * however that is safe only when all the existing references are under its + * control. + * + * @note Referencing and unreferencing the buffers is thread-safe and thus + * may be done from multiple threads simultaneously without any need for + * additional locking. + * + * @note Two different references to the same buffer can point to different + * parts of the buffer (i.e. their AVBufferRef.data will not be equal). + */ + +/** + * A reference counted buffer type. It is opaque and is meant to be used through + * references (AVBufferRef). + */ +typedef struct AVBuffer AVBuffer; + +/** + * A reference to a data buffer. + * + * The size of this struct is not a part of the public ABI and it is not meant + * to be allocated directly. + */ +typedef struct AVBufferRef { + AVBuffer *buffer; + + /** + * The data buffer. It is considered writable if and only if + * this is the only reference to the buffer, in which case + * av_buffer_is_writable() returns 1. + */ + uint8_t *data; + /** + * Size of data in bytes. + */ + int size; +} AVBufferRef; + +/** + * Allocate an AVBuffer of the given size using av_malloc(). + * + * @return an AVBufferRef of given size or NULL when out of memory + */ +AVBufferRef *av_buffer_alloc(int size); + +/** + * Same as av_buffer_alloc(), except the returned buffer will be initialized + * to zero. + */ +AVBufferRef *av_buffer_allocz(int size); + +/** + * Always treat the buffer as read-only, even when it has only one + * reference. + */ +#define AV_BUFFER_FLAG_READONLY (1 << 0) + +/** + * Create an AVBuffer from an existing array. + * + * If this function is successful, data is owned by the AVBuffer. The caller may + * only access data through the returned AVBufferRef and references derived from + * it. + * If this function fails, data is left untouched. + * @param data data array + * @param size size of data in bytes + * @param free a callback for freeing this buffer's data + * @param opaque parameter to be got for processing or passed to free + * @param flags a combination of AV_BUFFER_FLAG_* + * + * @return an AVBufferRef referring to data on success, NULL on failure. + */ +AVBufferRef *av_buffer_create(uint8_t *data, int size, + void (*free)(void *opaque, uint8_t *data), + void *opaque, int flags); + +/** + * Default free callback, which calls av_free() on the buffer data. + * This function is meant to be passed to av_buffer_create(), not called + * directly. + */ +void av_buffer_default_free(void *opaque, uint8_t *data); + +/** + * Create a new reference to an AVBuffer. + * + * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on + * failure. + */ +AVBufferRef *av_buffer_ref(AVBufferRef *buf); + +/** + * Free a given reference and automatically free the buffer if there are no more + * references to it. + * + * @param buf the reference to be freed. The pointer is set to NULL on return. + */ +void av_buffer_unref(AVBufferRef **buf); + +/** + * @return 1 if the caller may write to the data referred to by buf (which is + * true if and only if buf is the only reference to the underlying AVBuffer). + * Return 0 otherwise. + * A positive answer is valid until av_buffer_ref() is called on buf. + */ +int av_buffer_is_writable(const AVBufferRef *buf); + +/** + * @return the opaque parameter set by av_buffer_create. + */ +void *av_buffer_get_opaque(const AVBufferRef *buf); + +int av_buffer_get_ref_count(const AVBufferRef *buf); + +/** + * Create a writable reference from a given buffer reference, avoiding data copy + * if possible. + * + * @param buf buffer reference to make writable. On success, buf is either left + * untouched, or it is unreferenced and a new writable AVBufferRef is + * written in its place. On failure, buf is left untouched. + * @return 0 on success, a negative AVERROR on failure. + */ +int av_buffer_make_writable(AVBufferRef **buf); + +/** + * Reallocate a given buffer. + * + * @param buf a buffer reference to reallocate. On success, buf will be + * unreferenced and a new reference with the required size will be + * written in its place. On failure buf will be left untouched. *buf + * may be NULL, then a new buffer is allocated. + * @param size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + * + * @note the buffer is actually reallocated with av_realloc() only if it was + * initially allocated through av_buffer_realloc(NULL) and there is only one + * reference to it (i.e. the one passed to this function). In all other cases + * a new buffer is allocated and the data is copied. + */ +int av_buffer_realloc(AVBufferRef **buf, int size); + +/** + * @} + */ + +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_pool_get() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); + +/** + * Allocate and initialize a buffer pool with a more complex allocator. + * + * @param size size of each buffer in this pool + * @param opaque arbitrary user data used by the allocator + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. + * @param pool_free a function that will be called immediately before the pool + * is freed. I.e. after av_buffer_pool_uninit() is called + * by the caller and all the frames are returned to the pool + * and freed. It is intended to uninitialize the user opaque + * data. + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init2(int size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, int size), + void (*pool_free)(void *opaque)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * This function may be called simultaneously from multiple threads. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); + +/** + * @} + */ + +#endif /* AVUTIL_BUFFER_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/camellia.h b/thirdparty/user_include/ffmpeg/libavutil/camellia.h new file mode 100755 index 0000000000000000000000000000000000000000..e674c9b9a478252ab86727f4a3ba62cc959e2b7d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/camellia.h @@ -0,0 +1,70 @@ +/* + * An implementation of the CAMELLIA algorithm as mentioned in RFC3713 + * Copyright (c) 2014 Supraja Meedinti + * + * 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 + */ + +#ifndef AVUTIL_CAMELLIA_H +#define AVUTIL_CAMELLIA_H + +#include + + +/** + * @file + * @brief Public header for libavutil CAMELLIA algorithm + * @defgroup lavu_camellia CAMELLIA + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_camellia_size; + +struct AVCAMELLIA; + +/** + * Allocate an AVCAMELLIA context + * To free the struct: av_free(ptr) + */ +struct AVCAMELLIA *av_camellia_alloc(void); + +/** + * Initialize an AVCAMELLIA context. + * + * @param ctx an AVCAMELLIA context + * @param key a key of 16, 24, 32 bytes used for encryption/decryption + * @param key_bits number of keybits: possible are 128, 192, 256 + */ +int av_camellia_init(struct AVCAMELLIA *ctx, const uint8_t *key, int key_bits); + +/** + * Encrypt or decrypt a buffer using a previously initialized context + * + * @param ctx an AVCAMELLIA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 16 byte blocks + * @paran iv initialization vector for CBC mode, NULL for ECB mode + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_camellia_crypt(struct AVCAMELLIA *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt); + +/** + * @} + */ +#endif /* AVUTIL_CAMELLIA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/cast5.h b/thirdparty/user_include/ffmpeg/libavutil/cast5.h new file mode 100755 index 0000000000000000000000000000000000000000..ad5b347e685ed06d1170b75cad968b21b71ba4c0 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/cast5.h @@ -0,0 +1,80 @@ +/* + * An implementation of the CAST128 algorithm as mentioned in RFC2144 + * Copyright (c) 2014 Supraja Meedinti + * + * 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 + */ + +#ifndef AVUTIL_CAST5_H +#define AVUTIL_CAST5_H + +#include + + +/** + * @file + * @brief Public header for libavutil CAST5 algorithm + * @defgroup lavu_cast5 CAST5 + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_cast5_size; + +struct AVCAST5; + +/** + * Allocate an AVCAST5 context + * To free the struct: av_free(ptr) + */ +struct AVCAST5 *av_cast5_alloc(void); +/** + * Initialize an AVCAST5 context. + * + * @param ctx an AVCAST5 context + * @param key a key of 5,6,...16 bytes used for encryption/decryption + * @param key_bits number of keybits: possible are 40,48,...,128 + * @return 0 on success, less than 0 on failure + */ +int av_cast5_init(struct AVCAST5 *ctx, const uint8_t *key, int key_bits); + +/** + * Encrypt or decrypt a buffer using a previously initialized context, ECB mode only + * + * @param ctx an AVCAST5 context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_cast5_crypt(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context + * + * @param ctx an AVCAST5 context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, NULL for ECB mode + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_cast5_crypt2(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); +/** + * @} + */ +#endif /* AVUTIL_CAST5_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/channel_layout.h b/thirdparty/user_include/ffmpeg/libavutil/channel_layout.h new file mode 100755 index 0000000000000000000000000000000000000000..50bb8f03c586e1b505dc9aca5df669986911239a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/channel_layout.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * 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 + */ + +#ifndef AVUTIL_CHANNEL_LAYOUT_H +#define AVUTIL_CHANNEL_LAYOUT_H + +#include + +/** + * @file + * audio channel layout utility functions + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * @defgroup channel_masks Audio channel masks + * + * A channel layout is a 64-bits integer with a bit set for every channel. + * The number of bits set must be equal to the number of channels. + * The value 0 means that the channel layout is not known. + * @note this data structure is not powerful enough to handle channels + * combinations that have the same channel multiple times, such as + * dual-mono. + * + * @{ + */ +#define AV_CH_FRONT_LEFT 0x00000001 +#define AV_CH_FRONT_RIGHT 0x00000002 +#define AV_CH_FRONT_CENTER 0x00000004 +#define AV_CH_LOW_FREQUENCY 0x00000008 +#define AV_CH_BACK_LEFT 0x00000010 +#define AV_CH_BACK_RIGHT 0x00000020 +#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040 +#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080 +#define AV_CH_BACK_CENTER 0x00000100 +#define AV_CH_SIDE_LEFT 0x00000200 +#define AV_CH_SIDE_RIGHT 0x00000400 +#define AV_CH_TOP_CENTER 0x00000800 +#define AV_CH_TOP_FRONT_LEFT 0x00001000 +#define AV_CH_TOP_FRONT_CENTER 0x00002000 +#define AV_CH_TOP_FRONT_RIGHT 0x00004000 +#define AV_CH_TOP_BACK_LEFT 0x00008000 +#define AV_CH_TOP_BACK_CENTER 0x00010000 +#define AV_CH_TOP_BACK_RIGHT 0x00020000 +#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. +#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT. +#define AV_CH_WIDE_LEFT 0x0000000080000000ULL +#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL +#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL +#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL +#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL + +/** Channel mask value used for AVCodecContext.request_channel_layout + to indicate that the user requests the channel order of the decoder output + to be the native codec channel order. */ +#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL + +/** + * @} + * @defgroup channel_mask_c Audio channel layouts + * @{ + * */ +#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT) +#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) +#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT) +#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER) +#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY) +#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER) +#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) +#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) +#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) + +enum AVMatrixEncoding { + AV_MATRIX_ENCODING_NONE, + AV_MATRIX_ENCODING_DOLBY, + AV_MATRIX_ENCODING_DPLII, + AV_MATRIX_ENCODING_DPLIIX, + AV_MATRIX_ENCODING_DPLIIZ, + AV_MATRIX_ENCODING_DOLBYEX, + AV_MATRIX_ENCODING_DOLBYHEADPHONE, + AV_MATRIX_ENCODING_NB +}; + +/** + * Return a channel layout id that matches name, or 0 if no match is found. + * + * name can be one or several of the following notations, + * separated by '+' or '|': + * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0, + * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); + * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, + * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); + * - a number of channels, in decimal, followed by 'c', yielding + * the default channel layout for that number of channels (@see + * av_get_default_channel_layout); + * - a channel layout mask, in hexadecimal starting with "0x" (see the + * AV_CH_* macros). + * + * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" + */ +uint64_t av_get_channel_layout(const char *name); + +/** + * Return a channel layout and the number of channels based on the specified name. + * + * This function is similar to (@see av_get_channel_layout), but can also parse + * unknown channel layout specifications. + * + * @param[in] name channel layout specification string + * @param[out] channel_layout parsed channel layout (0 if unknown) + * @param[out] nb_channels number of channels + * + * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + */ +int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); + +/** + * Return a description of a channel layout. + * If nb_channels is <= 0, it is guessed from the channel_layout. + * + * @param buf put here the string containing the channel layout + * @param buf_size size in bytes of the buffer + */ +void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); + +struct AVBPrint; +/** + * Append a description of a channel layout to a bprint buffer. + */ +void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); + +/** + * Return the number of channels in the channel layout. + */ +int av_get_channel_layout_nb_channels(uint64_t channel_layout); + +/** + * Return default channel layout for a given number of channels. + */ +int64_t av_get_default_channel_layout(int nb_channels); + +/** + * Get the index of a channel in channel_layout. + * + * @param channel a channel layout describing exactly one channel which must be + * present in channel_layout. + * + * @return index of channel in channel_layout on success, a negative AVERROR + * on error. + */ +int av_get_channel_layout_channel_index(uint64_t channel_layout, + uint64_t channel); + +/** + * Get the channel with the given index in channel_layout. + */ +uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); + +/** + * Get the name of a given channel. + * + * @return channel name on success, NULL on error. + */ +const char *av_get_channel_name(uint64_t channel); + +/** + * Get the description of a given channel. + * + * @param channel a channel layout with a single channel + * @return channel description on success, NULL on error + */ +const char *av_get_channel_description(uint64_t channel); + +/** + * Get the value and name of a standard channel layout. + * + * @param[in] index index in an internal list, starting at 0 + * @param[out] layout channel layout mask + * @param[out] name name of the layout + * @return 0 if the layout exists, + * <0 if index is beyond the limits + */ +int av_get_standard_channel_layout(unsigned index, uint64_t *layout, + const char **name); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_CHANNEL_LAYOUT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/common.h b/thirdparty/user_include/ffmpeg/libavutil/common.h new file mode 100755 index 0000000000000000000000000000000000000000..bad43e426e07d0390d94533ed5432496e9021ea4 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/common.h @@ -0,0 +1,560 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * common internal and external API header + */ + +#ifndef AVUTIL_COMMON_H +#define AVUTIL_COMMON_H + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C) +#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "macros.h" +#include "version.h" +#include "libavutil/avconfig.h" + +#if AV_HAVE_BIGENDIAN +# define AV_NE(be, le) (be) +#else +# define AV_NE(be, le) (le) +#endif + +//rounded division & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +/* Fast a/(1<=0 and b>=0 */ +#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +/* Backwards compat. */ +#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT + +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) + +/** + * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they + * are not representable as absolute values of their type. This is the same + * as with *abs() + * @see FFNABS() + */ +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +/** + * Negative Absolute value. + * this works for all integers of all types. + * As with many macros, this evaluates its argument twice, it thus must not have + * a sideeffect, that is FFNABS(x++) has undefined behavior. + */ +#define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) + +/** + * Comparator. + * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 + * if x == y. This is useful for instance in a qsort comparator callback. + * Furthermore, compilers are able to optimize this to branchless code, and + * there is no risk of overflow with signed types. + * As with many macros, this evaluates its argument multiple times, it thus + * must not have a side-effect. + */ +#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c) + +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) + +/* misc math functions */ + +#ifdef HAVE_AV_CONFIG_H +# include "config.h" +# include "intmath.h" +#endif + +/* Pull in unguarded fallback defines at the end of this file. */ +#include "common.h" + +#ifndef av_log2 +av_const int av_log2(unsigned v); +#endif + +#ifndef av_log2_16bit +av_const int av_log2_16bit(unsigned v); +#endif + +/** + * Clip a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int av_clip_c(int a, int amin, int amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed 64bit integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a signed integer value into the 0-255 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint8_t av_clip_uint8_c(int a) +{ + if (a&(~0xFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -128,127 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int8_t av_clip_int8_c(int a) +{ + if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F; + else return a; +} + +/** + * Clip a signed integer value into the 0-65535 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const uint16_t av_clip_uint16_c(int a) +{ + if (a&(~0xFFFF)) return (~a)>>31; + else return a; +} + +/** + * Clip a signed integer value into the -32768,32767 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int16_t av_clip_int16_c(int a) +{ + if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF; + else return a; +} + +/** + * Clip a signed 64-bit integer value into the -2147483648,2147483647 range. + * @param a value to clip + * @return clipped value + */ +static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) +{ + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; +} + +/** + * Clip a signed integer into the -(2^p),(2^p-1) range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const int av_clip_intp2_c(int a, int p) +{ + if (((unsigned)a + (1 << p)) & ~((2 << p) - 1)) + return (a >> 31) ^ ((1 << p) - 1); + else + return a; +} + +/** + * Clip a signed integer to an unsigned power of two range. + * @param a value to clip + * @param p bit position to clip at + * @return clipped value + */ +static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p) +{ + if (a & ~((1<> 31 & ((1<= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Clip a double value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static av_always_inline av_const double av_clipd_c(double a, double amin, double amax) +{ +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** Compute ceil(log2(x)). + * @param x value used to compute ceil(log2(x)) + * @return computed ceiling of log2(x) + */ +static av_always_inline av_const int av_ceil_log2_c(int x) +{ + return av_log2((x - 1U) << 1); +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount_c(uint32_t x) +{ + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +} + +/** + * Count number of bits set to one in x + * @param x value to count bits of + * @return the number of bits set to one in x + */ +static av_always_inline av_const int av_popcount64_c(uint64_t x) +{ + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); +} + +static av_always_inline av_const int av_parity_c(uint32_t v) +{ + return av_popcount(v) & 1; +} + +#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) +#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24)) + +/** + * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_BYTE Expression reading one byte from the input. + * Evaluated up to 7 times (4 for the currently + * assigned Unicode range). With a memory buffer + * input, this could be *ptr++. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + * + * @warning ERROR should not contain a loop control statement which + * could interact with the internal while loop, and should force an + * exit from the macro code (e.g. through a goto or a return) in order + * to prevent undefined results. + */ +#define GET_UTF8(val, GET_BYTE, ERROR)\ + val= (GET_BYTE);\ + {\ + uint32_t top = (val & 128) >> 1;\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ + ERROR\ + while (val & top) {\ + int tmp= (GET_BYTE) - 128;\ + if(tmp>>6)\ + ERROR\ + val= (val<<6) + tmp;\ + top <<= 5;\ + }\ + val &= (top << 1) - 1;\ + } + +/** + * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form. + * + * @param val Output value, must be an lvalue of type uint32_t. + * @param GET_16BIT Expression returning two bytes of UTF-16 data converted + * to native byte order. Evaluated one or two times. + * @param ERROR Expression to be evaluated on invalid input, + * typically a goto statement. + */ +#define GET_UTF16(val, GET_16BIT, ERROR)\ + val = GET_16BIT;\ + {\ + unsigned int hi = val - 0xD800;\ + if (hi < 0x800) {\ + val = GET_16BIT - 0xDC00;\ + if (val > 0x3FFU || hi > 0x3FFU)\ + ERROR\ + val += (hi<<10) + 0x10000;\ + }\ + }\ + +/** + * @def PUT_UTF8(val, tmp, PUT_BYTE) + * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint8_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_BYTE. + * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination. + * It could be a function or a statement, and uses tmp as the input byte. + * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be + * executed up to 4 times for values in the valid UTF-8 range and up to + * 7 times in the general case, depending on the length of the converted + * Unicode character. + */ +#define PUT_UTF8(val, tmp, PUT_BYTE)\ + {\ + int bytes, shift;\ + uint32_t in = val;\ + if (in < 0x80) {\ + tmp = in;\ + PUT_BYTE\ + } else {\ + bytes = (av_log2(in) + 4) / 5;\ + shift = (bytes - 1) * 6;\ + tmp = (256 - (256 >> bytes)) | (in >> shift);\ + PUT_BYTE\ + while (shift >= 6) {\ + shift -= 6;\ + tmp = 0x80 | ((in >> shift) & 0x3f);\ + PUT_BYTE\ + }\ + }\ + } + +/** + * @def PUT_UTF16(val, tmp, PUT_16BIT) + * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes). + * @param val is an input-only argument and should be of type uint32_t. It holds + * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If + * val is given as a function it is executed only once. + * @param tmp is a temporary variable and should be of type uint16_t. It + * represents an intermediate value during conversion that is to be + * output by PUT_16BIT. + * @param PUT_16BIT writes the converted UTF-16 data to any proper destination + * in desired endianness. It could be a function or a statement, and uses tmp + * as the input byte. For example, PUT_BYTE could be "*output++ = tmp;" + * PUT_BYTE will be executed 1 or 2 times depending on input character. + */ +#define PUT_UTF16(val, tmp, PUT_16BIT)\ + {\ + uint32_t in = val;\ + if (in < 0x10000) {\ + tmp = in;\ + PUT_16BIT\ + } else {\ + tmp = 0xD800 | ((in - 0x10000) >> 10);\ + PUT_16BIT\ + tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\ + PUT_16BIT\ + }\ + }\ + + + +#include "mem.h" + +#ifdef HAVE_AV_CONFIG_H +# include "internal.h" +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* AVUTIL_COMMON_H */ + +/* + * The following definitions are outside the multiple inclusion guard + * to ensure they are immediately available in intmath.h. + */ + +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif diff --git a/thirdparty/user_include/ffmpeg/libavutil/cpu.h b/thirdparty/user_include/ffmpeg/libavutil/cpu.h new file mode 100755 index 0000000000000000000000000000000000000000..8bb9eb606bf2a2e30b879a2751764be1b12ce4f0 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/cpu.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * 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 + */ + +#ifndef AVUTIL_CPU_H +#define AVUTIL_CPU_H + +#include + +#include "attributes.h" + +#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */ + + /* lower 16 bits - CPU features */ +#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX +#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext +#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW +#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions +#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions +#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster + ///< than regular MMX/SSE (e.g. Core1) +#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt +#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions +#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster + ///< than regular MMX/SSE (e.g. Core1) +#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions +#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster +#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower +#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions +#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions +#define AV_CPU_FLAG_AESNI 0x80000 ///< Advanced Encryption Standard functions +#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer) +#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions +#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions +#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction +#define AV_CPU_FLAG_AVX2 0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used +#define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions +#define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1 +#define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2 +#define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used + +#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard +#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 +#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07 + +#define AV_CPU_FLAG_ARMV5TE (1 << 0) +#define AV_CPU_FLAG_ARMV6 (1 << 1) +#define AV_CPU_FLAG_ARMV6T2 (1 << 2) +#define AV_CPU_FLAG_VFP (1 << 3) +#define AV_CPU_FLAG_VFPV3 (1 << 4) +#define AV_CPU_FLAG_NEON (1 << 5) +#define AV_CPU_FLAG_ARMV8 (1 << 6) +#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations +#define AV_CPU_FLAG_SETEND (1 <<16) + +/** + * Return the flags which specify extensions supported by the CPU. + * The returned value is affected by av_force_cpu_flags() if that was used + * before. So av_get_cpu_flags() can easily be used in an application to + * detect the enabled cpu flags. + */ +int av_get_cpu_flags(void); + +/** + * Disables cpu detection and forces the specified flags. + * -1 is a special case that disables forcing of specific flags. + */ +void av_force_cpu_flags(int flags); + +/** + * Set a mask on flags returned by av_get_cpu_flags(). + * This function is mainly useful for testing. + * Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible + */ +attribute_deprecated void av_set_cpu_flags_mask(int mask); + +/** + * Parse CPU flags from a string. + * + * The returned flags contain the specified flags as well as related unspecified flags. + * + * This function exists only for compatibility with libav. + * Please use av_parse_cpu_caps() when possible. + * @return a combination of AV_CPU_* flags, negative on error. + */ +attribute_deprecated +int av_parse_cpu_flags(const char *s); + +/** + * Parse CPU caps from a string and update the given AV_CPU_* flags based on that. + * + * @return negative on error. + */ +int av_parse_cpu_caps(unsigned *flags, const char *s); + +/** + * @return the number of logical CPU cores present. + */ +int av_cpu_count(void); + +/** + * Get the maximum data alignment that may be required by FFmpeg. + * + * Note that this is affected by the build configuration and the CPU flags mask, + * so e.g. if the CPU supports AVX, but libavutil has been built with + * --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through + * av_set_cpu_flags_mask(), then this function will behave as if AVX is not + * present. + */ +size_t av_cpu_max_align(void); + +#endif /* AVUTIL_CPU_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/crc.h b/thirdparty/user_include/ffmpeg/libavutil/crc.h new file mode 100755 index 0000000000000000000000000000000000000000..47e22b4c7872ba1c623aa0b30bdb4bce9bb7c65e --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/crc.h @@ -0,0 +1,100 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_crc32 + * Public header for CRC hash function implementation. + */ + +#ifndef AVUTIL_CRC_H +#define AVUTIL_CRC_H + +#include +#include +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_crc32 CRC + * @ingroup lavu_hash + * CRC (Cyclic Redundancy Check) hash function implementation. + * + * This module supports numerous CRC polynomials, in addition to the most + * widely used CRC-32-IEEE. See @ref AVCRCId for a list of available + * polynomials. + * + * @{ + */ + +typedef uint32_t AVCRC; + +typedef enum { + AV_CRC_8_ATM, + AV_CRC_16_ANSI, + AV_CRC_16_CCITT, + AV_CRC_32_IEEE, + AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */ + AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */ + AV_CRC_24_IEEE, + AV_CRC_8_EBU, + AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ +}AVCRCId; + +/** + * Initialize a CRC table. + * @param ctx must be an array of size sizeof(AVCRC)*257 or sizeof(AVCRC)*1024 + * @param le If 1, the lowest bit represents the coefficient for the highest + * exponent of the corresponding polynomial (both for poly and + * actual CRC). + * If 0, you must swap the CRC parameter and the result of av_crc + * if you need the standard representation (can be simplified in + * most cases to e.g. bswap16): + * av_bswap32(crc << (32-bits)) + * @param bits number of bits for the CRC + * @param poly generator polynomial without the x**bits coefficient, in the + * representation as specified by le + * @param ctx_size size of ctx in bytes + * @return <0 on failure + */ +int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size); + +/** + * Get an initialized standard CRC table. + * @param crc_id ID of a standard CRC + * @return a pointer to the CRC table or NULL on failure + */ +const AVCRC *av_crc_get_table(AVCRCId crc_id); + +/** + * Calculate the CRC of a block. + * @param crc CRC of previous blocks if any or initial value for CRC + * @return CRC updated with the data from the given block + * + * @see av_crc_init() "le" parameter + */ +uint32_t av_crc(const AVCRC *ctx, uint32_t crc, + const uint8_t *buffer, size_t length) av_pure; + +/** + * @} + */ + +#endif /* AVUTIL_CRC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/des.h b/thirdparty/user_include/ffmpeg/libavutil/des.h new file mode 100755 index 0000000000000000000000000000000000000000..4cf11f5bca47a18544e172bc1d4457a3ff7a1720 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/des.h @@ -0,0 +1,77 @@ +/* + * DES encryption/decryption + * Copyright (c) 2007 Reimar Doeffinger + * + * 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 + */ + +#ifndef AVUTIL_DES_H +#define AVUTIL_DES_H + +#include + +/** + * @defgroup lavu_des DES + * @ingroup lavu_crypto + * @{ + */ + +typedef struct AVDES { + uint64_t round_keys[3][16]; + int triple_des; +} AVDES; + +/** + * Allocate an AVDES context. + */ +AVDES *av_des_alloc(void); + +/** + * @brief Initializes an AVDES context. + * + * @param key_bits must be 64 or 192 + * @param decrypt 0 for encryption/CBC-MAC, 1 for decryption + * @return zero on success, negative value otherwise + */ +int av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt); + +/** + * @brief Encrypts / decrypts using the DES algorithm. + * + * @param count number of 8 byte blocks + * @param dst destination array, can be equal to src, must be 8-byte aligned + * @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL + * @param iv initialization vector for CBC mode, if NULL then ECB will be used, + * must be 8-byte aligned + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_des_crypt(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); + +/** + * @brief Calculates CBC-MAC using the DES algorithm. + * + * @param count number of 8 byte blocks + * @param dst destination array, can be equal to src, must be 8-byte aligned + * @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL + */ +void av_des_mac(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count); + +/** + * @} + */ + +#endif /* AVUTIL_DES_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/dict.h b/thirdparty/user_include/ffmpeg/libavutil/dict.h new file mode 100755 index 0000000000000000000000000000000000000000..118f1f00ed2046fa5ae5a2440a5961190d923e3a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/dict.h @@ -0,0 +1,200 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Public dictionary API. + * @deprecated + * AVDictionary is provided for compatibility with libav. It is both in + * implementation as well as API inefficient. It does not scale and is + * extremely slow with large dictionaries. + * It is recommended that new code uses our tree container from tree.c/h + * where applicable, which uses AVL trees to achieve O(log n) performance. + */ + +#ifndef AVUTIL_DICT_H +#define AVUTIL_DICT_H + +#include + +#include "version.h" + +/** + * @addtogroup lavu_dict AVDictionary + * @ingroup lavu_data + * + * @brief Simple key:value store + * + * @{ + * Dictionaries are used for storing key:value pairs. To create + * an AVDictionary, simply pass an address of a NULL pointer to + * av_dict_set(). NULL can be used as an empty dictionary wherever + * a pointer to an AVDictionary is required. + * Use av_dict_get() to retrieve an entry or iterate over all + * entries and finally av_dict_free() to free the dictionary + * and all its contents. + * + @code + AVDictionary *d = NULL; // "create" an empty dictionary + AVDictionaryEntry *t = NULL; + + av_dict_set(&d, "foo", "bar", 0); // add an entry + + char *k = av_strdup("key"); // if your strings are already allocated, + char *v = av_strdup("value"); // you can avoid copying them like this + av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + + while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) { + <....> // iterate over all entries in d + } + av_dict_free(&d); + @endcode + */ + +#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */ +#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key, + ignoring the suffix of the found key string. Only relevant in av_dict_get(). */ +#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been + allocated with av_malloc() or another memory allocation function. */ +#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries. +#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no + delimiter is added, the strings are simply concatenated. */ +#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */ + +typedef struct AVDictionaryEntry { + char *key; + char *value; +} AVDictionaryEntry; + +typedef struct AVDictionary AVDictionary; + +/** + * Get a dictionary entry with matching key. + * + * The returned entry key or value must not be changed, or it will + * cause undefined behavior. + * + * To iterate through all the dictionary entries, you can set the matching key + * to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag. + * + * @param prev Set to the previous matching element to find the next. + * If set to NULL the first matching element is returned. + * @param key matching key + * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved + * @return found entry or NULL in case no matching entry was found in the dictionary + */ +AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, + const AVDictionaryEntry *prev, int flags); + +/** + * Get number of entries in dictionary. + * + * @param m dictionary + * @return number of entries in dictionary + */ +int av_dict_count(const AVDictionary *m); + +/** + * Set the given entry in *pm, overwriting an existing entry. + * + * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set, + * these arguments will be freed on error. + * + * Warning: Adding a new entry to a dictionary invalidates all existing entries + * previously returned with av_dict_get. + * + * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL + * a dictionary struct is allocated and put in *pm. + * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags) + * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags). + * Passing a NULL value will cause an existing entry to be deleted. + * @return >= 0 on success otherwise an error code <0 + */ +int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); + +/** + * Convenience wrapper for av_dict_set that converts the value to a string + * and stores it. + * + * Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error. + */ +int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags); + +/** + * Parse the key/value pairs list and add the parsed entries to a dictionary. + * + * In case of failure, all the successfully set entries are stored in + * *pm. You may need to manually free the created dictionary. + * + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @param flags flags to use when adding to dictionary. + * AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL + * are ignored since the key/value tokens will always + * be duplicated. + * @return 0 on success, negative AVERROR code on failure + */ +int av_dict_parse_string(AVDictionary **pm, const char *str, + const char *key_val_sep, const char *pairs_sep, + int flags); + +/** + * Copy entries from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, + * this function will allocate a struct for you and put it in *dst + * @param src pointer to source AVDictionary struct + * @param flags flags to use when setting entries in *dst + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag + * @return 0 on success, negative AVERROR code on failure. If dst was allocated + * by this function, callers should free the associated memory. + */ +int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); + +/** + * Free all the memory allocated for an AVDictionary struct + * and all keys and values. + */ +void av_dict_free(AVDictionary **m); + +/** + * Get dictionary entries as a string. + * + * Create a string containing dictionary's entries. + * Such string may be passed back to av_dict_parse_string(). + * @note String is escaped with backslashes ('\'). + * + * @param[in] m dictionary + * @param[out] buffer Pointer to buffer that will be allocated with string containg entries. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_dict_get_string(const AVDictionary *m, char **buffer, + const char key_val_sep, const char pairs_sep); + +/** + * @} + */ + +#endif /* AVUTIL_DICT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/display.h b/thirdparty/user_include/ffmpeg/libavutil/display.h new file mode 100755 index 0000000000000000000000000000000000000000..515adad795d529904dbf300cdd79e6356c742fa1 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/display.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Display matrix + */ + +#ifndef AVUTIL_DISPLAY_H +#define AVUTIL_DISPLAY_H + +#include +#include "common.h" + +/** + * @addtogroup lavu_video + * @{ + * + * @defgroup lavu_video_display Display transformation matrix functions + * @{ + */ + +/** + * @addtogroup lavu_video_display + * The display transformation matrix specifies an affine transformation that + * should be applied to video frames for correct presentation. It is compatible + * with the matrices stored in the ISO/IEC 14496-12 container format. + * + * The data is a 3x3 matrix represented as a 9-element array: + * + * @code{.unparsed} + * | a b u | + * (a, b, u, c, d, v, x, y, w) -> | c d v | + * | x y w | + * @endcode + * + * All numbers are stored in native endianness, as 16.16 fixed-point values, + * except for u, v and w, which are stored as 2.30 fixed-point values. + * + * The transformation maps a point (p, q) in the source (pre-transformation) + * frame to the point (p', q') in the destination (post-transformation) frame as + * follows: + * + * @code{.unparsed} + * | a b u | + * (p, q, 1) . | c d v | = z * (p', q', 1) + * | x y w | + * @endcode + * + * The transformation can also be more explicitly written in components as + * follows: + * + * @code{.unparsed} + * p' = (a * p + c * q + x) / z; + * q' = (b * p + d * q + y) / z; + * z = u * p + v * q + w + * @endcode + */ + +/** + * Extract the rotation component of the transformation matrix. + * + * @param matrix the transformation matrix + * @return the angle (in degrees) by which the transformation rotates the frame + * counterclockwise. The angle will be in range [-180.0, 180.0], + * or NaN if the matrix is singular. + * + * @note floating point numbers are inherently inexact, so callers are + * recommended to round the return value to nearest integer before use. + */ +double av_display_rotation_get(const int32_t matrix[9]); + +/** + * Initialize a transformation matrix describing a pure counterclockwise + * rotation by the specified angle (in degrees). + * + * @param matrix an allocated transformation matrix (will be fully overwritten + * by this function) + * @param angle rotation angle in degrees. + */ +void av_display_rotation_set(int32_t matrix[9], double angle); + +/** + * Flip the input matrix horizontally and/or vertically. + * + * @param matrix an allocated transformation matrix + * @param hflip whether the matrix should be flipped horizontally + * @param vflip whether the matrix should be flipped vertically + */ +void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_DISPLAY_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/downmix_info.h b/thirdparty/user_include/ffmpeg/libavutil/downmix_info.h new file mode 100755 index 0000000000000000000000000000000000000000..221cf5bf9bafb86a64c253b5097b7dc2625e8fa2 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/downmix_info.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Tim Walker + * + * 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 + */ + +#ifndef AVUTIL_DOWNMIX_INFO_H +#define AVUTIL_DOWNMIX_INFO_H + +#include "frame.h" + +/** + * @file + * audio downmix medatata + */ + +/** + * @addtogroup lavu_audio + * @{ + */ + +/** + * @defgroup downmix_info Audio downmix metadata + * @{ + */ + +/** + * Possible downmix types. + */ +enum AVDownmixType { + AV_DOWNMIX_TYPE_UNKNOWN, /**< Not indicated. */ + AV_DOWNMIX_TYPE_LORO, /**< Lo/Ro 2-channel downmix (Stereo). */ + AV_DOWNMIX_TYPE_LTRT, /**< Lt/Rt 2-channel downmix, Dolby Surround compatible. */ + AV_DOWNMIX_TYPE_DPLII, /**< Lt/Rt 2-channel downmix, Dolby Pro Logic II compatible. */ + AV_DOWNMIX_TYPE_NB /**< Number of downmix types. Not part of ABI. */ +}; + +/** + * This structure describes optional metadata relevant to a downmix procedure. + * + * All fields are set by the decoder to the value indicated in the audio + * bitstream (if present), or to a "sane" default otherwise. + */ +typedef struct AVDownmixInfo { + /** + * Type of downmix preferred by the mastering engineer. + */ + enum AVDownmixType preferred_downmix_type; + + /** + * Absolute scale factor representing the nominal level of the center + * channel during a regular downmix. + */ + double center_mix_level; + + /** + * Absolute scale factor representing the nominal level of the center + * channel during an Lt/Rt compatible downmix. + */ + double center_mix_level_ltrt; + + /** + * Absolute scale factor representing the nominal level of the surround + * channels during a regular downmix. + */ + double surround_mix_level; + + /** + * Absolute scale factor representing the nominal level of the surround + * channels during an Lt/Rt compatible downmix. + */ + double surround_mix_level_ltrt; + + /** + * Absolute scale factor representing the level at which the LFE data is + * mixed into L/R channels during downmixing. + */ + double lfe_mix_level; +} AVDownmixInfo; + +/** + * Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing. + * + * If the side data is absent, it is created and added to the frame. + * + * @param frame the frame for which the side data is to be obtained or created + * + * @return the AVDownmixInfo structure to be edited by the caller, or NULL if + * the structure cannot be allocated. + */ +AVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* AVUTIL_DOWNMIX_INFO_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/encryption_info.h b/thirdparty/user_include/ffmpeg/libavutil/encryption_info.h new file mode 100755 index 0000000000000000000000000000000000000000..8fe7ebfe43203f63e88c07c115e5c00c097fef1c --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/encryption_info.h @@ -0,0 +1,205 @@ +/** + * 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 + */ + +#ifndef AVUTIL_ENCRYPTION_INFO_H +#define AVUTIL_ENCRYPTION_INFO_H + +#include +#include + +typedef struct AVSubsampleEncryptionInfo { + /** The number of bytes that are clear. */ + unsigned int bytes_of_clear_data; + + /** + * The number of bytes that are protected. If using pattern encryption, + * the pattern applies to only the protected bytes; if not using pattern + * encryption, all these bytes are encrypted. + */ + unsigned int bytes_of_protected_data; +} AVSubsampleEncryptionInfo; + +/** + * This describes encryption info for a packet. This contains frame-specific + * info for how to decrypt the packet before passing it to the decoder. + * + * The size of this struct is not part of the public ABI. + */ +typedef struct AVEncryptionInfo { + /** The fourcc encryption scheme, in big-endian byte order. */ + uint32_t scheme; + + /** + * Only used for pattern encryption. This is the number of 16-byte blocks + * that are encrypted. + */ + uint32_t crypt_byte_block; + + /** + * Only used for pattern encryption. This is the number of 16-byte blocks + * that are clear. + */ + uint32_t skip_byte_block; + + /** + * The ID of the key used to encrypt the packet. This should always be + * 16 bytes long, but may be changed in the future. + */ + uint8_t *key_id; + uint32_t key_id_size; + + /** + * The initialization vector. This may have been zero-filled to be the + * correct block size. This should always be 16 bytes long, but may be + * changed in the future. + */ + uint8_t *iv; + uint32_t iv_size; + + /** + * An array of subsample encryption info specifying how parts of the sample + * are encrypted. If there are no subsamples, then the whole sample is + * encrypted. + */ + AVSubsampleEncryptionInfo *subsamples; + uint32_t subsample_count; +} AVEncryptionInfo; + +/** + * This describes info used to initialize an encryption key system. + * + * The size of this struct is not part of the public ABI. + */ +typedef struct AVEncryptionInitInfo { + /** + * A unique identifier for the key system this is for, can be NULL if it + * is not known. This should always be 16 bytes, but may change in the + * future. + */ + uint8_t* system_id; + uint32_t system_id_size; + + /** + * An array of key IDs this initialization data is for. All IDs are the + * same length. Can be NULL if there are no known key IDs. + */ + uint8_t** key_ids; + /** The number of key IDs. */ + uint32_t num_key_ids; + /** + * The number of bytes in each key ID. This should always be 16, but may + * change in the future. + */ + uint32_t key_id_size; + + /** + * Key-system specific initialization data. This data is copied directly + * from the file and the format depends on the specific key system. This + * can be NULL if there is no initialization data; in that case, there + * will be at least one key ID. + */ + uint8_t* data; + uint32_t data_size; + + /** + * An optional pointer to the next initialization info in the list. + */ + struct AVEncryptionInitInfo *next; +} AVEncryptionInitInfo; + +/** + * Allocates an AVEncryptionInfo structure and sub-pointers to hold the given + * number of subsamples. This will allocate pointers for the key ID, IV, + * and subsample entries, set the size members, and zero-initialize the rest. + * + * @param subsample_count The number of subsamples. + * @param key_id_size The number of bytes in the key ID, should be 16. + * @param iv_size The number of bytes in the IV, should be 16. + * + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size); + +/** + * Allocates an AVEncryptionInfo structure with a copy of the given data. + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info); + +/** + * Frees the given encryption info object. This MUST NOT be used to free the + * side-data data pointer, that should use normal side-data methods. + */ +void av_encryption_info_free(AVEncryptionInfo *info); + +/** + * Creates a copy of the AVEncryptionInfo that is contained in the given side + * data. The resulting object should be passed to av_encryption_info_free() + * when done. + * + * @return The new AVEncryptionInfo structure, or NULL on error. + */ +AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, size_t side_data_size); + +/** + * Allocates and initializes side data that holds a copy of the given encryption + * info. The resulting pointer should be either freed using av_free or given + * to av_packet_add_side_data(). + * + * @return The new side-data pointer, or NULL. + */ +uint8_t *av_encryption_info_add_side_data( + const AVEncryptionInfo *info, size_t *side_data_size); + + +/** + * Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the + * given sizes. This will allocate pointers and set all the fields. + * + * @return The new AVEncryptionInitInfo structure, or NULL on error. + */ +AVEncryptionInitInfo *av_encryption_init_info_alloc( + uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size); + +/** + * Frees the given encryption init info object. This MUST NOT be used to free + * the side-data data pointer, that should use normal side-data methods. + */ +void av_encryption_init_info_free(AVEncryptionInitInfo* info); + +/** + * Creates a copy of the AVEncryptionInitInfo that is contained in the given + * side data. The resulting object should be passed to + * av_encryption_init_info_free() when done. + * + * @return The new AVEncryptionInitInfo structure, or NULL on error. + */ +AVEncryptionInitInfo *av_encryption_init_info_get_side_data( + const uint8_t* side_data, size_t side_data_size); + +/** + * Allocates and initializes side data that holds a copy of the given encryption + * init info. The resulting pointer should be either freed using av_free or + * given to av_packet_add_side_data(). + * + * @return The new side-data pointer, or NULL. + */ +uint8_t *av_encryption_init_info_add_side_data( + const AVEncryptionInitInfo *info, size_t *side_data_size); + +#endif /* AVUTIL_ENCRYPTION_INFO_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/error.h b/thirdparty/user_include/ffmpeg/libavutil/error.h new file mode 100755 index 0000000000000000000000000000000000000000..71df4da353b9cd95e45e86c14acc0c285854f0af --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/error.h @@ -0,0 +1,126 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * error code definitions + */ + +#ifndef AVUTIL_ERROR_H +#define AVUTIL_ERROR_H + +#include +#include + +/** + * @addtogroup lavu_error + * + * @{ + */ + + +/* error handling */ +#if EDOM > 0 +#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions. +#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value. +#else +/* Some platforms have E* and errno already negated. */ +#define AVERROR(e) (e) +#define AVUNERROR(e) (e) +#endif + +#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d)) + +#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found +#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2 +#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small +#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found +#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found +#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found +#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file +#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted +#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library +#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found +#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input +#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found +#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found +#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome +#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found + +#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found +/** + * This is semantically identical to AVERROR_BUG + * it has been introduced in Libav after our AVERROR_BUG and with a modified value. + */ +#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ') +#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library +#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it. +#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED) +#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED) +/* HTTP & RTSP errors */ +#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0') +#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1') +#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3') +#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4') +#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X') +#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X') + +#define AV_ERROR_MAX_STRING_SIZE 64 + +/** + * Put a description of the AVERROR code errnum in errbuf. + * In case of failure the global variable errno is set to indicate the + * error. Even in case of failure av_strerror() will print a generic + * error message indicating the errnum provided to errbuf. + * + * @param errnum error code to describe + * @param errbuf buffer to which description is written + * @param errbuf_size the size in bytes of errbuf + * @return 0 on success, a negative value if a description for errnum + * cannot be found + */ +int av_strerror(int errnum, char *errbuf, size_t errbuf_size); + +/** + * Fill the provided buffer with a string containing an error string + * corresponding to the AVERROR code errnum. + * + * @param errbuf a buffer + * @param errbuf_size size in bytes of errbuf + * @param errnum error code to describe + * @return the buffer in input, filled with the error description + * @see av_strerror() + */ +static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum) +{ + av_strerror(errnum, errbuf, errbuf_size); + return errbuf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_err2str(errnum) \ + av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) + +/** + * @} + */ + +#endif /* AVUTIL_ERROR_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/eval.h b/thirdparty/user_include/ffmpeg/libavutil/eval.h new file mode 100755 index 0000000000000000000000000000000000000000..dacd22b96e66cec8818f1b2f5c806df166eb9d86 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/eval.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2002 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * simple arithmetic expression evaluator + */ + +#ifndef AVUTIL_EVAL_H +#define AVUTIL_EVAL_H + +#include "avutil.h" + +typedef struct AVExpr AVExpr; + +/** + * Parse and evaluate an expression. + * Note, this is significantly slower than av_expr_eval(). + * + * @param res a pointer to a double where is put the result value of + * the expression, or NAN in case of error + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param const_values a zero terminated array of values for the identifiers from const_names + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @param log_ctx parent logging context + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse_and_eval(double *res, const char *s, + const char * const *const_names, const double *const_values, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + void *opaque, int log_offset, void *log_ctx); + +/** + * Parse an expression. + * + * @param expr a pointer where is put an AVExpr containing the parsed + * value in case of successful parsing, or NULL otherwise. + * The pointed to AVExpr must be freed with av_expr_free() by the user + * when it is not needed anymore. + * @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)" + * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0} + * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers + * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument + * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers + * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments + * @param log_ctx parent logging context + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_expr_parse(AVExpr **expr, const char *s, + const char * const *const_names, + const char * const *func1_names, double (* const *funcs1)(void *, double), + const char * const *func2_names, double (* const *funcs2)(void *, double, double), + int log_offset, void *log_ctx); + +/** + * Evaluate a previously parsed expression. + * + * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names + * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2 + * @return the value of the expression + */ +double av_expr_eval(AVExpr *e, const double *const_values, void *opaque); + +/** + * Free a parsed expression previously created with av_expr_parse(). + */ +void av_expr_free(AVExpr *e); + +/** + * Parse the string in numstr and return its value as a double. If + * the string is empty, contains only whitespaces, or does not contain + * an initial substring that has the expected syntax for a + * floating-point number, no conversion is performed. In this case, + * returns a value of zero and the value returned in tail is the value + * of numstr. + * + * @param numstr a string representing a number, may contain one of + * the International System number postfixes, for example 'K', 'M', + * 'G'. If 'i' is appended after the postfix, powers of 2 are used + * instead of powers of 10. The 'B' postfix multiplies the value by + * 8, and can be appended after another postfix or used alone. This + * allows using for example 'KB', 'MiB', 'G' and 'B' as postfix. + * @param tail if non-NULL puts here the pointer to the char next + * after the last parsed character + */ +double av_strtod(const char *numstr, char **tail); + +#endif /* AVUTIL_EVAL_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/ffversion.h b/thirdparty/user_include/ffmpeg/libavutil/ffversion.h new file mode 100755 index 0000000000000000000000000000000000000000..8f7fdad1828896fe8dc45d44188e8146caa0a37b --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/ffversion.h @@ -0,0 +1,5 @@ +/* Automatically generated by version.sh, do not manually edit! */ +#ifndef AVUTIL_FFVERSION_H +#define AVUTIL_FFVERSION_H +#define FFMPEG_VERSION "4.2.4" +#endif /* AVUTIL_FFVERSION_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/fifo.h b/thirdparty/user_include/ffmpeg/libavutil/fifo.h new file mode 100755 index 0000000000000000000000000000000000000000..dc7bc6f0dd7925a6c0e94847d537fa62164a4639 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/fifo.h @@ -0,0 +1,179 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * a very simple circular buffer FIFO implementation + */ + +#ifndef AVUTIL_FIFO_H +#define AVUTIL_FIFO_H + +#include +#include "avutil.h" +#include "attributes.h" + +typedef struct AVFifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; + uint32_t rndx, wndx; +} AVFifoBuffer; + +/** + * Initialize an AVFifoBuffer. + * @param size of FIFO + * @return AVFifoBuffer or NULL in case of memory allocation failure + */ +AVFifoBuffer *av_fifo_alloc(unsigned int size); + +/** + * Initialize an AVFifoBuffer. + * @param nmemb number of elements + * @param size size of the single element + * @return AVFifoBuffer or NULL in case of memory allocation failure + */ +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size); + +/** + * Free an AVFifoBuffer. + * @param f AVFifoBuffer to free + */ +void av_fifo_free(AVFifoBuffer *f); + +/** + * Free an AVFifoBuffer and reset pointer to NULL. + * @param f AVFifoBuffer to free + */ +void av_fifo_freep(AVFifoBuffer **f); + +/** + * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. + * @param f AVFifoBuffer to reset + */ +void av_fifo_reset(AVFifoBuffer *f); + +/** + * Return the amount of data in bytes in the AVFifoBuffer, that is the + * amount of data you can read from it. + * @param f AVFifoBuffer to read from + * @return size + */ +int av_fifo_size(const AVFifoBuffer *f); + +/** + * Return the amount of space in bytes in the AVFifoBuffer, that is the + * amount of data you can write into it. + * @param f AVFifoBuffer to write into + * @return size + */ +int av_fifo_space(const AVFifoBuffer *f); + +/** + * Feed data at specific position from an AVFifoBuffer to a user-supplied callback. + * Similar as av_fifo_gereric_read but without discarding data. + * @param f AVFifoBuffer to read from + * @param offset offset from current read position + * @param buf_size number of bytes to read + * @param func generic read function + * @param dest data destination + */ +int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)); + +/** + * Feed data from an AVFifoBuffer to a user-supplied callback. + * Similar as av_fifo_gereric_read but without discarding data. + * @param f AVFifoBuffer to read from + * @param buf_size number of bytes to read + * @param func generic read function + * @param dest data destination + */ +int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); + +/** + * Feed data from an AVFifoBuffer to a user-supplied callback. + * @param f AVFifoBuffer to read from + * @param buf_size number of bytes to read + * @param func generic read function + * @param dest data destination + */ +int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); + +/** + * Feed data from a user-supplied callback to an AVFifoBuffer. + * @param f AVFifoBuffer to write to + * @param src data source; non-const since it may be used as a + * modifiable context by the function defined in func + * @param size number of bytes to write + * @param func generic write function; the first parameter is src, + * the second is dest_buf, the third is dest_buf_size. + * func must return the number of bytes written to dest_buf, or <= 0 to + * indicate no more data available to write. + * If func is NULL, src is interpreted as a simple byte array for source data. + * @return the number of bytes written to the FIFO + */ +int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); + +/** + * Resize an AVFifoBuffer. + * In case of reallocation failure, the old FIFO is kept unchanged. + * + * @param f AVFifoBuffer to resize + * @param size new AVFifoBuffer size in bytes + * @return <0 for failure, >=0 otherwise + */ +int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); + +/** + * Enlarge an AVFifoBuffer. + * In case of reallocation failure, the old FIFO is kept unchanged. + * The new fifo size may be larger than the requested size. + * + * @param f AVFifoBuffer to resize + * @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size() + * @return <0 for failure, >=0 otherwise + */ +int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); + +/** + * Read and discard the specified amount of data from an AVFifoBuffer. + * @param f AVFifoBuffer to read from + * @param size amount of data to read in bytes + */ +void av_fifo_drain(AVFifoBuffer *f, int size); + +/** + * Return a pointer to the data stored in a FIFO buffer at a certain offset. + * The FIFO buffer is not modified. + * + * @param f AVFifoBuffer to peek at, f must be non-NULL + * @param offs an offset in bytes, its absolute value must be less + * than the used buffer size or the returned pointer will + * point outside to the buffer data. + * The used buffer size can be checked with av_fifo_size(). + */ +static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) +{ + uint8_t *ptr = f->rptr + offs; + if (ptr >= f->end) + ptr = f->buffer + (ptr - f->end); + else if (ptr < f->buffer) + ptr = f->end - (f->buffer - ptr); + return ptr; +} + +#endif /* AVUTIL_FIFO_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/file.h b/thirdparty/user_include/ffmpeg/libavutil/file.h new file mode 100755 index 0000000000000000000000000000000000000000..3ef4a6022cd08cb918f55a6b1c4c9facf68065c8 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/file.h @@ -0,0 +1,71 @@ +/* + * 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 + */ + +#ifndef AVUTIL_FILE_H +#define AVUTIL_FILE_H + +#include + +#include "avutil.h" + +/** + * @file + * Misc file utilities. + */ + +/** + * Read the file with name filename, and put its content in a newly + * allocated buffer or map it with mmap() when available. + * In case of success set *bufptr to the read or mmapped buffer, and + * *size to the size in bytes of the buffer in *bufptr. + * Unlike mmap this function succeeds with zero sized files, in this + * case *bufptr will be set to NULL and *size will be set to 0. + * The returned buffer must be released with av_file_unmap(). + * + * @param log_offset loglevel offset used for logging + * @param log_ctx context used for logging + * @return a non negative number in case of success, a negative value + * corresponding to an AVERROR error code in case of failure + */ +av_warn_unused_result +int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, + int log_offset, void *log_ctx); + +/** + * Unmap or free the buffer bufptr created by av_file_map(). + * + * @param size size in bytes of bufptr, must be the same as returned + * by av_file_map() + */ +void av_file_unmap(uint8_t *bufptr, size_t size); + +/** + * Wrapper to work around the lack of mkstemp() on mingw. + * Also, tries to create file in /tmp first, if possible. + * *prefix can be a character constant; *filename will be allocated internally. + * @return file descriptor of opened file (or negative value corresponding to an + * AVERROR code on error) + * and opened file name in **filename. + * @note On very old libcs it is necessary to set a secure umask before + * calling this, av_tempfile() can't call umask itself as it is used in + * libraries and could interfere with the calling application. + * @deprecated as fd numbers cannot be passed saftely between libs on some platforms + */ +int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx); + +#endif /* AVUTIL_FILE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/frame.h b/thirdparty/user_include/ffmpeg/libavutil/frame.h new file mode 100755 index 0000000000000000000000000000000000000000..5d3231e7bb68975266e1637f124bb7a284524444 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/frame.h @@ -0,0 +1,971 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_frame + * reference-counted frame API + */ + +#ifndef AVUTIL_FRAME_H +#define AVUTIL_FRAME_H + +#include +#include + +#include "avutil.h" +#include "buffer.h" +#include "dict.h" +#include "rational.h" +#include "samplefmt.h" +#include "pixfmt.h" +#include "version.h" + + +/** + * @defgroup lavu_frame AVFrame + * @ingroup lavu_data + * + * @{ + * AVFrame is an abstraction for reference-counted raw multimedia data. + */ + +enum AVFrameSideDataType { + /** + * The data is the AVPanScan struct defined in libavcodec. + */ + AV_FRAME_DATA_PANSCAN, + /** + * ATSC A53 Part 4 Closed Captions. + * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data. + * The number of bytes of CC data is AVFrameSideData.size. + */ + AV_FRAME_DATA_A53_CC, + /** + * Stereoscopic 3d metadata. + * The data is the AVStereo3D struct defined in libavutil/stereo3d.h. + */ + AV_FRAME_DATA_STEREO3D, + /** + * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h. + */ + AV_FRAME_DATA_MATRIXENCODING, + /** + * Metadata relevant to a downmix procedure. + * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. + */ + AV_FRAME_DATA_DOWNMIX_INFO, + /** + * ReplayGain information in the form of the AVReplayGain struct. + */ + AV_FRAME_DATA_REPLAYGAIN, + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the frame for correct + * presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_FRAME_DATA_DISPLAYMATRIX, + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_FRAME_DATA_AFD, + /** + * Motion vectors exported by some codecs (on demand through the export_mvs + * flag set in the libavcodec AVCodecContext flags2 option). + * The data is the AVMotionVector struct defined in + * libavutil/motion_vector.h. + */ + AV_FRAME_DATA_MOTION_VECTORS, + /** + * Recommmends skipping the specified number of samples. This is exported + * only if the "skip_manual" AVOption is set in libavcodec. + * This has the same format as AV_PKT_DATA_SKIP_SAMPLES. + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_FRAME_DATA_SKIP_SAMPLES, + /** + * This side data must be associated with an audio frame and corresponds to + * enum AVAudioServiceType defined in avcodec.h. + */ + AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + /** + * Mastering display metadata associated with a video frame. The payload is + * an AVMasteringDisplayMetadata type and contains information about the + * mastering display color volume. + */ + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, + /** + * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. + * This is set on the first frame of a GOP that has a temporal reference of 0. + */ + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This payload contains data in + * the form of the AVContentLightMetadata struct. + */ + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, + + /** + * The data contains an ICC profile as an opaque octet buffer following the + * format described by ISO 15076-1 with an optional name defined in the + * metadata key entry "name". + */ + AV_FRAME_DATA_ICC_PROFILE, + +#if FF_API_FRAME_QP + /** + * Implementation-specific description of the format of AV_FRAME_QP_TABLE_DATA. + * The contents of this side data are undocumented and internal; use + * av_frame_set_qp_table() and av_frame_get_qp_table() to access this in a + * meaningful way instead. + */ + AV_FRAME_DATA_QP_TABLE_PROPERTIES, + + /** + * Raw QP table data. Its format is described by + * AV_FRAME_DATA_QP_TABLE_PROPERTIES. Use av_frame_set_qp_table() and + * av_frame_get_qp_table() to access this instead. + */ + AV_FRAME_DATA_QP_TABLE_DATA, +#endif + + /** + * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.c. + */ + AV_FRAME_DATA_S12M_TIMECODE, + + /** + * HDR dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRPlus type and contains information for color + * volume transform - application 4 of SMPTE 2094-40:2016 standard. + */ + AV_FRAME_DATA_DYNAMIC_HDR_PLUS, + + /** + * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of + * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. + */ + AV_FRAME_DATA_REGIONS_OF_INTEREST, +}; + +enum AVActiveFormatDescription { + AV_AFD_SAME = 8, + AV_AFD_4_3 = 9, + AV_AFD_16_9 = 10, + AV_AFD_14_9 = 11, + AV_AFD_4_3_SP_14_9 = 13, + AV_AFD_16_9_SP_14_9 = 14, + AV_AFD_SP_4_3 = 15, +}; + + +/** + * Structure to hold side data for an AVFrame. + * + * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + */ +typedef struct AVFrameSideData { + enum AVFrameSideDataType type; + uint8_t *data; + int size; + AVDictionary *metadata; + AVBufferRef *buf; +} AVFrameSideData; + +/** + * Structure describing a single Region Of Interest. + * + * When multiple regions are defined in a single side-data block, they + * should be ordered from most to least important - some encoders are only + * capable of supporting a limited number of distinct regions, so will have + * to truncate the list. + * + * When overlapping regions are defined, the first region containing a given + * area of the frame applies. + */ +typedef struct AVRegionOfInterest { + /** + * Must be set to the size of this data structure (that is, + * sizeof(AVRegionOfInterest)). + */ + uint32_t self_size; + /** + * Distance in pixels from the top edge of the frame to the top and + * bottom edges and from the left edge of the frame to the left and + * right edges of the rectangle defining this region of interest. + * + * The constraints on a region are encoder dependent, so the region + * actually affected may be slightly larger for alignment or other + * reasons. + */ + int top; + int bottom; + int left; + int right; + /** + * Quantisation offset. + * + * Must be in the range -1 to +1. A value of zero indicates no quality + * change. A negative value asks for better quality (less quantisation), + * while a positive value asks for worse quality (greater quantisation). + * + * The range is calibrated so that the extreme values indicate the + * largest possible offset - if the rest of the frame is encoded with the + * worst possible quality, an offset of -1 indicates that this region + * should be encoded with the best possible quality anyway. Intermediate + * values are then interpolated in some codec-dependent way. + * + * For example, in 10-bit H.264 the quantisation parameter varies between + * -12 and 51. A typical qoffset value of -1/10 therefore indicates that + * this region should be encoded with a QP around one-tenth of the full + * range better than the rest of the frame. So, if most of the frame + * were to be encoded with a QP of around 30, this region would get a QP + * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). + * An extreme value of -1 would indicate that this region should be + * encoded with the best possible quality regardless of the treatment of + * the rest of the frame - that is, should be encoded at a QP of -12. + */ + AVRational qoffset; +} AVRegionOfInterest; + +/** + * This structure describes decoded (raw) audio or video data. + * + * AVFrame must be allocated using av_frame_alloc(). Note that this only + * allocates the AVFrame itself, the buffers for the data must be managed + * through other means (see below). + * AVFrame must be freed with av_frame_free(). + * + * AVFrame is typically allocated once and then reused multiple times to hold + * different data (e.g. a single AVFrame to hold frames received from a + * decoder). In such a case, av_frame_unref() will free any references held by + * the frame and reset it to its original clean state before it + * is reused again. + * + * The data described by an AVFrame is usually reference counted through the + * AVBuffer API. The underlying buffer references are stored in AVFrame.buf / + * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at + * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, + * every single data plane must be contained in one of the buffers in + * AVFrame.buf or AVFrame.extended_buf. + * There may be a single buffer for all the data, or one separate buffer for + * each plane, or anything in between. + * + * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added + * to the end with a minor bump. + * + * Fields can be accessed through AVOptions, the name string used, matches the + * C structure field name for fields accessible through AVOptions. The AVClass + * for AVFrame can be obtained from avcodec_get_frame_class() + */ +typedef struct AVFrame { +#define AV_NUM_DATA_POINTERS 8 + /** + * pointer to the picture/channel planes. + * This might be different from the first allocated byte + * + * Some decoders access areas outside 0,0 - width,height, please + * see avcodec_align_dimensions2(). Some filters and swscale can read + * up to 16 bytes beyond the planes, if these filters are to be used, + * then 16 extra bytes must be allocated. + * + * NOTE: Except for hwaccel formats, pointers not needed by the format + * MUST be set to NULL. + */ + uint8_t *data[AV_NUM_DATA_POINTERS]; + + /** + * For video, size in bytes of each picture line. + * For audio, size in bytes of each plane. + * + * For audio, only linesize[0] may be set. For planar audio, each channel + * plane must be the same size. + * + * For video the linesizes should be multiples of the CPUs alignment + * preference, this is 16 or 32 for modern desktop CPUs. + * Some code requires such alignment other code can be slower without + * correct alignment, for yet other it makes no difference. + * + * @note The linesize may be larger than the size of usable data -- there + * may be extra padding present for performance reasons. + */ + int linesize[AV_NUM_DATA_POINTERS]; + + /** + * pointers to the data planes/channels. + * + * For video, this should simply point to data[]. + * + * For planar audio, each channel has a separate data pointer, and + * linesize[0] contains the size of each channel buffer. + * For packed audio, there is just one data pointer, and linesize[0] + * contains the total size of the buffer for all channels. + * + * Note: Both data and extended_data should always be set in a valid frame, + * but for planar audio with more channels that can fit in data, + * extended_data must be used in order to access all channels. + */ + uint8_t **extended_data; + + /** + * @name Video dimensions + * Video frames only. The coded dimensions (in pixels) of the video frame, + * i.e. the size of the rectangle that contains some well-defined values. + * + * @note The part of the frame intended for display/presentation is further + * restricted by the @ref cropping "Cropping rectangle". + * @{ + */ + int width, height; + /** + * @} + */ + + /** + * number of audio samples (per channel) described by this frame + */ + int nb_samples; + + /** + * format of the frame, -1 if unknown or unset + * Values correspond to enum AVPixelFormat for video frames, + * enum AVSampleFormat for audio) + */ + int format; + + /** + * 1 -> keyframe, 0-> not + */ + int key_frame; + + /** + * Picture type of the frame. + */ + enum AVPictureType pict_type; + + /** + * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. + */ + AVRational sample_aspect_ratio; + + /** + * Presentation timestamp in time_base units (time when frame should be shown to user). + */ + int64_t pts; + +#if FF_API_PKT_PTS + /** + * PTS copied from the AVPacket that was decoded to produce this frame. + * @deprecated use the pts field instead + */ + attribute_deprecated + int64_t pkt_pts; +#endif + + /** + * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) + * This is also the Presentation time of this AVFrame calculated from + * only AVPacket.dts values without pts values. + */ + int64_t pkt_dts; + + /** + * picture number in bitstream order + */ + int coded_picture_number; + /** + * picture number in display order + */ + int display_picture_number; + + /** + * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) + */ + int quality; + + /** + * for some private data of the user + */ + void *opaque; + +#if FF_API_ERROR_FRAME + /** + * @deprecated unused + */ + attribute_deprecated + uint64_t error[AV_NUM_DATA_POINTERS]; +#endif + + /** + * When decoding, this signals how much the picture must be delayed. + * extra_delay = repeat_pict / (2*fps) + */ + int repeat_pict; + + /** + * The content of the picture is interlaced. + */ + int interlaced_frame; + + /** + * If the content is interlaced, is top field displayed first. + */ + int top_field_first; + + /** + * Tell user application that palette has changed from previous frame. + */ + int palette_has_changed; + + /** + * reordered opaque 64 bits (generally an integer or a double precision float + * PTS but can be anything). + * The user sets AVCodecContext.reordered_opaque to represent the input at + * that time, + * the decoder reorders values as needed and sets AVFrame.reordered_opaque + * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque + */ + int64_t reordered_opaque; + + /** + * Sample rate of the audio data. + */ + int sample_rate; + + /** + * Channel layout of the audio data. + */ + uint64_t channel_layout; + + /** + * AVBuffer references backing the data for this frame. If all elements of + * this array are NULL, then this frame is not reference counted. This array + * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must + * also be non-NULL for all j < i. + * + * There may be at most one AVBuffer per data plane, so for video this array + * always contains all the references. For planar audio with more than + * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in + * this array. Then the extra AVBufferRef pointers are stored in the + * extended_buf array. + */ + AVBufferRef *buf[AV_NUM_DATA_POINTERS]; + + /** + * For planar audio which requires more than AV_NUM_DATA_POINTERS + * AVBufferRef pointers, this array will hold all the references which + * cannot fit into AVFrame.buf. + * + * Note that this is different from AVFrame.extended_data, which always + * contains all the pointers. This array only contains the extra pointers, + * which cannot fit into AVFrame.buf. + * + * This array is always allocated using av_malloc() by whoever constructs + * the frame. It is freed in av_frame_unref(). + */ + AVBufferRef **extended_buf; + /** + * Number of elements in extended_buf. + */ + int nb_extended_buf; + + AVFrameSideData **side_data; + int nb_side_data; + +/** + * @defgroup lavu_frame_flags AV_FRAME_FLAGS + * @ingroup lavu_frame + * Flags describing additional frame properties. + * + * @{ + */ + +/** + * The frame data may be corrupted, e.g. due to decoding errors. + */ +#define AV_FRAME_FLAG_CORRUPT (1 << 0) +/** + * A flag to mark the frames which need to be decoded, but shouldn't be output. + */ +#define AV_FRAME_FLAG_DISCARD (1 << 2) +/** + * @} + */ + + /** + * Frame flags, a combination of @ref lavu_frame_flags + */ + int flags; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + enum AVColorPrimaries color_primaries; + + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + enum AVChromaLocation chroma_location; + + /** + * frame timestamp estimated using various heuristics, in stream time base + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int64_t best_effort_timestamp; + + /** + * reordered pos from the last AVPacket that has been input into the decoder + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pos; + + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_duration; + + /** + * metadata. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVDictionary *metadata; + + /** + * decode error flags of the frame, set to a combination of + * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there + * were errors during the decoding. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int decode_error_flags; +#define FF_DECODE_ERROR_INVALID_BITSTREAM 1 +#define FF_DECODE_ERROR_MISSING_REFERENCE 2 +#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 +#define FF_DECODE_ERROR_DECODE_SLICES 8 + + /** + * number of audio channels, only used for audio. + * - encoding: unused + * - decoding: Read by user. + */ + int channels; + + /** + * size of the corresponding packet containing the compressed + * frame. + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int pkt_size; + +#if FF_API_FRAME_QP + /** + * QP table + */ + attribute_deprecated + int8_t *qscale_table; + /** + * QP store stride + */ + attribute_deprecated + int qstride; + + attribute_deprecated + int qscale_type; + + attribute_deprecated + AVBufferRef *qp_table_buf; +#endif + /** + * For hwaccel-format frames, this should be a reference to the + * AVHWFramesContext describing the frame. + */ + AVBufferRef *hw_frames_ctx; + + /** + * AVBufferRef for free use by the API user. FFmpeg will never check the + * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when + * the frame is unreferenced. av_frame_copy_props() calls create a new + * reference with av_buffer_ref() for the target frame's opaque_ref field. + * + * This is unrelated to the opaque field, although it serves a similar + * purpose. + */ + AVBufferRef *opaque_ref; + + /** + * @anchor cropping + * @name Cropping + * Video frames only. The number of pixels to discard from the the + * top/bottom/left/right border of the frame to obtain the sub-rectangle of + * the frame intended for presentation. + * @{ + */ + size_t crop_top; + size_t crop_bottom; + size_t crop_left; + size_t crop_right; + /** + * @} + */ + + /** + * AVBufferRef for internal use by a single libav* library. + * Must not be used to transfer data between libraries. + * Has to be NULL when ownership of the frame leaves the respective library. + * + * Code outside the FFmpeg libs should never check or change the contents of the buffer ref. + * + * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced. + * av_frame_copy_props() calls create a new reference with av_buffer_ref() + * for the target frame's private_ref field. + */ + AVBufferRef *private_ref; +} AVFrame; + +#if FF_API_FRAME_GET_SET +/** + * Accessors for some AVFrame fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame); +attribute_deprecated +void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_pkt_duration (const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_duration (AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_pkt_pos (const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_pos (AVFrame *frame, int64_t val); +attribute_deprecated +int64_t av_frame_get_channel_layout (const AVFrame *frame); +attribute_deprecated +void av_frame_set_channel_layout (AVFrame *frame, int64_t val); +attribute_deprecated +int av_frame_get_channels (const AVFrame *frame); +attribute_deprecated +void av_frame_set_channels (AVFrame *frame, int val); +attribute_deprecated +int av_frame_get_sample_rate (const AVFrame *frame); +attribute_deprecated +void av_frame_set_sample_rate (AVFrame *frame, int val); +attribute_deprecated +AVDictionary *av_frame_get_metadata (const AVFrame *frame); +attribute_deprecated +void av_frame_set_metadata (AVFrame *frame, AVDictionary *val); +attribute_deprecated +int av_frame_get_decode_error_flags (const AVFrame *frame); +attribute_deprecated +void av_frame_set_decode_error_flags (AVFrame *frame, int val); +attribute_deprecated +int av_frame_get_pkt_size(const AVFrame *frame); +attribute_deprecated +void av_frame_set_pkt_size(AVFrame *frame, int val); +#if FF_API_FRAME_QP +attribute_deprecated +int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type); +attribute_deprecated +int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type); +#endif +attribute_deprecated +enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame); +attribute_deprecated +void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val); +attribute_deprecated +enum AVColorRange av_frame_get_color_range(const AVFrame *frame); +attribute_deprecated +void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val); +#endif + +/** + * Get the name of a colorspace. + * @return a static string identifying the colorspace; can be NULL. + */ +const char *av_get_colorspace_name(enum AVColorSpace val); + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using av_frame_free(). + * + * @return An AVFrame filled with default values or NULL on failure. + * + * @note this only allocates the AVFrame itself, not the data buffers. Those + * must be allocated through other means, e.g. with av_frame_get_buffer() or + * manually. + */ +AVFrame *av_frame_alloc(void); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. If the frame is reference counted, it will be + * unreferenced first. + * + * @param frame frame to be freed. The pointer will be set to NULL. + */ +void av_frame_free(AVFrame **frame); + +/** + * Set up a new reference to the data described by the source frame. + * + * Copy frame properties from src to dst and create a new reference for each + * AVBufferRef from src. + * + * If src is not reference counted, new buffers are allocated and the data is + * copied. + * + * @warning: dst MUST have been either unreferenced with av_frame_unref(dst), + * or newly allocated with av_frame_alloc() before calling this + * function, or undefined behavior will occur. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_frame_ref(AVFrame *dst, const AVFrame *src); + +/** + * Create a new frame that references the same data as src. + * + * This is a shortcut for av_frame_alloc()+av_frame_ref(). + * + * @return newly created AVFrame on success, NULL on error. + */ +AVFrame *av_frame_clone(const AVFrame *src); + +/** + * Unreference all the buffers referenced by frame and reset the frame fields. + */ +void av_frame_unref(AVFrame *frame); + +/** + * Move everything contained in src to dst and reset src. + * + * @warning: dst is not unreferenced, but directly overwritten without reading + * or deallocating its contents. Call av_frame_unref(dst) manually + * before calling this function to ensure that no memory is leaked. + */ +void av_frame_move_ref(AVFrame *dst, AVFrame *src); + +/** + * Allocate new buffer(s) for audio or video data. + * + * The following fields must be set on frame before calling this function: + * - format (pixel format for video, sample format for audio) + * - width and height for video + * - nb_samples and channel_layout for audio + * + * This function will fill AVFrame.data and AVFrame.buf arrays and, if + * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. + * For planar formats, one buffer will be allocated for each plane. + * + * @warning: if frame already has been allocated, calling this function will + * leak memory. In addition, undefined behavior can occur in certain + * cases. + * + * @param frame frame in which to store the new buffers. + * @param align Required buffer size alignment. If equal to 0, alignment will be + * chosen automatically for the current CPU. It is highly + * recommended to pass 0 here unless you know what you are doing. + * + * @return 0 on success, a negative AVERROR on error. + */ +int av_frame_get_buffer(AVFrame *frame, int align); + +/** + * Check if the frame data is writable. + * + * @return A positive value if the frame data is writable (which is true if and + * only if each of the underlying buffers has only one reference, namely the one + * stored in this frame). Return 0 otherwise. + * + * If 1 is returned the answer is valid until av_buffer_ref() is called on any + * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly). + * + * @see av_frame_make_writable(), av_buffer_is_writable() + */ +int av_frame_is_writable(AVFrame *frame); + +/** + * Ensure that the frame data is writable, avoiding data copy if possible. + * + * Do nothing if the frame is writable, allocate new buffers and copy the data + * if it is not. + * + * @return 0 on success, a negative AVERROR on error. + * + * @see av_frame_is_writable(), av_buffer_is_writable(), + * av_buffer_make_writable() + */ +int av_frame_make_writable(AVFrame *frame); + +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + +/** + * Copy only "metadata" fields from src to dst. + * + * Metadata for the purpose of this function are those fields that do not affect + * the data layout in the buffers. E.g. pts, sample rate (for audio) or sample + * aspect ratio (for video), but not width/height or channel layout. + * Side data is also copied. + */ +int av_frame_copy_props(AVFrame *dst, const AVFrame *src); + +/** + * Get the buffer reference a given data plane is stored in. + * + * @param plane index of the data plane of interest in frame->extended_data. + * + * @return the buffer reference that contains the plane or NULL if the input + * frame is not valid. + */ +AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane); + +/** + * Add a new side data to a frame. + * + * @param frame a frame to which the side data should be added + * @param type type of the added side data + * @param size size of the side data + * + * @return newly added side data on success, NULL on error + */ +AVFrameSideData *av_frame_new_side_data(AVFrame *frame, + enum AVFrameSideDataType type, + int size); + +/** + * Add a new side data to a frame from an existing AVBufferRef + * + * @param frame a frame to which the side data should be added + * @param type the type of the added side data + * @param buf an AVBufferRef to add as side data. The ownership of + * the reference is transferred to the frame. + * + * @return newly added side data on success, NULL on error. On failure + * the frame is unchanged and the AVBufferRef remains owned by + * the caller. + */ +AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame, + enum AVFrameSideDataType type, + AVBufferRef *buf); + +/** + * @return a pointer to the side data of a given type on success, NULL if there + * is no side data with such type in this frame. + */ +AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, + enum AVFrameSideDataType type); + +/** + * If side data of the supplied type exists in the frame, free it and remove it + * from the frame. + */ +void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); + + +/** + * Flags for frame cropping. + */ +enum { + /** + * Apply the maximum possible cropping, even if it requires setting the + * AVFrame.data[] entries to unaligned pointers. Passing unaligned data + * to FFmpeg API is generally not allowed, and causes undefined behavior + * (such as crashes). You can pass unaligned data only to FFmpeg APIs that + * are explicitly documented to accept it. Use this flag only if you + * absolutely know what you are doing. + */ + AV_FRAME_CROP_UNALIGNED = 1 << 0, +}; + +/** + * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/ + * crop_bottom fields. If cropping is successful, the function will adjust the + * data pointers and the width/height fields, and set the crop fields to 0. + * + * In all cases, the cropping boundaries will be rounded to the inherent + * alignment of the pixel format. In some cases, such as for opaque hwaccel + * formats, the left/top cropping is ignored. The crop fields are set to 0 even + * if the cropping was rounded or ignored. + * + * @param frame the frame which should be cropped + * @param flags Some combination of AV_FRAME_CROP_* flags, or 0. + * + * @return >= 0 on success, a negative AVERROR on error. If the cropping fields + * were invalid, AVERROR(ERANGE) is returned, and nothing is changed. + */ +int av_frame_apply_cropping(AVFrame *frame, int flags); + +/** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** + * @} + */ + +#endif /* AVUTIL_FRAME_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hash.h b/thirdparty/user_include/ffmpeg/libavutil/hash.h new file mode 100755 index 0000000000000000000000000000000000000000..7693e6bf0dbca59d878755c786a38c11647e5848 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hash.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2013 Reimar Döffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_hash_generic + * Generic hashing API + */ + +#ifndef AVUTIL_HASH_H +#define AVUTIL_HASH_H + +#include + +#include "version.h" + +/** + * @defgroup lavu_hash Hash Functions + * @ingroup lavu_crypto + * Hash functions useful in multimedia. + * + * Hash functions are widely used in multimedia, from error checking and + * concealment to internal regression testing. libavutil has efficient + * implementations of a variety of hash functions that may be useful for + * FFmpeg and other multimedia applications. + * + * @{ + * + * @defgroup lavu_hash_generic Generic Hashing API + * An abstraction layer for all hash functions supported by libavutil. + * + * If your application needs to support a wide range of different hash + * functions, then the Generic Hashing API is for you. It provides a generic, + * reusable API for @ref lavu_hash "all hash functions" implemented in libavutil. + * If you just need to use one particular hash function, use the @ref lavu_hash + * "individual hash" directly. + * + * @section Sample Code + * + * A basic template for using the Generic Hashing API follows: + * + * @code + * struct AVHashContext *ctx = NULL; + * const char *hash_name = NULL; + * uint8_t *output_buf = NULL; + * + * // Select from a string returned by av_hash_names() + * hash_name = ...; + * + * // Allocate a hash context + * ret = av_hash_alloc(&ctx, hash_name); + * if (ret < 0) + * return ret; + * + * // Initialize the hash context + * av_hash_init(ctx); + * + * // Update the hash context with data + * while (data_left) { + * av_hash_update(ctx, data, size); + * } + * + * // Now we have no more data, so it is time to finalize the hash and get the + * // output. But we need to first allocate an output buffer. Note that you can + * // use any memory allocation function, including malloc(), not just + * // av_malloc(). + * output_buf = av_malloc(av_hash_get_size(ctx)); + * if (!output_buf) + * return AVERROR(ENOMEM); + * + * // Finalize the hash context. + * // You can use any of the av_hash_final*() functions provided, for other + * // output formats. If you do so, be sure to adjust the memory allocation + * // above. See the function documentation below for the exact amount of extra + * // memory needed. + * av_hash_final(ctx, output_buffer); + * + * // Free the context + * av_hash_freep(&ctx); + * @endcode + * + * @section Hash Function-Specific Information + * If the CRC32 hash is selected, the #AV_CRC_32_IEEE polynomial will be + * used. + * + * If the Murmur3 hash is selected, the default seed will be used. See @ref + * lavu_murmur3_seedinfo "Murmur3" for more information. + * + * @{ + */ + +/** + * @example ffhash.c + * This example is a simple command line application that takes one or more + * arguments. It demonstrates a typical use of the hashing API with allocation, + * initialization, updating, and finalizing. + */ + +struct AVHashContext; + +/** + * Allocate a hash context for the algorithm specified by name. + * + * @return >= 0 for success, a negative error code for failure + * + * @note The context is not initialized after a call to this function; you must + * call av_hash_init() to do so. + */ +int av_hash_alloc(struct AVHashContext **ctx, const char *name); + +/** + * Get the names of available hash algorithms. + * + * This function can be used to enumerate the algorithms. + * + * @param[in] i Index of the hash algorithm, starting from 0 + * @return Pointer to a static string or `NULL` if `i` is out of range + */ +const char *av_hash_names(int i); + +/** + * Get the name of the algorithm corresponding to the given hash context. + */ +const char *av_hash_get_name(const struct AVHashContext *ctx); + +/** + * Maximum value that av_hash_get_size() will currently return. + * + * You can use this if you absolutely want or need to use static allocation for + * the output buffer and are fine with not supporting hashes newly added to + * libavutil without recompilation. + * + * @warning + * Adding new hashes with larger sizes, and increasing the macro while doing + * so, will not be considered an ABI change. To prevent your code from + * overflowing a buffer, either dynamically allocate the output buffer with + * av_hash_get_size(), or limit your use of the Hashing API to hashes that are + * already in FFmpeg during the time of compilation. + */ +#define AV_HASH_MAX_SIZE 64 + +/** + * Get the size of the resulting hash value in bytes. + * + * The maximum value this function will currently return is available as macro + * #AV_HASH_MAX_SIZE. + * + * @param[in] ctx Hash context + * @return Size of the hash value in bytes + */ +int av_hash_get_size(const struct AVHashContext *ctx); + +/** + * Initialize or reset a hash context. + * + * @param[in,out] ctx Hash context + */ +void av_hash_init(struct AVHashContext *ctx); + +/** + * Update a hash context with additional data. + * + * @param[in,out] ctx Hash context + * @param[in] src Data to be added to the hash context + * @param[in] len Size of the additional data + */ +#if FF_API_CRYPTO_SIZE_T +void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len); +#else +void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, size_t len); +#endif + +/** + * Finalize a hash context and compute the actual hash value. + * + * The minimum size of `dst` buffer is given by av_hash_get_size() or + * #AV_HASH_MAX_SIZE. The use of the latter macro is discouraged. + * + * It is not safe to update or finalize a hash context again, if it has already + * been finalized. + * + * @param[in,out] ctx Hash context + * @param[out] dst Where the final hash value will be stored + * + * @see av_hash_final_bin() provides an alternative API + */ +void av_hash_final(struct AVHashContext *ctx, uint8_t *dst); + +/** + * Finalize a hash context and store the actual hash value in a buffer. + * + * It is not safe to update or finalize a hash context again, if it has already + * been finalized. + * + * If `size` is smaller than the hash size (given by av_hash_get_size()), the + * hash is truncated; if size is larger, the buffer is padded with 0. + * + * @param[in,out] ctx Hash context + * @param[out] dst Where the final hash value will be stored + * @param[in] size Number of bytes to write to `dst` + */ +void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and store the hexadecimal representation of the + * actual hash value as a string. + * + * It is not safe to update or finalize a hash context again, if it has already + * been finalized. + * + * The string is always 0-terminated. + * + * If `size` is smaller than `2 * hash_size + 1`, where `hash_size` is the + * value returned by av_hash_get_size(), the string will be truncated. + * + * @param[in,out] ctx Hash context + * @param[out] dst Where the string will be stored + * @param[in] size Maximum number of bytes to write to `dst` + */ +void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and store the Base64 representation of the + * actual hash value as a string. + * + * It is not safe to update or finalize a hash context again, if it has already + * been finalized. + * + * The string is always 0-terminated. + * + * If `size` is smaller than AV_BASE64_SIZE(hash_size), where `hash_size` is + * the value returned by av_hash_get_size(), the string will be truncated. + * + * @param[in,out] ctx Hash context + * @param[out] dst Where the final hash value will be stored + * @param[in] size Maximum number of bytes to write to `dst` + */ +void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Free hash context and set hash context pointer to `NULL`. + * + * @param[in,out] ctx Pointer to hash context + */ +void av_hash_freep(struct AVHashContext **ctx); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_HASH_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hdr_dynamic_metadata.h b/thirdparty/user_include/ffmpeg/libavutil/hdr_dynamic_metadata.h new file mode 100755 index 0000000000000000000000000000000000000000..2d72de56aecd858fa3cc1e54b3918a2ecad79108 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hdr_dynamic_metadata.h @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2018 Mohammad Izadi + * + * 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 + */ + +#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H +#define AVUTIL_HDR_DYNAMIC_METADATA_H + +#include "frame.h" +#include "rational.h" + +/** + * Option for overlapping elliptical pixel selectors in an image. + */ +enum AVHDRPlusOverlapProcessOption { + AV_HDR_PLUS_OVERLAP_PROCESS_WEIGHTED_AVERAGING = 0, + AV_HDR_PLUS_OVERLAP_PROCESS_LAYERING = 1, +}; + +/** + * Represents the percentile at a specific percentage in + * a distribution. + */ +typedef struct AVHDRPlusPercentile { + /** + * The percentage value corresponding to a specific percentile linearized + * RGB value in the processing window in the scene. The value shall be in + * the range of 0 to100, inclusive. + */ + uint8_t percentage; + + /** + * The linearized maxRGB value at a specific percentile in the processing + * window in the scene. The value shall be in the range of 0 to 1, inclusive + * and in multiples of 0.00001. + */ + AVRational percentile; +} AVHDRPlusPercentile; + +/** + * Color transform parameters at a processing window in a dynamic metadata for + * SMPTE 2094-40. + */ +typedef struct AVHDRPlusColorTransformParams { + /** + * The relative x coordinate of the top left pixel of the processing + * window. The value shall be in the range of 0 and 1, inclusive and + * in multiples of 1/(width of Picture - 1). The value 1 corresponds + * to the absolute coordinate of width of Picture - 1. The value for + * first processing window shall be 0. + */ + AVRational window_upper_left_corner_x; + + /** + * The relative y coordinate of the top left pixel of the processing + * window. The value shall be in the range of 0 and 1, inclusive and + * in multiples of 1/(height of Picture - 1). The value 1 corresponds + * to the absolute coordinate of height of Picture - 1. The value for + * first processing window shall be 0. + */ + AVRational window_upper_left_corner_y; + + /** + * The relative x coordinate of the bottom right pixel of the processing + * window. The value shall be in the range of 0 and 1, inclusive and + * in multiples of 1/(width of Picture - 1). The value 1 corresponds + * to the absolute coordinate of width of Picture - 1. The value for + * first processing window shall be 1. + */ + AVRational window_lower_right_corner_x; + + /** + * The relative y coordinate of the bottom right pixel of the processing + * window. The value shall be in the range of 0 and 1, inclusive and + * in multiples of 1/(height of Picture - 1). The value 1 corresponds + * to the absolute coordinate of height of Picture - 1. The value for + * first processing window shall be 1. + */ + AVRational window_lower_right_corner_y; + + /** + * The x coordinate of the center position of the concentric internal and + * external ellipses of the elliptical pixel selector in the processing + * window. The value shall be in the range of 0 to (width of Picture - 1), + * inclusive and in multiples of 1 pixel. + */ + uint16_t center_of_ellipse_x; + + /** + * The y coordinate of the center position of the concentric internal and + * external ellipses of the elliptical pixel selector in the processing + * window. The value shall be in the range of 0 to (height of Picture - 1), + * inclusive and in multiples of 1 pixel. + */ + uint16_t center_of_ellipse_y; + + /** + * The clockwise rotation angle in degree of arc with respect to the + * positive direction of the x-axis of the concentric internal and external + * ellipses of the elliptical pixel selector in the processing window. The + * value shall be in the range of 0 to 180, inclusive and in multiples of 1. + */ + uint8_t rotation_angle; + + /** + * The semi-major axis value of the internal ellipse of the elliptical pixel + * selector in amount of pixels in the processing window. The value shall be + * in the range of 1 to 65535, inclusive and in multiples of 1 pixel. + */ + uint16_t semimajor_axis_internal_ellipse; + + /** + * The semi-major axis value of the external ellipse of the elliptical pixel + * selector in amount of pixels in the processing window. The value + * shall not be less than semimajor_axis_internal_ellipse of the current + * processing window. The value shall be in the range of 1 to 65535, + * inclusive and in multiples of 1 pixel. + */ + uint16_t semimajor_axis_external_ellipse; + + /** + * The semi-minor axis value of the external ellipse of the elliptical pixel + * selector in amount of pixels in the processing window. The value shall be + * in the range of 1 to 65535, inclusive and in multiples of 1 pixel. + */ + uint16_t semiminor_axis_external_ellipse; + + /** + * Overlap process option indicates one of the two methods of combining + * rendered pixels in the processing window in an image with at least one + * elliptical pixel selector. For overlapping elliptical pixel selectors + * in an image, overlap_process_option shall have the same value. + */ + enum AVHDRPlusOverlapProcessOption overlap_process_option; + + /** + * The maximum of the color components of linearized RGB values in the + * processing window in the scene. The values should be in the range of 0 to + * 1, inclusive and in multiples of 0.00001. maxscl[ 0 ], maxscl[ 1 ], and + * maxscl[ 2 ] are corresponding to R, G, B color components respectively. + */ + AVRational maxscl[3]; + + /** + * The average of linearized maxRGB values in the processing window in the + * scene. The value should be in the range of 0 to 1, inclusive and in + * multiples of 0.00001. + */ + AVRational average_maxrgb; + + /** + * The number of linearized maxRGB values at given percentiles in the + * processing window in the scene. The maximum value shall be 15. + */ + uint8_t num_distribution_maxrgb_percentiles; + + /** + * The linearized maxRGB values at given percentiles in the + * processing window in the scene. + */ + AVHDRPlusPercentile distribution_maxrgb[15]; + + /** + * The fraction of selected pixels in the image that contains the brightest + * pixel in the scene. The value shall be in the range of 0 to 1, inclusive + * and in multiples of 0.001. + */ + AVRational fraction_bright_pixels; + + /** + * This flag indicates that the metadata for the tone mapping function in + * the processing window is present (for value of 1). + */ + uint8_t tone_mapping_flag; + + /** + * The x coordinate of the separation point between the linear part and the + * curved part of the tone mapping function. The value shall be in the range + * of 0 to 1, excluding 0 and in multiples of 1/4095. + */ + AVRational knee_point_x; + + /** + * The y coordinate of the separation point between the linear part and the + * curved part of the tone mapping function. The value shall be in the range + * of 0 to 1, excluding 0 and in multiples of 1/4095. + */ + AVRational knee_point_y; + + /** + * The number of the intermediate anchor parameters of the tone mapping + * function in the processing window. The maximum value shall be 15. + */ + uint8_t num_bezier_curve_anchors; + + /** + * The intermediate anchor parameters of the tone mapping function in the + * processing window in the scene. The values should be in the range of 0 + * to 1, inclusive and in multiples of 1/1023. + */ + AVRational bezier_curve_anchors[15]; + + /** + * This flag shall be equal to 0 in bitstreams conforming to this version of + * this Specification. Other values are reserved for future use. + */ + uint8_t color_saturation_mapping_flag; + + /** + * The color saturation gain in the processing window in the scene. The + * value shall be in the range of 0 to 63/8, inclusive and in multiples of + * 1/8. The default value shall be 1. + */ + AVRational color_saturation_weight; +} AVHDRPlusColorTransformParams; + +/** + * This struct represents dynamic metadata for color volume transform - + * application 4 of SMPTE 2094-40:2016 standard. + * + * To be used as payload of a AVFrameSideData or AVPacketSideData with the + * appropriate type. + * + * @note The struct should be allocated with + * av_dynamic_hdr_plus_alloc() and its size is not a part of + * the public ABI. + */ +typedef struct AVDynamicHDRPlus { + /** + * Country code by Rec. ITU-T T.35 Annex A. The value shall be 0xB5. + */ + uint8_t itu_t_t35_country_code; + + /** + * Application version in the application defining document in ST-2094 + * suite. The value shall be set to 0. + */ + uint8_t application_version; + + /** + * The number of processing windows. The value shall be in the range + * of 1 to 3, inclusive. + */ + uint8_t num_windows; + + /** + * The color transform parameters for every processing window. + */ + AVHDRPlusColorTransformParams params[3]; + + /** + * The nominal maximum display luminance of the targeted system display, + * in units of 0.0001 candelas per square metre. The value shall be in + * the range of 0 to 10000, inclusive. + */ + AVRational targeted_system_display_maximum_luminance; + + /** + * This flag shall be equal to 0 in bit streams conforming to this version + * of this Specification. The value 1 is reserved for future use. + */ + uint8_t targeted_system_display_actual_peak_luminance_flag; + + /** + * The number of rows in the targeted system_display_actual_peak_luminance + * array. The value shall be in the range of 2 to 25, inclusive. + */ + uint8_t num_rows_targeted_system_display_actual_peak_luminance; + + /** + * The number of columns in the + * targeted_system_display_actual_peak_luminance array. The value shall be + * in the range of 2 to 25, inclusive. + */ + uint8_t num_cols_targeted_system_display_actual_peak_luminance; + + /** + * The normalized actual peak luminance of the targeted system display. The + * values should be in the range of 0 to 1, inclusive and in multiples of + * 1/15. + */ + AVRational targeted_system_display_actual_peak_luminance[25][25]; + + /** + * This flag shall be equal to 0 in bitstreams conforming to this version of + * this Specification. The value 1 is reserved for future use. + */ + uint8_t mastering_display_actual_peak_luminance_flag; + + /** + * The number of rows in the mastering_display_actual_peak_luminance array. + * The value shall be in the range of 2 to 25, inclusive. + */ + uint8_t num_rows_mastering_display_actual_peak_luminance; + + /** + * The number of columns in the mastering_display_actual_peak_luminance + * array. The value shall be in the range of 2 to 25, inclusive. + */ + uint8_t num_cols_mastering_display_actual_peak_luminance; + + /** + * The normalized actual peak luminance of the mastering display used for + * mastering the image essence. The values should be in the range of 0 to 1, + * inclusive and in multiples of 1/15. + */ + AVRational mastering_display_actual_peak_luminance[25][25]; +} AVDynamicHDRPlus; + +/** + * Allocate an AVDynamicHDRPlus structure and set its fields to + * default values. The resulting struct can be freed using av_freep(). + * + * @return An AVDynamicHDRPlus filled with default values or NULL + * on failure. + */ +AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size); + +/** + * Allocate a complete AVDynamicHDRPlus and add it to the frame. + * @param frame The frame which side data is added to. + * + * @return The AVDynamicHDRPlus structure to be filled by caller or NULL + * on failure. + */ +AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame); + +#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hmac.h b/thirdparty/user_include/ffmpeg/libavutil/hmac.h new file mode 100755 index 0000000000000000000000000000000000000000..412e950719ba5391989c2936d9c73b6a4823b658 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hmac.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012 Martin Storsjo + * + * 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 + */ + +#ifndef AVUTIL_HMAC_H +#define AVUTIL_HMAC_H + +#include + +#include "version.h" +/** + * @defgroup lavu_hmac HMAC + * @ingroup lavu_crypto + * @{ + */ + +enum AVHMACType { + AV_HMAC_MD5, + AV_HMAC_SHA1, + AV_HMAC_SHA224, + AV_HMAC_SHA256, + AV_HMAC_SHA384, + AV_HMAC_SHA512, +}; + +typedef struct AVHMAC AVHMAC; + +/** + * Allocate an AVHMAC context. + * @param type The hash function used for the HMAC. + */ +AVHMAC *av_hmac_alloc(enum AVHMACType type); + +/** + * Free an AVHMAC context. + * @param ctx The context to free, may be NULL + */ +void av_hmac_free(AVHMAC *ctx); + +/** + * Initialize an AVHMAC context with an authentication key. + * @param ctx The HMAC context + * @param key The authentication key + * @param keylen The length of the key, in bytes + */ +void av_hmac_init(AVHMAC *ctx, const uint8_t *key, unsigned int keylen); + +/** + * Hash data with the HMAC. + * @param ctx The HMAC context + * @param data The data to hash + * @param len The length of the data, in bytes + */ +void av_hmac_update(AVHMAC *ctx, const uint8_t *data, unsigned int len); + +/** + * Finish hashing and output the HMAC digest. + * @param ctx The HMAC context + * @param out The output buffer to write the digest into + * @param outlen The length of the out buffer, in bytes + * @return The number of bytes written to out, or a negative error code. + */ +int av_hmac_final(AVHMAC *ctx, uint8_t *out, unsigned int outlen); + +/** + * Hash an array of data with a key. + * @param ctx The HMAC context + * @param data The data to hash + * @param len The length of the data, in bytes + * @param key The authentication key + * @param keylen The length of the key, in bytes + * @param out The output buffer to write the digest into + * @param outlen The length of the out buffer, in bytes + * @return The number of bytes written to out, or a negative error code. + */ +int av_hmac_calc(AVHMAC *ctx, const uint8_t *data, unsigned int len, + const uint8_t *key, unsigned int keylen, + uint8_t *out, unsigned int outlen); + +/** + * @} + */ + +#endif /* AVUTIL_HMAC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext.h new file mode 100755 index 0000000000000000000000000000000000000000..f5a4b623877477c0d778bea1ab051be074fe09d5 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext.h @@ -0,0 +1,584 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_H +#define AVUTIL_HWCONTEXT_H + +#include "buffer.h" +#include "frame.h" +#include "log.h" +#include "pixfmt.h" + +enum AVHWDeviceType { + AV_HWDEVICE_TYPE_NONE, + AV_HWDEVICE_TYPE_VDPAU, + AV_HWDEVICE_TYPE_CUDA, + AV_HWDEVICE_TYPE_VAAPI, + AV_HWDEVICE_TYPE_DXVA2, + AV_HWDEVICE_TYPE_QSV, + AV_HWDEVICE_TYPE_VIDEOTOOLBOX, + AV_HWDEVICE_TYPE_D3D11VA, + AV_HWDEVICE_TYPE_DRM, + AV_HWDEVICE_TYPE_OPENCL, + AV_HWDEVICE_TYPE_MEDIACODEC, +}; + +typedef struct AVHWDeviceInternal AVHWDeviceInternal; + +/** + * This struct aggregates all the (hardware/vendor-specific) "high-level" state, + * i.e. state that is not tied to a concrete processing configuration. + * E.g., in an API that supports hardware-accelerated encoding and decoding, + * this struct will (if possible) wrap the state that is common to both encoding + * and decoding and from which specific instances of encoders or decoders can be + * derived. + * + * This struct is reference-counted with the AVBuffer mechanism. The + * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field + * points to the actual AVHWDeviceContext. Further objects derived from + * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with + * specific properties) will hold an internal reference to it. After all the + * references are released, the AVHWDeviceContext itself will be freed, + * optionally invoking a user-specified callback for uninitializing the hardware + * state. + */ +typedef struct AVHWDeviceContext { + /** + * A class for logging. Set by av_hwdevice_ctx_alloc(). + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWDeviceInternal *internal; + + /** + * This field identifies the underlying API used for hardware access. + * + * This field is set when this struct is allocated and never changed + * afterwards. + */ + enum AVHWDeviceType type; + + /** + * The format-specific data, allocated and freed by libavutil along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwcontext_*.h) and filled as described in the + * documentation before calling av_hwdevice_ctx_init(). + * + * After calling av_hwdevice_ctx_init() this struct should not be modified + * by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwdevice_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + * + * @note when other objects (e.g an AVHWFramesContext) are derived from this + * struct, this callback will be invoked after all such child objects + * are fully uninitialized and their respective destructors invoked. + */ + void (*free)(struct AVHWDeviceContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; +} AVHWDeviceContext; + +typedef struct AVHWFramesInternal AVHWFramesInternal; + +/** + * This struct describes a set or pool of "hardware" frames (i.e. those with + * data not located in normal system memory). All the frames in the pool are + * assumed to be allocated in the same way and interchangeable. + * + * This struct is reference-counted with the AVBuffer mechanism and tied to a + * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor + * yields a reference, whose data field points to the actual AVHWFramesContext + * struct. + */ +typedef struct AVHWFramesContext { + /** + * A class for logging. + */ + const AVClass *av_class; + + /** + * Private data used internally by libavutil. Must not be accessed in any + * way by the caller. + */ + AVHWFramesInternal *internal; + + /** + * A reference to the parent AVHWDeviceContext. This reference is owned and + * managed by the enclosing AVHWFramesContext, but the caller may derive + * additional references from it. + */ + AVBufferRef *device_ref; + + /** + * The parent AVHWDeviceContext. This is simply a pointer to + * device_ref->data provided for convenience. + * + * Set by libavutil in av_hwframe_ctx_init(). + */ + AVHWDeviceContext *device_ctx; + + /** + * The format-specific data, allocated and freed automatically along with + * this context. + * + * Should be cast by the user to the format-specific context defined in the + * corresponding header (hwframe_*.h) and filled as described in the + * documentation before calling av_hwframe_ctx_init(). + * + * After any frames using this context are created, the contents of this + * struct should not be modified by the caller. + */ + void *hwctx; + + /** + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * + * If non-NULL, this callback will be called when the last reference to + * this context is unreferenced, immediately before it is freed. + */ + void (*free)(struct AVHWFramesContext *ctx); + + /** + * Arbitrary user data, to be used e.g. by the free() callback. + */ + void *user_opaque; + + /** + * A pool from which the frames are allocated by av_hwframe_get_buffer(). + * This field may be set by the caller before calling av_hwframe_ctx_init(). + * The buffers returned by calling av_buffer_pool_get() on this pool must + * have the properties described in the documentation in the corresponding hw + * type's header (hwcontext_*.h). The pool will be freed strictly before + * this struct's free() callback is invoked. + * + * This field may be NULL, then libavutil will attempt to allocate a pool + * internally. Note that certain device types enforce pools allocated at + * fixed size (frame count), which cannot be extended dynamically. In such a + * case, initial_pool_size must be set appropriately. + */ + AVBufferPool *pool; + + /** + * Initial size of the frame pool. If a device type does not support + * dynamically resizing the pool, then this is also the maximum pool size. + * + * May be set by the caller before calling av_hwframe_ctx_init(). Must be + * set if pool is NULL and the device type does not support dynamic pools. + */ + int initial_pool_size; + + /** + * The pixel format identifying the underlying HW surface type. + * + * Must be a hwaccel format, i.e. the corresponding descriptor must have the + * AV_PIX_FMT_FLAG_HWACCEL flag set. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + enum AVPixelFormat format; + + /** + * The pixel format identifying the actual data layout of the hardware + * frames. + * + * Must be set by the caller before calling av_hwframe_ctx_init(). + * + * @note when the underlying API does not provide the exact data layout, but + * only the colorspace/bit depth, this field should be set to the fully + * planar version of that format (e.g. for 8-bit 420 YUV it should be + * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). + */ + enum AVPixelFormat sw_format; + + /** + * The allocated dimensions of the frames in this pool. + * + * Must be set by the user before calling av_hwframe_ctx_init(). + */ + int width, height; +} AVHWFramesContext; + +/** + * Look up an AVHWDeviceType by name. + * + * @param name String name of the device type (case-insensitive). + * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if + * not found. + */ +enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name); + +/** Get the string name of an AVHWDeviceType. + * + * @param type Type from enum AVHWDeviceType. + * @return Pointer to a static string containing the name, or NULL if the type + * is not valid. + */ +const char *av_hwdevice_get_type_name(enum AVHWDeviceType type); + +/** + * Iterate over supported device types. + * + * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type + * returned by this function in subsequent iterations. + * @return The next usable device type from enum AVHWDeviceType, or + * AV_HWDEVICE_TYPE_NONE if there are no more. + */ +enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev); + +/** + * Allocate an AVHWDeviceContext for a given hardware type. + * + * @param type the type of the hardware device to allocate. + * @return a reference to the newly created AVHWDeviceContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); + +/** + * Finalize the device context before use. This function must be called after + * the context is filled with all the required information and before it is + * used in any way. + * + * @param ref a reference to the AVHWDeviceContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwdevice_ctx_init(AVBufferRef *ref); + +/** + * Open a device of the specified type and create an AVHWDeviceContext for it. + * + * This is a convenience function intended to cover the simple cases. Callers + * who need to fine-tune device creation/management should open the device + * manually and then wrap it in an AVHWDeviceContext using + * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init(). + * + * The returned context is already initialized and ready for use, the caller + * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of + * the created AVHWDeviceContext are set by this function and should not be + * touched by the caller. + * + * @param device_ctx On success, a reference to the newly-created device context + * will be written here. The reference is owned by the caller + * and must be released with av_buffer_unref() when no longer + * needed. On failure, NULL will be written to this pointer. + * @param type The type of the device to create. + * @param device A type-specific string identifying the device to open. + * @param opts A dictionary of additional (type-specific) options to use in + * opening the device. The dictionary remains owned by the caller. + * @param flags currently unused + * + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, + const char *device, AVDictionary *opts, int flags); + +/** + * Create a new device of the specified type from an existing device. + * + * If the source device is a device of the target type or was originally + * derived from such a device (possibly through one or more intermediate + * devices of other types), then this will return a reference to the + * existing device of the same type as is requested. + * + * Otherwise, it will attempt to derive a new device from the given source + * device. If direct derivation to the new type is not implemented, it will + * attempt the same derivation from each ancestor of the source device in + * turn looking for an implemented derivation method. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, int flags); + + +/** + * Allocate an AVHWFramesContext tied to a given device context. + * + * @param device_ctx a reference to a AVHWDeviceContext. This function will make + * a new reference for internal use, the one passed to the + * function remains owned by the caller. + * @return a reference to the newly created AVHWFramesContext on success or NULL + * on failure. + */ +AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); + +/** + * Finalize the context before use. This function must be called after the + * context is filled with all the required information and before it is attached + * to any frames. + * + * @param ref a reference to the AVHWFramesContext + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_ctx_init(AVBufferRef *ref); + +/** + * Allocate a new frame attached to the given AVHWFramesContext. + * + * @param hwframe_ctx a reference to an AVHWFramesContext + * @param frame an empty (freshly allocated or unreffed) frame to be filled with + * newly allocated buffers. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); + +/** + * Copy data to or from a hw surface. At least one of dst/src must have an + * AVHWFramesContext attached. + * + * If src has an AVHWFramesContext attached, then the format of dst (if set) + * must use one of the formats returned by av_hwframe_transfer_get_formats(src, + * AV_HWFRAME_TRANSFER_DIRECTION_FROM). + * If dst has an AVHWFramesContext attached, then the format of src must use one + * of the formats returned by av_hwframe_transfer_get_formats(dst, + * AV_HWFRAME_TRANSFER_DIRECTION_TO) + * + * dst may be "clean" (i.e. with data/buf pointers unset), in which case the + * data buffers will be allocated by this function using av_frame_get_buffer(). + * If dst->format is set, then this format will be used, otherwise (when + * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. + * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * + * @param dst the destination frame. dst is not touched on failure. + * @param src the source frame. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR error code on failure. + */ +int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); + +enum AVHWFrameTransferDirection { + /** + * Transfer the data from the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_FROM, + + /** + * Transfer the data to the queried hw frame. + */ + AV_HWFRAME_TRANSFER_DIRECTION_TO, +}; + +/** + * Get a list of possible source or target formats usable in + * av_hwframe_transfer_data(). + * + * @param hwframe_ctx the frame context to obtain the information for + * @param dir the direction of the transfer + * @param formats the pointer to the output format list will be written here. + * The list is terminated with AV_PIX_FMT_NONE and must be freed + * by the caller when no longer needed using av_free(). + * If this function returns successfully, the format list will + * have at least one item (not counting the terminator). + * On failure, the contents of this pointer are unspecified. + * @param flags currently unused, should be set to zero + * @return 0 on success, a negative AVERROR code on failure. + */ +int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats, int flags); + + +/** + * This struct describes the constraints on hardware frames attached to + * a given device with a hardware-specific configuration. This is returned + * by av_hwdevice_get_hwframe_constraints() and must be freed by + * av_hwframe_constraints_free() after use. + */ +typedef struct AVHWFramesConstraints { + /** + * A list of possible values for format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. This member will always be filled. + */ + enum AVPixelFormat *valid_hw_formats; + + /** + * A list of possible values for sw_format in the hw_frames_ctx, + * terminated by AV_PIX_FMT_NONE. Can be NULL if this information is + * not known. + */ + enum AVPixelFormat *valid_sw_formats; + + /** + * The minimum size of frames in this hw_frames_ctx. + * (Zero if not known.) + */ + int min_width; + int min_height; + + /** + * The maximum size of frames in this hw_frames_ctx. + * (INT_MAX if not known / no limit.) + */ + int max_width; + int max_height; +} AVHWFramesConstraints; + +/** + * Allocate a HW-specific configuration structure for a given HW device. + * After use, the user must free all members as required by the specific + * hardware structure being used, then free the structure itself with + * av_free(). + * + * @param device_ctx a reference to the associated AVHWDeviceContext. + * @return The newly created HW-specific configuration structure on + * success or NULL on failure. + */ +void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx); + +/** + * Get the constraints on HW frames given a device and the HW-specific + * configuration to be used with that device. If no HW-specific + * configuration is provided, returns the maximum possible capabilities + * of the device. + * + * @param ref a reference to the associated AVHWDeviceContext. + * @param hwconfig a filled HW-specific configuration structure, or NULL + * to return the maximum possible capabilities of the device. + * @return AVHWFramesConstraints structure describing the constraints + * on the device, or NULL if not available. + */ +AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, + const void *hwconfig); + +/** + * Free an AVHWFrameConstraints structure. + * + * @param constraints The (filled or unfilled) AVHWFrameConstraints structure. + */ +void av_hwframe_constraints_free(AVHWFramesConstraints **constraints); + + +/** + * Flags to apply to frame mappings. + */ +enum { + /** + * The mapping must be readable. + */ + AV_HWFRAME_MAP_READ = 1 << 0, + /** + * The mapping must be writeable. + */ + AV_HWFRAME_MAP_WRITE = 1 << 1, + /** + * The mapped frame will be overwritten completely in subsequent + * operations, so the current frame data need not be loaded. Any values + * which are not overwritten are unspecified. + */ + AV_HWFRAME_MAP_OVERWRITE = 1 << 2, + /** + * The mapping must be direct. That is, there must not be any copying in + * the map or unmap steps. Note that performance of direct mappings may + * be much lower than normal memory. + */ + AV_HWFRAME_MAP_DIRECT = 1 << 3, +}; + +/** + * Map a hardware frame. + * + * This has a number of different possible effects, depending on the format + * and origin of the src and dst frames. On input, src should be a usable + * frame with valid buffers and dst should be blank (typically as just created + * by av_frame_alloc()). src should have an associated hwframe context, and + * dst may optionally have a format and associated hwframe context. + * + * If src was created by mapping a frame from the hwframe context of dst, + * then this function undoes the mapping - dst is replaced by a reference to + * the frame that src was originally mapped from. + * + * If both src and dst have an associated hwframe context, then this function + * attempts to map the src frame from its hardware context to that of dst and + * then fill dst with appropriate data to be usable there. This will only be + * possible if the hwframe contexts and associated devices are compatible - + * given compatible devices, av_hwframe_ctx_create_derived() can be used to + * create a hwframe context for dst in which mapping should be possible. + * + * If src has a hwframe context but dst does not, then the src frame is + * mapped to normal memory and should thereafter be usable as a normal frame. + * If the format is set on dst, then the mapping will attempt to create dst + * with that format and fail if it is not possible. If format is unset (is + * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate + * format to use is (probably the sw_format of the src hwframe context). + * + * A return value of AVERROR(ENOSYS) indicates that the mapping is not + * possible with the given arguments and hwframe setup, while other return + * values indicate that it failed somehow. + * + * @param dst Destination frame, to contain the mapping. + * @param src Source frame, to be mapped. + * @param flags Some combination of AV_HWFRAME_MAP_* flags. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags); + + +/** + * Create and initialise an AVHWFramesContext as a mapping of another existing + * AVHWFramesContext on a different device. + * + * av_hwframe_ctx_init() should not be called after this. + * + * @param derived_frame_ctx On success, a reference to the newly created + * AVHWFramesContext. + * @param derived_device_ctx A reference to the device to create the new + * AVHWFramesContext on. + * @param source_frame_ctx A reference to an existing AVHWFramesContext + * which will be mapped to the derived context. + * @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the + * mapping parameters to apply to frames which are allocated + * in the derived device. + * @return Zero on success, negative AVERROR code on failure. + */ +int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, + enum AVPixelFormat format, + AVBufferRef *derived_device_ctx, + AVBufferRef *source_frame_ctx, + int flags); + +#endif /* AVUTIL_HWCONTEXT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_cuda.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_cuda.h new file mode 100755 index 0000000000000000000000000000000000000000..81a0552cabb73d3c51afe311488fb9c42ea1c724 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_cuda.h @@ -0,0 +1,52 @@ +/* + * 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 + */ + + +#ifndef AVUTIL_HWCONTEXT_CUDA_H +#define AVUTIL_HWCONTEXT_CUDA_H + +#ifndef CUDA_VERSION +#include +#endif + +#include "pixfmt.h" + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_CUDA. + * + * This API supports dynamic frame pools. AVHWFramesContext.pool must return + * AVBufferRefs whose data pointer is a CUdeviceptr. + */ + +typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal; + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVCUDADeviceContext { + CUcontext cuda_ctx; + CUstream stream; + AVCUDADeviceContextInternal *internal; +} AVCUDADeviceContext; + +/** + * AVHWFramesContext.hwctx is currently not used + */ + +#endif /* AVUTIL_HWCONTEXT_CUDA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_d3d11va.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_d3d11va.h new file mode 100755 index 0000000000000000000000000000000000000000..9f91e9b1b67bffee523ff1063c32ae924ccf8370 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_d3d11va.h @@ -0,0 +1,169 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_D3D11VA_H +#define AVUTIL_HWCONTEXT_D3D11VA_H + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_D3D11VA. + * + * The default pool implementation will be fixed-size if initial_pool_size is + * set (and allocate elements from an array texture). Otherwise it will allocate + * individual textures. Be aware that decoding requires a single array texture. + * + * Using sw_format==AV_PIX_FMT_YUV420P has special semantics, and maps to + * DXGI_FORMAT_420_OPAQUE. av_hwframe_transfer_data() is not supported for + * this format. Refer to MSDN for details. + * + * av_hwdevice_ctx_create() for this device type supports a key named "debug" + * for the AVDictionary entry. If this is set to any value, the device creation + * code will try to load various supported D3D debugging layers. + */ + +#include +#include + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVD3D11VADeviceContext { + /** + * Device used for texture creation and access. This can also be used to + * set the libavcodec decoding device. + * + * Must be set by the user. This is the only mandatory field - the other + * device context fields are set from this and are available for convenience. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11Device *device; + + /** + * If unset, this will be set from the device field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11DeviceContext *device_context; + + /** + * If unset, this will be set from the device field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11VideoDevice *video_device; + + /** + * If unset, this will be set from the device_context field on init. + * + * Deallocating the AVHWDeviceContext will always release this interface, + * and it does not matter whether it was user-allocated. + */ + ID3D11VideoContext *video_context; + + /** + * Callbacks for locking. They protect accesses to device_context and + * video_context calls. They also protect access to the internal staging + * texture (for av_hwframe_transfer_data() calls). They do NOT protect + * access to hwcontext or decoder state in general. + * + * If unset on init, the hwcontext implementation will set them to use an + * internal mutex. + * + * The underlying lock must be recursive. lock_ctx is for free use by the + * locking implementation. + */ + void (*lock)(void *lock_ctx); + void (*unlock)(void *lock_ctx); + void *lock_ctx; +} AVD3D11VADeviceContext; + +/** + * D3D11 frame descriptor for pool allocation. + * + * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer pointing at an object of this type describing the + * planes of the frame. + * + * This has no use outside of custom allocation, and AVFrame AVBufferRef do not + * necessarily point to an instance of this struct. + */ +typedef struct AVD3D11FrameDescriptor { + /** + * The texture in which the frame is located. The reference count is + * managed by the AVBufferRef, and destroying the reference will release + * the interface. + * + * Normally stored in AVFrame.data[0]. + */ + ID3D11Texture2D *texture; + + /** + * The index into the array texture element representing the frame, or 0 + * if the texture is not an array texture. + * + * Normally stored in AVFrame.data[1] (cast from intptr_t). + */ + intptr_t index; +} AVD3D11FrameDescriptor; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVD3D11VAFramesContext { + /** + * The canonical texture used for pool allocation. If this is set to NULL + * on init, the hwframes implementation will allocate and set an array + * texture if initial_pool_size > 0. + * + * The only situation when the API user should set this is: + * - the user wants to do manual pool allocation (setting + * AVHWFramesContext.pool), instead of letting AVHWFramesContext + * allocate the pool + * - of an array texture + * - and wants it to use it for decoding + * - this has to be done before calling av_hwframe_ctx_init() + * + * Deallocating the AVHWFramesContext will always release this interface, + * and it does not matter whether it was user-allocated. + * + * This is in particular used by the libavcodec D3D11VA hwaccel, which + * requires a single array texture. It will create ID3D11VideoDecoderOutputView + * objects for each array texture element on decoder initialization. + */ + ID3D11Texture2D *texture; + + /** + * D3D11_TEXTURE2D_DESC.BindFlags used for texture creation. The user must + * at least set D3D11_BIND_DECODER if the frames context is to be used for + * video decoding. + * This field is ignored/invalid if a user-allocated texture is provided. + */ + UINT BindFlags; + + /** + * D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation. + * This field is ignored/invalid if a user-allocated texture is provided. + */ + UINT MiscFlags; +} AVD3D11VAFramesContext; + +#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_drm.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_drm.h new file mode 100755 index 0000000000000000000000000000000000000000..42709f215ef9adc7d5eee2ea2574c198d8171534 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_drm.h @@ -0,0 +1,169 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_DRM_H +#define AVUTIL_HWCONTEXT_DRM_H + +#include +#include + +/** + * @file + * API-specific header for AV_HWDEVICE_TYPE_DRM. + * + * Internal frame allocation is not currently supported - all frames + * must be allocated by the user. Thus AVHWFramesContext is always + * NULL, though this may change if support for frame allocation is + * added in future. + */ + +enum { + /** + * The maximum number of layers/planes in a DRM frame. + */ + AV_DRM_MAX_PLANES = 4 +}; + +/** + * DRM object descriptor. + * + * Describes a single DRM object, addressing it as a PRIME file + * descriptor. + */ +typedef struct AVDRMObjectDescriptor { + /** + * DRM PRIME fd for the object. + */ + int fd; + /** + * Total size of the object. + * + * (This includes any parts not which do not contain image data.) + */ + size_t size; + /** + * Format modifier applied to the object (DRM_FORMAT_MOD_*). + * + * If the format modifier is unknown then this should be set to + * DRM_FORMAT_MOD_INVALID. + */ + uint64_t format_modifier; +} AVDRMObjectDescriptor; + +/** + * DRM plane descriptor. + * + * Describes a single plane of a layer, which is contained within + * a single object. + */ +typedef struct AVDRMPlaneDescriptor { + /** + * Index of the object containing this plane in the objects + * array of the enclosing frame descriptor. + */ + int object_index; + /** + * Offset within that object of this plane. + */ + ptrdiff_t offset; + /** + * Pitch (linesize) of this plane. + */ + ptrdiff_t pitch; +} AVDRMPlaneDescriptor; + +/** + * DRM layer descriptor. + * + * Describes a single layer within a frame. This has the structure + * defined by its format, and will contain one or more planes. + */ +typedef struct AVDRMLayerDescriptor { + /** + * Format of the layer (DRM_FORMAT_*). + */ + uint32_t format; + /** + * Number of planes in the layer. + * + * This must match the number of planes required by format. + */ + int nb_planes; + /** + * Array of planes in this layer. + */ + AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]; +} AVDRMLayerDescriptor; + +/** + * DRM frame descriptor. + * + * This is used as the data pointer for AV_PIX_FMT_DRM_PRIME frames. + * It is also used by user-allocated frame pools - allocating in + * AVHWFramesContext.pool must return AVBufferRefs which contain + * an object of this type. + * + * The fields of this structure should be set such it can be + * imported directly by EGL using the EGL_EXT_image_dma_buf_import + * and EGL_EXT_image_dma_buf_import_modifiers extensions. + * (Note that the exact layout of a particular format may vary between + * platforms - we only specify that the same platform should be able + * to import it.) + * + * The total number of planes must not exceed AV_DRM_MAX_PLANES, and + * the order of the planes by increasing layer index followed by + * increasing plane index must be the same as the order which would + * be used for the data pointers in the equivalent software format. + */ +typedef struct AVDRMFrameDescriptor { + /** + * Number of DRM objects making up this frame. + */ + int nb_objects; + /** + * Array of objects making up the frame. + */ + AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]; + /** + * Number of layers in the frame. + */ + int nb_layers; + /** + * Array of layers in the frame. + */ + AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]; +} AVDRMFrameDescriptor; + +/** + * DRM device. + * + * Allocated as AVHWDeviceContext.hwctx. + */ +typedef struct AVDRMDeviceContext { + /** + * File descriptor of DRM device. + * + * This is used as the device to create frames on, and may also be + * used in some derivation and mapping operations. + * + * If no device is required, set to -1. + */ + int fd; +} AVDRMDeviceContext; + +#endif /* AVUTIL_HWCONTEXT_DRM_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_dxva2.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_dxva2.h new file mode 100755 index 0000000000000000000000000000000000000000..e1b79bc0dee8c25657d63da619c9265b958a5520 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_dxva2.h @@ -0,0 +1,75 @@ +/* + * 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 + */ + + +#ifndef AVUTIL_HWCONTEXT_DXVA2_H +#define AVUTIL_HWCONTEXT_DXVA2_H + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_DXVA2. + * + * Only fixed-size pools are supported. + * + * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer set to a pointer to IDirect3DSurface9. + */ + +#include +#include + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVDXVA2DeviceContext { + IDirect3DDeviceManager9 *devmgr; +} AVDXVA2DeviceContext; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVDXVA2FramesContext { + /** + * The surface type (e.g. DXVA2_VideoProcessorRenderTarget or + * DXVA2_VideoDecoderRenderTarget). Must be set by the caller. + */ + DWORD surface_type; + + /** + * The surface pool. When an external pool is not provided by the caller, + * this will be managed (allocated and filled on init, freed on uninit) by + * libavutil. + */ + IDirect3DSurface9 **surfaces; + int nb_surfaces; + + /** + * Certain drivers require the decoder to be destroyed before the surfaces. + * To allow internally managed pools to work properly in such cases, this + * field is provided. + * + * If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on + * it just before the internal surface pool is freed. + * + * This is for convenience only. Some code uses other methods to manage the + * decoder reference. + */ + IDirectXVideoDecoder *decoder_to_release; +} AVDXVA2FramesContext; + +#endif /* AVUTIL_HWCONTEXT_DXVA2_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_mediacodec.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_mediacodec.h new file mode 100755 index 0000000000000000000000000000000000000000..101a9806d59e36f69151ca298c00543f4a503133 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_mediacodec.h @@ -0,0 +1,36 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_MEDIACODEC_H +#define AVUTIL_HWCONTEXT_MEDIACODEC_H + +/** + * MediaCodec details. + * + * Allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVMediaCodecDeviceContext { + /** + * android/view/Surface handle, to be filled by the user. + * + * This is the default surface used by decoders on this device. + */ + void *surface; +} AVMediaCodecDeviceContext; + +#endif /* AVUTIL_HWCONTEXT_MEDIACODEC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_qsv.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_qsv.h new file mode 100755 index 0000000000000000000000000000000000000000..b98d611cfc4039037f14b154ee6049f049b4de65 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_qsv.h @@ -0,0 +1,53 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_QSV_H +#define AVUTIL_HWCONTEXT_QSV_H + +#include + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_QSV. + * + * This API does not support dynamic frame pools. AVHWFramesContext.pool must + * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct. + */ + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVQSVDeviceContext { + mfxSession session; +} AVQSVDeviceContext; + +/** + * This struct is allocated as AVHWFramesContext.hwctx + */ +typedef struct AVQSVFramesContext { + mfxFrameSurface1 *surfaces; + int nb_surfaces; + + /** + * A combination of MFX_MEMTYPE_* describing the frame pool. + */ + int frame_type; +} AVQSVFramesContext; + +#endif /* AVUTIL_HWCONTEXT_QSV_H */ + diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vaapi.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vaapi.h new file mode 100755 index 0000000000000000000000000000000000000000..0b2e071cb33533cc8e5db32c540591291392430c --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vaapi.h @@ -0,0 +1,117 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_VAAPI_H +#define AVUTIL_HWCONTEXT_VAAPI_H + +#include + +/** + * @file + * API-specific header for AV_HWDEVICE_TYPE_VAAPI. + * + * Dynamic frame pools are supported, but note that any pool used as a render + * target is required to be of fixed size in order to be be usable as an + * argument to vaCreateContext(). + * + * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer set to a VASurfaceID. + */ + +enum { + /** + * The quirks field has been set by the user and should not be detected + * automatically by av_hwdevice_ctx_init(). + */ + AV_VAAPI_DRIVER_QUIRK_USER_SET = (1 << 0), + /** + * The driver does not destroy parameter buffers when they are used by + * vaRenderPicture(). Additional code will be required to destroy them + * separately afterwards. + */ + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS = (1 << 1), + + /** + * The driver does not support the VASurfaceAttribMemoryType attribute, + * so the surface allocation code will not try to use it. + */ + AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE = (1 << 2), + + /** + * The driver does not support surface attributes at all. + * The surface allocation code will never pass them to surface allocation, + * and the results of the vaQuerySurfaceAttributes() call will be faked. + */ + AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES = (1 << 3), +}; + +/** + * VAAPI connection details. + * + * Allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVVAAPIDeviceContext { + /** + * The VADisplay handle, to be filled by the user. + */ + VADisplay display; + /** + * Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), + * with reference to a table of known drivers, unless the + * AV_VAAPI_DRIVER_QUIRK_USER_SET bit is already present. The user + * may need to refer to this field when performing any later + * operations using VAAPI with the same VADisplay. + */ + unsigned int driver_quirks; +} AVVAAPIDeviceContext; + +/** + * VAAPI-specific data associated with a frame pool. + * + * Allocated as AVHWFramesContext.hwctx. + */ +typedef struct AVVAAPIFramesContext { + /** + * Set by the user to apply surface attributes to all surfaces in + * the frame pool. If null, default settings are used. + */ + VASurfaceAttrib *attributes; + int nb_attributes; + /** + * The surfaces IDs of all surfaces in the pool after creation. + * Only valid if AVHWFramesContext.initial_pool_size was positive. + * These are intended to be used as the render_targets arguments to + * vaCreateContext(). + */ + VASurfaceID *surface_ids; + int nb_surfaces; +} AVVAAPIFramesContext; + +/** + * VAAPI hardware pipeline configuration details. + * + * Allocated with av_hwdevice_hwconfig_alloc(). + */ +typedef struct AVVAAPIHWConfig { + /** + * ID of a VAAPI pipeline configuration. + */ + VAConfigID config_id; +} AVVAAPIHWConfig; + +#endif /* AVUTIL_HWCONTEXT_VAAPI_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vdpau.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vdpau.h new file mode 100755 index 0000000000000000000000000000000000000000..1b7ea1e443bdc4938416e1cd10c4263007e0c52d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_vdpau.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_VDPAU_H +#define AVUTIL_HWCONTEXT_VDPAU_H + +#include + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_VDPAU. + * + * This API supports dynamic frame pools. AVHWFramesContext.pool must return + * AVBufferRefs whose data pointer is a VdpVideoSurface. + */ + +/** + * This struct is allocated as AVHWDeviceContext.hwctx + */ +typedef struct AVVDPAUDeviceContext { + VdpDevice device; + VdpGetProcAddress *get_proc_address; +} AVVDPAUDeviceContext; + +/** + * AVHWFramesContext.hwctx is currently not used + */ + +#endif /* AVUTIL_HWCONTEXT_VDPAU_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/hwcontext_videotoolbox.h b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_videotoolbox.h new file mode 100755 index 0000000000000000000000000000000000000000..380918d92ee42d514a337dfd1a29209daf141721 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/hwcontext_videotoolbox.h @@ -0,0 +1,54 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H +#define AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H + +#include + +#include + +#include "pixfmt.h" + +/** + * @file + * An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX. + * + * This API currently does not support frame allocation, as the raw VideoToolbox + * API does allocation, and FFmpeg itself never has the need to allocate frames. + * + * If the API user sets a custom pool, AVHWFramesContext.pool must return + * AVBufferRefs whose data pointer is a CVImageBufferRef or CVPixelBufferRef. + * + * Currently AVHWDeviceContext.hwctx and AVHWFramesContext.hwctx are always + * NULL. + */ + +/** + * Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat. + * Returns AV_PIX_FMT_NONE if no known equivalent was found. + */ +enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt); + +/** + * Convert an AVPixelFormat to a VideoToolbox (actually CoreVideo) format. + * Returns 0 if no known equivalent was found. + */ +uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt); + +#endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/imgutils.h b/thirdparty/user_include/ffmpeg/libavutil/imgutils.h new file mode 100755 index 0000000000000000000000000000000000000000..5b790ecf0ab32e4ce182f06acf2f455b5c9c0d9b --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/imgutils.h @@ -0,0 +1,277 @@ +/* + * 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 + */ + +#ifndef AVUTIL_IMGUTILS_H +#define AVUTIL_IMGUTILS_H + +/** + * @file + * misc image utilities + * + * @addtogroup lavu_picture + * @{ + */ + +#include "avutil.h" +#include "pixdesc.h" +#include "rational.h" + +/** + * Compute the max pixel step for each plane of an image with a + * format described by pixdesc. + * + * The pixel step is the distance in bytes between the first byte of + * the group of bytes which describe a pixel component and the first + * byte of the successive group in the same plane for the same + * component. + * + * @param max_pixsteps an array which is filled with the max pixel step + * for each plane. Since a plane may contain different pixel + * components, the computed max_pixsteps[plane] is relative to the + * component in the plane with the max pixel step. + * @param max_pixstep_comps an array which is filled with the component + * for each plane which has the max pixel step. May be NULL. + */ +void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], + const AVPixFmtDescriptor *pixdesc); + +/** + * Compute the size of an image line with format pix_fmt and width + * width for the plane plane. + * + * @return the computed size in bytes + */ +int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane); + +/** + * Fill plane linesizes for an image with pixel format pix_fmt and + * width width. + * + * @param linesizes array to be filled with the linesize for each plane + * @return >= 0 in case of success, a negative error code otherwise + */ +int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); + +/** + * Fill plane data pointers for an image with pixel format pix_fmt and + * height height. + * + * @param data pointers array to be filled with the pointer for each image plane + * @param ptr the pointer to a buffer which will contain the image + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]); + +/** + * Allocate an image with size w and h and pixel format pix_fmt, and + * fill pointers and linesizes accordingly. + * The allocated image buffer has to be freed by using + * av_freep(&pointers[0]). + * + * @param align the value to use for buffer size alignment + * @return the size in bytes required for the image buffer, a negative + * error code in case of failure + */ +int av_image_alloc(uint8_t *pointers[4], int linesizes[4], + int w, int h, enum AVPixelFormat pix_fmt, int align); + +/** + * Copy image plane from src to dst. + * That is, copy "height" number of lines of "bytewidth" bytes each. + * The first byte of each successive line is separated by *_linesize + * bytes. + * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * + * @param dst_linesize linesize for the image plane in dst + * @param src_linesize linesize for the image plane in src + */ +void av_image_copy_plane(uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, + int bytewidth, int height); + +/** + * Copy image in src_data to dst_data. + * + * @param dst_linesizes linesizes for the image in dst_data + * @param src_linesizes linesizes for the image in src_data + */ +void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], + const uint8_t *src_data[4], const int src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where + * available, this function will use special functionality for reading from such + * memory, which may result in greatly improved performance compared to plain + * av_image_copy(). + * + * The data pointers and the linesizes must be aligned to the maximum required + * by the CPU architecture. + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_copy(). + * @note On x86, the linesizes currently need to be aligned to the cacheline + * size (i.e. 64) to get improved performance. + */ +void av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], + const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4], + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesize linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the assumed linesize alignment + * @return the buffer size in bytes, a negative error code in case of failure + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesize linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of the image can be addressed with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); + +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + +/** + * Check if the given sample aspect ratio of an image is valid. + * + * It is considered invalid if the denominator is 0 or if applying the ratio + * to the image size would make the smaller dimension less than 1. If the + * sar numerator is 0, it is considered unknown and will return as valid. + * + * @param w width of the image + * @param h height of the image + * @param sar sample aspect ratio of the image + * @return 0 if valid, a negative AVERROR code otherwise + */ +int av_image_check_sar(unsigned int w, unsigned int h, AVRational sar); + +/** + * Overwrite the image data with black. This is suitable for filling a + * sub-rectangle of an image, meaning the padding between the right most pixel + * and the left most pixel on the next line will not be overwritten. For some + * formats, the image size might be rounded up due to inherent alignment. + * + * If the pixel format has alpha, the alpha is cleared to opaque. + * + * This can return an error if the pixel format is not supported. Normally, all + * non-hwaccel pixel formats should be supported. + * + * Passing NULL for dst_data is allowed. Then the function returns whether the + * operation would have succeeded. (It can return an error if the pix_fmt is + * not supported.) + * + * @param dst_data data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param pix_fmt the pixel format of the image + * @param range the color range of the image (important for colorspaces such as YUV) + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @return 0 if the image data was cleared, a negative AVERROR code otherwise + */ +int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], + enum AVPixelFormat pix_fmt, enum AVColorRange range, + int width, int height); + +/** + * @} + */ + + +#endif /* AVUTIL_IMGUTILS_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/intfloat.h b/thirdparty/user_include/ffmpeg/libavutil/intfloat.h new file mode 100755 index 0000000000000000000000000000000000000000..fe3d7ec4a5b6f5f616c103aef5a5cf7ec01f8242 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/intfloat.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * 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 + */ + +#ifndef AVUTIL_INTFLOAT_H +#define AVUTIL_INTFLOAT_H + +#include +#include "attributes.h" + +union av_intfloat32 { + uint32_t i; + float f; +}; + +union av_intfloat64 { + uint64_t i; + double f; +}; + +/** + * Reinterpret a 32-bit integer as a float. + */ +static av_always_inline float av_int2float(uint32_t i) +{ + union av_intfloat32 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a float as a 32-bit integer. + */ +static av_always_inline uint32_t av_float2int(float f) +{ + union av_intfloat32 v; + v.f = f; + return v.i; +} + +/** + * Reinterpret a 64-bit integer as a double. + */ +static av_always_inline double av_int2double(uint64_t i) +{ + union av_intfloat64 v; + v.i = i; + return v.f; +} + +/** + * Reinterpret a double as a 64-bit integer. + */ +static av_always_inline uint64_t av_double2int(double f) +{ + union av_intfloat64 v; + v.f = f; + return v.i; +} + +#endif /* AVUTIL_INTFLOAT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/intreadwrite.h b/thirdparty/user_include/ffmpeg/libavutil/intreadwrite.h new file mode 100755 index 0000000000000000000000000000000000000000..4c8413a536868b9a272d1030a20d0d776880b1d8 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/intreadwrite.h @@ -0,0 +1,644 @@ +/* + * 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 + */ + +#ifndef AVUTIL_INTREADWRITE_H +#define AVUTIL_INTREADWRITE_H + +#include +#include "libavutil/avconfig.h" +#include "attributes.h" +#include "bswap.h" + +typedef union { + uint64_t u64; + uint32_t u32[2]; + uint16_t u16[4]; + uint8_t u8 [8]; + double f64; + float f32[2]; +} av_alias av_alias64; + +typedef union { + uint32_t u32; + uint16_t u16[2]; + uint8_t u8 [4]; + float f32; +} av_alias av_alias32; + +typedef union { + uint16_t u16; + uint8_t u8 [2]; +} av_alias av_alias16; + +/* + * Arch-specific headers can provide any combination of + * AV_[RW][BLN](16|24|32|48|64) and AV_(COPY|SWAP|ZERO)(64|128) macros. + * Preprocessor symbols must be defined, even if these are implemented + * as inline functions. + * + * R/W means read/write, B/L/N means big/little/native endianness. + * The following macros require aligned access, compared to their + * unaligned variants: AV_(COPY|SWAP|ZERO)(64|128), AV_[RW]N[8-64]A. + * Incorrect usage may range from abysmal performance to crash + * depending on the platform. + * + * The unaligned variants are AV_[RW][BLN][8-64] and AV_COPY*U. + */ + +#ifdef HAVE_AV_CONFIG_H + +#include "config.h" + +#if ARCH_ARM +# include "arm/intreadwrite.h" +#elif ARCH_AVR32 +# include "avr32/intreadwrite.h" +#elif ARCH_MIPS +# include "mips/intreadwrite.h" +#elif ARCH_PPC +# include "ppc/intreadwrite.h" +#elif ARCH_TOMI +# include "tomi/intreadwrite.h" +#elif ARCH_X86 +# include "x86/intreadwrite.h" +#endif + +#endif /* HAVE_AV_CONFIG_H */ + +/* + * Map AV_RNXX <-> AV_R[BL]XX for all variants provided by per-arch headers. + */ + +#if AV_HAVE_BIGENDIAN + +# if defined(AV_RN16) && !defined(AV_RB16) +# define AV_RB16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RB16) +# define AV_RN16(p) AV_RB16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WB16) +# define AV_WB16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WB16) +# define AV_WN16(p, v) AV_WB16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RB24) +# define AV_RB24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RB24) +# define AV_RN24(p) AV_RB24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WB24) +# define AV_WB24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WB24) +# define AV_WN24(p, v) AV_WB24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RB32) +# define AV_RB32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RB32) +# define AV_RN32(p) AV_RB32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WB32) +# define AV_WB32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WB32) +# define AV_WN32(p, v) AV_WB32(p, v) +# endif + +# if defined(AV_RN48) && !defined(AV_RB48) +# define AV_RB48(p) AV_RN48(p) +# elif !defined(AV_RN48) && defined(AV_RB48) +# define AV_RN48(p) AV_RB48(p) +# endif + +# if defined(AV_WN48) && !defined(AV_WB48) +# define AV_WB48(p, v) AV_WN48(p, v) +# elif !defined(AV_WN48) && defined(AV_WB48) +# define AV_WN48(p, v) AV_WB48(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RB64) +# define AV_RB64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RB64) +# define AV_RN64(p) AV_RB64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WB64) +# define AV_WB64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WB64) +# define AV_WN64(p, v) AV_WB64(p, v) +# endif + +#else /* AV_HAVE_BIGENDIAN */ + +# if defined(AV_RN16) && !defined(AV_RL16) +# define AV_RL16(p) AV_RN16(p) +# elif !defined(AV_RN16) && defined(AV_RL16) +# define AV_RN16(p) AV_RL16(p) +# endif + +# if defined(AV_WN16) && !defined(AV_WL16) +# define AV_WL16(p, v) AV_WN16(p, v) +# elif !defined(AV_WN16) && defined(AV_WL16) +# define AV_WN16(p, v) AV_WL16(p, v) +# endif + +# if defined(AV_RN24) && !defined(AV_RL24) +# define AV_RL24(p) AV_RN24(p) +# elif !defined(AV_RN24) && defined(AV_RL24) +# define AV_RN24(p) AV_RL24(p) +# endif + +# if defined(AV_WN24) && !defined(AV_WL24) +# define AV_WL24(p, v) AV_WN24(p, v) +# elif !defined(AV_WN24) && defined(AV_WL24) +# define AV_WN24(p, v) AV_WL24(p, v) +# endif + +# if defined(AV_RN32) && !defined(AV_RL32) +# define AV_RL32(p) AV_RN32(p) +# elif !defined(AV_RN32) && defined(AV_RL32) +# define AV_RN32(p) AV_RL32(p) +# endif + +# if defined(AV_WN32) && !defined(AV_WL32) +# define AV_WL32(p, v) AV_WN32(p, v) +# elif !defined(AV_WN32) && defined(AV_WL32) +# define AV_WN32(p, v) AV_WL32(p, v) +# endif + +# if defined(AV_RN48) && !defined(AV_RL48) +# define AV_RL48(p) AV_RN48(p) +# elif !defined(AV_RN48) && defined(AV_RL48) +# define AV_RN48(p) AV_RL48(p) +# endif + +# if defined(AV_WN48) && !defined(AV_WL48) +# define AV_WL48(p, v) AV_WN48(p, v) +# elif !defined(AV_WN48) && defined(AV_WL48) +# define AV_WN48(p, v) AV_WL48(p, v) +# endif + +# if defined(AV_RN64) && !defined(AV_RL64) +# define AV_RL64(p) AV_RN64(p) +# elif !defined(AV_RN64) && defined(AV_RL64) +# define AV_RN64(p) AV_RL64(p) +# endif + +# if defined(AV_WN64) && !defined(AV_WL64) +# define AV_WL64(p, v) AV_WN64(p, v) +# elif !defined(AV_WN64) && defined(AV_WL64) +# define AV_WN64(p, v) AV_WL64(p, v) +# endif + +#endif /* !AV_HAVE_BIGENDIAN */ + +/* + * Define AV_[RW]N helper macros to simplify definitions not provided + * by per-arch headers. + */ + +#if defined(__GNUC__) + +union unaligned_64 { uint64_t l; } __attribute__((packed)) av_alias; +union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias; +union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; + +# define AV_RN(s, p) (((const union unaligned_##s *) (p))->l) +# define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v)) + +#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64) || defined(_M_ARM64)) && AV_HAVE_FAST_UNALIGNED + +# define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p))) +# define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v)) + +#elif AV_HAVE_FAST_UNALIGNED + +# define AV_RN(s, p) (((const av_alias##s*)(p))->u##s) +# define AV_WN(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#else + +#ifndef AV_RB16 +# define AV_RB16(x) \ + ((((const uint8_t*)(x))[0] << 8) | \ + ((const uint8_t*)(x))[1]) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, val) do { \ + uint16_t d = (val); \ + ((uint8_t*)(p))[1] = (d); \ + ((uint8_t*)(p))[0] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RL16 +# define AV_RL16(x) \ + ((((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, val) do { \ + uint16_t d = (val); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + } while(0) +#endif + +#ifndef AV_RB32 +# define AV_RB32(x) \ + (((uint32_t)((const uint8_t*)(x))[0] << 24) | \ + (((const uint8_t*)(x))[1] << 16) | \ + (((const uint8_t*)(x))[2] << 8) | \ + ((const uint8_t*)(x))[3]) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, val) do { \ + uint32_t d = (val); \ + ((uint8_t*)(p))[3] = (d); \ + ((uint8_t*)(p))[2] = (d)>>8; \ + ((uint8_t*)(p))[1] = (d)>>16; \ + ((uint8_t*)(p))[0] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RL32 +# define AV_RL32(x) \ + (((uint32_t)((const uint8_t*)(x))[3] << 24) | \ + (((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, val) do { \ + uint32_t d = (val); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + } while(0) +#endif + +#ifndef AV_RB64 +# define AV_RB64(x) \ + (((uint64_t)((const uint8_t*)(x))[0] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 8) | \ + (uint64_t)((const uint8_t*)(x))[7]) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, val) do { \ + uint64_t d = (val); \ + ((uint8_t*)(p))[7] = (d); \ + ((uint8_t*)(p))[6] = (d)>>8; \ + ((uint8_t*)(p))[5] = (d)>>16; \ + ((uint8_t*)(p))[4] = (d)>>24; \ + ((uint8_t*)(p))[3] = (d)>>32; \ + ((uint8_t*)(p))[2] = (d)>>40; \ + ((uint8_t*)(p))[1] = (d)>>48; \ + ((uint8_t*)(p))[0] = (d)>>56; \ + } while(0) +#endif + +#ifndef AV_RL64 +# define AV_RL64(x) \ + (((uint64_t)((const uint8_t*)(x))[7] << 56) | \ + ((uint64_t)((const uint8_t*)(x))[6] << 48) | \ + ((uint64_t)((const uint8_t*)(x))[5] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 8) | \ + (uint64_t)((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, val) do { \ + uint64_t d = (val); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + ((uint8_t*)(p))[4] = (d)>>32; \ + ((uint8_t*)(p))[5] = (d)>>40; \ + ((uint8_t*)(p))[6] = (d)>>48; \ + ((uint8_t*)(p))[7] = (d)>>56; \ + } while(0) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RN(s, p) AV_RB##s(p) +# define AV_WN(s, p, v) AV_WB##s(p, v) +#else +# define AV_RN(s, p) AV_RL##s(p) +# define AV_WN(s, p, v) AV_WL##s(p, v) +#endif + +#endif /* HAVE_FAST_UNALIGNED */ + +#ifndef AV_RN16 +# define AV_RN16(p) AV_RN(16, p) +#endif + +#ifndef AV_RN32 +# define AV_RN32(p) AV_RN(32, p) +#endif + +#ifndef AV_RN64 +# define AV_RN64(p) AV_RN(64, p) +#endif + +#ifndef AV_WN16 +# define AV_WN16(p, v) AV_WN(16, p, v) +#endif + +#ifndef AV_WN32 +# define AV_WN32(p, v) AV_WN(32, p, v) +#endif + +#ifndef AV_WN64 +# define AV_WN64(p, v) AV_WN(64, p, v) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RB(s, p) AV_RN##s(p) +# define AV_WB(s, p, v) AV_WN##s(p, v) +# define AV_RL(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WL(s, p, v) AV_WN##s(p, av_bswap##s(v)) +#else +# define AV_RB(s, p) av_bswap##s(AV_RN##s(p)) +# define AV_WB(s, p, v) AV_WN##s(p, av_bswap##s(v)) +# define AV_RL(s, p) AV_RN##s(p) +# define AV_WL(s, p, v) AV_WN##s(p, v) +#endif + +#define AV_RB8(x) (((const uint8_t*)(x))[0]) +#define AV_WB8(p, d) do { ((uint8_t*)(p))[0] = (d); } while(0) + +#define AV_RL8(x) AV_RB8(x) +#define AV_WL8(p, d) AV_WB8(p, d) + +#ifndef AV_RB16 +# define AV_RB16(p) AV_RB(16, p) +#endif +#ifndef AV_WB16 +# define AV_WB16(p, v) AV_WB(16, p, v) +#endif + +#ifndef AV_RL16 +# define AV_RL16(p) AV_RL(16, p) +#endif +#ifndef AV_WL16 +# define AV_WL16(p, v) AV_WL(16, p, v) +#endif + +#ifndef AV_RB32 +# define AV_RB32(p) AV_RB(32, p) +#endif +#ifndef AV_WB32 +# define AV_WB32(p, v) AV_WB(32, p, v) +#endif + +#ifndef AV_RL32 +# define AV_RL32(p) AV_RL(32, p) +#endif +#ifndef AV_WL32 +# define AV_WL32(p, v) AV_WL(32, p, v) +#endif + +#ifndef AV_RB64 +# define AV_RB64(p) AV_RB(64, p) +#endif +#ifndef AV_WB64 +# define AV_WB64(p, v) AV_WB(64, p, v) +#endif + +#ifndef AV_RL64 +# define AV_RL64(p) AV_RL(64, p) +#endif +#ifndef AV_WL64 +# define AV_WL64(p, v) AV_WL(64, p, v) +#endif + +#ifndef AV_RB24 +# define AV_RB24(x) \ + ((((const uint8_t*)(x))[0] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[2]) +#endif +#ifndef AV_WB24 +# define AV_WB24(p, d) do { \ + ((uint8_t*)(p))[2] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[0] = (d)>>16; \ + } while(0) +#endif + +#ifndef AV_RL24 +# define AV_RL24(x) \ + ((((const uint8_t*)(x))[2] << 16) | \ + (((const uint8_t*)(x))[1] << 8) | \ + ((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL24 +# define AV_WL24(p, d) do { \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + } while(0) +#endif + +#ifndef AV_RB48 +# define AV_RB48(x) \ + (((uint64_t)((const uint8_t*)(x))[0] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 8) | \ + (uint64_t)((const uint8_t*)(x))[5]) +#endif +#ifndef AV_WB48 +# define AV_WB48(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[5] = (d); \ + ((uint8_t*)(p))[4] = (d)>>8; \ + ((uint8_t*)(p))[3] = (d)>>16; \ + ((uint8_t*)(p))[2] = (d)>>24; \ + ((uint8_t*)(p))[1] = (d)>>32; \ + ((uint8_t*)(p))[0] = (d)>>40; \ + } while(0) +#endif + +#ifndef AV_RL48 +# define AV_RL48(x) \ + (((uint64_t)((const uint8_t*)(x))[5] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 8) | \ + (uint64_t)((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL48 +# define AV_WL48(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + ((uint8_t*)(p))[4] = (d)>>32; \ + ((uint8_t*)(p))[5] = (d)>>40; \ + } while(0) +#endif + +/* + * The AV_[RW]NA macros access naturally aligned data + * in a type-safe way. + */ + +#define AV_RNA(s, p) (((const av_alias##s*)(p))->u##s) +#define AV_WNA(s, p, v) (((av_alias##s*)(p))->u##s = (v)) + +#ifndef AV_RN16A +# define AV_RN16A(p) AV_RNA(16, p) +#endif + +#ifndef AV_RN32A +# define AV_RN32A(p) AV_RNA(32, p) +#endif + +#ifndef AV_RN64A +# define AV_RN64A(p) AV_RNA(64, p) +#endif + +#ifndef AV_WN16A +# define AV_WN16A(p, v) AV_WNA(16, p, v) +#endif + +#ifndef AV_WN32A +# define AV_WN32A(p, v) AV_WNA(32, p, v) +#endif + +#ifndef AV_WN64A +# define AV_WN64A(p, v) AV_WNA(64, p, v) +#endif + +#if AV_HAVE_BIGENDIAN +# define AV_RLA(s, p) av_bswap##s(AV_RN##s##A(p)) +# define AV_WLA(s, p, v) AV_WN##s##A(p, av_bswap##s(v)) +#else +# define AV_RLA(s, p) AV_RN##s##A(p) +# define AV_WLA(s, p, v) AV_WN##s##A(p, v) +#endif + +#ifndef AV_RL64A +# define AV_RL64A(p) AV_RLA(64, p) +#endif +#ifndef AV_WL64A +# define AV_WL64A(p, v) AV_WLA(64, p, v) +#endif + +/* + * The AV_COPYxxU macros are suitable for copying data to/from unaligned + * memory locations. + */ + +#define AV_COPYU(n, d, s) AV_WN##n(d, AV_RN##n(s)); + +#ifndef AV_COPY16U +# define AV_COPY16U(d, s) AV_COPYU(16, d, s) +#endif + +#ifndef AV_COPY32U +# define AV_COPY32U(d, s) AV_COPYU(32, d, s) +#endif + +#ifndef AV_COPY64U +# define AV_COPY64U(d, s) AV_COPYU(64, d, s) +#endif + +#ifndef AV_COPY128U +# define AV_COPY128U(d, s) \ + do { \ + AV_COPY64U(d, s); \ + AV_COPY64U((char *)(d) + 8, (const char *)(s) + 8); \ + } while(0) +#endif + +/* Parameters for AV_COPY*, AV_SWAP*, AV_ZERO* must be + * naturally aligned. They may be implemented using MMX, + * so emms_c() must be called before using any float code + * afterwards. + */ + +#define AV_COPY(n, d, s) \ + (((av_alias##n*)(d))->u##n = ((const av_alias##n*)(s))->u##n) + +#ifndef AV_COPY16 +# define AV_COPY16(d, s) AV_COPY(16, d, s) +#endif + +#ifndef AV_COPY32 +# define AV_COPY32(d, s) AV_COPY(32, d, s) +#endif + +#ifndef AV_COPY64 +# define AV_COPY64(d, s) AV_COPY(64, d, s) +#endif + +#ifndef AV_COPY128 +# define AV_COPY128(d, s) \ + do { \ + AV_COPY64(d, s); \ + AV_COPY64((char*)(d)+8, (char*)(s)+8); \ + } while(0) +#endif + +#define AV_SWAP(n, a, b) FFSWAP(av_alias##n, *(av_alias##n*)(a), *(av_alias##n*)(b)) + +#ifndef AV_SWAP64 +# define AV_SWAP64(a, b) AV_SWAP(64, a, b) +#endif + +#define AV_ZERO(n, d) (((av_alias##n*)(d))->u##n = 0) + +#ifndef AV_ZERO16 +# define AV_ZERO16(d) AV_ZERO(16, d) +#endif + +#ifndef AV_ZERO32 +# define AV_ZERO32(d) AV_ZERO(32, d) +#endif + +#ifndef AV_ZERO64 +# define AV_ZERO64(d) AV_ZERO(64, d) +#endif + +#ifndef AV_ZERO128 +# define AV_ZERO128(d) \ + do { \ + AV_ZERO64(d); \ + AV_ZERO64((char*)(d)+8); \ + } while(0) +#endif + +#endif /* AVUTIL_INTREADWRITE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/lfg.h b/thirdparty/user_include/ffmpeg/libavutil/lfg.h new file mode 100755 index 0000000000000000000000000000000000000000..2b669205d18995d12bd6689bd724fc33e07b803e --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/lfg.h @@ -0,0 +1,80 @@ +/* + * Lagged Fibonacci PRNG + * Copyright (c) 2008 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_LFG_H +#define AVUTIL_LFG_H + +#include + +/** + * Context structure for the Lagged Fibonacci PRNG. + * The exact layout, types and content of this struct may change and should + * not be accessed directly. Only its sizeof() is guranteed to stay the same + * to allow easy instanciation. + */ +typedef struct AVLFG { + unsigned int state[64]; + int index; +} AVLFG; + +void av_lfg_init(AVLFG *c, unsigned int seed); + +/** + * Seed the state of the ALFG using binary data. + * + * Return value: 0 on success, negative value (AVERROR) on failure. + */ +int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length); + +/** + * Get the next random unsigned 32-bit number using an ALFG. + * + * Please also consider a simple LCG like state= state*1664525+1013904223, + * it may be good enough and faster for your specific use case. + */ +static inline unsigned int av_lfg_get(AVLFG *c){ + unsigned a = c->state[c->index & 63] = c->state[(c->index-24) & 63] + c->state[(c->index-55) & 63]; + c->index += 1U; + return a; +} + +/** + * Get the next random unsigned 32-bit number using a MLFG. + * + * Please also consider av_lfg_get() above, it is faster. + */ +static inline unsigned int av_mlfg_get(AVLFG *c){ + unsigned int a= c->state[(c->index-55) & 63]; + unsigned int b= c->state[(c->index-24) & 63]; + a = c->state[c->index & 63] = 2*a*b+a+b; + c->index += 1U; + return a; +} + +/** + * Get the next two numbers generated by a Box-Muller Gaussian + * generator using the random numbers issued by lfg. + * + * @param out array where the two generated numbers are placed + */ +void av_bmg_get(AVLFG *lfg, double out[2]); + +#endif /* AVUTIL_LFG_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/log.h b/thirdparty/user_include/ffmpeg/libavutil/log.h new file mode 100755 index 0000000000000000000000000000000000000000..d9554e609d40027760b744e666db44984103072d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/log.h @@ -0,0 +1,362 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_LOG_H +#define AVUTIL_LOG_H + +#include +#include "avutil.h" +#include "attributes.h" +#include "version.h" + +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB ///< not part of ABI/API +}AVClassCategory; + +#define AV_IS_INPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT)) + +#define AV_IS_OUTPUT_DEVICE(category) \ + (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \ + ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT)) + +struct AVOptionRanges; + +/** + * Describe the class of an AVClass context structure. That is an + * arbitrary struct of which the first field is a pointer to an + * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). + */ +typedef struct AVClass { + /** + * The name of the class; usually it is the same name as the + * context structure type to which the AVClass is associated. + */ + const char* class_name; + + /** + * A pointer to a function which returns the name of a context + * instance ctx associated with the class. + */ + const char* (*item_name)(void* ctx); + + /** + * a pointer to the first option specified in the class if any or NULL + * + * @see av_set_default_options() + */ + const struct AVOption *option; + + /** + * LIBAVUTIL_VERSION with which this structure was created. + * This is used to allow fields to be added without requiring major + * version bumps everywhere. + */ + + int version; + + /** + * Offset in the structure where log_level_offset is stored. + * 0 means there is no such variable + */ + int log_level_offset_offset; + + /** + * Offset in the structure where a pointer to the parent context for + * logging is stored. For example a decoder could pass its AVCodecContext + * to eval as such a parent context, which an av_log() implementation + * could then leverage to display the parent context. + * The offset can be NULL. + */ + int parent_log_context_offset; + + /** + * Return next AVOptions-enabled child or NULL + */ + void* (*child_next)(void *obj, void *prev); + + /** + * Return an AVClass corresponding to the next potential + * AVOptions-enabled child. + * + * The difference between child_next and this is that + * child_next iterates over _already existing_ objects, while + * child_class_next iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_next)(const struct AVClass *prev); + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); +} AVClass; + +/** + * @addtogroup lavu_log + * + * @{ + * + * @defgroup lavu_log_constants Logging Constants + * + * @{ + */ + +/** + * Print no output. + */ +#define AV_LOG_QUIET -8 + +/** + * Something went really wrong and we will crash now. + */ +#define AV_LOG_PANIC 0 + +/** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ +#define AV_LOG_FATAL 8 + +/** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ +#define AV_LOG_ERROR 16 + +/** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ +#define AV_LOG_WARNING 24 + +/** + * Standard information. + */ +#define AV_LOG_INFO 32 + +/** + * Detailed information. + */ +#define AV_LOG_VERBOSE 40 + +/** + * Stuff which is only useful for libav* developers. + */ +#define AV_LOG_DEBUG 48 + +/** + * Extremely verbose debugging, useful for libav* development. + */ +#define AV_LOG_TRACE 56 + +#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET) + +/** + * @} + */ + +/** + * Sets additional colors for extended debugging sessions. + * @code + av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), "Message in purple\n"); + @endcode + * Requires 256color terminal support. Uses outside debugging is not + * recommended. + */ +#define AV_LOG_C(x) ((x) << 8) + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + */ +void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); + + +/** + * Send the specified message to the log if the level is less than or equal + * to the current av_log_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log_set_callback + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_vlog(void *avcl, int level, const char *fmt, va_list vl); + +/** + * Get the current log level + * + * @see lavu_log_constants + * + * @return Current log level + */ +int av_log_get_level(void); + +/** + * Set the log level + * + * @see lavu_log_constants + * + * @param level Logging level + */ +void av_log_set_level(int level); + +/** + * Set the logging callback + * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * + * @see av_log_default_callback + * + * @param callback A logging function with a compatible signature. + */ +void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)); + +/** + * Default logging callback + * + * It prints the message to stderr, optionally colorizing it. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct. + * @param level The importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant". + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param vl The arguments referenced by the format string. + */ +void av_log_default_callback(void *avcl, int level, const char *fmt, + va_list vl); + +/** + * Return the context name + * + * @param ctx The AVClass context + * + * @return The AVClass class_name + */ +const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formatted line; + * may be NULL if line_size is 0 + * @param line_size size of the buffer; at most line_size-1 characters will + * be written to the buffer, plus one null terminator + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + * @return Returns a negative value if an error occurred, otherwise returns + * the number of characters that would have been written for a + * sufficiently large buffer, not including the terminating null + * character. If the return value is not less than line_size, it means + * that the log message was truncated to fit the buffer. + */ +int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); + +/** + * Skip repeated messages, this requires the user app to use av_log() instead of + * (f)printf as the 2 would otherwise interfere and lead to + * "Last message repeated x times" messages below (f)printf messages with some + * bad luck. + * Also to receive the last, "last repeated" line if any, the user app must + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end + */ +#define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + +void av_log_set_flags(int arg); +int av_log_get_flags(void); + +/** + * @} + */ + +#endif /* AVUTIL_LOG_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/lzo.h b/thirdparty/user_include/ffmpeg/libavutil/lzo.h new file mode 100755 index 0000000000000000000000000000000000000000..c03403992d5f68e7fa8e0e1240522366bb99eee4 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/lzo.h @@ -0,0 +1,66 @@ +/* + * LZO 1x decompression + * copyright (c) 2006 Reimar Doeffinger + * + * 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 + */ + +#ifndef AVUTIL_LZO_H +#define AVUTIL_LZO_H + +/** + * @defgroup lavu_lzo LZO + * @ingroup lavu_crypto + * + * @{ + */ + +#include + +/** @name Error flags returned by av_lzo1x_decode + * @{ */ +/// end of the input buffer reached before decoding finished +#define AV_LZO_INPUT_DEPLETED 1 +/// decoded data did not fit into output buffer +#define AV_LZO_OUTPUT_FULL 2 +/// a reference to previously decoded data was wrong +#define AV_LZO_INVALID_BACKPTR 4 +/// a non-specific error in the compressed bitstream +#define AV_LZO_ERROR 8 +/** @} */ + +#define AV_LZO_INPUT_PADDING 8 +#define AV_LZO_OUTPUT_PADDING 12 + +/** + * @brief Decodes LZO 1x compressed data. + * @param out output buffer + * @param outlen size of output buffer, number of bytes left are returned here + * @param in input buffer + * @param inlen size of input buffer, number of bytes left are returned here + * @return 0 on success, otherwise a combination of the error flags above + * + * Make sure all buffers are appropriately padded, in must provide + * AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes. + */ +int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen); + +/** + * @} + */ + +#endif /* AVUTIL_LZO_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/macros.h b/thirdparty/user_include/ffmpeg/libavutil/macros.h new file mode 100755 index 0000000000000000000000000000000000000000..2007ee5619871558dd07cd516ca77324dcf75940 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/macros.h @@ -0,0 +1,50 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Utility Preprocessor macros + */ + +#ifndef AVUTIL_MACROS_H +#define AVUTIL_MACROS_H + +/** + * @addtogroup preproc_misc Preprocessor String Macros + * + * String manipulation macros + * + * @{ + */ + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define AV_GLUE(a, b) a ## b +#define AV_JOIN(a, b) AV_GLUE(a, b) + +/** + * @} + */ + +#define AV_PRAGMA(s) _Pragma(#s) + +#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +#endif /* AVUTIL_MACROS_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/mastering_display_metadata.h b/thirdparty/user_include/ffmpeg/libavutil/mastering_display_metadata.h new file mode 100755 index 0000000000000000000000000000000000000000..c23b07c3cd80d9239138eb5589b7203c2e11ccb0 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/mastering_display_metadata.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 Neil Birkbeck + * + * 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 + */ + +#ifndef AVUTIL_MASTERING_DISPLAY_METADATA_H +#define AVUTIL_MASTERING_DISPLAY_METADATA_H + +#include "frame.h" +#include "rational.h" + + +/** + * Mastering display metadata capable of representing the color volume of + * the display used to master the content (SMPTE 2086:2014). + * + * To be used as payload of a AVFrameSideData or AVPacketSideData with the + * appropriate type. + * + * @note The struct should be allocated with av_mastering_display_metadata_alloc() + * and its size is not a part of the public ABI. + */ +typedef struct AVMasteringDisplayMetadata { + /** + * CIE 1931 xy chromaticity coords of color primaries (r, g, b order). + */ + AVRational display_primaries[3][2]; + + /** + * CIE 1931 xy chromaticity coords of white point. + */ + AVRational white_point[2]; + + /** + * Min luminance of mastering display (cd/m^2). + */ + AVRational min_luminance; + + /** + * Max luminance of mastering display (cd/m^2). + */ + AVRational max_luminance; + + /** + * Flag indicating whether the display primaries (and white point) are set. + */ + int has_primaries; + + /** + * Flag indicating whether the luminance (min_ and max_) have been set. + */ + int has_luminance; + +} AVMasteringDisplayMetadata; + +/** + * Allocate an AVMasteringDisplayMetadata structure and set its fields to + * default values. The resulting struct can be freed using av_freep(). + * + * @return An AVMasteringDisplayMetadata filled with default values or NULL + * on failure. + */ +AVMasteringDisplayMetadata *av_mastering_display_metadata_alloc(void); + +/** + * Allocate a complete AVMasteringDisplayMetadata and add it to the frame. + * + * @param frame The frame which side data is added to. + * + * @return The AVMasteringDisplayMetadata structure to be filled by caller. + */ +AVMasteringDisplayMetadata *av_mastering_display_metadata_create_side_data(AVFrame *frame); + +/** + * Content light level needed by to transmit HDR over HDMI (CTA-861.3). + * + * To be used as payload of a AVFrameSideData or AVPacketSideData with the + * appropriate type. + * + * @note The struct should be allocated with av_content_light_metadata_alloc() + * and its size is not a part of the public ABI. + */ +typedef struct AVContentLightMetadata { + /** + * Max content light level (cd/m^2). + */ + unsigned MaxCLL; + + /** + * Max average light level per frame (cd/m^2). + */ + unsigned MaxFALL; +} AVContentLightMetadata; + +/** + * Allocate an AVContentLightMetadata structure and set its fields to + * default values. The resulting struct can be freed using av_freep(). + * + * @return An AVContentLightMetadata filled with default values or NULL + * on failure. + */ +AVContentLightMetadata *av_content_light_metadata_alloc(size_t *size); + +/** + * Allocate a complete AVContentLightMetadata and add it to the frame. + * + * @param frame The frame which side data is added to. + * + * @return The AVContentLightMetadata structure to be filled by caller. + */ +AVContentLightMetadata *av_content_light_metadata_create_side_data(AVFrame *frame); + +#endif /* AVUTIL_MASTERING_DISPLAY_METADATA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/mathematics.h b/thirdparty/user_include/ffmpeg/libavutil/mathematics.h new file mode 100755 index 0000000000000000000000000000000000000000..54901800ba6ad22fd33d6c8595400d378c7429ca --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/mathematics.h @@ -0,0 +1,242 @@ +/* + * copyright (c) 2005-2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @addtogroup lavu_math + * Mathematical utilities for working with timestamp and time base. + */ + +#ifndef AVUTIL_MATHEMATICS_H +#define AVUTIL_MATHEMATICS_H + +#include +#include +#include "attributes.h" +#include "rational.h" +#include "intfloat.h" + +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif +#ifndef M_LOG2_10 +#define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ +#endif +#ifndef M_PHI +#define M_PHI 1.61803398874989484820 /* phi / golden ratio */ +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#ifndef NAN +#define NAN av_int2float(0x7fc00000) +#endif +#ifndef INFINITY +#define INFINITY av_int2float(0x7f800000) +#endif + +/** + * @addtogroup lavu_math + * + * @{ + */ + +/** + * Rounding methods. + */ +enum AVRounding { + AV_ROUND_ZERO = 0, ///< Round toward zero. + AV_ROUND_INF = 1, ///< Round away from zero. + AV_ROUND_DOWN = 2, ///< Round toward -infinity. + AV_ROUND_UP = 3, ///< Round toward +infinity. + AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + /** + * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through + * unchanged, avoiding special cases for #AV_NOPTS_VALUE. + * + * Unlike other values of the enumeration AVRounding, this value is a + * bitmask that must be used in conjunction with another value of the + * enumeration through a bitwise OR, in order to set behavior for normal + * cases. + * + * @code{.c} + * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling 3: + * // Calculating 3 * 1 / 2 + * // 3 / 2 is rounded up to 2 + * // => 2 + * + * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + * // Rescaling AV_NOPTS_VALUE: + * // AV_NOPTS_VALUE == INT64_MIN + * // AV_NOPTS_VALUE is passed through + * // => AV_NOPTS_VALUE + * @endcode + */ + AV_ROUND_PASS_MINMAX = 8192, +}; + +/** + * Compute the greatest common divisor of two integer operands. + * + * @param a,b Operands + * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0; + * if a == 0 and b == 0, returns 0. + */ +int64_t av_const av_gcd(int64_t a, int64_t b); + +/** + * Rescale a 64-bit integer with rounding to nearest. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow. + * + * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; + +/** + * Rescale a 64-bit integer with specified rounding. + * + * The operation is mathematically equivalent to `a * b / c`, but writing that + * directly can overflow, and does not support different rounding methods. + * + * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() + */ +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd() + */ +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; + +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * The operation is mathematically equivalent to `a * bq / cq`. + * + * @see av_rescale(), av_rescale_rnd(), av_rescale_q() + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) av_const; + +/** + * Compare two timestamps each in its own time base. + * + * @return One of the following values: + * - -1 if `ts_a` is before `ts_b` + * - 1 if `ts_a` is after `ts_b` + * - 0 if they represent the same position + * + * @warning + * The result of the function is undefined if one of the timestamps is outside + * the `int64_t` range when represented in the other's timebase. + */ +int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); + +/** + * Compare the remainders of two integer operands divided by a common divisor. + * + * In other words, compare the least significant `log2(mod)` bits of integers + * `a` and `b`. + * + * @code{.c} + * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10 (0x1) < 0x02 % 0x10 (0x2) + * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02) + * @endcode + * + * @param a,b Operands + * @param mod Divisor; must be a power of 2 + * @return + * - a negative value if `a % mod < b % mod` + * - a positive value if `a % mod > b % mod` + * - zero if `a % mod == b % mod` + */ +int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); + +/** + * Rescale a timestamp while preserving known durations. + * + * This function is designed to be called per audio packet to scale the input + * timestamp to a different time base. Compared to a simple av_rescale_q() + * call, this function is robust against possible inconsistent frame durations. + * + * The `last` parameter is a state variable that must be preserved for all + * subsequent calls for the same stream. For the first call, `*last` should be + * initialized to #AV_NOPTS_VALUE. + * + * @param[in] in_tb Input time base + * @param[in] in_ts Input timestamp + * @param[in] fs_tb Duration time base; typically this is finer-grained + * (greater) than `in_tb` and `out_tb` + * @param[in] duration Duration till the next call to this function (i.e. + * duration of the current packet/frame) + * @param[in,out] last Pointer to a timestamp expressed in terms of + * `fs_tb`, acting as a state variable + * @param[in] out_tb Output timebase + * @return Timestamp expressed in terms of `out_tb` + * + * @note In the context of this function, "duration" is in term of samples, not + * seconds. + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param[in] ts Input timestamp + * @param[in] ts_tb Input timestamp time base + * @param[in] inc Value to be added + * @param[in] inc_tb Time base of `inc` + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + + +/** + * @} + */ + +#endif /* AVUTIL_MATHEMATICS_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/md5.h b/thirdparty/user_include/ffmpeg/libavutil/md5.h new file mode 100755 index 0000000000000000000000000000000000000000..ca72ccbf8371145a33c51886ad7af99a83405492 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/md5.h @@ -0,0 +1,98 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_md5 + * Public header for MD5 hash function implementation. + */ + +#ifndef AVUTIL_MD5_H +#define AVUTIL_MD5_H + +#include +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_md5 MD5 + * @ingroup lavu_hash + * MD5 hash function implementation. + * + * @{ + */ + +extern const int av_md5_size; + +struct AVMD5; + +/** + * Allocate an AVMD5 context. + */ +struct AVMD5 *av_md5_alloc(void); + +/** + * Initialize MD5 hashing. + * + * @param ctx pointer to the function context (of size av_md5_size) + */ +void av_md5_init(struct AVMD5 *ctx); + +/** + * Update hash value. + * + * @param ctx hash function context + * @param src input data to update hash with + * @param len input data length + */ +#if FF_API_CRYPTO_SIZE_T +void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, int len); +#else +void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, size_t len); +#endif + +/** + * Finish hashing and output digest value. + * + * @param ctx hash function context + * @param dst buffer where output digest value is stored + */ +void av_md5_final(struct AVMD5 *ctx, uint8_t *dst); + +/** + * Hash an array of data. + * + * @param dst The output buffer to write the digest into + * @param src The data to hash + * @param len The length of the data, in bytes + */ +#if FF_API_CRYPTO_SIZE_T +void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len); +#else +void av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len); +#endif + +/** + * @} + */ + +#endif /* AVUTIL_MD5_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/mem.h b/thirdparty/user_include/ffmpeg/libavutil/mem.h new file mode 100755 index 0000000000000000000000000000000000000000..5fb1a02dd9cf10a2e12784400c9e6da38d258cb3 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/mem.h @@ -0,0 +1,700 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_mem + * Memory handling functions + */ + +#ifndef AVUTIL_MEM_H +#define AVUTIL_MEM_H + +#include +#include + +#include "attributes.h" +#include "error.h" +#include "avutil.h" + +/** + * @addtogroup lavu_mem + * Utilities for manipulating memory. + * + * FFmpeg has several applications of memory that are not required of a typical + * program. For example, the computing-heavy components like video decoding and + * encoding can be sped up significantly through the use of aligned memory. + * + * However, for each of FFmpeg's applications of memory, there might not be a + * recognized or standardized API for that specific use. Memory alignment, for + * instance, varies wildly depending on operating systems, architectures, and + * compilers. Hence, this component of @ref libavutil is created to make + * dealing with memory consistently possible on all platforms. + * + * @{ + * + * @defgroup lavu_mem_macros Alignment Macros + * Helper macros for declaring aligned variables. + * @{ + */ + +/** + * @def DECLARE_ALIGNED(n,t,v) + * Declare a variable that is aligned in memory. + * + * @code{.c} + * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42; + * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128]; + * + * // The default-alignment equivalent would be + * uint16_t aligned_int = 42; + * uint8_t aligned_array[128]; + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_ALIGNED(n,t,v) + * Declare an aligned variable appropriate for use in inline assembly code. + * + * @code{.c} + * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_CONST(n,t,v) + * Declare a static constant aligned variable appropriate for use in inline + * assembly code. + * + * @code{.c} + * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__DJGPP__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v +#elif defined(__GNUC__) || defined(__clang__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_attrs Function Attributes + * Function attributes applicable to memory handling functions. + * + * These function attributes can help compilers emit more useful warnings, or + * generate better code. + * @{ + */ + +/** + * @def av_malloc_attrib + * Function attribute denoting a malloc-like function. + * + * @see Function attribute `malloc` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(3,1) + #define av_malloc_attrib __attribute__((__malloc__)) +#else + #define av_malloc_attrib +#endif + +/** + * @def av_alloc_size(...) + * Function attribute used on a function that allocates memory, whose size is + * given by the specified parameter(s). + * + * @code{.c} + * void *av_malloc(size_t size) av_alloc_size(1); + * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2); + * @endcode + * + * @param ... One or two parameter indexes, separated by a comma + * + * @see Function attribute `alloc_size` in GCC's documentation + */ + +#if AV_GCC_VERSION_AT_LEAST(4,3) + #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) +#else + #define av_alloc_size(...) +#endif + +/** + * @} + */ + +/** + * @defgroup lavu_mem_funcs Heap Management + * Functions responsible for allocating, freeing, and copying memory. + * + * All memory allocation functions have a built-in upper limit of `INT_MAX` + * bytes. This may be changed with av_max_alloc(), although exercise extreme + * caution when doing so. + * + * @{ + */ + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU). + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_mallocz() + */ +void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block with alignment suitable for all memory accesses + * (including vectors if available on the CPU) and zero all the bytes of the + * block. + * + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + * @see av_malloc() + */ +void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); + +/** + * Allocate a memory block for an array with av_malloc(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of element + * @param size Size of a single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * @see av_malloc() + */ +av_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size); + +/** + * Allocate a memory block for an array with av_mallocz(). + * + * The allocated memory will have size `size * nmemb` bytes. + * + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to the allocated block, or `NULL` if the block cannot + * be allocated + * + * @see av_mallocz() + * @see av_malloc_array() + */ +av_alloc_size(1, 2) void *av_mallocz_array(size_t nmemb, size_t size); + +/** + * Non-inlined equivalent of av_mallocz_array(). + * + * Created for symmetry with the calloc() C function. + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib; + +/** + * Allocate, reallocate, or free a block of memory. + * + * If `ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param size Size in bytes of the memory block to be allocated or + * reallocated + * + * @return Pointer to a newly-reallocated block or `NULL` if the block + * cannot be reallocated or the function is used to free the memory block + * + * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be + * correctly aligned. + * @see av_fast_realloc() + * @see av_reallocp() + */ +void *av_realloc(void *ptr, size_t size) av_alloc_size(2); + +/** + * Allocate, reallocate, or free a block of memory through a pointer to a + * pointer. + * + * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is + * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or + * shrink that block of memory according to `size`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already allocated + * with av_realloc(), or a pointer to `NULL`. The pointer + * is updated on success, or freed on failure. + * @param[in] size Size in bytes for the memory block to be allocated or + * reallocated + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +av_warn_unused_result +int av_reallocp(void *ptr, size_t size); + +/** + * Allocate, reallocate, or free a block of memory. + * + * This function does the same thing as av_realloc(), except: + * - It takes two size arguments and allocates `nelem * elsize` bytes, + * after checking the result of the multiplication for integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic + * @code{.c} + * buf = realloc(buf); + * if (!buf) + * return -1; + * @endcode + * pattern. + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate, reallocate, or free an array. + * + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. If + * `nmemb` is zero, free the memory block pointed to by `ptr`. + * + * @param ptr Pointer to a memory block already allocated with + * av_realloc() or `NULL` + * @param nmemb Number of elements in the array + * @param size Size of the single element of the array + * + * @return Pointer to a newly-reallocated block or NULL if the block + * cannot be reallocated or the function is used to free the memory block + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + * @see av_reallocp_array() + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate, reallocate, or free an array through a pointer to a pointer. + * + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. If `nmemb` is + * zero, free the memory block pointed to by `*ptr`. + * + * @param[in,out] ptr Pointer to a pointer to a memory block already + * allocated with av_realloc(), or a pointer to `NULL`. + * The pointer is updated on success, or freed on failure. + * @param[in] nmemb Number of elements + * @param[in] size Size of the single element + * + * @return Zero on success, an AVERROR error code on failure + * + * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be + * correctly aligned. + */ +int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + +/** + * Reallocate the given buffer if it is not large enough, otherwise do nothing. + * + * If the given buffer is `NULL`, then a new uninitialized buffer is allocated. + * + * If the given buffer is not large enough, and reallocation fails, `NULL` is + * returned and `*size` is set to 0, but the original buffer is not changed or + * freed. + * + * A typical use pattern follows: + * + * @code{.c} + * uint8_t *buf = ...; + * uint8_t *new_buf = av_fast_realloc(buf, ¤t_size, size_needed); + * if (!new_buf) { + * // Allocation failed; clean up original buffer + * av_freep(&buf); + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Already allocated buffer, or `NULL` + * @param[in,out] size Pointer to the size of buffer `ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `ptr` + * @return `ptr` if the buffer is large enough, a pointer to newly reallocated + * buffer if the buffer was not large enough, or `NULL` in case of + * error + * @see av_realloc() + * @see av_fast_malloc() + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc(), the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special handling to + * avoid memleaks is necessary. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @code{.c} + * uint8_t *buf = ...; + * av_fast_malloc(&buf, ¤t_size, size_needed); + * if (!buf) { + * // Allocation failed; buf already freed + * return AVERROR(ENOMEM); + * } + * @endcode + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_realloc() + * @see av_fast_mallocz() + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate and clear a buffer, reusing the given one if large enough. + * + * Like av_fast_malloc(), but all newly allocated space is initially cleared. + * Reused buffer is not cleared. + * + * `*ptr` is allowed to be `NULL`, in which case allocation always happens if + * `size_needed` is greater than 0. + * + * @param[in,out] ptr Pointer to pointer to an already allocated buffer. + * `*ptr` will be overwritten with pointer to new + * buffer on success or `NULL` on failure + * @param[in,out] size Pointer to the size of buffer `*ptr`. `*size` is + * updated to the new allocated size, in particular 0 + * in case of failure. + * @param[in] min_size Desired minimal size of buffer `*ptr` + * @see av_fast_malloc() + */ +void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family. + * + * @param ptr Pointer to the memory block which should be freed. + * + * @note `ptr = NULL` is explicitly allowed. + * @note It is recommended that you use av_freep() instead, to prevent leaving + * behind dangling pointers. + * @see av_freep() + */ +void av_free(void *ptr); + +/** + * Free a memory block which has been allocated with a function of av_malloc() + * or av_realloc() family, and set the pointer pointing to it to `NULL`. + * + * @code{.c} + * uint8_t *buf = av_malloc(16); + * av_free(buf); + * // buf now contains a dangling pointer to freed memory, and accidental + * // dereference of buf will result in a use-after-free, which may be a + * // security risk. + * + * uint8_t *buf = av_malloc(16); + * av_freep(&buf); + * // buf is now NULL, and accidental dereference will only result in a + * // NULL-pointer dereference. + * @endcode + * + * @param ptr Pointer to the pointer to the memory block which should be freed + * @note `*ptr = NULL` is safe and leads to no action. + * @see av_free() + */ +void av_freep(void *ptr); + +/** + * Duplicate a string. + * + * @param s String to be duplicated + * @return Pointer to a newly-allocated string containing a + * copy of `s` or `NULL` if the string cannot be allocated + * @see av_strndup() + */ +char *av_strdup(const char *s) av_malloc_attrib; + +/** + * Duplicate a substring of a string. + * + * @param s String to be duplicated + * @param len Maximum length of the resulting string (not counting the + * terminating byte) + * @return Pointer to a newly-allocated string containing a + * substring of `s` or `NULL` if the string cannot be allocated + */ +char *av_strndup(const char *s, size_t len) av_malloc_attrib; + +/** + * Duplicate a buffer with av_malloc(). + * + * @param p Buffer to be duplicated + * @param size Size in bytes of the buffer copied + * @return Pointer to a newly allocated buffer containing a + * copy of `p` or `NULL` if the buffer cannot be allocated + */ +void *av_memdup(const void *p, size_t size); + +/** + * Overlapping memcpy() implementation. + * + * @param dst Destination buffer + * @param back Number of bytes back to start copying (i.e. the initial size of + * the overlapping window); must be > 0 + * @param cnt Number of bytes to copy; must be >= 0 + * + * @note `cnt > back` is valid, this will copy the bytes we just copied, + * thus creating a repeating pattern with a period length of `back`. + */ +void av_memcpy_backptr(uint8_t *dst, int back, int cnt); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_dynarray Dynamic Array + * + * Utilities to make an array grow when needed. + * + * Sometimes, the programmer would want to have an array that can grow when + * needed. The libavutil dynamic array utilities fill that need. + * + * libavutil supports two systems of appending elements onto a dynamically + * allocated array, the first one storing the pointer to the value in the + * array, and the second storing the value directly. In both systems, the + * caller is responsible for maintaining a variable containing the length of + * the array, as well as freeing of the array after use. + * + * The first system stores pointers to values in a block of dynamically + * allocated memory. Since only pointers are stored, the function does not need + * to know the size of the type. Both av_dynarray_add() and + * av_dynarray_add_nofree() implement this system. + * + * @code + * type **array = NULL; //< an array of pointers to values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * av_dynarray_add(&array, &nb, &to_be_added); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * av_dynarray_add(&array, &nb, &to_be_added2); + * if (nb == 0) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // &to_be_added == array[0] + * // &to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * The second system stores the value directly in a block of memory. As a + * result, the function has to know the size of the type. av_dynarray2_add() + * implements this mechanism. + * + * @code + * type *array = NULL; //< an array of values + * int nb = 0; //< a variable to keep track of the length of the array + * + * type to_be_added = ...; + * type to_be_added2 = ...; + * + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL); + * if (!addr) + * return AVERROR(ENOMEM); + * memcpy(addr, &to_be_added, sizeof(to_be_added)); + * + * // Shortcut of the above. + * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), + * (const void *)&to_be_added2); + * if (!addr) + * return AVERROR(ENOMEM); + * + * // Now: + * // nb == 2 + * // to_be_added == array[0] + * // to_be_added2 == array[1] + * + * av_freep(&array); + * @endcode + * + * @{ + */ + +/** + * Add the pointer to an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem Element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @return >=0 on success, negative otherwise + * @see av_dynarray_add(), av_dynarray2_add() + */ +av_warn_unused_result +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size `elem_size` to a dynamic array. + * + * The array is reallocated when its number of elements reaches powers of 2. + * Therefore, the amortized cost of adding an element is constant. + * + * In case of success, the pointer to the array is updated in order to + * point to the new grown array, and the number pointed to by `nb_ptr` + * is incremented. + * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and + * `*nb_ptr` is set to 0. + * + * @param[in,out] tab_ptr Pointer to the array to grow + * @param[in,out] nb_ptr Pointer to the number of elements in the array + * @param[in] elem_size Size in bytes of an element in the array + * @param[in] elem_data Pointer to the data of the element to add. If + * `NULL`, the space of the newly added element is + * allocated but left uninitialized. + * + * @return Pointer to the data of the element to copy in the newly allocated + * space + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * @} + */ + +/** + * @defgroup lavu_mem_misc Miscellaneous Functions + * + * Other functions related to memory allocation. + * + * @{ + */ + +/** + * Multiply two `size_t` values checking for overflow. + * + * @param[in] a,b Operands of multiplication + * @param[out] r Pointer to the result of the operation + * @return 0 on success, AVERROR(EINVAL) on overflow + */ +static inline int av_size_mult(size_t a, size_t b, size_t *r) +{ + size_t t = a * b; + /* Hack inspired from glibc: don't try the division if nelem and elsize + * are both less than sqrt(SIZE_MAX). */ + if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) + return AVERROR(EINVAL); + *r = t; + return 0; +} + +/** + * Set the maximum size that may be allocated in one block. + * + * The value specified with this function is effective for all libavutil's @ref + * lavu_mem_funcs "heap management functions." + * + * By default, the max value is defined as `INT_MAX`. + * + * @param max Value to be set as the new maximum size + * + * @warning Exercise extreme caution when using this function. Don't touch + * this if you do not understand the full consequence of doing so. + */ +void av_max_alloc(size_t max); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_MEM_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/motion_vector.h b/thirdparty/user_include/ffmpeg/libavutil/motion_vector.h new file mode 100755 index 0000000000000000000000000000000000000000..ec295563889a0a79ab9a8de8c147292fab1bb7ee --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/motion_vector.h @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#ifndef AVUTIL_MOTION_VECTOR_H +#define AVUTIL_MOTION_VECTOR_H + +#include + +typedef struct AVMotionVector { + /** + * Where the current macroblock comes from; negative value when it comes + * from the past, positive value when it comes from the future. + * XXX: set exact relative ref frame reference instead of a +/- 1 "direction". + */ + int32_t source; + /** + * Width and height of the block. + */ + uint8_t w, h; + /** + * Absolute source position. Can be outside the frame area. + */ + int16_t src_x, src_y; + /** + * Absolute destination position. Can be outside the frame area. + */ + int16_t dst_x, dst_y; + /** + * Extra flag information. + * Currently unused. + */ + uint64_t flags; + /** + * Motion vector + * src_x = dst_x + motion_x / motion_scale + * src_y = dst_y + motion_y / motion_scale + */ + int32_t motion_x, motion_y; + uint16_t motion_scale; +} AVMotionVector; + +#endif /* AVUTIL_MOTION_VECTOR_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/murmur3.h b/thirdparty/user_include/ffmpeg/libavutil/murmur3.h new file mode 100755 index 0000000000000000000000000000000000000000..1b09175c1ec21f0595f8aca8cf400f3a6c741d69 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/murmur3.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2013 Reimar Döffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_murmur3 + * Public header for MurmurHash3 hash function implementation. + */ + +#ifndef AVUTIL_MURMUR3_H +#define AVUTIL_MURMUR3_H + +#include + +#include "version.h" + +/** + * @defgroup lavu_murmur3 Murmur3 + * @ingroup lavu_hash + * MurmurHash3 hash function implementation. + * + * MurmurHash3 is a non-cryptographic hash function, of which three + * incompatible versions were created by its inventor Austin Appleby: + * + * - 32-bit output + * - 128-bit output for 32-bit platforms + * - 128-bit output for 64-bit platforms + * + * FFmpeg only implements the last variant: 128-bit output designed for 64-bit + * platforms. Even though the hash function was designed for 64-bit platforms, + * the function in reality works on 32-bit systems too, only with reduced + * performance. + * + * @anchor lavu_murmur3_seedinfo + * By design, MurmurHash3 requires a seed to operate. In response to this, + * libavutil provides two functions for hash initiation, one that requires a + * seed (av_murmur3_init_seeded()) and one that uses a fixed arbitrary integer + * as the seed, and therefore does not (av_murmur3_init()). + * + * To make hashes comparable, you should provide the same seed for all calls to + * this hash function -- if you are supplying one yourself, that is. + * + * @{ + */ + +/** + * Allocate an AVMurMur3 hash context. + * + * @return Uninitialized hash context or `NULL` in case of error + */ +struct AVMurMur3 *av_murmur3_alloc(void); + +/** + * Initialize or reinitialize an AVMurMur3 hash context with a seed. + * + * @param[out] c Hash context + * @param[in] seed Random seed + * + * @see av_murmur3_init() + * @see @ref lavu_murmur3_seedinfo "Detailed description" on a discussion of + * seeds for MurmurHash3. + */ +void av_murmur3_init_seeded(struct AVMurMur3 *c, uint64_t seed); + +/** + * Initialize or reinitialize an AVMurMur3 hash context. + * + * Equivalent to av_murmur3_init_seeded() with a built-in seed. + * + * @param[out] c Hash context + * + * @see av_murmur3_init_seeded() + * @see @ref lavu_murmur3_seedinfo "Detailed description" on a discussion of + * seeds for MurmurHash3. + */ +void av_murmur3_init(struct AVMurMur3 *c); + +/** + * Update hash context with new data. + * + * @param[out] c Hash context + * @param[in] src Input data to update hash with + * @param[in] len Number of bytes to read from `src` + */ +#if FF_API_CRYPTO_SIZE_T +void av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, int len); +#else +void av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, size_t len); +#endif + +/** + * Finish hashing and output digest value. + * + * @param[in,out] c Hash context + * @param[out] dst Buffer where output digest value is stored + */ +void av_murmur3_final(struct AVMurMur3 *c, uint8_t dst[16]); + +/** + * @} + */ + +#endif /* AVUTIL_MURMUR3_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/opt.h b/thirdparty/user_include/ffmpeg/libavutil/opt.h new file mode 100755 index 0000000000000000000000000000000000000000..39f4a8dda0e798ee595f147d6a7e85d89ad47e99 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/opt.h @@ -0,0 +1,865 @@ +/* + * AVOptions + * copyright (c) 2005 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_OPT_H +#define AVUTIL_OPT_H + +/** + * @file + * AVOptions + */ + +#include "rational.h" +#include "avutil.h" +#include "dict.h" +#include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" +#include "version.h" + +/** + * @defgroup avoptions AVOptions + * @ingroup lavu_data + * @{ + * AVOptions provide a generic system to declare options on arbitrary structs + * ("objects"). An option can have a help text, a type and a range of possible + * values. Options may then be enumerated, read and written to. + * + * @section avoptions_implement Implementing AVOptions + * This section describes how to add AVOptions capabilities to a struct. + * + * All AVOptions-related information is stored in an AVClass. Therefore + * the first member of the struct should be a pointer to an AVClass describing it. + * The option field of the AVClass must be set to a NULL-terminated static array + * of AVOptions. Each AVOption must have a non-empty name, a type, a default + * value and for number-type AVOptions also a range of allowed values. It must + * also declare an offset in bytes from the start of the struct, where the field + * associated with this AVOption is located. Other fields in the AVOption struct + * should also be set when applicable, but are not required. + * + * The following example illustrates an AVOptions-enabled struct: + * @code + * typedef struct test_struct { + * const AVClass *class; + * int int_opt; + * char *str_opt; + * uint8_t *bin_opt; + * int bin_len; + * } test_struct; + * + * static const AVOption test_options[] = { + * { "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt), + * AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX }, + * { "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt), + * AV_OPT_TYPE_STRING }, + * { "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt), + * AV_OPT_TYPE_BINARY }, + * { NULL }, + * }; + * + * static const AVClass test_class = { + * .class_name = "test class", + * .item_name = av_default_item_name, + * .option = test_options, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * @endcode + * + * Next, when allocating your struct, you must ensure that the AVClass pointer + * is set to the correct value. Then, av_opt_set_defaults() can be called to + * initialize defaults. After that the struct is ready to be used with the + * AVOptions API. + * + * When cleaning up, you may use the av_opt_free() function to automatically + * free all the allocated string and binary options. + * + * Continuing with the above example: + * + * @code + * test_struct *alloc_test_struct(void) + * { + * test_struct *ret = av_mallocz(sizeof(*ret)); + * ret->class = &test_class; + * av_opt_set_defaults(ret); + * return ret; + * } + * void free_test_struct(test_struct **foo) + * { + * av_opt_free(*foo); + * av_freep(foo); + * } + * @endcode + * + * @subsection avoptions_implement_nesting Nesting + * It may happen that an AVOptions-enabled struct contains another + * AVOptions-enabled struct as a member (e.g. AVCodecContext in + * libavcodec exports generic options, while its priv_data field exports + * codec-specific options). In such a case, it is possible to set up the + * parent struct to export a child's options. To do that, simply + * implement AVClass.child_next() and AVClass.child_class_next() in the + * parent struct's AVClass. + * Assuming that the test_struct from above now also contains a + * child_struct field: + * + * @code + * typedef struct child_struct { + * AVClass *class; + * int flags_opt; + * } child_struct; + * static const AVOption child_opts[] = { + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX }, + * { NULL }, + * }; + * static const AVClass child_class = { + * .class_name = "child class", + * .item_name = av_default_item_name, + * .option = child_opts, + * .version = LIBAVUTIL_VERSION_INT, + * }; + * + * void *child_next(void *obj, void *prev) + * { + * test_struct *t = obj; + * if (!prev && t->child_struct) + * return t->child_struct; + * return NULL + * } + * const AVClass child_class_next(const AVClass *prev) + * { + * return prev ? NULL : &child_class; + * } + * @endcode + * Putting child_next() and child_class_next() as defined above into + * test_class will now make child_struct's options accessible through + * test_struct (again, proper setup as described above needs to be done on + * child_struct right after it is created). + * + * From the above example it might not be clear why both child_next() + * and child_class_next() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_next() + * iterates over all possible child classes. E.g. if an AVCodecContext + * was initialized to use a codec which has private options, then its + * child_next() will return AVCodecContext.priv_data and finish + * iterating. OTOH child_class_next() on AVCodecContext.av_class will + * iterate over all available codecs with private options. + * + * @subsection avoptions_implement_named_constants Named constants + * It is possible to create named constants for options. Simply set the unit + * field of the option the constants should apply to a string and + * create the constants themselves as options of type AV_OPT_TYPE_CONST + * with their unit field set to the same string. + * Their default_val field should contain the value of the named + * constant. + * For example, to add some named constants for the test_flags option + * above, put the following into the child_opts array: + * @code + * { "test_flags", "This is a test option of flags type.", + * offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" }, + * { "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" }, + * @endcode + * + * @section avoptions_use Using AVOptions + * This section deals with accessing options in an AVOptions-enabled struct. + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or + * AVFormatContext in libavformat. + * + * @subsection avoptions_use_examine Examining AVOptions + * The basic functions for examining options are av_opt_next(), which iterates + * over all options defined for one object, and av_opt_find(), which searches + * for an option with the given name. + * + * The situation is more complicated with nesting. An AVOptions-enabled struct + * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag + * to av_opt_find() will make the function search children recursively. + * + * For enumerating there are basically two cases. The first is when you want to + * get all options that may potentially exist on the struct and its children + * (e.g. when constructing documentation). In that case you should call + * av_opt_child_class_next() recursively on the parent struct's AVClass. The + * second case is when you have an already initialized struct with all its + * children and you want to get all options that can be actually written or read + * from it. In that case you should call av_opt_child_next() recursively (and + * av_opt_next() on each result). + * + * @subsection avoptions_use_get_set Reading and writing AVOptions + * When setting options, you often have a string read directly from the + * user. In such a case, simply passing it to av_opt_set() is enough. For + * non-string type options, av_opt_set() will parse the string according to the + * option type. + * + * Similarly av_opt_get() will read any option type and convert it to a string + * which will be returned. Do not forget that the string is allocated, so you + * have to free it with av_free(). + * + * In some cases it may be more convenient to put all options into an + * AVDictionary and call av_opt_set_dict() on it. A specific case of this + * are the format/codec open functions in lavf/lavc which take a dictionary + * filled with option as a parameter. This makes it possible to set some options + * that cannot be set otherwise, since e.g. the input file format is not known + * before the file is actually opened. + */ + +enum AVOptionType{ + AV_OPT_TYPE_FLAGS, + AV_OPT_TYPE_INT, + AV_OPT_TYPE_INT64, + AV_OPT_TYPE_DOUBLE, + AV_OPT_TYPE_FLOAT, + AV_OPT_TYPE_STRING, + AV_OPT_TYPE_RATIONAL, + AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, + AV_OPT_TYPE_CONST, + AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT, + AV_OPT_TYPE_SAMPLE_FMT, + AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational + AV_OPT_TYPE_DURATION, + AV_OPT_TYPE_COLOR, + AV_OPT_TYPE_CHANNEL_LAYOUT, + AV_OPT_TYPE_BOOL, +}; + +/** + * AVOption + */ +typedef struct AVOption { + const char *name; + + /** + * short English help text + * @todo What about other languages? + */ + const char *help; + + /** + * The offset relative to the context structure where the option + * value is stored. It should be 0 for named constants. + */ + int offset; + enum AVOptionType type; + + /** + * the default value for scalar options + */ + union { + int64_t i64; + double dbl; + const char *str; + /* TODO those are unused now */ + AVRational q; + } default_val; + double min; ///< minimum valid value for the option + double max; ///< maximum valid value for the option + + int flags; +#define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding +#define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding +#define AV_OPT_FLAG_AUDIO_PARAM 8 +#define AV_OPT_FLAG_VIDEO_PARAM 16 +#define AV_OPT_FLAG_SUBTITLE_PARAM 32 +/** + * The option is intended for exporting values to the caller. + */ +#define AV_OPT_FLAG_EXPORT 64 +/** + * The option may not be set through the AVOptions API, only read. + * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. + */ +#define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering +#define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information +//FIXME think about enc-audio, ... style flags + + /** + * The logical unit to which the option belongs. Non-constant + * options and corresponding named constants share the same + * unit. May be NULL. + */ + const char *unit; +} AVOption; + +/** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + +/** + * Show the obj options. + * + * @param req_flags requested flags for the options to show. Show only the + * options for which it is opt->flags & req_flags. + * @param rej_flags rejected flags for the options to show. Show only the + * options for which it is !(opt->flags & req_flags). + * @param av_log_obj log context to use for showing the options + */ +int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); + +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ +void av_opt_set_defaults(void *s); + +/** + * Set the values of all AVOption fields to their default values. Only these + * AVOption fields for which (opt->flags & mask) == flags will have their + * default applied to s. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + * @param mask combination of AV_OPT_FLAG_* + * @param flags combination of AV_OPT_FLAG_* + */ +void av_opt_set_defaults2(void *s, int mask, int flags); + +/** + * Parse the key/value pairs list in opts. For each key/value pair + * found, stores the value in the field in ctx that is named like the + * key. ctx must be an AVClass context, storing is done using + * AVOptions. + * + * @param opts options string to parse, may be NULL + * @param key_val_sep a 0-terminated list of characters used to + * separate key from value + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other + * @return the number of successfully set key/value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_opt_set() if a key/value pair + * cannot be set + */ +int av_set_options_string(void *ctx, const char *opts, + const char *key_val_sep, const char *pairs_sep); + +/** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** + * Free all allocated objects in obj. + */ +void av_opt_free(void *obj); + +/** + * Check whether a particular flag is set in a flags field. + * + * @param field_name the name of the flag field option + * @param flag_name the name of the flag to check + * @return non-zero if the flag is set, zero if the flag isn't set, + * isn't of the right type, or the flags field doesn't exist. + */ +int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict(void *obj, struct AVDictionary **options); + + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + +/** + * @defgroup opt_eval_funcs Evaluating option strings + * @{ + * This group of functions can be used to evaluate option strings + * and get numbers out of them. They do the same thing as av_opt_set(), + * except the result is written into the caller-supplied pointer. + * + * @param obj a struct whose first element is a pointer to AVClass. + * @param o an option for which the string is to be evaluated. + * @param val string to be evaluated. + * @param *_out value of the string will be written here. + * + * @return 0 on success, a negative number on failure. + */ +int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out); +int av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out); +int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out); +int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out); +int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out); +int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out); +/** + * @} + */ + +#define AV_OPT_SEARCH_CHILDREN (1 << 0) /**< Search in possible children of the + given object first. */ +/** + * The obj passed to av_opt_find() is fake -- only a double pointer to AVClass + * instead of a required pointer to a struct containing AVClass. This is + * useful for searching for options without needing to allocate the corresponding + * object. + */ +#define AV_OPT_SEARCH_FAKE_OBJ (1 << 1) + +/** + * In av_opt_get, return NULL if the option has a pointer type and is set to NULL, + * rather than returning an empty string. + */ +#define AV_OPT_ALLOW_NULL (1 << 2) + +/** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return A pointer to the option found, or NULL if no option + * was found. + * + * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable + * directly with av_opt_set(). Use special calls which take an options + * AVDictionary (e.g. avformat_open_input()) to set options found with this + * flag. + */ +const AVOption *av_opt_find(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags); + +/** + * Look for an option in an object. Consider only options which + * have all the specified flags set. + * + * @param[in] obj A pointer to a struct whose first element is a + * pointer to an AVClass. + * Alternatively a double pointer to an AVClass, if + * AV_OPT_SEARCH_FAKE_OBJ search flag is set. + * @param[in] name The name of the option to look for. + * @param[in] unit When searching for named constants, name of the unit + * it belongs to. + * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * @param[out] target_obj if non-NULL, an object to which the option belongs will be + * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present + * in search_flags. This parameter is ignored if search_flags contain + * AV_OPT_SEARCH_FAKE_OBJ. + * + * @return A pointer to the option found, or NULL if no option + * was found. + */ +const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, + int opt_flags, int search_flags, void **target_obj); + +/** + * Iterate over all AVOptions belonging to obj. + * + * @param obj an AVOptions-enabled struct or a double pointer to an + * AVClass describing it. + * @param prev result of the previous call to av_opt_next() on this object + * or NULL + * @return next AVOption or NULL + */ +const AVOption *av_opt_next(const void *obj, const AVOption *prev); + +/** + * Iterate over AVOptions-enabled children of obj. + * + * @param prev result of a previous call to this function or NULL + * @return next AVOptions-enabled child or NULL + */ +void *av_opt_child_next(void *obj, void *prev); + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param prev result of a previous call to this function or NULL + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev); + +/** + * @defgroup opt_set_funcs Option setting functions + * @{ + * Those functions set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. In case of av_opt_set() if the field is not + * of a string type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be set on a child of obj. + * + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + */ +int av_opt_set (void *obj, const char *name, const char *val, int search_flags); +int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags); +int av_opt_set_double (void *obj, const char *name, double val, int search_flags); +int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); +/** + * @note Any old dictionary present is discarded and replaced with a copy of the new one. The + * caller still owns val is and responsible for freeing it. + */ +int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) + +/** + * @} + */ + +/** + * @defgroup opt_get_funcs Option getting functions + * @{ + * Those functions get a value of the option with the given name from an object. + * + * @param[in] obj a struct whose first element is a pointer to an AVClass. + * @param[in] name name of the option to get. + * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN + * is passed here, then the option may be found in a child of obj. + * @param[out] out_val value of the option will be written here + * @return >=0 on success, a negative error code otherwise + */ +/** + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller + * + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the option has + * AV_OPT_TYPE_STRING or AV_OPT_TYPE_BINARY and is set to NULL, *out_val will be set + * to NULL instead of an allocated empty string. + */ +int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); +int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); +int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val); +int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); +/** + * @param[out] out_val The returned dictionary is a copy of the actual value and must + * be freed with av_dict_free() by the caller + */ +int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val); +/** + * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Copy options from src object into dest object. + * + * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object. + * Original memory allocated for such options is freed unless both src and dest options points to the same memory. + * + * @param dest Object to copy from + * @param src Object to copy into + * @return 0 on success, negative on error + */ +int av_opt_copy(void *dest, const void *src); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** + * Check if given option is set to its default value. + * + * Options o must belong to the obj. This function must not be called to check child's options state. + * @see av_opt_is_set_to_default_by_name(). + * + * @param obj AVClass object to check option on + * @param o option to be checked + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default(void *obj, const AVOption *o); + +/** + * Check if given option is set to its default value. + * + * @param obj AVClass object to check option on + * @param name option name + * @param search_flags combination of AV_OPT_SEARCH_* + * @return >0 when option is set to its default, + * 0 when option is not set its default, + * <0 on error + */ +int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags); + + +#define AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 ///< Serialize options that are not set to default values only. +#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 ///< Serialize options that exactly match opt_flags only. + +/** + * Serialize object's options. + * + * Create a string containing object's serialized options. + * Such string may be passed back to av_opt_set_from_string() in order to restore option values. + * A key/value or pairs separator occurring in the serialized value or + * name string are escaped through the av_escape() function. + * + * @param[in] obj AVClass object to serialize + * @param[in] opt_flags serialize options with all the specified flags set (AV_OPT_FLAG) + * @param[in] flags combination of AV_OPT_SERIALIZE_* flags + * @param[out] buffer Pointer to buffer that will be allocated with string containg serialized options. + * Buffer must be freed by the caller when is no longer needed. + * @param[in] key_val_sep character used to separate key from value + * @param[in] pairs_sep character used to separate two pairs from each other + * @return >= 0 on success, negative on error + * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same. + */ +int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer, + const char key_val_sep, const char pairs_sep); +/** + * @} + */ + +#endif /* AVUTIL_OPT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/parseutils.h b/thirdparty/user_include/ffmpeg/libavutil/parseutils.h new file mode 100755 index 0000000000000000000000000000000000000000..e66d24b76e5535579b87dd82e5768619158286ff --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/parseutils.h @@ -0,0 +1,193 @@ +/* + * 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 + */ + +#ifndef AVUTIL_PARSEUTILS_H +#define AVUTIL_PARSEUTILS_H + +#include + +#include "rational.h" + +/** + * @file + * misc parsing utilities + */ + +/** + * Parse str and store the parsed ratio in q. + * + * Note that a ratio with infinite (1/0) or negative value is + * considered valid, so you should check on the returned value if you + * want to exclude those values. + * + * The undefined value can be expressed using the "0:0" string. + * + * @param[in,out] q pointer to the AVRational which will contain the ratio + * @param[in] str the string to parse: it has to be a string in the format + * num:den, a float number or an expression + * @param[in] max the maximum allowed numerator and denominator + * @param[in] log_offset log level offset which is applied to the log + * level of log_ctx + * @param[in] log_ctx parent logging context + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx); + +#define av_parse_ratio_quiet(rate, str, max) \ + av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL) + +/** + * Parse str and put in width_ptr and height_ptr the detected values. + * + * @param[in,out] width_ptr pointer to the variable which will contain the detected + * width value + * @param[in,out] height_ptr pointer to the variable which will contain the detected + * height value + * @param[in] str the string to parse: it has to be a string in the format + * width x height or a valid video size abbreviation. + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str); + +/** + * Parse str and store the detected values in *rate. + * + * @param[in,out] rate pointer to the AVRational which will contain the detected + * frame rate + * @param[in] str the string to parse: it has to be a string in the format + * rate_num / rate_den, a float number or a valid video rate abbreviation + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_video_rate(AVRational *rate, const char *str); + +/** + * Put the RGBA values that correspond to color_string in rgba_color. + * + * @param color_string a string specifying a color. It can be the name of + * a color (case insensitive match) or a [0x|#]RRGGBB[AA] sequence, + * possibly followed by "@" and a string representing the alpha + * component. + * The alpha component may be a string composed by "0x" followed by an + * hexadecimal number or a decimal number between 0.0 and 1.0, which + * represents the opacity value (0x00/0.0 means completely transparent, + * 0xff/1.0 completely opaque). + * If the alpha component is not specified then 0xff is assumed. + * The string "random" will result in a random color. + * @param slen length of the initial part of color_string containing the + * color. It can be set to -1 if color_string is a null terminated string + * containing nothing else than the color. + * @return >= 0 in case of success, a negative value in case of + * failure (for example if color_string cannot be parsed). + */ +int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, + void *log_ctx); + +/** + * Get the name of a color from the internal table of hard-coded named + * colors. + * + * This function is meant to enumerate the color names recognized by + * av_parse_color(). + * + * @param color_idx index of the requested color, starting from 0 + * @param rgbp if not NULL, will point to a 3-elements array with the color value in RGB + * @return the color name string or NULL if color_idx is not in the array + */ +const char *av_get_known_color_name(int color_idx, const uint8_t **rgb); + +/** + * Parse timestr and return in *time a corresponding number of + * microseconds. + * + * @param timeval puts here the number of microseconds corresponding + * to the string in timestr. If the string represents a duration, it + * is the number of microseconds contained in the time interval. If + * the string is a date, is the number of microseconds since 1st of + * January, 1970 up to the time of the parsed date. If timestr cannot + * be successfully parsed, set *time to INT64_MIN. + + * @param timestr a string representing a date or a duration. + * - If a date the syntax is: + * @code + * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z] + * now + * @endcode + * If the value is "now" it takes the current time. + * Time is local time unless Z is appended, in which case it is + * interpreted as UTC. + * If the year-month-day part is not specified it takes the current + * year-month-day. + * - If a duration the syntax is: + * @code + * [-][HH:]MM:SS[.m...] + * [-]S+[.m...] + * @endcode + * @param duration flag which tells how to interpret timestr, if not + * zero timestr is interpreted as a duration, otherwise as a date + * @return >= 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_parse_time(int64_t *timeval, const char *timestr, int duration); + +/** + * Attempt to find a specific tag in a URL. + * + * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. + * Return 1 if found. + */ +int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); + +/** + * Simplified version of strptime + * + * Parse the input string p according to the format string fmt and + * store its results in the structure dt. + * This implementation supports only a subset of the formats supported + * by the standard strptime(). + * + * The supported input field descriptors are listed below. + * - %H: the hour as a decimal number, using a 24-hour clock, in the + * range '00' through '23' + * - %J: hours as a decimal number, in the range '0' through INT_MAX + * - %M: the minute as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %S: the second as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %Y: the year as a decimal number, using the Gregorian calendar + * - %m: the month as a decimal number, in the range '1' through '12' + * - %d: the day of the month as a decimal number, in the range '1' + * through '31' + * - %T: alias for '%H:%M:%S' + * - %%: a literal '%' + * + * @return a pointer to the first character not processed in this function + * call. In case the input string contains more characters than + * required by the format string the return value points right after + * the last consumed input character. In case the whole input string + * is consumed the return value points to the null byte at the end of + * the string. On failure NULL is returned. + */ +char *av_small_strptime(const char *p, const char *fmt, struct tm *dt); + +/** + * Convert the decomposed UTC time in tm to a time_t value. + */ +time_t av_timegm(struct tm *tm); + +#endif /* AVUTIL_PARSEUTILS_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/pixdesc.h b/thirdparty/user_include/ffmpeg/libavutil/pixdesc.h new file mode 100755 index 0000000000000000000000000000000000000000..c055810ae877243884370f8018cdbe6c983dcee9 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/pixdesc.h @@ -0,0 +1,440 @@ +/* + * pixel format descriptor + * Copyright (c) 2009 Michael Niedermayer + * + * 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 + */ + +#ifndef AVUTIL_PIXDESC_H +#define AVUTIL_PIXDESC_H + +#include + +#include "attributes.h" +#include "pixfmt.h" +#include "version.h" + +typedef struct AVComponentDescriptor { + /** + * Which of the 4 planes contains the component. + */ + int plane; + + /** + * Number of elements between 2 horizontally consecutive pixels. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int step; + + /** + * Number of elements before the component of the first pixel. + * Elements are bits for bitstream formats, bytes otherwise. + */ + int offset; + + /** + * Number of least significant bits that must be shifted away + * to get the value. + */ + int shift; + + /** + * Number of bits in the component. + */ + int depth; + +#if FF_API_PLUS1_MINUS1 + /** deprecated, use step instead */ + attribute_deprecated int step_minus1; + + /** deprecated, use depth instead */ + attribute_deprecated int depth_minus1; + + /** deprecated, use offset instead */ + attribute_deprecated int offset_plus1; +#endif +} AVComponentDescriptor; + +/** + * Descriptor that unambiguously describes how the bits of a pixel are + * stored in the up to 4 data planes of an image. It also stores the + * subsampling factors and number of components. + * + * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV + * and all the YUV variants) AVPixFmtDescriptor just stores how values + * are stored not what these values represent. + */ +typedef struct AVPixFmtDescriptor { + const char *name; + uint8_t nb_components; ///< The number of components each pixel has, (1-4) + + /** + * Amount to shift the luma width right to find the chroma width. + * For YV12 this is 1 for example. + * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_w; + + /** + * Amount to shift the luma height right to find the chroma height. + * For YV12 this is 1 for example. + * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h) + * The note above is needed to ensure rounding up. + * This value only refers to the chroma components. + */ + uint8_t log2_chroma_h; + + /** + * Combination of AV_PIX_FMT_FLAG_... flags. + */ + uint64_t flags; + + /** + * Parameters that describe how pixels are packed. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components: + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. + * + * If present, the Alpha channel is always the last component. + */ + AVComponentDescriptor comp[4]; + + /** + * Alternative comma-separated names. + */ + const char *alias; +} AVPixFmtDescriptor; + +/** + * Pixel format is big-endian. + */ +#define AV_PIX_FMT_FLAG_BE (1 << 0) +/** + * Pixel format has a palette in data[1], values are indexes in this palette. + */ +#define AV_PIX_FMT_FLAG_PAL (1 << 1) +/** + * All values of a component are bit-wise packed end to end. + */ +#define AV_PIX_FMT_FLAG_BITSTREAM (1 << 2) +/** + * Pixel format is an HW accelerated format. + */ +#define AV_PIX_FMT_FLAG_HWACCEL (1 << 3) +/** + * At least one pixel component is not in the first data plane. + */ +#define AV_PIX_FMT_FLAG_PLANAR (1 << 4) +/** + * The pixel format contains RGB-like data (as opposed to YUV/grayscale). + */ +#define AV_PIX_FMT_FLAG_RGB (1 << 5) + +/** + * The pixel format is "pseudo-paletted". This means that it contains a + * fixed palette in the 2nd plane but the palette is fixed/constant for each + * PIX_FMT. This allows interpreting the data as if it was PAL8, which can + * in some cases be simpler. Or the data can be interpreted purely based on + * the pixel format without using the palette. + * An example of a pseudo-paletted format is AV_PIX_FMT_GRAY8 + * + * @deprecated This flag is deprecated, and will be removed. When it is removed, + * the extra palette allocation in AVFrame.data[1] is removed as well. Only + * actual paletted formats (as indicated by AV_PIX_FMT_FLAG_PAL) will have a + * palette. Starting with FFmpeg versions which have this flag deprecated, the + * extra "pseudo" palette is already ignored, and API users are not required to + * allocate a palette for AV_PIX_FMT_FLAG_PSEUDOPAL formats (it was required + * before the deprecation, though). + */ +#define AV_PIX_FMT_FLAG_PSEUDOPAL (1 << 6) + +/** + * The pixel format has an alpha channel. This is set on all formats that + * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always + * straight, never pre-multiplied. + * + * If a codec or a filter does not support alpha, it should set all alpha to + * opaque, or use the equivalent pixel formats without alpha component, e.g. + * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA. + */ +#define AV_PIX_FMT_FLAG_ALPHA (1 << 7) + +/** + * The pixel format is following a Bayer pattern + */ +#define AV_PIX_FMT_FLAG_BAYER (1 << 8) + +/** + * The pixel format contains IEEE-754 floating point values. Precision (double, + * single, or half) should be determined by the pixel size (64, 32, or 16 bits). + */ +#define AV_PIX_FMT_FLAG_FLOAT (1 << 9) + +/** + * Return the number of bits per pixel used by the pixel format + * described by pixdesc. Note that this is not the same as the number + * of bits per sample. + * + * The returned number of bits refers to the number of bits actually + * used for storing the pixel information, that is padding bits are + * not counted. + */ +int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** + * @return a pixel format descriptor for provided pixel format or NULL if + * this pixel format is unknown. + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt); + +/** + * Iterate over all pixel format descriptors known to libavutil. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev); + +/** + * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc + * is not a valid pointer to a pixel format descriptor. + */ +enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w (horizontal/width shift) + * @param[out] v_shift store log2_chroma_h (vertical/height shift) + * + * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format + */ +int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, + int *h_shift, int *v_shift); + +/** + * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a + * valid pixel format. + */ +int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); + +/** + * @return the name for provided color range or NULL if unknown. + */ +const char *av_color_range_name(enum AVColorRange range); + +/** + * @return the AVColorRange value for name or an AVError if not found. + */ +int av_color_range_from_name(const char *name); + +/** + * @return the name for provided color primaries or NULL if unknown. + */ +const char *av_color_primaries_name(enum AVColorPrimaries primaries); + +/** + * @return the AVColorPrimaries value for name or an AVError if not found. + */ +int av_color_primaries_from_name(const char *name); + +/** + * @return the name for provided color transfer or NULL if unknown. + */ +const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer); + +/** + * @return the AVColorTransferCharacteristic value for name or an AVError if not found. + */ +int av_color_transfer_from_name(const char *name); + +/** + * @return the name for provided color space or NULL if unknown. + */ +const char *av_color_space_name(enum AVColorSpace space); + +/** + * @return the AVColorSpace value for name or an AVError if not found. + */ +int av_color_space_from_name(const char *name); + +/** + * @return the name for provided chroma location or NULL if unknown. + */ +const char *av_chroma_location_name(enum AVChromaLocation location); + +/** + * @return the AVChromaLocation value for name or an AVError if not found. + */ +int av_chroma_location_from_name(const char *name); + +/** + * Return the pixel format corresponding to name. + * + * If there is no pixel format with name name, then looks for a + * pixel format with the name corresponding to the native endian + * format of name. + * For example in a little-endian system, first looks for "gray16", + * then for "gray16le". + * + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. + */ +enum AVPixelFormat av_get_pix_fmt(const char *name); + +/** + * Return the short name for a pixel format, NULL in case pix_fmt is + * unknown. + * + * @see av_get_pix_fmt(), av_get_pix_fmt_string() + */ +const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); + +/** + * Print in buf the string corresponding to the pixel format with + * number pix_fmt, or a header if pix_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param pix_fmt the number of the pixel format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + */ +char *av_get_pix_fmt_string(char *buf, int buf_size, + enum AVPixelFormat pix_fmt); + +/** + * Read a line from an image, and write the values of the + * pixel format component c to dst. + * + * @param data the array containing the pointers to the planes of the image + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to read + * @param y the vertical coordinate of the first pixel to read + * @param w the width of the line to read, that is the number of + * values to write to dst + * @param read_pal_component if not zero and the format is a paletted + * format writes the values corresponding to the palette + * component c in data[1] to dst, rather than the palette indexes in + * data[0]. The behavior is undefined if the format is not paletted. + * @param dst_element_size size of elements in dst array (2 or 4 byte) + */ +void av_read_image_line2(void *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component, + int dst_element_size); + +void av_read_image_line(uint16_t *dst, const uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int read_pal_component); + +/** + * Write the values from src to the pixel format component c of an + * image line. + * + * @param src array containing the values to write + * @param data the array containing the pointers to the planes of the + * image to write into. It is supposed to be zeroed. + * @param linesize the array containing the linesizes of the image + * @param desc the pixel format descriptor for the image + * @param x the horizontal coordinate of the first pixel to write + * @param y the vertical coordinate of the first pixel to write + * @param w the width of the line to write, that is the number of + * values to write to the image line + * @param src_element_size size of elements in src array (2 or 4 byte) + */ +void av_write_image_line2(const void *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w, int src_element_size); + +void av_write_image_line(const uint16_t *src, uint8_t *data[4], + const int linesize[4], const AVPixFmtDescriptor *desc, + int x, int y, int c, int w); + +/** + * Utility function to swap the endianness of a pixel format. + * + * @param[in] pix_fmt the pixel format + * + * @return pixel format with swapped endianness if it exists, + * otherwise AV_PIX_FMT_NONE + */ +enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +#endif /* AVUTIL_PIXDESC_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/pixelutils.h b/thirdparty/user_include/ffmpeg/libavutil/pixelutils.h new file mode 100755 index 0000000000000000000000000000000000000000..a8dbc157e1055a636de42a64233c20a7d1c56c08 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/pixelutils.h @@ -0,0 +1,52 @@ +/* + * 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 + */ + +#ifndef AVUTIL_PIXELUTILS_H +#define AVUTIL_PIXELUTILS_H + +#include +#include +#include "common.h" + +/** + * Sum of abs(src1[x] - src2[x]) + */ +typedef int (*av_pixelutils_sad_fn)(const uint8_t *src1, ptrdiff_t stride1, + const uint8_t *src2, ptrdiff_t stride2); + +/** + * Get a potentially optimized pointer to a Sum-of-absolute-differences + * function (see the av_pixelutils_sad_fn prototype). + * + * @param w_bits 1< + * + * 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 + */ + +#ifndef AVUTIL_PIXFMT_H +#define AVUTIL_PIXFMT_H + +/** + * @file + * pixel format definitions + */ + +#include "libavutil/avconfig.h" +#include "version.h" + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/** + * Pixel format. + * + * @note + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little-endian CPU architectures and ARGB on + * big-endian CPUs. + * + * @note + * If the resolution is not a multiple of the chroma subsampling factor + * then the chroma plane resolution must be rounded up. + * + * @par + * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB32 palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + * + * @par + * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like + * for pal8. This palette is filled in automatically by the function + * allocating the picture. + */ +enum AVPixelFormat { + AV_PIX_FMT_NONE = -1, + AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) + AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr + AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... + AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... + AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) + AV_PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples) + AV_PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) + AV_PIX_FMT_GRAY8, ///< Y , 8bpp + AV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb + AV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette + AV_PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range + AV_PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range + AV_PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range + AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 + AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 + AV_PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb) + AV_PIX_FMT_BGR4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb) + AV_PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb) + AV_PIX_FMT_RGB4, ///< packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits + AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb) + AV_PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_ARGB, ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB... + AV_PIX_FMT_RGBA, ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA... + AV_PIX_FMT_ABGR, ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR... + AV_PIX_FMT_BGRA, ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA... + + AV_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian + AV_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian + AV_PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) + AV_PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range + AV_PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples) + AV_PIX_FMT_RGB48BE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian + + AV_PIX_FMT_RGB565BE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian + AV_PIX_FMT_RGB565LE, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian + AV_PIX_FMT_RGB555BE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_RGB555LE, ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined + + AV_PIX_FMT_BGR565BE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian + AV_PIX_FMT_BGR565LE, ///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian + AV_PIX_FMT_BGR555BE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined + AV_PIX_FMT_BGR555LE, ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined + +#if FF_API_VAAPI + /** @name Deprecated pixel formats */ + /**@{*/ + AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers + AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers + AV_PIX_FMT_VAAPI_VLD, ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID + /**@}*/ + AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD, +#else + /** + * Hardware acceleration through VA-API, data[3] contains a + * VASurfaceID. + */ + AV_PIX_FMT_VAAPI, +#endif + + AV_PIX_FMT_YUV420P16LE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P16BE, ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV422P16LE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P16BE, ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer + + AV_PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian, X=unused/undefined + AV_PIX_FMT_YA8, ///< 8 bits gray, 8 bits alpha + + AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + + AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ + AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp + AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP + AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian + AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian + AV_PIX_FMT_GBRP10BE, ///< planar GBR 4:4:4 30bpp, big-endian + AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian + AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian + AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian + AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA422P9LE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA444P9BE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + AV_PIX_FMT_YUVA444P9LE, ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian) + AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian) + AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) + AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) + AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 + AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) + AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + + AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb + + AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) + AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) + + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + /** + * HW acceleration through QSV, data[3] contains a pointer to the + * mfxFrameSurface1 structure. + */ + AV_PIX_FMT_QSV, + /** + * HW acceleration though MMAL, data[3] contains a pointer to the + * MMAL_BUFFER_HEADER_T structure. + */ + AV_PIX_FMT_MMAL, + + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + + /** + * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers + * exactly as for system memory frames. + */ + AV_PIX_FMT_CUDA, + + AV_PIX_FMT_0RGB, ///< packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */ + + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing + + AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian + AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian + AV_PIX_FMT_AYUV64LE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian + AV_PIX_FMT_AYUV64BE, ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian + + AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox + + AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian + AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian + + AV_PIX_FMT_GBRAP12BE, ///< planar GBR 4:4:4:4 48bpp, big-endian + AV_PIX_FMT_GBRAP12LE, ///< planar GBR 4:4:4:4 48bpp, little-endian + + AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian + AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian + + AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + + /** + * Hardware surfaces for Direct3D11. + * + * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11 + * hwaccel API and filtering support AV_PIX_FMT_D3D11 only. + * + * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the + * texture array index of the frame as intptr_t if the ID3D11Texture2D is + * an array texture (or always 0 if it's a normal texture). + */ + AV_PIX_FMT_D3D11, + + AV_PIX_FMT_GRAY9BE, ///< Y , 9bpp, big-endian + AV_PIX_FMT_GRAY9LE, ///< Y , 9bpp, little-endian + + AV_PIX_FMT_GBRPF32BE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, big-endian + AV_PIX_FMT_GBRPF32LE, ///< IEEE-754 single precision planar GBR 4:4:4, 96bpp, little-endian + AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian + AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian + + /** + * DRM-managed buffers exposed through PRIME buffer sharing. + * + * data[0] points to an AVDRMFrameDescriptor. + */ + AV_PIX_FMT_DRM_PRIME, + /** + * Hardware surfaces for OpenCL. + * + * data[i] contain 2D image objects (typed in C as cl_mem, used + * in OpenCL as image2d_t) for each plane of the surface. + */ + AV_PIX_FMT_OPENCL, + + AV_PIX_FMT_GRAY14BE, ///< Y , 14bpp, big-endian + AV_PIX_FMT_GRAY14LE, ///< Y , 14bpp, little-endian + + AV_PIX_FMT_GRAYF32BE, ///< IEEE-754 single precision Y, 32bpp, big-endian + AV_PIX_FMT_GRAYF32LE, ///< IEEE-754 single precision Y, 32bpp, little-endian + + AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian + AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian + AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian + + AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) + AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +}; + +#if AV_HAVE_BIGENDIAN +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be +#else +# define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le +#endif + +#define AV_PIX_FMT_RGB32 AV_PIX_FMT_NE(ARGB, BGRA) +#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) +#define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) +#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) + +#define AV_PIX_FMT_GRAY9 AV_PIX_FMT_NE(GRAY9BE, GRAY9LE) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) +#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE) +#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) +#define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) +#define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) +#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE) +#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE) +#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE) +#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE) +#define AV_PIX_FMT_BGR48 AV_PIX_FMT_NE(BGR48BE, BGR48LE) +#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE) +#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE) +#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE) +#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE) + +#define AV_PIX_FMT_YUV420P9 AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define AV_PIX_FMT_YUV422P9 AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE) +#define AV_PIX_FMT_YUV444P9 AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE) +#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) +#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) +#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE) +#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) +#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) +#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) +#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) + +#define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) +#define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) +#define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP10 AV_PIX_FMT_NE(GBRAP10BE, GBRAP10LE) +#define AV_PIX_FMT_GBRAP12 AV_PIX_FMT_NE(GBRAP12BE, GBRAP12LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + +#define AV_PIX_FMT_GBRPF32 AV_PIX_FMT_NE(GBRPF32BE, GBRPF32LE) +#define AV_PIX_FMT_GBRAPF32 AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE) + +#define AV_PIX_FMT_GRAYF32 AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE) + +#define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) +#define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) +#define AV_PIX_FMT_YUVA444P9 AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE) +#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE) +#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE) +#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE) +#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE) +#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE) +#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE) +#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE) +#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE) + +#define AV_PIX_FMT_XYZ12 AV_PIX_FMT_NE(XYZ12BE, XYZ12LE) +#define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) +#define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) +#define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) + +/** + * Chromaticity coordinates of the source primaries. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1. + */ +enum 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_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, + AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors + AVCOL_PRI_NB ///< Not part of ABI +}; + +/** + * Color Transfer Characteristic. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2. + */ +enum 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_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, + AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + AVCOL_TRC_NB ///< Not part of ABI +}; + +/** + * YUV colorspace type. + * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3. + */ +enum 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 + AVCOL_SPC_SMPTE240M = 7, ///< functionally identical to above + AVCOL_SPC_YCGCO = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO, + 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_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + AVCOL_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + AVCOL_SPC_NB ///< Not part of ABI +}; + +/** + * MPEG vs JPEG YUV range. + */ +enum AVColorRange { + AVCOL_RANGE_UNSPECIFIED = 0, + AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB ///< Not part of ABI +}; + +/** + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +enum AVChromaLocation { + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0 + AVCHROMA_LOC_CENTER = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0 + AVCHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB ///< Not part of ABI +}; + +#endif /* AVUTIL_PIXFMT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/random_seed.h b/thirdparty/user_include/ffmpeg/libavutil/random_seed.h new file mode 100755 index 0000000000000000000000000000000000000000..0462a048e048317b0150aa3b800171a96a668e45 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/random_seed.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 Baptiste Coudurier + * + * 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 + */ + +#ifndef AVUTIL_RANDOM_SEED_H +#define AVUTIL_RANDOM_SEED_H + +#include +/** + * @addtogroup lavu_crypto + * @{ + */ + +/** + * Get a seed to use in conjunction with random functions. + * This function tries to provide a good seed at a best effort bases. + * Its possible to call this function multiple times if more bits are needed. + * It can be quite slow, which is why it should only be used as seed for a faster + * PRNG. The quality of the seed depends on the platform. + */ +uint32_t av_get_random_seed(void); + +/** + * @} + */ + +#endif /* AVUTIL_RANDOM_SEED_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/rational.h b/thirdparty/user_include/ffmpeg/libavutil/rational.h new file mode 100755 index 0000000000000000000000000000000000000000..5c6b67b4e9f843ea93fc7ba305ff54a3062f4ea5 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/rational.h @@ -0,0 +1,214 @@ +/* + * rational numbers + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_math_rational + * Utilties for rational number calculation. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_RATIONAL_H +#define AVUTIL_RATIONAL_H + +#include +#include +#include "attributes.h" + +/** + * @defgroup lavu_math_rational AVRational + * @ingroup lavu_math + * Rational number calculation. + * + * While rational numbers can be expressed as floating-point numbers, the + * conversion process is a lossy one, so are floating-point operations. On the + * other hand, the nature of FFmpeg demands highly accurate calculation of + * timestamps. This set of rational number utilities serves as a generic + * interface for manipulating rational numbers as pairs of numerators and + * denominators. + * + * Many of the functions that operate on AVRational's have the suffix `_q`, in + * reference to the mathematical symbol "ℚ" (Q) which denotes the set of all + * rational numbers. + * + * @{ + */ + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct AVRational{ + int num; ///< Numerator + int den; ///< Denominator +} AVRational; + +/** + * Create an AVRational. + * + * Useful for compilers that do not support compound literals. + * + * @note The return value is not reduced. + * @see av_reduce() + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** + * Compare two rationals. + * + * @param a First rational + * @param b Second rational + * + * @return One of the following values: + * - 0 if `a == b` + * - 1 if `a > b` + * - -1 if `a < b` + * - `INT_MIN` if one of the values is of the form `0 / 0` + */ +static inline int av_cmp_q(AVRational a, AVRational b){ + const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; + + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; + else if(b.den && a.den) return 0; + else if(a.num && b.num) return (a.num>>31) - (b.num>>31); + else return INT_MIN; +} + +/** + * Convert an AVRational to a `double`. + * @param a AVRational to convert + * @return `a` in floating-point form + * @see av_d2q() + */ +static inline double av_q2d(AVRational a){ + return a.num / (double) a.den; +} + +/** + * Reduce a fraction. + * + * This is useful for framerate calculations. + * + * @param[out] dst_num Destination numerator + * @param[out] dst_den Destination denominator + * @param[in] num Source numerator + * @param[in] den Source denominator + * @param[in] max Maximum allowed values for `dst_num` & `dst_den` + * @return 1 if the operation is exact, 0 otherwise + */ +int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max); + +/** + * Multiply two rationals. + * @param b First rational + * @param c Second rational + * @return b*c + */ +AVRational av_mul_q(AVRational b, AVRational c) av_const; + +/** + * Divide one rational by another. + * @param b First rational + * @param c Second rational + * @return b/c + */ +AVRational av_div_q(AVRational b, AVRational c) av_const; + +/** + * Add two rationals. + * @param b First rational + * @param c Second rational + * @return b+c + */ +AVRational av_add_q(AVRational b, AVRational c) av_const; + +/** + * Subtract one rational from another. + * @param b First rational + * @param c Second rational + * @return b-c + */ +AVRational av_sub_q(AVRational b, AVRational c) av_const; + +/** + * Invert a rational. + * @param q value + * @return 1 / q + */ +static av_always_inline AVRational av_inv_q(AVRational q) +{ + AVRational r = { q.den, q.num }; + return r; +} + +/** + * Convert a double precision floating point number to a rational. + * + * In case of infinity, the returned value is expressed as `{1, 0}` or + * `{-1, 0}` depending on the sign. + * + * @param d `double` to convert + * @param max Maximum allowed numerator and denominator + * @return `d` in AVRational form + * @see av_q2d() + */ +AVRational av_d2q(double d, int max) av_const; + +/** + * Find which of the two rationals is closer to another rational. + * + * @param q Rational to be compared against + * @param q1,q2 Rationals to be tested + * @return One of the following values: + * - 1 if `q1` is nearer to `q` than `q2` + * - -1 if `q2` is nearer to `q` than `q1` + * - 0 if they have the same distance + */ +int av_nearer_q(AVRational q, AVRational q1, AVRational q2); + +/** + * Find the value in a list of rationals nearest a given reference rational. + * + * @param q Reference rational + * @param q_list Array of rationals terminated by `{0, 0}` + * @return Index of the nearest value found in the array + */ +int av_find_nearest_q_idx(AVRational q, const AVRational* q_list); + +/** + * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point + * format. + * + * @param q Rational to be converted + * @return Equivalent floating-point value, expressed as an unsigned 32-bit + * integer. + * @note The returned value is platform-indepedant. + */ +uint32_t av_q2intfloat(AVRational q); + +/** + * @} + */ + +#endif /* AVUTIL_RATIONAL_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/rc4.h b/thirdparty/user_include/ffmpeg/libavutil/rc4.h new file mode 100755 index 0000000000000000000000000000000000000000..029cd2ad58b9dd3850c22703a60f73d6486da888 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/rc4.h @@ -0,0 +1,66 @@ +/* + * RC4 encryption/decryption/pseudo-random number generator + * + * 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 + */ + +#ifndef AVUTIL_RC4_H +#define AVUTIL_RC4_H + +#include + +/** + * @defgroup lavu_rc4 RC4 + * @ingroup lavu_crypto + * @{ + */ + +typedef struct AVRC4 { + uint8_t state[256]; + int x, y; +} AVRC4; + +/** + * Allocate an AVRC4 context. + */ +AVRC4 *av_rc4_alloc(void); + +/** + * @brief Initializes an AVRC4 context. + * + * @param key_bits must be a multiple of 8 + * @param decrypt 0 for encryption, 1 for decryption, currently has no effect + * @return zero on success, negative value otherwise + */ +int av_rc4_init(struct AVRC4 *d, const uint8_t *key, int key_bits, int decrypt); + +/** + * @brief Encrypts / decrypts using the RC4 algorithm. + * + * @param count number of bytes + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst, may be NULL + * @param iv not (yet) used for RC4, should be NULL + * @param decrypt 0 for encryption, 1 for decryption, not (yet) used + */ +void av_rc4_crypt(struct AVRC4 *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_RC4_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/replaygain.h b/thirdparty/user_include/ffmpeg/libavutil/replaygain.h new file mode 100755 index 0000000000000000000000000000000000000000..b49bf1a3d968620618665d237e88b48aa90d7a4d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/replaygain.h @@ -0,0 +1,50 @@ +/* + * 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 + */ + +#ifndef AVUTIL_REPLAYGAIN_H +#define AVUTIL_REPLAYGAIN_H + +#include + +/** + * ReplayGain information (see + * http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification). + * The size of this struct is a part of the public ABI. + */ +typedef struct AVReplayGain { + /** + * Track replay gain in microbels (divide by 100000 to get the value in dB). + * Should be set to INT32_MIN when unknown. + */ + int32_t track_gain; + /** + * Peak track amplitude, with 100000 representing full scale (but values + * may overflow). 0 when unknown. + */ + uint32_t track_peak; + /** + * Same as track_gain, but for the whole album. + */ + int32_t album_gain; + /** + * Same as track_peak, but for the whole album, + */ + uint32_t album_peak; +} AVReplayGain; + +#endif /* AVUTIL_REPLAYGAIN_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/ripemd.h b/thirdparty/user_include/ffmpeg/libavutil/ripemd.h new file mode 100755 index 0000000000000000000000000000000000000000..0db6858ff33218c432b477f61596a4bda36655f6 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/ripemd.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007 Michael Niedermayer + * Copyright (C) 2013 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_ripemd + * Public header for RIPEMD hash function implementation. + */ + +#ifndef AVUTIL_RIPEMD_H +#define AVUTIL_RIPEMD_H + +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_ripemd RIPEMD + * @ingroup lavu_hash + * RIPEMD hash function implementation. + * + * @{ + */ + +extern const int av_ripemd_size; + +struct AVRIPEMD; + +/** + * Allocate an AVRIPEMD context. + */ +struct AVRIPEMD *av_ripemd_alloc(void); + +/** + * Initialize RIPEMD hashing. + * + * @param context pointer to the function context (of size av_ripemd_size) + * @param bits number of bits in digest (128, 160, 256 or 320 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_ripemd_init(struct AVRIPEMD* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +#if FF_API_CRYPTO_SIZE_T +void av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, unsigned int len); +#else +void av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, size_t len); +#endif + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_ripemd_final(struct AVRIPEMD* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_RIPEMD_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/samplefmt.h b/thirdparty/user_include/ffmpeg/libavutil/samplefmt.h new file mode 100755 index 0000000000000000000000000000000000000000..8cd43ae8568a890f825299ee1e6d6f35ad1e5c5d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/samplefmt.h @@ -0,0 +1,272 @@ +/* + * 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 + */ + +#ifndef AVUTIL_SAMPLEFMT_H +#define AVUTIL_SAMPLEFMT_H + +#include + +#include "avutil.h" +#include "attributes.h" + +/** + * @addtogroup lavu_audio + * @{ + * + * @defgroup lavu_sampfmts Audio sample formats + * + * Audio sample format enumeration and related convenience functions. + * @{ + */ + +/** + * Audio sample formats + * + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. + * + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: + * + * @par + * For planar sample formats, each audio channel is in a separate data plane, + * and linesize is the buffer size, in bytes, for a single plane. All data + * planes must be the same size. For packed sample formats, only the first data + * plane is used, and samples for each channel are interleaved. In this case, + * linesize is the buffer size, in bytes, for the 1 plane. + * + */ +enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, ///< unsigned 8 bits + AV_SAMPLE_FMT_S16, ///< signed 16 bits + AV_SAMPLE_FMT_S32, ///< signed 32 bits + AV_SAMPLE_FMT_FLT, ///< float + AV_SAMPLE_FMT_DBL, ///< double + + AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar + AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar + AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar + AV_SAMPLE_FMT_FLTP, ///< float, planar + AV_SAMPLE_FMT_DBLP, ///< double, planar + AV_SAMPLE_FMT_S64, ///< signed 64 bits + AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar + + AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically +}; + +/** + * Return the name of sample_fmt, or NULL if sample_fmt is not + * recognized. + */ +const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); + +/** + * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE + * on error. + */ +enum AVSampleFormat av_get_sample_fmt(const char *name); + +/** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** + * Get the packed alternative form of the given sample format. + * + * If the passed sample_fmt is already in packed format, the format returned is + * the same as the input. + * + * @return the packed alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Get the planar alternative form of the given sample format. + * + * If the passed sample_fmt is already in planar format, the format returned is + * the same as the input. + * + * @return the planar alternative form of the given sample format or + AV_SAMPLE_FMT_NONE on error. + */ +enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); + +/** + * Generate a string corresponding to the sample format with + * sample_fmt, or a header if sample_fmt is negative. + * + * @param buf the buffer where to write the string + * @param buf_size the size of buf + * @param sample_fmt the number of the sample format to print the + * corresponding info string, or a negative value to print the + * corresponding header. + * @return the pointer to the filled buffer or NULL if sample_fmt is + * unknown or in case of other errors + */ +char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); + +/** + * Return number of bytes per sample. + * + * @param sample_fmt the sample format + * @return number of bytes per sample or zero if unknown for the given + * sample format + */ +int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt); + +/** + * Check if the sample format is planar. + * + * @param sample_fmt the sample format to inspect + * @return 1 if the sample format is planar, 0 if it is interleaved + */ +int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt); + +/** + * Get the required buffer size for the given audio parameters. + * + * @param[out] linesize calculated linesize, may be NULL + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return required buffer size, or negative error code on failure + */ +int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * @} + * + * @defgroup lavu_sampmanip Samples manipulation + * + * Functions that manipulate audio samples + * @{ + */ + +/** + * Fill plane data pointers and linesize for samples with sample + * format sample_fmt. + * + * The audio_data array is filled with the pointers to the samples data planes: + * for planar, set the start point of each channel's data within the buffer, + * for packed, set the start point of the entire buffer only. + * + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize calculated linesize, may be NULL + * @param buf the pointer to a buffer containing the samples + * @param nb_channels the number of channels + * @param nb_samples the number of samples in a single channel + * @param sample_fmt the sample format + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return minimum size in bytes required for the buffer in case + * of success at the next bump + */ +int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, + const uint8_t *buf, + int nb_channels, int nb_samples, + enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a samples buffer for nb_samples samples, and fill data pointers and + * linesize accordingly. + * The allocated samples buffer can be freed by using av_freep(&audio_data[0]) + * Allocated data will be initialized to silence. + * + * @see enum AVSampleFormat + * The documentation for AVSampleFormat describes the data layout. + * + * @param[out] audio_data array to be filled with the pointer for each channel + * @param[out] linesize aligned size for audio buffer(s), may be NULL + * @param nb_channels number of audio channels + * @param nb_samples number of samples per channel + * @param align buffer size alignment (0 = default, 1 = no alignment) + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump + * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() + */ +int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** + * Copy samples from src to dst. + * + * @param dst destination array of pointers to data planes + * @param src source array of pointers to data planes + * @param dst_offset offset in samples at which the data will be written to dst + * @param src_offset offset in samples at which the data will be read from src + * @param nb_samples number of samples to be copied + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, + int src_offset, int nb_samples, int nb_channels, + enum AVSampleFormat sample_fmt); + +/** + * Fill an audio buffer with silence. + * + * @param audio_data array of pointers to data planes + * @param offset offset in samples at which to start filling + * @param nb_samples number of samples to fill + * @param nb_channels number of audio channels + * @param sample_fmt audio sample format + */ +int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, + int nb_channels, enum AVSampleFormat sample_fmt); + +/** + * @} + * @} + */ +#endif /* AVUTIL_SAMPLEFMT_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/sha.h b/thirdparty/user_include/ffmpeg/libavutil/sha.h new file mode 100755 index 0000000000000000000000000000000000000000..c0180e5729a2e9232bdbf387b9b74d6acc25e943 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/sha.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_sha + * Public header for SHA-1 & SHA-256 hash function implementations. + */ + +#ifndef AVUTIL_SHA_H +#define AVUTIL_SHA_H + +#include +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_sha SHA + * @ingroup lavu_hash + * SHA-1 and SHA-256 (Secure Hash Algorithm) hash function implementations. + * + * This module supports the following SHA hash functions: + * + * - SHA-1: 160 bits + * - SHA-224: 224 bits, as a variant of SHA-2 + * - SHA-256: 256 bits, as a variant of SHA-2 + * + * @see For SHA-384, SHA-512, and variants thereof, see @ref lavu_sha512. + * + * @{ + */ + +extern const int av_sha_size; + +struct AVSHA; + +/** + * Allocate an AVSHA context. + */ +struct AVSHA *av_sha_alloc(void); + +/** + * Initialize SHA-1 or SHA-2 hashing. + * + * @param context pointer to the function context (of size av_sha_size) + * @param bits number of bits in digest (SHA-1 - 160 bits, SHA-2 224 or 256 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_sha_init(struct AVSHA* context, int bits); + +/** + * Update hash value. + * + * @param ctx hash function context + * @param data input data to update hash with + * @param len input data length + */ +#if FF_API_CRYPTO_SIZE_T +void av_sha_update(struct AVSHA *ctx, const uint8_t *data, unsigned int len); +#else +void av_sha_update(struct AVSHA *ctx, const uint8_t *data, size_t len); +#endif + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_sha_final(struct AVSHA* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_SHA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/sha512.h b/thirdparty/user_include/ffmpeg/libavutil/sha512.h new file mode 100755 index 0000000000000000000000000000000000000000..bef714b41cf720918ef28f7c484a7d93018fc37a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/sha512.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007 Michael Niedermayer + * Copyright (C) 2013 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu_sha512 + * Public header for SHA-512 implementation. + */ + +#ifndef AVUTIL_SHA512_H +#define AVUTIL_SHA512_H + +#include +#include + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_sha512 SHA-512 + * @ingroup lavu_hash + * SHA-512 (Secure Hash Algorithm) hash function implementations. + * + * This module supports the following SHA-2 hash functions: + * + * - SHA-512/224: 224 bits + * - SHA-512/256: 256 bits + * - SHA-384: 384 bits + * - SHA-512: 512 bits + * + * @see For SHA-1, SHA-256, and variants thereof, see @ref lavu_sha. + * + * @{ + */ + +extern const int av_sha512_size; + +struct AVSHA512; + +/** + * Allocate an AVSHA512 context. + */ +struct AVSHA512 *av_sha512_alloc(void); + +/** + * Initialize SHA-2 512 hashing. + * + * @param context pointer to the function context (of size av_sha512_size) + * @param bits number of bits in digest (224, 256, 384 or 512 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_sha512_init(struct AVSHA512* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +#if FF_API_CRYPTO_SIZE_T +void av_sha512_update(struct AVSHA512* context, const uint8_t* data, unsigned int len); +#else +void av_sha512_update(struct AVSHA512* context, const uint8_t* data, size_t len); +#endif + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_sha512_final(struct AVSHA512* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_SHA512_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/spherical.h b/thirdparty/user_include/ffmpeg/libavutil/spherical.h new file mode 100755 index 0000000000000000000000000000000000000000..cef759cf278bf8ac239746056c8daa16f923f43d --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/spherical.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2016 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Spherical video + */ + +#ifndef AVUTIL_SPHERICAL_H +#define AVUTIL_SPHERICAL_H + +#include +#include + +/** + * @addtogroup lavu_video + * @{ + * + * @defgroup lavu_video_spherical Spherical video mapping + * @{ + */ + +/** + * @addtogroup lavu_video_spherical + * A spherical video file contains surfaces that need to be mapped onto a + * sphere. Depending on how the frame was converted, a different distortion + * transformation or surface recomposition function needs to be applied before + * the video should be mapped and displayed. + */ + +/** + * Projection of the video surface(s) on a sphere. + */ +enum AVSphericalProjection { + /** + * Video represents a sphere mapped on a flat surface using + * equirectangular projection. + */ + AV_SPHERICAL_EQUIRECTANGULAR, + + /** + * Video frame is split into 6 faces of a cube, and arranged on a + * 3x2 layout. Faces are oriented upwards for the front, left, right, + * and back faces. The up face is oriented so the top of the face is + * forwards and the down face is oriented so the top of the face is + * to the back. + */ + AV_SPHERICAL_CUBEMAP, + + /** + * Video represents a portion of a sphere mapped on a flat surface + * using equirectangular projection. The @ref bounding fields indicate + * the position of the current video in a larger surface. + */ + AV_SPHERICAL_EQUIRECTANGULAR_TILE, +}; + +/** + * This structure describes how to handle spherical videos, outlining + * information about projection, initial layout, and any other view modifier. + * + * @note The struct must be allocated with av_spherical_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVSphericalMapping { + /** + * Projection type. + */ + enum AVSphericalProjection projection; + + /** + * @name Initial orientation + * @{ + * There fields describe additional rotations applied to the sphere after + * the video frame is mapped onto it. The sphere is rotated around the + * viewer, who remains stationary. The order of transformation is always + * yaw, followed by pitch, and finally by roll. + * + * The coordinate system matches the one defined in OpenGL, where the + * forward vector (z) is coming out of screen, and it is equivalent to + * a rotation matrix of R = r_y(yaw) * r_x(pitch) * r_z(roll). + * + * A positive yaw rotates the portion of the sphere in front of the viewer + * toward their right. A positive pitch rotates the portion of the sphere + * in front of the viewer upwards. A positive roll tilts the portion of + * the sphere in front of the viewer to the viewer's right. + * + * These values are exported as 16.16 fixed point. + * + * See this equirectangular projection as example: + * + * @code{.unparsed} + * Yaw + * -180 0 180 + * 90 +-------------+-------------+ 180 + * | | | up + * P | | | y| forward + * i | ^ | | /z + * t 0 +-------------X-------------+ 0 Roll | / + * c | | | | / + * h | | | 0|/_____right + * | | | x + * -90 +-------------+-------------+ -180 + * + * X - the default camera center + * ^ - the default up vector + * @endcode + */ + int32_t yaw; ///< Rotation around the up vector [-180, 180]. + int32_t pitch; ///< Rotation around the right vector [-90, 90]. + int32_t roll; ///< Rotation around the forward vector [-180, 180]. + /** + * @} + */ + + /** + * @name Bounding rectangle + * @anchor bounding + * @{ + * These fields indicate the location of the current tile, and where + * it should be mapped relative to the original surface. They are + * exported as 0.32 fixed point, and can be converted to classic + * pixel values with av_spherical_bounds(). + * + * @code{.unparsed} + * +----------------+----------+ + * | |bound_top | + * | +--------+ | + * | bound_left |tile | | + * +<---------->| |<--->+bound_right + * | +--------+ | + * | | | + * | bound_bottom| | + * +----------------+----------+ + * @endcode + * + * If needed, the original video surface dimensions can be derived + * by adding the current stream or frame size to the related bounds, + * like in the following example: + * + * @code{c} + * original_width = tile->width + bound_left + bound_right; + * original_height = tile->height + bound_top + bound_bottom; + * @endcode + * + * @note These values are valid only for the tiled equirectangular + * projection type (@ref AV_SPHERICAL_EQUIRECTANGULAR_TILE), + * and should be ignored in all other cases. + */ + uint32_t bound_left; ///< Distance from the left edge + uint32_t bound_top; ///< Distance from the top edge + uint32_t bound_right; ///< Distance from the right edge + uint32_t bound_bottom; ///< Distance from the bottom edge + /** + * @} + */ + + /** + * Number of pixels to pad from the edge of each cube face. + * + * @note This value is valid for only for the cubemap projection type + * (@ref AV_SPHERICAL_CUBEMAP), and should be ignored in all other + * cases. + */ + uint32_t padding; +} AVSphericalMapping; + +/** + * Allocate a AVSphericalVideo structure and initialize its fields to default + * values. + * + * @return the newly allocated struct or NULL on failure + */ +AVSphericalMapping *av_spherical_alloc(size_t *size); + +/** + * Convert the @ref bounding fields from an AVSphericalVideo + * from 0.32 fixed point to pixels. + * + * @param map The AVSphericalVideo map to read bound values from. + * @param width Width of the current frame or stream. + * @param height Height of the current frame or stream. + * @param left Pixels from the left edge. + * @param top Pixels from the top edge. + * @param right Pixels from the right edge. + * @param bottom Pixels from the bottom edge. + */ +void av_spherical_tile_bounds(const AVSphericalMapping *map, + size_t width, size_t height, + size_t *left, size_t *top, + size_t *right, size_t *bottom); + +/** + * Provide a human-readable name of a given AVSphericalProjection. + * + * @param projection The input AVSphericalProjection. + * + * @return The name of the AVSphericalProjection, or "unknown". + */ +const char *av_spherical_projection_name(enum AVSphericalProjection projection); + +/** + * Get the AVSphericalProjection form a human-readable name. + * + * @param name The input string. + * + * @return The AVSphericalProjection value, or -1 if not found. + */ +int av_spherical_from_name(const char *name); +/** + * @} + * @} + */ + +#endif /* AVUTIL_SPHERICAL_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/stereo3d.h b/thirdparty/user_include/ffmpeg/libavutil/stereo3d.h new file mode 100755 index 0000000000000000000000000000000000000000..d421aac2a26b12feb5ef94f5e5441832df556f48 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/stereo3d.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Stereoscopic video + */ + +#ifndef AVUTIL_STEREO3D_H +#define AVUTIL_STEREO3D_H + +#include + +#include "frame.h" + +/** + * @addtogroup lavu_video + * @{ + * + * @defgroup lavu_video_stereo3d Stereo3D types and functions + * @{ + */ + +/** + * @addtogroup lavu_video_stereo3d + * A stereoscopic video file consists in multiple views embedded in a single + * frame, usually describing two views of a scene. This file describes all + * possible codec-independent view arrangements. + * */ + +/** + * List of possible 3D Types + */ +enum AVStereo3DType { + /** + * Video is not stereoscopic (and metadata has to be there). + */ + AV_STEREO3D_2D, + + /** + * Views are next to each other. + * + * @code{.unparsed} + * LLLLRRRR + * LLLLRRRR + * LLLLRRRR + * ... + * @endcode + */ + AV_STEREO3D_SIDEBYSIDE, + + /** + * Views are on top of each other. + * + * @code{.unparsed} + * LLLLLLLL + * LLLLLLLL + * RRRRRRRR + * RRRRRRRR + * @endcode + */ + AV_STEREO3D_TOPBOTTOM, + + /** + * Views are alternated temporally. + * + * @code{.unparsed} + * frame0 frame1 frame2 ... + * LLLLLLLL RRRRRRRR LLLLLLLL + * LLLLLLLL RRRRRRRR LLLLLLLL + * LLLLLLLL RRRRRRRR LLLLLLLL + * ... ... ... + * @endcode + */ + AV_STEREO3D_FRAMESEQUENCE, + + /** + * Views are packed in a checkerboard-like structure per pixel. + * + * @code{.unparsed} + * LRLRLRLR + * RLRLRLRL + * LRLRLRLR + * ... + * @endcode + */ + AV_STEREO3D_CHECKERBOARD, + + /** + * Views are next to each other, but when upscaling + * apply a checkerboard pattern. + * + * @code{.unparsed} + * LLLLRRRR L L L L R R R R + * LLLLRRRR => L L L L R R R R + * LLLLRRRR L L L L R R R R + * LLLLRRRR L L L L R R R R + * @endcode + */ + AV_STEREO3D_SIDEBYSIDE_QUINCUNX, + + /** + * Views are packed per line, as if interlaced. + * + * @code{.unparsed} + * LLLLLLLL + * RRRRRRRR + * LLLLLLLL + * ... + * @endcode + */ + AV_STEREO3D_LINES, + + /** + * Views are packed per column. + * + * @code{.unparsed} + * LRLRLRLR + * LRLRLRLR + * LRLRLRLR + * ... + * @endcode + */ + AV_STEREO3D_COLUMNS, +}; + +/** + * List of possible view types. + */ +enum AVStereo3DView { + /** + * Frame contains two packed views. + */ + AV_STEREO3D_VIEW_PACKED, + + /** + * Frame contains only the left view. + */ + AV_STEREO3D_VIEW_LEFT, + + /** + * Frame contains only the right view. + */ + AV_STEREO3D_VIEW_RIGHT, +}; + +/** + * Inverted views, Right/Bottom represents the left view. + */ +#define AV_STEREO3D_FLAG_INVERT (1 << 0) + +/** + * Stereo 3D type: this structure describes how two videos are packed + * within a single video surface, with additional information as needed. + * + * @note The struct must be allocated with av_stereo3d_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVStereo3D { + /** + * How views are packed within the video. + */ + enum AVStereo3DType type; + + /** + * Additional information about the frame packing. + */ + int flags; + + /** + * Determines which views are packed. + */ + enum AVStereo3DView view; +} AVStereo3D; + +/** + * Allocate an AVStereo3D structure and set its fields to default values. + * The resulting struct can be freed using av_freep(). + * + * @return An AVStereo3D filled with default values or NULL on failure. + */ +AVStereo3D *av_stereo3d_alloc(void); + +/** + * Allocate a complete AVFrameSideData and add it to the frame. + * + * @param frame The frame which side data is added to. + * + * @return The AVStereo3D structure to be filled by caller. + */ +AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame); + +/** + * Provide a human-readable name of a given stereo3d type. + * + * @param type The input stereo3d type value. + * + * @return The name of the stereo3d value, or "unknown". + */ +const char *av_stereo3d_type_name(unsigned int type); + +/** + * Get the AVStereo3DType form a human-readable name. + * + * @param name The input string. + * + * @return The AVStereo3DType value, or -1 if not found. + */ +int av_stereo3d_from_name(const char *name); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_STEREO3D_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/tea.h b/thirdparty/user_include/ffmpeg/libavutil/tea.h new file mode 100755 index 0000000000000000000000000000000000000000..dd929bdafdc42b00102ac4db2c38ca5afd607f55 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/tea.h @@ -0,0 +1,71 @@ +/* + * A 32-bit implementation of the TEA algorithm + * Copyright (c) 2015 Vesselin Bontchev + * + * 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 + */ + +#ifndef AVUTIL_TEA_H +#define AVUTIL_TEA_H + +#include + +/** + * @file + * @brief Public header for libavutil TEA algorithm + * @defgroup lavu_tea TEA + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_tea_size; + +struct AVTEA; + +/** + * Allocate an AVTEA context + * To free the struct: av_free(ptr) + */ +struct AVTEA *av_tea_alloc(void); + +/** + * Initialize an AVTEA context. + * + * @param ctx an AVTEA context + * @param key a key of 16 bytes used for encryption/decryption + * @param rounds the number of rounds in TEA (64 is the "standard") + */ +void av_tea_init(struct AVTEA *ctx, const uint8_t key[16], int rounds); + +/** + * Encrypt or decrypt a buffer using a previously initialized context. + * + * @param ctx an AVTEA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_tea_crypt(struct AVTEA *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_TEA_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/threadmessage.h b/thirdparty/user_include/ffmpeg/libavutil/threadmessage.h new file mode 100755 index 0000000000000000000000000000000000000000..42ce655f365ac4527b0b4bf223b82db902efdc41 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/threadmessage.h @@ -0,0 +1,115 @@ +/* + * 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 + */ + +#ifndef AVUTIL_THREADMESSAGE_H +#define AVUTIL_THREADMESSAGE_H + +typedef struct AVThreadMessageQueue AVThreadMessageQueue; + +typedef enum AVThreadMessageFlags { + + /** + * Perform non-blocking operation. + * If this flag is set, send and recv operations are non-blocking and + * return AVERROR(EAGAIN) immediately if they can not proceed. + */ + AV_THREAD_MESSAGE_NONBLOCK = 1, + +} AVThreadMessageFlags; + +/** + * Allocate a new message queue. + * + * @param mq pointer to the message queue + * @param nelem maximum number of elements in the queue + * @param elsize size of each element in the queue + * @return >=0 for success; <0 for error, in particular AVERROR(ENOSYS) if + * lavu was built without thread support + */ +int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, + unsigned nelem, + unsigned elsize); + +/** + * Free a message queue. + * + * The message queue must no longer be in use by another thread. + */ +void av_thread_message_queue_free(AVThreadMessageQueue **mq); + +/** + * Send a message on the queue. + */ +int av_thread_message_queue_send(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Receive a message from the queue. + */ +int av_thread_message_queue_recv(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Set the sending error code. + * + * If the error code is set to non-zero, av_thread_message_queue_send() will + * return it immediately. Conventional values, such as AVERROR_EOF or + * AVERROR(EAGAIN), can be used to cause the sending thread to stop or + * suspend its operation. + */ +void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, + int err); + +/** + * Set the receiving error code. + * + * If the error code is set to non-zero, av_thread_message_queue_recv() will + * return it immediately when there are no longer available messages. + * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used + * to cause the receiving thread to stop or suspend its operation. + */ +void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, + int err); + +/** + * Set the optional free message callback function which will be called if an + * operation is removing messages from the queue. + */ +void av_thread_message_queue_set_free_func(AVThreadMessageQueue *mq, + void (*free_func)(void *msg)); + +/** + * Return the current number of messages in the queue. + * + * @return the current number of messages or AVERROR(ENOSYS) if lavu was built + * without thread support + */ +int av_thread_message_queue_nb_elems(AVThreadMessageQueue *mq); + +/** + * Flush the message queue + * + * This function is mostly equivalent to reading and free-ing every message + * except that it will be done in a single operation (no lock/unlock between + * reads). + */ +void av_thread_message_flush(AVThreadMessageQueue *mq); + +#endif /* AVUTIL_THREADMESSAGE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/time.h b/thirdparty/user_include/ffmpeg/libavutil/time.h new file mode 100755 index 0000000000000000000000000000000000000000..dc169b064a0d7d4659809da42e0a6942449fba39 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/time.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2000-2003 Fabrice Bellard + * + * 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 + */ + +#ifndef AVUTIL_TIME_H +#define AVUTIL_TIME_H + +#include + +/** + * Get the current time in microseconds. + */ +int64_t av_gettime(void); + +/** + * Get the current time in microseconds since some unspecified starting point. + * On platforms that support it, the time comes from a monotonic clock + * This property makes this time source ideal for measuring relative time. + * The returned values may not be monotonic on platforms where a monotonic + * clock is not available. + */ +int64_t av_gettime_relative(void); + +/** + * Indicates with a boolean result if the av_gettime_relative() time source + * is monotonic. + */ +int av_gettime_relative_is_monotonic(void); + +/** + * Sleep for a period of time. Although the duration is expressed in + * microseconds, the actual delay may be rounded to the precision of the + * system timer. + * + * @param usec Number of microseconds to sleep. + * @return zero on success or (negative) error code. + */ +int av_usleep(unsigned usec); + +#endif /* AVUTIL_TIME_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/timecode.h b/thirdparty/user_include/ffmpeg/libavutil/timecode.h new file mode 100755 index 0000000000000000000000000000000000000000..37c1361bc281ad6bf52d2ae0315fe32148389847 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/timecode.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier + * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Timecode helpers header + */ + +#ifndef AVUTIL_TIMECODE_H +#define AVUTIL_TIMECODE_H + +#include +#include "rational.h" + +#define AV_TIMECODE_STR_SIZE 23 + +enum AVTimecodeFlag { + AV_TIMECODE_FLAG_DROPFRAME = 1<<0, ///< timecode is drop frame + AV_TIMECODE_FLAG_24HOURSMAX = 1<<1, ///< timecode wraps after 24 hours + AV_TIMECODE_FLAG_ALLOWNEGATIVE = 1<<2, ///< negative time values are allowed +}; + +typedef struct { + int start; ///< timecode frame start (first base frame number) + uint32_t flags; ///< flags such as drop frame, +24 hours support, ... + AVRational rate; ///< frame rate in rational form + unsigned fps; ///< frame per second; must be consistent with the rate field +} AVTimecode; + +/** + * Adjust frame number for NTSC drop frame time code. + * + * @param framenum frame number to adjust + * @param fps frame per second, 30 or 60 + * @return adjusted frame number + * @warning adjustment is only valid in NTSC 29.97 and 59.94 + */ +int av_timecode_adjust_ntsc_framenum2(int framenum, int fps); + +/** + * Convert frame number to SMPTE 12M binary representation. + * + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the SMPTE binary representation + * + * @note Frame number adjustment is automatically done in case of drop timecode, + * you do NOT have to call av_timecode_adjust_ntsc_framenum2(). + * @note The frame number is relative to tc->start. + * @note Color frame (CF), binary group flags (BGF) and biphase mark polarity + * correction (PC) bits are set to zero. + */ +uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum); + +/** + * Load timecode string in buf. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the buf parameter + * + * @note Timecode representation can be a negative timecode and have more than + * 24 hours, but will only be honored if the flags are correctly set. + * @note The frame number is relative to tc->start. + */ +char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum); + +/** + * Get the timecode string from the SMPTE timecode format. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tcsmpte the 32-bit SMPTE timecode + * @param prevent_df prevent the use of a drop flag when it is known the DF bit + * is arbitrary + * @return the buf parameter + */ +char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df); + +/** + * Get the timecode string from the 25-bit timecode format (MPEG GOP format). + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc25bit the 25-bits timecode + * @return the buf parameter + */ +char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit); + +/** + * Init a timecode struct with the passed parameters. + * + * @param log_ctx a pointer to an arbitrary struct of which the first field + * is a pointer to an AVClass struct (used for av_log) + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param flags miscellaneous flags such as drop frame, +24 hours, ... + * (see AVTimecodeFlag) + * @param frame_start the first frame number + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx); + +/** + * Parse timecode representation (hh:mm:ss[:;.]ff). + * + * @param log_ctx a pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct (used for av_log). + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param str timecode string which will determine the frame start + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx); + +/** + * Check if the timecode feature is available for the given frame rate + * + * @return 0 if supported, <0 otherwise + */ +int av_timecode_check_frame_rate(AVRational rate); + +#endif /* AVUTIL_TIMECODE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/timestamp.h b/thirdparty/user_include/ffmpeg/libavutil/timestamp.h new file mode 100755 index 0000000000000000000000000000000000000000..e082f01b40b332fc3bfec2ed86d65d2eaafe5d5e --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/timestamp.h @@ -0,0 +1,78 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * timestamp utils, mostly useful for debugging/logging purposes + */ + +#ifndef AVUTIL_TIMESTAMP_H +#define AVUTIL_TIMESTAMP_H + +#include "common.h" + +#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) && !defined(PRId64) +#error missing -D__STDC_FORMAT_MACROS / #define __STDC_FORMAT_MACROS +#endif + +#define AV_TS_MAX_STRING_SIZE 32 + +/** + * Fill the provided buffer with a string containing a timestamp + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @return the buffer in input + */ +static inline char *av_ts_make_string(char *buf, int64_t ts) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%" PRId64, ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts) + +/** + * Fill the provided buffer with a string containing a timestamp time + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @param tb the timebase of the timestamp + * @return the buffer in input + */ +static inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6g", av_q2d(*tb) * ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb) + +#endif /* AVUTIL_TIMESTAMP_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/tree.h b/thirdparty/user_include/ffmpeg/libavutil/tree.h new file mode 100755 index 0000000000000000000000000000000000000000..d5e0aebfbdb7c1f7e4fc36b437f5c6147c82b94a --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/tree.h @@ -0,0 +1,138 @@ +/* + * copyright (c) 2006 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * A tree container. + * @author Michael Niedermayer + */ + +#ifndef AVUTIL_TREE_H +#define AVUTIL_TREE_H + +#include "attributes.h" +#include "version.h" + +/** + * @addtogroup lavu_tree AVTree + * @ingroup lavu_data + * + * Low-complexity tree container + * + * Insertion, removal, finding equal, largest which is smaller than and + * smallest which is larger than, all have O(log n) worst-case complexity. + * @{ + */ + + +struct AVTreeNode; +extern const int av_tree_node_size; + +/** + * Allocate an AVTreeNode. + */ +struct AVTreeNode *av_tree_node_alloc(void); + +/** + * Find an element. + * @param root a pointer to the root node of the tree + * @param next If next is not NULL, then next[0] will contain the previous + * element and next[1] the next element. If either does not exist, + * then the corresponding entry in next is unchanged. + * @param cmp compare function used to compare elements in the tree, + * API identical to that of Standard C's qsort + * It is guaranteed that the first and only the first argument to cmp() + * will be the key parameter to av_tree_find(), thus it could if the + * user wants, be a different type (like an opaque context). + * @return An element with cmp(key, elem) == 0 or NULL if no such element + * exists in the tree. + */ +void *av_tree_find(const struct AVTreeNode *root, void *key, + int (*cmp)(const void *key, const void *b), void *next[2]); + +/** + * Insert or remove an element. + * + * If *next is NULL, then the supplied element will be removed if it exists. + * If *next is non-NULL, then the supplied element will be inserted, unless + * it already exists in the tree. + * + * @param rootp A pointer to a pointer to the root node of the tree; note that + * the root node can change during insertions, this is required + * to keep the tree balanced. + * @param key pointer to the element key to insert in the tree + * @param next Used to allocate and free AVTreeNodes. For insertion the user + * must set it to an allocated and zeroed object of at least + * av_tree_node_size bytes size. av_tree_insert() will set it to + * NULL if it has been consumed. + * For deleting elements *next is set to NULL by the user and + * av_tree_insert() will set it to the AVTreeNode which was + * used for the removed element. + * This allows the use of flat arrays, which have + * lower overhead compared to many malloced elements. + * You might want to define a function like: + * @code + * void *tree_insert(struct AVTreeNode **rootp, void *key, + * int (*cmp)(void *key, const void *b), + * AVTreeNode **next) + * { + * if (!*next) + * *next = av_mallocz(av_tree_node_size); + * return av_tree_insert(rootp, key, cmp, next); + * } + * void *tree_remove(struct AVTreeNode **rootp, void *key, + * int (*cmp)(void *key, const void *b, AVTreeNode **next)) + * { + * av_freep(next); + * return av_tree_insert(rootp, key, cmp, next); + * } + * @endcode + * @param cmp compare function used to compare elements in the tree, API identical + * to that of Standard C's qsort + * @return If no insertion happened, the found element; if an insertion or + * removal happened, then either key or NULL will be returned. + * Which one it is depends on the tree state and the implementation. You + * should make no assumptions that it's one or the other in the code. + */ +void *av_tree_insert(struct AVTreeNode **rootp, void *key, + int (*cmp)(const void *key, const void *b), + struct AVTreeNode **next); + +void av_tree_destroy(struct AVTreeNode *t); + +/** + * Apply enu(opaque, &elem) to all the elements in the tree in a given range. + * + * @param cmp a comparison function that returns < 0 for an element below the + * range, > 0 for an element above the range and == 0 for an + * element inside the range + * + * @note The cmp function should use the same ordering used to construct the + * tree. + */ +void av_tree_enumerate(struct AVTreeNode *t, void *opaque, + int (*cmp)(void *opaque, void *elem), + int (*enu)(void *opaque, void *elem)); + +/** + * @} + */ + +#endif /* AVUTIL_TREE_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/twofish.h b/thirdparty/user_include/ffmpeg/libavutil/twofish.h new file mode 100755 index 0000000000000000000000000000000000000000..813cfecdf8b81b70e324bf1cd08080f9704980b3 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/twofish.h @@ -0,0 +1,70 @@ +/* + * An implementation of the TwoFish algorithm + * Copyright (c) 2015 Supraja Meedinti + * + * 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 + */ + +#ifndef AVUTIL_TWOFISH_H +#define AVUTIL_TWOFISH_H + +#include + + +/** + * @file + * @brief Public header for libavutil TWOFISH algorithm + * @defgroup lavu_twofish TWOFISH + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_twofish_size; + +struct AVTWOFISH; + +/** + * Allocate an AVTWOFISH context + * To free the struct: av_free(ptr) + */ +struct AVTWOFISH *av_twofish_alloc(void); + +/** + * Initialize an AVTWOFISH context. + * + * @param ctx an AVTWOFISH context + * @param key a key of size ranging from 1 to 32 bytes used for encryption/decryption + * @param key_bits number of keybits: 128, 192, 256 If less than the required, padded with zeroes to nearest valid value; return value is 0 if key_bits is 128/192/256, -1 if less than 0, 1 otherwise + */ +int av_twofish_init(struct AVTWOFISH *ctx, const uint8_t *key, int key_bits); + +/** + * Encrypt or decrypt a buffer using a previously initialized context + * + * @param ctx an AVTWOFISH context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 16 byte blocks + * @paran iv initialization vector for CBC mode, NULL for ECB mode + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_twofish_crypt(struct AVTWOFISH *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt); + +/** + * @} + */ +#endif /* AVUTIL_TWOFISH_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/tx.h b/thirdparty/user_include/ffmpeg/libavutil/tx.h new file mode 100755 index 0000000000000000000000000000000000000000..b1f2d963533367df7607dc9ac5ffe094ffc41630 --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/tx.h @@ -0,0 +1,81 @@ +/* + * 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 + */ + +#ifndef AVUTIL_TX_H +#define AVUTIL_TX_H + +#include +#include + +typedef struct AVTXContext AVTXContext; + +typedef struct AVComplexFloat { + float re, im; +} AVComplexFloat; + +enum AVTXType { + /** + * Standard complex to complex FFT with sample data type AVComplexFloat. + * Scaling currently unsupported + */ + AV_TX_FLOAT_FFT = 0, + /** + * Standard MDCT with sample data type of float and a scale type of + * float. Length is the frame size, not the window size (which is 2x frame) + */ + AV_TX_FLOAT_MDCT = 1, +}; + +/** + * Function pointer to a function to perform the transform. + * + * @note Using a different context than the one allocated during av_tx_init() + * is not allowed. + * + * @param s the transform context + * @param out the output array + * @param in the input array + * @param stride the input or output stride (depending on transform direction) + * in bytes, currently implemented for all MDCT transforms + */ +typedef void (*av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride); + +/** + * Initialize a transform context with the given configuration + * Currently power of two lengths from 4 to 131072 are supported, along with + * any length decomposable to a power of two and either 3, 5 or 15. + * + * @param ctx the context to allocate, will be NULL on error + * @param tx pointer to the transform function pointer to set + * @param type type the type of transform + * @param inv whether to do an inverse or a forward transform + * @param len the size of the transform in samples + * @param scale pointer to the value to scale the output if supported by type + * @param flags currently unused + * + * @return 0 on success, negative error code on failure + */ +int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, + int inv, int len, const void *scale, uint64_t flags); + +/** + * Frees a context and sets ctx to NULL, does nothing when ctx == NULL + */ +void av_tx_uninit(AVTXContext **ctx); + +#endif /* AVUTIL_TX_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/version.h b/thirdparty/user_include/ffmpeg/libavutil/version.h new file mode 100755 index 0000000000000000000000000000000000000000..24ca8ab7db7d1f6083265f7dbb3fa0c9cce23e0b --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/version.h @@ -0,0 +1,139 @@ +/* + * copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @ingroup lavu + * Libavutil version macros + */ + +#ifndef AVUTIL_VERSION_H +#define AVUTIL_VERSION_H + +#include "macros.h" + +/** + * @addtogroup version_utils + * + * Useful to check and match library version in order to maintain + * backward compatibility. + * + * The FFmpeg libraries follow a versioning sheme very similar to + * Semantic Versioning (http://semver.org/) + * The difference is that the component called PATCH is called MICRO in FFmpeg + * and its value is reset to 100 instead of 0 to keep it above or equal to 100. + * Also we do not increase MICRO for every bugfix or change in git master. + * + * Prior to FFmpeg 3.2 point releases did not change any lib version number to + * avoid aliassing different git master checkouts. + * Starting with FFmpeg 3.2, the released library versions will occupy + * a separate MAJOR.MINOR that is not used on the master development branch. + * That is if we branch a release of master 55.10.123 we will bump to 55.11.100 + * for the release and master will continue at 55.12.100 after it. Each new + * point release will then bump the MICRO improving the usefulness of the lib + * versions. + * + * @{ + */ + +#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c)) +#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c +#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) + +/** + * Extract version components from the full ::AV_VERSION_INT int as returned + * by functions like ::avformat_version() and ::avcodec_version() + */ +#define AV_VERSION_MAJOR(a) ((a) >> 16) +#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8) +#define AV_VERSION_MICRO(a) ((a) & 0xFF) + +/** + * @} + */ + +/** + * @defgroup lavu_ver Version and Build diagnostics + * + * Macros and function useful to check at compiletime and at runtime + * which version of libavutil is in use. + * + * @{ + */ + +#define LIBAVUTIL_VERSION_MAJOR 56 +#define LIBAVUTIL_VERSION_MINOR 31 +#define LIBAVUTIL_VERSION_MICRO 100 + +#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \ + LIBAVUTIL_VERSION_MINOR, \ + LIBAVUTIL_VERSION_MICRO) +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + +/** + * @defgroup lavu_depr_guards Deprecation Guards + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + * @{ + */ + +#ifndef FF_API_VAAPI +#define FF_API_VAAPI (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_FRAME_QP +#define FF_API_FRAME_QP (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PLUS1_MINUS1 +#define FF_API_PLUS1_MINUS1 (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_ERROR_FRAME +#define FF_API_ERROR_FRAME (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PKT_PTS +#define FF_API_PKT_PTS (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_CRYPTO_SIZE_T +#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_FRAME_GET_SET +#define FF_API_FRAME_GET_SET (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_PSEUDOPAL +#define FF_API_PSEUDOPAL (LIBAVUTIL_VERSION_MAJOR < 57) +#endif + + +/** + * @} + * @} + */ + +#endif /* AVUTIL_VERSION_H */ diff --git a/thirdparty/user_include/ffmpeg/libavutil/xtea.h b/thirdparty/user_include/ffmpeg/libavutil/xtea.h new file mode 100755 index 0000000000000000000000000000000000000000..735427c109a15229f7750073b4591763d6ab60ca --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libavutil/xtea.h @@ -0,0 +1,94 @@ +/* + * A 32-bit implementation of the XTEA algorithm + * Copyright (c) 2012 Samuel Pitoiset + * + * 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 + */ + +#ifndef AVUTIL_XTEA_H +#define AVUTIL_XTEA_H + +#include + +/** + * @file + * @brief Public header for libavutil XTEA algorithm + * @defgroup lavu_xtea XTEA + * @ingroup lavu_crypto + * @{ + */ + +typedef struct AVXTEA { + uint32_t key[16]; +} AVXTEA; + +/** + * Allocate an AVXTEA context. + */ +AVXTEA *av_xtea_alloc(void); + +/** + * Initialize an AVXTEA context. + * + * @param ctx an AVXTEA context + * @param key a key of 16 bytes used for encryption/decryption, + * interpreted as big endian 32 bit numbers + */ +void av_xtea_init(struct AVXTEA *ctx, const uint8_t key[16]); + +/** + * Initialize an AVXTEA context. + * + * @param ctx an AVXTEA context + * @param key a key of 16 bytes used for encryption/decryption, + * interpreted as little endian 32 bit numbers + */ +void av_xtea_le_init(struct AVXTEA *ctx, const uint8_t key[16]); + +/** + * Encrypt or decrypt a buffer using a previously initialized context, + * in big endian format. + * + * @param ctx an AVXTEA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_xtea_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * Encrypt or decrypt a buffer using a previously initialized context, + * in little endian format. + * + * @param ctx an AVXTEA context + * @param dst destination array, can be equal to src + * @param src source array, can be equal to dst + * @param count number of 8 byte blocks + * @param iv initialization vector for CBC mode, if NULL then ECB will be used + * @param decrypt 0 for encryption, 1 for decryption + */ +void av_xtea_le_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src, + int count, uint8_t *iv, int decrypt); + +/** + * @} + */ + +#endif /* AVUTIL_XTEA_H */ diff --git a/thirdparty/user_include/ffmpeg/libswresample/swresample.h b/thirdparty/user_include/ffmpeg/libswresample/swresample.h new file mode 100755 index 0000000000000000000000000000000000000000..c7b84fbcac526ed3b28d404a4c1385a641984bfd --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libswresample/swresample.h @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at) + * + * This file is part of libswresample + * + * libswresample 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. + * + * libswresample 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 libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_SWRESAMPLE_H +#define SWRESAMPLE_SWRESAMPLE_H + +/** + * @file + * @ingroup lswr + * libswresample public header + */ + +/** + * @defgroup lswr libswresample + * @{ + * + * Audio resampling, sample format conversion and mixing library. + * + * Interaction with lswr is done through SwrContext, which is + * allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * The first thing you will need to do in order to use lswr is to allocate + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you + * are using the former, you must set options through the @ref avoptions API. + * The latter function provides the same feature, but it allows you to set some + * common options in the same statement. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix). This is using the swr_alloc() function. + * @code + * SwrContext *swr = swr_alloc(); + * av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(swr, "in_sample_rate", 48000, 0); + * av_opt_set_int(swr, "out_sample_rate", 44100, 0); + * av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * The same job can be done using swr_alloc_set_opts() as well: + * @code + * SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context + * AV_CH_LAYOUT_STEREO, // out_ch_layout + * AV_SAMPLE_FMT_S16, // out_sample_fmt + * 44100, // out_sample_rate + * AV_CH_LAYOUT_5POINT1, // in_ch_layout + * AV_SAMPLE_FMT_FLTP, // in_sample_fmt + * 48000, // in_sample_rate + * 0, // log_offset + * NULL); // log_ctx + * @endcode + * + * Once all values have been set, it must be initialized with swr_init(). If + * you need to change the conversion parameters, you can change the parameters + * using @ref AVOptions, as described above in the first example; or by using + * swr_alloc_set_opts(), but with the first argument the allocated context. + * You must then call swr_init() again. + * + * The conversion itself is done by repeatedly calling swr_convert(). + * Note that the samples may get buffered in swr if you provide insufficient + * output space or if sample rate conversion is done, which requires "future" + * samples. Samples that do not require future input can be retrieved at any + * time by using swr_convert() (in_count can be set to 0). + * At the end of conversion the resampling buffer can be flushed by calling + * swr_convert() with NULL in and 0 in_count. + * + * The samples used in the conversion process can be managed with the libavutil + * @ref lavu_sampmanip "samples manipulation" API, including av_samples_alloc() + * function used in the following example. + * + * The delay between input and output, can at any time be found by using + * swr_get_delay(). + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_samples; + * + * while (get_input(&input, &in_samples)) { + * uint8_t *output; + * int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, NULL, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = swr_convert(swr, &output, out_samples, + * input, in_samples); + * handle_output(output, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished, the conversion + * context and everything associated with it must be freed with swr_free(). + * A swr_close() function is also available, but it exists mainly for + * compatibility with libavresample, and is not required to be called. + * + * There will be no memory leak if the data is not completely flushed before + * swr_free(). + */ + +#include +#include "libavutil/channel_layout.h" +#include "libavutil/frame.h" +#include "libavutil/samplefmt.h" + +#include "libswresample/version.h" + +/** + * @name Option constants + * These constants are used for the @ref avoptions interface for lswr. + * @{ + * + */ + +#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate +//TODO use int resample ? +//long term TODO can we enable this dynamically? + +/** Dithering algorithms */ +enum SwrDitherType { + SWR_DITHER_NONE = 0, + SWR_DITHER_RECTANGULAR, + SWR_DITHER_TRIANGULAR, + SWR_DITHER_TRIANGULAR_HIGHPASS, + + SWR_DITHER_NS = 64, ///< not part of API/ABI + SWR_DITHER_NS_LIPSHITZ, + SWR_DITHER_NS_F_WEIGHTED, + SWR_DITHER_NS_MODIFIED_E_WEIGHTED, + SWR_DITHER_NS_IMPROVED_E_WEIGHTED, + SWR_DITHER_NS_SHIBATA, + SWR_DITHER_NS_LOW_SHIBATA, + SWR_DITHER_NS_HIGH_SHIBATA, + SWR_DITHER_NB, ///< not part of API/ABI +}; + +/** Resampling Engines */ +enum SwrEngine { + SWR_ENGINE_SWR, /**< SW Resampler */ + SWR_ENGINE_SOXR, /**< SoX Resampler */ + SWR_ENGINE_NB, ///< not part of API/ABI +}; + +/** Resampling Filter Types */ +enum SwrFilterType { + SWR_FILTER_TYPE_CUBIC, /**< Cubic */ + SWR_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall windowed sinc */ + SWR_FILTER_TYPE_KAISER, /**< Kaiser windowed sinc */ +}; + +/** + * @} + */ + +/** + * The libswresample context. Unlike libavcodec and libavformat, this structure + * is opaque. This means that if you would like to set options, you must use + * the @ref avoptions API and cannot directly set values to members of the + * structure. + */ +typedef struct SwrContext SwrContext; + +/** + * Get the AVClass for SwrContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + * @return the AVClass of SwrContext + */ +const AVClass *swr_get_class(void); + +/** + * @name SwrContext constructor functions + * @{ + */ + +/** + * Allocate SwrContext. + * + * If you use this function you will need to set the parameters (manually or + * with swr_alloc_set_opts()) before calling swr_init(). + * + * @see swr_alloc_set_opts(), swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc(void); + +/** + * Initialize context after user parameters have been set. + * @note The context must be configured using the AVOption API. + * + * @see av_opt_set_int() + * @see av_opt_set_dict() + * + * @param[in,out] s Swr context to initialize + * @return AVERROR error code in case of failure. + */ +int swr_init(struct SwrContext *s); + +/** + * Check whether an swr context has been initialized or not. + * + * @param[in] s Swr context to check + * @see swr_init() + * @return positive if it has been initialized, 0 if not initialized + */ +int swr_is_initialized(struct SwrContext *s); + +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require s to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters + * on the allocated context. + * + * @param s existing Swr context if available, or NULL if not + * @param out_ch_layout output channel layout (AV_CH_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (AV_CH_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return NULL on error, allocated context otherwise + */ +struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, + int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); + +/** + * @} + * + * @name SwrContext destructor functions + * @{ + */ + +/** + * Free the given SwrContext and set the pointer to NULL. + * + * @param[in] s a pointer to a pointer to Swr context + */ +void swr_free(struct SwrContext **s); + +/** + * Closes the context so that swr_is_initialized() returns 0. + * + * The context can be brought back to life by running swr_init(), + * swr_init() can also be used without swr_close(). + * This function is mainly provided for simplifying the usecase + * where one tries to support libavresample and libswresample. + * + * @param[in,out] s Swr context to be closed + */ +void swr_close(struct SwrContext *s); + +/** + * @} + * + * @name Core conversion functions + * @{ + */ + +/** Convert audio. + * + * in and in_count can be set to 0 to flush the last few samples out at the + * end. + * + * If more input is provided than output space, then the input will be buffered. + * You can avoid this buffering by using swr_get_out_samples() to retrieve an + * upper bound on the required number of output samples for the given number of + * input samples. Conversion will run directly without copying whenever possible. + * + * @param s allocated Swr context, with parameters set + * @param out output buffers, only the first one need be set in case of packed audio + * @param out_count amount of space available for output in samples per channel + * @param in input buffers, only the first one need to be set in case of packed audio + * @param in_count number of input samples available in one channel + * + * @return number of samples output per channel, negative value on error + */ +int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, + const uint8_t **in , int in_count); + +/** + * Convert the next timestamp from input to output + * timestamps are in 1/(in_sample_rate * out_sample_rate) units. + * + * @note There are 2 slightly differently behaving modes. + * @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX) + * in this case timestamps will be passed through with delays compensated + * @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX) + * in this case the output timestamps will match output sample numbers. + * See ffmpeg-resampler(1) for the two modes of compensation. + * + * @param s[in] initialized Swr context + * @param pts[in] timestamp for the next input sample, INT64_MIN if unknown + * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are + * function used internally for timestamp compensation. + * @return the output timestamp for the next output sample + */ +int64_t swr_next_pts(struct SwrContext *s, int64_t pts); + +/** + * @} + * + * @name Low-level option setting functions + * These functons provide a means to set low-level options that is not possible + * with the AVOption API. + * @{ + */ + +/** + * Activate resampling compensation ("soft" compensation). This function is + * internally called when needed in swr_next_pts(). + * + * @param[in,out] s allocated Swr context. If it is not initialized, + * or SWR_FLAG_RESAMPLE is not set, swr_init() is + * called with the flag set. + * @param[in] sample_delta delta in PTS per sample + * @param[in] compensation_distance number of samples to compensate for + * @return >= 0 on success, AVERROR error codes if: + * @li @c s is NULL, + * @li @c compensation_distance is less than 0, + * @li @c compensation_distance is 0 but sample_delta is not, + * @li compensation unsupported by resampler, or + * @li swr_init() fails when called. + */ +int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance); + +/** + * Set a customized input channel mapping. + * + * @param[in,out] s allocated Swr context, not yet initialized + * @param[in] channel_map customized input channel mapping (array of channel + * indexes, -1 for a muted channel) + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); + +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + */ +int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double rematrix_maxval, + double rematrix_volume, double *matrix, + int stride, enum AVMatrixEncoding matrix_encoding, + void *log_ctx); + +/** + * Set a customized remix matrix. + * + * @param s allocated Swr context, not yet initialized + * @param matrix remix coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o + * @param stride offset between lines of the matrix + * @return >= 0 on success, or AVERROR error code in case of failure. + */ +int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride); + +/** + * @} + * + * @name Sample handling functions + * @{ + */ + +/** + * Drops the specified number of output samples. + * + * This function, along with swr_inject_silence(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_drop_output(struct SwrContext *s, int count); + +/** + * Injects the specified number of silence samples. + * + * This function, along with swr_drop_output(), is called by swr_next_pts() + * if needed for "hard" compensation. + * + * @param s allocated Swr context + * @param count number of samples to be dropped + * + * @return >= 0 on success, or a negative AVERROR code on failure + */ +int swr_inject_silence(struct SwrContext *s, int count); + +/** + * Gets the delay the next input sample will experience relative to the next output sample. + * + * Swresample can buffer data if more input has been provided than available + * output space, also converting between sample rates needs a delay. + * This function returns the sum of all such delays. + * The exact delay is not necessarily an integer value in either input or + * output sample rate. Especially when downsampling by a large value, the + * output sample rate may be a poor choice to represent the delay, similarly + * for upsampling and the input sample rate. + * + * @param s swr context + * @param base timebase in which the returned delay will be: + * @li if it's set to 1 the returned delay is in seconds + * @li if it's set to 1000 the returned delay is in milliseconds + * @li if it's set to the input sample rate then the returned + * delay is in input samples + * @li if it's set to the output sample rate then the returned + * delay is in output samples + * @li if it's the least common multiple of in_sample_rate and + * out_sample_rate then an exact rounding-free delay will be + * returned + * @returns the delay in 1 / @c base units. + */ +int64_t swr_get_delay(struct SwrContext *s, int64_t base); + +/** + * Find an upper bound on the number of samples that the next swr_convert + * call will output, if called with in_samples of input samples. This + * depends on the internal state, and anything changing the internal state + * (like further swr_convert() calls) will may change the number of samples + * swr_get_out_samples() returns for the same number of input samples. + * + * @param in_samples number of input samples. + * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts() + * or swr_set_compensation() invalidates this limit + * @note it is recommended to pass the correct available buffer size + * to all functions like swr_convert() even if swr_get_out_samples() + * indicates that less would be used. + * @returns an upper bound on the number of samples that the next swr_convert + * will output or a negative value to indicate an error + */ +int swr_get_out_samples(struct SwrContext *s, int in_samples); + +/** + * @} + * + * @name Configuration accessors + * @{ + */ + +/** + * Return the @ref LIBSWRESAMPLE_VERSION_INT constant. + * + * This is useful to check if the build-time libswresample has the same version + * as the run-time one. + * + * @returns the unsigned int-typed version + */ +unsigned swresample_version(void); + +/** + * Return the swr build-time configuration. + * + * @returns the build-time @c ./configure flags + */ +const char *swresample_configuration(void); + +/** + * Return the swr license. + * + * @returns the license of libswresample, determined at build-time + */ +const char *swresample_license(void); + +/** + * @} + * + * @name AVFrame based API + * @{ + */ + +/** + * Convert the samples in the input AVFrame and write them to the output AVFrame. + * + * Input and output AVFrames must have channel_layout, sample_rate and format set. + * + * If the output AVFrame does not have the data pointers allocated the nb_samples + * field will be set using av_frame_get_buffer() + * is called to allocate the frame. + * + * The output AVFrame can be NULL or have fewer allocated samples than required. + * In this case, any remaining samples not written to the output will be added + * to an internal FIFO buffer, to be returned at the next call to this function + * or to swr_convert(). + * + * If converting sample rate, there may be data remaining in the internal + * resampling delay buffer. swr_get_delay() tells the number of + * remaining samples. To get this data as output, call this function or + * swr_convert() with NULL input. + * + * If the SwrContext configuration does not match the output and + * input AVFrame settings the conversion does not take place and depending on + * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED + * or the result of a bitwise-OR of them is returned. + * + * @see swr_delay() + * @see swr_convert() + * @see swr_get_delay() + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure or nonmatching + * configuration. + */ +int swr_convert_frame(SwrContext *swr, + AVFrame *output, const AVFrame *input); + +/** + * Configure or reconfigure the SwrContext using the information + * provided by the AVFrames. + * + * The original resampling context is reset even on failure. + * The function calls swr_close() internally if the context is open. + * + * @see swr_close(); + * + * @param swr audio resample context + * @param output output AVFrame + * @param input input AVFrame + * @return 0 on success, AVERROR on failure. + */ +int swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in); + +/** + * @} + * @} + */ + +#endif /* SWRESAMPLE_SWRESAMPLE_H */ diff --git a/thirdparty/user_include/ffmpeg/libswresample/version.h b/thirdparty/user_include/ffmpeg/libswresample/version.h new file mode 100755 index 0000000000000000000000000000000000000000..a0b361bc1f137973d131cffe78404bf2cc6ba6ec --- /dev/null +++ b/thirdparty/user_include/ffmpeg/libswresample/version.h @@ -0,0 +1,45 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample 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. + * + * libswresample 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 libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_H +#define SWRESAMPLE_VERSION_H + +/** + * @file + * Libswresample version macros + */ + +#include "libavutil/avutil.h" + +#define LIBSWRESAMPLE_VERSION_MAJOR 3 +#define LIBSWRESAMPLE_VERSION_MINOR 5 +#define LIBSWRESAMPLE_VERSION_MICRO 100 + +#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_VERSION AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \ + LIBSWRESAMPLE_VERSION_MINOR, \ + LIBSWRESAMPLE_VERSION_MICRO) +#define LIBSWRESAMPLE_BUILD LIBSWRESAMPLE_VERSION_INT + +#define LIBSWRESAMPLE_IDENT "SwR" AV_STRINGIFY(LIBSWRESAMPLE_VERSION) + +#endif /* SWRESAMPLE_VERSION_H */ diff --git a/thirdparty/user_include/openssl/aes.h b/thirdparty/user_include/openssl/aes.h new file mode 100755 index 0000000000000000000000000000000000000000..245c552abd05fcc19876f012c067d37c68ac46f0 --- /dev/null +++ b/thirdparty/user_include/openssl/aes.h @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_AES_H +# define HEADER_AES_H + +# include + +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define AES_ENCRYPT 1 +# define AES_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ +# define AES_MAXNR 14 +# define AES_BLOCK_SIZE 16 + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { +# ifdef AES_LONG + unsigned long rd_key[4 * (AES_MAXNR + 1)]; +# else + unsigned int rd_key[4 * (AES_MAXNR + 1)]; +# endif + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +const char *AES_options(void); + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num); +/* NB: the IV is _two_ blocks long */ +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +/* NB: the IV is _four_ blocks long */ +void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc); + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); + + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/thirdparty/user_include/openssl/asn1.h b/thirdparty/user_include/openssl/asn1.h new file mode 100755 index 0000000000000000000000000000000000000000..9522eec18f7a95938c4ea396ab5add6791380c90 --- /dev/null +++ b/thirdparty/user_include/openssl/asn1.h @@ -0,0 +1,886 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1_H +# define HEADER_ASN1_H + +# include +# include +# include +# include +# include +# include +# include + +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define V_ASN1_UNIVERSAL 0x00 +# define V_ASN1_APPLICATION 0x40 +# define V_ASN1_CONTEXT_SPECIFIC 0x80 +# define V_ASN1_PRIVATE 0xc0 + +# define V_ASN1_CONSTRUCTED 0x20 +# define V_ASN1_PRIMITIVE_TAG 0x1f +# define V_ASN1_PRIMATIVE_TAG /*compat*/ V_ASN1_PRIMITIVE_TAG + +# define V_ASN1_APP_CHOOSE -2/* let the recipient choose */ +# define V_ASN1_OTHER -3/* used in ASN1_TYPE */ +# define V_ASN1_ANY -4/* used in ASN1 template code */ + +# define V_ASN1_UNDEF -1 +/* ASN.1 tag values */ +# define V_ASN1_EOC 0 +# define V_ASN1_BOOLEAN 1 /**/ +# define V_ASN1_INTEGER 2 +# define V_ASN1_BIT_STRING 3 +# define V_ASN1_OCTET_STRING 4 +# define V_ASN1_NULL 5 +# define V_ASN1_OBJECT 6 +# define V_ASN1_OBJECT_DESCRIPTOR 7 +# define V_ASN1_EXTERNAL 8 +# define V_ASN1_REAL 9 +# define V_ASN1_ENUMERATED 10 +# define V_ASN1_UTF8STRING 12 +# define V_ASN1_SEQUENCE 16 +# define V_ASN1_SET 17 +# define V_ASN1_NUMERICSTRING 18 /**/ +# define V_ASN1_PRINTABLESTRING 19 +# define V_ASN1_T61STRING 20 +# define V_ASN1_TELETEXSTRING 20/* alias */ +# define V_ASN1_VIDEOTEXSTRING 21 /**/ +# define V_ASN1_IA5STRING 22 +# define V_ASN1_UTCTIME 23 +# define V_ASN1_GENERALIZEDTIME 24 /**/ +# define V_ASN1_GRAPHICSTRING 25 /**/ +# define V_ASN1_ISO64STRING 26 /**/ +# define V_ASN1_VISIBLESTRING 26/* alias */ +# define V_ASN1_GENERALSTRING 27 /**/ +# define V_ASN1_UNIVERSALSTRING 28 /**/ +# define V_ASN1_BMPSTRING 30 + +/* + * NB the constants below are used internally by ASN1_INTEGER + * and ASN1_ENUMERATED to indicate the sign. They are *not* on + * the wire tag values. + */ + +# define V_ASN1_NEG 0x100 +# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) + +/* For use with d2i_ASN1_type_bytes() */ +# define B_ASN1_NUMERICSTRING 0x0001 +# define B_ASN1_PRINTABLESTRING 0x0002 +# define B_ASN1_T61STRING 0x0004 +# define B_ASN1_TELETEXSTRING 0x0004 +# define B_ASN1_VIDEOTEXSTRING 0x0008 +# define B_ASN1_IA5STRING 0x0010 +# define B_ASN1_GRAPHICSTRING 0x0020 +# define B_ASN1_ISO64STRING 0x0040 +# define B_ASN1_VISIBLESTRING 0x0040 +# define B_ASN1_GENERALSTRING 0x0080 +# define B_ASN1_UNIVERSALSTRING 0x0100 +# define B_ASN1_OCTET_STRING 0x0200 +# define B_ASN1_BIT_STRING 0x0400 +# define B_ASN1_BMPSTRING 0x0800 +# define B_ASN1_UNKNOWN 0x1000 +# define B_ASN1_UTF8STRING 0x2000 +# define B_ASN1_UTCTIME 0x4000 +# define B_ASN1_GENERALIZEDTIME 0x8000 +# define B_ASN1_SEQUENCE 0x10000 +/* For use with ASN1_mbstring_copy() */ +# define MBSTRING_FLAG 0x1000 +# define MBSTRING_UTF8 (MBSTRING_FLAG) +# define MBSTRING_ASC (MBSTRING_FLAG|1) +# define MBSTRING_BMP (MBSTRING_FLAG|2) +# define MBSTRING_UNIV (MBSTRING_FLAG|4) +# define SMIME_OLDMIME 0x400 +# define SMIME_CRLFEOL 0x800 +# define SMIME_STREAM 0x1000 + struct X509_algor_st; +DEFINE_STACK_OF(X509_ALGOR) + +# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */ +/* + * This indicates that the ASN1_STRING is not a real value but just a place + * holder for the location where indefinite length constructed data should be + * inserted in the memory buffer + */ +# define ASN1_STRING_FLAG_NDEF 0x010 + +/* + * This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been accessed. + * The flag will be reset when content has been written to it. + */ + +# define ASN1_STRING_FLAG_CONT 0x020 +/* + * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING + * type. + */ +# define ASN1_STRING_FLAG_MSTRING 0x040 +/* String is embedded and only content should be freed */ +# define ASN1_STRING_FLAG_EMBED 0x080 +/* String should be parsed in RFC 5280's time format */ +# define ASN1_STRING_FLAG_X509_TIME 0x100 +/* This is the base type that holds just about everything :-) */ +struct asn1_string_st { + int length; + int type; + unsigned char *data; + /* + * The value of the following field depends on the type being held. It + * is mostly being used for BIT_STRING so if the input data has a + * non-zero 'unused bits' value, it will be handled correctly + */ + long flags; +}; + +/* + * ASN1_ENCODING structure: this is used to save the received encoding of an + * ASN1 type. This is useful to get round problems with invalid encodings + * which can break signatures. + */ + +typedef struct ASN1_ENCODING_st { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ +} ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +# define ASN1_LONG_UNDEF 0x7fffffffL + +# define STABLE_FLAGS_MALLOC 0x01 +/* + * A zero passed to ASN1_STRING_TABLE_new_add for the flags is interpreted + * as "don't change" and STABLE_FLAGS_MALLOC is always set. By setting + * STABLE_FLAGS_MALLOC only we can clear the existing value. Use the alias + * STABLE_FLAGS_CLEAR to reflect this. + */ +# define STABLE_FLAGS_CLEAR STABLE_FLAGS_MALLOC +# define STABLE_NO_MASK 0x02 +# define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +DEFINE_STACK_OF(ASN1_STRING_TABLE) + +/* size limits: this stuff is taken straight from RFC2459 */ + +# define ub_name 32768 +# define ub_common_name 64 +# define ub_locality_name 128 +# define ub_state_name 128 +# define ub_organization_name 64 +# define ub_organization_unit_name 64 +# define ub_title 64 +# define ub_email_address 128 + +/* + * Declarations for template structures: for full definitions see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +# define DECLARE_ASN1_NDEF_FUNCTION(name) \ + int i2d_##name##_NDEF(name *a, unsigned char **out); + +# define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + type *name##_new(void); \ + void name##_free(type *a); + +# define DECLARE_ASN1_PRINT_FUNCTION(stname) \ + DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname) + +# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx); + +# define D2I_OF(type) type *(*)(type **,const unsigned char **,long) +# define I2D_OF(type) int (*)(type *,unsigned char **) +# define I2D_OF_const(type) int (*)(const type *,unsigned char **) + +# define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +# define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +# define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +# define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +# define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + +# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) +# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **) +# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) + +TYPEDEF_D2I2D_OF(void); + +/*- + * The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +# define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +# define DECLARE_ASN1_ITEM(name) \ + OPENSSL_EXTERN const ASN1_ITEM name##_it; + +# else + +/* + * Platforms that can't easily handle shared global variables are declared as + * functions returning ASN1_ITEM pointers. + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM *ASN1_ITEM_EXP (void); + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr()) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (iptr##_it) + +# define ASN1_ITEM_rptr(ref) (ref##_it()) + +# define DECLARE_ASN1_ITEM(name) \ + const ASN1_ITEM * name##_it(void); + +# endif + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* + * These determine which characters to escape: RFC2253 special characters, + * control characters and MSB set characters + */ + +# define ASN1_STRFLGS_ESC_2253 1 +# define ASN1_STRFLGS_ESC_CTRL 2 +# define ASN1_STRFLGS_ESC_MSB 4 + +/* + * This flag determines how we do escaping: normally RC2253 backslash only, + * set this to use backslash and quote. + */ + +# define ASN1_STRFLGS_ESC_QUOTE 8 + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +# define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +# define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +# define CHARTYPE_LAST_ESC_2253 0x40 + +/* + * NB the internal flags are safely reused below by flags handled at the top + * level. + */ + +/* + * If this is set we convert all character strings to UTF8 first + */ + +# define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* + * If this is set we don't attempt to interpret content: just assume all + * strings are 1 byte per character. This will produce some pretty odd + * looking output! + */ + +# define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +# define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* + * This determines which strings to display and which to 'dump' (hex dump of + * content octets or DER encoding). We can only dump non character strings or + * everything. If we don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to the usual escaping + * options. + */ + +# define ASN1_STRFLGS_DUMP_ALL 0x80 +# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* + * These determine what 'dumping' does, we can dump the content octets or the + * DER encoding: both use the RFC2253 #XXXXX notation. + */ + +# define ASN1_STRFLGS_DUMP_DER 0x200 + +/* + * This flag specifies that RC2254 escaping shall be performed. + */ +#define ASN1_STRFLGS_ESC_2254 0x400 + +/* + * All the string flags consistent with RFC2253, escaping control characters + * isn't essential in RFC2253 but it is advisable anyway. + */ + +# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DEFINE_STACK_OF(ASN1_INTEGER) + +DEFINE_STACK_OF(ASN1_GENERALSTRING) + +DEFINE_STACK_OF(ASN1_UTF8STRING) + +typedef struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING *asn1_string; + ASN1_OBJECT *object; + ASN1_INTEGER *integer; + ASN1_ENUMERATED *enumerated; + ASN1_BIT_STRING *bit_string; + ASN1_OCTET_STRING *octet_string; + ASN1_PRINTABLESTRING *printablestring; + ASN1_T61STRING *t61string; + ASN1_IA5STRING *ia5string; + ASN1_GENERALSTRING *generalstring; + ASN1_BMPSTRING *bmpstring; + ASN1_UNIVERSALSTRING *universalstring; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *generalizedtime; + ASN1_VISIBLESTRING *visiblestring; + ASN1_UTF8STRING *utf8string; + /* + * set and sequence are left complete and still contain the set or + * sequence bytes + */ + ASN1_STRING *set; + ASN1_STRING *sequence; + ASN1_VALUE *asn1_value; + } value; +} ASN1_TYPE; + +DEFINE_STACK_OF(ASN1_TYPE) + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY) + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + +# define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +# define B_ASN1_PRINTABLE \ + B_ASN1_NUMERICSTRING| \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_SEQUENCE|\ + B_ASN1_UNKNOWN + +# define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +# define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +int ASN1_TYPE_get(const ASN1_TYPE *a); +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t); +void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t); + +ASN1_OBJECT *ASN1_OBJECT_new(void); +void ASN1_OBJECT_free(ASN1_OBJECT *a); +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp); +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); + +DECLARE_ASN1_ITEM(ASN1_OBJECT) + +DEFINE_STACK_OF(ASN1_OBJECT) + +ASN1_STRING *ASN1_STRING_new(void); +void ASN1_STRING_free(ASN1_STRING *a); +void ASN1_STRING_clear_free(ASN1_STRING *a); +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a); +ASN1_STRING *ASN1_STRING_type_new(int type); +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + /* + * Since this is used to store all sorts of things, via macros, for now, + * make its data void * + */ +int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); +int ASN1_STRING_length(const ASN1_STRING *x); +void ASN1_STRING_length_set(ASN1_STRING *x, int n); +int ASN1_STRING_type(const ASN1_STRING *x); +DEPRECATEDIN_1_1_0(unsigned char *ASN1_STRING_data(ASN1_STRING *x)) +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x); + +DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING) +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length); +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n); +int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, + const unsigned char *flags, int flags_len); + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent); +int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl); +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, + BIT_STRING_BITNAME *tbl); + +DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER) +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x); +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y); + +DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t); +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, + long offset_sec); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); + +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to); + +DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a); +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b); +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, + int len); + +DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_NULL) +DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +int UTF8_putc(unsigned char *str, int len, unsigned long value); + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) +DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_TIME) + +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF) + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_TIME_check(const ASN1_TIME *t); +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, + ASN1_GENERALIZEDTIME **out); +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); +int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str); +int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm); +int ASN1_TIME_normalize(ASN1_TIME *s); +int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t); +int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b); + +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a); +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size); +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a); +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size); +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a); +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size); +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type); +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a); + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num); +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln); + +int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a); +int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r); +int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a); +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r); + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +long ASN1_INTEGER_get(const ASN1_INTEGER *a); +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); + +int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a); +int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r); + + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai); +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +int ASN1_PRINTABLE_type(const unsigned char *s, int max); + +unsigned long ASN1_tag2bit(int tag); + +/* SPECIALS */ +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax); +int ASN1_check_infinite_end(unsigned char **p, long len); +int ASN1_const_check_infinite_end(const unsigned char **p, long len); +void ASN1_put_object(unsigned char **pp, int constructed, int length, + int tag, int xclass); +int ASN1_put_eoc(unsigned char **pp); +int ASN1_object_size(int constructed, int length, int tag); + +/* Used to implement other functions */ +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); + +# define ASN1_dup_of(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_dup_of_const(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(const type, x))) + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +/* ASN1 alloc/free macros for when a type is only used internally */ + +# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) +# define M_ASN1_free_of(x, type) \ + ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) + +# ifndef OPENSSL_NO_STDIO +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x); + +# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x); + +# define ASN1_i2d_fp_of(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_fp_of_const(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags); +# endif + +int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in); + +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x); + +# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x); + +# define ASN1_i2d_bio_of(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_bio_of_const(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); +int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); +int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); +int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a); +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); +int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags); +int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off); +int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, + unsigned char *buf, int off); +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent); +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, + int dump); +const char *ASN1_tag2str(int tag); + +/* Used to load and write Netscape format cert */ + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len); +int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len); +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, + unsigned char *data, int len); +int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len); + +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it); + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, + ASN1_OCTET_STRING **oct); + +void ASN1_STRING_set_default_mask(unsigned long mask); +int ASN1_STRING_set_default_mask_asc(const char *p); +unsigned long ASN1_STRING_get_default_mask(void); +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask); +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize); + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, + int inform, int nid); +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +void ASN1_STRING_TABLE_cleanup(void); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it); + +void ASN1_add_oid_module(void); +void ASN1_add_stable_module(void); + +ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf); +ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf); +int ASN1_str2mask(const char *str, unsigned long *pmask); + +/* ASN1 Print flags */ + +/* Indicate missing OPTIONAL fields */ +# define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001 +/* Mark start and end of SEQUENCE */ +# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002 +/* Mark start and end of SEQUENCE/SET OF */ +# define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004 +/* Show the ASN1 type of primitives */ +# define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008 +/* Don't show ASN1 type of ANY */ +# define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010 +/* Don't show ASN1 type of MSTRINGs */ +# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020 +/* Don't show field names in SEQUENCE */ +# define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040 +/* Show structure names of each SEQUENCE field */ +# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080 +/* Don't show structure name even at top level */ +# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100 + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, + const ASN1_ITEM *it, const ASN1_PCTX *pctx); +ASN1_PCTX *ASN1_PCTX_new(void); +void ASN1_PCTX_free(ASN1_PCTX *p); +unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags); + +ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx)); +void ASN1_SCTX_free(ASN1_SCTX *p); +const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p); +const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p); +unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p); +void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data); +void *ASN1_SCTX_get_app_data(ASN1_SCTX *p); + +const BIO_METHOD *BIO_f_asn1(void); + +BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it); + +int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it); +int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const char *hdr, const ASN1_ITEM *it); +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it); +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it); +int SMIME_crlf_copy(BIO *in, BIO *out, int flags); +int SMIME_text(BIO *in, BIO *out); + +const ASN1_ITEM *ASN1_ITEM_lookup(const char *name); +const ASN1_ITEM *ASN1_ITEM_get(size_t i); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/asn1_mac.h b/thirdparty/user_include/openssl/asn1_mac.h new file mode 100755 index 0000000000000000000000000000000000000000..7ac1782a3f20d3ba5918eaac67802b88696ca94f --- /dev/null +++ b/thirdparty/user_include/openssl/asn1_mac.h @@ -0,0 +1,10 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#error "This file is obsolete; please update your software." diff --git a/thirdparty/user_include/openssl/asn1err.h b/thirdparty/user_include/openssl/asn1err.h new file mode 100755 index 0000000000000000000000000000000000000000..5a91126db954d044d581cc844513c18cd87f89d1 --- /dev/null +++ b/thirdparty/user_include/openssl/asn1err.h @@ -0,0 +1,252 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1ERR_H +# define HEADER_ASN1ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ASN1_strings(void); + +/* + * ASN1 function codes. + */ +# define ASN1_F_A2D_ASN1_OBJECT 100 +# define ASN1_F_A2I_ASN1_INTEGER 102 +# define ASN1_F_A2I_ASN1_STRING 103 +# define ASN1_F_APPEND_EXP 176 +# define ASN1_F_ASN1_BIO_INIT 113 +# define ASN1_F_ASN1_BIT_STRING_SET_BIT 183 +# define ASN1_F_ASN1_CB 177 +# define ASN1_F_ASN1_CHECK_TLEN 104 +# define ASN1_F_ASN1_COLLECT 106 +# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108 +# define ASN1_F_ASN1_D2I_FP 109 +# define ASN1_F_ASN1_D2I_READ_BIO 107 +# define ASN1_F_ASN1_DIGEST 184 +# define ASN1_F_ASN1_DO_ADB 110 +# define ASN1_F_ASN1_DO_LOCK 233 +# define ASN1_F_ASN1_DUP 111 +# define ASN1_F_ASN1_ENC_SAVE 115 +# define ASN1_F_ASN1_EX_C2I 204 +# define ASN1_F_ASN1_FIND_END 190 +# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216 +# define ASN1_F_ASN1_GENERATE_V3 178 +# define ASN1_F_ASN1_GET_INT64 224 +# define ASN1_F_ASN1_GET_OBJECT 114 +# define ASN1_F_ASN1_GET_UINT64 225 +# define ASN1_F_ASN1_I2D_BIO 116 +# define ASN1_F_ASN1_I2D_FP 117 +# define ASN1_F_ASN1_ITEM_D2I_FP 206 +# define ASN1_F_ASN1_ITEM_DUP 191 +# define ASN1_F_ASN1_ITEM_EMBED_D2I 120 +# define ASN1_F_ASN1_ITEM_EMBED_NEW 121 +# define ASN1_F_ASN1_ITEM_FLAGS_I2D 118 +# define ASN1_F_ASN1_ITEM_I2D_BIO 192 +# define ASN1_F_ASN1_ITEM_I2D_FP 193 +# define ASN1_F_ASN1_ITEM_PACK 198 +# define ASN1_F_ASN1_ITEM_SIGN 195 +# define ASN1_F_ASN1_ITEM_SIGN_CTX 220 +# define ASN1_F_ASN1_ITEM_UNPACK 199 +# define ASN1_F_ASN1_ITEM_VERIFY 197 +# define ASN1_F_ASN1_MBSTRING_NCOPY 122 +# define ASN1_F_ASN1_OBJECT_NEW 123 +# define ASN1_F_ASN1_OUTPUT_DATA 214 +# define ASN1_F_ASN1_PCTX_NEW 205 +# define ASN1_F_ASN1_PRIMITIVE_NEW 119 +# define ASN1_F_ASN1_SCTX_NEW 221 +# define ASN1_F_ASN1_SIGN 128 +# define ASN1_F_ASN1_STR2TYPE 179 +# define ASN1_F_ASN1_STRING_GET_INT64 227 +# define ASN1_F_ASN1_STRING_GET_UINT64 230 +# define ASN1_F_ASN1_STRING_SET 186 +# define ASN1_F_ASN1_STRING_TABLE_ADD 129 +# define ASN1_F_ASN1_STRING_TO_BN 228 +# define ASN1_F_ASN1_STRING_TYPE_NEW 130 +# define ASN1_F_ASN1_TEMPLATE_EX_D2I 132 +# define ASN1_F_ASN1_TEMPLATE_NEW 133 +# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131 +# define ASN1_F_ASN1_TIME_ADJ 217 +# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134 +# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 +# define ASN1_F_ASN1_UTCTIME_ADJ 218 +# define ASN1_F_ASN1_VERIFY 137 +# define ASN1_F_B64_READ_ASN1 209 +# define ASN1_F_B64_WRITE_ASN1 210 +# define ASN1_F_BIO_NEW_NDEF 208 +# define ASN1_F_BITSTR_CB 180 +# define ASN1_F_BN_TO_ASN1_STRING 229 +# define ASN1_F_C2I_ASN1_BIT_STRING 189 +# define ASN1_F_C2I_ASN1_INTEGER 194 +# define ASN1_F_C2I_ASN1_OBJECT 196 +# define ASN1_F_C2I_IBUF 226 +# define ASN1_F_C2I_UINT64_INT 101 +# define ASN1_F_COLLECT_DATA 140 +# define ASN1_F_D2I_ASN1_OBJECT 147 +# define ASN1_F_D2I_ASN1_UINTEGER 150 +# define ASN1_F_D2I_AUTOPRIVATEKEY 207 +# define ASN1_F_D2I_PRIVATEKEY 154 +# define ASN1_F_D2I_PUBLICKEY 155 +# define ASN1_F_DO_BUF 142 +# define ASN1_F_DO_CREATE 124 +# define ASN1_F_DO_DUMP 125 +# define ASN1_F_DO_TCREATE 222 +# define ASN1_F_I2A_ASN1_OBJECT 126 +# define ASN1_F_I2D_ASN1_BIO_STREAM 211 +# define ASN1_F_I2D_ASN1_OBJECT 143 +# define ASN1_F_I2D_DSA_PUBKEY 161 +# define ASN1_F_I2D_EC_PUBKEY 181 +# define ASN1_F_I2D_PRIVATEKEY 163 +# define ASN1_F_I2D_PUBLICKEY 164 +# define ASN1_F_I2D_RSA_PUBKEY 165 +# define ASN1_F_LONG_C2I 166 +# define ASN1_F_NDEF_PREFIX 127 +# define ASN1_F_NDEF_SUFFIX 136 +# define ASN1_F_OID_MODULE_INIT 174 +# define ASN1_F_PARSE_TAGGING 182 +# define ASN1_F_PKCS5_PBE2_SET_IV 167 +# define ASN1_F_PKCS5_PBE2_SET_SCRYPT 231 +# define ASN1_F_PKCS5_PBE_SET 202 +# define ASN1_F_PKCS5_PBE_SET0_ALGOR 215 +# define ASN1_F_PKCS5_PBKDF2_SET 219 +# define ASN1_F_PKCS5_SCRYPT_SET 232 +# define ASN1_F_SMIME_READ_ASN1 212 +# define ASN1_F_SMIME_TEXT 213 +# define ASN1_F_STABLE_GET 138 +# define ASN1_F_STBL_MODULE_INIT 223 +# define ASN1_F_UINT32_C2I 105 +# define ASN1_F_UINT32_NEW 139 +# define ASN1_F_UINT64_C2I 112 +# define ASN1_F_UINT64_NEW 141 +# define ASN1_F_X509_CRL_ADD0_REVOKED 169 +# define ASN1_F_X509_INFO_NEW 170 +# define ASN1_F_X509_NAME_ENCODE 203 +# define ASN1_F_X509_NAME_EX_D2I 158 +# define ASN1_F_X509_NAME_EX_NEW 171 +# define ASN1_F_X509_PKEY_NEW 173 + +/* + * ASN1 reason codes. + */ +# define ASN1_R_ADDING_OBJECT 171 +# define ASN1_R_ASN1_PARSE_ERROR 203 +# define ASN1_R_ASN1_SIG_PARSE_ERROR 204 +# define ASN1_R_AUX_ERROR 100 +# define ASN1_R_BAD_OBJECT_HEADER 102 +# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214 +# define ASN1_R_BN_LIB 105 +# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +# define ASN1_R_BUFFER_TOO_SMALL 107 +# define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108 +# define ASN1_R_CONTEXT_NOT_INITIALISED 217 +# define ASN1_R_DATA_IS_WRONG 109 +# define ASN1_R_DECODE_ERROR 110 +# define ASN1_R_DEPTH_EXCEEDED 174 +# define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198 +# define ASN1_R_ENCODE_ERROR 112 +# define ASN1_R_ERROR_GETTING_TIME 173 +# define ASN1_R_ERROR_LOADING_SECTION 172 +# define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114 +# define ASN1_R_EXPECTING_AN_INTEGER 115 +# define ASN1_R_EXPECTING_AN_OBJECT 116 +# define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +# define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +# define ASN1_R_FIELD_MISSING 121 +# define ASN1_R_FIRST_NUM_TOO_LARGE 122 +# define ASN1_R_HEADER_TOO_LONG 123 +# define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175 +# define ASN1_R_ILLEGAL_BOOLEAN 176 +# define ASN1_R_ILLEGAL_CHARACTERS 124 +# define ASN1_R_ILLEGAL_FORMAT 177 +# define ASN1_R_ILLEGAL_HEX 178 +# define ASN1_R_ILLEGAL_IMPLICIT_TAG 179 +# define ASN1_R_ILLEGAL_INTEGER 180 +# define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226 +# define ASN1_R_ILLEGAL_NESTED_TAGGING 181 +# define ASN1_R_ILLEGAL_NULL 125 +# define ASN1_R_ILLEGAL_NULL_VALUE 182 +# define ASN1_R_ILLEGAL_OBJECT 183 +# define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 +# define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 +# define ASN1_R_ILLEGAL_PADDING 221 +# define ASN1_R_ILLEGAL_TAGGED_ANY 127 +# define ASN1_R_ILLEGAL_TIME_VALUE 184 +# define ASN1_R_ILLEGAL_ZERO_CONTENT 222 +# define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185 +# define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 +# define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220 +# define ASN1_R_INVALID_BMPSTRING_LENGTH 129 +# define ASN1_R_INVALID_DIGIT 130 +# define ASN1_R_INVALID_MIME_TYPE 205 +# define ASN1_R_INVALID_MODIFIER 186 +# define ASN1_R_INVALID_NUMBER 187 +# define ASN1_R_INVALID_OBJECT_ENCODING 216 +# define ASN1_R_INVALID_SCRYPT_PARAMETERS 227 +# define ASN1_R_INVALID_SEPARATOR 131 +# define ASN1_R_INVALID_STRING_TABLE_VALUE 218 +# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 +# define ASN1_R_INVALID_UTF8STRING 134 +# define ASN1_R_INVALID_VALUE 219 +# define ASN1_R_LIST_ERROR 188 +# define ASN1_R_MIME_NO_CONTENT_TYPE 206 +# define ASN1_R_MIME_PARSE_ERROR 207 +# define ASN1_R_MIME_SIG_PARSE_ERROR 208 +# define ASN1_R_MISSING_EOC 137 +# define ASN1_R_MISSING_SECOND_NUMBER 138 +# define ASN1_R_MISSING_VALUE 189 +# define ASN1_R_MSTRING_NOT_UNIVERSAL 139 +# define ASN1_R_MSTRING_WRONG_TAG 140 +# define ASN1_R_NESTED_ASN1_STRING 197 +# define ASN1_R_NESTED_TOO_DEEP 201 +# define ASN1_R_NON_HEX_CHARACTERS 141 +# define ASN1_R_NOT_ASCII_FORMAT 190 +# define ASN1_R_NOT_ENOUGH_DATA 142 +# define ASN1_R_NO_CONTENT_TYPE 209 +# define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +# define ASN1_R_NO_MULTIPART_BODY_FAILURE 210 +# define ASN1_R_NO_MULTIPART_BOUNDARY 211 +# define ASN1_R_NO_SIG_CONTENT_TYPE 212 +# define ASN1_R_NULL_IS_WRONG_LENGTH 144 +# define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 +# define ASN1_R_ODD_NUMBER_OF_CHARS 145 +# define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 +# define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 +# define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +# define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192 +# define ASN1_R_SHORT_LINE 150 +# define ASN1_R_SIG_INVALID_MIME_TYPE 213 +# define ASN1_R_STREAMING_NOT_SUPPORTED 202 +# define ASN1_R_STRING_TOO_LONG 151 +# define ASN1_R_STRING_TOO_SHORT 152 +# define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +# define ASN1_R_TIME_NOT_ASCII_FORMAT 193 +# define ASN1_R_TOO_LARGE 223 +# define ASN1_R_TOO_LONG 155 +# define ASN1_R_TOO_SMALL 224 +# define ASN1_R_TYPE_NOT_CONSTRUCTED 156 +# define ASN1_R_TYPE_NOT_PRIMITIVE 195 +# define ASN1_R_UNEXPECTED_EOC 159 +# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215 +# define ASN1_R_UNKNOWN_FORMAT 160 +# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 +# define ASN1_R_UNKNOWN_OBJECT_TYPE 162 +# define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +# define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199 +# define ASN1_R_UNKNOWN_TAG 194 +# define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 +# define ASN1_R_UNSUPPORTED_CIPHER 228 +# define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +# define ASN1_R_UNSUPPORTED_TYPE 196 +# define ASN1_R_WRONG_INTEGER_TYPE 225 +# define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200 +# define ASN1_R_WRONG_TAG 168 + +#endif diff --git a/thirdparty/user_include/openssl/asn1t.h b/thirdparty/user_include/openssl/asn1t.h new file mode 100755 index 0000000000000000000000000000000000000000..a450ba0d9dea5df587c58a2b0c3fe10e235adcea --- /dev/null +++ b/thirdparty/user_include/openssl/asn1t.h @@ -0,0 +1,945 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASN1T_H +# define HEADER_ASN1T_H + +# include +# include +# include + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + const ASN1_ITEM itname##_it = { + +# define static_ASN1_ITEM_start(itname) \ + static const ASN1_ITEM itname##_it = { + +# define ASN1_ITEM_end(itname) \ + }; + +# else + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)())) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + const ASN1_ITEM * itname##_it(void) \ + { \ + static const ASN1_ITEM local_it = { + +# define static_ASN1_ITEM_start(itname) \ + static ASN1_ITEM_start(itname) + +# define ASN1_ITEM_end(itname) \ + }; \ + return &local_it; \ + } + +# endif + +/* Macros to aid ASN1 template writing */ + +# define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +# define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + +/* This is a ASN1 type which just embeds a template */ + +/*- + * This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +# define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +# define static_ASN1_SEQUENCE_END(stname) static_ASN1_SEQUENCE_END_name(stname, stname) + +# define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #tname \ + ASN1_ITEM_end(tname) + +# define static_ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE(tname) \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + +# define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_BROKEN_SEQUENCE(tname) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_ref(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) +# define static_ASN1_BROKEN_SEQUENCE_END(stname) \ + static_ASN1_SEQUENCE_END_ref(stname, stname) + +# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) +# define static_ASN1_SEQUENCE_END_cb(stname, tname) static_ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #tname \ + ASN1_ITEM_end(tname) +# define static_ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/*- + * This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +# define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +# define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +# define static_ASN1_CHOICE_END(stname) static_ASN1_CHOICE_END_name(stname, stname) + +# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +# define static_ASN1_CHOICE_END_name(stname, tname) static_ASN1_CHOICE_END_selector(stname, tname, type) + +# define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define static_ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +# define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | (ex), tag, stname, field, type) + +# define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | (ex), tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# else +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb } +# endif +/* Plain simple type */ +# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) +/* Embedded simple type */ +# define ASN1_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_EMBED,0, stname, field, type) + +/* OPTIONAL simple type */ +# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) +# define ASN1_OPT_EMBED(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) +# define ASN1_IMP_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_EMBED) + +/* IMPLICIT tagged OPTIONAL simple type */ +# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) +# define ASN1_IMP_OPT_EMBED(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED) + +/* Same as above but EXPLICIT */ + +# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +# define ASN1_EXP_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_EMBED) +# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) +# define ASN1_EXP_OPT_EMBED(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_EMBED) + +/* SEQUENCE OF type */ +# define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +# define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +# define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +# define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* EXPLICIT using indefinite length constructed form */ +# define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + +/* EXPLICIT OPTIONAL using indefinite length constructed form */ +# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) + +/* Macros for the ASN1_ADB structure */ + +# define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + adb_cb,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +# else + +# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \ + ;\ + static const ASN1_ITEM *name##_adb(void) \ + { \ + static const ASN1_ADB internal_adb = \ + {\ + flags,\ + offsetof(name, field),\ + adb_cb,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + }; \ + return (const ASN1_ITEM *) &internal_adb; \ + } \ + void dummy_function(void) + +# endif + +# define ADB_ENTRY(val, template) {val, template} + +# define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +/* + * This is the ASN1 template structure that defines a wrapper round the + * actual type. It determines the actual position of the field in the value + * structure, various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { + unsigned long flags; /* Various flags */ + long tag; /* tag, not used if no tagging */ + unsigned long offset; /* Offset of this field in structure */ + const char *field_name; /* Field name */ + ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +# define ASN1_TEMPLATE_item(t) (t->item_ptr) +# define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + int (*adb_cb)(long *psel); /* Application callback */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +# define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +# define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* + * Special case: this refers to a SET OF that will be sorted into DER order + * when encoded *and* the corresponding STACK will be modified to match the + * new order. + */ +# define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +# define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* + * These flags mean the tag should be taken from the tag field. If EXPLICIT + * then the underlying type is used for the inner tag. + */ + +/* IMPLICIT tagging */ +# define ASN1_TFLG_IMPTAG (0x1 << 3) + +/* EXPLICIT tagging, inner tag from underlying type */ +# define ASN1_TFLG_EXPTAG (0x2 << 3) + +# define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +# define ASN1_TFLG_IMPLICIT (ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT) + +/* context specific EXPLICIT */ +# define ASN1_TFLG_EXPLICIT (ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT) + +/* + * If tagging is in force these determine the type of tag to use. Otherwise + * the tag is determined by the underlying type. These values reflect the + * actual octet format. + */ + +/* Universal tag */ +# define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +# define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +# define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +# define ASN1_TFLG_PRIVATE (0x3<<6) + +# define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* + * These are for ANY DEFINED BY type. In this case the 'item' field points to + * an ASN1_ADB structure which contains a table of values to decode the + * relevant type + */ + +# define ASN1_TFLG_ADB_MASK (0x3<<8) + +# define ASN1_TFLG_ADB_OID (0x1<<8) + +# define ASN1_TFLG_ADB_INT (0x1<<9) + +/* + * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes + * indefinite length constructed encoding to be used if required. + */ + +# define ASN1_TFLG_NDEF (0x1<<11) + +/* Field is embedded and not a pointer */ +# define ASN1_TFLG_EMBED (0x1 << 12) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { + char itype; /* The item type, primitive, SEQUENCE, CHOICE + * or extern */ + long utype; /* underlying type */ + const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains + * the contents */ + long tcount; /* Number of templates if SEQUENCE or CHOICE */ + const void *funcs; /* functions that handle this type */ + long size; /* Structure size (usually) */ + const char *sname; /* Structure name */ +}; + +/*- + * These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + * NDEF_SEQUENCE is the same as SEQUENCE except + * that it will use indefinite length constructed + * encoding if requested. + * + */ + +# define ASN1_ITYPE_PRIMITIVE 0x0 + +# define ASN1_ITYPE_SEQUENCE 0x1 + +# define ASN1_ITYPE_CHOICE 0x2 + +# define ASN1_ITYPE_EXTERN 0x4 + +# define ASN1_ITYPE_MSTRING 0x5 + +# define ASN1_ITYPE_NDEF_SEQUENCE 0x6 + +/* + * Cache for ASN1 tag and length, so we don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st { + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, + const ASN1_PCTX *pctx); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, + int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, + int len, int utype, char *free_cont, + const ASN1_ITEM *it); +typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval, + const ASN1_ITEM *it, int indent, + const ASN1_PCTX *pctx); + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; + ASN1_ex_print_func *asn1_ex_print; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; + ASN1_primitive_print *prim_print; +} ASN1_PRIMITIVE_FUNCS; + +/* + * This is the ASN1_AUX structure: it handles various miscellaneous + * requirements. For example the use of reference counts and an informational + * callback. The "informational callback" is called at various points during + * the ASN1 encoding and decoding. It can be used to provide minor + * customisation of the structures used. This is most useful where the + * supplied routines *almost* do the right thing but need some extra help at + * a few points. If the callback returns zero then it is assumed a fatal + * error has occurred and the main operation should be abandoned. If major + * changes in the default behaviour are required then an external type is + * more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + int ref_lock; /* Lock type to use */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* For print related callbacks exarg points to this structure */ +typedef struct ASN1_PRINT_ARG_st { + BIO *out; + int indent; + const ASN1_PCTX *pctx; +} ASN1_PRINT_ARG; + +/* For streaming related callbacks exarg points to this structure */ +typedef struct ASN1_STREAM_ARG_st { + /* BIO to stream through */ + BIO *out; + /* BIO with filters appended */ + BIO *ndef_bio; + /* Streaming I/O boundary */ + unsigned char **boundary; +} ASN1_STREAM_ARG; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +# define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +# define ASN1_AFLG_ENCODING 2 +/* The Sequence length is invalid */ +# define ASN1_AFLG_BROKEN 4 + +/* operation values for asn1_cb */ + +# define ASN1_OP_NEW_PRE 0 +# define ASN1_OP_NEW_POST 1 +# define ASN1_OP_FREE_PRE 2 +# define ASN1_OP_FREE_POST 3 +# define ASN1_OP_D2I_PRE 4 +# define ASN1_OP_D2I_POST 5 +# define ASN1_OP_I2D_PRE 6 +# define ASN1_OP_I2D_POST 7 +# define ASN1_OP_PRINT_PRE 8 +# define ASN1_OP_PRINT_POST 9 +# define ASN1_OP_STREAM_PRE 10 +# define ASN1_OP_STREAM_POST 11 +# define ASN1_OP_DETACHED_PRE 12 +# define ASN1_OP_DETACHED_POST 13 + +/* Macro to implement a primitive type */ +# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +# define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ + int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ + { \ + return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ + } + +# define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \ + static stname *d2i_##stname(stname **a, \ + const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \ + ASN1_ITEM_rptr(stname)); \ + } \ + static int i2d_##stname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, \ + ASN1_ITEM_rptr(stname)); \ + } + +/* + * This includes evil casts to remove const: they will go away when full ASN1 + * constification is done. + */ +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \ + IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx) \ + { \ + return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \ + ASN1_ITEM_rptr(itname), pctx); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) +DECLARE_ASN1_ITEM(CBIGNUM) +DECLARE_ASN1_ITEM(BIGNUM) +DECLARE_ASN1_ITEM(INT32) +DECLARE_ASN1_ITEM(ZINT32) +DECLARE_ASN1_ITEM(UINT32) +DECLARE_ASN1_ITEM(ZUINT32) +DECLARE_ASN1_ITEM(INT64) +DECLARE_ASN1_ITEM(ZINT64) +DECLARE_ASN1_ITEM(UINT64) +DECLARE_ASN1_ITEM(ZUINT64) + +# if OPENSSL_API_COMPAT < 0x10200000L +/* + * LONG and ZLONG are strongly discouraged for use as stored data, as the + * underlying C type (long) differs in size depending on the architecture. + * They are designed with 32-bit longs in mind. + */ +DECLARE_ASN1_ITEM(LONG) +DECLARE_ASN1_ITEM(ZLONG) +# endif + +DEFINE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/async.h b/thirdparty/user_include/openssl/async.h new file mode 100755 index 0000000000000000000000000000000000000000..7052b89052af2640ecae4255d7c2d4c97c997362 --- /dev/null +++ b/thirdparty/user_include/openssl/async.h @@ -0,0 +1,76 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifndef HEADER_ASYNC_H +# define HEADER_ASYNC_H + +#if defined(_WIN32) +# if defined(BASETYPES) || defined(_WINDEF_H) +/* application has to include to use this */ +#define OSSL_ASYNC_FD HANDLE +#define OSSL_BAD_ASYNC_FD INVALID_HANDLE_VALUE +# endif +#else +#define OSSL_ASYNC_FD int +#define OSSL_BAD_ASYNC_FD -1 +#endif +# include + + +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct async_job_st ASYNC_JOB; +typedef struct async_wait_ctx_st ASYNC_WAIT_CTX; + +#define ASYNC_ERR 0 +#define ASYNC_NO_JOBS 1 +#define ASYNC_PAUSE 2 +#define ASYNC_FINISH 3 + +int ASYNC_init_thread(size_t max_size, size_t init_size); +void ASYNC_cleanup_thread(void); + +#ifdef OSSL_ASYNC_FD +ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void); +void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx); +int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD fd, + void *custom_data, + void (*cleanup)(ASYNC_WAIT_CTX *, const void *, + OSSL_ASYNC_FD, void *)); +int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key, + OSSL_ASYNC_FD *fd, void **custom_data); +int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd, + size_t *numfds); +int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd, + size_t *numaddfds, OSSL_ASYNC_FD *delfd, + size_t *numdelfds); +int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key); +#endif + +int ASYNC_is_capable(void); + +int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret, + int (*func)(void *), void *args, size_t size); +int ASYNC_pause_job(void); + +ASYNC_JOB *ASYNC_get_current_job(void); +ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job); +void ASYNC_block_pause(void); +void ASYNC_unblock_pause(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/asyncerr.h b/thirdparty/user_include/openssl/asyncerr.h new file mode 100755 index 0000000000000000000000000000000000000000..5497ba75279ee5d9dffc3a1f1a02b6c04197516e --- /dev/null +++ b/thirdparty/user_include/openssl/asyncerr.h @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ASYNCERR_H +# define HEADER_ASYNCERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ASYNC_strings(void); + +/* + * ASYNC function codes. + */ +# define ASYNC_F_ASYNC_CTX_NEW 100 +# define ASYNC_F_ASYNC_INIT_THREAD 101 +# define ASYNC_F_ASYNC_JOB_NEW 102 +# define ASYNC_F_ASYNC_PAUSE_JOB 103 +# define ASYNC_F_ASYNC_START_FUNC 104 +# define ASYNC_F_ASYNC_START_JOB 105 +# define ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD 106 + +/* + * ASYNC reason codes. + */ +# define ASYNC_R_FAILED_TO_SET_POOL 101 +# define ASYNC_R_FAILED_TO_SWAP_CONTEXT 102 +# define ASYNC_R_INIT_FAILED 105 +# define ASYNC_R_INVALID_POOL_SIZE 103 + +#endif diff --git a/thirdparty/user_include/openssl/bio.h b/thirdparty/user_include/openssl/bio.h new file mode 100755 index 0000000000000000000000000000000000000000..2888b42da84dfc1bafb3df51bcdb5886fea0914d --- /dev/null +++ b/thirdparty/user_include/openssl/bio.h @@ -0,0 +1,804 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BIO_H +# define HEADER_BIO_H + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# endif +# include + +# include +# include + +# ifndef OPENSSL_NO_SCTP +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* There are the classes of BIOs */ +# define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ +# define BIO_TYPE_FILTER 0x0200 +# define BIO_TYPE_SOURCE_SINK 0x0400 + +/* These are the 'types' of BIOs */ +# define BIO_TYPE_NONE 0 +# define BIO_TYPE_MEM ( 1|BIO_TYPE_SOURCE_SINK) +# define BIO_TYPE_FILE ( 2|BIO_TYPE_SOURCE_SINK) + +# define BIO_TYPE_FD ( 4|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_SOCKET ( 5|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_NULL ( 6|BIO_TYPE_SOURCE_SINK) +# define BIO_TYPE_SSL ( 7|BIO_TYPE_FILTER) +# define BIO_TYPE_MD ( 8|BIO_TYPE_FILTER) +# define BIO_TYPE_BUFFER ( 9|BIO_TYPE_FILTER) +# define BIO_TYPE_CIPHER (10|BIO_TYPE_FILTER) +# define BIO_TYPE_BASE64 (11|BIO_TYPE_FILTER) +# define BIO_TYPE_CONNECT (12|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_ACCEPT (13|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) + +# define BIO_TYPE_NBIO_TEST (16|BIO_TYPE_FILTER)/* server proxy BIO */ +# define BIO_TYPE_NULL_FILTER (17|BIO_TYPE_FILTER) +# define BIO_TYPE_BIO (19|BIO_TYPE_SOURCE_SINK)/* half a BIO pair */ +# define BIO_TYPE_LINEBUFFER (20|BIO_TYPE_FILTER) +# define BIO_TYPE_DGRAM (21|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# define BIO_TYPE_ASN1 (22|BIO_TYPE_FILTER) +# define BIO_TYPE_COMP (23|BIO_TYPE_FILTER) +# ifndef OPENSSL_NO_SCTP +# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR) +# endif + +#define BIO_TYPE_START 128 + +/* + * BIO_FILENAME_READ|BIO_CLOSE to open or close on free. + * BIO_set_fp(in,stdin,BIO_NOCLOSE); + */ +# define BIO_NOCLOSE 0x00 +# define BIO_CLOSE 0x01 + +/* + * These are used in the following macros and are passed to BIO_ctrl() + */ +# define BIO_CTRL_RESET 1/* opt - rewind/zero etc */ +# define BIO_CTRL_EOF 2/* opt - are we at the eof */ +# define BIO_CTRL_INFO 3/* opt - extra tit-bits */ +# define BIO_CTRL_SET 4/* man - set the 'IO' type */ +# define BIO_CTRL_GET 5/* man - get the 'IO' type */ +# define BIO_CTRL_PUSH 6/* opt - internal, used to signify change */ +# define BIO_CTRL_POP 7/* opt - internal, used to signify change */ +# define BIO_CTRL_GET_CLOSE 8/* man - set the 'close' on free */ +# define BIO_CTRL_SET_CLOSE 9/* man - set the 'close' on free */ +# define BIO_CTRL_PENDING 10/* opt - is their more data buffered */ +# define BIO_CTRL_FLUSH 11/* opt - 'flush' buffered output */ +# define BIO_CTRL_DUP 12/* man - extra stuff for 'duped' BIO */ +# define BIO_CTRL_WPENDING 13/* opt - number of bytes still to write */ +# define BIO_CTRL_SET_CALLBACK 14/* opt - set callback function */ +# define BIO_CTRL_GET_CALLBACK 15/* opt - set callback function */ + +# define BIO_CTRL_PEEK 29/* BIO_f_buffer special */ +# define BIO_CTRL_SET_FILENAME 30/* BIO_s_file special */ + +/* dgram BIO stuff */ +# define BIO_CTRL_DGRAM_CONNECT 31/* BIO dgram special */ +# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected + * socket to be passed in */ +# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */ +# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */ + +# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */ + +/* #ifdef IP_MTU_DISCOVER */ +# define BIO_CTRL_DGRAM_MTU_DISCOVER 39/* set DF bit on egress packets */ +/* #endif */ + +# define BIO_CTRL_DGRAM_QUERY_MTU 40/* as kernel for current MTU */ +# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 +# define BIO_CTRL_DGRAM_GET_MTU 41/* get cached value for MTU */ +# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU. + * want to use this if asking + * the kernel fails */ + +# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was + * exceed in the previous write + * operation */ + +# define BIO_CTRL_DGRAM_GET_PEER 46 +# define BIO_CTRL_DGRAM_SET_PEER 44/* Destination for the data */ + +# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout + * to adjust socket timeouts */ +# define BIO_CTRL_DGRAM_SET_DONT_FRAG 48 + +# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD 49 + +/* Deliberately outside of OPENSSL_NO_SCTP - used in bss_dgram.c */ +# define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50 +# ifndef OPENSSL_NO_SCTP +/* SCTP stuff */ +# define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51 +# define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52 +# define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53 +# define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60 +# define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61 +# define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62 +# define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63 +# define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64 +# define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65 +# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70 +# endif + +# define BIO_CTRL_DGRAM_SET_PEEK_MODE 71 + +/* modifiers */ +# define BIO_FP_READ 0x02 +# define BIO_FP_WRITE 0x04 +# define BIO_FP_APPEND 0x08 +# define BIO_FP_TEXT 0x10 + +# define BIO_FLAGS_READ 0x01 +# define BIO_FLAGS_WRITE 0x02 +# define BIO_FLAGS_IO_SPECIAL 0x04 +# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL) +# define BIO_FLAGS_SHOULD_RETRY 0x08 +# ifndef BIO_FLAGS_UPLINK +/* + * "UPLINK" flag denotes file descriptors provided by application. It + * defaults to 0, as most platforms don't require UPLINK interface. + */ +# define BIO_FLAGS_UPLINK 0 +# endif + +# define BIO_FLAGS_BASE64_NO_NL 0x100 + +/* + * This is used with memory BIOs: + * BIO_FLAGS_MEM_RDONLY means we shouldn't free up or change the data in any way; + * BIO_FLAGS_NONCLEAR_RST means we shouldn't clear data on reset. + */ +# define BIO_FLAGS_MEM_RDONLY 0x200 +# define BIO_FLAGS_NONCLEAR_RST 0x400 + +typedef union bio_addr_st BIO_ADDR; +typedef struct bio_addrinfo_st BIO_ADDRINFO; + +int BIO_get_new_index(void); +void BIO_set_flags(BIO *b, int flags); +int BIO_test_flags(const BIO *b, int flags); +void BIO_clear_flags(BIO *b, int flags); + +# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0)) +# define BIO_set_retry_special(b) \ + BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_read(b) \ + BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_write(b) \ + BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY)) + +/* These are normally used internally in BIOs */ +# define BIO_clear_retry_flags(b) \ + BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_get_retry_flags(b) \ + BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) + +/* These should be used by the application to tell why we should retry */ +# define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ) +# define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE) +# define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL) +# define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS) +# define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY) + +/* + * The next three are used in conjunction with the BIO_should_io_special() + * condition. After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int + * *reason); will walk the BIO stack and return the 'reason' for the special + * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return + * the code. + */ +/* + * Returned from the SSL bio when the certificate retrieval code had an error + */ +# define BIO_RR_SSL_X509_LOOKUP 0x01 +/* Returned from the connect BIO when a connect would have blocked */ +# define BIO_RR_CONNECT 0x02 +/* Returned from the accept BIO when an accept would have blocked */ +# define BIO_RR_ACCEPT 0x03 + +/* These are passed by the BIO callback */ +# define BIO_CB_FREE 0x01 +# define BIO_CB_READ 0x02 +# define BIO_CB_WRITE 0x03 +# define BIO_CB_PUTS 0x04 +# define BIO_CB_GETS 0x05 +# define BIO_CB_CTRL 0x06 + +/* + * The callback is called before and after the underling operation, The + * BIO_CB_RETURN flag indicates if it is after the call + */ +# define BIO_CB_RETURN 0x80 +# define BIO_CB_return(a) ((a)|BIO_CB_RETURN) +# define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) +# define BIO_cb_post(a) ((a)&BIO_CB_RETURN) + +typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi, + long argl, long ret); +typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp, + size_t len, int argi, + long argl, int ret, size_t *processed); +BIO_callback_fn BIO_get_callback(const BIO *b); +void BIO_set_callback(BIO *b, BIO_callback_fn callback); + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b); +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback); + +char *BIO_get_callback_arg(const BIO *b); +void BIO_set_callback_arg(BIO *b, char *arg); + +typedef struct bio_method_st BIO_METHOD; + +const char *BIO_method_name(const BIO *b); +int BIO_method_type(const BIO *b); + +typedef int BIO_info_cb(BIO *, int, int); +typedef BIO_info_cb bio_info_cb; /* backward compatibility */ + +DEFINE_STACK_OF(BIO) + +/* Prefix and suffix callback in ASN1 BIO */ +typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen, + void *parg); + +# ifndef OPENSSL_NO_SCTP +/* SCTP parameter structs */ +struct bio_dgram_sctp_sndinfo { + uint16_t snd_sid; + uint16_t snd_flags; + uint32_t snd_ppid; + uint32_t snd_context; +}; + +struct bio_dgram_sctp_rcvinfo { + uint16_t rcv_sid; + uint16_t rcv_ssn; + uint16_t rcv_flags; + uint32_t rcv_ppid; + uint32_t rcv_tsn; + uint32_t rcv_cumtsn; + uint32_t rcv_context; +}; + +struct bio_dgram_sctp_prinfo { + uint16_t pr_policy; + uint32_t pr_value; +}; +# endif + +/* + * #define BIO_CONN_get_param_hostname BIO_ctrl + */ + +# define BIO_C_SET_CONNECT 100 +# define BIO_C_DO_STATE_MACHINE 101 +# define BIO_C_SET_NBIO 102 +/* # define BIO_C_SET_PROXY_PARAM 103 */ +# define BIO_C_SET_FD 104 +# define BIO_C_GET_FD 105 +# define BIO_C_SET_FILE_PTR 106 +# define BIO_C_GET_FILE_PTR 107 +# define BIO_C_SET_FILENAME 108 +# define BIO_C_SET_SSL 109 +# define BIO_C_GET_SSL 110 +# define BIO_C_SET_MD 111 +# define BIO_C_GET_MD 112 +# define BIO_C_GET_CIPHER_STATUS 113 +# define BIO_C_SET_BUF_MEM 114 +# define BIO_C_GET_BUF_MEM_PTR 115 +# define BIO_C_GET_BUFF_NUM_LINES 116 +# define BIO_C_SET_BUFF_SIZE 117 +# define BIO_C_SET_ACCEPT 118 +# define BIO_C_SSL_MODE 119 +# define BIO_C_GET_MD_CTX 120 +/* # define BIO_C_GET_PROXY_PARAM 121 */ +# define BIO_C_SET_BUFF_READ_DATA 122/* data to read first */ +# define BIO_C_GET_CONNECT 123 +# define BIO_C_GET_ACCEPT 124 +# define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +# define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +# define BIO_C_FILE_SEEK 128 +# define BIO_C_GET_CIPHER_CTX 129 +# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input + * value */ +# define BIO_C_SET_BIND_MODE 131 +# define BIO_C_GET_BIND_MODE 132 +# define BIO_C_FILE_TELL 133 +# define BIO_C_GET_SOCKS 134 +# define BIO_C_SET_SOCKS 135 + +# define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +# define BIO_C_GET_WRITE_BUF_SIZE 137 +# define BIO_C_MAKE_BIO_PAIR 138 +# define BIO_C_DESTROY_BIO_PAIR 139 +# define BIO_C_GET_WRITE_GUARANTEE 140 +# define BIO_C_GET_READ_REQUEST 141 +# define BIO_C_SHUTDOWN_WR 142 +# define BIO_C_NREAD0 143 +# define BIO_C_NREAD 144 +# define BIO_C_NWRITE0 145 +# define BIO_C_NWRITE 146 +# define BIO_C_RESET_READ_REQUEST 147 +# define BIO_C_SET_MD_CTX 148 + +# define BIO_C_SET_PREFIX 149 +# define BIO_C_GET_PREFIX 150 +# define BIO_C_SET_SUFFIX 151 +# define BIO_C_GET_SUFFIX 152 + +# define BIO_C_SET_EX_ARG 153 +# define BIO_C_GET_EX_ARG 154 + +# define BIO_C_SET_CONNECT_MODE 155 + +# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) +# define BIO_get_app_data(s) BIO_get_ex_data(s,0) + +# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) + +# ifndef OPENSSL_NO_SOCK +/* IP families we support, for BIO_s_connect() and BIO_s_accept() */ +/* Note: the underlying operating system may not support some of them */ +# define BIO_FAMILY_IPV4 4 +# define BIO_FAMILY_IPV6 6 +# define BIO_FAMILY_IPANY 256 + +/* BIO_s_connect() */ +# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0, \ + (char *)(name)) +# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1, \ + (char *)(port)) +# define BIO_set_conn_address(b,addr) BIO_ctrl(b,BIO_C_SET_CONNECT,2, \ + (char *)(addr)) +# define BIO_set_conn_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_CONNECT,3,f) +# define BIO_get_conn_hostname(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)) +# define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)) +# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)) +# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL) +# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL) + +/* BIO_s_accept() */ +# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \ + (char *)(name)) +# define BIO_set_accept_port(b,port) BIO_ctrl(b,BIO_C_SET_ACCEPT,1, \ + (char *)(port)) +# define BIO_get_accept_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)) +# define BIO_get_accept_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,1)) +# define BIO_get_peer_name(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,2)) +# define BIO_get_peer_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,3)) +/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ +# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(n)?(void *)"a":NULL) +# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,3, \ + (char *)(bio)) +# define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f) +# define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL) + +/* Aliases kept for backward compatibility */ +# define BIO_BIND_NORMAL 0 +# define BIO_BIND_REUSEADDR BIO_SOCK_REUSEADDR +# define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR +# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) +# define BIO_get_bind_mode(b) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) + +/* BIO_s_accept() and BIO_s_connect() */ +# define BIO_do_connect(b) BIO_do_handshake(b) +# define BIO_do_accept(b) BIO_do_handshake(b) +# endif /* OPENSSL_NO_SOCK */ + +# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) + +/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */ +# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) +# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)(c)) + +/* BIO_s_file() */ +# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)(fp)) +# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)(fpp)) + +/* BIO_s_fd() and BIO_s_file() */ +# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) +# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) + +/* + * name is cast to lose const, but might be better to route through a + * function so we can do it safely + */ +# ifdef CONST_STRICT +/* + * If you are wondering why this isn't defined, its because CONST_STRICT is + * purely a compile-time kludge to allow const to be checked. + */ +int BIO_read_filename(BIO *b, const char *name); +# else +# define BIO_read_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ,(char *)(name)) +# endif +# define BIO_write_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_WRITE,name) +# define BIO_append_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_APPEND,name) +# define BIO_rw_filename(b,name) (int)BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name) + +/* + * WARNING WARNING, this ups the reference count on the read bio of the SSL + * structure. This is because the ssl read BIO is now pointed to by the + * next_bio field in the bio. So when you free the BIO, make sure you are + * doing a BIO_free_all() to catch the underlying BIO. + */ +# define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)(ssl)) +# define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)(sslp)) +# define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL) +# define BIO_set_ssl_renegotiate_bytes(b,num) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL) +# define BIO_get_num_renegotiates(b) \ + BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL) +# define BIO_set_ssl_renegotiate_timeout(b,seconds) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL) + +/* defined in evp.h */ +/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)(md)) */ + +# define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)(pp)) +# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)(bm)) +# define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0, \ + (char *)(pp)) +# define BIO_set_mem_eof_return(b,v) \ + BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL) + +/* For the BIO_f_buffer() type */ +# define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL) +# define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL) +# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0) +# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1) +# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf) + +/* Don't use the next one unless you know what you are doing :-) */ +# define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret)) + +# define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) +# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL) +# define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL) +# define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) +# define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) +# define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) +/* ...pending macros have inappropriate return type */ +size_t BIO_ctrl_pending(BIO *b); +size_t BIO_ctrl_wpending(BIO *b); +# define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) +# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \ + cbp) +# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb) + +/* For the BIO_f_buffer() type */ +# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) +# define BIO_buffer_peek(b,s,l) BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s)) + +/* For BIO_s_bio() */ +# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) +# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) +# define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) +# define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) +# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL) +/* macros with inappropriate type -- but ...pending macros use int too: */ +# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) +# define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) +size_t BIO_ctrl_get_write_guarantee(BIO *b); +size_t BIO_ctrl_get_read_request(BIO *b); +int BIO_ctrl_reset_read_request(BIO *b); + +/* ctrl macros for dgram */ +# define BIO_ctrl_dgram_connect(b,peer) \ + (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)(peer)) +# define BIO_ctrl_set_connected(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, 0, (char *)(peer)) +# define BIO_dgram_recv_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL) +# define BIO_dgram_send_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL) +# define BIO_dgram_get_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer)) +# define BIO_dgram_set_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer)) +# define BIO_dgram_get_mtu_overhead(b) \ + (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) + +#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef) +int BIO_set_ex_data(BIO *bio, int idx, void *data); +void *BIO_get_ex_data(BIO *bio, int idx); +uint64_t BIO_number_read(BIO *bio); +uint64_t BIO_number_written(BIO *bio); + +/* For BIO_f_asn1() */ +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, + asn1_ps_func *prefix_free); +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, + asn1_ps_func **pprefix_free); +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, + asn1_ps_func *suffix_free); +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, + asn1_ps_func **psuffix_free); + +const BIO_METHOD *BIO_s_file(void); +BIO *BIO_new_file(const char *filename, const char *mode); +# ifndef OPENSSL_NO_STDIO +BIO *BIO_new_fp(FILE *stream, int close_flag); +# endif +BIO *BIO_new(const BIO_METHOD *type); +int BIO_free(BIO *a); +void BIO_set_data(BIO *a, void *ptr); +void *BIO_get_data(BIO *a); +void BIO_set_init(BIO *a, int init); +int BIO_get_init(BIO *a); +void BIO_set_shutdown(BIO *a, int shut); +int BIO_get_shutdown(BIO *a); +void BIO_vfree(BIO *a); +int BIO_up_ref(BIO *a); +int BIO_read(BIO *b, void *data, int dlen); +int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes); +int BIO_gets(BIO *bp, char *buf, int size); +int BIO_write(BIO *b, const void *data, int dlen); +int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written); +int BIO_puts(BIO *bp, const char *buf); +int BIO_indent(BIO *b, int indent, int max); +long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); +void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); +long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); +BIO *BIO_push(BIO *b, BIO *append); +BIO *BIO_pop(BIO *b); +void BIO_free_all(BIO *a); +BIO *BIO_find_type(BIO *b, int bio_type); +BIO *BIO_next(BIO *b); +void BIO_set_next(BIO *b, BIO *next); +BIO *BIO_get_retry_BIO(BIO *bio, int *reason); +int BIO_get_retry_reason(BIO *bio); +void BIO_set_retry_reason(BIO *bio, int reason); +BIO *BIO_dup_chain(BIO *in); + +int BIO_nread0(BIO *bio, char **buf); +int BIO_nread(BIO *bio, char **buf, int num); +int BIO_nwrite0(BIO *bio, char **buf); +int BIO_nwrite(BIO *bio, char **buf, int num); + +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, + long argl, long ret); + +const BIO_METHOD *BIO_s_mem(void); +const BIO_METHOD *BIO_s_secmem(void); +BIO *BIO_new_mem_buf(const void *buf, int len); +# ifndef OPENSSL_NO_SOCK +const BIO_METHOD *BIO_s_socket(void); +const BIO_METHOD *BIO_s_connect(void); +const BIO_METHOD *BIO_s_accept(void); +# endif +const BIO_METHOD *BIO_s_fd(void); +const BIO_METHOD *BIO_s_log(void); +const BIO_METHOD *BIO_s_bio(void); +const BIO_METHOD *BIO_s_null(void); +const BIO_METHOD *BIO_f_null(void); +const BIO_METHOD *BIO_f_buffer(void); +const BIO_METHOD *BIO_f_linebuffer(void); +const BIO_METHOD *BIO_f_nbio_test(void); +# ifndef OPENSSL_NO_DGRAM +const BIO_METHOD *BIO_s_datagram(void); +int BIO_dgram_non_fatal_error(int error); +BIO *BIO_new_dgram(int fd, int close_flag); +# ifndef OPENSSL_NO_SCTP +const BIO_METHOD *BIO_s_datagram_sctp(void); +BIO *BIO_new_dgram_sctp(int fd, int close_flag); +int BIO_dgram_is_sctp(BIO *bio); +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications) (BIO *bio, + void *context, + void *buf), + void *context); +int BIO_dgram_sctp_wait_for_dry(BIO *b); +int BIO_dgram_sctp_msg_waiting(BIO *b); +# endif +# endif + +# ifndef OPENSSL_NO_SOCK +int BIO_sock_should_retry(int i); +int BIO_sock_non_fatal_error(int error); +# endif + +int BIO_fd_should_retry(int i); +int BIO_fd_non_fatal_error(int error); +int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len); +int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len, int indent); +int BIO_dump(BIO *b, const char *bytes, int len); +int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent); +# ifndef OPENSSL_NO_STDIO +int BIO_dump_fp(FILE *fp, const char *s, int len); +int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent); +# endif +int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, + int datalen); + +# ifndef OPENSSL_NO_SOCK +BIO_ADDR *BIO_ADDR_new(void); +int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, + const void *where, size_t wherelen, unsigned short port); +void BIO_ADDR_free(BIO_ADDR *); +void BIO_ADDR_clear(BIO_ADDR *ap); +int BIO_ADDR_family(const BIO_ADDR *ap); +int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l); +unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap); +char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric); +char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric); +char *BIO_ADDR_path_string(const BIO_ADDR *ap); + +const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai); +int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai); +const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai); +void BIO_ADDRINFO_free(BIO_ADDRINFO *bai); + +enum BIO_hostserv_priorities { + BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV +}; +int BIO_parse_hostserv(const char *hostserv, char **host, char **service, + enum BIO_hostserv_priorities hostserv_prio); +enum BIO_lookup_type { + BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER +}; +int BIO_lookup(const char *host, const char *service, + enum BIO_lookup_type lookup_type, + int family, int socktype, BIO_ADDRINFO **res); +int BIO_lookup_ex(const char *host, const char *service, + int lookup_type, int family, int socktype, int protocol, + BIO_ADDRINFO **res); +int BIO_sock_error(int sock); +int BIO_socket_ioctl(int fd, long type, void *arg); +int BIO_socket_nbio(int fd, int mode); +int BIO_sock_init(void); +# if OPENSSL_API_COMPAT < 0x10100000L +# define BIO_sock_cleanup() while(0) continue +# endif +int BIO_set_tcp_ndelay(int sock, int turn_on); + +DEPRECATEDIN_1_1_0(struct hostent *BIO_gethostbyname(const char *name)) +DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr)) +DEPRECATEDIN_1_1_0(int BIO_get_host_ip(const char *str, unsigned char *ip)) +DEPRECATEDIN_1_1_0(int BIO_get_accept_socket(char *host_port, int mode)) +DEPRECATEDIN_1_1_0(int BIO_accept(int sock, char **ip_port)) + +union BIO_sock_info_u { + BIO_ADDR *addr; +}; +enum BIO_sock_info_type { + BIO_SOCK_INFO_ADDRESS +}; +int BIO_sock_info(int sock, + enum BIO_sock_info_type type, union BIO_sock_info_u *info); + +# define BIO_SOCK_REUSEADDR 0x01 +# define BIO_SOCK_V6_ONLY 0x02 +# define BIO_SOCK_KEEPALIVE 0x04 +# define BIO_SOCK_NONBLOCK 0x08 +# define BIO_SOCK_NODELAY 0x10 + +int BIO_socket(int domain, int socktype, int protocol, int options); +int BIO_connect(int sock, const BIO_ADDR *addr, int options); +int BIO_bind(int sock, const BIO_ADDR *addr, int options); +int BIO_listen(int sock, const BIO_ADDR *addr, int options); +int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options); +int BIO_closesocket(int sock); + +BIO *BIO_new_socket(int sock, int close_flag); +BIO *BIO_new_connect(const char *host_port); +BIO *BIO_new_accept(const char *host_port); +# endif /* OPENSSL_NO_SOCK*/ + +BIO *BIO_new_fd(int fd, int close_flag); + +int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, + BIO **bio2, size_t writebuf2); +/* + * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. + * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default + * value. + */ + +void BIO_copy_next_retry(BIO *b); + +/* + * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); + */ + +# define ossl_bio__attr__(x) +# if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__APPLE__) + /* + * Because we support the 'z' modifier, which made its appearance in C99, + * we can't use __attribute__ with pre C99 dialects. + */ +# if __STDC_VERSION__ >= 199901L +# undef ossl_bio__attr__ +# define ossl_bio__attr__ __attribute__ +# if __GNUC__*10 + __GNUC_MINOR__ >= 44 +# define ossl_bio__printf__ __gnu_printf__ +# else +# define ossl_bio__printf__ __printf__ +# endif +# endif +# endif +int BIO_printf(BIO *bio, const char *format, ...) +ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 3))); +int BIO_vprintf(BIO *bio, const char *format, va_list args) +ossl_bio__attr__((__format__(ossl_bio__printf__, 2, 0))); +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 4))); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) +ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0))); +# undef ossl_bio__attr__ +# undef ossl_bio__printf__ + + +BIO_METHOD *BIO_meth_new(int type, const char *name); +void BIO_meth_free(BIO_METHOD *biom); +int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int); +int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t, + size_t *); +int BIO_meth_set_write(BIO_METHOD *biom, + int (*write) (BIO *, const char *, int)); +int BIO_meth_set_write_ex(BIO_METHOD *biom, + int (*bwrite) (BIO *, const char *, size_t, size_t *)); +int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int); +int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *); +int BIO_meth_set_read(BIO_METHOD *biom, + int (*read) (BIO *, char *, int)); +int BIO_meth_set_read_ex(BIO_METHOD *biom, + int (*bread) (BIO *, char *, size_t, size_t *)); +int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *); +int BIO_meth_set_puts(BIO_METHOD *biom, + int (*puts) (BIO *, const char *)); +int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int); +int BIO_meth_set_gets(BIO_METHOD *biom, + int (*gets) (BIO *, char *, int)); +long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *); +int BIO_meth_set_ctrl(BIO_METHOD *biom, + long (*ctrl) (BIO *, int, long, void *)); +int (*BIO_meth_get_create(const BIO_METHOD *bion)) (BIO *); +int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)); +int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *); +int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)); +long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) + (BIO *, int, BIO_info_cb *); +int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, + long (*callback_ctrl) (BIO *, int, + BIO_info_cb *)); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/bioerr.h b/thirdparty/user_include/openssl/bioerr.h new file mode 100755 index 0000000000000000000000000000000000000000..f119a59c36ccb1e892ad84138814f17ae3cf98b1 --- /dev/null +++ b/thirdparty/user_include/openssl/bioerr.h @@ -0,0 +1,120 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BIOERR_H +# define HEADER_BIOERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BIO_strings(void); + +/* + * BIO function codes. + */ +# define BIO_F_ACPT_STATE 100 +# define BIO_F_ADDRINFO_WRAP 148 +# define BIO_F_ADDR_STRINGS 134 +# define BIO_F_BIO_ACCEPT 101 +# define BIO_F_BIO_ACCEPT_EX 137 +# define BIO_F_BIO_ACCEPT_NEW 152 +# define BIO_F_BIO_ADDR_NEW 144 +# define BIO_F_BIO_BIND 147 +# define BIO_F_BIO_CALLBACK_CTRL 131 +# define BIO_F_BIO_CONNECT 138 +# define BIO_F_BIO_CONNECT_NEW 153 +# define BIO_F_BIO_CTRL 103 +# define BIO_F_BIO_GETS 104 +# define BIO_F_BIO_GET_HOST_IP 106 +# define BIO_F_BIO_GET_NEW_INDEX 102 +# define BIO_F_BIO_GET_PORT 107 +# define BIO_F_BIO_LISTEN 139 +# define BIO_F_BIO_LOOKUP 135 +# define BIO_F_BIO_LOOKUP_EX 143 +# define BIO_F_BIO_MAKE_PAIR 121 +# define BIO_F_BIO_METH_NEW 146 +# define BIO_F_BIO_NEW 108 +# define BIO_F_BIO_NEW_DGRAM_SCTP 145 +# define BIO_F_BIO_NEW_FILE 109 +# define BIO_F_BIO_NEW_MEM_BUF 126 +# define BIO_F_BIO_NREAD 123 +# define BIO_F_BIO_NREAD0 124 +# define BIO_F_BIO_NWRITE 125 +# define BIO_F_BIO_NWRITE0 122 +# define BIO_F_BIO_PARSE_HOSTSERV 136 +# define BIO_F_BIO_PUTS 110 +# define BIO_F_BIO_READ 111 +# define BIO_F_BIO_READ_EX 105 +# define BIO_F_BIO_READ_INTERN 120 +# define BIO_F_BIO_SOCKET 140 +# define BIO_F_BIO_SOCKET_NBIO 142 +# define BIO_F_BIO_SOCK_INFO 141 +# define BIO_F_BIO_SOCK_INIT 112 +# define BIO_F_BIO_WRITE 113 +# define BIO_F_BIO_WRITE_EX 119 +# define BIO_F_BIO_WRITE_INTERN 128 +# define BIO_F_BUFFER_CTRL 114 +# define BIO_F_CONN_CTRL 127 +# define BIO_F_CONN_STATE 115 +# define BIO_F_DGRAM_SCTP_NEW 149 +# define BIO_F_DGRAM_SCTP_READ 132 +# define BIO_F_DGRAM_SCTP_WRITE 133 +# define BIO_F_DOAPR_OUTCH 150 +# define BIO_F_FILE_CTRL 116 +# define BIO_F_FILE_READ 130 +# define BIO_F_LINEBUFFER_CTRL 129 +# define BIO_F_LINEBUFFER_NEW 151 +# define BIO_F_MEM_WRITE 117 +# define BIO_F_NBIOF_NEW 154 +# define BIO_F_SLG_WRITE 155 +# define BIO_F_SSL_NEW 118 + +/* + * BIO reason codes. + */ +# define BIO_R_ACCEPT_ERROR 100 +# define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET 141 +# define BIO_R_AMBIGUOUS_HOST_OR_SERVICE 129 +# define BIO_R_BAD_FOPEN_MODE 101 +# define BIO_R_BROKEN_PIPE 124 +# define BIO_R_CONNECT_ERROR 103 +# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107 +# define BIO_R_GETSOCKNAME_ERROR 132 +# define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133 +# define BIO_R_GETTING_SOCKTYPE 134 +# define BIO_R_INVALID_ARGUMENT 125 +# define BIO_R_INVALID_SOCKET 135 +# define BIO_R_IN_USE 123 +# define BIO_R_LENGTH_TOO_LONG 102 +# define BIO_R_LISTEN_V6_ONLY 136 +# define BIO_R_LOOKUP_RETURNED_NOTHING 142 +# define BIO_R_MALFORMED_HOST_OR_SERVICE 130 +# define BIO_R_NBIO_CONNECT_ERROR 110 +# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143 +# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144 +# define BIO_R_NO_PORT_DEFINED 113 +# define BIO_R_NO_SUCH_FILE 128 +# define BIO_R_NULL_PARAMETER 115 +# define BIO_R_UNABLE_TO_BIND_SOCKET 117 +# define BIO_R_UNABLE_TO_CREATE_SOCKET 118 +# define BIO_R_UNABLE_TO_KEEPALIVE 137 +# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 +# define BIO_R_UNABLE_TO_NODELAY 138 +# define BIO_R_UNABLE_TO_REUSEADDR 139 +# define BIO_R_UNAVAILABLE_IP_FAMILY 145 +# define BIO_R_UNINITIALIZED 120 +# define BIO_R_UNKNOWN_INFO_TYPE 140 +# define BIO_R_UNSUPPORTED_IP_FAMILY 146 +# define BIO_R_UNSUPPORTED_METHOD 121 +# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131 +# define BIO_R_WRITE_TO_READ_ONLY_BIO 126 +# define BIO_R_WSASTARTUP 122 + +#endif diff --git a/thirdparty/user_include/openssl/blowfish.h b/thirdparty/user_include/openssl/blowfish.h new file mode 100755 index 0000000000000000000000000000000000000000..cd3e460e98f3e7cd26c2145700da779c84d26278 --- /dev/null +++ b/thirdparty/user_include/openssl/blowfish.h @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BLOWFISH_H +# define HEADER_BLOWFISH_H + +# include + +# ifndef OPENSSL_NO_BF +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define BF_ENCRYPT 1 +# define BF_DECRYPT 0 + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define BF_LONG unsigned int + +# define BF_ROUNDS 16 +# define BF_BLOCK 8 + +typedef struct bf_key_st { + BF_LONG P[BF_ROUNDS + 2]; + BF_LONG S[4 * 256]; +} BF_KEY; + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data, const BF_KEY *key); +void BF_decrypt(BF_LONG *data, const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num); +const char *BF_options(void); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/bn.h b/thirdparty/user_include/openssl/bn.h new file mode 100755 index 0000000000000000000000000000000000000000..8af05d00e59a90cb7c764eeda0b8a269504dd5a1 --- /dev/null +++ b/thirdparty/user_include/openssl/bn.h @@ -0,0 +1,539 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BN_H +# define HEADER_BN_H + +# include +# ifndef OPENSSL_NO_STDIO +# include +# endif +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 64-bit processor with LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT_LONG +# define BN_ULONG unsigned long +# define BN_BYTES 8 +# endif + +/* + * 64-bit processor other than LP64 ABI + */ +# ifdef SIXTY_FOUR_BIT +# define BN_ULONG unsigned long long +# define BN_BYTES 8 +# endif + +# ifdef THIRTY_TWO_BIT +# define BN_ULONG unsigned int +# define BN_BYTES 4 +# endif + +# define BN_BITS2 (BN_BYTES * 8) +# define BN_BITS (BN_BITS2 * 2) +# define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1)) + +# define BN_FLG_MALLOCED 0x01 +# define BN_FLG_STATIC_DATA 0x02 + +/* + * avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ +# define BN_FLG_CONSTTIME 0x04 +# define BN_FLG_SECURE 0x08 + +# if OPENSSL_API_COMPAT < 0x00908000L +/* deprecated name for the flag */ +# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME +# define BN_FLG_FREE 0x8000 /* used for debugging */ +# endif + +void BN_set_flags(BIGNUM *b, int n); +int BN_get_flags(const BIGNUM *b, int n); + +/* Values for |top| in BN_rand() */ +#define BN_RAND_TOP_ANY -1 +#define BN_RAND_TOP_ONE 0 +#define BN_RAND_TOP_TWO 1 + +/* Values for |bottom| in BN_rand() */ +#define BN_RAND_BOTTOM_ANY 0 +#define BN_RAND_BOTTOM_ODD 1 + +/* + * get a clone of a BIGNUM with changed flags, for *temporary* use only (the + * two BIGNUMs cannot be used in parallel!). Also only for *read only* use. The + * value |dest| should be a newly allocated BIGNUM obtained via BN_new() that + * has not been otherwise initialised or used. + */ +void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags); + +/* Wrapper function to make using BN_GENCB easier */ +int BN_GENCB_call(BN_GENCB *cb, int a, int b); + +BN_GENCB *BN_GENCB_new(void); +void BN_GENCB_free(BN_GENCB *cb); + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *), + void *cb_arg); + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *), + void *cb_arg); + +void *BN_GENCB_get_arg(BN_GENCB *cb); + +# define BN_prime_checks 0 /* default: select number of iterations based + * on the size of the number */ + +/* + * BN_prime_checks_for_size() returns the number of Miller-Rabin iterations + * that will be done for checking that a random number is probably prime. The + * error rate for accepting a composite number as prime depends on the size of + * the prime |b|. The error rates used are for calculating an RSA key with 2 primes, + * and so the level is what you would expect for a key of double the size of the + * prime. + * + * This table is generated using the algorithm of FIPS PUB 186-4 + * Digital Signature Standard (DSS), section F.1, page 117. + * (https://dx.doi.org/10.6028/NIST.FIPS.186-4) + * + * The following magma script was used to generate the output: + * securitybits:=125; + * k:=1024; + * for t:=1 to 65 do + * for M:=3 to Floor(2*Sqrt(k-1)-1) do + * S:=0; + * // Sum over m + * for m:=3 to M do + * s:=0; + * // Sum over j + * for j:=2 to m do + * s+:=(RealField(32)!2)^-(j+(k-1)/j); + * end for; + * S+:=2^(m-(m-1)*t)*s; + * end for; + * A:=2^(k-2-M*t); + * B:=8*(Pi(RealField(32))^2-6)/3*2^(k-2)*S; + * pkt:=2.00743*Log(2)*k*2^-k*(A+B); + * seclevel:=Floor(-Log(2,pkt)); + * if seclevel ge securitybits then + * printf "k: %5o, security: %o bits (t: %o, M: %o)\n",k,seclevel,t,M; + * break; + * end if; + * end for; + * if seclevel ge securitybits then break; end if; + * end for; + * + * It can be run online at: + * http://magma.maths.usyd.edu.au/calc + * + * And will output: + * k: 1024, security: 129 bits (t: 6, M: 23) + * + * k is the number of bits of the prime, securitybits is the level we want to + * reach. + * + * prime length | RSA key size | # MR tests | security level + * -------------+--------------|------------+--------------- + * (b) >= 6394 | >= 12788 | 3 | 256 bit + * (b) >= 3747 | >= 7494 | 3 | 192 bit + * (b) >= 1345 | >= 2690 | 4 | 128 bit + * (b) >= 1080 | >= 2160 | 5 | 128 bit + * (b) >= 852 | >= 1704 | 5 | 112 bit + * (b) >= 476 | >= 952 | 5 | 80 bit + * (b) >= 400 | >= 800 | 6 | 80 bit + * (b) >= 347 | >= 694 | 7 | 80 bit + * (b) >= 308 | >= 616 | 8 | 80 bit + * (b) >= 55 | >= 110 | 27 | 64 bit + * (b) >= 6 | >= 12 | 34 | 64 bit + */ + +# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \ + (b) >= 1345 ? 4 : \ + (b) >= 476 ? 5 : \ + (b) >= 400 ? 6 : \ + (b) >= 347 ? 7 : \ + (b) >= 308 ? 8 : \ + (b) >= 55 ? 27 : \ + /* b >= 6 */ 34) + +# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) + +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_zero(const BIGNUM *a); +int BN_is_one(const BIGNUM *a); +int BN_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_odd(const BIGNUM *a); + +# define BN_one(a) (BN_set_word((a),1)) + +void BN_zero_ex(BIGNUM *a); + +# if OPENSSL_API_COMPAT >= 0x00908000L +# define BN_zero(a) BN_zero_ex(a) +# else +# define BN_zero(a) (BN_set_word((a),0)) +# endif + +const BIGNUM *BN_value_one(void); +char *BN_options(void); +BN_CTX *BN_CTX_new(void); +BN_CTX *BN_CTX_secure_new(void); +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_priv_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG l); +int BN_security_bits(int L, int N); +BIGNUM *BN_new(void); +BIGNUM *BN_secure_new(void); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +void BN_swap(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +/** BN_set_negative sets sign of a BIGNUM + * \param b pointer to the BIGNUM object + * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise + */ +void BN_set_negative(BIGNUM *b, int n); +/** BN_is_negative returns 1 if the BIGNUM is negative + * \param b pointer to the BIGNUM object + * \return 1 if a < 0 and 0 otherwise + */ +int BN_is_negative(const BIGNUM *b); + +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx); +# define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx)) +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(const BIGNUM *a); + +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(const BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +int BN_mask_bits(BIGNUM *a, int n); +# ifndef OPENSSL_NO_STDIO +int BN_print_fp(FILE *fp, const BIGNUM *a); +# endif +int BN_print(BIO *bio, const BIGNUM *a); +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char *BN_bn2hex(const BIGNUM *a); +char *BN_bn2dec(const BIGNUM *a); +int BN_hex2bn(BIGNUM **a, const char *str); +int BN_dec2bn(BIGNUM **a, const char *str); +int BN_asc2bn(BIGNUM **a, const char *str); +int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns + * -2 for + * error */ +BIGNUM *BN_mod_inverse(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + +/* Deprecated versions */ +DEPRECATEDIN_0_9_8(BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, + const BIGNUM *rem, + void (*callback) (int, int, + void *), + void *cb_arg)) +DEPRECATEDIN_0_9_8(int + BN_is_prime(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), + BN_CTX *ctx, void *cb_arg)) +DEPRECATEDIN_0_9_8(int + BN_is_prime_fasttest(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), + BN_CTX *ctx, void *cb_arg, + int do_trial_division)) + +/* Newer versions */ +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, + const BIGNUM *rem, BN_GENCB *cb); +int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb); +int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); + +int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx); + +int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, + const BIGNUM *Xp, const BIGNUM *Xp1, + const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb); +int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1, + BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e, + BN_CTX *ctx, BN_GENCB *cb); + +BN_MONT_CTX *BN_MONT_CTX_new(void); +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from); +BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock, + const BIGNUM *mod, BN_CTX *ctx); + +/* BN_BLINDING flags */ +# define BN_BLINDING_NO_UPDATE 0x00000001 +# define BN_BLINDING_NO_RECREATE 0x00000002 + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *); +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, + BN_CTX *); + +int BN_BLINDING_is_current_thread(BN_BLINDING *b); +void BN_BLINDING_set_current_thread(BN_BLINDING *b); +int BN_BLINDING_lock(BN_BLINDING *b); +int BN_BLINDING_unlock(BN_BLINDING *b); + +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); +void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx); + +DEPRECATEDIN_0_9_8(void BN_set_params(int mul, int high, int low, int mont)) +DEPRECATEDIN_0_9_8(int BN_get_params(int which)) /* 0, mul, 1 high, 2 low, 3 + * mont */ + +BN_RECP_CTX *BN_RECP_CTX_new(void); +void BN_RECP_CTX_free(BN_RECP_CTX *recp); +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx); +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx); +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +# ifndef OPENSSL_NO_EC2M + +/* + * Functions for arithmetic over binary polynomials represented by BIGNUMs. + * The BIGNUM::neg property of BIGNUMs representing binary polynomials is + * ignored. Note that input arguments are not const so that their bit arrays + * can be expanded to the appropriate size if needed. + */ + +/* + * r = a + b + */ +int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +# define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b) +/* + * r=a mod p + */ +int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +# define BN_GF2m_cmp(a, b) BN_ucmp((a), (b)) +/*- + * Some functions allow for representation of the irreducible polynomials + * as an unsigned int[], say p. The irreducible f(t) is then of the form: + * t^p[0] + t^p[1] + ... + t^p[k] + * where m = p[0] > p[1] > ... > p[k] = 0. + */ +/* r = a mod p */ +int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], + BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const int p[], + BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max); +int BN_GF2m_arr2poly(const int p[], BIGNUM *a); + +# endif + +/* + * faster mod functions for the 'NIST primes' 0 <= a < p^2 + */ +int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +const BIGNUM *BN_get0_nist_prime_192(void); +const BIGNUM *BN_get0_nist_prime_224(void); +const BIGNUM *BN_get0_nist_prime_256(void); +const BIGNUM *BN_get0_nist_prime_384(void); +const BIGNUM *BN_get0_nist_prime_521(void); + +int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a, + const BIGNUM *field, BN_CTX *ctx); + +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, + const BIGNUM *priv, const unsigned char *message, + size_t message_len, BN_CTX *ctx); + +/* Primes from RFC 2409 */ +BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn); +BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn); + +/* Primes from RFC 3526 */ +BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define get_rfc2409_prime_768 BN_get_rfc2409_prime_768 +# define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024 +# define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536 +# define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048 +# define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072 +# define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096 +# define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144 +# define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192 +# endif + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/bnerr.h b/thirdparty/user_include/openssl/bnerr.h new file mode 100755 index 0000000000000000000000000000000000000000..8a022cc0698deb7d959696f1333fbbf8318d1e44 --- /dev/null +++ b/thirdparty/user_include/openssl/bnerr.h @@ -0,0 +1,96 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BNERR_H +# define HEADER_BNERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BN_strings(void); + +/* + * BN function codes. + */ +# define BN_F_BNRAND 127 +# define BN_F_BNRAND_RANGE 138 +# define BN_F_BN_BLINDING_CONVERT_EX 100 +# define BN_F_BN_BLINDING_CREATE_PARAM 128 +# define BN_F_BN_BLINDING_INVERT_EX 101 +# define BN_F_BN_BLINDING_NEW 102 +# define BN_F_BN_BLINDING_UPDATE 103 +# define BN_F_BN_BN2DEC 104 +# define BN_F_BN_BN2HEX 105 +# define BN_F_BN_COMPUTE_WNAF 142 +# define BN_F_BN_CTX_GET 116 +# define BN_F_BN_CTX_NEW 106 +# define BN_F_BN_CTX_START 129 +# define BN_F_BN_DIV 107 +# define BN_F_BN_DIV_RECP 130 +# define BN_F_BN_EXP 123 +# define BN_F_BN_EXPAND_INTERNAL 120 +# define BN_F_BN_GENCB_NEW 143 +# define BN_F_BN_GENERATE_DSA_NONCE 140 +# define BN_F_BN_GENERATE_PRIME_EX 141 +# define BN_F_BN_GF2M_MOD 131 +# define BN_F_BN_GF2M_MOD_EXP 132 +# define BN_F_BN_GF2M_MOD_MUL 133 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 +# define BN_F_BN_GF2M_MOD_SQR 136 +# define BN_F_BN_GF2M_MOD_SQRT 137 +# define BN_F_BN_LSHIFT 145 +# define BN_F_BN_MOD_EXP2_MONT 118 +# define BN_F_BN_MOD_EXP_MONT 109 +# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 +# define BN_F_BN_MOD_EXP_MONT_WORD 117 +# define BN_F_BN_MOD_EXP_RECP 125 +# define BN_F_BN_MOD_EXP_SIMPLE 126 +# define BN_F_BN_MOD_INVERSE 110 +# define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 +# define BN_F_BN_MOD_LSHIFT_QUICK 119 +# define BN_F_BN_MOD_SQRT 121 +# define BN_F_BN_MONT_CTX_NEW 149 +# define BN_F_BN_MPI2BN 112 +# define BN_F_BN_NEW 113 +# define BN_F_BN_POOL_GET 147 +# define BN_F_BN_RAND 114 +# define BN_F_BN_RAND_RANGE 122 +# define BN_F_BN_RECP_CTX_NEW 150 +# define BN_F_BN_RSHIFT 146 +# define BN_F_BN_SET_WORDS 144 +# define BN_F_BN_STACK_PUSH 148 +# define BN_F_BN_USUB 115 + +/* + * BN reason codes. + */ +# define BN_R_ARG2_LT_ARG3 100 +# define BN_R_BAD_RECIPROCAL 101 +# define BN_R_BIGNUM_TOO_LONG 114 +# define BN_R_BITS_TOO_SMALL 118 +# define BN_R_CALLED_WITH_EVEN_MODULUS 102 +# define BN_R_DIV_BY_ZERO 103 +# define BN_R_ENCODING_ERROR 104 +# define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +# define BN_R_INPUT_NOT_REDUCED 110 +# define BN_R_INVALID_LENGTH 106 +# define BN_R_INVALID_RANGE 115 +# define BN_R_INVALID_SHIFT 119 +# define BN_R_NOT_A_SQUARE 111 +# define BN_R_NOT_INITIALIZED 107 +# define BN_R_NO_INVERSE 108 +# define BN_R_NO_SOLUTION 116 +# define BN_R_PRIVATE_KEY_TOO_LARGE 117 +# define BN_R_P_IS_NOT_PRIME 112 +# define BN_R_TOO_MANY_ITERATIONS 113 +# define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +#endif diff --git a/thirdparty/user_include/openssl/buffer.h b/thirdparty/user_include/openssl/buffer.h new file mode 100755 index 0000000000000000000000000000000000000000..d2765766b7cebb1164cbc9d4873d20cf38154eb7 --- /dev/null +++ b/thirdparty/user_include/openssl/buffer.h @@ -0,0 +1,58 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BUFFER_H +# define HEADER_BUFFER_H + +# include +# ifndef HEADER_CRYPTO_H +# include +# endif +# include + + +#ifdef __cplusplus +extern "C" { +#endif + +# include +# include + +/* + * These names are outdated as of OpenSSL 1.1; a future release + * will move them to be deprecated. + */ +# define BUF_strdup(s) OPENSSL_strdup(s) +# define BUF_strndup(s, size) OPENSSL_strndup(s, size) +# define BUF_memdup(data, size) OPENSSL_memdup(data, size) +# define BUF_strlcpy(dst, src, size) OPENSSL_strlcpy(dst, src, size) +# define BUF_strlcat(dst, src, size) OPENSSL_strlcat(dst, src, size) +# define BUF_strnlen(str, maxlen) OPENSSL_strnlen(str, maxlen) + +struct buf_mem_st { + size_t length; /* current number of bytes */ + char *data; + size_t max; /* size of buffer */ + unsigned long flags; +}; + +# define BUF_MEM_FLAG_SECURE 0x01 + +BUF_MEM *BUF_MEM_new(void); +BUF_MEM *BUF_MEM_new_ex(unsigned long flags); +void BUF_MEM_free(BUF_MEM *a); +size_t BUF_MEM_grow(BUF_MEM *str, size_t len); +size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len); +void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/buffererr.h b/thirdparty/user_include/openssl/buffererr.h new file mode 100755 index 0000000000000000000000000000000000000000..3aee1323238363c4ceede5bb1de69e58575010c6 --- /dev/null +++ b/thirdparty/user_include/openssl/buffererr.h @@ -0,0 +1,30 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_BUFERR_H +# define HEADER_BUFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_BUF_strings(void); + +/* + * BUF function codes. + */ +# define BUF_F_BUF_MEM_GROW 100 +# define BUF_F_BUF_MEM_GROW_CLEAN 105 +# define BUF_F_BUF_MEM_NEW 101 + +/* + * BUF reason codes. + */ + +#endif diff --git a/thirdparty/user_include/openssl/camellia.h b/thirdparty/user_include/openssl/camellia.h new file mode 100755 index 0000000000000000000000000000000000000000..151f3c134917153a7d89927ff0e6a64c7236b363 --- /dev/null +++ b/thirdparty/user_include/openssl/camellia.h @@ -0,0 +1,83 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CAMELLIA_H +# define HEADER_CAMELLIA_H + +# include + +# ifndef OPENSSL_NO_CAMELLIA +# include +#ifdef __cplusplus +extern "C" { +#endif + +# define CAMELLIA_ENCRYPT 1 +# define CAMELLIA_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ + +/* This should be a hidden type, but EVP requires that the size be known */ + +# define CAMELLIA_BLOCK_SIZE 16 +# define CAMELLIA_TABLE_BYTE_LEN 272 +# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match + * with WORD */ + +struct camellia_key_st { + union { + double d; /* ensures 64-bit align */ + KEY_TABLE_TYPE rd_key; + } u; + int grand_rounds; +}; +typedef struct camellia_key_st CAMELLIA_KEY; + +int Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key); + +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void Camellia_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); + +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc); +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc); +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num); +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/cast.h b/thirdparty/user_include/openssl/cast.h new file mode 100755 index 0000000000000000000000000000000000000000..2cc89ae0133cd23e5554ea4d91f832f96e2c3a06 --- /dev/null +++ b/thirdparty/user_include/openssl/cast.h @@ -0,0 +1,53 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CAST_H +# define HEADER_CAST_H + +# include + +# ifndef OPENSSL_NO_CAST +# ifdef __cplusplus +extern "C" { +# endif + +# define CAST_ENCRYPT 1 +# define CAST_DECRYPT 0 + +# define CAST_LONG unsigned int + +# define CAST_BLOCK 8 +# define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ +} CAST_KEY; + +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAST_KEY *key, int enc); +void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *ks, unsigned char *iv, + int enc); +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/cmac.h b/thirdparty/user_include/openssl/cmac.h new file mode 100755 index 0000000000000000000000000000000000000000..3535a9abf7519f3f5962c65c9b488c2482c33031 --- /dev/null +++ b/thirdparty/user_include/openssl/cmac.h @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMAC_H +# define HEADER_CMAC_H + +# ifndef OPENSSL_NO_CMAC + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +/* Opaque */ +typedef struct CMAC_CTX_st CMAC_CTX; + +CMAC_CTX *CMAC_CTX_new(void); +void CMAC_CTX_cleanup(CMAC_CTX *ctx); +void CMAC_CTX_free(CMAC_CTX *ctx); +EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx); +int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in); + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl); +int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen); +int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen); +int CMAC_resume(CMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +# endif +#endif diff --git a/thirdparty/user_include/openssl/cms.h b/thirdparty/user_include/openssl/cms.h new file mode 100755 index 0000000000000000000000000000000000000000..ddf37e56f8d41fecfcd6e98e0f393ec2a5f4c4d0 --- /dev/null +++ b/thirdparty/user_include/openssl/cms.h @@ -0,0 +1,342 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMS_H +# define HEADER_CMS_H + +# include + +# ifndef OPENSSL_NO_CMS +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct CMS_ContentInfo_st CMS_ContentInfo; +typedef struct CMS_SignerInfo_st CMS_SignerInfo; +typedef struct CMS_CertificateChoices CMS_CertificateChoices; +typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; +typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest; +typedef struct CMS_Receipt_st CMS_Receipt; +typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey; +typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute; + +DEFINE_STACK_OF(CMS_SignerInfo) +DEFINE_STACK_OF(CMS_RecipientEncryptedKey) +DEFINE_STACK_OF(CMS_RecipientInfo) +DEFINE_STACK_OF(CMS_RevocationInfoChoice) +DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) +DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest) +DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo) + +# define CMS_SIGNERINFO_ISSUER_SERIAL 0 +# define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +# define CMS_RECIPINFO_NONE -1 +# define CMS_RECIPINFO_TRANS 0 +# define CMS_RECIPINFO_AGREE 1 +# define CMS_RECIPINFO_KEK 2 +# define CMS_RECIPINFO_PASS 3 +# define CMS_RECIPINFO_OTHER 4 + +/* S/MIME related flags */ + +# define CMS_TEXT 0x1 +# define CMS_NOCERTS 0x2 +# define CMS_NO_CONTENT_VERIFY 0x4 +# define CMS_NO_ATTR_VERIFY 0x8 +# define CMS_NOSIGS \ + (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY) +# define CMS_NOINTERN 0x10 +# define CMS_NO_SIGNER_CERT_VERIFY 0x20 +# define CMS_NOVERIFY 0x20 +# define CMS_DETACHED 0x40 +# define CMS_BINARY 0x80 +# define CMS_NOATTR 0x100 +# define CMS_NOSMIMECAP 0x200 +# define CMS_NOOLDMIMETYPE 0x400 +# define CMS_CRLFEOL 0x800 +# define CMS_STREAM 0x1000 +# define CMS_NOCRL 0x2000 +# define CMS_PARTIAL 0x4000 +# define CMS_REUSE_DIGEST 0x8000 +# define CMS_USE_KEYID 0x10000 +# define CMS_DEBUG_DECRYPT 0x20000 +# define CMS_KEY_PARAM 0x40000 +# define CMS_ASCIICRLF 0x80000 + +const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms); + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +int CMS_is_detached(CMS_ContentInfo *cms); +int CMS_set_detached(CMS_ContentInfo *cms, int detached); + +# ifdef HEADER_PEM_H +DECLARE_PEM_rw_const(CMS, CMS_ContentInfo) +# endif +int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms); +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms); +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms); + +BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms); +int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags); +int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, + int flags); +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont); +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags); + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, + unsigned int flags); + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, + unsigned int flags); + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, unsigned int flags); + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags); + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags); + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, + size_t keylen, unsigned int flags); + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags); + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags); + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, unsigned int flags); + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags); + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + const unsigned char *id, size_t idlen); +int CMS_decrypt_set1_password(CMS_ContentInfo *cms, + unsigned char *pass, ossl_ssize_t passlen); + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri); +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType); + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype); + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen); + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen); + +int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, + unsigned char *pass, + ossl_ssize_t passlen); + +CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, + int iter, int wrap_nid, + int pbe_nid, + unsigned char *pass, + ossl_ssize_t passlen, + const EVP_CIPHER *kekciph); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); +int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid); +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms); + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms); +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert); +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert); +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms); + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms); +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl); +int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl); +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms); + +int CMS_SignedData_init(CMS_ContentInfo *cms); +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags); +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si); +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si); +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert); +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + unsigned int flags); +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, + X509 **signer, X509_ALGOR **pdig, + X509_ALGOR **psig); +ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si); +int CMS_SignerInfo_sign(CMS_SignerInfo *si); +int CMS_SignerInfo_verify(CMS_SignerInfo *si); +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain); + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs); +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize); +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap); + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si); +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid, + int lastpos, int type); + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si); +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +# ifdef HEADER_X509V3_H + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr); +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) + *receiptList, STACK_OF(GENERAL_NAMES) + *receiptsTo); +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr); +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto); +# endif +int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pukm); +STACK_OF(CMS_RecipientEncryptedKey) +*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri); + +int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, + X509_ALGOR **pubalg, + ASN1_BIT_STRING **pubkey, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert); + +int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, + ASN1_OCTET_STRING **keyid, + ASN1_GENERALIZEDTIME **tm, + CMS_OtherKeyAttribute **other, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert); +int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk); +EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri); +int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, + CMS_RecipientEncryptedKey *rek); + +int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, + ASN1_OCTET_STRING *ukm, int keylen); + +/* Backward compatibility for spelling errors. */ +# define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM +# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \ + CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/cmserr.h b/thirdparty/user_include/openssl/cmserr.h new file mode 100755 index 0000000000000000000000000000000000000000..3f8ae26da80192892801144dbcad1228c5a5a90d --- /dev/null +++ b/thirdparty/user_include/openssl/cmserr.h @@ -0,0 +1,196 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CMSERR_H +# define HEADER_CMSERR_H + +# include + +# ifndef OPENSSL_NO_CMS + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CMS_strings(void); + +/* + * CMS function codes. + */ +# define CMS_F_CHECK_CONTENT 99 +# define CMS_F_CMS_ADD0_CERT 164 +# define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 +# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165 +# define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 +# define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 +# define CMS_F_CMS_ADD1_SIGNER 102 +# define CMS_F_CMS_ADD1_SIGNINGTIME 103 +# define CMS_F_CMS_COMPRESS 104 +# define CMS_F_CMS_COMPRESSEDDATA_CREATE 105 +# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106 +# define CMS_F_CMS_COPY_CONTENT 107 +# define CMS_F_CMS_COPY_MESSAGEDIGEST 108 +# define CMS_F_CMS_DATA 109 +# define CMS_F_CMS_DATAFINAL 110 +# define CMS_F_CMS_DATAINIT 111 +# define CMS_F_CMS_DECRYPT 112 +# define CMS_F_CMS_DECRYPT_SET1_KEY 113 +# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166 +# define CMS_F_CMS_DECRYPT_SET1_PKEY 114 +# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 +# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 +# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +# define CMS_F_CMS_DIGEST_VERIFY 118 +# define CMS_F_CMS_ENCODE_RECEIPT 161 +# define CMS_F_CMS_ENCRYPT 119 +# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT 179 +# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 +# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 +# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 +# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 +# define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 +# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 +# define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +# define CMS_F_CMS_ENV_ASN1_CTRL 171 +# define CMS_F_CMS_FINAL 127 +# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 +# define CMS_F_CMS_GET0_CONTENT 129 +# define CMS_F_CMS_GET0_ECONTENT_TYPE 130 +# define CMS_F_CMS_GET0_ENVELOPED 131 +# define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 +# define CMS_F_CMS_GET0_SIGNED 133 +# define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 +# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 +# define CMS_F_CMS_RECEIPT_VERIFY 160 +# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 +# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143 +# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167 +# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +# define CMS_F_CMS_SD_ASN1_CTRL 170 +# define CMS_F_CMS_SET1_IAS 176 +# define CMS_F_CMS_SET1_KEYID 177 +# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 +# define CMS_F_CMS_SET_DETACHED 147 +# define CMS_F_CMS_SIGN 148 +# define CMS_F_CMS_SIGNED_DATA_INIT 149 +# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150 +# define CMS_F_CMS_SIGNERINFO_SIGN 151 +# define CMS_F_CMS_SIGNERINFO_VERIFY 152 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +# define CMS_F_CMS_SIGN_RECEIPT 163 +# define CMS_F_CMS_STREAM 155 +# define CMS_F_CMS_UNCOMPRESS 156 +# define CMS_F_CMS_VERIFY 157 +# define CMS_F_KEK_UNWRAP_KEY 180 + +/* + * CMS reason codes. + */ +# define CMS_R_ADD_SIGNER_ERROR 99 +# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175 +# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160 +# define CMS_R_CERTIFICATE_VERIFY_ERROR 100 +# define CMS_R_CIPHER_INITIALISATION_ERROR 101 +# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102 +# define CMS_R_CMS_DATAFINAL_ERROR 103 +# define CMS_R_CMS_LIB 104 +# define CMS_R_CONTENTIDENTIFIER_MISMATCH 170 +# define CMS_R_CONTENT_NOT_FOUND 105 +# define CMS_R_CONTENT_TYPE_MISMATCH 171 +# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106 +# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107 +# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108 +# define CMS_R_CONTENT_VERIFY_ERROR 109 +# define CMS_R_CTRL_ERROR 110 +# define CMS_R_CTRL_FAILURE 111 +# define CMS_R_DECRYPT_ERROR 112 +# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113 +# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114 +# define CMS_R_ERROR_SETTING_KEY 115 +# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116 +# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117 +# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176 +# define CMS_R_INVALID_KEY_LENGTH 118 +# define CMS_R_MD_BIO_INIT_ERROR 119 +# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120 +# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121 +# define CMS_R_MSGSIGDIGEST_ERROR 172 +# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162 +# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163 +# define CMS_R_NEED_ONE_SIGNER 164 +# define CMS_R_NOT_A_SIGNED_RECEIPT 165 +# define CMS_R_NOT_ENCRYPTED_DATA 122 +# define CMS_R_NOT_KEK 123 +# define CMS_R_NOT_KEY_AGREEMENT 181 +# define CMS_R_NOT_KEY_TRANSPORT 124 +# define CMS_R_NOT_PWRI 177 +# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125 +# define CMS_R_NO_CIPHER 126 +# define CMS_R_NO_CONTENT 127 +# define CMS_R_NO_CONTENT_TYPE 173 +# define CMS_R_NO_DEFAULT_DIGEST 128 +# define CMS_R_NO_DIGEST_SET 129 +# define CMS_R_NO_KEY 130 +# define CMS_R_NO_KEY_OR_CERT 174 +# define CMS_R_NO_MATCHING_DIGEST 131 +# define CMS_R_NO_MATCHING_RECIPIENT 132 +# define CMS_R_NO_MATCHING_SIGNATURE 166 +# define CMS_R_NO_MSGSIGDIGEST 167 +# define CMS_R_NO_PASSWORD 178 +# define CMS_R_NO_PRIVATE_KEY 133 +# define CMS_R_NO_PUBLIC_KEY 134 +# define CMS_R_NO_RECEIPT_REQUEST 168 +# define CMS_R_NO_SIGNERS 135 +# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136 +# define CMS_R_RECEIPT_DECODE_ERROR 169 +# define CMS_R_RECIPIENT_ERROR 137 +# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138 +# define CMS_R_SIGNFINAL_ERROR 139 +# define CMS_R_SMIME_TEXT_ERROR 140 +# define CMS_R_STORE_INIT_ERROR 141 +# define CMS_R_TYPE_NOT_COMPRESSED_DATA 142 +# define CMS_R_TYPE_NOT_DATA 143 +# define CMS_R_TYPE_NOT_DIGESTED_DATA 144 +# define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145 +# define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 +# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147 +# define CMS_R_UNKNOWN_CIPHER 148 +# define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149 +# define CMS_R_UNKNOWN_ID 150 +# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151 +# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152 +# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 +# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179 +# define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE 155 +# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154 +# define CMS_R_UNSUPPORTED_TYPE 156 +# define CMS_R_UNWRAP_ERROR 157 +# define CMS_R_UNWRAP_FAILURE 180 +# define CMS_R_VERIFICATION_FAILURE 158 +# define CMS_R_WRAP_ERROR 159 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/comp.h b/thirdparty/user_include/openssl/comp.h new file mode 100755 index 0000000000000000000000000000000000000000..d814d3cf2518c79741b3cf5ab46a0fe977e976c2 --- /dev/null +++ b/thirdparty/user_include/openssl/comp.h @@ -0,0 +1,53 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_COMP_H +# define HEADER_COMP_H + +# include + +# ifndef OPENSSL_NO_COMP +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + + + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth); +const COMP_METHOD *COMP_CTX_get_method(const COMP_CTX *ctx); +int COMP_CTX_get_type(const COMP_CTX* comp); +int COMP_get_type(const COMP_METHOD *meth); +const char *COMP_get_name(const COMP_METHOD *meth); +void COMP_CTX_free(COMP_CTX *ctx); + +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); + +COMP_METHOD *COMP_zlib(void); + +#if OPENSSL_API_COMPAT < 0x10100000L +#define COMP_zlib_cleanup() while(0) continue +#endif + +# ifdef HEADER_BIO_H +# ifdef ZLIB +const BIO_METHOD *BIO_f_zlib(void); +# endif +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/comperr.h b/thirdparty/user_include/openssl/comperr.h new file mode 100755 index 0000000000000000000000000000000000000000..edea63a6809321f2b388c859cd35b2a2e1a308c7 --- /dev/null +++ b/thirdparty/user_include/openssl/comperr.h @@ -0,0 +1,40 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_COMPERR_H +# define HEADER_COMPERR_H + +# include + +# ifndef OPENSSL_NO_COMP + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_COMP_strings(void); + +/* + * COMP function codes. + */ +# define COMP_F_BIO_ZLIB_FLUSH 99 +# define COMP_F_BIO_ZLIB_NEW 100 +# define COMP_F_BIO_ZLIB_READ 101 +# define COMP_F_BIO_ZLIB_WRITE 102 +# define COMP_F_COMP_CTX_NEW 103 + +/* + * COMP reason codes. + */ +# define COMP_R_ZLIB_DEFLATE_ERROR 99 +# define COMP_R_ZLIB_INFLATE_ERROR 100 +# define COMP_R_ZLIB_NOT_SUPPORTED 101 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/conf.h b/thirdparty/user_include/openssl/conf.h new file mode 100755 index 0000000000000000000000000000000000000000..7336cd2f1d1a22888a120910f384f893c1f61680 --- /dev/null +++ b/thirdparty/user_include/openssl/conf.h @@ -0,0 +1,168 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONF_H +# define HEADER_CONF_H + +# include +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *section; + char *name; + char *value; +} CONF_VALUE; + +DEFINE_STACK_OF(CONF_VALUE) +DEFINE_LHASH_OF(CONF_VALUE); + +struct conf_st; +struct conf_method_st; +typedef struct conf_method_st CONF_METHOD; + +struct conf_method_st { + const char *name; + CONF *(*create) (CONF_METHOD *meth); + int (*init) (CONF *conf); + int (*destroy) (CONF *conf); + int (*destroy_data) (CONF *conf); + int (*load_bio) (CONF *conf, BIO *bp, long *eline); + int (*dump) (const CONF *conf, BIO *bp); + int (*is_number) (const CONF *conf, char c); + int (*to_int) (const CONF *conf, char c); + int (*load) (CONF *conf, const char *name, long *eline); +}; + +/* Module definitions */ + +typedef struct conf_imodule_st CONF_IMODULE; +typedef struct conf_module_st CONF_MODULE; + +DEFINE_STACK_OF(CONF_MODULE) +DEFINE_STACK_OF(CONF_IMODULE) + +/* DSO module function typedefs */ +typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf); +typedef void conf_finish_func (CONF_IMODULE *md); + +# define CONF_MFLAGS_IGNORE_ERRORS 0x1 +# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2 +# define CONF_MFLAGS_SILENT 0x4 +# define CONF_MFLAGS_NO_DSO 0x8 +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# define CONF_MFLAGS_DEFAULT_SECTION 0x20 + +int CONF_set_default_method(CONF_METHOD *meth); +void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash); +LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, + long *eline); +# ifndef OPENSSL_NO_STDIO +LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, + long *eline); +# endif +LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, + long *eline); +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, + const char *section); +char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +void CONF_free(LHASH_OF(CONF_VALUE) *conf); +#ifndef OPENSSL_NO_STDIO +int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out); +#endif +int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out); + +DEPRECATEDIN_1_1_0(void OPENSSL_config(const char *config_name)) + +#if OPENSSL_API_COMPAT < 0x10100000L +# define OPENSSL_no_config() \ + OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) +#endif + +/* + * New conf code. The semantics are different from the functions above. If + * that wasn't the case, the above functions would have been replaced + */ + +struct conf_st { + CONF_METHOD *meth; + void *meth_data; + LHASH_OF(CONF_VALUE) *data; +}; + +CONF *NCONF_new(CONF_METHOD *meth); +CONF_METHOD *NCONF_default(void); +CONF_METHOD *NCONF_WIN32(void); +void NCONF_free(CONF *conf); +void NCONF_free_data(CONF *conf); + +int NCONF_load(CONF *conf, const char *file, long *eline); +# ifndef OPENSSL_NO_STDIO +int NCONF_load_fp(CONF *conf, FILE *fp, long *eline); +# endif +int NCONF_load_bio(CONF *conf, BIO *bp, long *eline); +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, + const char *section); +char *NCONF_get_string(const CONF *conf, const char *group, const char *name); +int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, + long *result); +#ifndef OPENSSL_NO_STDIO +int NCONF_dump_fp(const CONF *conf, FILE *out); +#endif +int NCONF_dump_bio(const CONF *conf, BIO *out); + +#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r) + +/* Module functions */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void CONF_modules_unload(int all); +void CONF_modules_finish(void); +#if OPENSSL_API_COMPAT < 0x10100000L +# define CONF_modules_free() while(0) continue +#endif +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc); + +const char *CONF_imodule_get_name(const CONF_IMODULE *md); +const char *CONF_imodule_get_value(const CONF_IMODULE *md); +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md); +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data); +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md); +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md); +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags); +void *CONF_module_get_usr_data(CONF_MODULE *pmod); +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data); + +char *CONF_get1_default_config_file(void); + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb) (const char *elem, int len, void *usr), + void *arg); + +void OPENSSL_load_builtin_modules(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/conf_api.h b/thirdparty/user_include/openssl/conf_api.h new file mode 100755 index 0000000000000000000000000000000000000000..a0275ad79bc4f0fe00675e71ab9fd68e9bfe46a9 --- /dev/null +++ b/thirdparty/user_include/openssl/conf_api.h @@ -0,0 +1,40 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONF_API_H +# define HEADER_CONF_API_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section); + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name); +long _CONF_get_number(const CONF *conf, const char *section, + const char *name); + +int _CONF_new_data(CONF *conf); +void _CONF_free_data(CONF *conf); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/conferr.h b/thirdparty/user_include/openssl/conferr.h new file mode 100755 index 0000000000000000000000000000000000000000..d1c92f45d82dbbacc8d0041464fccedd4975c4e3 --- /dev/null +++ b/thirdparty/user_include/openssl/conferr.h @@ -0,0 +1,72 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CONFERR_H +# define HEADER_CONFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CONF_strings(void); + +/* + * CONF function codes. + */ +# define CONF_F_CONF_DUMP_FP 104 +# define CONF_F_CONF_LOAD 100 +# define CONF_F_CONF_LOAD_FP 103 +# define CONF_F_CONF_PARSE_LIST 119 +# define CONF_F_DEF_LOAD 120 +# define CONF_F_DEF_LOAD_BIO 121 +# define CONF_F_GET_NEXT_FILE 107 +# define CONF_F_MODULE_ADD 122 +# define CONF_F_MODULE_INIT 115 +# define CONF_F_MODULE_LOAD_DSO 117 +# define CONF_F_MODULE_RUN 118 +# define CONF_F_NCONF_DUMP_BIO 105 +# define CONF_F_NCONF_DUMP_FP 106 +# define CONF_F_NCONF_GET_NUMBER_E 112 +# define CONF_F_NCONF_GET_SECTION 108 +# define CONF_F_NCONF_GET_STRING 109 +# define CONF_F_NCONF_LOAD 113 +# define CONF_F_NCONF_LOAD_BIO 110 +# define CONF_F_NCONF_LOAD_FP 114 +# define CONF_F_NCONF_NEW 111 +# define CONF_F_PROCESS_INCLUDE 116 +# define CONF_F_SSL_MODULE_INIT 123 +# define CONF_F_STR_COPY 101 + +/* + * CONF reason codes. + */ +# define CONF_R_ERROR_LOADING_DSO 110 +# define CONF_R_LIST_CANNOT_BE_NULL 115 +# define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 +# define CONF_R_MISSING_EQUAL_SIGN 101 +# define CONF_R_MISSING_INIT_FUNCTION 112 +# define CONF_R_MODULE_INITIALIZATION_ERROR 109 +# define CONF_R_NO_CLOSE_BRACE 102 +# define CONF_R_NO_CONF 105 +# define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106 +# define CONF_R_NO_SECTION 107 +# define CONF_R_NO_SUCH_FILE 114 +# define CONF_R_NO_VALUE 108 +# define CONF_R_NUMBER_TOO_LARGE 121 +# define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111 +# define CONF_R_SSL_COMMAND_SECTION_EMPTY 117 +# define CONF_R_SSL_COMMAND_SECTION_NOT_FOUND 118 +# define CONF_R_SSL_SECTION_EMPTY 119 +# define CONF_R_SSL_SECTION_NOT_FOUND 120 +# define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103 +# define CONF_R_UNKNOWN_MODULE_NAME 113 +# define CONF_R_VARIABLE_EXPANSION_TOO_LONG 116 +# define CONF_R_VARIABLE_HAS_NO_VALUE 104 + +#endif diff --git a/thirdparty/user_include/openssl/crypto.h b/thirdparty/user_include/openssl/crypto.h new file mode 100755 index 0000000000000000000000000000000000000000..7d0b526236f8e579429614a9ac5076eca6f53556 --- /dev/null +++ b/thirdparty/user_include/openssl/crypto.h @@ -0,0 +1,445 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CRYPTO_H +# define HEADER_CRYPTO_H + +# include +# include + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# endif + +# include +# include +# include +# include +# include + +# ifdef CHARSET_EBCDIC +# include +# endif + +/* + * Resolve problems on some operating systems with symbol names that clash + * one way or another + */ +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSLeay OpenSSL_version_num +# define SSLeay_version OpenSSL_version +# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +# define SSLEAY_VERSION OPENSSL_VERSION +# define SSLEAY_CFLAGS OPENSSL_CFLAGS +# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON +# define SSLEAY_PLATFORM OPENSSL_PLATFORM +# define SSLEAY_DIR OPENSSL_DIR + +/* + * Old type for allocating dynamic locks. No longer used. Use the new thread + * API instead. + */ +typedef struct { + int dummy; +} CRYPTO_dynlock; + +# endif /* OPENSSL_API_COMPAT */ + +typedef void CRYPTO_RWLOCK; + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void); +int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock); +int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock); +int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock); +void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); + +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); + +/* + * The following can be used to detect memory leaks in the library. If + * used, it turns on malloc checking + */ +# define CRYPTO_MEM_CHECK_OFF 0x0 /* Control only */ +# define CRYPTO_MEM_CHECK_ON 0x1 /* Control and mode bit */ +# define CRYPTO_MEM_CHECK_ENABLE 0x2 /* Control and mode bit */ +# define CRYPTO_MEM_CHECK_DISABLE 0x3 /* Control only */ + +struct crypto_ex_data_st { + STACK_OF(void) *sk; +}; +DEFINE_STACK_OF(void) + +/* + * Per class, we have a STACK of function pointers. + */ +# define CRYPTO_EX_INDEX_SSL 0 +# define CRYPTO_EX_INDEX_SSL_CTX 1 +# define CRYPTO_EX_INDEX_SSL_SESSION 2 +# define CRYPTO_EX_INDEX_X509 3 +# define CRYPTO_EX_INDEX_X509_STORE 4 +# define CRYPTO_EX_INDEX_X509_STORE_CTX 5 +# define CRYPTO_EX_INDEX_DH 6 +# define CRYPTO_EX_INDEX_DSA 7 +# define CRYPTO_EX_INDEX_EC_KEY 8 +# define CRYPTO_EX_INDEX_RSA 9 +# define CRYPTO_EX_INDEX_ENGINE 10 +# define CRYPTO_EX_INDEX_UI 11 +# define CRYPTO_EX_INDEX_BIO 12 +# define CRYPTO_EX_INDEX_APP 13 +# define CRYPTO_EX_INDEX_UI_METHOD 14 +# define CRYPTO_EX_INDEX_DRBG 15 +# define CRYPTO_EX_INDEX__COUNT 16 + +/* No longer needed, so this is a no-op */ +#define OPENSSL_malloc_init() while(0) continue + +int CRYPTO_mem_ctrl(int mode); + +# define OPENSSL_malloc(num) \ + CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_zalloc(num) \ + CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_realloc(addr, num) \ + CRYPTO_realloc(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_clear_realloc(addr, old_num, num) \ + CRYPTO_clear_realloc(addr, old_num, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_clear_free(addr, num) \ + CRYPTO_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_free(addr) \ + CRYPTO_free(addr, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_memdup(str, s) \ + CRYPTO_memdup((str), s, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_strdup(str) \ + CRYPTO_strdup(str, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_strndup(str, n) \ + CRYPTO_strndup(str, n, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_malloc(num) \ + CRYPTO_secure_malloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_zalloc(num) \ + CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_free(addr) \ + CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_clear_free(addr, num) \ + CRYPTO_secure_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_secure_actual_size(ptr) \ + CRYPTO_secure_actual_size(ptr) + +size_t OPENSSL_strlcpy(char *dst, const char *src, size_t siz); +size_t OPENSSL_strlcat(char *dst, const char *src, size_t siz); +size_t OPENSSL_strnlen(const char *str, size_t maxlen); +char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len); +unsigned char *OPENSSL_hexstr2buf(const char *str, long *len); +int OPENSSL_hexchar2int(unsigned char c); + +# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type)) + +unsigned long OpenSSL_version_num(void); +const char *OpenSSL_version(int type); +# define OPENSSL_VERSION 0 +# define OPENSSL_CFLAGS 1 +# define OPENSSL_BUILT_ON 2 +# define OPENSSL_PLATFORM 3 +# define OPENSSL_DIR 4 +# define OPENSSL_ENGINES_DIR 5 + +int OPENSSL_issetugid(void); + +typedef void CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp); +__owur int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +/* No longer use an index. */ +int CRYPTO_free_ex_index(int class_index, int idx); + +/* + * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a + * given class (invokes whatever per-class callbacks are applicable) + */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + const CRYPTO_EX_DATA *from); + +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); + +/* + * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular + * index (relative to the class type involved) + */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx); + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * This function cleans up all "ex_data" state. It mustn't be called under + * potential race-conditions. + */ +# define CRYPTO_cleanup_all_ex_data() while(0) continue + +/* + * The old locking functions have been removed completely without compatibility + * macros. This is because the old functions either could not properly report + * errors, or the returned error values were not clearly documented. + * Replacing the locking functions with no-ops would cause race condition + * issues in the affected applications. It is far better for them to fail at + * compile time. + * On the other hand, the locking callbacks are no longer used. Consequently, + * the callback management functions can be safely replaced with no-op macros. + */ +# define CRYPTO_num_locks() (1) +# define CRYPTO_set_locking_callback(func) +# define CRYPTO_get_locking_callback() (NULL) +# define CRYPTO_set_add_lock_callback(func) +# define CRYPTO_get_add_lock_callback() (NULL) + +/* + * These defines where used in combination with the old locking callbacks, + * they are not called anymore, but old code that's not called might still + * use them. + */ +# define CRYPTO_LOCK 1 +# define CRYPTO_UNLOCK 2 +# define CRYPTO_READ 4 +# define CRYPTO_WRITE 8 + +/* This structure is no longer used */ +typedef struct crypto_threadid_st { + int dummy; +} CRYPTO_THREADID; +/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */ +# define CRYPTO_THREADID_set_numeric(id, val) +# define CRYPTO_THREADID_set_pointer(id, ptr) +# define CRYPTO_THREADID_set_callback(threadid_func) (0) +# define CRYPTO_THREADID_get_callback() (NULL) +# define CRYPTO_THREADID_current(id) +# define CRYPTO_THREADID_cmp(a, b) (-1) +# define CRYPTO_THREADID_cpy(dest, src) +# define CRYPTO_THREADID_hash(id) (0UL) + +# if OPENSSL_API_COMPAT < 0x10000000L +# define CRYPTO_set_id_callback(func) +# define CRYPTO_get_id_callback() (NULL) +# define CRYPTO_thread_id() (0UL) +# endif /* OPENSSL_API_COMPAT < 0x10000000L */ + +# define CRYPTO_set_dynlock_create_callback(dyn_create_function) +# define CRYPTO_set_dynlock_lock_callback(dyn_lock_function) +# define CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function) +# define CRYPTO_get_dynlock_create_callback() (NULL) +# define CRYPTO_get_dynlock_lock_callback() (NULL) +# define CRYPTO_get_dynlock_destroy_callback() (NULL) +# endif /* OPENSSL_API_COMPAT < 0x10100000L */ + +int CRYPTO_set_mem_functions( + void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, int), + void (*f) (void *, const char *, int)); +int CRYPTO_set_mem_debug(int flag); +void CRYPTO_get_mem_functions( + void *(**m) (size_t, const char *, int), + void *(**r) (void *, size_t, const char *, int), + void (**f) (void *, const char *, int)); + +void *CRYPTO_malloc(size_t num, const char *file, int line); +void *CRYPTO_zalloc(size_t num, const char *file, int line); +void *CRYPTO_memdup(const void *str, size_t siz, const char *file, int line); +char *CRYPTO_strdup(const char *str, const char *file, int line); +char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line); +void CRYPTO_free(void *ptr, const char *file, int line); +void CRYPTO_clear_free(void *ptr, size_t num, const char *file, int line); +void *CRYPTO_realloc(void *addr, size_t num, const char *file, int line); +void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num, + const char *file, int line); + +int CRYPTO_secure_malloc_init(size_t sz, int minsize); +int CRYPTO_secure_malloc_done(void); +void *CRYPTO_secure_malloc(size_t num, const char *file, int line); +void *CRYPTO_secure_zalloc(size_t num, const char *file, int line); +void CRYPTO_secure_free(void *ptr, const char *file, int line); +void CRYPTO_secure_clear_free(void *ptr, size_t num, + const char *file, int line); +int CRYPTO_secure_allocated(const void *ptr); +int CRYPTO_secure_malloc_initialized(void); +size_t CRYPTO_secure_actual_size(void *ptr); +size_t CRYPTO_secure_used(void); + +void OPENSSL_cleanse(void *ptr, size_t len); + +# ifndef OPENSSL_NO_CRYPTO_MDEBUG +# define OPENSSL_mem_debug_push(info) \ + CRYPTO_mem_debug_push(info, OPENSSL_FILE, OPENSSL_LINE) +# define OPENSSL_mem_debug_pop() \ + CRYPTO_mem_debug_pop() +int CRYPTO_mem_debug_push(const char *info, const char *file, int line); +int CRYPTO_mem_debug_pop(void); +void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount); + +/*- + * Debugging functions (enabled by CRYPTO_set_mem_debug(1)) + * The flag argument has the following significance: + * 0: called before the actual memory allocation has taken place + * 1: called after the actual memory allocation has taken place + */ +void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag, + const char *file, int line); +void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag, + const char *file, int line); +void CRYPTO_mem_debug_free(void *addr, int flag, + const char *file, int line); + +int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u), + void *u); +# ifndef OPENSSL_NO_STDIO +int CRYPTO_mem_leaks_fp(FILE *); +# endif +int CRYPTO_mem_leaks(BIO *bio); +# endif + +/* die if we have to */ +ossl_noreturn void OPENSSL_die(const char *assertion, const char *file, int line); +# if OPENSSL_API_COMPAT < 0x10100000L +# define OpenSSLDie(f,l,a) OPENSSL_die((a),(f),(l)) +# endif +# define OPENSSL_assert(e) \ + (void)((e) ? 0 : (OPENSSL_die("assertion failed: " #e, OPENSSL_FILE, OPENSSL_LINE), 1)) + +int OPENSSL_isservice(void); + +int FIPS_mode(void); +int FIPS_mode_set(int r); + +void OPENSSL_init(void); +# ifdef OPENSSL_SYS_UNIX +void OPENSSL_fork_prepare(void); +void OPENSSL_fork_parent(void); +void OPENSSL_fork_child(void); +# endif + +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); +int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); +int OPENSSL_gmtime_diff(int *pday, int *psec, + const struct tm *from, const struct tm *to); + +/* + * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. + * It takes an amount of time dependent on |len|, but independent of the + * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements + * into a defined order as the return value when a != b is undefined, other + * than to be non-zero. + */ +int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); + +/* Standard initialisation options */ +# define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0x00000001L +# define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L +# define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L +# define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L +# define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0x00000010L +# define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0x00000020L +# define OPENSSL_INIT_LOAD_CONFIG 0x00000040L +# define OPENSSL_INIT_NO_LOAD_CONFIG 0x00000080L +# define OPENSSL_INIT_ASYNC 0x00000100L +# define OPENSSL_INIT_ENGINE_RDRAND 0x00000200L +# define OPENSSL_INIT_ENGINE_DYNAMIC 0x00000400L +# define OPENSSL_INIT_ENGINE_OPENSSL 0x00000800L +# define OPENSSL_INIT_ENGINE_CRYPTODEV 0x00001000L +# define OPENSSL_INIT_ENGINE_CAPI 0x00002000L +# define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L +# define OPENSSL_INIT_ENGINE_AFALG 0x00008000L +/* OPENSSL_INIT_ZLIB 0x00010000L */ +# define OPENSSL_INIT_ATFORK 0x00020000L +/* OPENSSL_INIT_BASE_ONLY 0x00040000L */ +# define OPENSSL_INIT_NO_ATEXIT 0x00080000L +/* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */ +/* Max OPENSSL_INIT flag value is 0x80000000 */ + +/* openssl and dasync not counted as builtin */ +# define OPENSSL_INIT_ENGINE_ALL_BUILTIN \ + (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \ + | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \ + OPENSSL_INIT_ENGINE_PADLOCK) + + +/* Library initialisation functions */ +void OPENSSL_cleanup(void); +int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); +int OPENSSL_atexit(void (*handler)(void)); +void OPENSSL_thread_stop(void); + +/* Low-level control of initialization */ +OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void); +# ifndef OPENSSL_NO_STDIO +int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, + const char *config_filename); +void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, + unsigned long flags); +int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, + const char *config_appname); +# endif +void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings); + +# if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) +# if defined(_WIN32) +# if defined(BASETYPES) || defined(_WINDEF_H) +/* application has to include in order to use this */ +typedef DWORD CRYPTO_THREAD_LOCAL; +typedef DWORD CRYPTO_THREAD_ID; + +typedef LONG CRYPTO_ONCE; +# define CRYPTO_ONCE_STATIC_INIT 0 +# endif +# else +# include +typedef pthread_once_t CRYPTO_ONCE; +typedef pthread_key_t CRYPTO_THREAD_LOCAL; +typedef pthread_t CRYPTO_THREAD_ID; + +# define CRYPTO_ONCE_STATIC_INIT PTHREAD_ONCE_INIT +# endif +# endif + +# if !defined(CRYPTO_ONCE_STATIC_INIT) +typedef unsigned int CRYPTO_ONCE; +typedef unsigned int CRYPTO_THREAD_LOCAL; +typedef unsigned int CRYPTO_THREAD_ID; +# define CRYPTO_ONCE_STATIC_INIT 0 +# endif + +int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)); + +int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)); +void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key); +int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val); +int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key); + +CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void); +int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/cryptoerr.h b/thirdparty/user_include/openssl/cryptoerr.h new file mode 100755 index 0000000000000000000000000000000000000000..10723d0454b3c558f3f8a4f10fc50d6ea67eae9f --- /dev/null +++ b/thirdparty/user_include/openssl/cryptoerr.h @@ -0,0 +1,56 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CRYPTOERR_H +# define HEADER_CRYPTOERR_H + +# ifdef __cplusplus +extern "C" +# endif + +# include + +int ERR_load_CRYPTO_strings(void); + +/* + * CRYPTO function codes. + */ +# define CRYPTO_F_CMAC_CTX_NEW 120 +# define CRYPTO_F_CRYPTO_DUP_EX_DATA 110 +# define CRYPTO_F_CRYPTO_FREE_EX_DATA 111 +# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +# define CRYPTO_F_CRYPTO_MEMDUP 115 +# define CRYPTO_F_CRYPTO_NEW_EX_DATA 112 +# define CRYPTO_F_CRYPTO_OCB128_COPY_CTX 121 +# define CRYPTO_F_CRYPTO_OCB128_INIT 122 +# define CRYPTO_F_CRYPTO_SET_EX_DATA 102 +# define CRYPTO_F_FIPS_MODE_SET 109 +# define CRYPTO_F_GET_AND_LOCK 113 +# define CRYPTO_F_OPENSSL_ATEXIT 114 +# define CRYPTO_F_OPENSSL_BUF2HEXSTR 117 +# define CRYPTO_F_OPENSSL_FOPEN 119 +# define CRYPTO_F_OPENSSL_HEXSTR2BUF 118 +# define CRYPTO_F_OPENSSL_INIT_CRYPTO 116 +# define CRYPTO_F_OPENSSL_LH_NEW 126 +# define CRYPTO_F_OPENSSL_SK_DEEP_COPY 127 +# define CRYPTO_F_OPENSSL_SK_DUP 128 +# define CRYPTO_F_PKEY_HMAC_INIT 123 +# define CRYPTO_F_PKEY_POLY1305_INIT 124 +# define CRYPTO_F_PKEY_SIPHASH_INIT 125 +# define CRYPTO_F_SK_RESERVE 129 + +/* + * CRYPTO reason codes. + */ +# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 +# define CRYPTO_R_ILLEGAL_HEX_DIGIT 102 +# define CRYPTO_R_ODD_NUMBER_OF_DIGITS 103 + +#endif diff --git a/thirdparty/user_include/openssl/ct.h b/thirdparty/user_include/openssl/ct.h new file mode 100755 index 0000000000000000000000000000000000000000..d4262fa0480476a95bad4bf043e21a0d18c98bde --- /dev/null +++ b/thirdparty/user_include/openssl/ct.h @@ -0,0 +1,476 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CT_H +# define HEADER_CT_H + +# include + +# ifndef OPENSSL_NO_CT +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + + +/* Minimum RSA key size, from RFC6962 */ +# define SCT_MIN_RSA_BITS 2048 + +/* All hashes are SHA256 in v1 of Certificate Transparency */ +# define CT_V1_HASHLEN SHA256_DIGEST_LENGTH + +typedef enum { + CT_LOG_ENTRY_TYPE_NOT_SET = -1, + CT_LOG_ENTRY_TYPE_X509 = 0, + CT_LOG_ENTRY_TYPE_PRECERT = 1 +} ct_log_entry_type_t; + +typedef enum { + SCT_VERSION_NOT_SET = -1, + SCT_VERSION_V1 = 0 +} sct_version_t; + +typedef enum { + SCT_SOURCE_UNKNOWN, + SCT_SOURCE_TLS_EXTENSION, + SCT_SOURCE_X509V3_EXTENSION, + SCT_SOURCE_OCSP_STAPLED_RESPONSE +} sct_source_t; + +typedef enum { + SCT_VALIDATION_STATUS_NOT_SET, + SCT_VALIDATION_STATUS_UNKNOWN_LOG, + SCT_VALIDATION_STATUS_VALID, + SCT_VALIDATION_STATUS_INVALID, + SCT_VALIDATION_STATUS_UNVERIFIED, + SCT_VALIDATION_STATUS_UNKNOWN_VERSION +} sct_validation_status_t; + +DEFINE_STACK_OF(SCT) +DEFINE_STACK_OF(CTLOG) + +/****************************************** + * CT policy evaluation context functions * + ******************************************/ + +/* + * Creates a new, empty policy evaluation context. + * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished + * with the CT_POLICY_EVAL_CTX. + */ +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void); + +/* Deletes a policy evaluation context and anything it owns. */ +void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx); + +/* Gets the peer certificate that the SCTs are for */ +X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the certificate associated with the received SCTs. + * Increments the reference count of cert. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert); + +/* Gets the issuer of the aforementioned certificate */ +X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the issuer of the certificate associated with the received SCTs. + * Increments the reference count of issuer. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer); + +/* Gets the CT logs that are trusted sources of SCTs */ +const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx); + +/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */ +void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store); + +/* + * Gets the time, in milliseconds since the Unix epoch, that will be used as the + * current time when checking whether an SCT was issued in the future. + * Such SCTs will fail validation, as required by RFC6962. + */ +uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch. + * If an SCT's timestamp is after this time, it will be interpreted as having + * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs + * whose timestamp is in the future", so an SCT will not validate in this case. + */ +void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms); + +/***************** + * SCT functions * + *****************/ + +/* + * Creates a new, blank SCT. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new(void); + +/* + * Creates a new SCT from some base64-encoded strings. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new_from_base64(unsigned char version, + const char *logid_base64, + ct_log_entry_type_t entry_type, + uint64_t timestamp, + const char *extensions_base64, + const char *signature_base64); + +/* + * Frees the SCT and the underlying data structures. + */ +void SCT_free(SCT *sct); + +/* + * Free a stack of SCTs, and the underlying SCTs themselves. + * Intended to be compatible with X509V3_EXT_FREE. + */ +void SCT_LIST_free(STACK_OF(SCT) *a); + +/* + * Returns the version of the SCT. + */ +sct_version_t SCT_get_version(const SCT *sct); + +/* + * Set the version of an SCT. + * Returns 1 on success, 0 if the version is unrecognized. + */ +__owur int SCT_set_version(SCT *sct, sct_version_t version); + +/* + * Returns the log entry type of the SCT. + */ +ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct); + +/* + * Set the log entry type of an SCT. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type); + +/* + * Gets the ID of the log that an SCT came from. + * Ownership of the log ID remains with the SCT. + * Returns the length of the log ID. + */ +size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id); + +/* + * Set the log ID of an SCT to point directly to the *log_id specified. + * The SCT takes ownership of the specified pointer. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len); + +/* + * Set the log ID of an SCT. + * This makes a copy of the log_id. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, + size_t log_id_len); + +/* + * Returns the timestamp for the SCT (epoch time in milliseconds). + */ +uint64_t SCT_get_timestamp(const SCT *sct); + +/* + * Set the timestamp of an SCT (epoch time in milliseconds). + */ +void SCT_set_timestamp(SCT *sct, uint64_t timestamp); + +/* + * Return the NID for the signature used by the SCT. + * For CT v1, this will be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset). + */ +int SCT_get_signature_nid(const SCT *sct); + +/* + * Set the signature type of an SCT + * For CT v1, this should be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_signature_nid(SCT *sct, int nid); + +/* + * Set *ext to point to the extension data for the SCT. ext must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext); + +/* + * Set the extensions of an SCT to point directly to the *ext specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len); + +/* + * Set the extensions of an SCT. + * This takes a copy of the ext. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_extensions(SCT *sct, const unsigned char *ext, + size_t ext_len); + +/* + * Set *sig to point to the signature for the SCT. sig must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_signature(const SCT *sct, unsigned char **sig); + +/* + * Set the signature of an SCT to point directly to the *sig specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len); + +/* + * Set the signature of an SCT to be a copy of the *sig specified. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set1_signature(SCT *sct, const unsigned char *sig, + size_t sig_len); + +/* + * The origin of this SCT, e.g. TLS extension, OCSP response, etc. + */ +sct_source_t SCT_get_source(const SCT *sct); + +/* + * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc. + * Returns 1 on success, 0 otherwise. + */ +__owur int SCT_set_source(SCT *sct, sct_source_t source); + +/* + * Returns a text string describing the validation status of |sct|. + */ +const char *SCT_validation_status_string(const SCT *sct); + +/* + * Pretty-prints an |sct| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came + * from, so that the log name can be printed. + */ +void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs); + +/* + * Pretty-prints an |sct_list| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * SCTs will be delimited by |separator|. + * If |logs| is not NULL, it will be used to lookup the CT log that each SCT + * came from, so that the log names can be printed. + */ +void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *logs); + +/* + * Gets the last result of validating this SCT. + * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET. + */ +sct_validation_status_t SCT_get_validation_status(const SCT *sct); + +/* + * Validates the given SCT with the provided context. + * Sets the "validation_status" field of the SCT. + * Returns 1 if the SCT is valid and the signature verifies. + * Returns 0 if the SCT is invalid or could not be verified. + * Returns -1 if an error occurs. + */ +__owur int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx); + +/* + * Validates the given list of SCTs with the provided context. + * Sets the "validation_status" field of each SCT. + * Returns 1 if there are no invalid SCTs and all signatures verify. + * Returns 0 if at least one SCT is invalid or could not be verified. + * Returns a negative integer if an error occurs. + */ +__owur int SCT_LIST_validate(const STACK_OF(SCT) *scts, + CT_POLICY_EVAL_CTX *ctx); + + +/********************************* + * SCT parsing and serialisation * + *********************************/ + +/* + * Serialize (to TLS format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just return the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +__owur int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Convert TLS format SCT list to a stack of SCTs. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + size_t len); + +/* + * Serialize (to DER format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just returns the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +__owur int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Parses an SCT list in DER format and returns it. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + long len); + +/* + * Serialize (to TLS format) an |sct| and write it to |out|. + * If |out| is null, no SCT will be output but the length will still be returned. + * If |out| points to a null pointer, a string will be allocated to hold the + * TLS-format SCT. It is the responsibility of the caller to free it. + * If |out| points to an allocated string, the TLS-format SCT will be written + * to it. + * The length of the SCT in TLS format will be returned. + */ +__owur int i2o_SCT(const SCT *sct, unsigned char **out); + +/* + * Parses an SCT in TLS format and returns it. + * If |psct| is not null, it will end up pointing to the parsed SCT. If it + * already points to a non-null pointer, the pointer will be free'd. + * |in| should be a pointer to a string containing the TLS-format SCT. + * |in| will be advanced to the end of the SCT if parsing succeeds. + * |len| should be the length of the SCT in |in|. + * Returns NULL if an error occurs. + * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len' + * fields will be populated (with |in| and |len| respectively). + */ +SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len); + +/******************** + * CT log functions * + ********************/ + +/* + * Creates a new CT log instance with the given |public_key| and |name|. + * Takes ownership of |public_key| but copies |name|. + * Returns NULL if malloc fails or if |public_key| cannot be converted to DER. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name); + +/* + * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER + * in |pkey_base64|. The |name| is a string to help users identify this log. + * Returns 1 on success, 0 on failure. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +int CTLOG_new_from_base64(CTLOG ** ct_log, + const char *pkey_base64, const char *name); + +/* + * Deletes a CT log instance and its fields. + */ +void CTLOG_free(CTLOG *log); + +/* Gets the name of the CT log */ +const char *CTLOG_get0_name(const CTLOG *log); +/* Gets the ID of the CT log */ +void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, + size_t *log_id_len); +/* Gets the public key of the CT log */ +EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log); + +/************************** + * CT log store functions * + **************************/ + +/* + * Creates a new CT log store. + * Should be deleted by the caller using CTLOG_STORE_free when no longer needed. + */ +CTLOG_STORE *CTLOG_STORE_new(void); + +/* + * Deletes a CT log store and all of the CT log instances held within. + */ +void CTLOG_STORE_free(CTLOG_STORE *store); + +/* + * Finds a CT log in the store based on its log ID. + * Returns the CT log, or NULL if no match is found. + */ +const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, + const uint8_t *log_id, + size_t log_id_len); + +/* + * Loads a CT log list into a |store| from a |file|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +__owur int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file); + +/* + * Loads the default CT log list into a |store|. + * See internal/cryptlib.h for the environment variable and file path that are + * consulted to find the default file. + * Returns 1 if loading is successful, or 0 otherwise. + */ +__owur int CTLOG_STORE_load_default_file(CTLOG_STORE *store); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/cterr.h b/thirdparty/user_include/openssl/cterr.h new file mode 100755 index 0000000000000000000000000000000000000000..764e1a22046240c36273aa2ce0a2f4d59601f1b2 --- /dev/null +++ b/thirdparty/user_include/openssl/cterr.h @@ -0,0 +1,76 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_CTERR_H +# define HEADER_CTERR_H + +# include + +# ifndef OPENSSL_NO_CT + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_CT_strings(void); + +/* + * CT function codes. + */ +# define CT_F_CTLOG_NEW 117 +# define CT_F_CTLOG_NEW_FROM_BASE64 118 +# define CT_F_CTLOG_NEW_FROM_CONF 119 +# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122 +# define CT_F_CTLOG_STORE_LOAD_FILE 123 +# define CT_F_CTLOG_STORE_LOAD_LOG 130 +# define CT_F_CTLOG_STORE_NEW 131 +# define CT_F_CT_BASE64_DECODE 124 +# define CT_F_CT_POLICY_EVAL_CTX_NEW 133 +# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125 +# define CT_F_I2O_SCT 107 +# define CT_F_I2O_SCT_LIST 108 +# define CT_F_I2O_SCT_SIGNATURE 109 +# define CT_F_O2I_SCT 110 +# define CT_F_O2I_SCT_LIST 111 +# define CT_F_O2I_SCT_SIGNATURE 112 +# define CT_F_SCT_CTX_NEW 126 +# define CT_F_SCT_CTX_VERIFY 128 +# define CT_F_SCT_NEW 100 +# define CT_F_SCT_NEW_FROM_BASE64 127 +# define CT_F_SCT_SET0_LOG_ID 101 +# define CT_F_SCT_SET1_EXTENSIONS 114 +# define CT_F_SCT_SET1_LOG_ID 115 +# define CT_F_SCT_SET1_SIGNATURE 116 +# define CT_F_SCT_SET_LOG_ENTRY_TYPE 102 +# define CT_F_SCT_SET_SIGNATURE_NID 103 +# define CT_F_SCT_SET_VERSION 104 + +/* + * CT reason codes. + */ +# define CT_R_BASE64_DECODE_ERROR 108 +# define CT_R_INVALID_LOG_ID_LENGTH 100 +# define CT_R_LOG_CONF_INVALID 109 +# define CT_R_LOG_CONF_INVALID_KEY 110 +# define CT_R_LOG_CONF_MISSING_DESCRIPTION 111 +# define CT_R_LOG_CONF_MISSING_KEY 112 +# define CT_R_LOG_KEY_INVALID 113 +# define CT_R_SCT_FUTURE_TIMESTAMP 116 +# define CT_R_SCT_INVALID 104 +# define CT_R_SCT_INVALID_SIGNATURE 107 +# define CT_R_SCT_LIST_INVALID 105 +# define CT_R_SCT_LOG_ID_MISMATCH 114 +# define CT_R_SCT_NOT_SET 106 +# define CT_R_SCT_UNSUPPORTED_VERSION 115 +# define CT_R_UNRECOGNIZED_SIGNATURE_NID 101 +# define CT_R_UNSUPPORTED_ENTRY_TYPE 102 +# define CT_R_UNSUPPORTED_VERSION 103 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/des.h b/thirdparty/user_include/openssl/des.h new file mode 100755 index 0000000000000000000000000000000000000000..be4abbdfd0e6b95e4a5fdde2cdaec032afeb5f92 --- /dev/null +++ b/thirdparty/user_include/openssl/des.h @@ -0,0 +1,174 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DES_H +# define HEADER_DES_H + +# include + +# ifndef OPENSSL_NO_DES +# ifdef __cplusplus +extern "C" { +# endif +# include + +typedef unsigned int DES_LONG; + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +typedef unsigned char DES_cblock[8]; +typedef /* const */ unsigned char const_DES_cblock[8]; +/* + * With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * and + * const_DES_cblock * are incompatible pointer types. + */ + +typedef struct DES_ks { + union { + DES_cblock cblock; + /* + * make sure things are correct size on machines with 8 byte longs + */ + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + +# define DES_KEY_SZ (sizeof(DES_cblock)) +# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +# define DES_ENCRYPT 1 +# define DES_DECRYPT 0 + +# define DES_CBC_MODE 0 +# define DES_PCBC_MODE 1 + +# define DES_ecb2_encrypt(i,o,k1,k2,e) \ + DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +OPENSSL_DECLARE_GLOBAL(int, DES_check_key); /* defaults to false */ +# define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key) + +const char *DES_options(void); +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec); +/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */ +void DES_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc); +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc); + +/* + * This is the DES encryption function that gets called by just about every + * other DES routine in the library. You should not use this function except + * to implement 'modes' of DES. I say this because the functions that call + * this routine do the conversion from 'char *' to long, and this needs to be + * done to make sure 'non-aligned' memory access do not occur. The + * characters are loaded 'little endian'. Data is a pointer to 2 unsigned + * long's and ks is the DES_key_schedule to use. enc, is non zero specifies + * encryption, zero if decryption. + */ +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc); + +/* + * This functions is the same as DES_encrypt1() except that the DES initial + * permutation (IP) and final permutation (FP) have been left out. As for + * DES_encrypt1(), you should not use this function. It is used by the + * routines in the library that implement triple DES. IP() DES_encrypt2() + * DES_encrypt2() DES_encrypt2() FP() is the same as DES_encrypt1() + * DES_encrypt1() DES_encrypt1() except faster :-). + */ +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc); + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec, int enc); +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num); +char *DES_fcrypt(const char *buf, const char *salt, char *ret); +char *DES_crypt(const char *buf, const char *salt); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed); +int DES_random_key(DES_cblock *ret); +void DES_set_odd_parity(DES_cblock *key); +int DES_check_key_parity(const_DES_cblock *key); +int DES_is_weak_key(const_DES_cblock *key); +/* + * DES_set_key (= set_key = DES_key_sched = key_sched) calls + * DES_set_key_checked if global variable DES_check_key is set, + * DES_set_key_unchecked otherwise. + */ +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_string_to_key(const char *str, DES_cblock *key); +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2); +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc); +void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num); + +# define DES_fixup_key_parity DES_set_odd_parity + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/dh.h b/thirdparty/user_include/openssl/dh.h new file mode 100755 index 0000000000000000000000000000000000000000..3527540cdddb4387d6f39da625931b6c50e5e4e2 --- /dev/null +++ b/thirdparty/user_include/openssl/dh.h @@ -0,0 +1,340 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DH_H +# define HEADER_DH_H + +# include + +# ifndef OPENSSL_NO_DH +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# ifndef OPENSSL_DH_MAX_MODULUS_BITS +# define OPENSSL_DH_MAX_MODULUS_BITS 10000 +# endif + +# define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024 + +# define DH_FLAG_CACHE_MONT_P 0x01 + +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define DH_FLAG_NO_EXP_CONSTTIME 0x00 +# endif + +/* + * If this flag is set the DH method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define DH_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DH_FLAG_NON_FIPS_ALLOW 0x0400 + +/* Already defined in ossl_typ.h */ +/* typedef struct dh_st DH; */ +/* typedef struct dh_method DH_METHOD; */ + +DECLARE_ASN1_ITEM(DHparams) + +# define DH_GENERATOR_2 2 +/* #define DH_GENERATOR_3 3 */ +# define DH_GENERATOR_5 5 + +/* DH_check error codes */ +# define DH_CHECK_P_NOT_PRIME 0x01 +# define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +# define DH_UNABLE_TO_CHECK_GENERATOR 0x04 +# define DH_NOT_SUITABLE_GENERATOR 0x08 +# define DH_CHECK_Q_NOT_PRIME 0x10 +# define DH_CHECK_INVALID_Q_VALUE 0x20 +# define DH_CHECK_INVALID_J_VALUE 0x40 + +/* DH_check_pub_key error codes */ +# define DH_CHECK_PUBKEY_TOO_SMALL 0x01 +# define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +# define DH_CHECK_PUBKEY_INVALID 0x04 + +/* + * primes p where (p-1)/2 is prime too are called "safe"; we define this for + * backward compatibility: + */ +# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME + +# define d2i_DHparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x)) +# define d2i_DHparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x) +# define i2d_DHparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x) + +# define d2i_DHxparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHxparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHxparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x)) +# define d2i_DHxparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x) +# define i2d_DHxparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x) + +DH *DHparams_dup(DH *); + +const DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(const DH_METHOD *meth); +const DH_METHOD *DH_get_default_method(void); +int DH_set_method(DH *dh, const DH_METHOD *meth); +DH *DH_new_method(ENGINE *engine); + +DH *DH_new(void); +void DH_free(DH *dh); +int DH_up_ref(DH *dh); +int DH_bits(const DH *dh); +int DH_size(const DH *dh); +int DH_security_bits(const DH *dh); +#define DH_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, l, p, newf, dupf, freef) +int DH_set_ex_data(DH *d, int idx, void *arg); +void *DH_get_ex_data(DH *d, int idx); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(DH *DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, + void *), + void *cb_arg)) + +/* New version */ +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); + +int DH_check_params_ex(const DH *dh); +int DH_check_ex(const DH *dh); +int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key); +int DH_check_params(const DH *dh, int *ret); +int DH_check(const DH *dh, int *codes); +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes); +int DH_generate_key(DH *dh); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh); +DH *d2i_DHparams(DH **a, const unsigned char **pp, long length); +int i2d_DHparams(const DH *a, unsigned char **pp); +DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length); +int i2d_DHxparams(const DH *a, unsigned char **pp); +# ifndef OPENSSL_NO_STDIO +int DHparams_print_fp(FILE *fp, const DH *x); +# endif +int DHparams_print(BIO *bp, const DH *x); + +/* RFC 5114 parameters */ +DH *DH_get_1024_160(void); +DH *DH_get_2048_224(void); +DH *DH_get_2048_256(void); + +/* Named parameters, currently RFC7919 */ +DH *DH_new_by_nid(int nid); +int DH_get_nid(const DH *dh); + +# ifndef OPENSSL_NO_CMS +/* RFC2631 KDF */ +int DH_KDF_X9_42(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + ASN1_OBJECT *key_oid, + const unsigned char *ukm, size_t ukmlen, const EVP_MD *md); +# endif + +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DH_get0_key(const DH *dh, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DH_get0_p(const DH *dh); +const BIGNUM *DH_get0_q(const DH *dh); +const BIGNUM *DH_get0_g(const DH *dh); +const BIGNUM *DH_get0_priv_key(const DH *dh); +const BIGNUM *DH_get0_pub_key(const DH *dh); +void DH_clear_flags(DH *dh, int flags); +int DH_test_flags(const DH *dh, int flags); +void DH_set_flags(DH *dh, int flags); +ENGINE *DH_get0_engine(DH *d); +long DH_get_length(const DH *dh); +int DH_set_length(DH *dh, long length); + +DH_METHOD *DH_meth_new(const char *name, int flags); +void DH_meth_free(DH_METHOD *dhm); +DH_METHOD *DH_meth_dup(const DH_METHOD *dhm); +const char *DH_meth_get0_name(const DH_METHOD *dhm); +int DH_meth_set1_name(DH_METHOD *dhm, const char *name); +int DH_meth_get_flags(const DH_METHOD *dhm); +int DH_meth_set_flags(DH_METHOD *dhm, int flags); +void *DH_meth_get0_app_data(const DH_METHOD *dhm); +int DH_meth_set0_app_data(DH_METHOD *dhm, void *app_data); +int (*DH_meth_get_generate_key(const DH_METHOD *dhm)) (DH *); +int DH_meth_set_generate_key(DH_METHOD *dhm, int (*generate_key) (DH *)); +int (*DH_meth_get_compute_key(const DH_METHOD *dhm)) + (unsigned char *key, const BIGNUM *pub_key, DH *dh); +int DH_meth_set_compute_key(DH_METHOD *dhm, + int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh)); +int (*DH_meth_get_bn_mod_exp(const DH_METHOD *dhm)) + (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *, BN_MONT_CTX *); +int DH_meth_set_bn_mod_exp(DH_METHOD *dhm, + int (*bn_mod_exp) (const DH *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)); +int (*DH_meth_get_init(const DH_METHOD *dhm))(DH *); +int DH_meth_set_init(DH_METHOD *dhm, int (*init)(DH *)); +int (*DH_meth_get_finish(const DH_METHOD *dhm)) (DH *); +int DH_meth_set_finish(DH_METHOD *dhm, int (*finish) (DH *)); +int (*DH_meth_get_generate_params(const DH_METHOD *dhm)) + (DH *, int, int, BN_GENCB *); +int DH_meth_set_generate_params(DH_METHOD *dhm, + int (*generate_params) (DH *, int, int, BN_GENCB *)); + + +# define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dhx_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, \ + EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_DH_NID, nid, NULL) + +# define EVP_PKEY_CTX_set_dh_pad(ctx, pad) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_PAD, pad, NULL) + +# define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid)) + +# define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(poid)) + +# define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)(plen)) + +# define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)(p)) + +# define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)(p)) + +# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13) +# define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14) +# define EVP_PKEY_CTRL_DH_NID (EVP_PKEY_ALG_CTRL + 15) +# define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 16) + +/* KDF types */ +# define EVP_PKEY_DH_KDF_NONE 1 +# ifndef OPENSSL_NO_CMS +# define EVP_PKEY_DH_KDF_X9_42 2 +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/dherr.h b/thirdparty/user_include/openssl/dherr.h new file mode 100755 index 0000000000000000000000000000000000000000..81e73f75c07d4e9e858cf9be8bb249f7d2353b25 --- /dev/null +++ b/thirdparty/user_include/openssl/dherr.h @@ -0,0 +1,84 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DHERR_H +# define HEADER_DHERR_H + +# include + +# ifndef OPENSSL_NO_DH + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_DH_strings(void); + +/* + * DH function codes. + */ +# define DH_F_COMPUTE_KEY 102 +# define DH_F_DHPARAMS_PRINT_FP 101 +# define DH_F_DH_BUILTIN_GENPARAMS 106 +# define DH_F_DH_CHECK_EX 121 +# define DH_F_DH_CHECK_PARAMS_EX 122 +# define DH_F_DH_CHECK_PUB_KEY_EX 123 +# define DH_F_DH_CMS_DECRYPT 114 +# define DH_F_DH_CMS_SET_PEERKEY 115 +# define DH_F_DH_CMS_SET_SHARED_INFO 116 +# define DH_F_DH_METH_DUP 117 +# define DH_F_DH_METH_NEW 118 +# define DH_F_DH_METH_SET1_NAME 119 +# define DH_F_DH_NEW_BY_NID 104 +# define DH_F_DH_NEW_METHOD 105 +# define DH_F_DH_PARAM_DECODE 107 +# define DH_F_DH_PKEY_PUBLIC_CHECK 124 +# define DH_F_DH_PRIV_DECODE 110 +# define DH_F_DH_PRIV_ENCODE 111 +# define DH_F_DH_PUB_DECODE 108 +# define DH_F_DH_PUB_ENCODE 109 +# define DH_F_DO_DH_PRINT 100 +# define DH_F_GENERATE_KEY 103 +# define DH_F_PKEY_DH_CTRL_STR 120 +# define DH_F_PKEY_DH_DERIVE 112 +# define DH_F_PKEY_DH_INIT 125 +# define DH_F_PKEY_DH_KEYGEN 113 + +/* + * DH reason codes. + */ +# define DH_R_BAD_GENERATOR 101 +# define DH_R_BN_DECODE_ERROR 109 +# define DH_R_BN_ERROR 106 +# define DH_R_CHECK_INVALID_J_VALUE 115 +# define DH_R_CHECK_INVALID_Q_VALUE 116 +# define DH_R_CHECK_PUBKEY_INVALID 122 +# define DH_R_CHECK_PUBKEY_TOO_LARGE 123 +# define DH_R_CHECK_PUBKEY_TOO_SMALL 124 +# define DH_R_CHECK_P_NOT_PRIME 117 +# define DH_R_CHECK_P_NOT_SAFE_PRIME 118 +# define DH_R_CHECK_Q_NOT_PRIME 119 +# define DH_R_DECODE_ERROR 104 +# define DH_R_INVALID_PARAMETER_NAME 110 +# define DH_R_INVALID_PARAMETER_NID 114 +# define DH_R_INVALID_PUBKEY 102 +# define DH_R_KDF_PARAMETER_ERROR 112 +# define DH_R_KEYS_NOT_SET 108 +# define DH_R_MISSING_PUBKEY 125 +# define DH_R_MODULUS_TOO_LARGE 103 +# define DH_R_NOT_SUITABLE_GENERATOR 120 +# define DH_R_NO_PARAMETERS_SET 107 +# define DH_R_NO_PRIVATE_VALUE 100 +# define DH_R_PARAMETER_ENCODING_ERROR 105 +# define DH_R_PEER_KEY_ERROR 111 +# define DH_R_SHARED_INFO_ERROR 113 +# define DH_R_UNABLE_TO_CHECK_GENERATOR 121 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/dsa.h b/thirdparty/user_include/openssl/dsa.h new file mode 100755 index 0000000000000000000000000000000000000000..822eff347a293abf4c1291ab7c4d76850495bb68 --- /dev/null +++ b/thirdparty/user_include/openssl/dsa.h @@ -0,0 +1,238 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSA_H +# define HEADER_DSA_H + +# include + +# ifndef OPENSSL_NO_DSA +# ifdef __cplusplus +extern "C" { +# endif +# include +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include + +# ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +# endif + +# define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024 + +# define DSA_FLAG_CACHE_MONT_P 0x01 +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define DSA_FLAG_NO_EXP_CONSTTIME 0x00 +# endif + +/* + * If this flag is set the DSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define DSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DSA_FLAG_NON_FIPS_ALLOW 0x0400 +# define DSA_FLAG_FIPS_CHECKED 0x0800 + +/* Already defined in ossl_typ.h */ +/* typedef struct dsa_st DSA; */ +/* typedef struct dsa_method DSA_METHOD; */ + +typedef struct DSA_SIG_st DSA_SIG; + +# define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \ + (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x)) +# define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \ + (unsigned char *)(x)) +# define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x) +# define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x) + +DSA *DSAparams_dup(DSA *x); +DSA_SIG *DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp); +DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length); +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +int DSA_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +const DSA_METHOD *DSA_OpenSSL(void); + +void DSA_set_default_method(const DSA_METHOD *); +const DSA_METHOD *DSA_get_default_method(void); +int DSA_set_method(DSA *dsa, const DSA_METHOD *); +const DSA_METHOD *DSA_get_method(DSA *d); + +DSA *DSA_new(void); +DSA *DSA_new_method(ENGINE *engine); +void DSA_free(DSA *r); +/* "up" the DSA object's reference count */ +int DSA_up_ref(DSA *r); +int DSA_size(const DSA *); +int DSA_bits(const DSA *d); +int DSA_security_bits(const DSA *d); + /* next 4 return -1 on error */ +DEPRECATEDIN_1_2_0(int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)) +int DSA_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa); +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa); +#define DSA_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, l, p, newf, dupf, freef) +int DSA_set_ex_data(DSA *d, int idx, void *arg); +void *DSA_get_ex_data(DSA *d, int idx); + +DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(DSA *DSA_generate_parameters(int bits, + unsigned char *seed, + int seed_len, + int *counter_ret, + unsigned long *h_ret, void + (*callback) (int, int, + void *), + void *cb_arg)) + +/* New version */ +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + +int DSA_generate_key(DSA *a); +int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); +int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); +int i2d_DSAparams(const DSA *a, unsigned char **pp); + +int DSAparams_print(BIO *bp, const DSA *x); +int DSA_print(BIO *bp, const DSA *x, int off); +# ifndef OPENSSL_NO_STDIO +int DSAparams_print_fp(FILE *fp, const DSA *x); +int DSA_print_fp(FILE *bp, const DSA *x, int off); +# endif + +# define DSS_prime_checks 64 +/* + * Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only + * have one value here we set the number of checks to 64 which is the 128 bit + * security level that is the highest level and valid for creating a 3072 bit + * DSA key. + */ +# define DSA_is_prime(n, callback, cb_arg) \ + BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) + +# ifndef OPENSSL_NO_DH +/* + * Convert DSA structure (key or just parameters) into DH structure (be + * careful to avoid small subgroup attacks when using this!) + */ +DH *DSA_dup_DH(const DSA *r); +# endif + +# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL) + +# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3) + +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DSA_get0_p(const DSA *d); +const BIGNUM *DSA_get0_q(const DSA *d); +const BIGNUM *DSA_get0_g(const DSA *d); +const BIGNUM *DSA_get0_pub_key(const DSA *d); +const BIGNUM *DSA_get0_priv_key(const DSA *d); +void DSA_clear_flags(DSA *d, int flags); +int DSA_test_flags(const DSA *d, int flags); +void DSA_set_flags(DSA *d, int flags); +ENGINE *DSA_get0_engine(DSA *d); + +DSA_METHOD *DSA_meth_new(const char *name, int flags); +void DSA_meth_free(DSA_METHOD *dsam); +DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam); +const char *DSA_meth_get0_name(const DSA_METHOD *dsam); +int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name); +int DSA_meth_get_flags(const DSA_METHOD *dsam); +int DSA_meth_set_flags(DSA_METHOD *dsam, int flags); +void *DSA_meth_get0_app_data(const DSA_METHOD *dsam); +int DSA_meth_set0_app_data(DSA_METHOD *dsam, void *app_data); +DSA_SIG *(*DSA_meth_get_sign(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA *); +int DSA_meth_set_sign(DSA_METHOD *dsam, + DSA_SIG *(*sign) (const unsigned char *, int, DSA *)); +int (*DSA_meth_get_sign_setup(const DSA_METHOD *dsam)) + (DSA *, BN_CTX *, BIGNUM **, BIGNUM **); +int DSA_meth_set_sign_setup(DSA_METHOD *dsam, + int (*sign_setup) (DSA *, BN_CTX *, BIGNUM **, BIGNUM **)); +int (*DSA_meth_get_verify(const DSA_METHOD *dsam)) + (const unsigned char *, int, DSA_SIG *, DSA *); +int DSA_meth_set_verify(DSA_METHOD *dsam, + int (*verify) (const unsigned char *, int, DSA_SIG *, DSA *)); +int (*DSA_meth_get_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +int DSA_meth_set_mod_exp(DSA_METHOD *dsam, + int (*mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *, + BN_MONT_CTX *)); +int (*DSA_meth_get_bn_mod_exp(const DSA_METHOD *dsam)) + (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *, BN_MONT_CTX *); +int DSA_meth_set_bn_mod_exp(DSA_METHOD *dsam, + int (*bn_mod_exp) (DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *)); +int (*DSA_meth_get_init(const DSA_METHOD *dsam))(DSA *); +int DSA_meth_set_init(DSA_METHOD *dsam, int (*init)(DSA *)); +int (*DSA_meth_get_finish(const DSA_METHOD *dsam)) (DSA *); +int DSA_meth_set_finish(DSA_METHOD *dsam, int (*finish) (DSA *)); +int (*DSA_meth_get_paramgen(const DSA_METHOD *dsam)) + (DSA *, int, const unsigned char *, int, int *, unsigned long *, + BN_GENCB *); +int DSA_meth_set_paramgen(DSA_METHOD *dsam, + int (*paramgen) (DSA *, int, const unsigned char *, int, int *, + unsigned long *, BN_GENCB *)); +int (*DSA_meth_get_keygen(const DSA_METHOD *dsam)) (DSA *); +int DSA_meth_set_keygen(DSA_METHOD *dsam, int (*keygen) (DSA *)); + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/dsaerr.h b/thirdparty/user_include/openssl/dsaerr.h new file mode 100755 index 0000000000000000000000000000000000000000..d94f97bba8f213c089cdced5e86533db4e3fc654 --- /dev/null +++ b/thirdparty/user_include/openssl/dsaerr.h @@ -0,0 +1,67 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DSAERR_H +# define HEADER_DSAERR_H + +# include + +# ifndef OPENSSL_NO_DSA + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_DSA_strings(void); + +/* + * DSA function codes. + */ +# define DSA_F_DSAPARAMS_PRINT 100 +# define DSA_F_DSAPARAMS_PRINT_FP 101 +# define DSA_F_DSA_BUILTIN_PARAMGEN 125 +# define DSA_F_DSA_BUILTIN_PARAMGEN2 126 +# define DSA_F_DSA_DO_SIGN 112 +# define DSA_F_DSA_DO_VERIFY 113 +# define DSA_F_DSA_METH_DUP 127 +# define DSA_F_DSA_METH_NEW 128 +# define DSA_F_DSA_METH_SET1_NAME 129 +# define DSA_F_DSA_NEW_METHOD 103 +# define DSA_F_DSA_PARAM_DECODE 119 +# define DSA_F_DSA_PRINT_FP 105 +# define DSA_F_DSA_PRIV_DECODE 115 +# define DSA_F_DSA_PRIV_ENCODE 116 +# define DSA_F_DSA_PUB_DECODE 117 +# define DSA_F_DSA_PUB_ENCODE 118 +# define DSA_F_DSA_SIGN 106 +# define DSA_F_DSA_SIGN_SETUP 107 +# define DSA_F_DSA_SIG_NEW 102 +# define DSA_F_OLD_DSA_PRIV_DECODE 122 +# define DSA_F_PKEY_DSA_CTRL 120 +# define DSA_F_PKEY_DSA_CTRL_STR 104 +# define DSA_F_PKEY_DSA_KEYGEN 121 + +/* + * DSA reason codes. + */ +# define DSA_R_BAD_Q_VALUE 102 +# define DSA_R_BN_DECODE_ERROR 108 +# define DSA_R_BN_ERROR 109 +# define DSA_R_DECODE_ERROR 104 +# define DSA_R_INVALID_DIGEST_TYPE 106 +# define DSA_R_INVALID_PARAMETERS 112 +# define DSA_R_MISSING_PARAMETERS 101 +# define DSA_R_MODULUS_TOO_LARGE 103 +# define DSA_R_NO_PARAMETERS_SET 107 +# define DSA_R_PARAMETER_ENCODING_ERROR 105 +# define DSA_R_Q_NOT_PRIME 113 +# define DSA_R_SEED_LEN_SMALL 110 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/dtls1.h b/thirdparty/user_include/openssl/dtls1.h new file mode 100755 index 0000000000000000000000000000000000000000..a312e386cf9ac83c1d76095ef8cbd3a10c42d635 --- /dev/null +++ b/thirdparty/user_include/openssl/dtls1.h @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DTLS1_H +# define HEADER_DTLS1_H + +#ifdef __cplusplus +extern "C" { +#endif + +# define DTLS1_VERSION 0xFEFF +# define DTLS1_2_VERSION 0xFEFD +# define DTLS_MIN_VERSION DTLS1_VERSION +# define DTLS_MAX_VERSION DTLS1_2_VERSION +# define DTLS1_VERSION_MAJOR 0xFE + +# define DTLS1_BAD_VER 0x0100 + +/* Special value for method supporting multiple versions */ +# define DTLS_ANY_VERSION 0x1FFFF + +/* lengths of messages */ +/* + * Actually the max cookie length in DTLS is 255. But we can't change this now + * due to compatibility concerns. + */ +# define DTLS1_COOKIE_LENGTH 256 + +# define DTLS1_RT_HEADER_LENGTH 13 + +# define DTLS1_HM_HEADER_LENGTH 12 + +# define DTLS1_HM_BAD_FRAGMENT -2 +# define DTLS1_HM_FRAGMENT_RETRY -3 + +# define DTLS1_CCS_HEADER_LENGTH 1 + +# define DTLS1_AL_HEADER_LENGTH 2 + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +# define DTLS1_TMO_READ_COUNT 2 +# define DTLS1_TMO_WRITE_COUNT 2 + +# define DTLS1_TMO_ALERT_COUNT 12 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/e_os2.h b/thirdparty/user_include/openssl/e_os2.h new file mode 100755 index 0000000000000000000000000000000000000000..97a776cdacc76817fb045b8e870208f89c922467 --- /dev/null +++ b/thirdparty/user_include/openssl/e_os2.h @@ -0,0 +1,300 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_E_OS2_H +# define HEADER_E_OS2_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * Detect operating systems. This probably needs completing. + * The result is that at least one OPENSSL_SYS_os macro should be defined. + * However, if none is defined, Unix is assumed. + **/ + +# define OPENSSL_SYS_UNIX + +/* --------------------- Microsoft operating systems ---------------------- */ + +/* + * Note that MSDOS actually denotes 32-bit environments running on top of + * MS-DOS, such as DJGPP one. + */ +# if defined(OPENSSL_SYS_MSDOS) +# undef OPENSSL_SYS_UNIX +# endif + +/* + * For 32 bit environment, there seems to be the CygWin environment and then + * all the others that try to do the same thing Microsoft does... + */ +/* + * UEFI lives here because it might be built with a Microsoft toolchain and + * we need to avoid the false positive match on Windows. + */ +# if defined(OPENSSL_SYS_UEFI) +# undef OPENSSL_SYS_UNIX +# elif defined(OPENSSL_SYS_UWIN) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WIN32_UWIN +# else +# if defined(__CYGWIN__) || defined(OPENSSL_SYS_CYGWIN) +# define OPENSSL_SYS_WIN32_CYGWIN +# else +# if defined(_WIN32) || defined(OPENSSL_SYS_WIN32) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN32) +# define OPENSSL_SYS_WIN32 +# endif +# endif +# if defined(_WIN64) || defined(OPENSSL_SYS_WIN64) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN64) +# define OPENSSL_SYS_WIN64 +# endif +# endif +# if defined(OPENSSL_SYS_WINNT) +# undef OPENSSL_SYS_UNIX +# endif +# if defined(OPENSSL_SYS_WINCE) +# undef OPENSSL_SYS_UNIX +# endif +# endif +# endif + +/* Anything that tries to look like Microsoft is "Windows" */ +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_SYS_MSDOS +# define OPENSSL_SYS_MSDOS +# endif +# endif + +/* + * DLL settings. This part is a bit tough, because it's up to the + * application implementor how he or she will link the application, so it + * requires some macro to be used. + */ +# ifdef OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_OPT_WINDLL +# if defined(_WINDLL) /* This is used when building OpenSSL to + * indicate that DLL linkage should be used */ +# define OPENSSL_OPT_WINDLL +# endif +# endif +# endif + +/* ------------------------------- OpenVMS -------------------------------- */ +# if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYS_VMS) +# if !defined(OPENSSL_SYS_VMS) +# undef OPENSSL_SYS_UNIX +# endif +# define OPENSSL_SYS_VMS +# if defined(__DECC) +# define OPENSSL_SYS_VMS_DECC +# elif defined(__DECCXX) +# define OPENSSL_SYS_VMS_DECC +# define OPENSSL_SYS_VMS_DECCXX +# else +# define OPENSSL_SYS_VMS_NODECC +# endif +# endif + +/* -------------------------------- Unix ---------------------------------- */ +# ifdef OPENSSL_SYS_UNIX +# if defined(linux) || defined(__linux__) && !defined(OPENSSL_SYS_LINUX) +# define OPENSSL_SYS_LINUX +# endif +# if defined(_AIX) && !defined(OPENSSL_SYS_AIX) +# define OPENSSL_SYS_AIX +# endif +# endif + +/* -------------------------------- VOS ----------------------------------- */ +# if defined(__VOS__) && !defined(OPENSSL_SYS_VOS) +# define OPENSSL_SYS_VOS +# ifdef __HPPA__ +# define OPENSSL_SYS_VOS_HPPA +# endif +# ifdef __IA32__ +# define OPENSSL_SYS_VOS_IA32 +# endif +# endif + +/** + * That's it for OS-specific stuff + *****************************************************************************/ + +/* Specials for I/O an exit */ +# ifdef OPENSSL_SYS_MSDOS +# define OPENSSL_UNISTD_IO +# define OPENSSL_DECLARE_EXIT extern void exit(int); +# else +# define OPENSSL_UNISTD_IO OPENSSL_UNISTD +# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */ +# endif + +/*- + * OPENSSL_EXTERN is normally used to declare a symbol with possible extra + * attributes to handle its presence in a shared library. + * OPENSSL_EXPORT is used to define a symbol with extra possible attributes + * to make it visible in a shared library. + * Care needs to be taken when a header file is used both to declare and + * define symbols. Basically, for any library that exports some global + * variables, the following code must be present in the header file that + * declares them, before OPENSSL_EXTERN is used: + * + * #ifdef SOME_BUILD_FLAG_MACRO + * # undef OPENSSL_EXTERN + * # define OPENSSL_EXTERN OPENSSL_EXPORT + * #endif + * + * The default is to have OPENSSL_EXPORT and OPENSSL_EXTERN + * have some generally sensible values. + */ + +# if defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL) +# define OPENSSL_EXPORT extern __declspec(dllexport) +# define OPENSSL_EXTERN extern __declspec(dllimport) +# else +# define OPENSSL_EXPORT extern +# define OPENSSL_EXTERN extern +# endif + +/*- + * Macros to allow global variables to be reached through function calls when + * required (if a shared library version requires it, for example. + * The way it's done allows definitions like this: + * + * // in foobar.c + * OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0) + * // in foobar.h + * OPENSSL_DECLARE_GLOBAL(int,foobar); + * #define foobar OPENSSL_GLOBAL_REF(foobar) + */ +# ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) \ + type *_shadow_##name(void) \ + { static type _hide_##name=value; return &_hide_##name; } +# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void) +# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name())) +# else +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) type _shadow_##name=value; +# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name +# define OPENSSL_GLOBAL_REF(name) _shadow_##name +# endif + +# ifdef _WIN32 +# ifdef _WIN64 +# define ossl_ssize_t __int64 +# define OSSL_SSIZE_MAX _I64_MAX +# else +# define ossl_ssize_t int +# define OSSL_SSIZE_MAX INT_MAX +# endif +# endif + +# if defined(OPENSSL_SYS_UEFI) && !defined(ossl_ssize_t) +# define ossl_ssize_t INTN +# define OSSL_SSIZE_MAX MAX_INTN +# endif + +# ifndef ossl_ssize_t +# define ossl_ssize_t ssize_t +# if defined(SSIZE_MAX) +# define OSSL_SSIZE_MAX SSIZE_MAX +# elif defined(_POSIX_SSIZE_MAX) +# define OSSL_SSIZE_MAX _POSIX_SSIZE_MAX +# else +# define OSSL_SSIZE_MAX ((ssize_t)(SIZE_MAX>>1)) +# endif +# endif + +# ifdef DEBUG_UNUSED +# define __owur __attribute__((__warn_unused_result__)) +# else +# define __owur +# endif + +/* Standard integer types */ +# if defined(OPENSSL_SYS_UEFI) +typedef INT8 int8_t; +typedef UINT8 uint8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef INT64 int64_t; +typedef UINT64 uint64_t; +# elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + defined(__osf__) || defined(__sgi) || defined(__hpux) || \ + defined(OPENSSL_SYS_VMS) || defined (__OpenBSD__) +# include +# elif defined(_MSC_VER) && _MSC_VER<=1500 +/* + * minimally required typdefs for systems not supporting inttypes.h or + * stdint.h: currently just older VC++ + */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +# else +# include +# endif + +/* ossl_inline: portable inline definition usable in public headers */ +# if !defined(inline) && !defined(__cplusplus) +# if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L + /* just use inline */ +# define ossl_inline inline +# elif defined(__GNUC__) && __GNUC__>=2 +# define ossl_inline __inline__ +# elif defined(_MSC_VER) + /* + * Visual Studio: inline is available in C++ only, however + * __inline is available for C, see + * http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx + */ +# define ossl_inline __inline +# else +# define ossl_inline +# endif +# else +# define ossl_inline inline +# endif + +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# define ossl_noreturn _Noreturn +# elif defined(__GNUC__) && __GNUC__ >= 2 +# define ossl_noreturn __attribute__((noreturn)) +# else +# define ossl_noreturn +# endif + +/* ossl_unused: portable unused attribute for use in public headers */ +# if defined(__GNUC__) +# define ossl_unused __attribute__((unused)) +# else +# define ossl_unused +# endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/ebcdic.h b/thirdparty/user_include/openssl/ebcdic.h new file mode 100755 index 0000000000000000000000000000000000000000..aa0128559992c9365b5c8dc8f2fe904a16ac2179 --- /dev/null +++ b/thirdparty/user_include/openssl/ebcdic.h @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EBCDIC_H +# define HEADER_EBCDIC_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Avoid name clashes with other applications */ +# define os_toascii _openssl_os_toascii +# define os_toebcdic _openssl_os_toebcdic +# define ebcdic2ascii _openssl_ebcdic2ascii +# define ascii2ebcdic _openssl_ascii2ebcdic + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void *ebcdic2ascii(void *dest, const void *srce, size_t count); +void *ascii2ebcdic(void *dest, const void *srce, size_t count); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/ec.h b/thirdparty/user_include/openssl/ec.h new file mode 100755 index 0000000000000000000000000000000000000000..347cfb6d097b91347ae75135b44da1be70290c4a --- /dev/null +++ b/thirdparty/user_include/openssl/ec.h @@ -0,0 +1,1478 @@ +/* + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EC_H +# define HEADER_EC_H + +# include + +# ifndef OPENSSL_NO_EC +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# ifdef __cplusplus +extern "C" { +# endif + +# ifndef OPENSSL_ECC_MAX_FIELD_BITS +# define OPENSSL_ECC_MAX_FIELD_BITS 661 +# endif + +/** Enum for the point conversion form as defined in X9.62 (ECDSA) + * for the encoding of a elliptic curve point (x,y) */ +typedef enum { + /** the point is encoded as z||x, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_COMPRESSED = 2, + /** the point is encoded as z||x||y, where z is the octet 0x04 */ + POINT_CONVERSION_UNCOMPRESSED = 4, + /** the point is encoded as z||x||y, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_HYBRID = 6 +} point_conversion_form_t; + +typedef struct ec_method_st EC_METHOD; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_point_st EC_POINT; +typedef struct ecpk_parameters_st ECPKPARAMETERS; +typedef struct ec_parameters_st ECPARAMETERS; + +/********************************************************************/ +/* EC_METHODs for curves over GF(p) */ +/********************************************************************/ + +/** Returns the basic GFp ec methods which provides the basis for the + * optimized methods. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_simple_method(void); + +/** Returns GFp methods using montgomery multiplication. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_mont_method(void); + +/** Returns GFp methods using optimized methods for NIST recommended curves + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nist_method(void); + +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +/** Returns 64-bit optimized methods for nistp224 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp224_method(void); + +/** Returns 64-bit optimized methods for nistp256 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp256_method(void); + +/** Returns 64-bit optimized methods for nistp521 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp521_method(void); +# endif + +# ifndef OPENSSL_NO_EC2M +/********************************************************************/ +/* EC_METHOD for curves over GF(2^m) */ +/********************************************************************/ + +/** Returns the basic GF2m ec method + * \return EC_METHOD object + */ +const EC_METHOD *EC_GF2m_simple_method(void); + +# endif + +/********************************************************************/ +/* EC_GROUP functions */ +/********************************************************************/ + +/** Creates a new EC_GROUP object + * \param meth EC_METHOD to use + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth); + +/** Frees a EC_GROUP object + * \param group EC_GROUP object to be freed. + */ +void EC_GROUP_free(EC_GROUP *group); + +/** Clears and frees a EC_GROUP object + * \param group EC_GROUP object to be cleared and freed. + */ +void EC_GROUP_clear_free(EC_GROUP *group); + +/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD. + * \param dst destination EC_GROUP object + * \param src source EC_GROUP object + * \return 1 on success and 0 if an error occurred. + */ +int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src); + +/** Creates a new EC_GROUP object and copies the copies the content + * form src to the newly created EC_KEY object + * \param src source EC_GROUP object + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_dup(const EC_GROUP *src); + +/** Returns the EC_METHOD of the EC_GROUP object. + * \param group EC_GROUP object + * \return EC_METHOD used in this EC_GROUP object. + */ +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); + +/** Returns the field type of the EC_METHOD. + * \param meth EC_METHOD object + * \return NID of the underlying field type OID. + */ +int EC_METHOD_get_field_type(const EC_METHOD *meth); + +/** Sets the generator and it's order/cofactor of a EC_GROUP object. + * \param group EC_GROUP object + * \param generator EC_POINT object with the generator. + * \param order the order of the group generated by the generator. + * \param cofactor the index of the sub-group generated by the generator + * in the group of all points on the elliptic curve. + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); + +/** Returns the generator of a EC_GROUP object. + * \param group EC_GROUP object + * \return the currently used generator (possibly NULL). + */ +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +/** Returns the montgomery data for order(Generator) + * \param group EC_GROUP object + * \return the currently used montgomery data (possibly NULL). +*/ +BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group); + +/** Gets the order of a EC_GROUP + * \param group EC_GROUP object + * \param order BIGNUM to which the order is copied + * \param ctx unused + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); + +/** Gets the order of an EC_GROUP + * \param group EC_GROUP object + * \return the group order + */ +const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); + +/** Gets the number of bits of the order of an EC_GROUP + * \param group EC_GROUP object + * \return number of bits of group order. + */ +int EC_GROUP_order_bits(const EC_GROUP *group); + +/** Gets the cofactor of a EC_GROUP + * \param group EC_GROUP object + * \param cofactor BIGNUM to which the cofactor is copied + * \param ctx unused + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx); + +/** Gets the cofactor of an EC_GROUP + * \param group EC_GROUP object + * \return the group cofactor + */ +const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group); + +/** Sets the name of a EC_GROUP object + * \param group EC_GROUP object + * \param nid NID of the curve name OID + */ +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid); + +/** Returns the curve name of a EC_GROUP object + * \param group EC_GROUP object + * \return NID of the curve name OID or 0 if not set. + */ +int EC_GROUP_get_curve_name(const EC_GROUP *group); + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); +int EC_GROUP_get_asn1_flag(const EC_GROUP *group); + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form); +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); + +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); +size_t EC_GROUP_get_seed_len(const EC_GROUP *); +size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); + +/** Sets the parameters of a ec curve defined by y^2 = x^3 + a*x + b (for GFp) + * or y^2 + x*y = x^3 + a*x^2 + b (for GF2m) + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +/** Gets the parameters of the ec curve defined by y^2 = x^3 + a*x + b (for GFp) + * or y^2 + x*y = x^3 + a*x^2 + b (for GF2m) + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *ctx); + +/** Sets the parameters of an ec curve. Synonym for EC_GROUP_set_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx)) + +/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, + BN_CTX *ctx)) + +# ifndef OPENSSL_NO_EC2M +/** Sets the parameter of an ec curve. Synonym for EC_GROUP_set_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx)) + +/** Gets the parameters of an ec curve. Synonym for EC_GROUP_get_curve + * \param group EC_GROUP object + * \param p BIGNUM with the prime number (GFp) or the polynomial + * defining the underlying field (GF2m) + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, + BN_CTX *ctx)) +# endif +/** Returns the number of bits needed to represent a field element + * \param group EC_GROUP object + * \return number of bits needed to represent a field element + */ +int EC_GROUP_get_degree(const EC_GROUP *group); + +/** Checks whether the parameter in the EC_GROUP define a valid ec group + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if group is a valid ec group and 0 otherwise + */ +int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx); + +/** Checks whether the discriminant of the elliptic curve is zero or not + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if the discriminant is not zero and 0 otherwise + */ +int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx); + +/** Compares two EC_GROUP objects + * \param a first EC_GROUP object + * \param b second EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 0 if the groups are equal, 1 if not, or -1 on error + */ +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); + +/* + * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after + * choosing an appropriate EC_METHOD + */ + +/** Creates a new EC_GROUP object with the specified parameters defined + * over GFp (defined by the equation y^2 = x^3 + a*x + b) + * \param p BIGNUM with the prime number + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M +/** Creates a new EC_GROUP object with the specified parameters defined + * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) + * \param p BIGNUM with the polynomial defining the underlying field + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# endif + +/** Creates a EC_GROUP object with a curve specified by a NID + * \param nid NID of the OID of the curve name + * \return newly created EC_GROUP object with specified curve or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +/** Creates a new EC_GROUP object from an ECPARAMETERS object + * \param params pointer to the ECPARAMETERS object + * \return newly created EC_GROUP object with specified curve or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params); + +/** Creates an ECPARAMETERS object for the given EC_GROUP object. + * \param group pointer to the EC_GROUP object + * \param params pointer to an existing ECPARAMETERS object or NULL + * \return pointer to the new ECPARAMETERS object or NULL + * if an error occurred. + */ +ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, + ECPARAMETERS *params); + +/** Creates a new EC_GROUP object from an ECPKPARAMETERS object + * \param params pointer to an existing ECPKPARAMETERS object, or NULL + * \return newly created EC_GROUP object with specified curve, or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params); + +/** Creates an ECPKPARAMETERS object for the given EC_GROUP object. + * \param group pointer to the EC_GROUP object + * \param params pointer to an existing ECPKPARAMETERS object or NULL + * \return pointer to the new ECPKPARAMETERS object or NULL + * if an error occurred. + */ +ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, + ECPKPARAMETERS *params); + +/********************************************************************/ +/* handling of internal curves */ +/********************************************************************/ + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* + * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all + * available curves or zero if a error occurred. In case r is not zero, + * nitems EC_builtin_curve structures are filled with the data of the first + * nitems internal groups + */ +size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); + +const char *EC_curve_nid2nist(int nid); +int EC_curve_nist2nid(const char *name); + +/********************************************************************/ +/* EC_POINT functions */ +/********************************************************************/ + +/** Creates a new EC_POINT object for the specified EC_GROUP + * \param group EC_GROUP the underlying EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_new(const EC_GROUP *group); + +/** Frees a EC_POINT object + * \param point EC_POINT object to be freed + */ +void EC_POINT_free(EC_POINT *point); + +/** Clears and frees a EC_POINT object + * \param point EC_POINT object to be cleared and freed + */ +void EC_POINT_clear_free(EC_POINT *point); + +/** Copies EC_POINT object + * \param dst destination EC_POINT object + * \param src source EC_POINT object + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src); + +/** Creates a new EC_POINT object and copies the content of the supplied + * EC_POINT + * \param src source EC_POINT object + * \param group underlying the EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group); + +/** Returns the EC_METHOD used in EC_POINT object + * \param point EC_POINT object + * \return the EC_METHOD used + */ +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point); + +/** Sets a point to infinity (neutral element) + * \param group underlying EC_GROUP object + * \param point EC_POINT to set to infinity + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point); + +/** Sets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param z BIGNUM with the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); + +/** Gets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param z BIGNUM for the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx); + +/** Sets the affine coordinates of an EC_POINT + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); + +/** Gets the affine coordinates of an EC_POINT. + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx); + +/** Sets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_set_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx)) + +/** Gets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_get_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + BN_CTX *ctx)) + +/** Sets the x9.62 compressed coordinates of a EC_POINT + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, int y_bit, + BN_CTX *ctx); + +/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of + * EC_POINT_set_compressed_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + int y_bit, + BN_CTX *ctx)) +# ifndef OPENSSL_NO_EC2M +/** Sets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_set_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx)) + +/** Gets the affine coordinates of an EC_POINT. A synonym of + * EC_POINT_get_affine_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, + BIGNUM *x, + BIGNUM *y, + BN_CTX *ctx)) + +/** Sets the x9.62 compressed coordinates of a EC_POINT. A synonym of + * EC_POINT_set_compressed_coordinates + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +DEPRECATEDIN_1_2_0(int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, + const BIGNUM *x, + int y_bit, + BN_CTX *ctx)) +# endif +/** Encodes a EC_POINT object to a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param form point conversion form + * \param buf memory buffer for the result. If NULL the function returns + * required buffer size. + * \param len length of the memory buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx); + +/** Decodes a EC_POINT from a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param buf memory buffer with the encoded ec point + * \param len length of the encoded ec point + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p, + const unsigned char *buf, size_t len, BN_CTX *ctx); + +/** Encodes an EC_POINT object to an allocated octet string + * \param group underlying EC_GROUP object + * \param point EC_POINT object + * \param form point conversion form + * \param pbuf returns pointer to allocated buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx); + +/* other interfaces to point2oct/oct2point: */ +BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BIGNUM *, BN_CTX *); +EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *, + EC_POINT *, BN_CTX *); +char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BN_CTX *); +EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, + EC_POINT *, BN_CTX *); + +/********************************************************************/ +/* functions for doing EC_POINT arithmetic */ +/********************************************************************/ + +/** Computes the sum of two EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = a + b) + * \param a EC_POINT object with the first summand + * \param b EC_POINT object with the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); + +/** Computes the double of a EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = 2 * a) + * \param a EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx); + +/** Computes the inverse of a EC_POINT + * \param group underlying EC_GROUP object + * \param a EC_POINT object to be inverted (it's used for the result as well) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); + +/** Checks whether the point is the neutral element of the group + * \param group the underlying EC_GROUP object + * \param p EC_POINT object + * \return 1 if the point is the neutral element and 0 otherwise + */ +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p); + +/** Checks whether the point is on the curve + * \param group underlying EC_GROUP object + * \param point EC_POINT object to check + * \param ctx BN_CTX object (optional) + * \return 1 if the point is on the curve, 0 if not, or -1 on error + */ +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx); + +/** Compares two EC_POINTs + * \param group underlying EC_GROUP object + * \param a first EC_POINT object + * \param b second EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 1 if the points are not equal, 0 if they are, or -1 on error + */ +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx); + +/** Computes r = generator * n + sum_{i=0}^{num-1} p[i] * m[i] + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param num number further summands + * \param p array of size num of EC_POINT objects + * \param m array of size num of BIGNUM objects + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + size_t num, const EC_POINT *p[], const BIGNUM *m[], + BN_CTX *ctx); + +/** Computes r = generator * n + q * m + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param q EC_POINT object with the first factor of the second summand + * \param m BIGNUM with the second factor of the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); + +/** Stores multiples of generator for faster point multiplication + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx); + +/** Reports whether a precomputation has been done + * \param group EC_GROUP object + * \return 1 if a pre-computation has been done and 0 otherwise + */ +int EC_GROUP_have_precompute_mult(const EC_GROUP *group); + +/********************************************************************/ +/* ASN1 stuff */ +/********************************************************************/ + +DECLARE_ASN1_ITEM(ECPKPARAMETERS) +DECLARE_ASN1_ALLOC_FUNCTIONS(ECPKPARAMETERS) +DECLARE_ASN1_ITEM(ECPARAMETERS) +DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) + +/* + * EC_GROUP_get_basis_type() returns the NID of the basis type used to + * represent the field elements + */ +int EC_GROUP_get_basis_type(const EC_GROUP *); +# ifndef OPENSSL_NO_EC2M +int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, + unsigned int *k2, unsigned int *k3); +# endif + +# define OPENSSL_EC_EXPLICIT_CURVE 0x000 +# define OPENSSL_EC_NAMED_CURVE 0x001 + +EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); +int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); + +# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) +# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) +# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ + (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x)) +# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ + (unsigned char *)(x)) + +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); +# ifndef OPENSSL_NO_STDIO +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); +# endif + +/********************************************************************/ +/* EC_KEY functions */ +/********************************************************************/ + +/* some values for the encoding_flag */ +# define EC_PKEY_NO_PARAMETERS 0x001 +# define EC_PKEY_NO_PUBKEY 0x002 + +/* some values for the flags field */ +# define EC_FLAG_NON_FIPS_ALLOW 0x1 +# define EC_FLAG_FIPS_CHECKED 0x2 +# define EC_FLAG_COFACTOR_ECDH 0x1000 + +/** Creates a new EC_KEY object. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new(void); + +int EC_KEY_get_flags(const EC_KEY *key); + +void EC_KEY_set_flags(EC_KEY *key, int flags); + +void EC_KEY_clear_flags(EC_KEY *key, int flags); + +/** Creates a new EC_KEY object using a named curve as underlying + * EC_GROUP object. + * \param nid NID of the named curve. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new_by_curve_name(int nid); + +/** Frees a EC_KEY object. + * \param key EC_KEY object to be freed. + */ +void EC_KEY_free(EC_KEY *key); + +/** Copies a EC_KEY object. + * \param dst destination EC_KEY object + * \param src src EC_KEY object + * \return dst or NULL if an error occurred. + */ +EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); + +/** Creates a new EC_KEY object and copies the content from src to it. + * \param src the source EC_KEY object + * \return newly created EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_dup(const EC_KEY *src); + +/** Increases the internal reference count of a EC_KEY object. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_up_ref(EC_KEY *key); + +/** Returns the ENGINE object of a EC_KEY object + * \param eckey EC_KEY object + * \return the ENGINE object (possibly NULL). + */ +ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey); + +/** Returns the EC_GROUP object of a EC_KEY object + * \param key EC_KEY object + * \return the EC_GROUP object (possibly NULL). + */ +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); + +/** Sets the EC_GROUP of a EC_KEY object. + * \param key EC_KEY object + * \param group EC_GROUP to use in the EC_KEY object (note: the EC_KEY + * object will use an own copy of the EC_GROUP). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); + +/** Returns the private key of a EC_KEY object. + * \param key EC_KEY object + * \return a BIGNUM with the private key (possibly NULL). + */ +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); + +/** Sets the private key of a EC_KEY object. + * \param key EC_KEY object + * \param prv BIGNUM with the private key (note: the EC_KEY object + * will use an own copy of the BIGNUM). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); + +/** Returns the public key of a EC_KEY object. + * \param key the EC_KEY object + * \return a EC_POINT object with the public key (possibly NULL) + */ +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); + +/** Sets the public key of a EC_KEY object. + * \param key EC_KEY object + * \param pub EC_POINT object with the public key (note: the EC_KEY object + * will use an own copy of the EC_POINT object). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +unsigned EC_KEY_get_enc_flags(const EC_KEY *key); +void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); +void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); + +#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef) +int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg); +void *EC_KEY_get_ex_data(const EC_KEY *key, int idx); + +/* wrapper functions for the underlying EC_GROUP object */ +void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); + +/** Creates a table of pre-computed multiples of the generator to + * accelerate further EC_KEY operations. + * \param key EC_KEY object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx); + +/** Creates a new ec private (and optional a new public) key. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_generate_key(EC_KEY *key); + +/** Verifies that a private and/or public key is valid. + * \param key the EC_KEY object + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_check_key(const EC_KEY *key); + +/** Indicates if an EC_KEY can be used for signing. + * \param eckey the EC_KEY object + * \return 1 if can can sign and 0 otherwise. + */ +int EC_KEY_can_sign(const EC_KEY *eckey); + +/** Sets a public key from affine coordinates performing + * necessary NIST PKV tests. + * \param key the EC_KEY object + * \param x public key x coordinate + * \param y public key y coordinate + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y); + +/** Encodes an EC_KEY public key to an allocated octet string + * \param key key to encode + * \param form point conversion form + * \param pbuf returns pointer to allocated buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, + unsigned char **pbuf, BN_CTX *ctx); + +/** Decodes a EC_KEY public key from a octet string + * \param key key to decode + * \param buf memory buffer with the encoded ec point + * \param len length of the encoded ec point + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred + */ + +int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, + BN_CTX *ctx); + +/** Decodes an EC_KEY private key from an octet string + * \param key key to decode + * \param buf memory buffer with the encoded private key + * \param len length of the encoded key + * \return 1 on success and 0 if an error occurred + */ + +int EC_KEY_oct2priv(EC_KEY *key, const unsigned char *buf, size_t len); + +/** Encodes a EC_KEY private key to an octet string + * \param key key to encode + * \param buf memory buffer for the result. If NULL the function returns + * required buffer size. + * \param len length of the memory buffer + * \return the length of the encoded octet string or 0 if an error occurred + */ + +size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len); + +/** Encodes an EC_KEY private key to an allocated octet string + * \param eckey key to encode + * \param pbuf returns pointer to allocated buffer + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf); + +/********************************************************************/ +/* de- and encoding functions for SEC1 ECPrivateKey */ +/********************************************************************/ + +/** Decodes a private key from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded private key + * \param len length of the DER encoded private key + * \return the decoded private key or NULL if an error occurred. + */ +EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a private key object and stores the result in a buffer. + * \param key the EC_KEY object to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC parameters */ +/********************************************************************/ + +/** Decodes ec parameter from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded ec parameters + * \param len length of the DER encoded ec parameters + * \return a EC_KEY object with the decoded parameters or NULL if an error + * occurred. + */ +EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes ec parameter and stores the result in a buffer. + * \param key the EC_KEY object with ec parameters to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECParameters(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC public key */ +/* (octet string, not DER -- hence 'o2i' and 'i2o') */ +/********************************************************************/ + +/** Decodes a ec public key from a octet string. + * \param key a pointer to a EC_KEY object which should be used + * \param in memory buffer with the encoded public key + * \param len length of the encoded public key + * \return EC_KEY object with decoded public key or NULL if an error + * occurred. + */ +EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a ec public key in an octet string. + * \param key the EC_KEY object with the public key + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred + */ +int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out); + +/** Prints out the ec parameters on human readable form. + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print(BIO *bp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); + +# ifndef OPENSSL_NO_STDIO +/** Prints out the ec parameters on human readable form. + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print_fp(FILE *fp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + +# endif + +const EC_KEY_METHOD *EC_KEY_OpenSSL(void); +const EC_KEY_METHOD *EC_KEY_get_default_method(void); +void EC_KEY_set_default_method(const EC_KEY_METHOD *meth); +const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key); +int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth); +EC_KEY *EC_KEY_new_method(ENGINE *engine); + +/** The old name for ecdh_KDF_X9_63 + * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62, + * it is actually specified in ANSI X9.63. + * This identifier is retained for backwards compatibility + */ +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md); + +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + const EC_KEY *ecdh, + void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)); + +typedef struct ECDSA_SIG_st ECDSA_SIG; + +/** Allocates and initialize a ECDSA_SIG structure + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_SIG_new(void); + +/** frees a ECDSA_SIG structure + * \param sig pointer to the ECDSA_SIG structure + */ +void ECDSA_SIG_free(ECDSA_SIG *sig); + +/** DER encode content of ECDSA_SIG object (note: this function modifies *pp + * (*pp += length of the DER encoded signature)). + * \param sig pointer to the ECDSA_SIG object + * \param pp pointer to a unsigned char pointer for the output or NULL + * \return the length of the DER encoded ECDSA_SIG object or 0 + */ +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); + +/** Decodes a DER encoded ECDSA signature (note: this function changes *pp + * (*pp += len)). + * \param sig pointer to ECDSA_SIG pointer (may be NULL) + * \param pp memory buffer with the DER encoded signature + * \param len length of the buffer + * \return pointer to the decoded ECDSA_SIG structure (or NULL) + */ +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); + +/** Accessor for r and s fields of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + * \param pr pointer to BIGNUM pointer for r (may be NULL) + * \param ps pointer to BIGNUM pointer for s (may be NULL) + */ +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); + +/** Accessor for r field of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + */ +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); + +/** Accessor for s field of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + */ +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); + +/** Setter for r and s fields of ECDSA_SIG + * \param sig pointer to ECDSA_SIG structure + * \param r pointer to BIGNUM for r (may be NULL) + * \param s pointer to BIGNUM for s (may be NULL) + */ +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +/** Computes the ECDSA signature of the given hash value using + * the supplied private key and returns the created signature. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optional), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey); + +/** Verifies that the supplied signature is a valid ECDSA + * signature of the supplied hash value using the supplied public key. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param sig ECDSA_SIG structure + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +/** Precompute parts of the signing operation + * \param eckey EC_KEY object containing a private EC key + * \param ctx BN_CTX object (optional) + * \param kinv BIGNUM pointer for the inverse of k + * \param rp BIGNUM pointer for x coordinate of k * generator + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig memory for the DER encoded created signature + * \param siglen pointer to the length of the returned signature + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig buffer to hold the DER encoded signature + * \param siglen pointer to the length of the returned signature + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optional), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); + +/** Verifies that the given signature is valid ECDSA signature + * of the supplied hash value using the specified public key. + * \param type this parameter is ignored + * \param dgst pointer to the hash value + * \param dgstlen length of the hash value + * \param sig pointer to the DER encoded signature + * \param siglen length of the DER encoded signature + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); + +/** Returns the maximum length of the DER encoded signature + * \param eckey EC_KEY object + * \return numbers of bytes required for the DER encoded signature + */ +int ECDSA_size(const EC_KEY *eckey); + +/********************************************************************/ +/* EC_KEY_METHOD constructors, destructors, writers and accessors */ +/********************************************************************/ + +EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth); +void EC_KEY_METHOD_free(EC_KEY_METHOD *meth); +void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, + int (*init)(EC_KEY *key), + void (*finish)(EC_KEY *key), + int (*copy)(EC_KEY *dest, const EC_KEY *src), + int (*set_group)(EC_KEY *key, const EC_GROUP *grp), + int (*set_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (*set_public)(EC_KEY *key, + const EC_POINT *pub_key)); + +void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, + int (*keygen)(EC_KEY *key)); + +void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, + int (*ckey)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)); + +void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, + int (*sign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)); + +void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, + int (*verify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (*verify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)); + +void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, + int (**pinit)(EC_KEY *key), + void (**pfinish)(EC_KEY *key), + int (**pcopy)(EC_KEY *dest, const EC_KEY *src), + int (**pset_group)(EC_KEY *key, + const EC_GROUP *grp), + int (**pset_private)(EC_KEY *key, + const BIGNUM *priv_key), + int (**pset_public)(EC_KEY *key, + const EC_POINT *pub_key)); + +void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, + int (**pkeygen)(EC_KEY *key)); + +void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, + int (**pck)(unsigned char **psec, + size_t *pseclen, + const EC_POINT *pub_key, + const EC_KEY *ecdh)); + +void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, + int (**psign)(int type, const unsigned char *dgst, + int dlen, unsigned char *sig, + unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey), + int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, + int dgst_len, + const BIGNUM *in_kinv, + const BIGNUM *in_r, + EC_KEY *eckey)); + +void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + int (**pverify)(int type, const unsigned + char *dgst, int dgst_len, + const unsigned char *sigbuf, + int sig_len, EC_KEY *eckey), + int (**pverify_sig)(const unsigned char *dgst, + int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)); + +# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x) + +# ifndef __cplusplus +# if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +# endif +# endif + +# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) + +# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) + +# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) + +# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \ + (void *)(plen)) + +# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p)) + +# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p)) + +/* SM2 will skip the operation check so no need to pass operation here */ +# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) + +# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) +/* KDF types */ +# define EVP_PKEY_ECDH_KDF_NONE 1 +# define EVP_PKEY_ECDH_KDF_X9_63 2 +/** The old name for EVP_PKEY_ECDH_KDF_X9_63 + * The ECDH KDF specification has been mistakingly attributed to ANSI X9.62, + * it is actually specified in ANSI X9.63. + * This identifier is retained for backwards compatibility + */ +# define EVP_PKEY_ECDH_KDF_X9_62 EVP_PKEY_ECDH_KDF_X9_63 + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/ecdh.h b/thirdparty/user_include/openssl/ecdh.h new file mode 100755 index 0000000000000000000000000000000000000000..681f3d5e557401876f9816109d8e705024ef53ca --- /dev/null +++ b/thirdparty/user_include/openssl/ecdh.h @@ -0,0 +1,10 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include diff --git a/thirdparty/user_include/openssl/ecdsa.h b/thirdparty/user_include/openssl/ecdsa.h new file mode 100755 index 0000000000000000000000000000000000000000..681f3d5e557401876f9816109d8e705024ef53ca --- /dev/null +++ b/thirdparty/user_include/openssl/ecdsa.h @@ -0,0 +1,10 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include diff --git a/thirdparty/user_include/openssl/ecerr.h b/thirdparty/user_include/openssl/ecerr.h new file mode 100755 index 0000000000000000000000000000000000000000..be313d2856b89ab5a24e0c9c7604a2168f9b6a29 --- /dev/null +++ b/thirdparty/user_include/openssl/ecerr.h @@ -0,0 +1,271 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ECERR_H +# define HEADER_ECERR_H + +# include + +# ifndef OPENSSL_NO_EC + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_EC_strings(void); + +/* + * EC function codes. + */ +# define EC_F_BN_TO_FELEM 224 +# define EC_F_D2I_ECPARAMETERS 144 +# define EC_F_D2I_ECPKPARAMETERS 145 +# define EC_F_D2I_ECPRIVATEKEY 146 +# define EC_F_DO_EC_KEY_PRINT 221 +# define EC_F_ECDH_CMS_DECRYPT 238 +# define EC_F_ECDH_CMS_SET_SHARED_INFO 239 +# define EC_F_ECDH_COMPUTE_KEY 246 +# define EC_F_ECDH_SIMPLE_COMPUTE_KEY 257 +# define EC_F_ECDSA_DO_SIGN_EX 251 +# define EC_F_ECDSA_DO_VERIFY 252 +# define EC_F_ECDSA_SIGN_EX 254 +# define EC_F_ECDSA_SIGN_SETUP 248 +# define EC_F_ECDSA_SIG_NEW 265 +# define EC_F_ECDSA_VERIFY 253 +# define EC_F_ECD_ITEM_VERIFY 270 +# define EC_F_ECKEY_PARAM2TYPE 223 +# define EC_F_ECKEY_PARAM_DECODE 212 +# define EC_F_ECKEY_PRIV_DECODE 213 +# define EC_F_ECKEY_PRIV_ENCODE 214 +# define EC_F_ECKEY_PUB_DECODE 215 +# define EC_F_ECKEY_PUB_ENCODE 216 +# define EC_F_ECKEY_TYPE2PARAM 220 +# define EC_F_ECPARAMETERS_PRINT 147 +# define EC_F_ECPARAMETERS_PRINT_FP 148 +# define EC_F_ECPKPARAMETERS_PRINT 149 +# define EC_F_ECPKPARAMETERS_PRINT_FP 150 +# define EC_F_ECP_NISTZ256_GET_AFFINE 240 +# define EC_F_ECP_NISTZ256_INV_MOD_ORD 275 +# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 243 +# define EC_F_ECP_NISTZ256_POINTS_MUL 241 +# define EC_F_ECP_NISTZ256_PRE_COMP_NEW 244 +# define EC_F_ECP_NISTZ256_WINDOWED_MUL 242 +# define EC_F_ECX_KEY_OP 266 +# define EC_F_ECX_PRIV_ENCODE 267 +# define EC_F_ECX_PUB_ENCODE 268 +# define EC_F_EC_ASN1_GROUP2CURVE 153 +# define EC_F_EC_ASN1_GROUP2FIELDID 154 +# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 +# define EC_F_EC_GF2M_SIMPLE_FIELD_INV 296 +# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 +# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 +# define EC_F_EC_GF2M_SIMPLE_LADDER_POST 285 +# define EC_F_EC_GF2M_SIMPLE_LADDER_PRE 288 +# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 +# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 +# define EC_F_EC_GF2M_SIMPLE_POINTS_MUL 289 +# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 +# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 +# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 +# define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +# define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +# define EC_F_EC_GFP_MONT_FIELD_INV 297 +# define EC_F_EC_GFP_MONT_FIELD_MUL 131 +# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 +# define EC_F_EC_GFP_MONT_FIELD_SQR 132 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 +# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 +# define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 +# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 +# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 +# define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 +# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 +# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 +# define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 +# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 +# define EC_F_EC_GFP_NIST_FIELD_MUL 200 +# define EC_F_EC_GFP_NIST_FIELD_SQR 201 +# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 +# define EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES 287 +# define EC_F_EC_GFP_SIMPLE_FIELD_INV 298 +# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 +# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +# define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +# define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 +# define EC_F_EC_GROUP_CHECK 170 +# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 +# define EC_F_EC_GROUP_COPY 106 +# define EC_F_EC_GROUP_GET_CURVE 291 +# define EC_F_EC_GROUP_GET_CURVE_GF2M 172 +# define EC_F_EC_GROUP_GET_CURVE_GFP 130 +# define EC_F_EC_GROUP_GET_DEGREE 173 +# define EC_F_EC_GROUP_GET_ECPARAMETERS 261 +# define EC_F_EC_GROUP_GET_ECPKPARAMETERS 262 +# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 +# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 +# define EC_F_EC_GROUP_NEW 108 +# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 +# define EC_F_EC_GROUP_NEW_FROM_DATA 175 +# define EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS 263 +# define EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS 264 +# define EC_F_EC_GROUP_SET_CURVE 292 +# define EC_F_EC_GROUP_SET_CURVE_GF2M 176 +# define EC_F_EC_GROUP_SET_CURVE_GFP 109 +# define EC_F_EC_GROUP_SET_GENERATOR 111 +# define EC_F_EC_GROUP_SET_SEED 286 +# define EC_F_EC_KEY_CHECK_KEY 177 +# define EC_F_EC_KEY_COPY 178 +# define EC_F_EC_KEY_GENERATE_KEY 179 +# define EC_F_EC_KEY_NEW 182 +# define EC_F_EC_KEY_NEW_METHOD 245 +# define EC_F_EC_KEY_OCT2PRIV 255 +# define EC_F_EC_KEY_PRINT 180 +# define EC_F_EC_KEY_PRINT_FP 181 +# define EC_F_EC_KEY_PRIV2BUF 279 +# define EC_F_EC_KEY_PRIV2OCT 256 +# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 +# define EC_F_EC_KEY_SIMPLE_CHECK_KEY 258 +# define EC_F_EC_KEY_SIMPLE_OCT2PRIV 259 +# define EC_F_EC_KEY_SIMPLE_PRIV2OCT 260 +# define EC_F_EC_PKEY_CHECK 273 +# define EC_F_EC_PKEY_PARAM_CHECK 274 +# define EC_F_EC_POINTS_MAKE_AFFINE 136 +# define EC_F_EC_POINTS_MUL 290 +# define EC_F_EC_POINT_ADD 112 +# define EC_F_EC_POINT_BN2POINT 280 +# define EC_F_EC_POINT_CMP 113 +# define EC_F_EC_POINT_COPY 114 +# define EC_F_EC_POINT_DBL 115 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES 293 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +# define EC_F_EC_POINT_INVERT 210 +# define EC_F_EC_POINT_IS_AT_INFINITY 118 +# define EC_F_EC_POINT_IS_ON_CURVE 119 +# define EC_F_EC_POINT_MAKE_AFFINE 120 +# define EC_F_EC_POINT_NEW 121 +# define EC_F_EC_POINT_OCT2POINT 122 +# define EC_F_EC_POINT_POINT2BUF 281 +# define EC_F_EC_POINT_POINT2OCT 123 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES 294 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES 295 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +# define EC_F_EC_POINT_SET_TO_INFINITY 127 +# define EC_F_EC_PRE_COMP_NEW 196 +# define EC_F_EC_SCALAR_MUL_LADDER 284 +# define EC_F_EC_WNAF_MUL 187 +# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +# define EC_F_I2D_ECPARAMETERS 190 +# define EC_F_I2D_ECPKPARAMETERS 191 +# define EC_F_I2D_ECPRIVATEKEY 192 +# define EC_F_I2O_ECPUBLICKEY 151 +# define EC_F_NISTP224_PRE_COMP_NEW 227 +# define EC_F_NISTP256_PRE_COMP_NEW 236 +# define EC_F_NISTP521_PRE_COMP_NEW 237 +# define EC_F_O2I_ECPUBLICKEY 152 +# define EC_F_OLD_EC_PRIV_DECODE 222 +# define EC_F_OSSL_ECDH_COMPUTE_KEY 247 +# define EC_F_OSSL_ECDSA_SIGN_SIG 249 +# define EC_F_OSSL_ECDSA_VERIFY_SIG 250 +# define EC_F_PKEY_ECD_CTRL 271 +# define EC_F_PKEY_ECD_DIGESTSIGN 272 +# define EC_F_PKEY_ECD_DIGESTSIGN25519 276 +# define EC_F_PKEY_ECD_DIGESTSIGN448 277 +# define EC_F_PKEY_ECX_DERIVE 269 +# define EC_F_PKEY_EC_CTRL 197 +# define EC_F_PKEY_EC_CTRL_STR 198 +# define EC_F_PKEY_EC_DERIVE 217 +# define EC_F_PKEY_EC_INIT 282 +# define EC_F_PKEY_EC_KDF_DERIVE 283 +# define EC_F_PKEY_EC_KEYGEN 199 +# define EC_F_PKEY_EC_PARAMGEN 219 +# define EC_F_PKEY_EC_SIGN 218 +# define EC_F_VALIDATE_ECX_DERIVE 278 + +/* + * EC reason codes. + */ +# define EC_R_ASN1_ERROR 115 +# define EC_R_BAD_SIGNATURE 156 +# define EC_R_BIGNUM_OUT_OF_RANGE 144 +# define EC_R_BUFFER_TOO_SMALL 100 +# define EC_R_CANNOT_INVERT 165 +# define EC_R_COORDINATES_OUT_OF_RANGE 146 +# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 +# define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 +# define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 +# define EC_R_DECODE_ERROR 142 +# define EC_R_DISCRIMINANT_IS_ZERO 118 +# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +# define EC_R_FIELD_TOO_LARGE 143 +# define EC_R_GF2M_NOT_SUPPORTED 147 +# define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 +# define EC_R_INCOMPATIBLE_OBJECTS 101 +# define EC_R_INVALID_ARGUMENT 112 +# define EC_R_INVALID_COMPRESSED_POINT 110 +# define EC_R_INVALID_COMPRESSION_BIT 109 +# define EC_R_INVALID_CURVE 141 +# define EC_R_INVALID_DIGEST 151 +# define EC_R_INVALID_DIGEST_TYPE 138 +# define EC_R_INVALID_ENCODING 102 +# define EC_R_INVALID_FIELD 103 +# define EC_R_INVALID_FORM 104 +# define EC_R_INVALID_GROUP_ORDER 122 +# define EC_R_INVALID_KEY 116 +# define EC_R_INVALID_OUTPUT_LENGTH 161 +# define EC_R_INVALID_PEER_KEY 133 +# define EC_R_INVALID_PENTANOMIAL_BASIS 132 +# define EC_R_INVALID_PRIVATE_KEY 123 +# define EC_R_INVALID_TRINOMIAL_BASIS 137 +# define EC_R_KDF_PARAMETER_ERROR 148 +# define EC_R_KEYS_NOT_SET 140 +# define EC_R_LADDER_POST_FAILURE 136 +# define EC_R_LADDER_PRE_FAILURE 153 +# define EC_R_LADDER_STEP_FAILURE 162 +# define EC_R_MISSING_PARAMETERS 124 +# define EC_R_MISSING_PRIVATE_KEY 125 +# define EC_R_NEED_NEW_SETUP_VALUES 157 +# define EC_R_NOT_A_NIST_PRIME 135 +# define EC_R_NOT_IMPLEMENTED 126 +# define EC_R_NOT_INITIALIZED 111 +# define EC_R_NO_PARAMETERS_SET 139 +# define EC_R_NO_PRIVATE_VALUE 154 +# define EC_R_OPERATION_NOT_SUPPORTED 152 +# define EC_R_PASSED_NULL_PARAMETER 134 +# define EC_R_PEER_KEY_ERROR 149 +# define EC_R_PKPARAMETERS2GROUP_FAILURE 127 +# define EC_R_POINT_ARITHMETIC_FAILURE 155 +# define EC_R_POINT_AT_INFINITY 106 +# define EC_R_POINT_COORDINATES_BLIND_FAILURE 163 +# define EC_R_POINT_IS_NOT_ON_CURVE 107 +# define EC_R_RANDOM_NUMBER_GENERATION_FAILED 158 +# define EC_R_SHARED_INFO_ERROR 150 +# define EC_R_SLOT_FULL 108 +# define EC_R_UNDEFINED_GENERATOR 113 +# define EC_R_UNDEFINED_ORDER 128 +# define EC_R_UNKNOWN_COFACTOR 164 +# define EC_R_UNKNOWN_GROUP 129 +# define EC_R_UNKNOWN_ORDER 114 +# define EC_R_UNSUPPORTED_FIELD 131 +# define EC_R_WRONG_CURVE_PARAMETERS 145 +# define EC_R_WRONG_ORDER 130 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/engine.h b/thirdparty/user_include/openssl/engine.h new file mode 100755 index 0000000000000000000000000000000000000000..0780f0fb5f327db9782995e9b94440e065555465 --- /dev/null +++ b/thirdparty/user_include/openssl/engine.h @@ -0,0 +1,751 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENGINE_H +# define HEADER_ENGINE_H + +# include + +# ifndef OPENSSL_NO_ENGINE +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# include +# include +# include +# include +# include +# endif +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* + * These flags are used to control combinations of algorithm (methods) by + * bitwise "OR"ing. + */ +# define ENGINE_METHOD_RSA (unsigned int)0x0001 +# define ENGINE_METHOD_DSA (unsigned int)0x0002 +# define ENGINE_METHOD_DH (unsigned int)0x0004 +# define ENGINE_METHOD_RAND (unsigned int)0x0008 +# define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 +# define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 +# define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200 +# define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400 +# define ENGINE_METHOD_EC (unsigned int)0x0800 +/* Obvious all-or-nothing cases. */ +# define ENGINE_METHOD_ALL (unsigned int)0xFFFF +# define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* + * This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used + * internally to control registration of ENGINE implementations, and can be + * set by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to + * initialise registered ENGINEs if they are not already initialised. + */ +# define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001 + +/* ENGINE flags that can be set by ENGINE_set_flags(). */ +/* Not used */ +/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ + +/* + * This flag is for ENGINEs that wish to handle the various 'CMD'-related + * control commands on their own. Without this flag, ENGINE_ctrl() handles + * these control commands on behalf of the ENGINE using their "cmd_defns" + * data. + */ +# define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 + +/* + * This flag is for ENGINEs who return new duplicate structures when found + * via "ENGINE_by_id()". When an ENGINE must store state (eg. if + * ENGINE_ctrl() commands are called in sequence as part of some stateful + * process like key-generation setup and execution), it can set this flag - + * then each attempt to obtain the ENGINE will result in it being copied into + * a new structure. Normally, ENGINEs don't declare this flag so + * ENGINE_by_id() just increments the existing ENGINE's structural reference + * count. + */ +# define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + +/* + * This flag if for an ENGINE that does not want its methods registered as + * part of ENGINE_register_all_complete() for example if the methods are not + * usable as default methods. + */ + +# define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008 + +/* + * ENGINEs can support their own command types, and these flags are used in + * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input + * each command expects. Currently only numeric and string input is + * supported. If a control command supports none of the _NUMERIC, _STRING, or + * _NO_INPUT options, then it is regarded as an "internal" control command - + * and not for use in config setting situations. As such, they're not + * available to the ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() + * access. Changes to this list of 'command types' should be reflected + * carefully in ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). + */ + +/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */ +# define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +/* + * accepts string input (cast from 'void*' to 'const char *', 4th parameter + * to ENGINE_ctrl) + */ +# define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +/* + * Indicates that the control command takes *no* input. Ie. the control + * command is unparameterised. + */ +# define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +/* + * Indicates that the control command is internal. This control command won't + * be shown in any output, and is only usable through the ENGINE_ctrl_cmd() + * function. + */ +# define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +/* + * NB: These 3 control commands are deprecated and should not be used. + * ENGINEs relying on these commands should compile conditional support for + * compatibility (eg. if these symbols are defined) but should also migrate + * the same functionality to their own ENGINE-specific control functions that + * can be "discovered" by calling applications. The fact these control + * commands wouldn't be "executable" (ie. usable by text-based config) + * doesn't change the fact that application code can find and use them + * without requiring per-ENGINE hacking. + */ + +/* + * These flags are used to tell the ctrl function what should be done. All + * command numbers are shared between all engines, even if some don't make + * sense to some engines. In such a case, they do nothing but return the + * error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. + */ +# define ENGINE_CTRL_SET_LOGSTREAM 1 +# define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +# define ENGINE_CTRL_HUP 3/* Close and reinitialise + * any handles/connections + * etc. */ +# define ENGINE_CTRL_SET_USER_INTERFACE 4/* Alternative to callback */ +# define ENGINE_CTRL_SET_CALLBACK_DATA 5/* User-specific data, used + * when calling the password + * callback and the user + * interface */ +# define ENGINE_CTRL_LOAD_CONFIGURATION 6/* Load a configuration, + * given a string that + * represents a file name + * or so */ +# define ENGINE_CTRL_LOAD_SECTION 7/* Load data from a given + * section in the already + * loaded configuration */ + +/* + * These control commands allow an application to deal with an arbitrary + * engine in a dynamic way. Warn: Negative return values indicate errors FOR + * THESE COMMANDS because zero is used to indicate 'end-of-list'. Other + * commands, including ENGINE-specific command types, return zero for an + * error. An ENGINE can choose to implement these ctrl functions, and can + * internally manage things however it chooses - it does so by setting the + * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise + * the ENGINE_ctrl() code handles this on the ENGINE's behalf using the + * cmd_defns data (set using ENGINE_set_cmd_defns()). This means an ENGINE's + * ctrl() handler need only implement its own commands - the above "meta" + * commands will be taken care of. + */ + +/* + * Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", + * then all the remaining control commands will return failure, so it is + * worth checking this first if the caller is trying to "discover" the + * engine's capabilities and doesn't want errors generated unnecessarily. + */ +# define ENGINE_CTRL_HAS_CTRL_FUNCTION 10 +/* + * Returns a positive command number for the first command supported by the + * engine. Returns zero if no ctrl commands are supported. + */ +# define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +/* + * The 'long' argument specifies a command implemented by the engine, and the + * return value is the next command supported, or zero if there are no more. + */ +# define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +/* + * The 'void*' argument is a command name (cast from 'const char *'), and the + * return value is the command that corresponds to it. + */ +# define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +/* + * The next two allow a command to be converted into its corresponding string + * form. In each case, the 'long' argument supplies the command. In the + * NAME_LEN case, the return value is the length of the command name (not + * counting a trailing EOL). In the NAME case, the 'void*' argument must be a + * string buffer large enough, and it will be populated with the name of the + * command (WITH a trailing EOL). + */ +# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +# define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +/* The next two are similar but give a "short description" of a command. */ +# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +# define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +/* + * With this command, the return value is the OR'd combination of + * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given + * engine-specific ctrl command expects. + */ +# define ENGINE_CTRL_GET_CMD_FLAGS 18 + +/* + * ENGINE implementations should start the numbering of their own control + * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). + */ +# define ENGINE_CMD_BASE 200 + +/* + * NB: These 2 nCipher "chil" control commands are deprecated, and their + * functionality is now available through ENGINE-specific control commands + * (exposed through the above-mentioned 'CMD'-handling). Code using these 2 + * commands should be migrated to the more general command handling before + * these are removed. + */ + +/* Flags specific to the nCipher "chil" engine */ +# define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 + /* + * Depending on the value of the (long)i argument, this sets or + * unsets the SimpleForkCheck flag in the CHIL API to enable or + * disable checking and workarounds for applications that fork(). + */ +# define ENGINE_CTRL_CHIL_NO_LOCKING 101 + /* + * This prevents the initialisation function from providing mutex + * callbacks to the nCipher library. + */ + +/* + * If an ENGINE supports its own specific control commands and wishes the + * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on + * its behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN + * entries to ENGINE_set_cmd_defns(). It should also implement a ctrl() + * handler that supports the stated commands (ie. the "cmd_num" entries as + * described by the array). NB: The array must be ordered in increasing order + * of cmd_num. "null-terminated" means that the last ENGINE_CMD_DEFN element + * has cmd_num set to zero and/or cmd_name set to NULL. + */ +typedef struct ENGINE_CMD_DEFN_st { + unsigned int cmd_num; /* The command number */ + const char *cmd_name; /* The command name itself */ + const char *cmd_desc; /* A short description of the command */ + unsigned int cmd_flags; /* The input the command expects */ +} ENGINE_CMD_DEFN; + +/* Generic function pointer */ +typedef int (*ENGINE_GEN_FUNC_PTR) (void); +/* Generic function pointer taking no arguments */ +typedef int (*ENGINE_GEN_INT_FUNC_PTR) (ENGINE *); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR) (ENGINE *, int, long, void *, + void (*f) (void)); +/* Generic load_key function pointer */ +typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, + UI_METHOD *ui_method, + void *callback_data); +typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, + X509 **pcert, EVP_PKEY **pkey, + STACK_OF(X509) **pother, + UI_METHOD *ui_method, + void *callback_data); +/*- + * These callback types are for an ENGINE's handler for cipher and digest logic. + * These handlers have these prototypes; + * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); + * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); + * Looking at how to implement these handlers in the case of cipher support, if + * the framework wants the EVP_CIPHER for 'nid', it will call; + * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure) + * If the framework wants a list of supported 'nid's, it will call; + * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error) + */ +/* + * Returns to a pointer to the array of supported cipher 'nid's. If the + * second parameter is non-NULL it is set to the size of the returned array. + */ +typedef int (*ENGINE_CIPHERS_PTR) (ENGINE *, const EVP_CIPHER **, + const int **, int); +typedef int (*ENGINE_DIGESTS_PTR) (ENGINE *, const EVP_MD **, const int **, + int); +typedef int (*ENGINE_PKEY_METHS_PTR) (ENGINE *, EVP_PKEY_METHOD **, + const int **, int); +typedef int (*ENGINE_PKEY_ASN1_METHS_PTR) (ENGINE *, EVP_PKEY_ASN1_METHOD **, + const int **, int); +/* + * STRUCTURE functions ... all of these functions deal with pointers to + * ENGINE structures where the pointers have a "structural reference". This + * means that their reference is to allowed access to the structure but it + * does not imply that the structure is functional. To simply increment or + * decrement the structural reference count, use ENGINE_by_id and + * ENGINE_free. NB: This is not required when iterating using ENGINE_get_next + * as it will automatically decrement the structural reference count of the + * "current" ENGINE and increment the structural reference count of the + * ENGINE it returns (unless it is NULL). + */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define ENGINE_load_openssl() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_OPENSSL, NULL) +# define ENGINE_load_dynamic() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL) +# ifndef OPENSSL_NO_STATIC_ENGINE +# define ENGINE_load_padlock() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_PADLOCK, NULL) +# define ENGINE_load_capi() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL) +# define ENGINE_load_afalg() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL) +# endif +# define ENGINE_load_cryptodev() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL) +# define ENGINE_load_rdrand() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_RDRAND, NULL) +#endif +void ENGINE_load_builtin_engines(void); + +/* + * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation + * "registry" handling. + */ +unsigned int ENGINE_get_table_flags(void); +void ENGINE_set_table_flags(unsigned int flags); + +/*- Manage registration of ENGINEs per "table". For each type, there are 3 + * functions; + * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one) + * ENGINE_unregister_***(e) - unregister the implementation from 'e' + * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list + * Cleanup is automatically registered from each table when required. + */ + +int ENGINE_register_RSA(ENGINE *e); +void ENGINE_unregister_RSA(ENGINE *e); +void ENGINE_register_all_RSA(void); + +int ENGINE_register_DSA(ENGINE *e); +void ENGINE_unregister_DSA(ENGINE *e); +void ENGINE_register_all_DSA(void); + +int ENGINE_register_EC(ENGINE *e); +void ENGINE_unregister_EC(ENGINE *e); +void ENGINE_register_all_EC(void); + +int ENGINE_register_DH(ENGINE *e); +void ENGINE_unregister_DH(ENGINE *e); +void ENGINE_register_all_DH(void); + +int ENGINE_register_RAND(ENGINE *e); +void ENGINE_unregister_RAND(ENGINE *e); +void ENGINE_register_all_RAND(void); + +int ENGINE_register_ciphers(ENGINE *e); +void ENGINE_unregister_ciphers(ENGINE *e); +void ENGINE_register_all_ciphers(void); + +int ENGINE_register_digests(ENGINE *e); +void ENGINE_unregister_digests(ENGINE *e); +void ENGINE_register_all_digests(void); + +int ENGINE_register_pkey_meths(ENGINE *e); +void ENGINE_unregister_pkey_meths(ENGINE *e); +void ENGINE_register_all_pkey_meths(void); + +int ENGINE_register_pkey_asn1_meths(ENGINE *e); +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e); +void ENGINE_register_all_pkey_asn1_meths(void); + +/* + * These functions register all support from the above categories. Note, use + * of these functions can result in static linkage of code your application + * may not need. If you only need a subset of functionality, consider using + * more selective initialisation. + */ +int ENGINE_register_complete(ENGINE *e); +int ENGINE_register_all_complete(void); + +/* + * Send parameterised control commands to the engine. The possibilities to + * send down an integer, a pointer to data or a function pointer are + * provided. Any of the parameters may or may not be NULL, depending on the + * command number. In actuality, this function only requires a structural + * (rather than functional) reference to an engine, but many control commands + * may require the engine be functional. The caller should be aware of trying + * commands that require an operational ENGINE, and only use functional + * references in such situations. + */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); + +/* + * This function tests if an ENGINE-specific command is usable as a + * "setting". Eg. in an application's config file that gets processed through + * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to + * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). + */ +int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + +/* + * This function works like ENGINE_ctrl() with the exception of taking a + * command name instead of a command number, and can handle optional + * commands. See the comment on ENGINE_ctrl_cmd_string() for an explanation + * on how to use the cmd_name and cmd_optional. + */ +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f) (void), int cmd_optional); + +/* + * This function passes a command-name and argument to an ENGINE. The + * cmd_name is converted to a command number and the control command is + * called using 'arg' as an argument (unless the ENGINE doesn't support such + * a command, in which case no control command is called). The command is + * checked for input flags, and if necessary the argument will be converted + * to a numeric value. If cmd_optional is non-zero, then if the ENGINE + * doesn't support the given cmd_name the return value will be success + * anyway. This function is intended for applications to use so that users + * (or config files) can supply engine-specific config data to the ENGINE at + * run-time to control behaviour of specific engines. As such, it shouldn't + * be used for calling ENGINE_ctrl() functions that return data, deal with + * binary data, or that are otherwise supposed to be used directly through + * ENGINE_ctrl() in application code. Any "return" data from an ENGINE_ctrl() + * operation in this function will be lost - the return value is interpreted + * as failure if the return value is zero, success otherwise, and this + * function returns a boolean value as a result. In other words, vendors of + * 'ENGINE'-enabled devices should write ENGINE implementations with + * parameterisations that work in this scheme, so that compliant ENGINE-based + * applications can work consistently with the same configuration for the + * same ENGINE-enabled devices, across applications. + */ +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + +/* + * These functions are useful for manufacturing new ENGINE structures. They + * don't address reference counting at all - one uses them to populate an + * ENGINE structure with personalised implementations of things prior to + * using it directly or adding it to the builtin ENGINE list in OpenSSL. + * These are also here so that the ENGINE structure doesn't have to be + * exposed and break binary compatibility! + */ +ENGINE *ENGINE_new(void); +int ENGINE_free(ENGINE *e); +int ENGINE_up_ref(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); +int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ecdsa_meth); +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); +int ENGINE_set_load_privkey_function(ENGINE *e, + ENGINE_LOAD_KEY_PTR loadpriv_f); +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); +int ENGINE_set_load_ssl_client_cert_function(ENGINE *e, + ENGINE_SSL_CLIENT_CERT_PTR + loadssl_f); +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f); +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f); +int ENGINE_set_flags(ENGINE *e, int flags); +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); +/* These functions allow control over any per-structure ENGINE data. */ +#define ENGINE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, l, p, newf, dupf, freef) +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); + +#if OPENSSL_API_COMPAT < 0x10100000L +/* + * This function previously cleaned up anything that needs it. Auto-deinit will + * now take care of it so it is no longer required to call this function. + */ +# define ENGINE_cleanup() while(0) continue +#endif + +/* + * These return values from within the ENGINE structure. These can be useful + * with functional references as well as structural references - it depends + * which you obtained. Using the result for functional purposes if you only + * obtained a structural reference may be problematic! + */ +const char *ENGINE_get_id(const ENGINE *e); +const char *ENGINE_get_name(const ENGINE *e); +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); +const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e); +const DH_METHOD *ENGINE_get_DH(const ENGINE *e); +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); +ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE + *e); +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e); +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e); +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, + const char *str, + int len); +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, + int len); +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); +int ENGINE_get_flags(const ENGINE *e); + +/* + * FUNCTIONAL functions. These functions deal with ENGINE structures that + * have (or will) be initialised for use. Broadly speaking, the structural + * functions are useful for iterating the list of available engine types, + * creating new engine types, and other "list" operations. These functions + * actually deal with ENGINEs that are to be used. As such these functions + * can fail (if applicable) when particular engines are unavailable - eg. if + * a hardware accelerator is not attached or not functioning correctly. Each + * ENGINE has 2 reference counts; structural and functional. Every time a + * functional reference is obtained or released, a corresponding structural + * reference is automatically obtained or released too. + */ + +/* + * Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently operational + * and cannot initialise. + */ +int ENGINE_init(ENGINE *e); +/* + * Free a functional reference to a engine type. This does not require a + * corresponding call to ENGINE_free as it also releases a structural + * reference. + */ +int ENGINE_finish(ENGINE *e); + +/* + * The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. + */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **ppkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, void *callback_data); + +/* + * This returns a pointer for the current ENGINE structure that is (by + * default) performing any RSA operations. The value returned is an + * incremented reference, so it should be free'd (ENGINE_finish) before it is + * discarded. + */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_EC(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +/* + * These functions can be used to get a functional reference to perform + * ciphering or digesting corresponding to "nid". + */ +ENGINE *ENGINE_get_cipher_engine(int nid); +ENGINE *ENGINE_get_digest_engine(int nid); +ENGINE *ENGINE_get_pkey_meth_engine(int nid); +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid); + +/* + * This sets a new default ENGINE structure for performing RSA operations. If + * the result is non-zero (success) then the ENGINE structure will have had + * its reference count up'd so the caller should still free their own + * reference 'e'. + */ +int ENGINE_set_default_RSA(ENGINE *e); +int ENGINE_set_default_string(ENGINE *e, const char *def_list); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_EC(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_ciphers(ENGINE *e); +int ENGINE_set_default_digests(ENGINE *e); +int ENGINE_set_default_pkey_meths(ENGINE *e); +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e); + +/* + * The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()" + * function, this function can result in unnecessary static linkage. If your + * application requires only specific functionality, consider using more + * selective functions. + */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +void ENGINE_add_conf_module(void); + +/* Deprecated functions ... */ +/* int ENGINE_clear_defaults(void); */ + +/**************************/ +/* DYNAMIC ENGINE SUPPORT */ +/**************************/ + +/* Binary/behaviour compatibility levels */ +# define OSSL_DYNAMIC_VERSION (unsigned long)0x00030000 +/* + * Binary versions older than this are too old for us (whether we're a loader + * or a loadee) + */ +# define OSSL_DYNAMIC_OLDEST (unsigned long)0x00030000 + +/* + * When compiling an ENGINE entirely as an external shared library, loadable + * by the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' + * structure type provides the calling application's (or library's) error + * functionality and memory management function pointers to the loaded + * library. These should be used/set in the loaded library code so that the + * loading application's 'state' will be used/changed in all operations. The + * 'static_state' pointer allows the loaded library to know if it shares the + * same static data as the calling application (or library), and thus whether + * these callbacks need to be set or not. + */ +typedef void *(*dyn_MEM_malloc_fn) (size_t, const char *, int); +typedef void *(*dyn_MEM_realloc_fn) (void *, size_t, const char *, int); +typedef void (*dyn_MEM_free_fn) (void *, const char *, int); +typedef struct st_dynamic_MEM_fns { + dyn_MEM_malloc_fn malloc_fn; + dyn_MEM_realloc_fn realloc_fn; + dyn_MEM_free_fn free_fn; +} dynamic_MEM_fns; +/* + * FIXME: Perhaps the memory and locking code (crypto.h) should declare and + * use these types so we (and any other dependent code) can simplify a bit?? + */ +/* The top-level structure */ +typedef struct st_dynamic_fns { + void *static_state; + dynamic_MEM_fns mem_fns; +} dynamic_fns; + +/* + * The version checking function should be of this prototype. NB: The + * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading + * code. If this function returns zero, it indicates a (potential) version + * incompatibility and the loaded library doesn't believe it can proceed. + * Otherwise, the returned value is the (latest) version supported by the + * loading library. The loader may still decide that the loaded code's + * version is unsatisfactory and could veto the load. The function is + * expected to be implemented with the symbol name "v_check", and a default + * implementation can be fully instantiated with + * IMPLEMENT_DYNAMIC_CHECK_FN(). + */ +typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version); +# define IMPLEMENT_DYNAMIC_CHECK_FN() \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v); \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \ + if (v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ + return 0; } + +/* + * This function is passed the ENGINE structure to initialise with its own + * function and command settings. It should not adjust the structural or + * functional reference counts. If this function returns zero, (a) the load + * will be aborted, (b) the previous ENGINE state will be memcpy'd back onto + * the structure, and (c) the shared library will be unloaded. So + * implementations should do their own internal cleanup in failure + * circumstances otherwise they could leak. The 'id' parameter, if non-NULL, + * represents the ENGINE id that the loader is looking for. If this is NULL, + * the shared library can choose to return failure or to initialise a + * 'default' ENGINE. If non-NULL, the shared library must initialise only an + * ENGINE matching the passed 'id'. The function is expected to be + * implemented with the symbol name "bind_engine". A standard implementation + * can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where the parameter + * 'fn' is a callback function that populates the ENGINE structure and + * returns an int value (zero for failure). 'fn' should have prototype; + * [static] int fn(ENGINE *e, const char *id); + */ +typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id, + const dynamic_fns *fns); +# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ + if (ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \ + CRYPTO_set_mem_functions(fns->mem_fns.malloc_fn, \ + fns->mem_fns.realloc_fn, \ + fns->mem_fns.free_fn); \ + skip_cbs: \ + if (!fn(e, id)) return 0; \ + return 1; } + +/* + * If the loading application (or library) and the loaded ENGINE library + * share the same static data (eg. they're both dynamically linked to the + * same libcrypto.so) we need a way to avoid trying to set system callbacks - + * this would fail, and for the same reason that it's unnecessary to try. If + * the loaded ENGINE has (or gets from through the loader) its own copy of + * the libcrypto static data, we will need to set the callbacks. The easiest + * way to detect this is to have a function that returns a pointer to some + * static data and let the loading application and loaded ENGINE compare + * their respective values. + */ +void *ENGINE_get_static_state(void); + +# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +DEPRECATEDIN_1_1_0(void ENGINE_setup_bsd_cryptodev(void)) +# endif + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/engineerr.h b/thirdparty/user_include/openssl/engineerr.h new file mode 100755 index 0000000000000000000000000000000000000000..b4c036b2106eeb955f46f2218be8ef82badad5b4 --- /dev/null +++ b/thirdparty/user_include/openssl/engineerr.h @@ -0,0 +1,107 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENGINEERR_H +# define HEADER_ENGINEERR_H + +# include + +# ifndef OPENSSL_NO_ENGINE + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_ENGINE_strings(void); + +/* + * ENGINE function codes. + */ +# define ENGINE_F_DIGEST_UPDATE 198 +# define ENGINE_F_DYNAMIC_CTRL 180 +# define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 +# define ENGINE_F_DYNAMIC_LOAD 182 +# define ENGINE_F_DYNAMIC_SET_DATA_CTX 183 +# define ENGINE_F_ENGINE_ADD 105 +# define ENGINE_F_ENGINE_BY_ID 106 +# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 +# define ENGINE_F_ENGINE_CTRL 142 +# define ENGINE_F_ENGINE_CTRL_CMD 178 +# define ENGINE_F_ENGINE_CTRL_CMD_STRING 171 +# define ENGINE_F_ENGINE_FINISH 107 +# define ENGINE_F_ENGINE_GET_CIPHER 185 +# define ENGINE_F_ENGINE_GET_DIGEST 186 +# define ENGINE_F_ENGINE_GET_FIRST 195 +# define ENGINE_F_ENGINE_GET_LAST 196 +# define ENGINE_F_ENGINE_GET_NEXT 115 +# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193 +# define ENGINE_F_ENGINE_GET_PKEY_METH 192 +# define ENGINE_F_ENGINE_GET_PREV 116 +# define ENGINE_F_ENGINE_INIT 119 +# define ENGINE_F_ENGINE_LIST_ADD 120 +# define ENGINE_F_ENGINE_LIST_REMOVE 121 +# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194 +# define ENGINE_F_ENGINE_NEW 122 +# define ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR 197 +# define ENGINE_F_ENGINE_REMOVE 123 +# define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189 +# define ENGINE_F_ENGINE_SET_ID 129 +# define ENGINE_F_ENGINE_SET_NAME 130 +# define ENGINE_F_ENGINE_TABLE_REGISTER 184 +# define ENGINE_F_ENGINE_UNLOCKED_FINISH 191 +# define ENGINE_F_ENGINE_UP_REF 190 +# define ENGINE_F_INT_CLEANUP_ITEM 199 +# define ENGINE_F_INT_CTRL_HELPER 172 +# define ENGINE_F_INT_ENGINE_CONFIGURE 188 +# define ENGINE_F_INT_ENGINE_MODULE_INIT 187 +# define ENGINE_F_OSSL_HMAC_INIT 200 + +/* + * ENGINE reason codes. + */ +# define ENGINE_R_ALREADY_LOADED 100 +# define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133 +# define ENGINE_R_CMD_NOT_EXECUTABLE 134 +# define ENGINE_R_COMMAND_TAKES_INPUT 135 +# define ENGINE_R_COMMAND_TAKES_NO_INPUT 136 +# define ENGINE_R_CONFLICTING_ENGINE_ID 103 +# define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +# define ENGINE_R_DSO_FAILURE 104 +# define ENGINE_R_DSO_NOT_FOUND 132 +# define ENGINE_R_ENGINES_SECTION_ERROR 148 +# define ENGINE_R_ENGINE_CONFIGURATION_ERROR 102 +# define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +# define ENGINE_R_ENGINE_SECTION_ERROR 149 +# define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +# define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +# define ENGINE_R_FINISH_FAILED 106 +# define ENGINE_R_ID_OR_NAME_MISSING 108 +# define ENGINE_R_INIT_FAILED 109 +# define ENGINE_R_INTERNAL_LIST_ERROR 110 +# define ENGINE_R_INVALID_ARGUMENT 143 +# define ENGINE_R_INVALID_CMD_NAME 137 +# define ENGINE_R_INVALID_CMD_NUMBER 138 +# define ENGINE_R_INVALID_INIT_VALUE 151 +# define ENGINE_R_INVALID_STRING 150 +# define ENGINE_R_NOT_INITIALISED 117 +# define ENGINE_R_NOT_LOADED 112 +# define ENGINE_R_NO_CONTROL_FUNCTION 120 +# define ENGINE_R_NO_INDEX 144 +# define ENGINE_R_NO_LOAD_FUNCTION 125 +# define ENGINE_R_NO_REFERENCE 130 +# define ENGINE_R_NO_SUCH_ENGINE 116 +# define ENGINE_R_UNIMPLEMENTED_CIPHER 146 +# define ENGINE_R_UNIMPLEMENTED_DIGEST 147 +# define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD 101 +# define ENGINE_R_VERSION_INCOMPATIBILITY 145 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/err.h b/thirdparty/user_include/openssl/err.h new file mode 100755 index 0000000000000000000000000000000000000000..6cae1a36510fb5be7507e292d1c7c4ed23af2c71 --- /dev/null +++ b/thirdparty/user_include/openssl/err.h @@ -0,0 +1,273 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ERR_H +# define HEADER_ERR_H + +# include + +# ifndef OPENSSL_NO_STDIO +# include +# include +# endif + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_NO_ERR +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e) +# else +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0) +# endif + +# include + +# define ERR_TXT_MALLOCED 0x01 +# define ERR_TXT_STRING 0x02 + +# define ERR_FLAG_MARK 0x01 + +# define ERR_NUM_ERRORS 16 +typedef struct err_state_st { + int err_flags[ERR_NUM_ERRORS]; + unsigned long err_buffer[ERR_NUM_ERRORS]; + char *err_data[ERR_NUM_ERRORS]; + int err_data_flags[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; + int err_line[ERR_NUM_ERRORS]; + int top, bottom; +} ERR_STATE; + +/* library */ +# define ERR_LIB_NONE 1 +# define ERR_LIB_SYS 2 +# define ERR_LIB_BN 3 +# define ERR_LIB_RSA 4 +# define ERR_LIB_DH 5 +# define ERR_LIB_EVP 6 +# define ERR_LIB_BUF 7 +# define ERR_LIB_OBJ 8 +# define ERR_LIB_PEM 9 +# define ERR_LIB_DSA 10 +# define ERR_LIB_X509 11 +/* #define ERR_LIB_METH 12 */ +# define ERR_LIB_ASN1 13 +# define ERR_LIB_CONF 14 +# define ERR_LIB_CRYPTO 15 +# define ERR_LIB_EC 16 +# define ERR_LIB_SSL 20 +/* #define ERR_LIB_SSL23 21 */ +/* #define ERR_LIB_SSL2 22 */ +/* #define ERR_LIB_SSL3 23 */ +/* #define ERR_LIB_RSAREF 30 */ +/* #define ERR_LIB_PROXY 31 */ +# define ERR_LIB_BIO 32 +# define ERR_LIB_PKCS7 33 +# define ERR_LIB_X509V3 34 +# define ERR_LIB_PKCS12 35 +# define ERR_LIB_RAND 36 +# define ERR_LIB_DSO 37 +# define ERR_LIB_ENGINE 38 +# define ERR_LIB_OCSP 39 +# define ERR_LIB_UI 40 +# define ERR_LIB_COMP 41 +# define ERR_LIB_ECDSA 42 +# define ERR_LIB_ECDH 43 +# define ERR_LIB_OSSL_STORE 44 +# define ERR_LIB_FIPS 45 +# define ERR_LIB_CMS 46 +# define ERR_LIB_TS 47 +# define ERR_LIB_HMAC 48 +/* # define ERR_LIB_JPAKE 49 */ +# define ERR_LIB_CT 50 +# define ERR_LIB_ASYNC 51 +# define ERR_LIB_KDF 52 +# define ERR_LIB_SM2 53 + +# define ERR_LIB_USER 128 + +# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define ASYNCerr(f,r) ERR_PUT_error(ERR_LIB_ASYNC,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE) + +# define ERR_PACK(l,f,r) ( \ + (((unsigned int)(l) & 0x0FF) << 24L) | \ + (((unsigned int)(f) & 0xFFF) << 12L) | \ + (((unsigned int)(r) & 0xFFF) ) ) +# define ERR_GET_LIB(l) (int)(((l) >> 24L) & 0x0FFL) +# define ERR_GET_FUNC(l) (int)(((l) >> 12L) & 0xFFFL) +# define ERR_GET_REASON(l) (int)( (l) & 0xFFFL) +# define ERR_FATAL_ERROR(l) (int)( (l) & ERR_R_FATAL) + +/* OS functions */ +# define SYS_F_FOPEN 1 +# define SYS_F_CONNECT 2 +# define SYS_F_GETSERVBYNAME 3 +# define SYS_F_SOCKET 4 +# define SYS_F_IOCTLSOCKET 5 +# define SYS_F_BIND 6 +# define SYS_F_LISTEN 7 +# define SYS_F_ACCEPT 8 +# define SYS_F_WSASTARTUP 9/* Winsock stuff */ +# define SYS_F_OPENDIR 10 +# define SYS_F_FREAD 11 +# define SYS_F_GETADDRINFO 12 +# define SYS_F_GETNAMEINFO 13 +# define SYS_F_SETSOCKOPT 14 +# define SYS_F_GETSOCKOPT 15 +# define SYS_F_GETSOCKNAME 16 +# define SYS_F_GETHOSTBYNAME 17 +# define SYS_F_FFLUSH 18 +# define SYS_F_OPEN 19 +# define SYS_F_CLOSE 20 +# define SYS_F_IOCTL 21 +# define SYS_F_STAT 22 +# define SYS_F_FCNTL 23 +# define SYS_F_FSTAT 24 + +/* reasons */ +# define ERR_R_SYS_LIB ERR_LIB_SYS/* 2 */ +# define ERR_R_BN_LIB ERR_LIB_BN/* 3 */ +# define ERR_R_RSA_LIB ERR_LIB_RSA/* 4 */ +# define ERR_R_DH_LIB ERR_LIB_DH/* 5 */ +# define ERR_R_EVP_LIB ERR_LIB_EVP/* 6 */ +# define ERR_R_BUF_LIB ERR_LIB_BUF/* 7 */ +# define ERR_R_OBJ_LIB ERR_LIB_OBJ/* 8 */ +# define ERR_R_PEM_LIB ERR_LIB_PEM/* 9 */ +# define ERR_R_DSA_LIB ERR_LIB_DSA/* 10 */ +# define ERR_R_X509_LIB ERR_LIB_X509/* 11 */ +# define ERR_R_ASN1_LIB ERR_LIB_ASN1/* 13 */ +# define ERR_R_EC_LIB ERR_LIB_EC/* 16 */ +# define ERR_R_BIO_LIB ERR_LIB_BIO/* 32 */ +# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */ +# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */ +# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */ +# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */ +# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */ +# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */ + +# define ERR_R_NESTED_ASN1_ERROR 58 +# define ERR_R_MISSING_ASN1_EOS 63 + +/* fatal error */ +# define ERR_R_FATAL 64 +# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) +# define ERR_R_DISABLED (5|ERR_R_FATAL) +# define ERR_R_INIT_FAIL (6|ERR_R_FATAL) +# define ERR_R_PASSED_INVALID_ARGUMENT (7) +# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL) + +/* + * 99 is the maximum possible ERR_R_... code, higher values are reserved for + * the individual libraries + */ + +typedef struct ERR_string_data_st { + unsigned long error; + const char *string; +} ERR_STRING_DATA; + +DEFINE_LHASH_OF(ERR_STRING_DATA); + +void ERR_put_error(int lib, int func, int reason, const char *file, int line); +void ERR_set_error_data(char *data, int flags); + +unsigned long ERR_get_error(void); +unsigned long ERR_get_error_line(const char **file, int *line); +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_error(void); +unsigned long ERR_peek_error_line(const char **file, int *line); +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_last_error(void); +unsigned long ERR_peek_last_error_line(const char **file, int *line); +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags); +void ERR_clear_error(void); +char *ERR_error_string(unsigned long e, char *buf); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +const char *ERR_lib_error_string(unsigned long e); +const char *ERR_func_error_string(unsigned long e); +const char *ERR_reason_error_string(unsigned long e); +void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), + void *u); +# ifndef OPENSSL_NO_STDIO +void ERR_print_errors_fp(FILE *fp); +# endif +void ERR_print_errors(BIO *bp); +void ERR_add_error_data(int num, ...); +void ERR_add_error_vdata(int num, va_list args); +int ERR_load_strings(int lib, ERR_STRING_DATA *str); +int ERR_load_strings_const(const ERR_STRING_DATA *str); +int ERR_unload_strings(int lib, ERR_STRING_DATA *str); +int ERR_load_ERR_strings(void); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define ERR_load_crypto_strings() \ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) +# define ERR_free_strings() while(0) continue +#endif + +DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *)) +DEPRECATEDIN_1_0_0(void ERR_remove_state(unsigned long pid)) +ERR_STATE *ERR_get_state(void); + +int ERR_get_next_error_library(void); + +int ERR_set_mark(void); +int ERR_pop_to_mark(void); +int ERR_clear_last_mark(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/evp.h b/thirdparty/user_include/openssl/evp.h new file mode 100755 index 0000000000000000000000000000000000000000..9f05b5a3b7f5295f069b7c4f5fb5ed09d53628ec --- /dev/null +++ b/thirdparty/user_include/openssl/evp.h @@ -0,0 +1,1633 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_ENVELOPE_H +# define HEADER_ENVELOPE_H + +# include +# include +# include +# include +# include + +# define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */ +# define EVP_MAX_KEY_LENGTH 64 +# define EVP_MAX_IV_LENGTH 16 +# define EVP_MAX_BLOCK_LENGTH 32 + +# define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +# define PKCS5_DEFAULT_ITER 2048 + +# include + +# define EVP_PK_RSA 0x0001 +# define EVP_PK_DSA 0x0002 +# define EVP_PK_DH 0x0004 +# define EVP_PK_EC 0x0008 +# define EVP_PKT_SIGN 0x0010 +# define EVP_PKT_ENC 0x0020 +# define EVP_PKT_EXCH 0x0040 +# define EVP_PKS_RSA 0x0100 +# define EVP_PKS_DSA 0x0200 +# define EVP_PKS_EC 0x0400 + +# define EVP_PKEY_NONE NID_undef +# define EVP_PKEY_RSA NID_rsaEncryption +# define EVP_PKEY_RSA2 NID_rsa +# define EVP_PKEY_RSA_PSS NID_rsassaPss +# define EVP_PKEY_DSA NID_dsa +# define EVP_PKEY_DSA1 NID_dsa_2 +# define EVP_PKEY_DSA2 NID_dsaWithSHA +# define EVP_PKEY_DSA3 NID_dsaWithSHA1 +# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 +# define EVP_PKEY_DH NID_dhKeyAgreement +# define EVP_PKEY_DHX NID_dhpublicnumber +# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +# define EVP_PKEY_SM2 NID_sm2 +# define EVP_PKEY_HMAC NID_hmac +# define EVP_PKEY_CMAC NID_cmac +# define EVP_PKEY_SCRYPT NID_id_scrypt +# define EVP_PKEY_TLS1_PRF NID_tls1_prf +# define EVP_PKEY_HKDF NID_hkdf +# define EVP_PKEY_POLY1305 NID_poly1305 +# define EVP_PKEY_SIPHASH NID_siphash +# define EVP_PKEY_X25519 NID_X25519 +# define EVP_PKEY_ED25519 NID_ED25519 +# define EVP_PKEY_X448 NID_X448 +# define EVP_PKEY_ED448 NID_ED448 + +#ifdef __cplusplus +extern "C" { +#endif + +# define EVP_PKEY_MO_SIGN 0x0001 +# define EVP_PKEY_MO_VERIFY 0x0002 +# define EVP_PKEY_MO_ENCRYPT 0x0004 +# define EVP_PKEY_MO_DECRYPT 0x0008 + +# ifndef EVP_MD +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type); +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md); +void EVP_MD_meth_free(EVP_MD *md); + +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize); +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize); +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize); +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags); +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx, + const void *data, + size_t count)); +int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx, + unsigned char *md)); +int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to, + const EVP_MD_CTX *from)); +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2)); + +int EVP_MD_meth_get_input_blocksize(const EVP_MD *md); +int EVP_MD_meth_get_result_size(const EVP_MD *md); +int EVP_MD_meth_get_app_datasize(const EVP_MD *md); +unsigned long EVP_MD_meth_get_flags(const EVP_MD *md); +int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx); +int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx, + const void *data, + size_t count); +int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx, + unsigned char *md); +int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to, + const EVP_MD_CTX *from); +int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx); +int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, + int p1, void *p2); + +/* digest can only handle a single block */ +# define EVP_MD_FLAG_ONESHOT 0x0001 + +/* digest is extensible-output function, XOF */ +# define EVP_MD_FLAG_XOF 0x0002 + +/* DigestAlgorithmIdentifier flags... */ + +# define EVP_MD_FLAG_DIGALGID_MASK 0x0018 + +/* NULL or absent parameter accepted. Use NULL */ + +# define EVP_MD_FLAG_DIGALGID_NULL 0x0000 + +/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */ + +# define EVP_MD_FLAG_DIGALGID_ABSENT 0x0008 + +/* Custom handling via ctrl */ + +# define EVP_MD_FLAG_DIGALGID_CUSTOM 0x0018 + +/* Note if suitable for use in FIPS mode */ +# define EVP_MD_FLAG_FIPS 0x0400 + +/* Digest ctrls */ + +# define EVP_MD_CTRL_DIGALGID 0x1 +# define EVP_MD_CTRL_MICALG 0x2 +# define EVP_MD_CTRL_XOF_LEN 0x3 + +/* Minimum Algorithm specific ctrl value */ + +# define EVP_MD_CTRL_ALG_CTRL 0x1000 + +# endif /* !EVP_MD */ + +/* values for EVP_MD_CTX flags */ + +# define EVP_MD_CTX_FLAG_ONESHOT 0x0001/* digest update will be + * called once only */ +# define EVP_MD_CTX_FLAG_CLEANED 0x0002/* context has already been + * cleaned */ +# define EVP_MD_CTX_FLAG_REUSE 0x0004/* Don't free up ctx->md_data + * in EVP_MD_CTX_reset */ +/* + * FIPS and pad options are ignored in 1.0.0, definitions are here so we + * don't accidentally reuse the values for other purposes. + */ + +# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008/* Allow use of non FIPS + * digest in FIPS mode */ + +/* + * The following PAD options are also currently ignored in 1.0.0, digest + * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*() + * instead. + */ +# define EVP_MD_CTX_FLAG_PAD_MASK 0xF0/* RSA mode to use */ +# define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00/* PKCS#1 v1.5 mode */ +# define EVP_MD_CTX_FLAG_PAD_X931 0x10/* X9.31 mode */ +# define EVP_MD_CTX_FLAG_PAD_PSS 0x20/* PSS mode */ + +# define EVP_MD_CTX_FLAG_NO_INIT 0x0100/* Don't initialize md_data */ +/* + * Some functions such as EVP_DigestSign only finalise copies of internal + * contexts so additional data can be included after the finalisation call. + * This is inefficient if this functionality is not required: it is disabled + * if the following flag is set. + */ +# define EVP_MD_CTX_FLAG_FINALISE 0x0200 +/* NOTE: 0x0400 is reserved for internal usage in evp_int.h */ + +EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len); +EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher); +void EVP_CIPHER_meth_free(EVP_CIPHER *cipher); + +int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len); +int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags); +int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size); +int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher, + int (*init) (EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc)); +int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher, + int (*do_cipher) (EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)); +int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher, + int (*cleanup) (EVP_CIPHER_CTX *)); +int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher, + int (*set_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)); +int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher, + int (*get_asn1_parameters) (EVP_CIPHER_CTX *, + ASN1_TYPE *)); +int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher, + int (*ctrl) (EVP_CIPHER_CTX *, int type, + int arg, void *ptr)); + +int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int enc); +int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl); +int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *); +int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *); +int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + ASN1_TYPE *); +int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, + int type, int arg, + void *ptr); + +/* Values for cipher flags */ + +/* Modes for ciphers */ + +# define EVP_CIPH_STREAM_CIPHER 0x0 +# define EVP_CIPH_ECB_MODE 0x1 +# define EVP_CIPH_CBC_MODE 0x2 +# define EVP_CIPH_CFB_MODE 0x3 +# define EVP_CIPH_OFB_MODE 0x4 +# define EVP_CIPH_CTR_MODE 0x5 +# define EVP_CIPH_GCM_MODE 0x6 +# define EVP_CIPH_CCM_MODE 0x7 +# define EVP_CIPH_XTS_MODE 0x10001 +# define EVP_CIPH_WRAP_MODE 0x10002 +# define EVP_CIPH_OCB_MODE 0x10003 +# define EVP_CIPH_MODE 0xF0007 +/* Set if variable length cipher */ +# define EVP_CIPH_VARIABLE_LENGTH 0x8 +/* Set if the iv handling should be done by the cipher itself */ +# define EVP_CIPH_CUSTOM_IV 0x10 +/* Set if the cipher's init() function should be called if key is NULL */ +# define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +/* Call ctrl() to init cipher parameters */ +# define EVP_CIPH_CTRL_INIT 0x40 +/* Don't use standard key length function */ +# define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +/* Don't use standard block padding */ +# define EVP_CIPH_NO_PADDING 0x100 +/* cipher handles random key generation */ +# define EVP_CIPH_RAND_KEY 0x200 +/* cipher has its own additional copying logic */ +# define EVP_CIPH_CUSTOM_COPY 0x400 +/* Allow use default ASN1 get/set iv */ +# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 +/* Buffer length in bits not bytes: CFB1 mode only */ +# define EVP_CIPH_FLAG_LENGTH_BITS 0x2000 +/* Note if suitable for use in FIPS mode */ +# define EVP_CIPH_FLAG_FIPS 0x4000 +/* Allow non FIPS cipher in FIPS mode */ +# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000 +/* + * Cipher handles any and all padding logic as well as finalisation. + */ +# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 +# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000 +/* Cipher can handle pipeline operations */ +# define EVP_CIPH_FLAG_PIPELINE 0X800000 + +/* + * Cipher context flag to indicate we can handle wrap mode: if allowed in + * older applications it could overflow buffers. + */ + +# define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1 + +/* ctrl() values */ + +# define EVP_CTRL_INIT 0x0 +# define EVP_CTRL_SET_KEY_LENGTH 0x1 +# define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +# define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +# define EVP_CTRL_GET_RC5_ROUNDS 0x4 +# define EVP_CTRL_SET_RC5_ROUNDS 0x5 +# define EVP_CTRL_RAND_KEY 0x6 +# define EVP_CTRL_PBE_PRF_NID 0x7 +# define EVP_CTRL_COPY 0x8 +# define EVP_CTRL_AEAD_SET_IVLEN 0x9 +# define EVP_CTRL_AEAD_GET_TAG 0x10 +# define EVP_CTRL_AEAD_SET_TAG 0x11 +# define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +# define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +# define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +# define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +# define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +# define EVP_CTRL_GCM_IV_GEN 0x13 +# define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +# define EVP_CTRL_CCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +# define EVP_CTRL_CCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +# define EVP_CTRL_CCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +# define EVP_CTRL_CCM_SET_L 0x14 +# define EVP_CTRL_CCM_SET_MSGLEN 0x15 +/* + * AEAD cipher deduces payload length and returns number of bytes required to + * store MAC and eventual padding. Subsequent call to EVP_Cipher even + * appends/verifies MAC. + */ +# define EVP_CTRL_AEAD_TLS1_AAD 0x16 +/* Used by composite AEAD ciphers, no-op in GCM, CCM... */ +# define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +/* Set the GCM invocation field, decrypt only */ +# define EVP_CTRL_GCM_SET_IV_INV 0x18 + +# define EVP_CTRL_TLS1_1_MULTIBLOCK_AAD 0x19 +# define EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT 0x1a +# define EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT 0x1b +# define EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE 0x1c + +# define EVP_CTRL_SSL3_MASTER_SECRET 0x1d + +/* EVP_CTRL_SET_SBOX takes the char * specifying S-boxes */ +# define EVP_CTRL_SET_SBOX 0x1e +/* + * EVP_CTRL_SBOX_USED takes a 'size_t' and 'char *', pointing at a + * pre-allocated buffer with specified size + */ +# define EVP_CTRL_SBOX_USED 0x1f +/* EVP_CTRL_KEY_MESH takes 'size_t' number of bytes to mesh the key after, + * 0 switches meshing off + */ +# define EVP_CTRL_KEY_MESH 0x20 +/* EVP_CTRL_BLOCK_PADDING_MODE takes the padding mode */ +# define EVP_CTRL_BLOCK_PADDING_MODE 0x21 + +/* Set the output buffers to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS 0x22 +/* Set the input buffers to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_INPUT_BUFS 0x23 +/* Set the input buffer lengths to use for a pipelined operation */ +# define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24 + +/* Padding modes */ +#define EVP_PADDING_PKCS7 1 +#define EVP_PADDING_ISO7816_4 2 +#define EVP_PADDING_ANSI923 3 +#define EVP_PADDING_ISO10126 4 +#define EVP_PADDING_ZERO 5 + +/* RFC 5246 defines additional data to be 13 bytes in length */ +# define EVP_AEAD_TLS1_AAD_LEN 13 + +typedef struct { + unsigned char *out; + const unsigned char *inp; + size_t len; + unsigned int interleave; +} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM; + +/* GCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +# define EVP_GCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +# define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +/* Length of tag for TLS */ +# define EVP_GCM_TLS_TAG_LEN 16 + +/* CCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +# define EVP_CCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +# define EVP_CCM_TLS_EXPLICIT_IV_LEN 8 +/* Total length of CCM IV length for TLS */ +# define EVP_CCM_TLS_IV_LEN 12 +/* Length of tag for TLS */ +# define EVP_CCM_TLS_TAG_LEN 16 +/* Length of CCM8 tag for TLS */ +# define EVP_CCM8_TLS_TAG_LEN 8 + +/* Length of tag for TLS */ +# define EVP_CHACHAPOLY_TLS_TAG_LEN 16 + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + + +/* Password based encryption function */ +typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, + int en_de); + +# ifndef OPENSSL_NO_RSA +# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +# endif + +# ifndef OPENSSL_NO_DSA +# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) +# endif + +# ifndef OPENSSL_NO_DH +# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ + (char *)(dh)) +# endif + +# ifndef OPENSSL_NO_EC +# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\ + (char *)(eckey)) +# endif +# ifndef OPENSSL_NO_SIPHASH +# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),EVP_PKEY_SIPHASH,\ + (char *)(shkey)) +# endif + +# ifndef OPENSSL_NO_POLY1305 +# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),EVP_PKEY_POLY1305,\ + (char *)(polykey)) +# endif + +/* Add some extra combinations */ +# define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) +# define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) +# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) +# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + +int EVP_MD_type(const EVP_MD *md); +# define EVP_MD_nid(e) EVP_MD_type(e) +# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e)) +int EVP_MD_pkey_type(const EVP_MD *md); +int EVP_MD_size(const EVP_MD *md); +int EVP_MD_block_size(const EVP_MD *md); +unsigned long EVP_MD_flags(const EVP_MD *md); + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); +int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx, + const void *data, size_t count); +void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx, + int (*update) (EVP_MD_CTX *ctx, + const void *data, size_t count)); +# define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher); +# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) +int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher); +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher); +# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE) + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); +const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx); +const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx); +unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx); +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num); +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx); +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data); +# define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) +# if OPENSSL_API_COMPAT < 0x10100000L +# define EVP_CIPHER_CTX_flags(c) EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(c)) +# endif +# define EVP_CIPHER_CTX_mode(c) EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(c)) + +# define EVP_ENCODE_LENGTH(l) ((((l)+2)/3*4)+((l)/48+1)*2+80) +# define EVP_DECODE_LENGTH(l) (((l)+3)/4*3+80) + +# define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_SignInit(a,b) EVP_DigestInit(a,b) +# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) +# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) +# define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) +# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + +# ifdef CONST_STRICT +void BIO_set_md(BIO *, const EVP_MD *md); +# else +# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)(md)) +# endif +# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)(mdp)) +# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0, \ + (char *)(mdcp)) +# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0, \ + (char *)(mdcp)) +# define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL) +# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0, \ + (char *)(c_pp)) + +/*__owur*/ int EVP_Cipher(EVP_CIPHER_CTX *c, + unsigned char *out, + const unsigned char *in, unsigned int inl); + +# define EVP_add_cipher_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_add_digest_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_delete_cipher_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS); +# define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + +int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2); +EVP_MD_CTX *EVP_MD_CTX_new(void); +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +# define EVP_MD_CTX_create() EVP_MD_CTX_new() +# define EVP_MD_CTX_init(ctx) EVP_MD_CTX_reset((ctx)) +# define EVP_MD_CTX_destroy(ctx) EVP_MD_CTX_free((ctx)) +__owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags); +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags); +__owur int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *impl); +__owur int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, + size_t cnt); +__owur int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, + unsigned int *s); +__owur int EVP_Digest(const void *data, size_t count, + unsigned char *md, unsigned int *size, + const EVP_MD *type, ENGINE *impl); + +__owur int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); +__owur int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +__owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, + unsigned int *s); +__owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, + size_t len); + +int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify); +int EVP_read_pw_string_min(char *buf, int minlen, int maxlen, + const char *prompt, int verify); +void EVP_set_pw_prompt(const char *prompt); +char *EVP_get_pw_prompt(void); + +__owur int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, + const unsigned char *data, int datal, int count, + unsigned char *key, unsigned char *iv); + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags); +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags); +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags); + +__owur int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +/*__owur*/ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv); +/*__owur*/ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +/*__owur*/ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); +/*__owur*/ int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); + +__owur int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +/*__owur*/ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv); +/*__owur*/ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +__owur int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); +/*__owur*/ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + +__owur int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, + int enc); +/*__owur*/ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, + const unsigned char *iv, int enc); +__owur int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +__owur int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); +__owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + +__owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, + EVP_PKEY *pkey); + +__owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen, const unsigned char *tbs, + size_t tbslen); + +__owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey); + +__owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + +/*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +__owur int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + size_t *siglen); + +__owur int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, + EVP_PKEY *pkey); +__owur int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); + +# ifndef OPENSSL_NO_RSA +__owur int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, + const unsigned char *iv, EVP_PKEY *priv); +__owur int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +__owur int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char **ek, int *ekl, unsigned char *iv, + EVP_PKEY **pubk, int npubk); +__owur int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +# endif + +EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void); +void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx); +int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx); +int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx); +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); +int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned + char *out, int *outl); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define EVP_CIPHER_CTX_init(c) EVP_CIPHER_CTX_reset(c) +# define EVP_CIPHER_CTX_cleanup(c) EVP_CIPHER_CTX_reset(c) +# endif +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c); +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); + +const BIO_METHOD *BIO_f_md(void); +const BIO_METHOD *BIO_f_base64(void); +const BIO_METHOD *BIO_f_cipher(void); +const BIO_METHOD *BIO_f_reliable(void); +__owur int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, + const unsigned char *i, int enc); + +const EVP_MD *EVP_md_null(void); +# ifndef OPENSSL_NO_MD2 +const EVP_MD *EVP_md2(void); +# endif +# ifndef OPENSSL_NO_MD4 +const EVP_MD *EVP_md4(void); +# endif +# ifndef OPENSSL_NO_MD5 +const EVP_MD *EVP_md5(void); +const EVP_MD *EVP_md5_sha1(void); +# endif +# ifndef OPENSSL_NO_BLAKE2 +const EVP_MD *EVP_blake2b512(void); +const EVP_MD *EVP_blake2s256(void); +# endif +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +const EVP_MD *EVP_sha512_224(void); +const EVP_MD *EVP_sha512_256(void); +const EVP_MD *EVP_sha3_224(void); +const EVP_MD *EVP_sha3_256(void); +const EVP_MD *EVP_sha3_384(void); +const EVP_MD *EVP_sha3_512(void); +const EVP_MD *EVP_shake128(void); +const EVP_MD *EVP_shake256(void); +# ifndef OPENSSL_NO_MDC2 +const EVP_MD *EVP_mdc2(void); +# endif +# ifndef OPENSSL_NO_RMD160 +const EVP_MD *EVP_ripemd160(void); +# endif +# ifndef OPENSSL_NO_WHIRLPOOL +const EVP_MD *EVP_whirlpool(void); +# endif +# ifndef OPENSSL_NO_SM3 +const EVP_MD *EVP_sm3(void); +# endif +const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +# ifndef OPENSSL_NO_DES +const EVP_CIPHER *EVP_des_ecb(void); +const EVP_CIPHER *EVP_des_ede(void); +const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_ede_ecb(void); +const EVP_CIPHER *EVP_des_ede3_ecb(void); +const EVP_CIPHER *EVP_des_cfb64(void); +# define EVP_des_cfb EVP_des_cfb64 +const EVP_CIPHER *EVP_des_cfb1(void); +const EVP_CIPHER *EVP_des_cfb8(void); +const EVP_CIPHER *EVP_des_ede_cfb64(void); +# define EVP_des_ede_cfb EVP_des_ede_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb64(void); +# define EVP_des_ede3_cfb EVP_des_ede3_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb1(void); +const EVP_CIPHER *EVP_des_ede3_cfb8(void); +const EVP_CIPHER *EVP_des_ofb(void); +const EVP_CIPHER *EVP_des_ede_ofb(void); +const EVP_CIPHER *EVP_des_ede3_ofb(void); +const EVP_CIPHER *EVP_des_cbc(void); +const EVP_CIPHER *EVP_des_ede_cbc(void); +const EVP_CIPHER *EVP_des_ede3_cbc(void); +const EVP_CIPHER *EVP_desx_cbc(void); +const EVP_CIPHER *EVP_des_ede3_wrap(void); +/* + * This should now be supported through the dev_crypto ENGINE. But also, why + * are rc4 and md5 declarations made here inside a "NO_DES" precompiler + * branch? + */ +# endif +# ifndef OPENSSL_NO_RC4 +const EVP_CIPHER *EVP_rc4(void); +const EVP_CIPHER *EVP_rc4_40(void); +# ifndef OPENSSL_NO_MD5 +const EVP_CIPHER *EVP_rc4_hmac_md5(void); +# endif +# endif +# ifndef OPENSSL_NO_IDEA +const EVP_CIPHER *EVP_idea_ecb(void); +const EVP_CIPHER *EVP_idea_cfb64(void); +# define EVP_idea_cfb EVP_idea_cfb64 +const EVP_CIPHER *EVP_idea_ofb(void); +const EVP_CIPHER *EVP_idea_cbc(void); +# endif +# ifndef OPENSSL_NO_RC2 +const EVP_CIPHER *EVP_rc2_ecb(void); +const EVP_CIPHER *EVP_rc2_cbc(void); +const EVP_CIPHER *EVP_rc2_40_cbc(void); +const EVP_CIPHER *EVP_rc2_64_cbc(void); +const EVP_CIPHER *EVP_rc2_cfb64(void); +# define EVP_rc2_cfb EVP_rc2_cfb64 +const EVP_CIPHER *EVP_rc2_ofb(void); +# endif +# ifndef OPENSSL_NO_BF +const EVP_CIPHER *EVP_bf_ecb(void); +const EVP_CIPHER *EVP_bf_cbc(void); +const EVP_CIPHER *EVP_bf_cfb64(void); +# define EVP_bf_cfb EVP_bf_cfb64 +const EVP_CIPHER *EVP_bf_ofb(void); +# endif +# ifndef OPENSSL_NO_CAST +const EVP_CIPHER *EVP_cast5_ecb(void); +const EVP_CIPHER *EVP_cast5_cbc(void); +const EVP_CIPHER *EVP_cast5_cfb64(void); +# define EVP_cast5_cfb EVP_cast5_cfb64 +const EVP_CIPHER *EVP_cast5_ofb(void); +# endif +# ifndef OPENSSL_NO_RC5 +const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); +const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void); +# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64 +const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); +# endif +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb1(void); +const EVP_CIPHER *EVP_aes_128_cfb8(void); +const EVP_CIPHER *EVP_aes_128_cfb128(void); +# define EVP_aes_128_cfb EVP_aes_128_cfb128 +const EVP_CIPHER *EVP_aes_128_ofb(void); +const EVP_CIPHER *EVP_aes_128_ctr(void); +const EVP_CIPHER *EVP_aes_128_ccm(void); +const EVP_CIPHER *EVP_aes_128_gcm(void); +const EVP_CIPHER *EVP_aes_128_xts(void); +const EVP_CIPHER *EVP_aes_128_wrap(void); +const EVP_CIPHER *EVP_aes_128_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_128_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb1(void); +const EVP_CIPHER *EVP_aes_192_cfb8(void); +const EVP_CIPHER *EVP_aes_192_cfb128(void); +# define EVP_aes_192_cfb EVP_aes_192_cfb128 +const EVP_CIPHER *EVP_aes_192_ofb(void); +const EVP_CIPHER *EVP_aes_192_ctr(void); +const EVP_CIPHER *EVP_aes_192_ccm(void); +const EVP_CIPHER *EVP_aes_192_gcm(void); +const EVP_CIPHER *EVP_aes_192_wrap(void); +const EVP_CIPHER *EVP_aes_192_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_192_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb1(void); +const EVP_CIPHER *EVP_aes_256_cfb8(void); +const EVP_CIPHER *EVP_aes_256_cfb128(void); +# define EVP_aes_256_cfb EVP_aes_256_cfb128 +const EVP_CIPHER *EVP_aes_256_ofb(void); +const EVP_CIPHER *EVP_aes_256_ctr(void); +const EVP_CIPHER *EVP_aes_256_ccm(void); +const EVP_CIPHER *EVP_aes_256_gcm(void); +const EVP_CIPHER *EVP_aes_256_xts(void); +const EVP_CIPHER *EVP_aes_256_wrap(void); +const EVP_CIPHER *EVP_aes_256_wrap_pad(void); +# ifndef OPENSSL_NO_OCB +const EVP_CIPHER *EVP_aes_256_ocb(void); +# endif +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void); +# ifndef OPENSSL_NO_ARIA +const EVP_CIPHER *EVP_aria_128_ecb(void); +const EVP_CIPHER *EVP_aria_128_cbc(void); +const EVP_CIPHER *EVP_aria_128_cfb1(void); +const EVP_CIPHER *EVP_aria_128_cfb8(void); +const EVP_CIPHER *EVP_aria_128_cfb128(void); +# define EVP_aria_128_cfb EVP_aria_128_cfb128 +const EVP_CIPHER *EVP_aria_128_ctr(void); +const EVP_CIPHER *EVP_aria_128_ofb(void); +const EVP_CIPHER *EVP_aria_128_gcm(void); +const EVP_CIPHER *EVP_aria_128_ccm(void); +const EVP_CIPHER *EVP_aria_192_ecb(void); +const EVP_CIPHER *EVP_aria_192_cbc(void); +const EVP_CIPHER *EVP_aria_192_cfb1(void); +const EVP_CIPHER *EVP_aria_192_cfb8(void); +const EVP_CIPHER *EVP_aria_192_cfb128(void); +# define EVP_aria_192_cfb EVP_aria_192_cfb128 +const EVP_CIPHER *EVP_aria_192_ctr(void); +const EVP_CIPHER *EVP_aria_192_ofb(void); +const EVP_CIPHER *EVP_aria_192_gcm(void); +const EVP_CIPHER *EVP_aria_192_ccm(void); +const EVP_CIPHER *EVP_aria_256_ecb(void); +const EVP_CIPHER *EVP_aria_256_cbc(void); +const EVP_CIPHER *EVP_aria_256_cfb1(void); +const EVP_CIPHER *EVP_aria_256_cfb8(void); +const EVP_CIPHER *EVP_aria_256_cfb128(void); +# define EVP_aria_256_cfb EVP_aria_256_cfb128 +const EVP_CIPHER *EVP_aria_256_ctr(void); +const EVP_CIPHER *EVP_aria_256_ofb(void); +const EVP_CIPHER *EVP_aria_256_gcm(void); +const EVP_CIPHER *EVP_aria_256_ccm(void); +# endif +# ifndef OPENSSL_NO_CAMELLIA +const EVP_CIPHER *EVP_camellia_128_ecb(void); +const EVP_CIPHER *EVP_camellia_128_cbc(void); +const EVP_CIPHER *EVP_camellia_128_cfb1(void); +const EVP_CIPHER *EVP_camellia_128_cfb8(void); +const EVP_CIPHER *EVP_camellia_128_cfb128(void); +# define EVP_camellia_128_cfb EVP_camellia_128_cfb128 +const EVP_CIPHER *EVP_camellia_128_ofb(void); +const EVP_CIPHER *EVP_camellia_128_ctr(void); +const EVP_CIPHER *EVP_camellia_192_ecb(void); +const EVP_CIPHER *EVP_camellia_192_cbc(void); +const EVP_CIPHER *EVP_camellia_192_cfb1(void); +const EVP_CIPHER *EVP_camellia_192_cfb8(void); +const EVP_CIPHER *EVP_camellia_192_cfb128(void); +# define EVP_camellia_192_cfb EVP_camellia_192_cfb128 +const EVP_CIPHER *EVP_camellia_192_ofb(void); +const EVP_CIPHER *EVP_camellia_192_ctr(void); +const EVP_CIPHER *EVP_camellia_256_ecb(void); +const EVP_CIPHER *EVP_camellia_256_cbc(void); +const EVP_CIPHER *EVP_camellia_256_cfb1(void); +const EVP_CIPHER *EVP_camellia_256_cfb8(void); +const EVP_CIPHER *EVP_camellia_256_cfb128(void); +# define EVP_camellia_256_cfb EVP_camellia_256_cfb128 +const EVP_CIPHER *EVP_camellia_256_ofb(void); +const EVP_CIPHER *EVP_camellia_256_ctr(void); +# endif +# ifndef OPENSSL_NO_CHACHA +const EVP_CIPHER *EVP_chacha20(void); +# ifndef OPENSSL_NO_POLY1305 +const EVP_CIPHER *EVP_chacha20_poly1305(void); +# endif +# endif + +# ifndef OPENSSL_NO_SEED +const EVP_CIPHER *EVP_seed_ecb(void); +const EVP_CIPHER *EVP_seed_cbc(void); +const EVP_CIPHER *EVP_seed_cfb128(void); +# define EVP_seed_cfb EVP_seed_cfb128 +const EVP_CIPHER *EVP_seed_ofb(void); +# endif + +# ifndef OPENSSL_NO_SM4 +const EVP_CIPHER *EVP_sm4_ecb(void); +const EVP_CIPHER *EVP_sm4_cbc(void); +const EVP_CIPHER *EVP_sm4_cfb128(void); +# define EVP_sm4_cfb EVP_sm4_cfb128 +const EVP_CIPHER *EVP_sm4_ofb(void); +const EVP_CIPHER *EVP_sm4_ctr(void); +# endif + +# if OPENSSL_API_COMPAT < 0x10100000L +# define OPENSSL_add_all_algorithms_conf() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS \ + | OPENSSL_INIT_LOAD_CONFIG, NULL) +# define OPENSSL_add_all_algorithms_noconf() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) + +# ifdef OPENSSL_LOAD_CONF +# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_conf() +# else +# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_noconf() +# endif + +# define OpenSSL_add_all_ciphers() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL) +# define OpenSSL_add_all_digests() \ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) + +# define EVP_cleanup() while(0) continue +# endif + +int EVP_add_cipher(const EVP_CIPHER *cipher); +int EVP_add_digest(const EVP_MD *digest); + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name); +const EVP_MD *EVP_get_digestbyname(const char *name); + +void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_CIPHER_do_all_sorted(void (*fn) + (const EVP_CIPHER *ciph, const char *from, + const char *to, void *x), void *arg); + +void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_MD_do_all_sorted(void (*fn) + (const EVP_MD *ciph, const char *from, + const char *to, void *x), void *arg); + +int EVP_PKEY_decrypt_old(unsigned char *dec_key, + const unsigned char *enc_key, int enc_key_len, + EVP_PKEY *private_key); +int EVP_PKEY_encrypt_old(unsigned char *enc_key, + const unsigned char *key, int key_len, + EVP_PKEY *pub_key); +int EVP_PKEY_type(int type); +int EVP_PKEY_id(const EVP_PKEY *pkey); +int EVP_PKEY_base_id(const EVP_PKEY *pkey); +int EVP_PKEY_bits(const EVP_PKEY *pkey); +int EVP_PKEY_security_bits(const EVP_PKEY *pkey); +int EVP_PKEY_size(const EVP_PKEY *pkey); +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); +int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); +# ifndef OPENSSL_NO_ENGINE +int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e); +# endif +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); +void *EVP_PKEY_get0(const EVP_PKEY *pkey); +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len); +# ifndef OPENSSL_NO_POLY1305 +const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len); +# endif +# ifndef OPENSSL_NO_SIPHASH +const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len); +# endif + +# ifndef OPENSSL_NO_RSA +struct rsa_st; +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); +struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DSA +struct dsa_st; +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key); +struct dsa_st *EVP_PKEY_get0_DSA(EVP_PKEY *pkey); +struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DH +struct dh_st; +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key); +struct dh_st *EVP_PKEY_get0_DH(EVP_PKEY *pkey); +struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_EC +struct ec_key_st; +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +# endif + +EVP_PKEY *EVP_PKEY_new(void); +int EVP_PKEY_up_ref(EVP_PKEY *pkey); +void EVP_PKEY_free(EVP_PKEY *pkey); + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp); + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode); +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid); + +int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, + const unsigned char *pt, size_t ptlen); +size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt); + +int EVP_CIPHER_type(const EVP_CIPHER *ctx); + +/* calls methods */ +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* These are used by EVP_CIPHER methods */ +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out); +int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + const EVP_MD *digest, int keylen, unsigned char *out); +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); + +#ifndef OPENSSL_NO_SCRYPT +int EVP_PBE_scrypt(const char *pass, size_t passlen, + const unsigned char *salt, size_t saltlen, + uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, + unsigned char *key, size_t keylen); + +int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de); +#endif + +void PKCS5_PBE_add(void); + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); + +/* PBE type */ + +/* Can appear as the outermost AlgorithmIdentifier */ +# define EVP_PBE_TYPE_OUTER 0x0 +/* Is an PRF type OID */ +# define EVP_PBE_TYPE_PRF 0x1 +/* Is a PKCS#5 v2.0 KDF */ +# define EVP_PBE_TYPE_KDF 0x2 + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, + int md_nid, EVP_PBE_KEYGEN *keygen); +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid, + EVP_PBE_KEYGEN **pkeygen); +void EVP_PBE_cleanup(void); +int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num); + +# define ASN1_PKEY_ALIAS 0x1 +# define ASN1_PKEY_DYNAMIC 0x2 +# define ASN1_PKEY_SIGPARAM_NULL 0x4 + +# define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1 +# define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2 +# define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3 +# define ASN1_PKEY_CTRL_CMS_SIGN 0x5 +# define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7 +# define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8 + +# define ASN1_PKEY_CTRL_SET1_TLS_ENCPT 0x9 +# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa + +int EVP_PKEY_asn1_get_count(void); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len); +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth); +int EVP_PKEY_asn1_add_alias(int to, int from); +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, + int *ppkey_flags, const char **pinfo, + const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth); + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey); +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, + const char *pem_str, + const char *info); +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, + const EVP_PKEY_ASN1_METHOD *src); +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth); +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, + int (*pub_decode) (EVP_PKEY *pk, + X509_PUBKEY *pub), + int (*pub_encode) (X509_PUBKEY *pub, + const EVP_PKEY *pk), + int (*pub_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*pub_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx), + int (*pkey_size) (const EVP_PKEY *pk), + int (*pkey_bits) (const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, + int (*priv_decode) (EVP_PKEY *pk, + const PKCS8_PRIV_KEY_INFO + *p8inf), + int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, + const EVP_PKEY *pk), + int (*priv_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, + int (*param_decode) (EVP_PKEY *pkey, + const unsigned char **pder, + int derlen), + int (*param_encode) (const EVP_PKEY *pkey, + unsigned char **pder), + int (*param_missing) (const EVP_PKEY *pk), + int (*param_copy) (EVP_PKEY *to, + const EVP_PKEY *from), + int (*param_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*param_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, + void (*pkey_free) (EVP_PKEY *pkey)); +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_ctrl) (EVP_PKEY *pkey, int op, + long arg1, void *arg2)); +void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, + int (*item_verify) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *a, + ASN1_BIT_STRING *sig, + EVP_PKEY *pkey), + int (*item_sign) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *alg1, + X509_ALGOR *alg2, + ASN1_BIT_STRING *sig)); + +void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth, + int (*siginf_set) (X509_SIG_INFO *siginf, + const X509_ALGOR *alg, + const ASN1_STRING *sig)); + +void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_pub_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_param_check) (const EVP_PKEY *pk)); + +void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_priv_key) (EVP_PKEY *pk, + const unsigned char + *priv, + size_t len)); +void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*set_pub_key) (EVP_PKEY *pk, + const unsigned char *pub, + size_t len)); +void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_priv_key) (const EVP_PKEY *pk, + unsigned char *priv, + size_t *len)); +void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth, + int (*get_pub_key) (const EVP_PKEY *pk, + unsigned char *pub, + size_t *len)); + +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits) (const EVP_PKEY + *pk)); + +# define EVP_PKEY_OP_UNDEFINED 0 +# define EVP_PKEY_OP_PARAMGEN (1<<1) +# define EVP_PKEY_OP_KEYGEN (1<<2) +# define EVP_PKEY_OP_SIGN (1<<3) +# define EVP_PKEY_OP_VERIFY (1<<4) +# define EVP_PKEY_OP_VERIFYRECOVER (1<<5) +# define EVP_PKEY_OP_SIGNCTX (1<<6) +# define EVP_PKEY_OP_VERIFYCTX (1<<7) +# define EVP_PKEY_OP_ENCRYPT (1<<8) +# define EVP_PKEY_OP_DECRYPT (1<<9) +# define EVP_PKEY_OP_DERIVE (1<<10) + +# define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \ + | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX) + +# define EVP_PKEY_OP_TYPE_CRYPT \ + (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT) + +# define EVP_PKEY_OP_TYPE_NOGEN \ + (EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_DERIVE) + +# define EVP_PKEY_OP_TYPE_GEN \ + (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN) + +# define EVP_PKEY_CTX_set_signature_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set_mac_key(ctx, key, len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_SET_MAC_KEY, len, (void *)(key)) + +# define EVP_PKEY_CTRL_MD 1 +# define EVP_PKEY_CTRL_PEER_KEY 2 + +# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 +# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 + +# define EVP_PKEY_CTRL_PKCS7_SIGN 5 + +# define EVP_PKEY_CTRL_SET_MAC_KEY 6 + +# define EVP_PKEY_CTRL_DIGESTINIT 7 + +/* Used by GOST key encryption in TLS */ +# define EVP_PKEY_CTRL_SET_IV 8 + +# define EVP_PKEY_CTRL_CMS_ENCRYPT 9 +# define EVP_PKEY_CTRL_CMS_DECRYPT 10 +# define EVP_PKEY_CTRL_CMS_SIGN 11 + +# define EVP_PKEY_CTRL_CIPHER 12 + +# define EVP_PKEY_CTRL_GET_MD 13 + +# define EVP_PKEY_CTRL_SET_DIGEST_SIZE 14 + +# define EVP_PKEY_ALG_CTRL 0x1000 + +# define EVP_PKEY_FLAG_AUTOARGLEN 2 +/* + * Method handles all operations: don't assume any digest related defaults. + */ +# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags); +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, + const EVP_PKEY_METHOD *meth); +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src); +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth); +size_t EVP_PKEY_meth_get_count(void); +const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx); + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value); +int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value); + +int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str); +int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex); + +int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md); + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen); + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, + const unsigned char *key, int keylen); +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len); +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, + const unsigned char *pub, + size_t len); +int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, + size_t *len); +int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, + size_t *len); + +EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, + size_t len, const EVP_CIPHER *cipher); + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + +typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, + int (*init) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, + void (*cleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, + int (*paramgen_init) (EVP_PKEY_CTX *ctx), + int (*paramgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, + int (*keygen_init) (EVP_PKEY_CTX *ctx), + int (*keygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, + int (*sign_init) (EVP_PKEY_CTX *ctx), + int (*sign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, + int (*verify_init) (EVP_PKEY_CTX *ctx), + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, + int (*verify_recover_init) (EVP_PKEY_CTX + *ctx), + int (*verify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, + int (*signctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*signctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, + int (*verifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*verifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, + int (*encrypt_init) (EVP_PKEY_CTX *ctx), + int (*encryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, + int (*decrypt_init) (EVP_PKEY_CTX *ctx), + int (*decrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, + int (*derive_init) (EVP_PKEY_CTX *ctx), + int (*derive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (*ctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*check) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth, + int (*digest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth, + int (**pinit) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth, + int (**pcopy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth, + void (**pcleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth, + int (**pparamgen_init) (EVP_PKEY_CTX *ctx), + int (**pparamgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth, + int (**pkeygen_init) (EVP_PKEY_CTX *ctx), + int (**pkeygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth, + int (**psign_init) (EVP_PKEY_CTX *ctx), + int (**psign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth, + int (**pverify_init) (EVP_PKEY_CTX *ctx), + int (**pverify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth, + int (**pverify_recover_init) (EVP_PKEY_CTX + *ctx), + int (**pverify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth, + int (**psignctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**psignctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth, + int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**pverifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth, + int (**pencrypt_init) (EVP_PKEY_CTX *ctx), + int (**pencryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth, + int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), + int (**pdecrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth, + int (**pderive_init) (EVP_PKEY_CTX *ctx), + int (**pderive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth, + int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (**pctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth, + int (**pcheck) (EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, + int (**pdigest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); +void EVP_add_alg_module(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/evperr.h b/thirdparty/user_include/openssl/evperr.h new file mode 100755 index 0000000000000000000000000000000000000000..84f03eb3c45f081de4cccb9e95a7f3c9e73667e1 --- /dev/null +++ b/thirdparty/user_include/openssl/evperr.h @@ -0,0 +1,194 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_EVPERR_H +# define HEADER_EVPERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_EVP_strings(void); + +/* + * EVP function codes. + */ +# define EVP_F_AESNI_INIT_KEY 165 +# define EVP_F_AES_GCM_CTRL 196 +# define EVP_F_AES_INIT_KEY 133 +# define EVP_F_AES_OCB_CIPHER 169 +# define EVP_F_AES_T4_INIT_KEY 178 +# define EVP_F_AES_WRAP_CIPHER 170 +# define EVP_F_ALG_MODULE_INIT 177 +# define EVP_F_ARIA_CCM_INIT_KEY 175 +# define EVP_F_ARIA_GCM_CTRL 197 +# define EVP_F_ARIA_GCM_INIT_KEY 176 +# define EVP_F_ARIA_INIT_KEY 185 +# define EVP_F_B64_NEW 198 +# define EVP_F_CAMELLIA_INIT_KEY 159 +# define EVP_F_CHACHA20_POLY1305_CTRL 182 +# define EVP_F_CMLL_T4_INIT_KEY 179 +# define EVP_F_DES_EDE3_WRAP_CIPHER 171 +# define EVP_F_DO_SIGVER_INIT 161 +# define EVP_F_ENC_NEW 199 +# define EVP_F_EVP_CIPHERINIT_EX 123 +# define EVP_F_EVP_CIPHER_ASN1_TO_PARAM 204 +# define EVP_F_EVP_CIPHER_CTX_COPY 163 +# define EVP_F_EVP_CIPHER_CTX_CTRL 124 +# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 +# define EVP_F_EVP_CIPHER_PARAM_TO_ASN1 205 +# define EVP_F_EVP_DECRYPTFINAL_EX 101 +# define EVP_F_EVP_DECRYPTUPDATE 166 +# define EVP_F_EVP_DIGESTFINALXOF 174 +# define EVP_F_EVP_DIGESTINIT_EX 128 +# define EVP_F_EVP_ENCRYPTDECRYPTUPDATE 219 +# define EVP_F_EVP_ENCRYPTFINAL_EX 127 +# define EVP_F_EVP_ENCRYPTUPDATE 167 +# define EVP_F_EVP_MD_CTX_COPY_EX 110 +# define EVP_F_EVP_MD_SIZE 162 +# define EVP_F_EVP_OPENINIT 102 +# define EVP_F_EVP_PBE_ALG_ADD 115 +# define EVP_F_EVP_PBE_ALG_ADD_TYPE 160 +# define EVP_F_EVP_PBE_CIPHERINIT 116 +# define EVP_F_EVP_PBE_SCRYPT 181 +# define EVP_F_EVP_PKCS82PKEY 111 +# define EVP_F_EVP_PKEY2PKCS8 113 +# define EVP_F_EVP_PKEY_ASN1_ADD0 188 +# define EVP_F_EVP_PKEY_CHECK 186 +# define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 +# define EVP_F_EVP_PKEY_CTX_CTRL 137 +# define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 +# define EVP_F_EVP_PKEY_CTX_DUP 156 +# define EVP_F_EVP_PKEY_CTX_MD 168 +# define EVP_F_EVP_PKEY_DECRYPT 104 +# define EVP_F_EVP_PKEY_DECRYPT_INIT 138 +# define EVP_F_EVP_PKEY_DECRYPT_OLD 151 +# define EVP_F_EVP_PKEY_DERIVE 153 +# define EVP_F_EVP_PKEY_DERIVE_INIT 154 +# define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155 +# define EVP_F_EVP_PKEY_ENCRYPT 105 +# define EVP_F_EVP_PKEY_ENCRYPT_INIT 139 +# define EVP_F_EVP_PKEY_ENCRYPT_OLD 152 +# define EVP_F_EVP_PKEY_GET0_DH 119 +# define EVP_F_EVP_PKEY_GET0_DSA 120 +# define EVP_F_EVP_PKEY_GET0_EC_KEY 131 +# define EVP_F_EVP_PKEY_GET0_HMAC 183 +# define EVP_F_EVP_PKEY_GET0_POLY1305 184 +# define EVP_F_EVP_PKEY_GET0_RSA 121 +# define EVP_F_EVP_PKEY_GET0_SIPHASH 172 +# define EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY 202 +# define EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY 203 +# define EVP_F_EVP_PKEY_KEYGEN 146 +# define EVP_F_EVP_PKEY_KEYGEN_INIT 147 +# define EVP_F_EVP_PKEY_METH_ADD0 194 +# define EVP_F_EVP_PKEY_METH_NEW 195 +# define EVP_F_EVP_PKEY_NEW 106 +# define EVP_F_EVP_PKEY_NEW_CMAC_KEY 193 +# define EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY 191 +# define EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY 192 +# define EVP_F_EVP_PKEY_PARAMGEN 148 +# define EVP_F_EVP_PKEY_PARAMGEN_INIT 149 +# define EVP_F_EVP_PKEY_PARAM_CHECK 189 +# define EVP_F_EVP_PKEY_PUBLIC_CHECK 190 +# define EVP_F_EVP_PKEY_SET1_ENGINE 187 +# define EVP_F_EVP_PKEY_SET_ALIAS_TYPE 206 +# define EVP_F_EVP_PKEY_SIGN 140 +# define EVP_F_EVP_PKEY_SIGN_INIT 141 +# define EVP_F_EVP_PKEY_VERIFY 142 +# define EVP_F_EVP_PKEY_VERIFY_INIT 143 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER 144 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145 +# define EVP_F_EVP_SIGNFINAL 107 +# define EVP_F_EVP_VERIFYFINAL 108 +# define EVP_F_INT_CTX_NEW 157 +# define EVP_F_OK_NEW 200 +# define EVP_F_PKCS5_PBE_KEYIVGEN 117 +# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 +# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164 +# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 180 +# define EVP_F_PKEY_SET_TYPE 158 +# define EVP_F_RC2_MAGIC_TO_METH 109 +# define EVP_F_RC5_CTRL 125 +# define EVP_F_S390X_AES_GCM_CTRL 201 +# define EVP_F_UPDATE 173 + +/* + * EVP reason codes. + */ +# define EVP_R_AES_KEY_SETUP_FAILED 143 +# define EVP_R_ARIA_KEY_SETUP_FAILED 176 +# define EVP_R_BAD_DECRYPT 100 +# define EVP_R_BUFFER_TOO_SMALL 155 +# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157 +# define EVP_R_CIPHER_PARAMETER_ERROR 122 +# define EVP_R_COMMAND_NOT_SUPPORTED 147 +# define EVP_R_COPY_ERROR 173 +# define EVP_R_CTRL_NOT_IMPLEMENTED 132 +# define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 +# define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 +# define EVP_R_DECODE_ERROR 114 +# define EVP_R_DIFFERENT_KEY_TYPES 101 +# define EVP_R_DIFFERENT_PARAMETERS 153 +# define EVP_R_ERROR_LOADING_SECTION 165 +# define EVP_R_ERROR_SETTING_FIPS_MODE 166 +# define EVP_R_EXPECTING_AN_HMAC_KEY 174 +# define EVP_R_EXPECTING_AN_RSA_KEY 127 +# define EVP_R_EXPECTING_A_DH_KEY 128 +# define EVP_R_EXPECTING_A_DSA_KEY 129 +# define EVP_R_EXPECTING_A_EC_KEY 142 +# define EVP_R_EXPECTING_A_POLY1305_KEY 164 +# define EVP_R_EXPECTING_A_SIPHASH_KEY 175 +# define EVP_R_FIPS_MODE_NOT_SUPPORTED 167 +# define EVP_R_GET_RAW_KEY_FAILED 182 +# define EVP_R_ILLEGAL_SCRYPT_PARAMETERS 171 +# define EVP_R_INITIALIZATION_ERROR 134 +# define EVP_R_INPUT_NOT_INITIALIZED 111 +# define EVP_R_INVALID_DIGEST 152 +# define EVP_R_INVALID_FIPS_MODE 168 +# define EVP_R_INVALID_KEY 163 +# define EVP_R_INVALID_KEY_LENGTH 130 +# define EVP_R_INVALID_OPERATION 148 +# define EVP_R_KEYGEN_FAILURE 120 +# define EVP_R_KEY_SETUP_FAILED 180 +# define EVP_R_MEMORY_LIMIT_EXCEEDED 172 +# define EVP_R_MESSAGE_DIGEST_IS_NULL 159 +# define EVP_R_METHOD_NOT_SUPPORTED 144 +# define EVP_R_MISSING_PARAMETERS 103 +# define EVP_R_NOT_XOF_OR_INVALID_LENGTH 178 +# define EVP_R_NO_CIPHER_SET 131 +# define EVP_R_NO_DEFAULT_DIGEST 158 +# define EVP_R_NO_DIGEST_SET 139 +# define EVP_R_NO_KEY_SET 154 +# define EVP_R_NO_OPERATION_SET 149 +# define EVP_R_ONLY_ONESHOT_SUPPORTED 177 +# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150 +# define EVP_R_OPERATON_NOT_INITIALIZED 151 +# define EVP_R_PARTIALLY_OVERLAPPING 162 +# define EVP_R_PBKDF2_ERROR 181 +# define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179 +# define EVP_R_PRIVATE_KEY_DECODE_ERROR 145 +# define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146 +# define EVP_R_PUBLIC_KEY_NOT_RSA 106 +# define EVP_R_UNKNOWN_CIPHER 160 +# define EVP_R_UNKNOWN_DIGEST 161 +# define EVP_R_UNKNOWN_OPTION 169 +# define EVP_R_UNKNOWN_PBE_ALGORITHM 121 +# define EVP_R_UNSUPPORTED_ALGORITHM 156 +# define EVP_R_UNSUPPORTED_CIPHER 107 +# define EVP_R_UNSUPPORTED_KEYLENGTH 123 +# define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124 +# define EVP_R_UNSUPPORTED_KEY_SIZE 108 +# define EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS 135 +# define EVP_R_UNSUPPORTED_PRF 125 +# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +# define EVP_R_UNSUPPORTED_SALT_TYPE 126 +# define EVP_R_WRAP_MODE_NOT_ALLOWED 170 +# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 + +#endif diff --git a/thirdparty/user_include/openssl/hmac.h b/thirdparty/user_include/openssl/hmac.h new file mode 100755 index 0000000000000000000000000000000000000000..458efc1d5181a89bb8ccab67e296da9ffcb27a7f --- /dev/null +++ b/thirdparty/user_include/openssl/hmac.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_HMAC_H +# define HEADER_HMAC_H + +# include + +# include + +# if OPENSSL_API_COMPAT < 0x10200000L +# define HMAC_MAX_MD_CBLOCK 128 /* Deprecated */ +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +size_t HMAC_size(const HMAC_CTX *e); +HMAC_CTX *HMAC_CTX_new(void); +int HMAC_CTX_reset(HMAC_CTX *ctx); +void HMAC_CTX_free(HMAC_CTX *ctx); + +DEPRECATEDIN_1_1_0(__owur int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md)) + +/*__owur*/ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl); +/*__owur*/ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, + size_t len); +/*__owur*/ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, + unsigned int *len); +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, + unsigned int *md_len); +__owur int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx); + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags); +const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/idea.h b/thirdparty/user_include/openssl/idea.h new file mode 100755 index 0000000000000000000000000000000000000000..4334f3ea71a67df340b81e1566488b93cff887c6 --- /dev/null +++ b/thirdparty/user_include/openssl/idea.h @@ -0,0 +1,64 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_IDEA_H +# define HEADER_IDEA_H + +# include + +# ifndef OPENSSL_NO_IDEA +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned int IDEA_INT; + +# define IDEA_ENCRYPT 1 +# define IDEA_DECRYPT 0 + +# define IDEA_BLOCK 8 +# define IDEA_KEY_LENGTH 16 + +typedef struct idea_key_st { + IDEA_INT data[9][6]; +} IDEA_KEY_SCHEDULE; + +const char *IDEA_options(void); +void IDEA_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +void IDEA_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void IDEA_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); +void IDEA_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int enc); +void IDEA_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num, int enc); +void IDEA_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num); +void IDEA_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define idea_options IDEA_options +# define idea_ecb_encrypt IDEA_ecb_encrypt +# define idea_set_encrypt_key IDEA_set_encrypt_key +# define idea_set_decrypt_key IDEA_set_decrypt_key +# define idea_cbc_encrypt IDEA_cbc_encrypt +# define idea_cfb64_encrypt IDEA_cfb64_encrypt +# define idea_ofb64_encrypt IDEA_ofb64_encrypt +# define idea_encrypt IDEA_encrypt +# endif + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/kdf.h b/thirdparty/user_include/openssl/kdf.h new file mode 100755 index 0000000000000000000000000000000000000000..5abd4c3714756a021b5a6c16ff0523fe7fd94fcf --- /dev/null +++ b/thirdparty/user_include/openssl/kdf.h @@ -0,0 +1,97 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_KDF_H +# define HEADER_KDF_H + +# include +#ifdef __cplusplus +extern "C" { +#endif + +# define EVP_PKEY_CTRL_TLS_MD (EVP_PKEY_ALG_CTRL) +# define EVP_PKEY_CTRL_TLS_SECRET (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_TLS_SEED (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_HKDF_MD (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_HKDF_SALT (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_PASS (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_SCRYPT_SALT (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_SCRYPT_N (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SCRYPT_R (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_SCRYPT_P (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES (EVP_PKEY_ALG_CTRL + 13) + +# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0 +# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1 +# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2 + +# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)(sec)) + +# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)(seed)) + +# define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set1_hkdf_key(pctx, key, keylen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key)) + +# define EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info)) + +# define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MODE, mode, NULL) + +# define EVP_PKEY_CTX_set1_pbe_pass(pctx, pass, passlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_PASS, passlen, (void *)(pass)) + +# define EVP_PKEY_CTX_set1_scrypt_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set_scrypt_N(pctx, n) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_N, n) + +# define EVP_PKEY_CTX_set_scrypt_r(pctx, r) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_R, r) + +# define EVP_PKEY_CTX_set_scrypt_p(pctx, p) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_P, p) + +# define EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, maxmem_bytes) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes) + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/kdferr.h b/thirdparty/user_include/openssl/kdferr.h new file mode 100755 index 0000000000000000000000000000000000000000..6437c271dd6ab083526870db66172923ff09510a --- /dev/null +++ b/thirdparty/user_include/openssl/kdferr.h @@ -0,0 +1,51 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_KDFERR_H +# define HEADER_KDFERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_KDF_strings(void); + +/* + * KDF function codes. + */ +# define KDF_F_PKEY_HKDF_CTRL_STR 103 +# define KDF_F_PKEY_HKDF_DERIVE 102 +# define KDF_F_PKEY_HKDF_INIT 108 +# define KDF_F_PKEY_SCRYPT_CTRL_STR 104 +# define KDF_F_PKEY_SCRYPT_CTRL_UINT64 105 +# define KDF_F_PKEY_SCRYPT_DERIVE 109 +# define KDF_F_PKEY_SCRYPT_INIT 106 +# define KDF_F_PKEY_SCRYPT_SET_MEMBUF 107 +# define KDF_F_PKEY_TLS1_PRF_CTRL_STR 100 +# define KDF_F_PKEY_TLS1_PRF_DERIVE 101 +# define KDF_F_PKEY_TLS1_PRF_INIT 110 +# define KDF_F_TLS1_PRF_ALG 111 + +/* + * KDF reason codes. + */ +# define KDF_R_INVALID_DIGEST 100 +# define KDF_R_MISSING_ITERATION_COUNT 109 +# define KDF_R_MISSING_KEY 104 +# define KDF_R_MISSING_MESSAGE_DIGEST 105 +# define KDF_R_MISSING_PARAMETER 101 +# define KDF_R_MISSING_PASS 110 +# define KDF_R_MISSING_SALT 111 +# define KDF_R_MISSING_SECRET 107 +# define KDF_R_MISSING_SEED 106 +# define KDF_R_UNKNOWN_PARAMETER_TYPE 103 +# define KDF_R_VALUE_ERROR 108 +# define KDF_R_VALUE_MISSING 102 + +#endif diff --git a/thirdparty/user_include/openssl/lhash.h b/thirdparty/user_include/openssl/lhash.h new file mode 100755 index 0000000000000000000000000000000000000000..47b99d17fb8a1e542a965ecb16f3ae4907877593 --- /dev/null +++ b/thirdparty/user_include/openssl/lhash.h @@ -0,0 +1,242 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Header for dynamic hash table routines Author - Eric Young + */ + +#ifndef HEADER_LHASH_H +# define HEADER_LHASH_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct lhash_node_st OPENSSL_LH_NODE; +typedef int (*OPENSSL_LH_COMPFUNC) (const void *, const void *); +typedef unsigned long (*OPENSSL_LH_HASHFUNC) (const void *); +typedef void (*OPENSSL_LH_DOALL_FUNC) (void *); +typedef void (*OPENSSL_LH_DOALL_FUNCARG) (void *, void *); +typedef struct lhash_st OPENSSL_LHASH; + +/* + * Macros for declaring and implementing type-safe wrappers for LHASH + * callbacks. This way, callbacks can be provided to LHASH structures without + * function pointer casting and the macro-defined callbacks provide + * per-variable casting before deferring to the underlying type-specific + * callbacks. NB: It is possible to place a "static" in front of both the + * DECLARE and IMPLEMENT macros if the functions are strictly internal. + */ + +/* First: "hash" functions */ +# define DECLARE_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *); +# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *arg) { \ + const o_type *a = arg; \ + return name##_hash(a); } +# define LHASH_HASH_FN(name) name##_LHASH_HASH + +/* Second: "compare" functions */ +# define DECLARE_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *, const void *); +# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *arg1, const void *arg2) { \ + const o_type *a = arg1; \ + const o_type *b = arg2; \ + return name##_cmp(a,b); } +# define LHASH_COMP_FN(name) name##_LHASH_COMP + +/* Fourth: "doall_arg" functions */ +# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *, void *); +# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ + o_type *a = arg1; \ + a_type *b = arg2; \ + name##_doall_arg(a, b); } +# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG + + +# define LH_LOAD_MULT 256 + +int OPENSSL_LH_error(OPENSSL_LHASH *lh); +OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c); +void OPENSSL_LH_free(OPENSSL_LHASH *lh); +void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data); +void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data); +void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data); +void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func); +void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg); +unsigned long OPENSSL_LH_strhash(const char *c); +unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh); +unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh); +void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load); + +# ifndef OPENSSL_NO_STDIO +void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp); +void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp); +void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp); +# endif +void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out); +void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out); +void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define _LHASH OPENSSL_LHASH +# define LHASH_NODE OPENSSL_LH_NODE +# define lh_error OPENSSL_LH_error +# define lh_new OPENSSL_LH_new +# define lh_free OPENSSL_LH_free +# define lh_insert OPENSSL_LH_insert +# define lh_delete OPENSSL_LH_delete +# define lh_retrieve OPENSSL_LH_retrieve +# define lh_doall OPENSSL_LH_doall +# define lh_doall_arg OPENSSL_LH_doall_arg +# define lh_strhash OPENSSL_LH_strhash +# define lh_num_items OPENSSL_LH_num_items +# ifndef OPENSSL_NO_STDIO +# define lh_stats OPENSSL_LH_stats +# define lh_node_stats OPENSSL_LH_node_stats +# define lh_node_usage_stats OPENSSL_LH_node_usage_stats +# endif +# define lh_stats_bio OPENSSL_LH_stats_bio +# define lh_node_stats_bio OPENSSL_LH_node_stats_bio +# define lh_node_usage_stats_bio OPENSSL_LH_node_usage_stats_bio +# endif + +/* Type checking... */ + +# define LHASH_OF(type) struct lhash_st_##type + +# define DEFINE_LHASH_OF(type) \ + LHASH_OF(type) { union lh_##type##_dummy { void* d1; unsigned long d2; int d3; } dummy; }; \ + static ossl_inline LHASH_OF(type) * \ + lh_##type##_new(unsigned long (*hfn)(const type *), \ + int (*cfn)(const type *, const type *)) \ + { \ + return (LHASH_OF(type) *) \ + OPENSSL_LH_new((OPENSSL_LH_HASHFUNC)hfn, (OPENSSL_LH_COMPFUNC)cfn); \ + } \ + static ossl_unused ossl_inline void lh_##type##_free(LHASH_OF(type) *lh) \ + { \ + OPENSSL_LH_free((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_insert(LHASH_OF(type) *lh, type *d) \ + { \ + return (type *)OPENSSL_LH_insert((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_delete(LHASH_OF(type) *lh, const type *d) \ + { \ + return (type *)OPENSSL_LH_delete((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline type *lh_##type##_retrieve(LHASH_OF(type) *lh, const type *d) \ + { \ + return (type *)OPENSSL_LH_retrieve((OPENSSL_LHASH *)lh, d); \ + } \ + static ossl_unused ossl_inline int lh_##type##_error(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_error((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline unsigned long lh_##type##_num_items(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_num_items((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline void lh_##type##_node_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_node_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline void lh_##type##_node_usage_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_node_usage_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline void lh_##type##_stats_bio(const LHASH_OF(type) *lh, BIO *out) \ + { \ + OPENSSL_LH_stats_bio((const OPENSSL_LHASH *)lh, out); \ + } \ + static ossl_unused ossl_inline unsigned long lh_##type##_get_down_load(LHASH_OF(type) *lh) \ + { \ + return OPENSSL_LH_get_down_load((OPENSSL_LHASH *)lh); \ + } \ + static ossl_unused ossl_inline void lh_##type##_set_down_load(LHASH_OF(type) *lh, unsigned long dl) \ + { \ + OPENSSL_LH_set_down_load((OPENSSL_LHASH *)lh, dl); \ + } \ + static ossl_unused ossl_inline void lh_##type##_doall(LHASH_OF(type) *lh, \ + void (*doall)(type *)) \ + { \ + OPENSSL_LH_doall((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNC)doall); \ + } \ + LHASH_OF(type) + +#define IMPLEMENT_LHASH_DOALL_ARG_CONST(type, argtype) \ + int_implement_lhash_doall(type, argtype, const type) + +#define IMPLEMENT_LHASH_DOALL_ARG(type, argtype) \ + int_implement_lhash_doall(type, argtype, type) + +#define int_implement_lhash_doall(type, argtype, cbargtype) \ + static ossl_unused ossl_inline void \ + lh_##type##_doall_##argtype(LHASH_OF(type) *lh, \ + void (*fn)(cbargtype *, argtype *), \ + argtype *arg) \ + { \ + OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNCARG)fn, (void *)arg); \ + } \ + LHASH_OF(type) + +DEFINE_LHASH_OF(OPENSSL_STRING); +# ifdef _MSC_VER +/* + * push and pop this warning: + * warning C4090: 'function': different 'const' qualifiers + */ +# pragma warning (push) +# pragma warning (disable: 4090) +# endif + +DEFINE_LHASH_OF(OPENSSL_CSTRING); + +# ifdef _MSC_VER +# pragma warning (pop) +# endif + +/* + * If called without higher optimization (min. -xO3) the Oracle Developer + * Studio compiler generates code for the defined (static inline) functions + * above. + * This would later lead to the linker complaining about missing symbols when + * this header file is included but the resulting object is not linked against + * the Crypto library (openssl#6912). + */ +# ifdef __SUNPRO_C +# pragma weak OPENSSL_LH_new +# pragma weak OPENSSL_LH_free +# pragma weak OPENSSL_LH_insert +# pragma weak OPENSSL_LH_delete +# pragma weak OPENSSL_LH_retrieve +# pragma weak OPENSSL_LH_error +# pragma weak OPENSSL_LH_num_items +# pragma weak OPENSSL_LH_node_stats_bio +# pragma weak OPENSSL_LH_node_usage_stats_bio +# pragma weak OPENSSL_LH_stats_bio +# pragma weak OPENSSL_LH_get_down_load +# pragma weak OPENSSL_LH_set_down_load +# pragma weak OPENSSL_LH_doall +# pragma weak OPENSSL_LH_doall_arg +# endif /* __SUNPRO_C */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/md2.h b/thirdparty/user_include/openssl/md2.h new file mode 100755 index 0000000000000000000000000000000000000000..7faf8e3d6566fb1efe6a12d073237f86fe8f1d5d --- /dev/null +++ b/thirdparty/user_include/openssl/md2.h @@ -0,0 +1,44 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD2_H +# define HEADER_MD2_H + +# include + +# ifndef OPENSSL_NO_MD2 +# include +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned char MD2_INT; + +# define MD2_DIGEST_LENGTH 16 +# define MD2_BLOCK 16 + +typedef struct MD2state_st { + unsigned int num; + unsigned char data[MD2_BLOCK]; + MD2_INT cksm[MD2_BLOCK]; + MD2_INT state[MD2_BLOCK]; +} MD2_CTX; + +const char *MD2_options(void); +int MD2_Init(MD2_CTX *c); +int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len); +int MD2_Final(unsigned char *md, MD2_CTX *c); +unsigned char *MD2(const unsigned char *d, size_t n, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/md4.h b/thirdparty/user_include/openssl/md4.h new file mode 100755 index 0000000000000000000000000000000000000000..940e29db409c1726c0180dc2d84c34111a2d2a98 --- /dev/null +++ b/thirdparty/user_include/openssl/md4.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD4_H +# define HEADER_MD4_H + +# include + +# ifndef OPENSSL_NO_MD4 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD4_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define MD4_LONG unsigned int + +# define MD4_CBLOCK 64 +# define MD4_LBLOCK (MD4_CBLOCK/4) +# define MD4_DIGEST_LENGTH 16 + +typedef struct MD4state_st { + MD4_LONG A, B, C, D; + MD4_LONG Nl, Nh; + MD4_LONG data[MD4_LBLOCK]; + unsigned int num; +} MD4_CTX; + +int MD4_Init(MD4_CTX *c); +int MD4_Update(MD4_CTX *c, const void *data, size_t len); +int MD4_Final(unsigned char *md, MD4_CTX *c); +unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md); +void MD4_Transform(MD4_CTX *c, const unsigned char *b); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/md5.h b/thirdparty/user_include/openssl/md5.h new file mode 100755 index 0000000000000000000000000000000000000000..2deb772118f2f2d6f04f4784f771135497954213 --- /dev/null +++ b/thirdparty/user_include/openssl/md5.h @@ -0,0 +1,50 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MD5_H +# define HEADER_MD5_H + +# include + +# ifndef OPENSSL_NO_MD5 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define MD5_LONG unsigned int + +# define MD5_CBLOCK 64 +# define MD5_LBLOCK (MD5_CBLOCK/4) +# define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st { + MD5_LONG A, B, C, D; + MD5_LONG Nl, Nh; + MD5_LONG data[MD5_LBLOCK]; + unsigned int num; +} MD5_CTX; + +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, size_t len); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/mdc2.h b/thirdparty/user_include/openssl/mdc2.h new file mode 100755 index 0000000000000000000000000000000000000000..aabd2bfaad8c48dd612b4fc24c8270c0849e2c6a --- /dev/null +++ b/thirdparty/user_include/openssl/mdc2.h @@ -0,0 +1,42 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MDC2_H +# define HEADER_MDC2_H + +# include + +#ifndef OPENSSL_NO_MDC2 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define MDC2_BLOCK 8 +# define MDC2_DIGEST_LENGTH 16 + +typedef struct mdc2_ctx_st { + unsigned int num; + unsigned char data[MDC2_BLOCK]; + DES_cblock h, hh; + int pad_type; /* either 1 or 2, default 1 */ +} MDC2_CTX; + +int MDC2_Init(MDC2_CTX *c); +int MDC2_Update(MDC2_CTX *c, const unsigned char *data, size_t len); +int MDC2_Final(unsigned char *md, MDC2_CTX *c); +unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/modes.h b/thirdparty/user_include/openssl/modes.h new file mode 100755 index 0000000000000000000000000000000000000000..d544f98d5585e9ab2e6b3ce68682607e7ba0c993 --- /dev/null +++ b/thirdparty/user_include/openssl/modes.h @@ -0,0 +1,208 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_MODES_H +# define HEADER_MODES_H + +# include + +# ifdef __cplusplus +extern "C" { +# endif +typedef void (*block128_f) (const unsigned char in[16], + unsigned char out[16], const void *key); + +typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int enc); + +typedef void (*ctr128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16]); + +typedef void (*ccm128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16], + unsigned char cmac[16]); + +void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); + +void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], unsigned int *num, + block128_f block); + +void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], + unsigned int *num, ctr128_f ctr); + +void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block); + +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); + +size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +typedef struct gcm128_context GCM128_CONTEXT; + +GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block); +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block); +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, + size_t len); +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx); + +typedef struct ccm128_context CCM128_CONTEXT; + +void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, + block128_f block); +int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, const unsigned char *nonce, + size_t nlen, size_t mlen); +void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, const unsigned char *aad, + size_t alen); +int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len); + +typedef struct xts128_context XTS128_CONTEXT; + +int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, + size_t len, int enc); + +size_t CRYPTO_128_wrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); + +size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); +size_t CRYPTO_128_wrap_pad(void *key, const unsigned char *icv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block); +size_t CRYPTO_128_unwrap_pad(void *key, const unsigned char *icv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block); + +# ifndef OPENSSL_NO_OCB +typedef struct ocb128_context OCB128_CONTEXT; + +typedef void (*ocb128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + size_t start_block_num, + unsigned char offset_i[16], + const unsigned char L_[][16], + unsigned char checksum[16]); + +OCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream); +int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, + block128_f encrypt, block128_f decrypt, + ocb128_f stream); +int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src, + void *keyenc, void *keydec); +int CRYPTO_ocb128_setiv(OCB128_CONTEXT *ctx, const unsigned char *iv, + size_t len, size_t taglen); +int CRYPTO_ocb128_aad(OCB128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, const unsigned char *in, + unsigned char *out, size_t len); +int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx, const unsigned char *in, + unsigned char *out, size_t len); +int CRYPTO_ocb128_finish(OCB128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +int CRYPTO_ocb128_tag(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_ocb128_cleanup(OCB128_CONTEXT *ctx); +# endif /* OPENSSL_NO_OCB */ + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/thirdparty/user_include/openssl/obj_mac.h b/thirdparty/user_include/openssl/obj_mac.h new file mode 100755 index 0000000000000000000000000000000000000000..31fad4640fe438ce60545883c1f6bb4cc03e8752 --- /dev/null +++ b/thirdparty/user_include/openssl/obj_mac.h @@ -0,0 +1,5198 @@ +/* + * WARNING: do not edit! + * Generated by crypto/objects/objects.pl + * + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_itu_t "ITU-T" +#define LN_itu_t "itu-t" +#define NID_itu_t 645 +#define OBJ_itu_t 0L + +#define NID_ccitt 404 +#define OBJ_ccitt OBJ_itu_t + +#define SN_iso "ISO" +#define LN_iso "iso" +#define NID_iso 181 +#define OBJ_iso 1L + +#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T" +#define LN_joint_iso_itu_t "joint-iso-itu-t" +#define NID_joint_iso_itu_t 646 +#define OBJ_joint_iso_itu_t 2L + +#define NID_joint_iso_ccitt 393 +#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t + +#define SN_member_body "member-body" +#define LN_member_body "ISO Member Body" +#define NID_member_body 182 +#define OBJ_member_body OBJ_iso,2L + +#define SN_identified_organization "identified-organization" +#define NID_identified_organization 676 +#define OBJ_identified_organization OBJ_iso,3L + +#define SN_hmac_md5 "HMAC-MD5" +#define LN_hmac_md5 "hmac-md5" +#define NID_hmac_md5 780 +#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L + +#define SN_hmac_sha1 "HMAC-SHA1" +#define LN_hmac_sha1 "hmac-sha1" +#define NID_hmac_sha1 781 +#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L + +#define SN_x509ExtAdmission "x509ExtAdmission" +#define LN_x509ExtAdmission "Professional Information or basis for Admission" +#define NID_x509ExtAdmission 1093 +#define OBJ_x509ExtAdmission OBJ_identified_organization,36L,8L,3L,3L + +#define SN_certicom_arc "certicom-arc" +#define NID_certicom_arc 677 +#define OBJ_certicom_arc OBJ_identified_organization,132L + +#define SN_ieee "ieee" +#define NID_ieee 1170 +#define OBJ_ieee OBJ_identified_organization,111L + +#define SN_ieee_siswg "ieee-siswg" +#define LN_ieee_siswg "IEEE Security in Storage Working Group" +#define NID_ieee_siswg 1171 +#define OBJ_ieee_siswg OBJ_ieee,2L,1619L + +#define SN_international_organizations "international-organizations" +#define LN_international_organizations "International Organizations" +#define NID_international_organizations 647 +#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L + +#define SN_wap "wap" +#define NID_wap 678 +#define OBJ_wap OBJ_international_organizations,43L + +#define SN_wap_wsg "wap-wsg" +#define NID_wap_wsg 679 +#define OBJ_wap_wsg OBJ_wap,1L + +#define SN_selected_attribute_types "selected-attribute-types" +#define LN_selected_attribute_types "Selected Attribute Types" +#define NID_selected_attribute_types 394 +#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L + +#define SN_clearance "clearance" +#define NID_clearance 395 +#define OBJ_clearance OBJ_selected_attribute_types,55L + +#define SN_ISO_US "ISO-US" +#define LN_ISO_US "ISO US Member Body" +#define NID_ISO_US 183 +#define OBJ_ISO_US OBJ_member_body,840L + +#define SN_X9_57 "X9-57" +#define LN_X9_57 "X9.57" +#define NID_X9_57 184 +#define OBJ_X9_57 OBJ_ISO_US,10040L + +#define SN_X9cm "X9cm" +#define LN_X9cm "X9.57 CM ?" +#define NID_X9cm 185 +#define OBJ_X9cm OBJ_X9_57,4L + +#define SN_ISO_CN "ISO-CN" +#define LN_ISO_CN "ISO CN Member Body" +#define NID_ISO_CN 1140 +#define OBJ_ISO_CN OBJ_member_body,156L + +#define SN_oscca "oscca" +#define NID_oscca 1141 +#define OBJ_oscca OBJ_ISO_CN,10197L + +#define SN_sm_scheme "sm-scheme" +#define NID_sm_scheme 1142 +#define OBJ_sm_scheme OBJ_oscca,1L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa OBJ_X9cm,1L + +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 OBJ_X9cm,3L + +#define SN_ansi_X9_62 "ansi-X9-62" +#define LN_ansi_X9_62 "ANSI X9.62" +#define NID_ansi_X9_62 405 +#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L + +#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L + +#define SN_X9_62_prime_field "prime-field" +#define NID_X9_62_prime_field 406 +#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L + +#define SN_X9_62_characteristic_two_field "characteristic-two-field" +#define NID_X9_62_characteristic_two_field 407 +#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L + +#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis" +#define NID_X9_62_id_characteristic_two_basis 680 +#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L + +#define SN_X9_62_onBasis "onBasis" +#define NID_X9_62_onBasis 681 +#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L + +#define SN_X9_62_tpBasis "tpBasis" +#define NID_X9_62_tpBasis 682 +#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L + +#define SN_X9_62_ppBasis "ppBasis" +#define NID_X9_62_ppBasis 683 +#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L + +#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L + +#define SN_X9_62_id_ecPublicKey "id-ecPublicKey" +#define NID_X9_62_id_ecPublicKey 408 +#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L + +#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L + +#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L + +#define SN_X9_62_c2pnb163v1 "c2pnb163v1" +#define NID_X9_62_c2pnb163v1 684 +#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L + +#define SN_X9_62_c2pnb163v2 "c2pnb163v2" +#define NID_X9_62_c2pnb163v2 685 +#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L + +#define SN_X9_62_c2pnb163v3 "c2pnb163v3" +#define NID_X9_62_c2pnb163v3 686 +#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L + +#define SN_X9_62_c2pnb176v1 "c2pnb176v1" +#define NID_X9_62_c2pnb176v1 687 +#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L + +#define SN_X9_62_c2tnb191v1 "c2tnb191v1" +#define NID_X9_62_c2tnb191v1 688 +#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L + +#define SN_X9_62_c2tnb191v2 "c2tnb191v2" +#define NID_X9_62_c2tnb191v2 689 +#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L + +#define SN_X9_62_c2tnb191v3 "c2tnb191v3" +#define NID_X9_62_c2tnb191v3 690 +#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L + +#define SN_X9_62_c2onb191v4 "c2onb191v4" +#define NID_X9_62_c2onb191v4 691 +#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L + +#define SN_X9_62_c2onb191v5 "c2onb191v5" +#define NID_X9_62_c2onb191v5 692 +#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L + +#define SN_X9_62_c2pnb208w1 "c2pnb208w1" +#define NID_X9_62_c2pnb208w1 693 +#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L + +#define SN_X9_62_c2tnb239v1 "c2tnb239v1" +#define NID_X9_62_c2tnb239v1 694 +#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L + +#define SN_X9_62_c2tnb239v2 "c2tnb239v2" +#define NID_X9_62_c2tnb239v2 695 +#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L + +#define SN_X9_62_c2tnb239v3 "c2tnb239v3" +#define NID_X9_62_c2tnb239v3 696 +#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L + +#define SN_X9_62_c2onb239v4 "c2onb239v4" +#define NID_X9_62_c2onb239v4 697 +#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L + +#define SN_X9_62_c2onb239v5 "c2onb239v5" +#define NID_X9_62_c2onb239v5 698 +#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L + +#define SN_X9_62_c2pnb272w1 "c2pnb272w1" +#define NID_X9_62_c2pnb272w1 699 +#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L + +#define SN_X9_62_c2pnb304w1 "c2pnb304w1" +#define NID_X9_62_c2pnb304w1 700 +#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L + +#define SN_X9_62_c2tnb359v1 "c2tnb359v1" +#define NID_X9_62_c2tnb359v1 701 +#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L + +#define SN_X9_62_c2pnb368w1 "c2pnb368w1" +#define NID_X9_62_c2pnb368w1 702 +#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L + +#define SN_X9_62_c2tnb431r1 "c2tnb431r1" +#define NID_X9_62_c2tnb431r1 703 +#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L + +#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L + +#define SN_X9_62_prime192v1 "prime192v1" +#define NID_X9_62_prime192v1 409 +#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L + +#define SN_X9_62_prime192v2 "prime192v2" +#define NID_X9_62_prime192v2 410 +#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L + +#define SN_X9_62_prime192v3 "prime192v3" +#define NID_X9_62_prime192v3 411 +#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L + +#define SN_X9_62_prime239v1 "prime239v1" +#define NID_X9_62_prime239v1 412 +#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L + +#define SN_X9_62_prime239v2 "prime239v2" +#define NID_X9_62_prime239v2 413 +#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L + +#define SN_X9_62_prime239v3 "prime239v3" +#define NID_X9_62_prime239v3 414 +#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L + +#define SN_X9_62_prime256v1 "prime256v1" +#define NID_X9_62_prime256v1 415 +#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L + +#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L + +#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1" +#define NID_ecdsa_with_SHA1 416 +#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L + +#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended" +#define NID_ecdsa_with_Recommended 791 +#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L + +#define SN_ecdsa_with_Specified "ecdsa-with-Specified" +#define NID_ecdsa_with_Specified 792 +#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L + +#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224" +#define NID_ecdsa_with_SHA224 793 +#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L + +#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256" +#define NID_ecdsa_with_SHA256 794 +#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L + +#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384" +#define NID_ecdsa_with_SHA384 795 +#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L + +#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512" +#define NID_ecdsa_with_SHA512 796 +#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L + +#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L + +#define SN_secp112r1 "secp112r1" +#define NID_secp112r1 704 +#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L + +#define SN_secp112r2 "secp112r2" +#define NID_secp112r2 705 +#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L + +#define SN_secp128r1 "secp128r1" +#define NID_secp128r1 706 +#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L + +#define SN_secp128r2 "secp128r2" +#define NID_secp128r2 707 +#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L + +#define SN_secp160k1 "secp160k1" +#define NID_secp160k1 708 +#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L + +#define SN_secp160r1 "secp160r1" +#define NID_secp160r1 709 +#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L + +#define SN_secp160r2 "secp160r2" +#define NID_secp160r2 710 +#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L + +#define SN_secp192k1 "secp192k1" +#define NID_secp192k1 711 +#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L + +#define SN_secp224k1 "secp224k1" +#define NID_secp224k1 712 +#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L + +#define SN_secp224r1 "secp224r1" +#define NID_secp224r1 713 +#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L + +#define SN_secp256k1 "secp256k1" +#define NID_secp256k1 714 +#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L + +#define SN_secp384r1 "secp384r1" +#define NID_secp384r1 715 +#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L + +#define SN_secp521r1 "secp521r1" +#define NID_secp521r1 716 +#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L + +#define SN_sect113r1 "sect113r1" +#define NID_sect113r1 717 +#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L + +#define SN_sect113r2 "sect113r2" +#define NID_sect113r2 718 +#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L + +#define SN_sect131r1 "sect131r1" +#define NID_sect131r1 719 +#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L + +#define SN_sect131r2 "sect131r2" +#define NID_sect131r2 720 +#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L + +#define SN_sect163k1 "sect163k1" +#define NID_sect163k1 721 +#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L + +#define SN_sect163r1 "sect163r1" +#define NID_sect163r1 722 +#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L + +#define SN_sect163r2 "sect163r2" +#define NID_sect163r2 723 +#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L + +#define SN_sect193r1 "sect193r1" +#define NID_sect193r1 724 +#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L + +#define SN_sect193r2 "sect193r2" +#define NID_sect193r2 725 +#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L + +#define SN_sect233k1 "sect233k1" +#define NID_sect233k1 726 +#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L + +#define SN_sect233r1 "sect233r1" +#define NID_sect233r1 727 +#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L + +#define SN_sect239k1 "sect239k1" +#define NID_sect239k1 728 +#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L + +#define SN_sect283k1 "sect283k1" +#define NID_sect283k1 729 +#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L + +#define SN_sect283r1 "sect283r1" +#define NID_sect283r1 730 +#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L + +#define SN_sect409k1 "sect409k1" +#define NID_sect409k1 731 +#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L + +#define SN_sect409r1 "sect409r1" +#define NID_sect409r1 732 +#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L + +#define SN_sect571k1 "sect571k1" +#define NID_sect571k1 733 +#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L + +#define SN_sect571r1 "sect571r1" +#define NID_sect571r1 734 +#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L + +#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L + +#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1" +#define NID_wap_wsg_idm_ecid_wtls1 735 +#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L + +#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3" +#define NID_wap_wsg_idm_ecid_wtls3 736 +#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L + +#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4" +#define NID_wap_wsg_idm_ecid_wtls4 737 +#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L + +#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5" +#define NID_wap_wsg_idm_ecid_wtls5 738 +#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L + +#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6" +#define NID_wap_wsg_idm_ecid_wtls6 739 +#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L + +#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7" +#define NID_wap_wsg_idm_ecid_wtls7 740 +#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L + +#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8" +#define NID_wap_wsg_idm_ecid_wtls8 741 +#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L + +#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9" +#define NID_wap_wsg_idm_ecid_wtls9 742 +#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L + +#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10" +#define NID_wap_wsg_idm_ecid_wtls10 743 +#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L + +#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11" +#define NID_wap_wsg_idm_ecid_wtls11 744 +#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L + +#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12" +#define NID_wap_wsg_idm_ecid_wtls12 745 +#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L + +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L + +#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC" +#define LN_id_PasswordBasedMAC "password based MAC" +#define NID_id_PasswordBasedMAC 782 +#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L + +#define SN_id_DHBasedMac "id-DHBasedMac" +#define LN_id_DHBasedMac "Diffie-Hellman based MAC" +#define NID_id_DHBasedMac 783 +#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L + +#define SN_rsadsi "rsadsi" +#define LN_rsadsi "RSA Data Security, Inc." +#define NID_rsadsi 1 +#define OBJ_rsadsi OBJ_ISO_US,113549L + +#define SN_pkcs "pkcs" +#define LN_pkcs "RSA Data Security, Inc. PKCS" +#define NID_pkcs 2 +#define OBJ_pkcs OBJ_rsadsi,1L + +#define SN_pkcs1 "pkcs1" +#define NID_pkcs1 186 +#define OBJ_pkcs1 OBJ_pkcs,1L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption OBJ_pkcs1,1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L + +#define SN_md4WithRSAEncryption "RSA-MD4" +#define LN_md4WithRSAEncryption "md4WithRSAEncryption" +#define NID_md4WithRSAEncryption 396 +#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L + +#define SN_rsaesOaep "RSAES-OAEP" +#define LN_rsaesOaep "rsaesOaep" +#define NID_rsaesOaep 919 +#define OBJ_rsaesOaep OBJ_pkcs1,7L + +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 911 +#define OBJ_mgf1 OBJ_pkcs1,8L + +#define SN_pSpecified "PSPECIFIED" +#define LN_pSpecified "pSpecified" +#define NID_pSpecified 935 +#define OBJ_pSpecified OBJ_pkcs1,9L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 912 +#define OBJ_rsassaPss OBJ_pkcs1,10L + +#define SN_sha256WithRSAEncryption "RSA-SHA256" +#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" +#define NID_sha256WithRSAEncryption 668 +#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L + +#define SN_sha384WithRSAEncryption "RSA-SHA384" +#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption" +#define NID_sha384WithRSAEncryption 669 +#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L + +#define SN_sha512WithRSAEncryption "RSA-SHA512" +#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption" +#define NID_sha512WithRSAEncryption 670 +#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L + +#define SN_sha224WithRSAEncryption "RSA-SHA224" +#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption" +#define NID_sha224WithRSAEncryption 671 +#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L + +#define SN_sha512_224WithRSAEncryption "RSA-SHA512/224" +#define LN_sha512_224WithRSAEncryption "sha512-224WithRSAEncryption" +#define NID_sha512_224WithRSAEncryption 1145 +#define OBJ_sha512_224WithRSAEncryption OBJ_pkcs1,15L + +#define SN_sha512_256WithRSAEncryption "RSA-SHA512/256" +#define LN_sha512_256WithRSAEncryption "sha512-256WithRSAEncryption" +#define NID_sha512_256WithRSAEncryption 1146 +#define OBJ_sha512_256WithRSAEncryption OBJ_pkcs1,16L + +#define SN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 OBJ_pkcs,3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +#define SN_pkcs5 "pkcs5" +#define NID_pkcs5 187 +#define OBJ_pkcs5 OBJ_pkcs,5L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L + +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L + +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 OBJ_pkcs5,12L + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 OBJ_pkcs5,13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 OBJ_pkcs5,14L + +#define SN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 OBJ_pkcs,7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data OBJ_pkcs7,1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed OBJ_pkcs7,2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest OBJ_pkcs7,5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +#define SN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 OBJ_pkcs,9L + +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +#define SN_ext_req "extReq" +#define LN_ext_req "Extension Request" +#define NID_ext_req 172 +#define OBJ_ext_req OBJ_pkcs9,14L + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +#define SN_SMIME "SMIME" +#define LN_SMIME "S/MIME" +#define NID_SMIME 188 +#define OBJ_SMIME OBJ_pkcs9,16L + +#define SN_id_smime_mod "id-smime-mod" +#define NID_id_smime_mod 189 +#define OBJ_id_smime_mod OBJ_SMIME,0L + +#define SN_id_smime_ct "id-smime-ct" +#define NID_id_smime_ct 190 +#define OBJ_id_smime_ct OBJ_SMIME,1L + +#define SN_id_smime_aa "id-smime-aa" +#define NID_id_smime_aa 191 +#define OBJ_id_smime_aa OBJ_SMIME,2L + +#define SN_id_smime_alg "id-smime-alg" +#define NID_id_smime_alg 192 +#define OBJ_id_smime_alg OBJ_SMIME,3L + +#define SN_id_smime_cd "id-smime-cd" +#define NID_id_smime_cd 193 +#define OBJ_id_smime_cd OBJ_SMIME,4L + +#define SN_id_smime_spq "id-smime-spq" +#define NID_id_smime_spq 194 +#define OBJ_id_smime_spq OBJ_SMIME,5L + +#define SN_id_smime_cti "id-smime-cti" +#define NID_id_smime_cti 195 +#define OBJ_id_smime_cti OBJ_SMIME,6L + +#define SN_id_smime_mod_cms "id-smime-mod-cms" +#define NID_id_smime_mod_cms 196 +#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L + +#define SN_id_smime_mod_ess "id-smime-mod-ess" +#define NID_id_smime_mod_ess 197 +#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L + +#define SN_id_smime_mod_oid "id-smime-mod-oid" +#define NID_id_smime_mod_oid 198 +#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L + +#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3" +#define NID_id_smime_mod_msg_v3 199 +#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L + +#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88" +#define NID_id_smime_mod_ets_eSignature_88 200 +#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L + +#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97" +#define NID_id_smime_mod_ets_eSignature_97 201 +#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L + +#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88" +#define NID_id_smime_mod_ets_eSigPolicy_88 202 +#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L + +#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97" +#define NID_id_smime_mod_ets_eSigPolicy_97 203 +#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L + +#define SN_id_smime_ct_receipt "id-smime-ct-receipt" +#define NID_id_smime_ct_receipt 204 +#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L + +#define SN_id_smime_ct_authData "id-smime-ct-authData" +#define NID_id_smime_ct_authData 205 +#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L + +#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert" +#define NID_id_smime_ct_publishCert 206 +#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L + +#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo" +#define NID_id_smime_ct_TSTInfo 207 +#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L + +#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo" +#define NID_id_smime_ct_TDTInfo 208 +#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L + +#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo" +#define NID_id_smime_ct_contentInfo 209 +#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L + +#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData" +#define NID_id_smime_ct_DVCSRequestData 210 +#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L + +#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData" +#define NID_id_smime_ct_DVCSResponseData 211 +#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L + +#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData" +#define NID_id_smime_ct_compressedData 786 +#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L + +#define SN_id_smime_ct_contentCollection "id-smime-ct-contentCollection" +#define NID_id_smime_ct_contentCollection 1058 +#define OBJ_id_smime_ct_contentCollection OBJ_id_smime_ct,19L + +#define SN_id_smime_ct_authEnvelopedData "id-smime-ct-authEnvelopedData" +#define NID_id_smime_ct_authEnvelopedData 1059 +#define OBJ_id_smime_ct_authEnvelopedData OBJ_id_smime_ct,23L + +#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF" +#define NID_id_ct_asciiTextWithCRLF 787 +#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L + +#define SN_id_ct_xml "id-ct-xml" +#define NID_id_ct_xml 1060 +#define OBJ_id_ct_xml OBJ_id_smime_ct,28L + +#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" +#define NID_id_smime_aa_receiptRequest 212 +#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L + +#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel" +#define NID_id_smime_aa_securityLabel 213 +#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L + +#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory" +#define NID_id_smime_aa_mlExpandHistory 214 +#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L + +#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint" +#define NID_id_smime_aa_contentHint 215 +#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L + +#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest" +#define NID_id_smime_aa_msgSigDigest 216 +#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L + +#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType" +#define NID_id_smime_aa_encapContentType 217 +#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L + +#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier" +#define NID_id_smime_aa_contentIdentifier 218 +#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L + +#define SN_id_smime_aa_macValue "id-smime-aa-macValue" +#define NID_id_smime_aa_macValue 219 +#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L + +#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels" +#define NID_id_smime_aa_equivalentLabels 220 +#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L + +#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference" +#define NID_id_smime_aa_contentReference 221 +#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L + +#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref" +#define NID_id_smime_aa_encrypKeyPref 222 +#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L + +#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate" +#define NID_id_smime_aa_signingCertificate 223 +#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L + +#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts" +#define NID_id_smime_aa_smimeEncryptCerts 224 +#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L + +#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken" +#define NID_id_smime_aa_timeStampToken 225 +#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L + +#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId" +#define NID_id_smime_aa_ets_sigPolicyId 226 +#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L + +#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType" +#define NID_id_smime_aa_ets_commitmentType 227 +#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L + +#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation" +#define NID_id_smime_aa_ets_signerLocation 228 +#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L + +#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr" +#define NID_id_smime_aa_ets_signerAttr 229 +#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L + +#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert" +#define NID_id_smime_aa_ets_otherSigCert 230 +#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L + +#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp" +#define NID_id_smime_aa_ets_contentTimestamp 231 +#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L + +#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs" +#define NID_id_smime_aa_ets_CertificateRefs 232 +#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L + +#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs" +#define NID_id_smime_aa_ets_RevocationRefs 233 +#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L + +#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues" +#define NID_id_smime_aa_ets_certValues 234 +#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L + +#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues" +#define NID_id_smime_aa_ets_revocationValues 235 +#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L + +#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp" +#define NID_id_smime_aa_ets_escTimeStamp 236 +#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L + +#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp" +#define NID_id_smime_aa_ets_certCRLTimestamp 237 +#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L + +#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp" +#define NID_id_smime_aa_ets_archiveTimeStamp 238 +#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L + +#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType" +#define NID_id_smime_aa_signatureType 239 +#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L + +#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc" +#define NID_id_smime_aa_dvcs_dvc 240 +#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L + +#define SN_id_smime_aa_signingCertificateV2 "id-smime-aa-signingCertificateV2" +#define NID_id_smime_aa_signingCertificateV2 1086 +#define OBJ_id_smime_aa_signingCertificateV2 OBJ_id_smime_aa,47L + +#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" +#define NID_id_smime_alg_ESDHwith3DES 241 +#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L + +#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2" +#define NID_id_smime_alg_ESDHwithRC2 242 +#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L + +#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap" +#define NID_id_smime_alg_3DESwrap 243 +#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L + +#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap" +#define NID_id_smime_alg_RC2wrap 244 +#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L + +#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH" +#define NID_id_smime_alg_ESDH 245 +#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L + +#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap" +#define NID_id_smime_alg_CMS3DESwrap 246 +#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L + +#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap" +#define NID_id_smime_alg_CMSRC2wrap 247 +#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L + +#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK" +#define NID_id_alg_PWRI_KEK 893 +#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L + +#define SN_id_smime_cd_ldap "id-smime-cd-ldap" +#define NID_id_smime_cd_ldap 248 +#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L + +#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri" +#define NID_id_smime_spq_ets_sqt_uri 249 +#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L + +#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice" +#define NID_id_smime_spq_ets_sqt_unotice 250 +#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L + +#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin" +#define NID_id_smime_cti_ets_proofOfOrigin 251 +#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L + +#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt" +#define NID_id_smime_cti_ets_proofOfReceipt 252 +#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L + +#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery" +#define NID_id_smime_cti_ets_proofOfDelivery 253 +#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L + +#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender" +#define NID_id_smime_cti_ets_proofOfSender 254 +#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L + +#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval" +#define NID_id_smime_cti_ets_proofOfApproval 255 +#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L + +#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation" +#define NID_id_smime_cti_ets_proofOfCreation 256 +#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName OBJ_pkcs9,20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID OBJ_pkcs9,21L + +#define SN_ms_csp_name "CSPName" +#define LN_ms_csp_name "Microsoft CSP Name" +#define NID_ms_csp_name 417 +#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L + +#define SN_LocalKeySet "LocalKeySet" +#define LN_LocalKeySet "Microsoft Local Key set" +#define NID_LocalKeySet 856 +#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L + +#define OBJ_certTypes OBJ_pkcs9,22L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate OBJ_certTypes,1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate OBJ_certTypes,2L + +#define OBJ_crlTypes OBJ_pkcs9,23L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl OBJ_crlTypes,1L + +#define OBJ_pkcs12 OBJ_pkcs,12L + +#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L + +#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L + +#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag OBJ_pkcs12_BagIds,1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag OBJ_pkcs12_BagIds,3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag OBJ_pkcs12_BagIds,4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag OBJ_pkcs12_BagIds,5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 OBJ_rsadsi,2L,2L + +#define SN_md4 "MD4" +#define LN_md4 "md4" +#define NID_md4 257 +#define OBJ_md4 OBJ_rsadsi,2L,4L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 OBJ_rsadsi,2L,5L + +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" +#define NID_md5_sha1 114 + +#define LN_hmacWithMD5 "hmacWithMD5" +#define NID_hmacWithMD5 797 +#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +#define SN_sm2 "SM2" +#define LN_sm2 "sm2" +#define NID_sm2 1172 +#define OBJ_sm2 OBJ_sm_scheme,301L + +#define SN_sm3 "SM3" +#define LN_sm3 "sm3" +#define NID_sm3 1143 +#define OBJ_sm3 OBJ_sm_scheme,401L + +#define SN_sm3WithRSAEncryption "RSA-SM3" +#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption" +#define NID_sm3WithRSAEncryption 1144 +#define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L + +#define LN_hmacWithSHA224 "hmacWithSHA224" +#define NID_hmacWithSHA224 798 +#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L + +#define LN_hmacWithSHA256 "hmacWithSHA256" +#define NID_hmacWithSHA256 799 +#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L + +#define LN_hmacWithSHA384 "hmacWithSHA384" +#define NID_hmacWithSHA384 800 +#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L + +#define LN_hmacWithSHA512 "hmacWithSHA512" +#define NID_hmacWithSHA512 801 +#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L + +#define LN_hmacWithSHA512_224 "hmacWithSHA512-224" +#define NID_hmacWithSHA512_224 1193 +#define OBJ_hmacWithSHA512_224 OBJ_rsadsi,2L,12L + +#define LN_hmacWithSHA512_256 "hmacWithSHA512-256" +#define NID_hmacWithSHA512_256 1194 +#define OBJ_hmacWithSHA512_256 OBJ_rsadsi,2L,13L + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 OBJ_rsadsi,3L,4L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_ms_ext_req "msExtReq" +#define LN_ms_ext_req "Microsoft Extension Request" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +#define SN_ms_smartcard_login "msSmartcardLogin" +#define LN_ms_smartcard_login "Microsoft Smartcardlogin" +#define NID_ms_smartcard_login 648 +#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L + +#define SN_ms_upn "msUPN" +#define LN_ms_upn "Microsoft Universal Principal Name" +#define NID_ms_upn 649 +#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +#define SN_id_pkix_mod "id-pkix-mod" +#define NID_id_pkix_mod 258 +#define OBJ_id_pkix_mod OBJ_id_pkix,0L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe OBJ_id_pkix,1L + +#define SN_id_qt "id-qt" +#define NID_id_qt 259 +#define OBJ_id_qt OBJ_id_pkix,2L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp OBJ_id_pkix,3L + +#define SN_id_it "id-it" +#define NID_id_it 260 +#define OBJ_id_it OBJ_id_pkix,4L + +#define SN_id_pkip "id-pkip" +#define NID_id_pkip 261 +#define OBJ_id_pkip OBJ_id_pkix,5L + +#define SN_id_alg "id-alg" +#define NID_id_alg 262 +#define OBJ_id_alg OBJ_id_pkix,6L + +#define SN_id_cmc "id-cmc" +#define NID_id_cmc 263 +#define OBJ_id_cmc OBJ_id_pkix,7L + +#define SN_id_on "id-on" +#define NID_id_on 264 +#define OBJ_id_on OBJ_id_pkix,8L + +#define SN_id_pda "id-pda" +#define NID_id_pda 265 +#define OBJ_id_pda OBJ_id_pkix,9L + +#define SN_id_aca "id-aca" +#define NID_id_aca 266 +#define OBJ_id_aca OBJ_id_pkix,10L + +#define SN_id_qcs "id-qcs" +#define NID_id_qcs 267 +#define OBJ_id_qcs OBJ_id_pkix,11L + +#define SN_id_cct "id-cct" +#define NID_id_cct 268 +#define OBJ_id_cct OBJ_id_pkix,12L + +#define SN_id_ppl "id-ppl" +#define NID_id_ppl 662 +#define OBJ_id_ppl OBJ_id_pkix,21L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad OBJ_id_pkix,48L + +#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88" +#define NID_id_pkix1_explicit_88 269 +#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L + +#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88" +#define NID_id_pkix1_implicit_88 270 +#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L + +#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93" +#define NID_id_pkix1_explicit_93 271 +#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L + +#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93" +#define NID_id_pkix1_implicit_93 272 +#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L + +#define SN_id_mod_crmf "id-mod-crmf" +#define NID_id_mod_crmf 273 +#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L + +#define SN_id_mod_cmc "id-mod-cmc" +#define NID_id_mod_cmc 274 +#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L + +#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88" +#define NID_id_mod_kea_profile_88 275 +#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L + +#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93" +#define NID_id_mod_kea_profile_93 276 +#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L + +#define SN_id_mod_cmp "id-mod-cmp" +#define NID_id_mod_cmp 277 +#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L + +#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88" +#define NID_id_mod_qualified_cert_88 278 +#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L + +#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93" +#define NID_id_mod_qualified_cert_93 279 +#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L + +#define SN_id_mod_attribute_cert "id-mod-attribute-cert" +#define NID_id_mod_attribute_cert 280 +#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L + +#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol" +#define NID_id_mod_timestamp_protocol 281 +#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L + +#define SN_id_mod_ocsp "id-mod-ocsp" +#define NID_id_mod_ocsp 282 +#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L + +#define SN_id_mod_dvcs "id-mod-dvcs" +#define NID_id_mod_dvcs 283 +#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L + +#define SN_id_mod_cmp2000 "id-mod-cmp2000" +#define NID_id_mod_cmp2000 284 +#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access OBJ_id_pe,1L + +#define SN_biometricInfo "biometricInfo" +#define LN_biometricInfo "Biometric Info" +#define NID_biometricInfo 285 +#define OBJ_biometricInfo OBJ_id_pe,2L + +#define SN_qcStatements "qcStatements" +#define NID_qcStatements 286 +#define OBJ_qcStatements OBJ_id_pe,3L + +#define SN_ac_auditEntity "ac-auditEntity" +#define NID_ac_auditEntity 287 +#define OBJ_ac_auditEntity OBJ_id_pe,4L + +#define SN_ac_targeting "ac-targeting" +#define NID_ac_targeting 288 +#define OBJ_ac_targeting OBJ_id_pe,5L + +#define SN_aaControls "aaControls" +#define NID_aaControls 289 +#define OBJ_aaControls OBJ_id_pe,6L + +#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock" +#define NID_sbgp_ipAddrBlock 290 +#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L + +#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum" +#define NID_sbgp_autonomousSysNum 291 +#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L + +#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier" +#define NID_sbgp_routerIdentifier 292 +#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L + +#define SN_ac_proxying "ac-proxying" +#define NID_ac_proxying 397 +#define OBJ_ac_proxying OBJ_id_pe,10L + +#define SN_sinfo_access "subjectInfoAccess" +#define LN_sinfo_access "Subject Information Access" +#define NID_sinfo_access 398 +#define OBJ_sinfo_access OBJ_id_pe,11L + +#define SN_proxyCertInfo "proxyCertInfo" +#define LN_proxyCertInfo "Proxy Certificate Information" +#define NID_proxyCertInfo 663 +#define OBJ_proxyCertInfo OBJ_id_pe,14L + +#define SN_tlsfeature "tlsfeature" +#define LN_tlsfeature "TLS Feature" +#define NID_tlsfeature 1020 +#define OBJ_tlsfeature OBJ_id_pe,24L + +#define SN_id_qt_cps "id-qt-cps" +#define LN_id_qt_cps "Policy Qualifier CPS" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps OBJ_id_qt,1L + +#define SN_id_qt_unotice "id-qt-unotice" +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice OBJ_id_qt,2L + +#define SN_textNotice "textNotice" +#define NID_textNotice 293 +#define OBJ_textNotice OBJ_id_qt,3L + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth OBJ_id_kp,1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth OBJ_id_kp,2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign OBJ_id_kp,3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect OBJ_id_kp,4L + +#define SN_ipsecEndSystem "ipsecEndSystem" +#define LN_ipsecEndSystem "IPSec End System" +#define NID_ipsecEndSystem 294 +#define OBJ_ipsecEndSystem OBJ_id_kp,5L + +#define SN_ipsecTunnel "ipsecTunnel" +#define LN_ipsecTunnel "IPSec Tunnel" +#define NID_ipsecTunnel 295 +#define OBJ_ipsecTunnel OBJ_id_kp,6L + +#define SN_ipsecUser "ipsecUser" +#define LN_ipsecUser "IPSec User" +#define NID_ipsecUser 296 +#define OBJ_ipsecUser OBJ_id_kp,7L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp OBJ_id_kp,8L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + +#define SN_dvcs "DVCS" +#define LN_dvcs "dvcs" +#define NID_dvcs 297 +#define OBJ_dvcs OBJ_id_kp,10L + +#define SN_ipsec_IKE "ipsecIKE" +#define LN_ipsec_IKE "ipsec Internet Key Exchange" +#define NID_ipsec_IKE 1022 +#define OBJ_ipsec_IKE OBJ_id_kp,17L + +#define SN_capwapAC "capwapAC" +#define LN_capwapAC "Ctrl/provision WAP Access" +#define NID_capwapAC 1023 +#define OBJ_capwapAC OBJ_id_kp,18L + +#define SN_capwapWTP "capwapWTP" +#define LN_capwapWTP "Ctrl/Provision WAP Termination" +#define NID_capwapWTP 1024 +#define OBJ_capwapWTP OBJ_id_kp,19L + +#define SN_sshClient "secureShellClient" +#define LN_sshClient "SSH Client" +#define NID_sshClient 1025 +#define OBJ_sshClient OBJ_id_kp,21L + +#define SN_sshServer "secureShellServer" +#define LN_sshServer "SSH Server" +#define NID_sshServer 1026 +#define OBJ_sshServer OBJ_id_kp,22L + +#define SN_sendRouter "sendRouter" +#define LN_sendRouter "Send Router" +#define NID_sendRouter 1027 +#define OBJ_sendRouter OBJ_id_kp,23L + +#define SN_sendProxiedRouter "sendProxiedRouter" +#define LN_sendProxiedRouter "Send Proxied Router" +#define NID_sendProxiedRouter 1028 +#define OBJ_sendProxiedRouter OBJ_id_kp,24L + +#define SN_sendOwner "sendOwner" +#define LN_sendOwner "Send Owner" +#define NID_sendOwner 1029 +#define OBJ_sendOwner OBJ_id_kp,25L + +#define SN_sendProxiedOwner "sendProxiedOwner" +#define LN_sendProxiedOwner "Send Proxied Owner" +#define NID_sendProxiedOwner 1030 +#define OBJ_sendProxiedOwner OBJ_id_kp,26L + +#define SN_cmcCA "cmcCA" +#define LN_cmcCA "CMC Certificate Authority" +#define NID_cmcCA 1131 +#define OBJ_cmcCA OBJ_id_kp,27L + +#define SN_cmcRA "cmcRA" +#define LN_cmcRA "CMC Registration Authority" +#define NID_cmcRA 1132 +#define OBJ_cmcRA OBJ_id_kp,28L + +#define SN_id_it_caProtEncCert "id-it-caProtEncCert" +#define NID_id_it_caProtEncCert 298 +#define OBJ_id_it_caProtEncCert OBJ_id_it,1L + +#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes" +#define NID_id_it_signKeyPairTypes 299 +#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L + +#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes" +#define NID_id_it_encKeyPairTypes 300 +#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L + +#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg" +#define NID_id_it_preferredSymmAlg 301 +#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L + +#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo" +#define NID_id_it_caKeyUpdateInfo 302 +#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L + +#define SN_id_it_currentCRL "id-it-currentCRL" +#define NID_id_it_currentCRL 303 +#define OBJ_id_it_currentCRL OBJ_id_it,6L + +#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs" +#define NID_id_it_unsupportedOIDs 304 +#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L + +#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest" +#define NID_id_it_subscriptionRequest 305 +#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L + +#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse" +#define NID_id_it_subscriptionResponse 306 +#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L + +#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq" +#define NID_id_it_keyPairParamReq 307 +#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L + +#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep" +#define NID_id_it_keyPairParamRep 308 +#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L + +#define SN_id_it_revPassphrase "id-it-revPassphrase" +#define NID_id_it_revPassphrase 309 +#define OBJ_id_it_revPassphrase OBJ_id_it,12L + +#define SN_id_it_implicitConfirm "id-it-implicitConfirm" +#define NID_id_it_implicitConfirm 310 +#define OBJ_id_it_implicitConfirm OBJ_id_it,13L + +#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime" +#define NID_id_it_confirmWaitTime 311 +#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L + +#define SN_id_it_origPKIMessage "id-it-origPKIMessage" +#define NID_id_it_origPKIMessage 312 +#define OBJ_id_it_origPKIMessage OBJ_id_it,15L + +#define SN_id_it_suppLangTags "id-it-suppLangTags" +#define NID_id_it_suppLangTags 784 +#define OBJ_id_it_suppLangTags OBJ_id_it,16L + +#define SN_id_regCtrl "id-regCtrl" +#define NID_id_regCtrl 313 +#define OBJ_id_regCtrl OBJ_id_pkip,1L + +#define SN_id_regInfo "id-regInfo" +#define NID_id_regInfo 314 +#define OBJ_id_regInfo OBJ_id_pkip,2L + +#define SN_id_regCtrl_regToken "id-regCtrl-regToken" +#define NID_id_regCtrl_regToken 315 +#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L + +#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator" +#define NID_id_regCtrl_authenticator 316 +#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L + +#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo" +#define NID_id_regCtrl_pkiPublicationInfo 317 +#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L + +#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions" +#define NID_id_regCtrl_pkiArchiveOptions 318 +#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L + +#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID" +#define NID_id_regCtrl_oldCertID 319 +#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L + +#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey" +#define NID_id_regCtrl_protocolEncrKey 320 +#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L + +#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs" +#define NID_id_regInfo_utf8Pairs 321 +#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L + +#define SN_id_regInfo_certReq "id-regInfo-certReq" +#define NID_id_regInfo_certReq 322 +#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L + +#define SN_id_alg_des40 "id-alg-des40" +#define NID_id_alg_des40 323 +#define OBJ_id_alg_des40 OBJ_id_alg,1L + +#define SN_id_alg_noSignature "id-alg-noSignature" +#define NID_id_alg_noSignature 324 +#define OBJ_id_alg_noSignature OBJ_id_alg,2L + +#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1" +#define NID_id_alg_dh_sig_hmac_sha1 325 +#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L + +#define SN_id_alg_dh_pop "id-alg-dh-pop" +#define NID_id_alg_dh_pop 326 +#define OBJ_id_alg_dh_pop OBJ_id_alg,4L + +#define SN_id_cmc_statusInfo "id-cmc-statusInfo" +#define NID_id_cmc_statusInfo 327 +#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L + +#define SN_id_cmc_identification "id-cmc-identification" +#define NID_id_cmc_identification 328 +#define OBJ_id_cmc_identification OBJ_id_cmc,2L + +#define SN_id_cmc_identityProof "id-cmc-identityProof" +#define NID_id_cmc_identityProof 329 +#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L + +#define SN_id_cmc_dataReturn "id-cmc-dataReturn" +#define NID_id_cmc_dataReturn 330 +#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L + +#define SN_id_cmc_transactionId "id-cmc-transactionId" +#define NID_id_cmc_transactionId 331 +#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L + +#define SN_id_cmc_senderNonce "id-cmc-senderNonce" +#define NID_id_cmc_senderNonce 332 +#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L + +#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce" +#define NID_id_cmc_recipientNonce 333 +#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L + +#define SN_id_cmc_addExtensions "id-cmc-addExtensions" +#define NID_id_cmc_addExtensions 334 +#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L + +#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP" +#define NID_id_cmc_encryptedPOP 335 +#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L + +#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP" +#define NID_id_cmc_decryptedPOP 336 +#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L + +#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness" +#define NID_id_cmc_lraPOPWitness 337 +#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L + +#define SN_id_cmc_getCert "id-cmc-getCert" +#define NID_id_cmc_getCert 338 +#define OBJ_id_cmc_getCert OBJ_id_cmc,15L + +#define SN_id_cmc_getCRL "id-cmc-getCRL" +#define NID_id_cmc_getCRL 339 +#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L + +#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest" +#define NID_id_cmc_revokeRequest 340 +#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L + +#define SN_id_cmc_regInfo "id-cmc-regInfo" +#define NID_id_cmc_regInfo 341 +#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L + +#define SN_id_cmc_responseInfo "id-cmc-responseInfo" +#define NID_id_cmc_responseInfo 342 +#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L + +#define SN_id_cmc_queryPending "id-cmc-queryPending" +#define NID_id_cmc_queryPending 343 +#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L + +#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom" +#define NID_id_cmc_popLinkRandom 344 +#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L + +#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness" +#define NID_id_cmc_popLinkWitness 345 +#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L + +#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance" +#define NID_id_cmc_confirmCertAcceptance 346 +#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L + +#define SN_id_on_personalData "id-on-personalData" +#define NID_id_on_personalData 347 +#define OBJ_id_on_personalData OBJ_id_on,1L + +#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier" +#define LN_id_on_permanentIdentifier "Permanent Identifier" +#define NID_id_on_permanentIdentifier 858 +#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L + +#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth" +#define NID_id_pda_dateOfBirth 348 +#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L + +#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth" +#define NID_id_pda_placeOfBirth 349 +#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L + +#define SN_id_pda_gender "id-pda-gender" +#define NID_id_pda_gender 351 +#define OBJ_id_pda_gender OBJ_id_pda,3L + +#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship" +#define NID_id_pda_countryOfCitizenship 352 +#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L + +#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence" +#define NID_id_pda_countryOfResidence 353 +#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L + +#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo" +#define NID_id_aca_authenticationInfo 354 +#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L + +#define SN_id_aca_accessIdentity "id-aca-accessIdentity" +#define NID_id_aca_accessIdentity 355 +#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L + +#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity" +#define NID_id_aca_chargingIdentity 356 +#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L + +#define SN_id_aca_group "id-aca-group" +#define NID_id_aca_group 357 +#define OBJ_id_aca_group OBJ_id_aca,4L + +#define SN_id_aca_role "id-aca-role" +#define NID_id_aca_role 358 +#define OBJ_id_aca_role OBJ_id_aca,5L + +#define SN_id_aca_encAttrs "id-aca-encAttrs" +#define NID_id_aca_encAttrs 399 +#define OBJ_id_aca_encAttrs OBJ_id_aca,6L + +#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1" +#define NID_id_qcs_pkixQCSyntax_v1 359 +#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L + +#define SN_id_cct_crs "id-cct-crs" +#define NID_id_cct_crs 360 +#define OBJ_id_cct_crs OBJ_id_cct,1L + +#define SN_id_cct_PKIData "id-cct-PKIData" +#define NID_id_cct_PKIData 361 +#define OBJ_id_cct_PKIData OBJ_id_cct,2L + +#define SN_id_cct_PKIResponse "id-cct-PKIResponse" +#define NID_id_cct_PKIResponse 362 +#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L + +#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage" +#define LN_id_ppl_anyLanguage "Any language" +#define NID_id_ppl_anyLanguage 664 +#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L + +#define SN_id_ppl_inheritAll "id-ppl-inheritAll" +#define LN_id_ppl_inheritAll "Inherit all" +#define NID_id_ppl_inheritAll 665 +#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L + +#define SN_Independent "id-ppl-independent" +#define LN_Independent "Independent" +#define NID_Independent 667 +#define OBJ_Independent OBJ_id_ppl,2L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP OBJ_id_ad,1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers OBJ_id_ad,2L + +#define SN_ad_timeStamping "ad_timestamping" +#define LN_ad_timeStamping "AD Time Stamping" +#define NID_ad_timeStamping 363 +#define OBJ_ad_timeStamping OBJ_id_ad,3L + +#define SN_ad_dvcs "AD_DVCS" +#define LN_ad_dvcs "ad dvcs" +#define NID_ad_dvcs 364 +#define OBJ_ad_dvcs OBJ_id_ad,4L + +#define SN_caRepository "caRepository" +#define LN_caRepository "CA Repository" +#define NID_caRepository 785 +#define OBJ_caRepository OBJ_id_ad,5L + +#define OBJ_id_pkix_OCSP OBJ_ad_OCSP + +#define SN_id_pkix_OCSP_basic "basicOCSPResponse" +#define LN_id_pkix_OCSP_basic "Basic OCSP Response" +#define NID_id_pkix_OCSP_basic 365 +#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L + +#define SN_id_pkix_OCSP_Nonce "Nonce" +#define LN_id_pkix_OCSP_Nonce "OCSP Nonce" +#define NID_id_pkix_OCSP_Nonce 366 +#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L + +#define SN_id_pkix_OCSP_CrlID "CrlID" +#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID" +#define NID_id_pkix_OCSP_CrlID 367 +#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L + +#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses" +#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses" +#define NID_id_pkix_OCSP_acceptableResponses 368 +#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L + +#define SN_id_pkix_OCSP_noCheck "noCheck" +#define LN_id_pkix_OCSP_noCheck "OCSP No Check" +#define NID_id_pkix_OCSP_noCheck 369 +#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L + +#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff" +#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff" +#define NID_id_pkix_OCSP_archiveCutoff 370 +#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L + +#define SN_id_pkix_OCSP_serviceLocator "serviceLocator" +#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator" +#define NID_id_pkix_OCSP_serviceLocator 371 +#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L + +#define SN_id_pkix_OCSP_extendedStatus "extendedStatus" +#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status" +#define NID_id_pkix_OCSP_extendedStatus 372 +#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L + +#define SN_id_pkix_OCSP_valid "valid" +#define NID_id_pkix_OCSP_valid 373 +#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L + +#define SN_id_pkix_OCSP_path "path" +#define NID_id_pkix_OCSP_path 374 +#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L + +#define SN_id_pkix_OCSP_trustRoot "trustRoot" +#define LN_id_pkix_OCSP_trustRoot "Trust Root" +#define NID_id_pkix_OCSP_trustRoot 375 +#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L + +#define SN_algorithm "algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 376 +#define OBJ_algorithm 1L,3L,14L,3L,2L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA OBJ_algorithm,3L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb OBJ_algorithm,6L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +#define OBJ_des_cbc OBJ_algorithm,7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 OBJ_algorithm,8L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +#define OBJ_des_cfb64 OBJ_algorithm,9L + +#define SN_rsaSignature "rsaSignature" +#define NID_rsaSignature 377 +#define OBJ_rsaSignature OBJ_algorithm,11L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 OBJ_algorithm,12L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA OBJ_algorithm,13L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +#define SN_des_ede_ecb "DES-EDE" +#define LN_des_ede_ecb "des-ede" +#define NID_des_ede_ecb 32 +#define OBJ_des_ede_ecb OBJ_algorithm,17L + +#define SN_des_ede3_ecb "DES-EDE3" +#define LN_des_ede3_ecb "des-ede3" +#define NID_des_ede3_ecb 33 + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha OBJ_algorithm,18L + +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 OBJ_algorithm,26L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA OBJ_algorithm,29L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +#define SN_blake2b512 "BLAKE2b512" +#define LN_blake2b512 "blake2b512" +#define NID_blake2b512 1056 +#define OBJ_blake2b512 1L,3L,6L,1L,4L,1L,1722L,12L,2L,1L,16L + +#define SN_blake2s256 "BLAKE2s256" +#define LN_blake2s256 "blake2s256" +#define NID_blake2s256 1057 +#define OBJ_blake2s256 1L,3L,6L,1L,4L,1L,1722L,12L,2L,2L,8L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +#define SN_X500 "X500" +#define LN_X500 "directory services (X.500)" +#define NID_X500 11 +#define OBJ_X500 2L,5L + +#define SN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 OBJ_X500,4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName OBJ_X509,3L + +#define SN_surname "SN" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname OBJ_X509,4L + +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber OBJ_X509,5L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName OBJ_X509,6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName OBJ_X509,7L + +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName OBJ_X509,8L + +#define SN_streetAddress "street" +#define LN_streetAddress "streetAddress" +#define NID_streetAddress 660 +#define OBJ_streetAddress OBJ_X509,9L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName OBJ_X509,10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName OBJ_X509,11L + +#define SN_title "title" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title OBJ_X509,12L + +#define LN_description "description" +#define NID_description 107 +#define OBJ_description OBJ_X509,13L + +#define LN_searchGuide "searchGuide" +#define NID_searchGuide 859 +#define OBJ_searchGuide OBJ_X509,14L + +#define LN_businessCategory "businessCategory" +#define NID_businessCategory 860 +#define OBJ_businessCategory OBJ_X509,15L + +#define LN_postalAddress "postalAddress" +#define NID_postalAddress 861 +#define OBJ_postalAddress OBJ_X509,16L + +#define LN_postalCode "postalCode" +#define NID_postalCode 661 +#define OBJ_postalCode OBJ_X509,17L + +#define LN_postOfficeBox "postOfficeBox" +#define NID_postOfficeBox 862 +#define OBJ_postOfficeBox OBJ_X509,18L + +#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName" +#define NID_physicalDeliveryOfficeName 863 +#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L + +#define LN_telephoneNumber "telephoneNumber" +#define NID_telephoneNumber 864 +#define OBJ_telephoneNumber OBJ_X509,20L + +#define LN_telexNumber "telexNumber" +#define NID_telexNumber 865 +#define OBJ_telexNumber OBJ_X509,21L + +#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier" +#define NID_teletexTerminalIdentifier 866 +#define OBJ_teletexTerminalIdentifier OBJ_X509,22L + +#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber" +#define NID_facsimileTelephoneNumber 867 +#define OBJ_facsimileTelephoneNumber OBJ_X509,23L + +#define LN_x121Address "x121Address" +#define NID_x121Address 868 +#define OBJ_x121Address OBJ_X509,24L + +#define LN_internationaliSDNNumber "internationaliSDNNumber" +#define NID_internationaliSDNNumber 869 +#define OBJ_internationaliSDNNumber OBJ_X509,25L + +#define LN_registeredAddress "registeredAddress" +#define NID_registeredAddress 870 +#define OBJ_registeredAddress OBJ_X509,26L + +#define LN_destinationIndicator "destinationIndicator" +#define NID_destinationIndicator 871 +#define OBJ_destinationIndicator OBJ_X509,27L + +#define LN_preferredDeliveryMethod "preferredDeliveryMethod" +#define NID_preferredDeliveryMethod 872 +#define OBJ_preferredDeliveryMethod OBJ_X509,28L + +#define LN_presentationAddress "presentationAddress" +#define NID_presentationAddress 873 +#define OBJ_presentationAddress OBJ_X509,29L + +#define LN_supportedApplicationContext "supportedApplicationContext" +#define NID_supportedApplicationContext 874 +#define OBJ_supportedApplicationContext OBJ_X509,30L + +#define SN_member "member" +#define NID_member 875 +#define OBJ_member OBJ_X509,31L + +#define SN_owner "owner" +#define NID_owner 876 +#define OBJ_owner OBJ_X509,32L + +#define LN_roleOccupant "roleOccupant" +#define NID_roleOccupant 877 +#define OBJ_roleOccupant OBJ_X509,33L + +#define SN_seeAlso "seeAlso" +#define NID_seeAlso 878 +#define OBJ_seeAlso OBJ_X509,34L + +#define LN_userPassword "userPassword" +#define NID_userPassword 879 +#define OBJ_userPassword OBJ_X509,35L + +#define LN_userCertificate "userCertificate" +#define NID_userCertificate 880 +#define OBJ_userCertificate OBJ_X509,36L + +#define LN_cACertificate "cACertificate" +#define NID_cACertificate 881 +#define OBJ_cACertificate OBJ_X509,37L + +#define LN_authorityRevocationList "authorityRevocationList" +#define NID_authorityRevocationList 882 +#define OBJ_authorityRevocationList OBJ_X509,38L + +#define LN_certificateRevocationList "certificateRevocationList" +#define NID_certificateRevocationList 883 +#define OBJ_certificateRevocationList OBJ_X509,39L + +#define LN_crossCertificatePair "crossCertificatePair" +#define NID_crossCertificatePair 884 +#define OBJ_crossCertificatePair OBJ_X509,40L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name OBJ_X509,41L + +#define SN_givenName "GN" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName OBJ_X509,42L + +#define SN_initials "initials" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials OBJ_X509,43L + +#define LN_generationQualifier "generationQualifier" +#define NID_generationQualifier 509 +#define OBJ_generationQualifier OBJ_X509,44L + +#define LN_x500UniqueIdentifier "x500UniqueIdentifier" +#define NID_x500UniqueIdentifier 503 +#define OBJ_x500UniqueIdentifier OBJ_X509,45L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier OBJ_X509,46L + +#define LN_enhancedSearchGuide "enhancedSearchGuide" +#define NID_enhancedSearchGuide 885 +#define OBJ_enhancedSearchGuide OBJ_X509,47L + +#define LN_protocolInformation "protocolInformation" +#define NID_protocolInformation 886 +#define OBJ_protocolInformation OBJ_X509,48L + +#define LN_distinguishedName "distinguishedName" +#define NID_distinguishedName 887 +#define OBJ_distinguishedName OBJ_X509,49L + +#define LN_uniqueMember "uniqueMember" +#define NID_uniqueMember 888 +#define OBJ_uniqueMember OBJ_X509,50L + +#define LN_houseIdentifier "houseIdentifier" +#define NID_houseIdentifier 889 +#define OBJ_houseIdentifier OBJ_X509,51L + +#define LN_supportedAlgorithms "supportedAlgorithms" +#define NID_supportedAlgorithms 890 +#define OBJ_supportedAlgorithms OBJ_X509,52L + +#define LN_deltaRevocationList "deltaRevocationList" +#define NID_deltaRevocationList 891 +#define OBJ_deltaRevocationList OBJ_X509,53L + +#define SN_dmdName "dmdName" +#define NID_dmdName 892 +#define OBJ_dmdName OBJ_X509,54L + +#define LN_pseudonym "pseudonym" +#define NID_pseudonym 510 +#define OBJ_pseudonym OBJ_X509,65L + +#define SN_role "role" +#define LN_role "role" +#define NID_role 400 +#define OBJ_role OBJ_X509,72L + +#define LN_organizationIdentifier "organizationIdentifier" +#define NID_organizationIdentifier 1089 +#define OBJ_organizationIdentifier OBJ_X509,97L + +#define SN_countryCode3c "c3" +#define LN_countryCode3c "countryCode3c" +#define NID_countryCode3c 1090 +#define OBJ_countryCode3c OBJ_X509,98L + +#define SN_countryCode3n "n3" +#define LN_countryCode3n "countryCode3n" +#define NID_countryCode3n 1091 +#define OBJ_countryCode3n OBJ_X509,99L + +#define LN_dnsName "dnsName" +#define NID_dnsName 1092 +#define OBJ_dnsName OBJ_X509,100L + +#define SN_X500algorithms "X500algorithms" +#define LN_X500algorithms "directory services - algorithms" +#define NID_X500algorithms 378 +#define OBJ_X500algorithms OBJ_X500,8L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa OBJ_X500algorithms,1L,1L + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2WithRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 OBJ_X500algorithms,3L,101L + +#define SN_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_ce OBJ_X500,29L + +#define SN_subject_directory_attributes "subjectDirectoryAttributes" +#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes" +#define NID_subject_directory_attributes 769 +#define OBJ_subject_directory_attributes OBJ_id_ce,9L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier OBJ_id_ce,14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage OBJ_id_ce,15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period OBJ_id_ce,16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name OBJ_id_ce,17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name OBJ_id_ce,18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints OBJ_id_ce,19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number OBJ_id_ce,20L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "X509v3 CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_id_ce,21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_id_ce,24L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl OBJ_id_ce,27L + +#define SN_issuing_distribution_point "issuingDistributionPoint" +#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point" +#define NID_issuing_distribution_point 770 +#define OBJ_issuing_distribution_point OBJ_id_ce,28L + +#define SN_certificate_issuer "certificateIssuer" +#define LN_certificate_issuer "X509v3 Certificate Issuer" +#define NID_certificate_issuer 771 +#define OBJ_certificate_issuer OBJ_id_ce,29L + +#define SN_name_constraints "nameConstraints" +#define LN_name_constraints "X509v3 Name Constraints" +#define NID_name_constraints 666 +#define OBJ_name_constraints OBJ_id_ce,30L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points OBJ_id_ce,31L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies OBJ_id_ce,32L + +#define SN_any_policy "anyPolicy" +#define LN_any_policy "X509v3 Any Policy" +#define NID_any_policy 746 +#define OBJ_any_policy OBJ_certificate_policies,0L + +#define SN_policy_mappings "policyMappings" +#define LN_policy_mappings "X509v3 Policy Mappings" +#define NID_policy_mappings 747 +#define OBJ_policy_mappings OBJ_id_ce,33L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier OBJ_id_ce,35L + +#define SN_policy_constraints "policyConstraints" +#define LN_policy_constraints "X509v3 Policy Constraints" +#define NID_policy_constraints 401 +#define OBJ_policy_constraints OBJ_id_ce,36L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage OBJ_id_ce,37L + +#define SN_freshest_crl "freshestCRL" +#define LN_freshest_crl "X509v3 Freshest CRL" +#define NID_freshest_crl 857 +#define OBJ_freshest_crl OBJ_id_ce,46L + +#define SN_inhibit_any_policy "inhibitAnyPolicy" +#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy" +#define NID_inhibit_any_policy 748 +#define OBJ_inhibit_any_policy OBJ_id_ce,54L + +#define SN_target_information "targetInformation" +#define LN_target_information "X509v3 AC Targeting" +#define NID_target_information 402 +#define OBJ_target_information OBJ_id_ce,55L + +#define SN_no_rev_avail "noRevAvail" +#define LN_no_rev_avail "X509v3 No Revocation Available" +#define NID_no_rev_avail 403 +#define OBJ_no_rev_avail OBJ_id_ce,56L + +#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage" +#define LN_anyExtendedKeyUsage "Any Extended Key Usage" +#define NID_anyExtendedKeyUsage 910 +#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L,16L,840L,1L,113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension OBJ_netscape,1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type OBJ_netscape,2L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc OBJ_netscape,4L,1L + +#define SN_org "ORG" +#define LN_org "org" +#define NID_org 379 +#define OBJ_org OBJ_iso,3L + +#define SN_dod "DOD" +#define LN_dod "dod" +#define NID_dod 380 +#define OBJ_dod OBJ_org,6L + +#define SN_iana "IANA" +#define LN_iana "iana" +#define NID_iana 381 +#define OBJ_iana OBJ_dod,1L + +#define OBJ_internet OBJ_iana + +#define SN_Directory "directory" +#define LN_Directory "Directory" +#define NID_Directory 382 +#define OBJ_Directory OBJ_internet,1L + +#define SN_Management "mgmt" +#define LN_Management "Management" +#define NID_Management 383 +#define OBJ_Management OBJ_internet,2L + +#define SN_Experimental "experimental" +#define LN_Experimental "Experimental" +#define NID_Experimental 384 +#define OBJ_Experimental OBJ_internet,3L + +#define SN_Private "private" +#define LN_Private "Private" +#define NID_Private 385 +#define OBJ_Private OBJ_internet,4L + +#define SN_Security "security" +#define LN_Security "Security" +#define NID_Security 386 +#define OBJ_Security OBJ_internet,5L + +#define SN_SNMPv2 "snmpv2" +#define LN_SNMPv2 "SNMPv2" +#define NID_SNMPv2 387 +#define OBJ_SNMPv2 OBJ_internet,6L + +#define LN_Mail "Mail" +#define NID_Mail 388 +#define OBJ_Mail OBJ_internet,7L + +#define SN_Enterprises "enterprises" +#define LN_Enterprises "Enterprises" +#define NID_Enterprises 389 +#define OBJ_Enterprises OBJ_Private,1L + +#define SN_dcObject "dcobject" +#define LN_dcObject "dcObject" +#define NID_dcObject 390 +#define OBJ_dcObject OBJ_Enterprises,1466L,344L + +#define SN_mime_mhs "mime-mhs" +#define LN_mime_mhs "MIME MHS" +#define NID_mime_mhs 504 +#define OBJ_mime_mhs OBJ_Mail,1L + +#define SN_mime_mhs_headings "mime-mhs-headings" +#define LN_mime_mhs_headings "mime-mhs-headings" +#define NID_mime_mhs_headings 505 +#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L + +#define SN_mime_mhs_bodies "mime-mhs-bodies" +#define LN_mime_mhs_bodies "mime-mhs-bodies" +#define NID_mime_mhs_bodies 506 +#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L + +#define SN_id_hex_partial_message "id-hex-partial-message" +#define LN_id_hex_partial_message "id-hex-partial-message" +#define NID_id_hex_partial_message 507 +#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L + +#define SN_id_hex_multipart_message "id-hex-multipart-message" +#define LN_id_hex_multipart_message "id-hex-multipart-message" +#define NID_id_hex_multipart_message 508 +#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression OBJ_id_smime_alg,8L + +#define OBJ_csor 2L,16L,840L,1L,101L,3L + +#define OBJ_nistAlgorithms OBJ_csor,4L + +#define OBJ_aes OBJ_nistAlgorithms,1L + +#define SN_aes_128_ecb "AES-128-ECB" +#define LN_aes_128_ecb "aes-128-ecb" +#define NID_aes_128_ecb 418 +#define OBJ_aes_128_ecb OBJ_aes,1L + +#define SN_aes_128_cbc "AES-128-CBC" +#define LN_aes_128_cbc "aes-128-cbc" +#define NID_aes_128_cbc 419 +#define OBJ_aes_128_cbc OBJ_aes,2L + +#define SN_aes_128_ofb128 "AES-128-OFB" +#define LN_aes_128_ofb128 "aes-128-ofb" +#define NID_aes_128_ofb128 420 +#define OBJ_aes_128_ofb128 OBJ_aes,3L + +#define SN_aes_128_cfb128 "AES-128-CFB" +#define LN_aes_128_cfb128 "aes-128-cfb" +#define NID_aes_128_cfb128 421 +#define OBJ_aes_128_cfb128 OBJ_aes,4L + +#define SN_id_aes128_wrap "id-aes128-wrap" +#define NID_id_aes128_wrap 788 +#define OBJ_id_aes128_wrap OBJ_aes,5L + +#define SN_aes_128_gcm "id-aes128-GCM" +#define LN_aes_128_gcm "aes-128-gcm" +#define NID_aes_128_gcm 895 +#define OBJ_aes_128_gcm OBJ_aes,6L + +#define SN_aes_128_ccm "id-aes128-CCM" +#define LN_aes_128_ccm "aes-128-ccm" +#define NID_aes_128_ccm 896 +#define OBJ_aes_128_ccm OBJ_aes,7L + +#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad" +#define NID_id_aes128_wrap_pad 897 +#define OBJ_id_aes128_wrap_pad OBJ_aes,8L + +#define SN_aes_192_ecb "AES-192-ECB" +#define LN_aes_192_ecb "aes-192-ecb" +#define NID_aes_192_ecb 422 +#define OBJ_aes_192_ecb OBJ_aes,21L + +#define SN_aes_192_cbc "AES-192-CBC" +#define LN_aes_192_cbc "aes-192-cbc" +#define NID_aes_192_cbc 423 +#define OBJ_aes_192_cbc OBJ_aes,22L + +#define SN_aes_192_ofb128 "AES-192-OFB" +#define LN_aes_192_ofb128 "aes-192-ofb" +#define NID_aes_192_ofb128 424 +#define OBJ_aes_192_ofb128 OBJ_aes,23L + +#define SN_aes_192_cfb128 "AES-192-CFB" +#define LN_aes_192_cfb128 "aes-192-cfb" +#define NID_aes_192_cfb128 425 +#define OBJ_aes_192_cfb128 OBJ_aes,24L + +#define SN_id_aes192_wrap "id-aes192-wrap" +#define NID_id_aes192_wrap 789 +#define OBJ_id_aes192_wrap OBJ_aes,25L + +#define SN_aes_192_gcm "id-aes192-GCM" +#define LN_aes_192_gcm "aes-192-gcm" +#define NID_aes_192_gcm 898 +#define OBJ_aes_192_gcm OBJ_aes,26L + +#define SN_aes_192_ccm "id-aes192-CCM" +#define LN_aes_192_ccm "aes-192-ccm" +#define NID_aes_192_ccm 899 +#define OBJ_aes_192_ccm OBJ_aes,27L + +#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad" +#define NID_id_aes192_wrap_pad 900 +#define OBJ_id_aes192_wrap_pad OBJ_aes,28L + +#define SN_aes_256_ecb "AES-256-ECB" +#define LN_aes_256_ecb "aes-256-ecb" +#define NID_aes_256_ecb 426 +#define OBJ_aes_256_ecb OBJ_aes,41L + +#define SN_aes_256_cbc "AES-256-CBC" +#define LN_aes_256_cbc "aes-256-cbc" +#define NID_aes_256_cbc 427 +#define OBJ_aes_256_cbc OBJ_aes,42L + +#define SN_aes_256_ofb128 "AES-256-OFB" +#define LN_aes_256_ofb128 "aes-256-ofb" +#define NID_aes_256_ofb128 428 +#define OBJ_aes_256_ofb128 OBJ_aes,43L + +#define SN_aes_256_cfb128 "AES-256-CFB" +#define LN_aes_256_cfb128 "aes-256-cfb" +#define NID_aes_256_cfb128 429 +#define OBJ_aes_256_cfb128 OBJ_aes,44L + +#define SN_id_aes256_wrap "id-aes256-wrap" +#define NID_id_aes256_wrap 790 +#define OBJ_id_aes256_wrap OBJ_aes,45L + +#define SN_aes_256_gcm "id-aes256-GCM" +#define LN_aes_256_gcm "aes-256-gcm" +#define NID_aes_256_gcm 901 +#define OBJ_aes_256_gcm OBJ_aes,46L + +#define SN_aes_256_ccm "id-aes256-CCM" +#define LN_aes_256_ccm "aes-256-ccm" +#define NID_aes_256_ccm 902 +#define OBJ_aes_256_ccm OBJ_aes,47L + +#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad" +#define NID_id_aes256_wrap_pad 903 +#define OBJ_id_aes256_wrap_pad OBJ_aes,48L + +#define SN_aes_128_xts "AES-128-XTS" +#define LN_aes_128_xts "aes-128-xts" +#define NID_aes_128_xts 913 +#define OBJ_aes_128_xts OBJ_ieee_siswg,0L,1L,1L + +#define SN_aes_256_xts "AES-256-XTS" +#define LN_aes_256_xts "aes-256-xts" +#define NID_aes_256_xts 914 +#define OBJ_aes_256_xts OBJ_ieee_siswg,0L,1L,2L + +#define SN_aes_128_cfb1 "AES-128-CFB1" +#define LN_aes_128_cfb1 "aes-128-cfb1" +#define NID_aes_128_cfb1 650 + +#define SN_aes_192_cfb1 "AES-192-CFB1" +#define LN_aes_192_cfb1 "aes-192-cfb1" +#define NID_aes_192_cfb1 651 + +#define SN_aes_256_cfb1 "AES-256-CFB1" +#define LN_aes_256_cfb1 "aes-256-cfb1" +#define NID_aes_256_cfb1 652 + +#define SN_aes_128_cfb8 "AES-128-CFB8" +#define LN_aes_128_cfb8 "aes-128-cfb8" +#define NID_aes_128_cfb8 653 + +#define SN_aes_192_cfb8 "AES-192-CFB8" +#define LN_aes_192_cfb8 "aes-192-cfb8" +#define NID_aes_192_cfb8 654 + +#define SN_aes_256_cfb8 "AES-256-CFB8" +#define LN_aes_256_cfb8 "aes-256-cfb8" +#define NID_aes_256_cfb8 655 + +#define SN_aes_128_ctr "AES-128-CTR" +#define LN_aes_128_ctr "aes-128-ctr" +#define NID_aes_128_ctr 904 + +#define SN_aes_192_ctr "AES-192-CTR" +#define LN_aes_192_ctr "aes-192-ctr" +#define NID_aes_192_ctr 905 + +#define SN_aes_256_ctr "AES-256-CTR" +#define LN_aes_256_ctr "aes-256-ctr" +#define NID_aes_256_ctr 906 + +#define SN_aes_128_ocb "AES-128-OCB" +#define LN_aes_128_ocb "aes-128-ocb" +#define NID_aes_128_ocb 958 + +#define SN_aes_192_ocb "AES-192-OCB" +#define LN_aes_192_ocb "aes-192-ocb" +#define NID_aes_192_ocb 959 + +#define SN_aes_256_ocb "AES-256-OCB" +#define LN_aes_256_ocb "aes-256-ocb" +#define NID_aes_256_ocb 960 + +#define SN_des_cfb1 "DES-CFB1" +#define LN_des_cfb1 "des-cfb1" +#define NID_des_cfb1 656 + +#define SN_des_cfb8 "DES-CFB8" +#define LN_des_cfb8 "des-cfb8" +#define NID_des_cfb8 657 + +#define SN_des_ede3_cfb1 "DES-EDE3-CFB1" +#define LN_des_ede3_cfb1 "des-ede3-cfb1" +#define NID_des_ede3_cfb1 658 + +#define SN_des_ede3_cfb8 "DES-EDE3-CFB8" +#define LN_des_ede3_cfb8 "des-ede3-cfb8" +#define NID_des_ede3_cfb8 659 + +#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L + +#define SN_sha256 "SHA256" +#define LN_sha256 "sha256" +#define NID_sha256 672 +#define OBJ_sha256 OBJ_nist_hashalgs,1L + +#define SN_sha384 "SHA384" +#define LN_sha384 "sha384" +#define NID_sha384 673 +#define OBJ_sha384 OBJ_nist_hashalgs,2L + +#define SN_sha512 "SHA512" +#define LN_sha512 "sha512" +#define NID_sha512 674 +#define OBJ_sha512 OBJ_nist_hashalgs,3L + +#define SN_sha224 "SHA224" +#define LN_sha224 "sha224" +#define NID_sha224 675 +#define OBJ_sha224 OBJ_nist_hashalgs,4L + +#define SN_sha512_224 "SHA512-224" +#define LN_sha512_224 "sha512-224" +#define NID_sha512_224 1094 +#define OBJ_sha512_224 OBJ_nist_hashalgs,5L + +#define SN_sha512_256 "SHA512-256" +#define LN_sha512_256 "sha512-256" +#define NID_sha512_256 1095 +#define OBJ_sha512_256 OBJ_nist_hashalgs,6L + +#define SN_sha3_224 "SHA3-224" +#define LN_sha3_224 "sha3-224" +#define NID_sha3_224 1096 +#define OBJ_sha3_224 OBJ_nist_hashalgs,7L + +#define SN_sha3_256 "SHA3-256" +#define LN_sha3_256 "sha3-256" +#define NID_sha3_256 1097 +#define OBJ_sha3_256 OBJ_nist_hashalgs,8L + +#define SN_sha3_384 "SHA3-384" +#define LN_sha3_384 "sha3-384" +#define NID_sha3_384 1098 +#define OBJ_sha3_384 OBJ_nist_hashalgs,9L + +#define SN_sha3_512 "SHA3-512" +#define LN_sha3_512 "sha3-512" +#define NID_sha3_512 1099 +#define OBJ_sha3_512 OBJ_nist_hashalgs,10L + +#define SN_shake128 "SHAKE128" +#define LN_shake128 "shake128" +#define NID_shake128 1100 +#define OBJ_shake128 OBJ_nist_hashalgs,11L + +#define SN_shake256 "SHAKE256" +#define LN_shake256 "shake256" +#define NID_shake256 1101 +#define OBJ_shake256 OBJ_nist_hashalgs,12L + +#define SN_hmac_sha3_224 "id-hmacWithSHA3-224" +#define LN_hmac_sha3_224 "hmac-sha3-224" +#define NID_hmac_sha3_224 1102 +#define OBJ_hmac_sha3_224 OBJ_nist_hashalgs,13L + +#define SN_hmac_sha3_256 "id-hmacWithSHA3-256" +#define LN_hmac_sha3_256 "hmac-sha3-256" +#define NID_hmac_sha3_256 1103 +#define OBJ_hmac_sha3_256 OBJ_nist_hashalgs,14L + +#define SN_hmac_sha3_384 "id-hmacWithSHA3-384" +#define LN_hmac_sha3_384 "hmac-sha3-384" +#define NID_hmac_sha3_384 1104 +#define OBJ_hmac_sha3_384 OBJ_nist_hashalgs,15L + +#define SN_hmac_sha3_512 "id-hmacWithSHA3-512" +#define LN_hmac_sha3_512 "hmac-sha3-512" +#define NID_hmac_sha3_512 1105 +#define OBJ_hmac_sha3_512 OBJ_nist_hashalgs,16L + +#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA224 "dsa_with_SHA224" +#define NID_dsa_with_SHA224 802 +#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L + +#define SN_dsa_with_SHA256 "dsa_with_SHA256" +#define NID_dsa_with_SHA256 803 +#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L + +#define OBJ_sigAlgs OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA384 "id-dsa-with-sha384" +#define LN_dsa_with_SHA384 "dsa_with_SHA384" +#define NID_dsa_with_SHA384 1106 +#define OBJ_dsa_with_SHA384 OBJ_sigAlgs,3L + +#define SN_dsa_with_SHA512 "id-dsa-with-sha512" +#define LN_dsa_with_SHA512 "dsa_with_SHA512" +#define NID_dsa_with_SHA512 1107 +#define OBJ_dsa_with_SHA512 OBJ_sigAlgs,4L + +#define SN_dsa_with_SHA3_224 "id-dsa-with-sha3-224" +#define LN_dsa_with_SHA3_224 "dsa_with_SHA3-224" +#define NID_dsa_with_SHA3_224 1108 +#define OBJ_dsa_with_SHA3_224 OBJ_sigAlgs,5L + +#define SN_dsa_with_SHA3_256 "id-dsa-with-sha3-256" +#define LN_dsa_with_SHA3_256 "dsa_with_SHA3-256" +#define NID_dsa_with_SHA3_256 1109 +#define OBJ_dsa_with_SHA3_256 OBJ_sigAlgs,6L + +#define SN_dsa_with_SHA3_384 "id-dsa-with-sha3-384" +#define LN_dsa_with_SHA3_384 "dsa_with_SHA3-384" +#define NID_dsa_with_SHA3_384 1110 +#define OBJ_dsa_with_SHA3_384 OBJ_sigAlgs,7L + +#define SN_dsa_with_SHA3_512 "id-dsa-with-sha3-512" +#define LN_dsa_with_SHA3_512 "dsa_with_SHA3-512" +#define NID_dsa_with_SHA3_512 1111 +#define OBJ_dsa_with_SHA3_512 OBJ_sigAlgs,8L + +#define SN_ecdsa_with_SHA3_224 "id-ecdsa-with-sha3-224" +#define LN_ecdsa_with_SHA3_224 "ecdsa_with_SHA3-224" +#define NID_ecdsa_with_SHA3_224 1112 +#define OBJ_ecdsa_with_SHA3_224 OBJ_sigAlgs,9L + +#define SN_ecdsa_with_SHA3_256 "id-ecdsa-with-sha3-256" +#define LN_ecdsa_with_SHA3_256 "ecdsa_with_SHA3-256" +#define NID_ecdsa_with_SHA3_256 1113 +#define OBJ_ecdsa_with_SHA3_256 OBJ_sigAlgs,10L + +#define SN_ecdsa_with_SHA3_384 "id-ecdsa-with-sha3-384" +#define LN_ecdsa_with_SHA3_384 "ecdsa_with_SHA3-384" +#define NID_ecdsa_with_SHA3_384 1114 +#define OBJ_ecdsa_with_SHA3_384 OBJ_sigAlgs,11L + +#define SN_ecdsa_with_SHA3_512 "id-ecdsa-with-sha3-512" +#define LN_ecdsa_with_SHA3_512 "ecdsa_with_SHA3-512" +#define NID_ecdsa_with_SHA3_512 1115 +#define OBJ_ecdsa_with_SHA3_512 OBJ_sigAlgs,12L + +#define SN_RSA_SHA3_224 "id-rsassa-pkcs1-v1_5-with-sha3-224" +#define LN_RSA_SHA3_224 "RSA-SHA3-224" +#define NID_RSA_SHA3_224 1116 +#define OBJ_RSA_SHA3_224 OBJ_sigAlgs,13L + +#define SN_RSA_SHA3_256 "id-rsassa-pkcs1-v1_5-with-sha3-256" +#define LN_RSA_SHA3_256 "RSA-SHA3-256" +#define NID_RSA_SHA3_256 1117 +#define OBJ_RSA_SHA3_256 OBJ_sigAlgs,14L + +#define SN_RSA_SHA3_384 "id-rsassa-pkcs1-v1_5-with-sha3-384" +#define LN_RSA_SHA3_384 "RSA-SHA3-384" +#define NID_RSA_SHA3_384 1118 +#define OBJ_RSA_SHA3_384 OBJ_sigAlgs,15L + +#define SN_RSA_SHA3_512 "id-rsassa-pkcs1-v1_5-with-sha3-512" +#define LN_RSA_SHA3_512 "RSA-SHA3-512" +#define NID_RSA_SHA3_512 1119 +#define OBJ_RSA_SHA3_512 OBJ_sigAlgs,16L + +#define SN_hold_instruction_code "holdInstructionCode" +#define LN_hold_instruction_code "Hold Instruction Code" +#define NID_hold_instruction_code 430 +#define OBJ_hold_instruction_code OBJ_id_ce,23L + +#define OBJ_holdInstruction OBJ_X9_57,2L + +#define SN_hold_instruction_none "holdInstructionNone" +#define LN_hold_instruction_none "Hold Instruction None" +#define NID_hold_instruction_none 431 +#define OBJ_hold_instruction_none OBJ_holdInstruction,1L + +#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer" +#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer" +#define NID_hold_instruction_call_issuer 432 +#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L + +#define SN_hold_instruction_reject "holdInstructionReject" +#define LN_hold_instruction_reject "Hold Instruction Reject" +#define NID_hold_instruction_reject 433 +#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L + +#define SN_data "data" +#define NID_data 434 +#define OBJ_data OBJ_itu_t,9L + +#define SN_pss "pss" +#define NID_pss 435 +#define OBJ_pss OBJ_data,2342L + +#define SN_ucl "ucl" +#define NID_ucl 436 +#define OBJ_ucl OBJ_pss,19200300L + +#define SN_pilot "pilot" +#define NID_pilot 437 +#define OBJ_pilot OBJ_ucl,100L + +#define LN_pilotAttributeType "pilotAttributeType" +#define NID_pilotAttributeType 438 +#define OBJ_pilotAttributeType OBJ_pilot,1L + +#define LN_pilotAttributeSyntax "pilotAttributeSyntax" +#define NID_pilotAttributeSyntax 439 +#define OBJ_pilotAttributeSyntax OBJ_pilot,3L + +#define LN_pilotObjectClass "pilotObjectClass" +#define NID_pilotObjectClass 440 +#define OBJ_pilotObjectClass OBJ_pilot,4L + +#define LN_pilotGroups "pilotGroups" +#define NID_pilotGroups 441 +#define OBJ_pilotGroups OBJ_pilot,10L + +#define LN_iA5StringSyntax "iA5StringSyntax" +#define NID_iA5StringSyntax 442 +#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L + +#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax" +#define NID_caseIgnoreIA5StringSyntax 443 +#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L + +#define LN_pilotObject "pilotObject" +#define NID_pilotObject 444 +#define OBJ_pilotObject OBJ_pilotObjectClass,3L + +#define LN_pilotPerson "pilotPerson" +#define NID_pilotPerson 445 +#define OBJ_pilotPerson OBJ_pilotObjectClass,4L + +#define SN_account "account" +#define NID_account 446 +#define OBJ_account OBJ_pilotObjectClass,5L + +#define SN_document "document" +#define NID_document 447 +#define OBJ_document OBJ_pilotObjectClass,6L + +#define SN_room "room" +#define NID_room 448 +#define OBJ_room OBJ_pilotObjectClass,7L + +#define LN_documentSeries "documentSeries" +#define NID_documentSeries 449 +#define OBJ_documentSeries OBJ_pilotObjectClass,9L + +#define SN_Domain "domain" +#define LN_Domain "Domain" +#define NID_Domain 392 +#define OBJ_Domain OBJ_pilotObjectClass,13L + +#define LN_rFC822localPart "rFC822localPart" +#define NID_rFC822localPart 450 +#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L + +#define LN_dNSDomain "dNSDomain" +#define NID_dNSDomain 451 +#define OBJ_dNSDomain OBJ_pilotObjectClass,15L + +#define LN_domainRelatedObject "domainRelatedObject" +#define NID_domainRelatedObject 452 +#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L + +#define LN_friendlyCountry "friendlyCountry" +#define NID_friendlyCountry 453 +#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L + +#define LN_simpleSecurityObject "simpleSecurityObject" +#define NID_simpleSecurityObject 454 +#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L + +#define LN_pilotOrganization "pilotOrganization" +#define NID_pilotOrganization 455 +#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L + +#define LN_pilotDSA "pilotDSA" +#define NID_pilotDSA 456 +#define OBJ_pilotDSA OBJ_pilotObjectClass,21L + +#define LN_qualityLabelledData "qualityLabelledData" +#define NID_qualityLabelledData 457 +#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L + +#define SN_userId "UID" +#define LN_userId "userId" +#define NID_userId 458 +#define OBJ_userId OBJ_pilotAttributeType,1L + +#define LN_textEncodedORAddress "textEncodedORAddress" +#define NID_textEncodedORAddress 459 +#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L + +#define SN_rfc822Mailbox "mail" +#define LN_rfc822Mailbox "rfc822Mailbox" +#define NID_rfc822Mailbox 460 +#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L + +#define SN_info "info" +#define NID_info 461 +#define OBJ_info OBJ_pilotAttributeType,4L + +#define LN_favouriteDrink "favouriteDrink" +#define NID_favouriteDrink 462 +#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L + +#define LN_roomNumber "roomNumber" +#define NID_roomNumber 463 +#define OBJ_roomNumber OBJ_pilotAttributeType,6L + +#define SN_photo "photo" +#define NID_photo 464 +#define OBJ_photo OBJ_pilotAttributeType,7L + +#define LN_userClass "userClass" +#define NID_userClass 465 +#define OBJ_userClass OBJ_pilotAttributeType,8L + +#define SN_host "host" +#define NID_host 466 +#define OBJ_host OBJ_pilotAttributeType,9L + +#define SN_manager "manager" +#define NID_manager 467 +#define OBJ_manager OBJ_pilotAttributeType,10L + +#define LN_documentIdentifier "documentIdentifier" +#define NID_documentIdentifier 468 +#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L + +#define LN_documentTitle "documentTitle" +#define NID_documentTitle 469 +#define OBJ_documentTitle OBJ_pilotAttributeType,12L + +#define LN_documentVersion "documentVersion" +#define NID_documentVersion 470 +#define OBJ_documentVersion OBJ_pilotAttributeType,13L + +#define LN_documentAuthor "documentAuthor" +#define NID_documentAuthor 471 +#define OBJ_documentAuthor OBJ_pilotAttributeType,14L + +#define LN_documentLocation "documentLocation" +#define NID_documentLocation 472 +#define OBJ_documentLocation OBJ_pilotAttributeType,15L + +#define LN_homeTelephoneNumber "homeTelephoneNumber" +#define NID_homeTelephoneNumber 473 +#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L + +#define SN_secretary "secretary" +#define NID_secretary 474 +#define OBJ_secretary OBJ_pilotAttributeType,21L + +#define LN_otherMailbox "otherMailbox" +#define NID_otherMailbox 475 +#define OBJ_otherMailbox OBJ_pilotAttributeType,22L + +#define LN_lastModifiedTime "lastModifiedTime" +#define NID_lastModifiedTime 476 +#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L + +#define LN_lastModifiedBy "lastModifiedBy" +#define NID_lastModifiedBy 477 +#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L + +#define SN_domainComponent "DC" +#define LN_domainComponent "domainComponent" +#define NID_domainComponent 391 +#define OBJ_domainComponent OBJ_pilotAttributeType,25L + +#define LN_aRecord "aRecord" +#define NID_aRecord 478 +#define OBJ_aRecord OBJ_pilotAttributeType,26L + +#define LN_pilotAttributeType27 "pilotAttributeType27" +#define NID_pilotAttributeType27 479 +#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L + +#define LN_mXRecord "mXRecord" +#define NID_mXRecord 480 +#define OBJ_mXRecord OBJ_pilotAttributeType,28L + +#define LN_nSRecord "nSRecord" +#define NID_nSRecord 481 +#define OBJ_nSRecord OBJ_pilotAttributeType,29L + +#define LN_sOARecord "sOARecord" +#define NID_sOARecord 482 +#define OBJ_sOARecord OBJ_pilotAttributeType,30L + +#define LN_cNAMERecord "cNAMERecord" +#define NID_cNAMERecord 483 +#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L + +#define LN_associatedDomain "associatedDomain" +#define NID_associatedDomain 484 +#define OBJ_associatedDomain OBJ_pilotAttributeType,37L + +#define LN_associatedName "associatedName" +#define NID_associatedName 485 +#define OBJ_associatedName OBJ_pilotAttributeType,38L + +#define LN_homePostalAddress "homePostalAddress" +#define NID_homePostalAddress 486 +#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L + +#define LN_personalTitle "personalTitle" +#define NID_personalTitle 487 +#define OBJ_personalTitle OBJ_pilotAttributeType,40L + +#define LN_mobileTelephoneNumber "mobileTelephoneNumber" +#define NID_mobileTelephoneNumber 488 +#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L + +#define LN_pagerTelephoneNumber "pagerTelephoneNumber" +#define NID_pagerTelephoneNumber 489 +#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L + +#define LN_friendlyCountryName "friendlyCountryName" +#define NID_friendlyCountryName 490 +#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L + +#define SN_uniqueIdentifier "uid" +#define LN_uniqueIdentifier "uniqueIdentifier" +#define NID_uniqueIdentifier 102 +#define OBJ_uniqueIdentifier OBJ_pilotAttributeType,44L + +#define LN_organizationalStatus "organizationalStatus" +#define NID_organizationalStatus 491 +#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L + +#define LN_janetMailbox "janetMailbox" +#define NID_janetMailbox 492 +#define OBJ_janetMailbox OBJ_pilotAttributeType,46L + +#define LN_mailPreferenceOption "mailPreferenceOption" +#define NID_mailPreferenceOption 493 +#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L + +#define LN_buildingName "buildingName" +#define NID_buildingName 494 +#define OBJ_buildingName OBJ_pilotAttributeType,48L + +#define LN_dSAQuality "dSAQuality" +#define NID_dSAQuality 495 +#define OBJ_dSAQuality OBJ_pilotAttributeType,49L + +#define LN_singleLevelQuality "singleLevelQuality" +#define NID_singleLevelQuality 496 +#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L + +#define LN_subtreeMinimumQuality "subtreeMinimumQuality" +#define NID_subtreeMinimumQuality 497 +#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L + +#define LN_subtreeMaximumQuality "subtreeMaximumQuality" +#define NID_subtreeMaximumQuality 498 +#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L + +#define LN_personalSignature "personalSignature" +#define NID_personalSignature 499 +#define OBJ_personalSignature OBJ_pilotAttributeType,53L + +#define LN_dITRedirect "dITRedirect" +#define NID_dITRedirect 500 +#define OBJ_dITRedirect OBJ_pilotAttributeType,54L + +#define SN_audio "audio" +#define NID_audio 501 +#define OBJ_audio OBJ_pilotAttributeType,55L + +#define LN_documentPublisher "documentPublisher" +#define NID_documentPublisher 502 +#define OBJ_documentPublisher OBJ_pilotAttributeType,56L + +#define SN_id_set "id-set" +#define LN_id_set "Secure Electronic Transactions" +#define NID_id_set 512 +#define OBJ_id_set OBJ_international_organizations,42L + +#define SN_set_ctype "set-ctype" +#define LN_set_ctype "content types" +#define NID_set_ctype 513 +#define OBJ_set_ctype OBJ_id_set,0L + +#define SN_set_msgExt "set-msgExt" +#define LN_set_msgExt "message extensions" +#define NID_set_msgExt 514 +#define OBJ_set_msgExt OBJ_id_set,1L + +#define SN_set_attr "set-attr" +#define NID_set_attr 515 +#define OBJ_set_attr OBJ_id_set,3L + +#define SN_set_policy "set-policy" +#define NID_set_policy 516 +#define OBJ_set_policy OBJ_id_set,5L + +#define SN_set_certExt "set-certExt" +#define LN_set_certExt "certificate extensions" +#define NID_set_certExt 517 +#define OBJ_set_certExt OBJ_id_set,7L + +#define SN_set_brand "set-brand" +#define NID_set_brand 518 +#define OBJ_set_brand OBJ_id_set,8L + +#define SN_setct_PANData "setct-PANData" +#define NID_setct_PANData 519 +#define OBJ_setct_PANData OBJ_set_ctype,0L + +#define SN_setct_PANToken "setct-PANToken" +#define NID_setct_PANToken 520 +#define OBJ_setct_PANToken OBJ_set_ctype,1L + +#define SN_setct_PANOnly "setct-PANOnly" +#define NID_setct_PANOnly 521 +#define OBJ_setct_PANOnly OBJ_set_ctype,2L + +#define SN_setct_OIData "setct-OIData" +#define NID_setct_OIData 522 +#define OBJ_setct_OIData OBJ_set_ctype,3L + +#define SN_setct_PI "setct-PI" +#define NID_setct_PI 523 +#define OBJ_setct_PI OBJ_set_ctype,4L + +#define SN_setct_PIData "setct-PIData" +#define NID_setct_PIData 524 +#define OBJ_setct_PIData OBJ_set_ctype,5L + +#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned" +#define NID_setct_PIDataUnsigned 525 +#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L + +#define SN_setct_HODInput "setct-HODInput" +#define NID_setct_HODInput 526 +#define OBJ_setct_HODInput OBJ_set_ctype,7L + +#define SN_setct_AuthResBaggage "setct-AuthResBaggage" +#define NID_setct_AuthResBaggage 527 +#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L + +#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage" +#define NID_setct_AuthRevReqBaggage 528 +#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L + +#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage" +#define NID_setct_AuthRevResBaggage 529 +#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L + +#define SN_setct_CapTokenSeq "setct-CapTokenSeq" +#define NID_setct_CapTokenSeq 530 +#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L + +#define SN_setct_PInitResData "setct-PInitResData" +#define NID_setct_PInitResData 531 +#define OBJ_setct_PInitResData OBJ_set_ctype,12L + +#define SN_setct_PI_TBS "setct-PI-TBS" +#define NID_setct_PI_TBS 532 +#define OBJ_setct_PI_TBS OBJ_set_ctype,13L + +#define SN_setct_PResData "setct-PResData" +#define NID_setct_PResData 533 +#define OBJ_setct_PResData OBJ_set_ctype,14L + +#define SN_setct_AuthReqTBS "setct-AuthReqTBS" +#define NID_setct_AuthReqTBS 534 +#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L + +#define SN_setct_AuthResTBS "setct-AuthResTBS" +#define NID_setct_AuthResTBS 535 +#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L + +#define SN_setct_AuthResTBSX "setct-AuthResTBSX" +#define NID_setct_AuthResTBSX 536 +#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L + +#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS" +#define NID_setct_AuthTokenTBS 537 +#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L + +#define SN_setct_CapTokenData "setct-CapTokenData" +#define NID_setct_CapTokenData 538 +#define OBJ_setct_CapTokenData OBJ_set_ctype,20L + +#define SN_setct_CapTokenTBS "setct-CapTokenTBS" +#define NID_setct_CapTokenTBS 539 +#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L + +#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg" +#define NID_setct_AcqCardCodeMsg 540 +#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L + +#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS" +#define NID_setct_AuthRevReqTBS 541 +#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L + +#define SN_setct_AuthRevResData "setct-AuthRevResData" +#define NID_setct_AuthRevResData 542 +#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L + +#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS" +#define NID_setct_AuthRevResTBS 543 +#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L + +#define SN_setct_CapReqTBS "setct-CapReqTBS" +#define NID_setct_CapReqTBS 544 +#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L + +#define SN_setct_CapReqTBSX "setct-CapReqTBSX" +#define NID_setct_CapReqTBSX 545 +#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L + +#define SN_setct_CapResData "setct-CapResData" +#define NID_setct_CapResData 546 +#define OBJ_setct_CapResData OBJ_set_ctype,28L + +#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS" +#define NID_setct_CapRevReqTBS 547 +#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L + +#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX" +#define NID_setct_CapRevReqTBSX 548 +#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L + +#define SN_setct_CapRevResData "setct-CapRevResData" +#define NID_setct_CapRevResData 549 +#define OBJ_setct_CapRevResData OBJ_set_ctype,31L + +#define SN_setct_CredReqTBS "setct-CredReqTBS" +#define NID_setct_CredReqTBS 550 +#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L + +#define SN_setct_CredReqTBSX "setct-CredReqTBSX" +#define NID_setct_CredReqTBSX 551 +#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L + +#define SN_setct_CredResData "setct-CredResData" +#define NID_setct_CredResData 552 +#define OBJ_setct_CredResData OBJ_set_ctype,34L + +#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS" +#define NID_setct_CredRevReqTBS 553 +#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L + +#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX" +#define NID_setct_CredRevReqTBSX 554 +#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L + +#define SN_setct_CredRevResData "setct-CredRevResData" +#define NID_setct_CredRevResData 555 +#define OBJ_setct_CredRevResData OBJ_set_ctype,37L + +#define SN_setct_PCertReqData "setct-PCertReqData" +#define NID_setct_PCertReqData 556 +#define OBJ_setct_PCertReqData OBJ_set_ctype,38L + +#define SN_setct_PCertResTBS "setct-PCertResTBS" +#define NID_setct_PCertResTBS 557 +#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L + +#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData" +#define NID_setct_BatchAdminReqData 558 +#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L + +#define SN_setct_BatchAdminResData "setct-BatchAdminResData" +#define NID_setct_BatchAdminResData 559 +#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L + +#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS" +#define NID_setct_CardCInitResTBS 560 +#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L + +#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS" +#define NID_setct_MeAqCInitResTBS 561 +#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L + +#define SN_setct_RegFormResTBS "setct-RegFormResTBS" +#define NID_setct_RegFormResTBS 562 +#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L + +#define SN_setct_CertReqData "setct-CertReqData" +#define NID_setct_CertReqData 563 +#define OBJ_setct_CertReqData OBJ_set_ctype,45L + +#define SN_setct_CertReqTBS "setct-CertReqTBS" +#define NID_setct_CertReqTBS 564 +#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L + +#define SN_setct_CertResData "setct-CertResData" +#define NID_setct_CertResData 565 +#define OBJ_setct_CertResData OBJ_set_ctype,47L + +#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS" +#define NID_setct_CertInqReqTBS 566 +#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L + +#define SN_setct_ErrorTBS "setct-ErrorTBS" +#define NID_setct_ErrorTBS 567 +#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L + +#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE" +#define NID_setct_PIDualSignedTBE 568 +#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L + +#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE" +#define NID_setct_PIUnsignedTBE 569 +#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L + +#define SN_setct_AuthReqTBE "setct-AuthReqTBE" +#define NID_setct_AuthReqTBE 570 +#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L + +#define SN_setct_AuthResTBE "setct-AuthResTBE" +#define NID_setct_AuthResTBE 571 +#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L + +#define SN_setct_AuthResTBEX "setct-AuthResTBEX" +#define NID_setct_AuthResTBEX 572 +#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L + +#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE" +#define NID_setct_AuthTokenTBE 573 +#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L + +#define SN_setct_CapTokenTBE "setct-CapTokenTBE" +#define NID_setct_CapTokenTBE 574 +#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L + +#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX" +#define NID_setct_CapTokenTBEX 575 +#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L + +#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE" +#define NID_setct_AcqCardCodeMsgTBE 576 +#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L + +#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE" +#define NID_setct_AuthRevReqTBE 577 +#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L + +#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE" +#define NID_setct_AuthRevResTBE 578 +#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L + +#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB" +#define NID_setct_AuthRevResTBEB 579 +#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L + +#define SN_setct_CapReqTBE "setct-CapReqTBE" +#define NID_setct_CapReqTBE 580 +#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L + +#define SN_setct_CapReqTBEX "setct-CapReqTBEX" +#define NID_setct_CapReqTBEX 581 +#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L + +#define SN_setct_CapResTBE "setct-CapResTBE" +#define NID_setct_CapResTBE 582 +#define OBJ_setct_CapResTBE OBJ_set_ctype,64L + +#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE" +#define NID_setct_CapRevReqTBE 583 +#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L + +#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX" +#define NID_setct_CapRevReqTBEX 584 +#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L + +#define SN_setct_CapRevResTBE "setct-CapRevResTBE" +#define NID_setct_CapRevResTBE 585 +#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L + +#define SN_setct_CredReqTBE "setct-CredReqTBE" +#define NID_setct_CredReqTBE 586 +#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L + +#define SN_setct_CredReqTBEX "setct-CredReqTBEX" +#define NID_setct_CredReqTBEX 587 +#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L + +#define SN_setct_CredResTBE "setct-CredResTBE" +#define NID_setct_CredResTBE 588 +#define OBJ_setct_CredResTBE OBJ_set_ctype,70L + +#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE" +#define NID_setct_CredRevReqTBE 589 +#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L + +#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX" +#define NID_setct_CredRevReqTBEX 590 +#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L + +#define SN_setct_CredRevResTBE "setct-CredRevResTBE" +#define NID_setct_CredRevResTBE 591 +#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L + +#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE" +#define NID_setct_BatchAdminReqTBE 592 +#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L + +#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE" +#define NID_setct_BatchAdminResTBE 593 +#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L + +#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE" +#define NID_setct_RegFormReqTBE 594 +#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L + +#define SN_setct_CertReqTBE "setct-CertReqTBE" +#define NID_setct_CertReqTBE 595 +#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L + +#define SN_setct_CertReqTBEX "setct-CertReqTBEX" +#define NID_setct_CertReqTBEX 596 +#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L + +#define SN_setct_CertResTBE "setct-CertResTBE" +#define NID_setct_CertResTBE 597 +#define OBJ_setct_CertResTBE OBJ_set_ctype,79L + +#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS" +#define NID_setct_CRLNotificationTBS 598 +#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L + +#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS" +#define NID_setct_CRLNotificationResTBS 599 +#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L + +#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS" +#define NID_setct_BCIDistributionTBS 600 +#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L + +#define SN_setext_genCrypt "setext-genCrypt" +#define LN_setext_genCrypt "generic cryptogram" +#define NID_setext_genCrypt 601 +#define OBJ_setext_genCrypt OBJ_set_msgExt,1L + +#define SN_setext_miAuth "setext-miAuth" +#define LN_setext_miAuth "merchant initiated auth" +#define NID_setext_miAuth 602 +#define OBJ_setext_miAuth OBJ_set_msgExt,3L + +#define SN_setext_pinSecure "setext-pinSecure" +#define NID_setext_pinSecure 603 +#define OBJ_setext_pinSecure OBJ_set_msgExt,4L + +#define SN_setext_pinAny "setext-pinAny" +#define NID_setext_pinAny 604 +#define OBJ_setext_pinAny OBJ_set_msgExt,5L + +#define SN_setext_track2 "setext-track2" +#define NID_setext_track2 605 +#define OBJ_setext_track2 OBJ_set_msgExt,7L + +#define SN_setext_cv "setext-cv" +#define LN_setext_cv "additional verification" +#define NID_setext_cv 606 +#define OBJ_setext_cv OBJ_set_msgExt,8L + +#define SN_set_policy_root "set-policy-root" +#define NID_set_policy_root 607 +#define OBJ_set_policy_root OBJ_set_policy,0L + +#define SN_setCext_hashedRoot "setCext-hashedRoot" +#define NID_setCext_hashedRoot 608 +#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L + +#define SN_setCext_certType "setCext-certType" +#define NID_setCext_certType 609 +#define OBJ_setCext_certType OBJ_set_certExt,1L + +#define SN_setCext_merchData "setCext-merchData" +#define NID_setCext_merchData 610 +#define OBJ_setCext_merchData OBJ_set_certExt,2L + +#define SN_setCext_cCertRequired "setCext-cCertRequired" +#define NID_setCext_cCertRequired 611 +#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L + +#define SN_setCext_tunneling "setCext-tunneling" +#define NID_setCext_tunneling 612 +#define OBJ_setCext_tunneling OBJ_set_certExt,4L + +#define SN_setCext_setExt "setCext-setExt" +#define NID_setCext_setExt 613 +#define OBJ_setCext_setExt OBJ_set_certExt,5L + +#define SN_setCext_setQualf "setCext-setQualf" +#define NID_setCext_setQualf 614 +#define OBJ_setCext_setQualf OBJ_set_certExt,6L + +#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities" +#define NID_setCext_PGWYcapabilities 615 +#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L + +#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier" +#define NID_setCext_TokenIdentifier 616 +#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L + +#define SN_setCext_Track2Data "setCext-Track2Data" +#define NID_setCext_Track2Data 617 +#define OBJ_setCext_Track2Data OBJ_set_certExt,9L + +#define SN_setCext_TokenType "setCext-TokenType" +#define NID_setCext_TokenType 618 +#define OBJ_setCext_TokenType OBJ_set_certExt,10L + +#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities" +#define NID_setCext_IssuerCapabilities 619 +#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L + +#define SN_setAttr_Cert "setAttr-Cert" +#define NID_setAttr_Cert 620 +#define OBJ_setAttr_Cert OBJ_set_attr,0L + +#define SN_setAttr_PGWYcap "setAttr-PGWYcap" +#define LN_setAttr_PGWYcap "payment gateway capabilities" +#define NID_setAttr_PGWYcap 621 +#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L + +#define SN_setAttr_TokenType "setAttr-TokenType" +#define NID_setAttr_TokenType 622 +#define OBJ_setAttr_TokenType OBJ_set_attr,2L + +#define SN_setAttr_IssCap "setAttr-IssCap" +#define LN_setAttr_IssCap "issuer capabilities" +#define NID_setAttr_IssCap 623 +#define OBJ_setAttr_IssCap OBJ_set_attr,3L + +#define SN_set_rootKeyThumb "set-rootKeyThumb" +#define NID_set_rootKeyThumb 624 +#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L + +#define SN_set_addPolicy "set-addPolicy" +#define NID_set_addPolicy 625 +#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L + +#define SN_setAttr_Token_EMV "setAttr-Token-EMV" +#define NID_setAttr_Token_EMV 626 +#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L + +#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime" +#define NID_setAttr_Token_B0Prime 627 +#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L + +#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM" +#define NID_setAttr_IssCap_CVM 628 +#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L + +#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2" +#define NID_setAttr_IssCap_T2 629 +#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L + +#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig" +#define NID_setAttr_IssCap_Sig 630 +#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L + +#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm" +#define LN_setAttr_GenCryptgrm "generate cryptogram" +#define NID_setAttr_GenCryptgrm 631 +#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L + +#define SN_setAttr_T2Enc "setAttr-T2Enc" +#define LN_setAttr_T2Enc "encrypted track 2" +#define NID_setAttr_T2Enc 632 +#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L + +#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt" +#define LN_setAttr_T2cleartxt "cleartext track 2" +#define NID_setAttr_T2cleartxt 633 +#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L + +#define SN_setAttr_TokICCsig "setAttr-TokICCsig" +#define LN_setAttr_TokICCsig "ICC or token signature" +#define NID_setAttr_TokICCsig 634 +#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L + +#define SN_setAttr_SecDevSig "setAttr-SecDevSig" +#define LN_setAttr_SecDevSig "secure device signature" +#define NID_setAttr_SecDevSig 635 +#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L + +#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA" +#define NID_set_brand_IATA_ATA 636 +#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L + +#define SN_set_brand_Diners "set-brand-Diners" +#define NID_set_brand_Diners 637 +#define OBJ_set_brand_Diners OBJ_set_brand,30L + +#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress" +#define NID_set_brand_AmericanExpress 638 +#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L + +#define SN_set_brand_JCB "set-brand-JCB" +#define NID_set_brand_JCB 639 +#define OBJ_set_brand_JCB OBJ_set_brand,35L + +#define SN_set_brand_Visa "set-brand-Visa" +#define NID_set_brand_Visa 640 +#define OBJ_set_brand_Visa OBJ_set_brand,4L + +#define SN_set_brand_MasterCard "set-brand-MasterCard" +#define NID_set_brand_MasterCard 641 +#define OBJ_set_brand_MasterCard OBJ_set_brand,5L + +#define SN_set_brand_Novus "set-brand-Novus" +#define NID_set_brand_Novus 642 +#define OBJ_set_brand_Novus OBJ_set_brand,6011L + +#define SN_des_cdmf "DES-CDMF" +#define LN_des_cdmf "des-cdmf" +#define NID_des_cdmf 643 +#define OBJ_des_cdmf OBJ_rsadsi,3L,10L + +#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET" +#define NID_rsaOAEPEncryptionSET 644 +#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L + +#define SN_ipsec3 "Oakley-EC2N-3" +#define LN_ipsec3 "ipsec3" +#define NID_ipsec3 749 + +#define SN_ipsec4 "Oakley-EC2N-4" +#define LN_ipsec4 "ipsec4" +#define NID_ipsec4 750 + +#define SN_whirlpool "whirlpool" +#define NID_whirlpool 804 +#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L + +#define SN_cryptopro "cryptopro" +#define NID_cryptopro 805 +#define OBJ_cryptopro OBJ_member_body,643L,2L,2L + +#define SN_cryptocom "cryptocom" +#define NID_cryptocom 806 +#define OBJ_cryptocom OBJ_member_body,643L,2L,9L + +#define SN_id_tc26 "id-tc26" +#define NID_id_tc26 974 +#define OBJ_id_tc26 OBJ_member_body,643L,7L,1L + +#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001" +#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001" +#define NID_id_GostR3411_94_with_GostR3410_2001 807 +#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L + +#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94" +#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94" +#define NID_id_GostR3411_94_with_GostR3410_94 808 +#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L + +#define SN_id_GostR3411_94 "md_gost94" +#define LN_id_GostR3411_94 "GOST R 34.11-94" +#define NID_id_GostR3411_94 809 +#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L + +#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94" +#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94" +#define NID_id_HMACGostR3411_94 810 +#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L + +#define SN_id_GostR3410_2001 "gost2001" +#define LN_id_GostR3410_2001 "GOST R 34.10-2001" +#define NID_id_GostR3410_2001 811 +#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L + +#define SN_id_GostR3410_94 "gost94" +#define LN_id_GostR3410_94 "GOST R 34.10-94" +#define NID_id_GostR3410_94 812 +#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L + +#define SN_id_Gost28147_89 "gost89" +#define LN_id_Gost28147_89 "GOST 28147-89" +#define NID_id_Gost28147_89 813 +#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L + +#define SN_gost89_cnt "gost89-cnt" +#define NID_gost89_cnt 814 + +#define SN_gost89_cnt_12 "gost89-cnt-12" +#define NID_gost89_cnt_12 975 + +#define SN_gost89_cbc "gost89-cbc" +#define NID_gost89_cbc 1009 + +#define SN_gost89_ecb "gost89-ecb" +#define NID_gost89_ecb 1010 + +#define SN_gost89_ctr "gost89-ctr" +#define NID_gost89_ctr 1011 + +#define SN_id_Gost28147_89_MAC "gost-mac" +#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC" +#define NID_id_Gost28147_89_MAC 815 +#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L + +#define SN_gost_mac_12 "gost-mac-12" +#define NID_gost_mac_12 976 + +#define SN_id_GostR3411_94_prf "prf-gostr3411-94" +#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF" +#define NID_id_GostR3411_94_prf 816 +#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L + +#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH" +#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH" +#define NID_id_GostR3410_2001DH 817 +#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L + +#define SN_id_GostR3410_94DH "id-GostR3410-94DH" +#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH" +#define NID_id_GostR3410_94DH 818 +#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L + +#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing" +#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819 +#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L + +#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing" +#define NID_id_Gost28147_89_None_KeyMeshing 820 +#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L + +#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet" +#define NID_id_GostR3411_94_TestParamSet 821 +#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L + +#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet" +#define NID_id_GostR3411_94_CryptoProParamSet 822 +#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L + +#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet" +#define NID_id_Gost28147_89_TestParamSet 823 +#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L + +#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824 +#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L + +#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825 +#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L + +#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826 +#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L + +#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827 +#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L + +#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L + +#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet" +#define NID_id_GostR3410_94_TestParamSet 831 +#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L + +#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832 +#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L + +#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833 +#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L + +#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834 +#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L + +#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835 +#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L + +#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L + +#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L + +#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L + +#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet" +#define NID_id_GostR3410_2001_TestParamSet 839 +#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L + +#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840 +#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L + +#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841 +#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L + +#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842 +#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L + +#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L + +#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L + +#define SN_id_GostR3410_94_a "id-GostR3410-94-a" +#define NID_id_GostR3410_94_a 845 +#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L + +#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis" +#define NID_id_GostR3410_94_aBis 846 +#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L + +#define SN_id_GostR3410_94_b "id-GostR3410-94-b" +#define NID_id_GostR3410_94_b 847 +#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L + +#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis" +#define NID_id_GostR3410_94_bBis 848 +#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L + +#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc" +#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet" +#define NID_id_Gost28147_89_cc 849 +#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L + +#define SN_id_GostR3410_94_cc "gost94cc" +#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom" +#define NID_id_GostR3410_94_cc 850 +#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L + +#define SN_id_GostR3410_2001_cc "gost2001cc" +#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom" +#define NID_id_GostR3410_2001_cc 851 +#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L + +#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc" +#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_94_cc 852 +#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L + +#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc" +#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853 +#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L + +#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc" +#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom" +#define NID_id_GostR3410_2001_ParamSet_cc 854 +#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L + +#define SN_id_tc26_algorithms "id-tc26-algorithms" +#define NID_id_tc26_algorithms 977 +#define OBJ_id_tc26_algorithms OBJ_id_tc26,1L + +#define SN_id_tc26_sign "id-tc26-sign" +#define NID_id_tc26_sign 978 +#define OBJ_id_tc26_sign OBJ_id_tc26_algorithms,1L + +#define SN_id_GostR3410_2012_256 "gost2012_256" +#define LN_id_GostR3410_2012_256 "GOST R 34.10-2012 with 256 bit modulus" +#define NID_id_GostR3410_2012_256 979 +#define OBJ_id_GostR3410_2012_256 OBJ_id_tc26_sign,1L + +#define SN_id_GostR3410_2012_512 "gost2012_512" +#define LN_id_GostR3410_2012_512 "GOST R 34.10-2012 with 512 bit modulus" +#define NID_id_GostR3410_2012_512 980 +#define OBJ_id_GostR3410_2012_512 OBJ_id_tc26_sign,2L + +#define SN_id_tc26_digest "id-tc26-digest" +#define NID_id_tc26_digest 981 +#define OBJ_id_tc26_digest OBJ_id_tc26_algorithms,2L + +#define SN_id_GostR3411_2012_256 "md_gost12_256" +#define LN_id_GostR3411_2012_256 "GOST R 34.11-2012 with 256 bit hash" +#define NID_id_GostR3411_2012_256 982 +#define OBJ_id_GostR3411_2012_256 OBJ_id_tc26_digest,2L + +#define SN_id_GostR3411_2012_512 "md_gost12_512" +#define LN_id_GostR3411_2012_512 "GOST R 34.11-2012 with 512 bit hash" +#define NID_id_GostR3411_2012_512 983 +#define OBJ_id_GostR3411_2012_512 OBJ_id_tc26_digest,3L + +#define SN_id_tc26_signwithdigest "id-tc26-signwithdigest" +#define NID_id_tc26_signwithdigest 984 +#define OBJ_id_tc26_signwithdigest OBJ_id_tc26_algorithms,3L + +#define SN_id_tc26_signwithdigest_gost3410_2012_256 "id-tc26-signwithdigest-gost3410-2012-256" +#define LN_id_tc26_signwithdigest_gost3410_2012_256 "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_256 985 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_256 OBJ_id_tc26_signwithdigest,2L + +#define SN_id_tc26_signwithdigest_gost3410_2012_512 "id-tc26-signwithdigest-gost3410-2012-512" +#define LN_id_tc26_signwithdigest_gost3410_2012_512 "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_512 986 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_512 OBJ_id_tc26_signwithdigest,3L + +#define SN_id_tc26_mac "id-tc26-mac" +#define NID_id_tc26_mac 987 +#define OBJ_id_tc26_mac OBJ_id_tc26_algorithms,4L + +#define SN_id_tc26_hmac_gost_3411_2012_256 "id-tc26-hmac-gost-3411-2012-256" +#define LN_id_tc26_hmac_gost_3411_2012_256 "HMAC GOST 34.11-2012 256 bit" +#define NID_id_tc26_hmac_gost_3411_2012_256 988 +#define OBJ_id_tc26_hmac_gost_3411_2012_256 OBJ_id_tc26_mac,1L + +#define SN_id_tc26_hmac_gost_3411_2012_512 "id-tc26-hmac-gost-3411-2012-512" +#define LN_id_tc26_hmac_gost_3411_2012_512 "HMAC GOST 34.11-2012 512 bit" +#define NID_id_tc26_hmac_gost_3411_2012_512 989 +#define OBJ_id_tc26_hmac_gost_3411_2012_512 OBJ_id_tc26_mac,2L + +#define SN_id_tc26_cipher "id-tc26-cipher" +#define NID_id_tc26_cipher 990 +#define OBJ_id_tc26_cipher OBJ_id_tc26_algorithms,5L + +#define SN_id_tc26_cipher_gostr3412_2015_magma "id-tc26-cipher-gostr3412-2015-magma" +#define NID_id_tc26_cipher_gostr3412_2015_magma 1173 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma OBJ_id_tc26_cipher,1L + +#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" +#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L + +#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" +#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175 +#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik "id-tc26-cipher-gostr3412-2015-kuznyechik" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik 1176 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik OBJ_id_tc26_cipher,2L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L + +#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" +#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178 +#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L + +#define SN_id_tc26_agreement "id-tc26-agreement" +#define NID_id_tc26_agreement 991 +#define OBJ_id_tc26_agreement OBJ_id_tc26_algorithms,6L + +#define SN_id_tc26_agreement_gost_3410_2012_256 "id-tc26-agreement-gost-3410-2012-256" +#define NID_id_tc26_agreement_gost_3410_2012_256 992 +#define OBJ_id_tc26_agreement_gost_3410_2012_256 OBJ_id_tc26_agreement,1L + +#define SN_id_tc26_agreement_gost_3410_2012_512 "id-tc26-agreement-gost-3410-2012-512" +#define NID_id_tc26_agreement_gost_3410_2012_512 993 +#define OBJ_id_tc26_agreement_gost_3410_2012_512 OBJ_id_tc26_agreement,2L + +#define SN_id_tc26_wrap "id-tc26-wrap" +#define NID_id_tc26_wrap 1179 +#define OBJ_id_tc26_wrap OBJ_id_tc26_algorithms,7L + +#define SN_id_tc26_wrap_gostr3412_2015_magma "id-tc26-wrap-gostr3412-2015-magma" +#define NID_id_tc26_wrap_gostr3412_2015_magma 1180 +#define OBJ_id_tc26_wrap_gostr3412_2015_magma OBJ_id_tc26_wrap,1L + +#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 "id-tc26-wrap-gostr3412-2015-magma-kexp15" +#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 1181 +#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L + +#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik "id-tc26-wrap-gostr3412-2015-kuznyechik" +#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik 1182 +#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik OBJ_id_tc26_wrap,2L + +#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" +#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183 +#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L + +#define SN_id_tc26_constants "id-tc26-constants" +#define NID_id_tc26_constants 994 +#define OBJ_id_tc26_constants OBJ_id_tc26,2L + +#define SN_id_tc26_sign_constants "id-tc26-sign-constants" +#define NID_id_tc26_sign_constants 995 +#define OBJ_id_tc26_sign_constants OBJ_id_tc26_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_constants "id-tc26-gost-3410-2012-256-constants" +#define NID_id_tc26_gost_3410_2012_256_constants 1147 +#define OBJ_id_tc26_gost_3410_2012_256_constants OBJ_id_tc26_sign_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_paramSetA "id-tc26-gost-3410-2012-256-paramSetA" +#define LN_id_tc26_gost_3410_2012_256_paramSetA "GOST R 34.10-2012 (256 bit) ParamSet A" +#define NID_id_tc26_gost_3410_2012_256_paramSetA 1148 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetA OBJ_id_tc26_gost_3410_2012_256_constants,1L + +#define SN_id_tc26_gost_3410_2012_256_paramSetB "id-tc26-gost-3410-2012-256-paramSetB" +#define LN_id_tc26_gost_3410_2012_256_paramSetB "GOST R 34.10-2012 (256 bit) ParamSet B" +#define NID_id_tc26_gost_3410_2012_256_paramSetB 1184 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetB OBJ_id_tc26_gost_3410_2012_256_constants,2L + +#define SN_id_tc26_gost_3410_2012_256_paramSetC "id-tc26-gost-3410-2012-256-paramSetC" +#define LN_id_tc26_gost_3410_2012_256_paramSetC "GOST R 34.10-2012 (256 bit) ParamSet C" +#define NID_id_tc26_gost_3410_2012_256_paramSetC 1185 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetC OBJ_id_tc26_gost_3410_2012_256_constants,3L + +#define SN_id_tc26_gost_3410_2012_256_paramSetD "id-tc26-gost-3410-2012-256-paramSetD" +#define LN_id_tc26_gost_3410_2012_256_paramSetD "GOST R 34.10-2012 (256 bit) ParamSet D" +#define NID_id_tc26_gost_3410_2012_256_paramSetD 1186 +#define OBJ_id_tc26_gost_3410_2012_256_paramSetD OBJ_id_tc26_gost_3410_2012_256_constants,4L + +#define SN_id_tc26_gost_3410_2012_512_constants "id-tc26-gost-3410-2012-512-constants" +#define NID_id_tc26_gost_3410_2012_512_constants 996 +#define OBJ_id_tc26_gost_3410_2012_512_constants OBJ_id_tc26_sign_constants,2L + +#define SN_id_tc26_gost_3410_2012_512_paramSetTest "id-tc26-gost-3410-2012-512-paramSetTest" +#define LN_id_tc26_gost_3410_2012_512_paramSetTest "GOST R 34.10-2012 (512 bit) testing parameter set" +#define NID_id_tc26_gost_3410_2012_512_paramSetTest 997 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetTest OBJ_id_tc26_gost_3410_2012_512_constants,0L + +#define SN_id_tc26_gost_3410_2012_512_paramSetA "id-tc26-gost-3410-2012-512-paramSetA" +#define LN_id_tc26_gost_3410_2012_512_paramSetA "GOST R 34.10-2012 (512 bit) ParamSet A" +#define NID_id_tc26_gost_3410_2012_512_paramSetA 998 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetA OBJ_id_tc26_gost_3410_2012_512_constants,1L + +#define SN_id_tc26_gost_3410_2012_512_paramSetB "id-tc26-gost-3410-2012-512-paramSetB" +#define LN_id_tc26_gost_3410_2012_512_paramSetB "GOST R 34.10-2012 (512 bit) ParamSet B" +#define NID_id_tc26_gost_3410_2012_512_paramSetB 999 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetB OBJ_id_tc26_gost_3410_2012_512_constants,2L + +#define SN_id_tc26_gost_3410_2012_512_paramSetC "id-tc26-gost-3410-2012-512-paramSetC" +#define LN_id_tc26_gost_3410_2012_512_paramSetC "GOST R 34.10-2012 (512 bit) ParamSet C" +#define NID_id_tc26_gost_3410_2012_512_paramSetC 1149 +#define OBJ_id_tc26_gost_3410_2012_512_paramSetC OBJ_id_tc26_gost_3410_2012_512_constants,3L + +#define SN_id_tc26_digest_constants "id-tc26-digest-constants" +#define NID_id_tc26_digest_constants 1000 +#define OBJ_id_tc26_digest_constants OBJ_id_tc26_constants,2L + +#define SN_id_tc26_cipher_constants "id-tc26-cipher-constants" +#define NID_id_tc26_cipher_constants 1001 +#define OBJ_id_tc26_cipher_constants OBJ_id_tc26_constants,5L + +#define SN_id_tc26_gost_28147_constants "id-tc26-gost-28147-constants" +#define NID_id_tc26_gost_28147_constants 1002 +#define OBJ_id_tc26_gost_28147_constants OBJ_id_tc26_cipher_constants,1L + +#define SN_id_tc26_gost_28147_param_Z "id-tc26-gost-28147-param-Z" +#define LN_id_tc26_gost_28147_param_Z "GOST 28147-89 TC26 parameter set" +#define NID_id_tc26_gost_28147_param_Z 1003 +#define OBJ_id_tc26_gost_28147_param_Z OBJ_id_tc26_gost_28147_constants,1L + +#define SN_INN "INN" +#define LN_INN "INN" +#define NID_INN 1004 +#define OBJ_INN OBJ_member_body,643L,3L,131L,1L,1L + +#define SN_OGRN "OGRN" +#define LN_OGRN "OGRN" +#define NID_OGRN 1005 +#define OBJ_OGRN OBJ_member_body,643L,100L,1L + +#define SN_SNILS "SNILS" +#define LN_SNILS "SNILS" +#define NID_SNILS 1006 +#define OBJ_SNILS OBJ_member_body,643L,100L,3L + +#define SN_subjectSignTool "subjectSignTool" +#define LN_subjectSignTool "Signing Tool of Subject" +#define NID_subjectSignTool 1007 +#define OBJ_subjectSignTool OBJ_member_body,643L,100L,111L + +#define SN_issuerSignTool "issuerSignTool" +#define LN_issuerSignTool "Signing Tool of Issuer" +#define NID_issuerSignTool 1008 +#define OBJ_issuerSignTool OBJ_member_body,643L,100L,112L + +#define SN_grasshopper_ecb "grasshopper-ecb" +#define NID_grasshopper_ecb 1012 + +#define SN_grasshopper_ctr "grasshopper-ctr" +#define NID_grasshopper_ctr 1013 + +#define SN_grasshopper_ofb "grasshopper-ofb" +#define NID_grasshopper_ofb 1014 + +#define SN_grasshopper_cbc "grasshopper-cbc" +#define NID_grasshopper_cbc 1015 + +#define SN_grasshopper_cfb "grasshopper-cfb" +#define NID_grasshopper_cfb 1016 + +#define SN_grasshopper_mac "grasshopper-mac" +#define NID_grasshopper_mac 1017 + +#define SN_magma_ecb "magma-ecb" +#define NID_magma_ecb 1187 + +#define SN_magma_ctr "magma-ctr" +#define NID_magma_ctr 1188 + +#define SN_magma_ofb "magma-ofb" +#define NID_magma_ofb 1189 + +#define SN_magma_cbc "magma-cbc" +#define NID_magma_cbc 1190 + +#define SN_magma_cfb "magma-cfb" +#define NID_magma_cfb 1191 + +#define SN_magma_mac "magma-mac" +#define NID_magma_mac 1192 + +#define SN_camellia_128_cbc "CAMELLIA-128-CBC" +#define LN_camellia_128_cbc "camellia-128-cbc" +#define NID_camellia_128_cbc 751 +#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L + +#define SN_camellia_192_cbc "CAMELLIA-192-CBC" +#define LN_camellia_192_cbc "camellia-192-cbc" +#define NID_camellia_192_cbc 752 +#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L + +#define SN_camellia_256_cbc "CAMELLIA-256-CBC" +#define LN_camellia_256_cbc "camellia-256-cbc" +#define NID_camellia_256_cbc 753 +#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L + +#define SN_id_camellia128_wrap "id-camellia128-wrap" +#define NID_id_camellia128_wrap 907 +#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L + +#define SN_id_camellia192_wrap "id-camellia192-wrap" +#define NID_id_camellia192_wrap 908 +#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L + +#define SN_id_camellia256_wrap "id-camellia256-wrap" +#define NID_id_camellia256_wrap 909 +#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L + +#define OBJ_ntt_ds 0L,3L,4401L,5L + +#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L + +#define SN_camellia_128_ecb "CAMELLIA-128-ECB" +#define LN_camellia_128_ecb "camellia-128-ecb" +#define NID_camellia_128_ecb 754 +#define OBJ_camellia_128_ecb OBJ_camellia,1L + +#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB" +#define LN_camellia_128_ofb128 "camellia-128-ofb" +#define NID_camellia_128_ofb128 766 +#define OBJ_camellia_128_ofb128 OBJ_camellia,3L + +#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB" +#define LN_camellia_128_cfb128 "camellia-128-cfb" +#define NID_camellia_128_cfb128 757 +#define OBJ_camellia_128_cfb128 OBJ_camellia,4L + +#define SN_camellia_128_gcm "CAMELLIA-128-GCM" +#define LN_camellia_128_gcm "camellia-128-gcm" +#define NID_camellia_128_gcm 961 +#define OBJ_camellia_128_gcm OBJ_camellia,6L + +#define SN_camellia_128_ccm "CAMELLIA-128-CCM" +#define LN_camellia_128_ccm "camellia-128-ccm" +#define NID_camellia_128_ccm 962 +#define OBJ_camellia_128_ccm OBJ_camellia,7L + +#define SN_camellia_128_ctr "CAMELLIA-128-CTR" +#define LN_camellia_128_ctr "camellia-128-ctr" +#define NID_camellia_128_ctr 963 +#define OBJ_camellia_128_ctr OBJ_camellia,9L + +#define SN_camellia_128_cmac "CAMELLIA-128-CMAC" +#define LN_camellia_128_cmac "camellia-128-cmac" +#define NID_camellia_128_cmac 964 +#define OBJ_camellia_128_cmac OBJ_camellia,10L + +#define SN_camellia_192_ecb "CAMELLIA-192-ECB" +#define LN_camellia_192_ecb "camellia-192-ecb" +#define NID_camellia_192_ecb 755 +#define OBJ_camellia_192_ecb OBJ_camellia,21L + +#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB" +#define LN_camellia_192_ofb128 "camellia-192-ofb" +#define NID_camellia_192_ofb128 767 +#define OBJ_camellia_192_ofb128 OBJ_camellia,23L + +#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB" +#define LN_camellia_192_cfb128 "camellia-192-cfb" +#define NID_camellia_192_cfb128 758 +#define OBJ_camellia_192_cfb128 OBJ_camellia,24L + +#define SN_camellia_192_gcm "CAMELLIA-192-GCM" +#define LN_camellia_192_gcm "camellia-192-gcm" +#define NID_camellia_192_gcm 965 +#define OBJ_camellia_192_gcm OBJ_camellia,26L + +#define SN_camellia_192_ccm "CAMELLIA-192-CCM" +#define LN_camellia_192_ccm "camellia-192-ccm" +#define NID_camellia_192_ccm 966 +#define OBJ_camellia_192_ccm OBJ_camellia,27L + +#define SN_camellia_192_ctr "CAMELLIA-192-CTR" +#define LN_camellia_192_ctr "camellia-192-ctr" +#define NID_camellia_192_ctr 967 +#define OBJ_camellia_192_ctr OBJ_camellia,29L + +#define SN_camellia_192_cmac "CAMELLIA-192-CMAC" +#define LN_camellia_192_cmac "camellia-192-cmac" +#define NID_camellia_192_cmac 968 +#define OBJ_camellia_192_cmac OBJ_camellia,30L + +#define SN_camellia_256_ecb "CAMELLIA-256-ECB" +#define LN_camellia_256_ecb "camellia-256-ecb" +#define NID_camellia_256_ecb 756 +#define OBJ_camellia_256_ecb OBJ_camellia,41L + +#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB" +#define LN_camellia_256_ofb128 "camellia-256-ofb" +#define NID_camellia_256_ofb128 768 +#define OBJ_camellia_256_ofb128 OBJ_camellia,43L + +#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB" +#define LN_camellia_256_cfb128 "camellia-256-cfb" +#define NID_camellia_256_cfb128 759 +#define OBJ_camellia_256_cfb128 OBJ_camellia,44L + +#define SN_camellia_256_gcm "CAMELLIA-256-GCM" +#define LN_camellia_256_gcm "camellia-256-gcm" +#define NID_camellia_256_gcm 969 +#define OBJ_camellia_256_gcm OBJ_camellia,46L + +#define SN_camellia_256_ccm "CAMELLIA-256-CCM" +#define LN_camellia_256_ccm "camellia-256-ccm" +#define NID_camellia_256_ccm 970 +#define OBJ_camellia_256_ccm OBJ_camellia,47L + +#define SN_camellia_256_ctr "CAMELLIA-256-CTR" +#define LN_camellia_256_ctr "camellia-256-ctr" +#define NID_camellia_256_ctr 971 +#define OBJ_camellia_256_ctr OBJ_camellia,49L + +#define SN_camellia_256_cmac "CAMELLIA-256-CMAC" +#define LN_camellia_256_cmac "camellia-256-cmac" +#define NID_camellia_256_cmac 972 +#define OBJ_camellia_256_cmac OBJ_camellia,50L + +#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1" +#define LN_camellia_128_cfb1 "camellia-128-cfb1" +#define NID_camellia_128_cfb1 760 + +#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1" +#define LN_camellia_192_cfb1 "camellia-192-cfb1" +#define NID_camellia_192_cfb1 761 + +#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1" +#define LN_camellia_256_cfb1 "camellia-256-cfb1" +#define NID_camellia_256_cfb1 762 + +#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8" +#define LN_camellia_128_cfb8 "camellia-128-cfb8" +#define NID_camellia_128_cfb8 763 + +#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8" +#define LN_camellia_192_cfb8 "camellia-192-cfb8" +#define NID_camellia_192_cfb8 764 + +#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8" +#define LN_camellia_256_cfb8 "camellia-256-cfb8" +#define NID_camellia_256_cfb8 765 + +#define OBJ_aria 1L,2L,410L,200046L,1L,1L + +#define SN_aria_128_ecb "ARIA-128-ECB" +#define LN_aria_128_ecb "aria-128-ecb" +#define NID_aria_128_ecb 1065 +#define OBJ_aria_128_ecb OBJ_aria,1L + +#define SN_aria_128_cbc "ARIA-128-CBC" +#define LN_aria_128_cbc "aria-128-cbc" +#define NID_aria_128_cbc 1066 +#define OBJ_aria_128_cbc OBJ_aria,2L + +#define SN_aria_128_cfb128 "ARIA-128-CFB" +#define LN_aria_128_cfb128 "aria-128-cfb" +#define NID_aria_128_cfb128 1067 +#define OBJ_aria_128_cfb128 OBJ_aria,3L + +#define SN_aria_128_ofb128 "ARIA-128-OFB" +#define LN_aria_128_ofb128 "aria-128-ofb" +#define NID_aria_128_ofb128 1068 +#define OBJ_aria_128_ofb128 OBJ_aria,4L + +#define SN_aria_128_ctr "ARIA-128-CTR" +#define LN_aria_128_ctr "aria-128-ctr" +#define NID_aria_128_ctr 1069 +#define OBJ_aria_128_ctr OBJ_aria,5L + +#define SN_aria_192_ecb "ARIA-192-ECB" +#define LN_aria_192_ecb "aria-192-ecb" +#define NID_aria_192_ecb 1070 +#define OBJ_aria_192_ecb OBJ_aria,6L + +#define SN_aria_192_cbc "ARIA-192-CBC" +#define LN_aria_192_cbc "aria-192-cbc" +#define NID_aria_192_cbc 1071 +#define OBJ_aria_192_cbc OBJ_aria,7L + +#define SN_aria_192_cfb128 "ARIA-192-CFB" +#define LN_aria_192_cfb128 "aria-192-cfb" +#define NID_aria_192_cfb128 1072 +#define OBJ_aria_192_cfb128 OBJ_aria,8L + +#define SN_aria_192_ofb128 "ARIA-192-OFB" +#define LN_aria_192_ofb128 "aria-192-ofb" +#define NID_aria_192_ofb128 1073 +#define OBJ_aria_192_ofb128 OBJ_aria,9L + +#define SN_aria_192_ctr "ARIA-192-CTR" +#define LN_aria_192_ctr "aria-192-ctr" +#define NID_aria_192_ctr 1074 +#define OBJ_aria_192_ctr OBJ_aria,10L + +#define SN_aria_256_ecb "ARIA-256-ECB" +#define LN_aria_256_ecb "aria-256-ecb" +#define NID_aria_256_ecb 1075 +#define OBJ_aria_256_ecb OBJ_aria,11L + +#define SN_aria_256_cbc "ARIA-256-CBC" +#define LN_aria_256_cbc "aria-256-cbc" +#define NID_aria_256_cbc 1076 +#define OBJ_aria_256_cbc OBJ_aria,12L + +#define SN_aria_256_cfb128 "ARIA-256-CFB" +#define LN_aria_256_cfb128 "aria-256-cfb" +#define NID_aria_256_cfb128 1077 +#define OBJ_aria_256_cfb128 OBJ_aria,13L + +#define SN_aria_256_ofb128 "ARIA-256-OFB" +#define LN_aria_256_ofb128 "aria-256-ofb" +#define NID_aria_256_ofb128 1078 +#define OBJ_aria_256_ofb128 OBJ_aria,14L + +#define SN_aria_256_ctr "ARIA-256-CTR" +#define LN_aria_256_ctr "aria-256-ctr" +#define NID_aria_256_ctr 1079 +#define OBJ_aria_256_ctr OBJ_aria,15L + +#define SN_aria_128_cfb1 "ARIA-128-CFB1" +#define LN_aria_128_cfb1 "aria-128-cfb1" +#define NID_aria_128_cfb1 1080 + +#define SN_aria_192_cfb1 "ARIA-192-CFB1" +#define LN_aria_192_cfb1 "aria-192-cfb1" +#define NID_aria_192_cfb1 1081 + +#define SN_aria_256_cfb1 "ARIA-256-CFB1" +#define LN_aria_256_cfb1 "aria-256-cfb1" +#define NID_aria_256_cfb1 1082 + +#define SN_aria_128_cfb8 "ARIA-128-CFB8" +#define LN_aria_128_cfb8 "aria-128-cfb8" +#define NID_aria_128_cfb8 1083 + +#define SN_aria_192_cfb8 "ARIA-192-CFB8" +#define LN_aria_192_cfb8 "aria-192-cfb8" +#define NID_aria_192_cfb8 1084 + +#define SN_aria_256_cfb8 "ARIA-256-CFB8" +#define LN_aria_256_cfb8 "aria-256-cfb8" +#define NID_aria_256_cfb8 1085 + +#define SN_aria_128_ccm "ARIA-128-CCM" +#define LN_aria_128_ccm "aria-128-ccm" +#define NID_aria_128_ccm 1120 +#define OBJ_aria_128_ccm OBJ_aria,37L + +#define SN_aria_192_ccm "ARIA-192-CCM" +#define LN_aria_192_ccm "aria-192-ccm" +#define NID_aria_192_ccm 1121 +#define OBJ_aria_192_ccm OBJ_aria,38L + +#define SN_aria_256_ccm "ARIA-256-CCM" +#define LN_aria_256_ccm "aria-256-ccm" +#define NID_aria_256_ccm 1122 +#define OBJ_aria_256_ccm OBJ_aria,39L + +#define SN_aria_128_gcm "ARIA-128-GCM" +#define LN_aria_128_gcm "aria-128-gcm" +#define NID_aria_128_gcm 1123 +#define OBJ_aria_128_gcm OBJ_aria,34L + +#define SN_aria_192_gcm "ARIA-192-GCM" +#define LN_aria_192_gcm "aria-192-gcm" +#define NID_aria_192_gcm 1124 +#define OBJ_aria_192_gcm OBJ_aria,35L + +#define SN_aria_256_gcm "ARIA-256-GCM" +#define LN_aria_256_gcm "aria-256-gcm" +#define NID_aria_256_gcm 1125 +#define OBJ_aria_256_gcm OBJ_aria,36L + +#define SN_kisa "KISA" +#define LN_kisa "kisa" +#define NID_kisa 773 +#define OBJ_kisa OBJ_member_body,410L,200004L + +#define SN_seed_ecb "SEED-ECB" +#define LN_seed_ecb "seed-ecb" +#define NID_seed_ecb 776 +#define OBJ_seed_ecb OBJ_kisa,1L,3L + +#define SN_seed_cbc "SEED-CBC" +#define LN_seed_cbc "seed-cbc" +#define NID_seed_cbc 777 +#define OBJ_seed_cbc OBJ_kisa,1L,4L + +#define SN_seed_cfb128 "SEED-CFB" +#define LN_seed_cfb128 "seed-cfb" +#define NID_seed_cfb128 779 +#define OBJ_seed_cfb128 OBJ_kisa,1L,5L + +#define SN_seed_ofb128 "SEED-OFB" +#define LN_seed_ofb128 "seed-ofb" +#define NID_seed_ofb128 778 +#define OBJ_seed_ofb128 OBJ_kisa,1L,6L + +#define SN_sm4_ecb "SM4-ECB" +#define LN_sm4_ecb "sm4-ecb" +#define NID_sm4_ecb 1133 +#define OBJ_sm4_ecb OBJ_sm_scheme,104L,1L + +#define SN_sm4_cbc "SM4-CBC" +#define LN_sm4_cbc "sm4-cbc" +#define NID_sm4_cbc 1134 +#define OBJ_sm4_cbc OBJ_sm_scheme,104L,2L + +#define SN_sm4_ofb128 "SM4-OFB" +#define LN_sm4_ofb128 "sm4-ofb" +#define NID_sm4_ofb128 1135 +#define OBJ_sm4_ofb128 OBJ_sm_scheme,104L,3L + +#define SN_sm4_cfb128 "SM4-CFB" +#define LN_sm4_cfb128 "sm4-cfb" +#define NID_sm4_cfb128 1137 +#define OBJ_sm4_cfb128 OBJ_sm_scheme,104L,4L + +#define SN_sm4_cfb1 "SM4-CFB1" +#define LN_sm4_cfb1 "sm4-cfb1" +#define NID_sm4_cfb1 1136 +#define OBJ_sm4_cfb1 OBJ_sm_scheme,104L,5L + +#define SN_sm4_cfb8 "SM4-CFB8" +#define LN_sm4_cfb8 "sm4-cfb8" +#define NID_sm4_cfb8 1138 +#define OBJ_sm4_cfb8 OBJ_sm_scheme,104L,6L + +#define SN_sm4_ctr "SM4-CTR" +#define LN_sm4_ctr "sm4-ctr" +#define NID_sm4_ctr 1139 +#define OBJ_sm4_ctr OBJ_sm_scheme,104L,7L + +#define SN_hmac "HMAC" +#define LN_hmac "hmac" +#define NID_hmac 855 + +#define SN_cmac "CMAC" +#define LN_cmac "cmac" +#define NID_cmac 894 + +#define SN_rc4_hmac_md5 "RC4-HMAC-MD5" +#define LN_rc4_hmac_md5 "rc4-hmac-md5" +#define NID_rc4_hmac_md5 915 + +#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1" +#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1" +#define NID_aes_128_cbc_hmac_sha1 916 + +#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1" +#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1" +#define NID_aes_192_cbc_hmac_sha1 917 + +#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1" +#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1" +#define NID_aes_256_cbc_hmac_sha1 918 + +#define SN_aes_128_cbc_hmac_sha256 "AES-128-CBC-HMAC-SHA256" +#define LN_aes_128_cbc_hmac_sha256 "aes-128-cbc-hmac-sha256" +#define NID_aes_128_cbc_hmac_sha256 948 + +#define SN_aes_192_cbc_hmac_sha256 "AES-192-CBC-HMAC-SHA256" +#define LN_aes_192_cbc_hmac_sha256 "aes-192-cbc-hmac-sha256" +#define NID_aes_192_cbc_hmac_sha256 949 + +#define SN_aes_256_cbc_hmac_sha256 "AES-256-CBC-HMAC-SHA256" +#define LN_aes_256_cbc_hmac_sha256 "aes-256-cbc-hmac-sha256" +#define NID_aes_256_cbc_hmac_sha256 950 + +#define SN_chacha20_poly1305 "ChaCha20-Poly1305" +#define LN_chacha20_poly1305 "chacha20-poly1305" +#define NID_chacha20_poly1305 1018 + +#define SN_chacha20 "ChaCha20" +#define LN_chacha20 "chacha20" +#define NID_chacha20 1019 + +#define SN_dhpublicnumber "dhpublicnumber" +#define LN_dhpublicnumber "X9.42 DH" +#define NID_dhpublicnumber 920 +#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L + +#define SN_brainpoolP160r1 "brainpoolP160r1" +#define NID_brainpoolP160r1 921 +#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L + +#define SN_brainpoolP160t1 "brainpoolP160t1" +#define NID_brainpoolP160t1 922 +#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L + +#define SN_brainpoolP192r1 "brainpoolP192r1" +#define NID_brainpoolP192r1 923 +#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L + +#define SN_brainpoolP192t1 "brainpoolP192t1" +#define NID_brainpoolP192t1 924 +#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L + +#define SN_brainpoolP224r1 "brainpoolP224r1" +#define NID_brainpoolP224r1 925 +#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L + +#define SN_brainpoolP224t1 "brainpoolP224t1" +#define NID_brainpoolP224t1 926 +#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L + +#define SN_brainpoolP256r1 "brainpoolP256r1" +#define NID_brainpoolP256r1 927 +#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L + +#define SN_brainpoolP256t1 "brainpoolP256t1" +#define NID_brainpoolP256t1 928 +#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L + +#define SN_brainpoolP320r1 "brainpoolP320r1" +#define NID_brainpoolP320r1 929 +#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L + +#define SN_brainpoolP320t1 "brainpoolP320t1" +#define NID_brainpoolP320t1 930 +#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L + +#define SN_brainpoolP384r1 "brainpoolP384r1" +#define NID_brainpoolP384r1 931 +#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L + +#define SN_brainpoolP384t1 "brainpoolP384t1" +#define NID_brainpoolP384t1 932 +#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L + +#define SN_brainpoolP512r1 "brainpoolP512r1" +#define NID_brainpoolP512r1 933 +#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L + +#define SN_brainpoolP512t1 "brainpoolP512t1" +#define NID_brainpoolP512t1 934 +#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L + +#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L + +#define OBJ_secg_scheme OBJ_certicom_arc,1L + +#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme" +#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936 +#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L + +#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme" +#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937 +#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L + +#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme" +#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938 +#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L + +#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme" +#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939 +#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L + +#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme" +#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940 +#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L + +#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941 +#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L + +#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942 +#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L + +#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943 +#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L + +#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944 +#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L + +#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945 +#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L + +#define SN_dh_std_kdf "dh-std-kdf" +#define NID_dh_std_kdf 946 + +#define SN_dh_cofactor_kdf "dh-cofactor-kdf" +#define NID_dh_cofactor_kdf 947 + +#define SN_ct_precert_scts "ct_precert_scts" +#define LN_ct_precert_scts "CT Precertificate SCTs" +#define NID_ct_precert_scts 951 +#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L + +#define SN_ct_precert_poison "ct_precert_poison" +#define LN_ct_precert_poison "CT Precertificate Poison" +#define NID_ct_precert_poison 952 +#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L + +#define SN_ct_precert_signer "ct_precert_signer" +#define LN_ct_precert_signer "CT Precertificate Signer" +#define NID_ct_precert_signer 953 +#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L + +#define SN_ct_cert_scts "ct_cert_scts" +#define LN_ct_cert_scts "CT Certificate SCTs" +#define NID_ct_cert_scts 954 +#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L + +#define SN_jurisdictionLocalityName "jurisdictionL" +#define LN_jurisdictionLocalityName "jurisdictionLocalityName" +#define NID_jurisdictionLocalityName 955 +#define OBJ_jurisdictionLocalityName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,1L + +#define SN_jurisdictionStateOrProvinceName "jurisdictionST" +#define LN_jurisdictionStateOrProvinceName "jurisdictionStateOrProvinceName" +#define NID_jurisdictionStateOrProvinceName 956 +#define OBJ_jurisdictionStateOrProvinceName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,2L + +#define SN_jurisdictionCountryName "jurisdictionC" +#define LN_jurisdictionCountryName "jurisdictionCountryName" +#define NID_jurisdictionCountryName 957 +#define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L + +#define SN_id_scrypt "id-scrypt" +#define LN_id_scrypt "scrypt" +#define NID_id_scrypt 973 +#define OBJ_id_scrypt 1L,3L,6L,1L,4L,1L,11591L,4L,11L + +#define SN_tls1_prf "TLS1-PRF" +#define LN_tls1_prf "tls1-prf" +#define NID_tls1_prf 1021 + +#define SN_hkdf "HKDF" +#define LN_hkdf "hkdf" +#define NID_hkdf 1036 + +#define SN_id_pkinit "id-pkinit" +#define NID_id_pkinit 1031 +#define OBJ_id_pkinit 1L,3L,6L,1L,5L,2L,3L + +#define SN_pkInitClientAuth "pkInitClientAuth" +#define LN_pkInitClientAuth "PKINIT Client Auth" +#define NID_pkInitClientAuth 1032 +#define OBJ_pkInitClientAuth OBJ_id_pkinit,4L + +#define SN_pkInitKDC "pkInitKDC" +#define LN_pkInitKDC "Signing KDC Response" +#define NID_pkInitKDC 1033 +#define OBJ_pkInitKDC OBJ_id_pkinit,5L + +#define SN_X25519 "X25519" +#define NID_X25519 1034 +#define OBJ_X25519 1L,3L,101L,110L + +#define SN_X448 "X448" +#define NID_X448 1035 +#define OBJ_X448 1L,3L,101L,111L + +#define SN_ED25519 "ED25519" +#define NID_ED25519 1087 +#define OBJ_ED25519 1L,3L,101L,112L + +#define SN_ED448 "ED448" +#define NID_ED448 1088 +#define OBJ_ED448 1L,3L,101L,113L + +#define SN_kx_rsa "KxRSA" +#define LN_kx_rsa "kx-rsa" +#define NID_kx_rsa 1037 + +#define SN_kx_ecdhe "KxECDHE" +#define LN_kx_ecdhe "kx-ecdhe" +#define NID_kx_ecdhe 1038 + +#define SN_kx_dhe "KxDHE" +#define LN_kx_dhe "kx-dhe" +#define NID_kx_dhe 1039 + +#define SN_kx_ecdhe_psk "KxECDHE-PSK" +#define LN_kx_ecdhe_psk "kx-ecdhe-psk" +#define NID_kx_ecdhe_psk 1040 + +#define SN_kx_dhe_psk "KxDHE-PSK" +#define LN_kx_dhe_psk "kx-dhe-psk" +#define NID_kx_dhe_psk 1041 + +#define SN_kx_rsa_psk "KxRSA_PSK" +#define LN_kx_rsa_psk "kx-rsa-psk" +#define NID_kx_rsa_psk 1042 + +#define SN_kx_psk "KxPSK" +#define LN_kx_psk "kx-psk" +#define NID_kx_psk 1043 + +#define SN_kx_srp "KxSRP" +#define LN_kx_srp "kx-srp" +#define NID_kx_srp 1044 + +#define SN_kx_gost "KxGOST" +#define LN_kx_gost "kx-gost" +#define NID_kx_gost 1045 + +#define SN_kx_any "KxANY" +#define LN_kx_any "kx-any" +#define NID_kx_any 1063 + +#define SN_auth_rsa "AuthRSA" +#define LN_auth_rsa "auth-rsa" +#define NID_auth_rsa 1046 + +#define SN_auth_ecdsa "AuthECDSA" +#define LN_auth_ecdsa "auth-ecdsa" +#define NID_auth_ecdsa 1047 + +#define SN_auth_psk "AuthPSK" +#define LN_auth_psk "auth-psk" +#define NID_auth_psk 1048 + +#define SN_auth_dss "AuthDSS" +#define LN_auth_dss "auth-dss" +#define NID_auth_dss 1049 + +#define SN_auth_gost01 "AuthGOST01" +#define LN_auth_gost01 "auth-gost01" +#define NID_auth_gost01 1050 + +#define SN_auth_gost12 "AuthGOST12" +#define LN_auth_gost12 "auth-gost12" +#define NID_auth_gost12 1051 + +#define SN_auth_srp "AuthSRP" +#define LN_auth_srp "auth-srp" +#define NID_auth_srp 1052 + +#define SN_auth_null "AuthNULL" +#define LN_auth_null "auth-null" +#define NID_auth_null 1053 + +#define SN_auth_any "AuthANY" +#define LN_auth_any "auth-any" +#define NID_auth_any 1064 + +#define SN_poly1305 "Poly1305" +#define LN_poly1305 "poly1305" +#define NID_poly1305 1061 + +#define SN_siphash "SipHash" +#define LN_siphash "siphash" +#define NID_siphash 1062 + +#define SN_ffdhe2048 "ffdhe2048" +#define NID_ffdhe2048 1126 + +#define SN_ffdhe3072 "ffdhe3072" +#define NID_ffdhe3072 1127 + +#define SN_ffdhe4096 "ffdhe4096" +#define NID_ffdhe4096 1128 + +#define SN_ffdhe6144 "ffdhe6144" +#define NID_ffdhe6144 1129 + +#define SN_ffdhe8192 "ffdhe8192" +#define NID_ffdhe8192 1130 + +#define SN_ISO_UA "ISO-UA" +#define NID_ISO_UA 1150 +#define OBJ_ISO_UA OBJ_member_body,804L + +#define SN_ua_pki "ua-pki" +#define NID_ua_pki 1151 +#define OBJ_ua_pki OBJ_ISO_UA,2L,1L,1L,1L + +#define SN_dstu28147 "dstu28147" +#define LN_dstu28147 "DSTU Gost 28147-2009" +#define NID_dstu28147 1152 +#define OBJ_dstu28147 OBJ_ua_pki,1L,1L,1L + +#define SN_dstu28147_ofb "dstu28147-ofb" +#define LN_dstu28147_ofb "DSTU Gost 28147-2009 OFB mode" +#define NID_dstu28147_ofb 1153 +#define OBJ_dstu28147_ofb OBJ_dstu28147,2L + +#define SN_dstu28147_cfb "dstu28147-cfb" +#define LN_dstu28147_cfb "DSTU Gost 28147-2009 CFB mode" +#define NID_dstu28147_cfb 1154 +#define OBJ_dstu28147_cfb OBJ_dstu28147,3L + +#define SN_dstu28147_wrap "dstu28147-wrap" +#define LN_dstu28147_wrap "DSTU Gost 28147-2009 key wrap" +#define NID_dstu28147_wrap 1155 +#define OBJ_dstu28147_wrap OBJ_dstu28147,5L + +#define SN_hmacWithDstu34311 "hmacWithDstu34311" +#define LN_hmacWithDstu34311 "HMAC DSTU Gost 34311-95" +#define NID_hmacWithDstu34311 1156 +#define OBJ_hmacWithDstu34311 OBJ_ua_pki,1L,1L,2L + +#define SN_dstu34311 "dstu34311" +#define LN_dstu34311 "DSTU Gost 34311-95" +#define NID_dstu34311 1157 +#define OBJ_dstu34311 OBJ_ua_pki,1L,2L,1L + +#define SN_dstu4145le "dstu4145le" +#define LN_dstu4145le "DSTU 4145-2002 little endian" +#define NID_dstu4145le 1158 +#define OBJ_dstu4145le OBJ_ua_pki,1L,3L,1L,1L + +#define SN_dstu4145be "dstu4145be" +#define LN_dstu4145be "DSTU 4145-2002 big endian" +#define NID_dstu4145be 1159 +#define OBJ_dstu4145be OBJ_dstu4145le,1L,1L + +#define SN_uacurve0 "uacurve0" +#define LN_uacurve0 "DSTU curve 0" +#define NID_uacurve0 1160 +#define OBJ_uacurve0 OBJ_dstu4145le,2L,0L + +#define SN_uacurve1 "uacurve1" +#define LN_uacurve1 "DSTU curve 1" +#define NID_uacurve1 1161 +#define OBJ_uacurve1 OBJ_dstu4145le,2L,1L + +#define SN_uacurve2 "uacurve2" +#define LN_uacurve2 "DSTU curve 2" +#define NID_uacurve2 1162 +#define OBJ_uacurve2 OBJ_dstu4145le,2L,2L + +#define SN_uacurve3 "uacurve3" +#define LN_uacurve3 "DSTU curve 3" +#define NID_uacurve3 1163 +#define OBJ_uacurve3 OBJ_dstu4145le,2L,3L + +#define SN_uacurve4 "uacurve4" +#define LN_uacurve4 "DSTU curve 4" +#define NID_uacurve4 1164 +#define OBJ_uacurve4 OBJ_dstu4145le,2L,4L + +#define SN_uacurve5 "uacurve5" +#define LN_uacurve5 "DSTU curve 5" +#define NID_uacurve5 1165 +#define OBJ_uacurve5 OBJ_dstu4145le,2L,5L + +#define SN_uacurve6 "uacurve6" +#define LN_uacurve6 "DSTU curve 6" +#define NID_uacurve6 1166 +#define OBJ_uacurve6 OBJ_dstu4145le,2L,6L + +#define SN_uacurve7 "uacurve7" +#define LN_uacurve7 "DSTU curve 7" +#define NID_uacurve7 1167 +#define OBJ_uacurve7 OBJ_dstu4145le,2L,7L + +#define SN_uacurve8 "uacurve8" +#define LN_uacurve8 "DSTU curve 8" +#define NID_uacurve8 1168 +#define OBJ_uacurve8 OBJ_dstu4145le,2L,8L + +#define SN_uacurve9 "uacurve9" +#define LN_uacurve9 "DSTU curve 9" +#define NID_uacurve9 1169 +#define OBJ_uacurve9 OBJ_dstu4145le,2L,9L diff --git a/thirdparty/user_include/openssl/objects.h b/thirdparty/user_include/openssl/objects.h new file mode 100755 index 0000000000000000000000000000000000000000..5e8b5762f8729f4e1774a71ebeea6c8cb66727da --- /dev/null +++ b/thirdparty/user_include/openssl/objects.h @@ -0,0 +1,175 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OBJECTS_H +# define HEADER_OBJECTS_H + +# include +# include +# include +# include + +# define OBJ_NAME_TYPE_UNDEF 0x00 +# define OBJ_NAME_TYPE_MD_METH 0x01 +# define OBJ_NAME_TYPE_CIPHER_METH 0x02 +# define OBJ_NAME_TYPE_PKEY_METH 0x03 +# define OBJ_NAME_TYPE_COMP_METH 0x04 +# define OBJ_NAME_TYPE_NUM 0x05 + +# define OBJ_NAME_ALIAS 0x8000 + +# define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01 +# define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct obj_name_st { + int type; + int alias; + const char *name; + const char *data; +} OBJ_NAME; + +# define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) + +int OBJ_NAME_init(void); +int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), + int (*cmp_func) (const char *, const char *), + void (*free_func) (const char *, int, const char *)); +const char *OBJ_NAME_get(const char *name, int type); +int OBJ_NAME_add(const char *name, int type, const char *data); +int OBJ_NAME_remove(const char *name, int type); +void OBJ_NAME_cleanup(int type); /* -1 for everything */ +void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg), + void *arg); +void OBJ_NAME_do_all_sorted(int type, + void (*fn) (const OBJ_NAME *, void *arg), + void *arg); + +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_nid2obj(int n); +const char *OBJ_nid2ln(int n); +const char *OBJ_nid2sn(int n); +int OBJ_obj2nid(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(const char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); +const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, + int (*cmp) (const void *, const void *)); +const void *OBJ_bsearch_ex_(const void *key, const void *base, int num, + int size, + int (*cmp) (const void *, const void *), + int flags); + +# define _DECLARE_OBJ_BSEARCH_CMP_FN(scope, type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *, const void *); \ + static int nm##_cmp(type1 const *, type2 const *); \ + scope type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +# define DECLARE_OBJ_BSEARCH_CMP_FN(type1, type2, cmp) \ + _DECLARE_OBJ_BSEARCH_CMP_FN(static, type1, type2, cmp) +# define DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +/*- + * Unsolved problem: if a type is actually a pointer type, like + * nid_triple is, then its impossible to get a const where you need + * it. Consider: + * + * typedef int nid_triple[3]; + * const void *a_; + * const nid_triple const *a = a_; + * + * The assignment discards a const because what you really want is: + * + * const int const * const *a = a_; + * + * But if you do that, you lose the fact that a is an array of 3 ints, + * which breaks comparison functions. + * + * Thus we end up having to cast, sadly, or unpack the + * declarations. Or, as I finally did in this case, declare nid_triple + * to be a struct, which it should have been in the first place. + * + * Ben, August 2008. + * + * Also, strictly speaking not all types need be const, but handling + * the non-constness means a lot of complication, and in practice + * comparison routines do always not touch their arguments. + */ + +# define IMPLEMENT_OBJ_BSEARCH_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + static type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define OBJ_bsearch(type1,key,type2,base,num,cmp) \ + ((type2 *)OBJ_bsearch_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN))) + +# define OBJ_bsearch_ex(type1,key,type2,base,num,cmp,flags) \ + ((type2 *)OBJ_bsearch_ex_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)type_2=CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN)),flags) + +int OBJ_new_nid(int num); +int OBJ_add_object(const ASN1_OBJECT *obj); +int OBJ_create(const char *oid, const char *sn, const char *ln); +#if OPENSSL_API_COMPAT < 0x10100000L +# define OBJ_cleanup() while(0) continue +#endif +int OBJ_create_objects(BIO *in); + +size_t OBJ_length(const ASN1_OBJECT *obj); +const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj); + +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); +int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid); +int OBJ_add_sigid(int signid, int dig_id, int pkey_id); +void OBJ_sigid_free(void); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/objectserr.h b/thirdparty/user_include/openssl/objectserr.h new file mode 100755 index 0000000000000000000000000000000000000000..02308dfac8fd726e24653d94e9746d696f0cb6f7 --- /dev/null +++ b/thirdparty/user_include/openssl/objectserr.h @@ -0,0 +1,38 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OBJERR_H +# define HEADER_OBJERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OBJ_strings(void); + +/* + * OBJ function codes. + */ +# define OBJ_F_OBJ_ADD_OBJECT 105 +# define OBJ_F_OBJ_ADD_SIGID 107 +# define OBJ_F_OBJ_CREATE 100 +# define OBJ_F_OBJ_DUP 101 +# define OBJ_F_OBJ_NAME_NEW_INDEX 106 +# define OBJ_F_OBJ_NID2LN 102 +# define OBJ_F_OBJ_NID2OBJ 103 +# define OBJ_F_OBJ_NID2SN 104 +# define OBJ_F_OBJ_TXT2OBJ 108 + +/* + * OBJ reason codes. + */ +# define OBJ_R_OID_EXISTS 102 +# define OBJ_R_UNKNOWN_NID 101 + +#endif diff --git a/thirdparty/user_include/openssl/ocsp.h b/thirdparty/user_include/openssl/ocsp.h new file mode 100755 index 0000000000000000000000000000000000000000..0a17166b5bf6a8876961588ae483626032a71e55 --- /dev/null +++ b/thirdparty/user_include/openssl/ocsp.h @@ -0,0 +1,352 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OCSP_H +# define HEADER_OCSP_H + +#include + +/* + * These definitions are outside the OPENSSL_NO_OCSP guard because although for + * historical reasons they have OCSP_* names, they can actually be used + * independently of OCSP. E.g. see RFC5280 + */ +/*- + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + */ +# define OCSP_REVOKED_STATUS_NOSTATUS -1 +# define OCSP_REVOKED_STATUS_UNSPECIFIED 0 +# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1 +# define OCSP_REVOKED_STATUS_CACOMPROMISE 2 +# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3 +# define OCSP_REVOKED_STATUS_SUPERSEDED 4 +# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5 +# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 +# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 + + +# ifndef OPENSSL_NO_OCSP + +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Various flags and values */ + +# define OCSP_DEFAULT_NONCE_LENGTH 16 + +# define OCSP_NOCERTS 0x1 +# define OCSP_NOINTERN 0x2 +# define OCSP_NOSIGS 0x4 +# define OCSP_NOCHAIN 0x8 +# define OCSP_NOVERIFY 0x10 +# define OCSP_NOEXPLICIT 0x20 +# define OCSP_NOCASIGN 0x40 +# define OCSP_NODELEGATED 0x80 +# define OCSP_NOCHECKS 0x100 +# define OCSP_TRUSTOTHER 0x200 +# define OCSP_RESPID_KEY 0x400 +# define OCSP_NOTIME 0x800 + +typedef struct ocsp_cert_id_st OCSP_CERTID; + +DEFINE_STACK_OF(OCSP_CERTID) + +typedef struct ocsp_one_request_st OCSP_ONEREQ; + +DEFINE_STACK_OF(OCSP_ONEREQ) + +typedef struct ocsp_req_info_st OCSP_REQINFO; +typedef struct ocsp_signature_st OCSP_SIGNATURE; +typedef struct ocsp_request_st OCSP_REQUEST; + +# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +# define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +# define OCSP_RESPONSE_STATUS_TRYLATER 3 +# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES; + +# define V_OCSP_RESPID_NAME 0 +# define V_OCSP_RESPID_KEY 1 + +DEFINE_STACK_OF(OCSP_RESPID) + +typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO; + +# define V_OCSP_CERTSTATUS_GOOD 0 +# define V_OCSP_CERTSTATUS_REVOKED 1 +# define V_OCSP_CERTSTATUS_UNKNOWN 2 + +typedef struct ocsp_cert_status_st OCSP_CERTSTATUS; +typedef struct ocsp_single_response_st OCSP_SINGLERESP; + +DEFINE_STACK_OF(OCSP_SINGLERESP) + +typedef struct ocsp_response_data_st OCSP_RESPDATA; + +typedef struct ocsp_basic_response_st OCSP_BASICRESP; + +typedef struct ocsp_crl_id_st OCSP_CRLID; +typedef struct ocsp_service_locator_st OCSP_SERVICELOC; + +# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" +# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" + +# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p) + +# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p) + +# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \ + bp,(char **)(x),cb,NULL) + +# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\ + (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \ + bp,(char **)(x),cb,NULL) + +# define PEM_write_bio_OCSP_REQUEST(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\ + bp,(char *)(o), NULL,NULL,0,NULL,NULL) + +# define PEM_write_bio_OCSP_RESPONSE(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ + bp,(char *)(o), NULL,NULL,0,NULL,NULL) + +# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o) + +# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o) + +# define ASN1_BIT_STRING_digest(data,type,md,len) \ + ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len) + +# define OCSP_CERTSTATUS_dup(cs)\ + (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\ + (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs)) + +OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id); + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req); +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, + int maxline); +int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx); +int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx); +OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline); +void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx); +void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len); +int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, + ASN1_VALUE *val); +int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval, + const ASN1_ITEM *it); +BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx); +int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path); +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req); +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value); + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, + const X509 *issuer); + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + const X509_NAME *issuerName, + const ASN1_BIT_STRING *issuerKey, + const ASN1_INTEGER *serialNumber); + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); + +const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs); +const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs); +const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs); + +int OCSP_resp_count(OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs); +const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, + const ASN1_OCTET_STRING **pid, + const X509_NAME **pname); +int OCSP_resp_get1_id(const OCSP_BASICRESP *bs, + ASN1_OCTET_STRING **pid, + X509_NAME **pname); + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec); + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, + X509_STORE *store, unsigned long flags); + +int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, + int *pssl); + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + +int OCSP_request_onereq_count(OCSP_REQUEST *req); +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one); +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid); +int OCSP_request_is_signed(OCSP_REQUEST *req); +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, + ASN1_TIME *nextupd); +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); +int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp, + X509 *signer, EVP_MD_CTX *ctx, + STACK_OF(X509) *certs, unsigned long flags); +int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert); +int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert); + +X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim); + +X509_EXTENSION *OCSP_accept_responses_new(char **oids); + +X509_EXTENSION *OCSP_archive_cutoff_new(char *tim); + +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls); + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x); +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos); +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos); +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc); +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc); +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, + int *idx); +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc); + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x); +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos); +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos); +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos); +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc); +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc); +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx); +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc); + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x); +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos); +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc); +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc); +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, + int *idx); +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc); + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x); +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos); +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc); +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc); +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, + int *idx); +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc); +const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x); + +DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS) +DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPID) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES) +DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTID) +DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST) +DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE) +DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_CRLID) +DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC) + +const char *OCSP_response_status_str(long s); +const char *OCSP_cert_status_str(long s); +const char *OCSP_crl_reason_str(long s); + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags); +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags); + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/ocsperr.h b/thirdparty/user_include/openssl/ocsperr.h new file mode 100755 index 0000000000000000000000000000000000000000..7d93b12d497ee0ab8aaee299efe08613444ddff4 --- /dev/null +++ b/thirdparty/user_include/openssl/ocsperr.h @@ -0,0 +1,74 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OCSPERR_H +# define HEADER_OCSPERR_H + +# include + +# ifndef OPENSSL_NO_OCSP + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OCSP_strings(void); + +/* + * OCSP function codes. + */ +# define OCSP_F_D2I_OCSP_NONCE 102 +# define OCSP_F_OCSP_BASIC_ADD1_STATUS 103 +# define OCSP_F_OCSP_BASIC_SIGN 104 +# define OCSP_F_OCSP_BASIC_SIGN_CTX 119 +# define OCSP_F_OCSP_BASIC_VERIFY 105 +# define OCSP_F_OCSP_CERT_ID_NEW 101 +# define OCSP_F_OCSP_CHECK_DELEGATED 106 +# define OCSP_F_OCSP_CHECK_IDS 107 +# define OCSP_F_OCSP_CHECK_ISSUER 108 +# define OCSP_F_OCSP_CHECK_VALIDITY 115 +# define OCSP_F_OCSP_MATCH_ISSUERID 109 +# define OCSP_F_OCSP_PARSE_URL 114 +# define OCSP_F_OCSP_REQUEST_SIGN 110 +# define OCSP_F_OCSP_REQUEST_VERIFY 116 +# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 +# define OCSP_F_PARSE_HTTP_LINE1 118 + +/* + * OCSP reason codes. + */ +# define OCSP_R_CERTIFICATE_VERIFY_ERROR 101 +# define OCSP_R_DIGEST_ERR 102 +# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122 +# define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123 +# define OCSP_R_ERROR_PARSING_URL 121 +# define OCSP_R_MISSING_OCSPSIGNING_USAGE 103 +# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124 +# define OCSP_R_NOT_BASIC_RESPONSE 104 +# define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105 +# define OCSP_R_NO_RESPONSE_DATA 108 +# define OCSP_R_NO_REVOKED_TIME 109 +# define OCSP_R_NO_SIGNER_KEY 130 +# define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110 +# define OCSP_R_REQUEST_NOT_SIGNED 128 +# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111 +# define OCSP_R_ROOT_CA_NOT_TRUSTED 112 +# define OCSP_R_SERVER_RESPONSE_ERROR 114 +# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115 +# define OCSP_R_SIGNATURE_FAILURE 117 +# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118 +# define OCSP_R_STATUS_EXPIRED 125 +# define OCSP_R_STATUS_NOT_YET_VALID 126 +# define OCSP_R_STATUS_TOO_OLD 127 +# define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119 +# define OCSP_R_UNKNOWN_NID 120 +# define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/opensslconf.h b/thirdparty/user_include/openssl/opensslconf.h new file mode 100755 index 0000000000000000000000000000000000000000..5fe1bb4b7e53cb6afcf13e65cd9c77bba7d3ac28 --- /dev/null +++ b/thirdparty/user_include/openssl/opensslconf.h @@ -0,0 +1,201 @@ +/* + * WARNING: do not edit! + * Generated by Makefile from include/openssl/opensslconf.h.in + * + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_ALGORITHM_DEFINES +# error OPENSSL_ALGORITHM_DEFINES no longer supported +#endif + +/* + * OpenSSL was configured with the following options: + */ + +#ifndef OPENSSL_SYS_MINGW64 +# define OPENSSL_SYS_MINGW64 1 +#endif +#ifndef OPENSSL_NO_MD2 +# define OPENSSL_NO_MD2 +#endif +#ifndef OPENSSL_NO_RC5 +# define OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif +#ifndef OPENSSL_RAND_SEED_OS +# define OPENSSL_RAND_SEED_OS +#endif +#ifndef OPENSSL_NO_ASAN +# define OPENSSL_NO_ASAN +#endif +#ifndef OPENSSL_NO_ASM +# define OPENSSL_NO_ASM +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +# define OPENSSL_NO_CRYPTO_MDEBUG +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +# define OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +#endif +#ifndef OPENSSL_NO_DEVCRYPTOENG +# define OPENSSL_NO_DEVCRYPTOENG +#endif +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# define OPENSSL_NO_EC_NISTP_64_GCC_128 +#endif +#ifndef OPENSSL_NO_EGD +# define OPENSSL_NO_EGD +#endif +#ifndef OPENSSL_NO_EXTERNAL_TESTS +# define OPENSSL_NO_EXTERNAL_TESTS +#endif +#ifndef OPENSSL_NO_FUZZ_AFL +# define OPENSSL_NO_FUZZ_AFL +#endif +#ifndef OPENSSL_NO_FUZZ_LIBFUZZER +# define OPENSSL_NO_FUZZ_LIBFUZZER +#endif +#ifndef OPENSSL_NO_HEARTBEATS +# define OPENSSL_NO_HEARTBEATS +#endif +#ifndef OPENSSL_NO_MSAN +# define OPENSSL_NO_MSAN +#endif +#ifndef OPENSSL_NO_SCTP +# define OPENSSL_NO_SCTP +#endif +#ifndef OPENSSL_NO_SSL_TRACE +# define OPENSSL_NO_SSL_TRACE +#endif +#ifndef OPENSSL_NO_SSL3 +# define OPENSSL_NO_SSL3 +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +# define OPENSSL_NO_SSL3_METHOD +#endif +#ifndef OPENSSL_NO_UBSAN +# define OPENSSL_NO_UBSAN +#endif +#ifndef OPENSSL_NO_UNIT_TEST +# define OPENSSL_NO_UNIT_TEST +#endif +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS +# define OPENSSL_NO_WEAK_SSL_CIPHERS +#endif +#ifndef OPENSSL_NO_DYNAMIC_ENGINE +# define OPENSSL_NO_DYNAMIC_ENGINE +#endif +#ifndef OPENSSL_NO_AFALGENG +# define OPENSSL_NO_AFALGENG +#endif + + +/* + * Sometimes OPENSSSL_NO_xxx ends up with an empty file and some compilers + * don't like that. This will hopefully silence them. + */ +#define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy; + +/* + * Applications should use -DOPENSSL_API_COMPAT= to suppress the + * declarations of functions deprecated in or before . Otherwise, they + * still won't see them if the library has been built to disable deprecated + * functions. + */ +#ifndef DECLARE_DEPRECATED +# define DECLARE_DEPRECATED(f) f; +# ifdef __GNUC__ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) +# undef DECLARE_DEPRECATED +# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated)); +# endif +# endif +#endif + +#ifndef OPENSSL_FILE +# ifdef OPENSSL_NO_FILENAMES +# define OPENSSL_FILE "" +# define OPENSSL_LINE 0 +# else +# define OPENSSL_FILE __FILE__ +# define OPENSSL_LINE __LINE__ +# endif +#endif + +#ifndef OPENSSL_MIN_API +# define OPENSSL_MIN_API 0 +#endif + +#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < OPENSSL_MIN_API +# undef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT OPENSSL_MIN_API +#endif + +/* + * Do not deprecate things to be deprecated in version 1.2.0 before the + * OpenSSL version number matches. + */ +#if OPENSSL_VERSION_NUMBER < 0x10200000L +# define DEPRECATEDIN_1_2_0(f) f; +#elif OPENSSL_API_COMPAT < 0x10200000L +# define DEPRECATEDIN_1_2_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_2_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x10100000L +# define DEPRECATEDIN_1_1_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_1_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x10000000L +# define DEPRECATEDIN_1_0_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_0_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x00908000L +# define DEPRECATEDIN_0_9_8(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_0_9_8(f) +#endif + +/* Generate 80386 code? */ +#undef I386_ONLY + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#define OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* + * The following are cipher-specific, but are part of the public API. + */ +#if !defined(OPENSSL_SYS_UEFI) +# undef BN_LLONG +/* Only one for the following should be defined */ +# undef SIXTY_FOUR_BIT_LONG +# define SIXTY_FOUR_BIT +# undef THIRTY_TWO_BIT +#endif + +#define RC4_INT unsigned int + +#ifdef __cplusplus +} +#endif diff --git a/thirdparty/user_include/openssl/opensslv.h b/thirdparty/user_include/openssl/opensslv.h new file mode 100755 index 0000000000000000000000000000000000000000..a4aa45bd246ce0612c4268d37cf4711ff16a80ae --- /dev/null +++ b/thirdparty/user_include/openssl/opensslv.h @@ -0,0 +1,101 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OPENSSLV_H +# define HEADER_OPENSSLV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*- + * Numeric release version identifier: + * MNNFFPPS: major minor fix patch status + * The status nibble has one of the values 0 for development, 1 to e for betas + * 1 to 14, and f for release. The patch level is exactly that. + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3-beta1 0x00903001 + * 0.9.3-beta2-dev 0x00903002 + * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) + * 0.9.3 0x0090300f + * 0.9.3a 0x0090301f + * 0.9.4 0x0090400f + * 1.2.3z 0x102031af + * + * For continuity reasons (because 0.9.5 is already out, and is coded + * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level + * part is slightly different, by setting the highest bit. This means + * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start + * with 0x0090600S... + * + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for + * major minor fix final patch/beta) + */ +# define OPENSSL_VERSION_NUMBER 0x1010102fL +# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1b 26 Feb 2019" + +/*- + * The macros below are to be used for shared library (.so, .dll, ...) + * versioning. That kind of versioning works a bit differently between + * operating systems. The most usual scheme is to set a major and a minor + * number, and have the runtime loader check that the major number is equal + * to what it was at application link time, while the minor number has to + * be greater or equal to what it was at application link time. With this + * scheme, the version number is usually part of the file name, like this: + * + * libcrypto.so.0.9 + * + * Some unixen also make a softlink with the major version number only: + * + * libcrypto.so.0 + * + * On Tru64 and IRIX 6.x it works a little bit differently. There, the + * shared library version is stored in the file, and is actually a series + * of versions, separated by colons. The rightmost version present in the + * library when linking an application is stored in the application to be + * matched at run time. When the application is run, a check is done to + * see if the library version stored in the application matches any of the + * versions in the version string of the library itself. + * This version string can be constructed in any way, depending on what + * kind of matching is desired. However, to implement the same scheme as + * the one used in the other unixen, all compatible versions, from lowest + * to highest, should be part of the string. Consecutive builds would + * give the following versions strings: + * + * 3.0 + * 3.0:3.1 + * 3.0:3.1:3.2 + * 4.0 + * 4.0:4.1 + * + * Notice how version 4 is completely incompatible with version, and + * therefore give the breach you can see. + * + * There may be other schemes as well that I haven't yet discovered. + * + * So, here's the way it works here: first of all, the library version + * number doesn't need at all to match the overall OpenSSL version. + * However, it's nice and more understandable if it actually does. + * The current library version is stored in the macro SHLIB_VERSION_NUMBER, + * which is just a piece of text in the format "M.m.e" (Major, minor, edit). + * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways, + * we need to keep a history of version numbers, which is done in the + * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and + * should only keep the versions that are binary compatible with the current. + */ +# define SHLIB_VERSION_HISTORY "" +# define SHLIB_VERSION_NUMBER "1.1" + + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_OPENSSLV_H */ diff --git a/thirdparty/user_include/openssl/ossl_typ.h b/thirdparty/user_include/openssl/ossl_typ.h new file mode 100755 index 0000000000000000000000000000000000000000..7993ca28f3da5ce5d53f198806bd032a740479be --- /dev/null +++ b/thirdparty/user_include/openssl/ossl_typ.h @@ -0,0 +1,196 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OPENSSL_TYPES_H +# define HEADER_OPENSSL_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +# ifdef NO_ASN1_TYPEDEFS +# define ASN1_INTEGER ASN1_STRING +# define ASN1_ENUMERATED ASN1_STRING +# define ASN1_BIT_STRING ASN1_STRING +# define ASN1_OCTET_STRING ASN1_STRING +# define ASN1_PRINTABLESTRING ASN1_STRING +# define ASN1_T61STRING ASN1_STRING +# define ASN1_IA5STRING ASN1_STRING +# define ASN1_UTCTIME ASN1_STRING +# define ASN1_GENERALIZEDTIME ASN1_STRING +# define ASN1_TIME ASN1_STRING +# define ASN1_GENERALSTRING ASN1_STRING +# define ASN1_UNIVERSALSTRING ASN1_STRING +# define ASN1_BMPSTRING ASN1_STRING +# define ASN1_VISIBLESTRING ASN1_STRING +# define ASN1_UTF8STRING ASN1_STRING +# define ASN1_BOOLEAN int +# define ASN1_NULL int +# else +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_STRING; +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +# endif + +typedef struct asn1_object_st ASN1_OBJECT; + +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_pctx_st ASN1_PCTX; +typedef struct asn1_sctx_st ASN1_SCTX; + +# ifdef _WIN32 +# undef X509_NAME +# undef X509_EXTENSIONS +# undef PKCS7_ISSUER_AND_SERIAL +# undef PKCS7_SIGNER_INFO +# undef OCSP_REQUEST +# undef OCSP_RESPONSE +# endif + +# ifdef BIGNUM +# undef BIGNUM +# endif +struct dane_st; +typedef struct bio_st BIO; +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_blinding_st BN_BLINDING; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct buf_mem_st BUF_MEM; + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct evp_pkey_st EVP_PKEY; + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX; + +typedef struct hmac_ctx_st HMAC_CTX; + +typedef struct dh_st DH; +typedef struct dh_method DH_METHOD; + +typedef struct dsa_st DSA; +typedef struct dsa_method DSA_METHOD; + +typedef struct rsa_st RSA; +typedef struct rsa_meth_st RSA_METHOD; + +typedef struct ec_key_st EC_KEY; +typedef struct ec_key_method_st EC_KEY_METHOD; + +typedef struct rand_meth_st RAND_METHOD; +typedef struct rand_drbg_st RAND_DRBG; + +typedef struct ssl_dane_st SSL_DANE; +typedef struct x509_st X509; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct X509_name_st X509_NAME; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; + +typedef struct x509_object_st X509_OBJECT; +typedef struct x509_lookup_st X509_LOOKUP; +typedef struct x509_lookup_method_st X509_LOOKUP_METHOD; +typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; + +typedef struct x509_sig_info_st X509_SIG_INFO; + +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; + +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct conf_st CONF; +typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; + +typedef struct ui_st UI; +typedef struct ui_method_st UI_METHOD; + +typedef struct engine_st ENGINE; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + +typedef struct comp_ctx_st COMP_CTX; +typedef struct comp_method_st COMP_METHOD; + +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; + +typedef struct ocsp_req_ctx_st OCSP_REQ_CTX; +typedef struct ocsp_response_st OCSP_RESPONSE; +typedef struct ocsp_responder_id_st OCSP_RESPID; + +typedef struct sct_st SCT; +typedef struct sct_ctx_st SCT_CTX; +typedef struct ctlog_st CTLOG; +typedef struct ctlog_store_st CTLOG_STORE; +typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX; + +typedef struct ossl_store_info_st OSSL_STORE_INFO; +typedef struct ossl_store_search_st OSSL_STORE_SEARCH; + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) +typedef intmax_t ossl_intmax_t; +typedef uintmax_t ossl_uintmax_t; +#else +/* + * Not long long, because the C-library can only be expected to provide + * strtoll(), strtoull() at the same time as intmax_t and strtoimax(), + * strtoumax(). Since we use these for parsing arguments, we need the + * conversion functions, not just the sizes. + */ +typedef long ossl_intmax_t; +typedef unsigned long ossl_uintmax_t; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/thirdparty/user_include/openssl/pem.h b/thirdparty/user_include/openssl/pem.h new file mode 100755 index 0000000000000000000000000000000000000000..2ef5b5d04c6e30d742b3ac541d6891fc96a99c11 --- /dev/null +++ b/thirdparty/user_include/openssl/pem.h @@ -0,0 +1,378 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEM_H +# define HEADER_PEM_H + +# include +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PEM_BUFSIZE 1024 + +# define PEM_STRING_X509_OLD "X509 CERTIFICATE" +# define PEM_STRING_X509 "CERTIFICATE" +# define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +# define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +# define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +# define PEM_STRING_X509_CRL "X509 CRL" +# define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +# define PEM_STRING_PUBLIC "PUBLIC KEY" +# define PEM_STRING_RSA "RSA PRIVATE KEY" +# define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +# define PEM_STRING_DSA "DSA PRIVATE KEY" +# define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +# define PEM_STRING_PKCS7 "PKCS7" +# define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +# define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +# define PEM_STRING_PKCS8INF "PRIVATE KEY" +# define PEM_STRING_DHPARAMS "DH PARAMETERS" +# define PEM_STRING_DHXPARAMS "X9.42 DH PARAMETERS" +# define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +# define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +# define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +# define PEM_STRING_ECPARAMETERS "EC PARAMETERS" +# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +# define PEM_STRING_PARAMETERS "PARAMETERS" +# define PEM_STRING_CMS "CMS" + +# define PEM_TYPE_ENCRYPTED 10 +# define PEM_TYPE_MIC_ONLY 20 +# define PEM_TYPE_MIC_CLEAR 30 +# define PEM_TYPE_CLEAR 40 + +/* + * These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: IMPLEMENT_PEM_rw(...) or + * IMPLEMENT_PEM_rw_cb(...) + */ + +# ifdef OPENSSL_NO_STDIO + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/ +# else + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, const type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# endif + +# define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, const type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +/* These are the same except they are for the declarations */ + +# if defined(OPENSSL_NO_STDIO) + +# define DECLARE_PEM_read_fp(name, type) /**/ +# define DECLARE_PEM_write_fp(name, type) /**/ +# define DECLARE_PEM_write_fp_const(name, type) /**/ +# define DECLARE_PEM_write_cb_fp(name, type) /**/ +# else + +# define DECLARE_PEM_read_fp(name, type) \ + type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x); + +# define DECLARE_PEM_write_fp_const(name, type) \ + int PEM_write_##name(FILE *fp, const type *x); + +# define DECLARE_PEM_write_cb_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# endif + +# define DECLARE_PEM_read_bio(name, type) \ + type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x); + +# define DECLARE_PEM_write_bio_const(name, type) \ + int PEM_write_bio_##name(BIO *bp, const type *x); + +# define DECLARE_PEM_write_cb_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) +# define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) +# define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) +# define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) +# define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) +# define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) +# define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) +typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata); + +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len, + pem_password_cb *callback, void *u); + +int PEM_read_bio(BIO *bp, char **name, char **header, + unsigned char **data, long *len); +# define PEM_FLAG_SECURE 0x1 +# define PEM_FLAG_EAY_COMPATIBLE 0x2 +# define PEM_FLAG_ONLY_B64 0x4 +int PEM_read_bio_ex(BIO *bp, char **name, char **header, + unsigned char **data, long *len, unsigned int flags); +int PEM_bytes_read_bio_secmem(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u); +int PEM_write_bio(BIO *bp, const char *name, const char *hdr, + const unsigned char *data, long len); +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u); +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cd, void *u); + +#ifndef OPENSSL_NO_STDIO +int PEM_read(FILE *fp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write(FILE *fp, const char *name, const char *hdr, + const unsigned char *data, long len); +void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u); +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); +#endif + +int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); +int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt); +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey); + +/* The default pem_password_cb that's used internally */ +int PEM_def_callback(char *buf, int num, int rwflag, void *userdata); +void PEM_proc_type(char *buf, int type); +void PEM_dek_info(char *buf, const char *type, int len, char *str); + +# include + +DECLARE_PEM_rw(X509, X509) +DECLARE_PEM_rw(X509_AUX, X509) +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) +DECLARE_PEM_rw(X509_CRL, X509_CRL) +DECLARE_PEM_rw(PKCS7, PKCS7) +DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) +DECLARE_PEM_rw(PKCS8, X509_SIG) +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) +# ifndef OPENSSL_NO_RSA +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) +# endif +# ifndef OPENSSL_NO_DSA +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) +DECLARE_PEM_rw(DSA_PUBKEY, DSA) +DECLARE_PEM_rw_const(DSAparams, DSA) +# endif +# ifndef OPENSSL_NO_EC +DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP) +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) +# endif +# ifndef OPENSSL_NO_DH +DECLARE_PEM_rw_const(DHparams, DH) +DECLARE_PEM_write_const(DHxparams, DH) +# endif +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + char *, int, pem_password_cb *, void *); +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +# ifndef OPENSSL_NO_STDIO +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cd, + void *u); +# endif +EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x); +int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x); + +# ifndef OPENSSL_NO_DSA +EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PrivateKey_bio(BIO *in); +EVP_PKEY *b2i_PublicKey_bio(BIO *in); +int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk); +int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk); +# ifndef OPENSSL_NO_RC4 +EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u); +int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, + pem_password_cb *cb, void *u); +# endif +# endif + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/pem2.h b/thirdparty/user_include/openssl/pem2.h new file mode 100755 index 0000000000000000000000000000000000000000..038fe790ace2300c1127d34dde439685338a0a48 --- /dev/null +++ b/thirdparty/user_include/openssl/pem2.h @@ -0,0 +1,13 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEM2_H +# define HEADER_PEM2_H +# include +#endif diff --git a/thirdparty/user_include/openssl/pemerr.h b/thirdparty/user_include/openssl/pemerr.h new file mode 100755 index 0000000000000000000000000000000000000000..cd61b823d31750a2af5eb150e0fa61a73084e5e8 --- /dev/null +++ b/thirdparty/user_include/openssl/pemerr.h @@ -0,0 +1,99 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PEMERR_H +# define HEADER_PEMERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PEM_strings(void); + +/* + * PEM function codes. + */ +# define PEM_F_B2I_DSS 127 +# define PEM_F_B2I_PVK_BIO 128 +# define PEM_F_B2I_RSA 129 +# define PEM_F_CHECK_BITLEN_DSA 130 +# define PEM_F_CHECK_BITLEN_RSA 131 +# define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120 +# define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121 +# define PEM_F_DO_B2I 132 +# define PEM_F_DO_B2I_BIO 133 +# define PEM_F_DO_BLOB_HEADER 134 +# define PEM_F_DO_I2B 146 +# define PEM_F_DO_PK8PKEY 126 +# define PEM_F_DO_PK8PKEY_FP 125 +# define PEM_F_DO_PVK_BODY 135 +# define PEM_F_DO_PVK_HEADER 136 +# define PEM_F_GET_HEADER_AND_DATA 143 +# define PEM_F_GET_NAME 144 +# define PEM_F_I2B_PVK 137 +# define PEM_F_I2B_PVK_BIO 138 +# define PEM_F_LOAD_IV 101 +# define PEM_F_PEM_ASN1_READ 102 +# define PEM_F_PEM_ASN1_READ_BIO 103 +# define PEM_F_PEM_ASN1_WRITE 104 +# define PEM_F_PEM_ASN1_WRITE_BIO 105 +# define PEM_F_PEM_DEF_CALLBACK 100 +# define PEM_F_PEM_DO_HEADER 106 +# define PEM_F_PEM_GET_EVP_CIPHER_INFO 107 +# define PEM_F_PEM_READ 108 +# define PEM_F_PEM_READ_BIO 109 +# define PEM_F_PEM_READ_BIO_DHPARAMS 141 +# define PEM_F_PEM_READ_BIO_EX 145 +# define PEM_F_PEM_READ_BIO_PARAMETERS 140 +# define PEM_F_PEM_READ_BIO_PRIVATEKEY 123 +# define PEM_F_PEM_READ_DHPARAMS 142 +# define PEM_F_PEM_READ_PRIVATEKEY 124 +# define PEM_F_PEM_SIGNFINAL 112 +# define PEM_F_PEM_WRITE 113 +# define PEM_F_PEM_WRITE_BIO 114 +# define PEM_F_PEM_WRITE_PRIVATEKEY 139 +# define PEM_F_PEM_X509_INFO_READ 115 +# define PEM_F_PEM_X509_INFO_READ_BIO 116 +# define PEM_F_PEM_X509_INFO_WRITE_BIO 117 + +/* + * PEM reason codes. + */ +# define PEM_R_BAD_BASE64_DECODE 100 +# define PEM_R_BAD_DECRYPT 101 +# define PEM_R_BAD_END_LINE 102 +# define PEM_R_BAD_IV_CHARS 103 +# define PEM_R_BAD_MAGIC_NUMBER 116 +# define PEM_R_BAD_PASSWORD_READ 104 +# define PEM_R_BAD_VERSION_NUMBER 117 +# define PEM_R_BIO_WRITE_FAILURE 118 +# define PEM_R_CIPHER_IS_NULL 127 +# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115 +# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119 +# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120 +# define PEM_R_HEADER_TOO_LONG 128 +# define PEM_R_INCONSISTENT_HEADER 121 +# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122 +# define PEM_R_KEYBLOB_TOO_SHORT 123 +# define PEM_R_MISSING_DEK_IV 129 +# define PEM_R_NOT_DEK_INFO 105 +# define PEM_R_NOT_ENCRYPTED 106 +# define PEM_R_NOT_PROC_TYPE 107 +# define PEM_R_NO_START_LINE 108 +# define PEM_R_PROBLEMS_GETTING_PASSWORD 109 +# define PEM_R_PVK_DATA_TOO_SHORT 124 +# define PEM_R_PVK_TOO_SHORT 125 +# define PEM_R_READ_KEY 111 +# define PEM_R_SHORT_HEADER 112 +# define PEM_R_UNEXPECTED_DEK_IV 130 +# define PEM_R_UNSUPPORTED_CIPHER 113 +# define PEM_R_UNSUPPORTED_ENCRYPTION 114 +# define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126 + +#endif diff --git a/thirdparty/user_include/openssl/pkcs12.h b/thirdparty/user_include/openssl/pkcs12.h new file mode 100755 index 0000000000000000000000000000000000000000..3f43dad6d961e0758d242686ebdeca4691a89eb8 --- /dev/null +++ b/thirdparty/user_include/openssl/pkcs12.h @@ -0,0 +1,223 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS12_H +# define HEADER_PKCS12_H + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PKCS12_KEY_ID 1 +# define PKCS12_IV_ID 2 +# define PKCS12_MAC_ID 3 + +/* Default iteration count */ +# ifndef PKCS12_DEFAULT_ITER +# define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER +# endif + +# define PKCS12_MAC_KEY_LENGTH 20 + +# define PKCS12_SALT_LEN 8 + +/* It's not clear if these are actually needed... */ +# define PKCS12_key_gen PKCS12_key_gen_utf8 +# define PKCS12_add_friendlyname PKCS12_add_friendlyname_utf8 + +/* MS key usage constants */ + +# define KEY_EX 0x10 +# define KEY_SIG 0x80 + +typedef struct PKCS12_MAC_DATA_st PKCS12_MAC_DATA; + +typedef struct PKCS12_st PKCS12; + +typedef struct PKCS12_SAFEBAG_st PKCS12_SAFEBAG; + +DEFINE_STACK_OF(PKCS12_SAFEBAG) + +typedef struct pkcs12_bag_st PKCS12_BAGS; + +# define PKCS12_ERROR 0 +# define PKCS12_OK 1 + +/* Compatibility macros */ + +#if OPENSSL_API_COMPAT < 0x10100000L + +# define M_PKCS12_bag_type PKCS12_bag_type +# define M_PKCS12_cert_bag_type PKCS12_cert_bag_type +# define M_PKCS12_crl_bag_type PKCS12_cert_bag_type + +# define PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert +# define PKCS12_certbag2scrl PKCS12_SAFEBAG_get1_crl +# define PKCS12_bag_type PKCS12_SAFEBAG_get_nid +# define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid +# define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert +# define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl +# define PKCS12_MAKE_KEYBAG PKCS12_SAFEBAG_create0_p8inf +# define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt + +#endif + +DEPRECATEDIN_1_1_0(ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid)) + +ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid); +int PKCS12_mac_present(const PKCS12 *p12); +void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, + const X509_ALGOR **pmacalg, + const ASN1_OCTET_STRING **psalt, + const ASN1_INTEGER **piter, + const PKCS12 *p12); + +const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag, + int attr_nid); +const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag); + +X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag); +const STACK_OF(PKCS12_SAFEBAG) * +PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag); +const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag); +const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag); + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid, + const char *pass, + int passlen, + unsigned char *salt, + int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf); + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, + int nid1, int nid2); +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass, + int passlen); +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag, + const char *pass, int passlen); +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, unsigned char *salt, + int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8); +X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen, + PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe); +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7); +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK_OF(PKCS12_SAFEBAG) *bags); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, + int passlen); + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes); +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12); + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen); +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_utf8(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, + const unsigned char *name, int namelen); +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); +ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, + int attr_nid); +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); +const STACK_OF(X509_ATTRIBUTE) * +PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag); +unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor, + const char *pass, int passlen, + const unsigned char *in, int inlen, + unsigned char **data, int *datalen, + int en_de); +void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, + const ASN1_OCTET_STRING *oct, int zbuf); +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, + const char *pass, int passlen, + void *obj, int zbuf); +PKCS12 *PKCS12_init(int mode); +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md_type, int en_de); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, const EVP_MD *md_type); +unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2asc(const unsigned char *uni, int unilen); +unsigned char *OPENSSL_utf82uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen); + +DECLARE_ASN1_FUNCTIONS(PKCS12) +DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA) +DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG) +DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS) + +DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS) +DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES) + +void PKCS12_PBE_add(void); +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca); +PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype); + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert); +PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, + EVP_PKEY *key, int key_usage, int iter, + int key_nid, const char *pass); +int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, + int safe_nid, int iter, const char *pass); +PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid); + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); +# ifndef OPENSSL_NO_STDIO +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); +# endif +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); +# ifndef OPENSSL_NO_STDIO +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); +# endif +int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/pkcs12err.h b/thirdparty/user_include/openssl/pkcs12err.h new file mode 100755 index 0000000000000000000000000000000000000000..c7184ffe744d04f1464a95da0c1764097098aab9 --- /dev/null +++ b/thirdparty/user_include/openssl/pkcs12err.h @@ -0,0 +1,77 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS12ERR_H +# define HEADER_PKCS12ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PKCS12_strings(void); + +/* + * PKCS12 function codes. + */ +# define PKCS12_F_OPENSSL_ASC2UNI 121 +# define PKCS12_F_OPENSSL_UNI2ASC 124 +# define PKCS12_F_OPENSSL_UNI2UTF8 127 +# define PKCS12_F_OPENSSL_UTF82UNI 129 +# define PKCS12_F_PKCS12_CREATE 105 +# define PKCS12_F_PKCS12_GEN_MAC 107 +# define PKCS12_F_PKCS12_INIT 109 +# define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106 +# define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108 +# define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117 +# define PKCS12_F_PKCS12_KEY_GEN_ASC 110 +# define PKCS12_F_PKCS12_KEY_GEN_UNI 111 +# define PKCS12_F_PKCS12_KEY_GEN_UTF8 116 +# define PKCS12_F_PKCS12_NEWPASS 128 +# define PKCS12_F_PKCS12_PACK_P7DATA 114 +# define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 +# define PKCS12_F_PKCS12_PARSE 118 +# define PKCS12_F_PKCS12_PBE_CRYPT 119 +# define PKCS12_F_PKCS12_PBE_KEYIVGEN 120 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_P8INF 112 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE0_PKCS8 113 +# define PKCS12_F_PKCS12_SAFEBAG_CREATE_PKCS8_ENCRYPT 133 +# define PKCS12_F_PKCS12_SETUP_MAC 122 +# define PKCS12_F_PKCS12_SET_MAC 123 +# define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130 +# define PKCS12_F_PKCS12_UNPACK_P7DATA 131 +# define PKCS12_F_PKCS12_VERIFY_MAC 126 +# define PKCS12_F_PKCS8_ENCRYPT 125 +# define PKCS12_F_PKCS8_SET0_PBE 132 + +/* + * PKCS12 reason codes. + */ +# define PKCS12_R_CANT_PACK_STRUCTURE 100 +# define PKCS12_R_CONTENT_TYPE_NOT_DATA 121 +# define PKCS12_R_DECODE_ERROR 101 +# define PKCS12_R_ENCODE_ERROR 102 +# define PKCS12_R_ENCRYPT_ERROR 103 +# define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120 +# define PKCS12_R_INVALID_NULL_ARGUMENT 104 +# define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 +# define PKCS12_R_IV_GEN_ERROR 106 +# define PKCS12_R_KEY_GEN_ERROR 107 +# define PKCS12_R_MAC_ABSENT 108 +# define PKCS12_R_MAC_GENERATION_ERROR 109 +# define PKCS12_R_MAC_SETUP_ERROR 110 +# define PKCS12_R_MAC_STRING_SET_ERROR 111 +# define PKCS12_R_MAC_VERIFY_FAILURE 113 +# define PKCS12_R_PARSE_ERROR 114 +# define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115 +# define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116 +# define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117 +# define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118 +# define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119 + +#endif diff --git a/thirdparty/user_include/openssl/pkcs7.h b/thirdparty/user_include/openssl/pkcs7.h new file mode 100755 index 0000000000000000000000000000000000000000..9b66e002d2851c0fb3265862828113eb5dc09a14 --- /dev/null +++ b/thirdparty/user_include/openssl/pkcs7.h @@ -0,0 +1,319 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS7_H +# define HEADER_PKCS7_H + +# include +# include +# include + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- +Encryption_ID DES-CBC +Digest_ID MD5 +Digest_Encryption_ID rsaEncryption +Key_Encryption_ID rsaEncryption +*/ + +typedef struct pkcs7_issuer_and_serial_st { + X509_NAME *issuer; + ASN1_INTEGER *serial; +} PKCS7_ISSUER_AND_SERIAL; + +typedef struct pkcs7_signer_info_st { + ASN1_INTEGER *version; /* version 1 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */ + /* The private key to sign with */ + EVP_PKEY *pkey; +} PKCS7_SIGNER_INFO; + +DEFINE_STACK_OF(PKCS7_SIGNER_INFO) + +typedef struct pkcs7_recip_info_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; /* get the pub-key from this */ +} PKCS7_RECIP_INFO; + +DEFINE_STACK_OF(PKCS7_RECIP_INFO) + +typedef struct pkcs7_signed_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + struct pkcs7_st *contents; +} PKCS7_SIGNED; +/* + * The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about + * merging the two + */ + +typedef struct pkcs7_enc_content_st { + ASN1_OBJECT *content_type; + X509_ALGOR *algorithm; + ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; +} PKCS7_ENC_CONTENT; + +typedef struct pkcs7_enveloped_st { + ASN1_INTEGER *version; /* version 0 */ + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENVELOPE; + +typedef struct pkcs7_signedandenveloped_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; +} PKCS7_SIGN_ENVELOPE; + +typedef struct pkcs7_digest_st { + ASN1_INTEGER *version; /* version 0 */ + X509_ALGOR *md; /* md used */ + struct pkcs7_st *contents; + ASN1_OCTET_STRING *digest; +} PKCS7_DIGEST; + +typedef struct pkcs7_encrypted_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENCRYPT; + +typedef struct pkcs7_st { + /* + * The following is non NULL if it contains ASN1 encoding of this + * structure + */ + unsigned char *asn1; + long length; +# define PKCS7_S_HEADER 0 +# define PKCS7_S_BODY 1 +# define PKCS7_S_TAIL 2 + int state; /* used during processing */ + int detached; + ASN1_OBJECT *type; + /* content as defined by the type */ + /* + * all encryption/message digests are applied to the 'contents', leaving + * out the 'type' field. + */ + union { + char *ptr; + /* NID_pkcs7_data */ + ASN1_OCTET_STRING *data; + /* NID_pkcs7_signed */ + PKCS7_SIGNED *sign; + /* NID_pkcs7_enveloped */ + PKCS7_ENVELOPE *enveloped; + /* NID_pkcs7_signedAndEnveloped */ + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + /* NID_pkcs7_digest */ + PKCS7_DIGEST *digest; + /* NID_pkcs7_encrypted */ + PKCS7_ENCRYPT *encrypted; + /* Anything else */ + ASN1_TYPE *other; + } d; +} PKCS7; + +DEFINE_STACK_OF(PKCS7) + +# define PKCS7_OP_SET_DETACHED_SIGNATURE 1 +# define PKCS7_OP_GET_DETACHED_SIGNATURE 2 + +# define PKCS7_get_signed_attributes(si) ((si)->auth_attr) +# define PKCS7_get_attributes(si) ((si)->unauth_attr) + +# define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed) +# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) +# define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped) +# define PKCS7_type_is_signedAndEnveloped(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) +# define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) +# define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) + +# define PKCS7_set_detached(p,v) \ + PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) +# define PKCS7_get_detached(p) \ + PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) + +# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) + +/* S/MIME related flags */ + +# define PKCS7_TEXT 0x1 +# define PKCS7_NOCERTS 0x2 +# define PKCS7_NOSIGS 0x4 +# define PKCS7_NOCHAIN 0x8 +# define PKCS7_NOINTERN 0x10 +# define PKCS7_NOVERIFY 0x20 +# define PKCS7_DETACHED 0x40 +# define PKCS7_BINARY 0x80 +# define PKCS7_NOATTR 0x100 +# define PKCS7_NOSMIMECAP 0x200 +# define PKCS7_NOOLDMIMETYPE 0x400 +# define PKCS7_CRLFEOL 0x800 +# define PKCS7_STREAM 0x1000 +# define PKCS7_NOCRL 0x2000 +# define PKCS7_PARTIAL 0x4000 +# define PKCS7_REUSE_DIGEST 0x8000 +# define PKCS7_NO_DUAL_CONTENT 0x10000 + +/* Flags: for compatibility with older code */ + +# define SMIME_TEXT PKCS7_TEXT +# define SMIME_NOCERTS PKCS7_NOCERTS +# define SMIME_NOSIGS PKCS7_NOSIGS +# define SMIME_NOCHAIN PKCS7_NOCHAIN +# define SMIME_NOINTERN PKCS7_NOINTERN +# define SMIME_NOVERIFY PKCS7_NOVERIFY +# define SMIME_DETACHED PKCS7_DETACHED +# define SMIME_BINARY PKCS7_BINARY +# define SMIME_NOATTR PKCS7_NOATTR + +/* CRLF ASCII canonicalisation */ +# define SMIME_ASCIICRLF 0x80000 + +DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) + +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, + const EVP_MD *type, unsigned char *md, + unsigned int *len); +# ifndef OPENSSL_NO_STDIO +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7); +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7); +# endif +PKCS7 *PKCS7_dup(PKCS7 *p7); +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7); +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7); +int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); +int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); + +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) +DECLARE_ASN1_FUNCTIONS(PKCS7) + +DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) +DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) + +DECLARE_ASN1_NDEF_FUNCTION(PKCS7) +DECLARE_ASN1_PRINT_FUNCTION(PKCS7) + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); + +int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst); +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si); +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); +int PKCS7_content_new(PKCS7 *p7, int nid); +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, + BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509); + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey, const EVP_MD *dgst); +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, + X509_ALGOR **pdig, X509_ALGOR **psig); +void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc); +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); +int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7); + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type, + void *data); +int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value); +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid); +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid); +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags); + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, + X509 *signcert, EVP_PKEY *pkey, + const EVP_MD *md, int flags); + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags); +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags); +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, + int flags); +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags); +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, + int flags); + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, + STACK_OF(X509_ALGOR) *cap); +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg); + +int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid); +int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t); +int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, + const unsigned char *md, int mdlen); + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags); +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont); + +BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/pkcs7err.h b/thirdparty/user_include/openssl/pkcs7err.h new file mode 100755 index 0000000000000000000000000000000000000000..0ba418d7805d07c20138ed5a1213ee08539835d7 --- /dev/null +++ b/thirdparty/user_include/openssl/pkcs7err.h @@ -0,0 +1,99 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_PKCS7ERR_H +# define HEADER_PKCS7ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_PKCS7_strings(void); + +/* + * PKCS7 function codes. + */ +# define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 136 +# define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 135 +# define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118 +# define PKCS7_F_PKCS7_ADD_CERTIFICATE 100 +# define PKCS7_F_PKCS7_ADD_CRL 101 +# define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 +# define PKCS7_F_PKCS7_ADD_SIGNATURE 131 +# define PKCS7_F_PKCS7_ADD_SIGNER 103 +# define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125 +# define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 138 +# define PKCS7_F_PKCS7_CTRL 104 +# define PKCS7_F_PKCS7_DATADECODE 112 +# define PKCS7_F_PKCS7_DATAFINAL 128 +# define PKCS7_F_PKCS7_DATAINIT 105 +# define PKCS7_F_PKCS7_DATAVERIFY 107 +# define PKCS7_F_PKCS7_DECRYPT 114 +# define PKCS7_F_PKCS7_DECRYPT_RINFO 133 +# define PKCS7_F_PKCS7_ENCODE_RINFO 132 +# define PKCS7_F_PKCS7_ENCRYPT 115 +# define PKCS7_F_PKCS7_FINAL 134 +# define PKCS7_F_PKCS7_FIND_DIGEST 127 +# define PKCS7_F_PKCS7_GET0_SIGNERS 124 +# define PKCS7_F_PKCS7_RECIP_INFO_SET 130 +# define PKCS7_F_PKCS7_SET_CIPHER 108 +# define PKCS7_F_PKCS7_SET_CONTENT 109 +# define PKCS7_F_PKCS7_SET_DIGEST 126 +# define PKCS7_F_PKCS7_SET_TYPE 110 +# define PKCS7_F_PKCS7_SIGN 116 +# define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 +# define PKCS7_F_PKCS7_SIGNER_INFO_SET 129 +# define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139 +# define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137 +# define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 +# define PKCS7_F_PKCS7_VERIFY 117 + +/* + * PKCS7 reason codes. + */ +# define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117 +# define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144 +# define PKCS7_R_CIPHER_NOT_INITIALIZED 116 +# define PKCS7_R_CONTENT_AND_DATA_PRESENT 118 +# define PKCS7_R_CTRL_ERROR 152 +# define PKCS7_R_DECRYPT_ERROR 119 +# define PKCS7_R_DIGEST_FAILURE 101 +# define PKCS7_R_ENCRYPTION_CTRL_FAILURE 149 +# define PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 150 +# define PKCS7_R_ERROR_ADDING_RECIPIENT 120 +# define PKCS7_R_ERROR_SETTING_CIPHER 121 +# define PKCS7_R_INVALID_NULL_POINTER 143 +# define PKCS7_R_INVALID_SIGNED_DATA_TYPE 155 +# define PKCS7_R_NO_CONTENT 122 +# define PKCS7_R_NO_DEFAULT_DIGEST 151 +# define PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND 154 +# define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +# define PKCS7_R_NO_SIGNATURES_ON_DATA 123 +# define PKCS7_R_NO_SIGNERS 142 +# define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 +# define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +# define PKCS7_R_PKCS7_ADD_SIGNER_ERROR 153 +# define PKCS7_R_PKCS7_DATASIGN 145 +# define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 +# define PKCS7_R_SIGNATURE_FAILURE 105 +# define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128 +# define PKCS7_R_SIGNING_CTRL_FAILURE 147 +# define PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 148 +# define PKCS7_R_SMIME_TEXT_ERROR 129 +# define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 +# define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107 +# define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108 +# define PKCS7_R_UNKNOWN_DIGEST_TYPE 109 +# define PKCS7_R_UNKNOWN_OPERATION 110 +# define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111 +# define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112 +# define PKCS7_R_WRONG_CONTENT_TYPE 113 +# define PKCS7_R_WRONG_PKCS7_TYPE 114 + +#endif diff --git a/thirdparty/user_include/openssl/rand.h b/thirdparty/user_include/openssl/rand.h new file mode 100755 index 0000000000000000000000000000000000000000..38a2a2718f8b8d6d2cf1687bddd5e8c19a3c3aaf --- /dev/null +++ b/thirdparty/user_include/openssl/rand.h @@ -0,0 +1,77 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RAND_H +# define HEADER_RAND_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rand_meth_st { + int (*seed) (const void *buf, int num); + int (*bytes) (unsigned char *buf, int num); + void (*cleanup) (void); + int (*add) (const void *buf, int num, double randomness); + int (*pseudorand) (unsigned char *buf, int num); + int (*status) (void); +}; + +int RAND_set_rand_method(const RAND_METHOD *meth); +const RAND_METHOD *RAND_get_rand_method(void); +# ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine); +# endif + +RAND_METHOD *RAND_OpenSSL(void); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define RAND_cleanup() while(0) continue +# endif +int RAND_bytes(unsigned char *buf, int num); +int RAND_priv_bytes(unsigned char *buf, int num); +DEPRECATEDIN_1_1_0(int RAND_pseudo_bytes(unsigned char *buf, int num)) + +void RAND_seed(const void *buf, int num); +void RAND_keep_random_devices_open(int keep); + +# if defined(__ANDROID__) && defined(__NDK_FPABI__) +__NDK_FPABI__ /* __attribute__((pcs("aapcs"))) on ARM */ +# endif +void RAND_add(const void *buf, int num, double randomness); +int RAND_load_file(const char *file, long max_bytes); +int RAND_write_file(const char *file); +const char *RAND_file_name(char *file, size_t num); +int RAND_status(void); + +# ifndef OPENSSL_NO_EGD +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes); +int RAND_egd(const char *path); +int RAND_egd_bytes(const char *path, int bytes); +# endif + +int RAND_poll(void); + +# if defined(_WIN32) && (defined(BASETYPES) || defined(_WINDEF_H)) +/* application has to include in order to use these */ +DEPRECATEDIN_1_1_0(void RAND_screen(void)) +DEPRECATEDIN_1_1_0(int RAND_event(UINT, WPARAM, LPARAM)) +# endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/rand_drbg.h b/thirdparty/user_include/openssl/rand_drbg.h new file mode 100755 index 0000000000000000000000000000000000000000..45b731b73c261e319dcdb508a4af4671ebbd8a72 --- /dev/null +++ b/thirdparty/user_include/openssl/rand_drbg.h @@ -0,0 +1,130 @@ +/* + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_DRBG_RAND_H +# define HEADER_DRBG_RAND_H + +# include +# include +# include + +/* + * RAND_DRBG flags + * + * Note: if new flags are added, the constant `rand_drbg_used_flags` + * in drbg_lib.c needs to be updated accordingly. + */ + +/* In CTR mode, disable derivation function ctr_df */ +# define RAND_DRBG_FLAG_CTR_NO_DF 0x1 + + +# if OPENSSL_API_COMPAT < 0x10200000L +/* This #define was replaced by an internal constant and should not be used. */ +# define RAND_DRBG_USED_FLAGS (RAND_DRBG_FLAG_CTR_NO_DF) +# endif + +/* + * Default security strength (in the sense of [NIST SP 800-90Ar1]) + * + * NIST SP 800-90Ar1 supports the strength of the DRBG being smaller than that + * of the cipher by collecting less entropy. The current DRBG implementation + * does not take RAND_DRBG_STRENGTH into account and sets the strength of the + * DRBG to that of the cipher. + * + * RAND_DRBG_STRENGTH is currently only used for the legacy RAND + * implementation. + * + * Currently supported ciphers are: NID_aes_128_ctr, NID_aes_192_ctr and + * NID_aes_256_ctr + */ +# define RAND_DRBG_STRENGTH 256 +/* Default drbg type */ +# define RAND_DRBG_TYPE NID_aes_256_ctr +/* Default drbg flags */ +# define RAND_DRBG_FLAGS 0 + + +# ifdef __cplusplus +extern "C" { +# endif + +/* + * Object lifetime functions. + */ +RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent); +RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent); +int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags); +int RAND_DRBG_set_defaults(int type, unsigned int flags); +int RAND_DRBG_instantiate(RAND_DRBG *drbg, + const unsigned char *pers, size_t perslen); +int RAND_DRBG_uninstantiate(RAND_DRBG *drbg); +void RAND_DRBG_free(RAND_DRBG *drbg); + +/* + * Object "use" functions. + */ +int RAND_DRBG_reseed(RAND_DRBG *drbg, + const unsigned char *adin, size_t adinlen, + int prediction_resistance); +int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, + int prediction_resistance, + const unsigned char *adin, size_t adinlen); +int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen); + +int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval); +int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval); + +int RAND_DRBG_set_reseed_defaults( + unsigned int master_reseed_interval, + unsigned int slave_reseed_interval, + time_t master_reseed_time_interval, + time_t slave_reseed_time_interval + ); + +RAND_DRBG *RAND_DRBG_get0_master(void); +RAND_DRBG *RAND_DRBG_get0_public(void); +RAND_DRBG *RAND_DRBG_get0_private(void); + +/* + * EXDATA + */ +# define RAND_DRBG_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DRBG, l, p, newf, dupf, freef) +int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg); +void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx); + +/* + * Callback function typedefs + */ +typedef size_t (*RAND_DRBG_get_entropy_fn)(RAND_DRBG *drbg, + unsigned char **pout, + int entropy, size_t min_len, + size_t max_len, + int prediction_resistance); +typedef void (*RAND_DRBG_cleanup_entropy_fn)(RAND_DRBG *ctx, + unsigned char *out, size_t outlen); +typedef size_t (*RAND_DRBG_get_nonce_fn)(RAND_DRBG *drbg, unsigned char **pout, + int entropy, size_t min_len, + size_t max_len); +typedef void (*RAND_DRBG_cleanup_nonce_fn)(RAND_DRBG *drbg, + unsigned char *out, size_t outlen); + +int RAND_DRBG_set_callbacks(RAND_DRBG *drbg, + RAND_DRBG_get_entropy_fn get_entropy, + RAND_DRBG_cleanup_entropy_fn cleanup_entropy, + RAND_DRBG_get_nonce_fn get_nonce, + RAND_DRBG_cleanup_nonce_fn cleanup_nonce); + + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/thirdparty/user_include/openssl/randerr.h b/thirdparty/user_include/openssl/randerr.h new file mode 100755 index 0000000000000000000000000000000000000000..599a2a18d41ff0a121258dac26468e50ab5576fe --- /dev/null +++ b/thirdparty/user_include/openssl/randerr.h @@ -0,0 +1,89 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RANDERR_H +# define HEADER_RANDERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_RAND_strings(void); + +/* + * RAND function codes. + */ +# define RAND_F_DRBG_BYTES 101 +# define RAND_F_DRBG_GET_ENTROPY 105 +# define RAND_F_DRBG_SETUP 117 +# define RAND_F_GET_ENTROPY 106 +# define RAND_F_RAND_BYTES 100 +# define RAND_F_RAND_DRBG_ENABLE_LOCKING 119 +# define RAND_F_RAND_DRBG_GENERATE 107 +# define RAND_F_RAND_DRBG_GET_ENTROPY 120 +# define RAND_F_RAND_DRBG_GET_NONCE 123 +# define RAND_F_RAND_DRBG_INSTANTIATE 108 +# define RAND_F_RAND_DRBG_NEW 109 +# define RAND_F_RAND_DRBG_RESEED 110 +# define RAND_F_RAND_DRBG_RESTART 102 +# define RAND_F_RAND_DRBG_SET 104 +# define RAND_F_RAND_DRBG_SET_DEFAULTS 121 +# define RAND_F_RAND_DRBG_UNINSTANTIATE 118 +# define RAND_F_RAND_LOAD_FILE 111 +# define RAND_F_RAND_POOL_ACQUIRE_ENTROPY 122 +# define RAND_F_RAND_POOL_ADD 103 +# define RAND_F_RAND_POOL_ADD_BEGIN 113 +# define RAND_F_RAND_POOL_ADD_END 114 +# define RAND_F_RAND_POOL_ATTACH 124 +# define RAND_F_RAND_POOL_BYTES_NEEDED 115 +# define RAND_F_RAND_POOL_NEW 116 +# define RAND_F_RAND_WRITE_FILE 112 + +/* + * RAND reason codes. + */ +# define RAND_R_ADDITIONAL_INPUT_TOO_LONG 102 +# define RAND_R_ALREADY_INSTANTIATED 103 +# define RAND_R_ARGUMENT_OUT_OF_RANGE 105 +# define RAND_R_CANNOT_OPEN_FILE 121 +# define RAND_R_DRBG_ALREADY_INITIALIZED 129 +# define RAND_R_DRBG_NOT_INITIALISED 104 +# define RAND_R_ENTROPY_INPUT_TOO_LONG 106 +# define RAND_R_ENTROPY_OUT_OF_RANGE 124 +# define RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED 127 +# define RAND_R_ERROR_INITIALISING_DRBG 107 +# define RAND_R_ERROR_INSTANTIATING_DRBG 108 +# define RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT 109 +# define RAND_R_ERROR_RETRIEVING_ENTROPY 110 +# define RAND_R_ERROR_RETRIEVING_NONCE 111 +# define RAND_R_FAILED_TO_CREATE_LOCK 126 +# define RAND_R_FUNC_NOT_IMPLEMENTED 101 +# define RAND_R_FWRITE_ERROR 123 +# define RAND_R_GENERATE_ERROR 112 +# define RAND_R_INTERNAL_ERROR 113 +# define RAND_R_IN_ERROR_STATE 114 +# define RAND_R_NOT_A_REGULAR_FILE 122 +# define RAND_R_NOT_INSTANTIATED 115 +# define RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED 128 +# define RAND_R_PARENT_LOCKING_NOT_ENABLED 130 +# define RAND_R_PARENT_STRENGTH_TOO_WEAK 131 +# define RAND_R_PERSONALISATION_STRING_TOO_LONG 116 +# define RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED 133 +# define RAND_R_PRNG_NOT_SEEDED 100 +# define RAND_R_RANDOM_POOL_OVERFLOW 125 +# define RAND_R_RANDOM_POOL_UNDERFLOW 134 +# define RAND_R_REQUEST_TOO_LARGE_FOR_DRBG 117 +# define RAND_R_RESEED_ERROR 118 +# define RAND_R_SELFTEST_FAILURE 119 +# define RAND_R_TOO_LITTLE_NONCE_REQUESTED 135 +# define RAND_R_TOO_MUCH_NONCE_REQUESTED 136 +# define RAND_R_UNSUPPORTED_DRBG_FLAGS 132 +# define RAND_R_UNSUPPORTED_DRBG_TYPE 120 + +#endif diff --git a/thirdparty/user_include/openssl/rc2.h b/thirdparty/user_include/openssl/rc2.h new file mode 100755 index 0000000000000000000000000000000000000000..585f9e4c3806760b2e782f7867a99dcd90ad7032 --- /dev/null +++ b/thirdparty/user_include/openssl/rc2.h @@ -0,0 +1,51 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC2_H +# define HEADER_RC2_H + +# include + +# ifndef OPENSSL_NO_RC2 +# ifdef __cplusplus +extern "C" { +# endif + +typedef unsigned int RC2_INT; + +# define RC2_ENCRYPT 1 +# define RC2_DECRYPT 0 + +# define RC2_BLOCK 8 +# define RC2_KEY_LENGTH 16 + +typedef struct rc2_key_st { + RC2_INT data[64]; +} RC2_KEY; + +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits); +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC2_KEY *key, int enc); +void RC2_encrypt(unsigned long *data, RC2_KEY *key); +void RC2_decrypt(unsigned long *data, RC2_KEY *key); +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/rc4.h b/thirdparty/user_include/openssl/rc4.h new file mode 100755 index 0000000000000000000000000000000000000000..86803b37fbe0d0e4dc0bee49c96ae28e164c4867 --- /dev/null +++ b/thirdparty/user_include/openssl/rc4.h @@ -0,0 +1,36 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC4_H +# define HEADER_RC4_H + +# include + +# ifndef OPENSSL_NO_RC4 +# include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc4_key_st { + RC4_INT x, y; + RC4_INT data[256]; +} RC4_KEY; + +const char *RC4_options(void); +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/rc5.h b/thirdparty/user_include/openssl/rc5.h new file mode 100755 index 0000000000000000000000000000000000000000..793f88e4e81432b9c8a649e5bcba17300d017c64 --- /dev/null +++ b/thirdparty/user_include/openssl/rc5.h @@ -0,0 +1,63 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RC5_H +# define HEADER_RC5_H + +# include + +# ifndef OPENSSL_NO_RC5 +# ifdef __cplusplus +extern "C" { +# endif + +# define RC5_ENCRYPT 1 +# define RC5_DECRYPT 0 + +# define RC5_32_INT unsigned int + +# define RC5_32_BLOCK 8 +# define RC5_32_KEY_LENGTH 16/* This is a default, max is 255 */ + +/* + * This are the only values supported. Tweak the code if you want more The + * most supported modes will be RC5-32/12/16 RC5-32/16/8 + */ +# define RC5_8_ROUNDS 8 +# define RC5_12_ROUNDS 12 +# define RC5_16_ROUNDS 16 + +typedef struct rc5_key_st { + /* Number of rounds */ + int rounds; + RC5_32_INT data[2 * (RC5_16_ROUNDS + 1)]; +} RC5_32_KEY; + +void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data, + int rounds); +void RC5_32_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC5_32_KEY *key, int enc); +void RC5_32_encrypt(unsigned long *data, RC5_32_KEY *key); +void RC5_32_decrypt(unsigned long *data, RC5_32_KEY *key); +void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *ks, unsigned char *iv, + int enc); +void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC5_32_KEY *schedule, + unsigned char *ivec, int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/ripemd.h b/thirdparty/user_include/openssl/ripemd.h new file mode 100755 index 0000000000000000000000000000000000000000..c42026aa42fe428b004e0959f64dca54b2d731e5 --- /dev/null +++ b/thirdparty/user_include/openssl/ripemd.h @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RIPEMD_H +# define HEADER_RIPEMD_H + +# include + +#ifndef OPENSSL_NO_RMD160 +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define RIPEMD160_LONG unsigned int + +# define RIPEMD160_CBLOCK 64 +# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +# define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct RIPEMD160state_st { + RIPEMD160_LONG A, B, C, D, E; + RIPEMD160_LONG Nl, Nh; + RIPEMD160_LONG data[RIPEMD160_LBLOCK]; + unsigned int num; +} RIPEMD160_CTX; + +int RIPEMD160_Init(RIPEMD160_CTX *c); +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len); +int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); +unsigned char *RIPEMD160(const unsigned char *d, size_t n, unsigned char *md); +void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b); + +# ifdef __cplusplus +} +# endif +# endif + + +#endif diff --git a/thirdparty/user_include/openssl/rsa.h b/thirdparty/user_include/openssl/rsa.h new file mode 100755 index 0000000000000000000000000000000000000000..cdce1264eb5ccd9ecd1973e442e7639bb2cdb2d3 --- /dev/null +++ b/thirdparty/user_include/openssl/rsa.h @@ -0,0 +1,512 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RSA_H +# define HEADER_RSA_H + +# include + +# ifndef OPENSSL_NO_RSA +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* The types RSA and RSA_METHOD are defined in ossl_typ.h */ + +# ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +# endif + +# define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024 + +# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS +# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072 +# endif +# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS + +/* exponent limit enforced for "large" modulus only */ +# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 +# endif + +# define RSA_3 0x3L +# define RSA_F4 0x10001L + +/* based on RFC 8017 appendix A.1.2 */ +# define RSA_ASN1_VERSION_DEFAULT 0 +# define RSA_ASN1_VERSION_MULTI 1 + +# define RSA_DEFAULT_PRIME_NUM 2 + +# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private + * match */ + +# define RSA_FLAG_CACHE_PUBLIC 0x0002 +# define RSA_FLAG_CACHE_PRIVATE 0x0004 +# define RSA_FLAG_BLINDING 0x0008 +# define RSA_FLAG_THREAD_SAFE 0x0010 +/* + * This flag means the private key operations will be handled by rsa_mod_exp + * and that they do not depend on the private key components being present: + * for example a key stored in external hardware. Without this flag + * bn_mod_exp gets called when private key components are absent. + */ +# define RSA_FLAG_EXT_PKEY 0x0020 + +/* + * new with 0.9.6j and 0.9.7b; the built-in + * RSA implementation now uses blinding by + * default (ignoring RSA_FLAG_BLINDING), + * but other engines might not need it + */ +# define RSA_FLAG_NO_BLINDING 0x0080 +# if OPENSSL_API_COMPAT < 0x10100000L +/* + * Does nothing. Previously this switched off constant time behaviour. + */ +# define RSA_FLAG_NO_CONSTTIME 0x0000 +# endif +# if OPENSSL_API_COMPAT < 0x00908000L +/* deprecated name for the flag*/ +/* + * new with 0.9.7h; the built-in RSA + * implementation now uses constant time + * modular exponentiation for secret exponents + * by default. This flag causes the + * faster variable sliding window method to + * be used for all exponents. + */ +# define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME +# endif + +# define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL) + +# define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad) + +# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) +/* Salt length matches digest */ +# define RSA_PSS_SALTLEN_DIGEST -1 +/* Verify only: auto detect salt length */ +# define RSA_PSS_SALTLEN_AUTO -2 +/* Set salt length to maximum possible */ +# define RSA_PSS_SALTLEN_MAX -3 +/* Old compatible max salt length for sign only */ +# define RSA_PSS_SALTLEN_MAX_SIGN -2 + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen) + +# define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL) + +# define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp) + +# define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL) + +# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)(pmd)) + +# define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)(l)) + +# define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)(l)) + +# define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \ + EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, \ + 0, (void *)(md)) + +# define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2) + +# define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5) + +# define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 8) + +# define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 10) + +# define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) + +# define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13) + +# define RSA_PKCS1_PADDING 1 +# define RSA_SSLV23_PADDING 2 +# define RSA_NO_PADDING 3 +# define RSA_PKCS1_OAEP_PADDING 4 +# define RSA_X931_PADDING 5 +/* EVP_PKEY_ only */ +# define RSA_PKCS1_PSS_PADDING 6 + +# define RSA_PKCS1_PADDING_SIZE 11 + +# define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg) +# define RSA_get_app_data(s) RSA_get_ex_data(s,0) + +RSA *RSA_new(void); +RSA *RSA_new_method(ENGINE *engine); +int RSA_bits(const RSA *rsa); +int RSA_size(const RSA *rsa); +int RSA_security_bits(const RSA *rsa); + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[], + BIGNUM *coeffs[], int pnum); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +int RSA_get_multi_prime_extra_count(const RSA *r); +int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[]); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[], + const BIGNUM *coeffs[]); +const BIGNUM *RSA_get0_n(const RSA *d); +const BIGNUM *RSA_get0_e(const RSA *d); +const BIGNUM *RSA_get0_d(const RSA *d); +const BIGNUM *RSA_get0_p(const RSA *d); +const BIGNUM *RSA_get0_q(const RSA *d); +const BIGNUM *RSA_get0_dmp1(const RSA *r); +const BIGNUM *RSA_get0_dmq1(const RSA *r); +const BIGNUM *RSA_get0_iqmp(const RSA *r); +void RSA_clear_flags(RSA *r, int flags); +int RSA_test_flags(const RSA *r, int flags); +void RSA_set_flags(RSA *r, int flags); +int RSA_get_version(RSA *r); +ENGINE *RSA_get0_engine(const RSA *r); + +/* Deprecated version */ +DEPRECATEDIN_0_9_8(RSA *RSA_generate_key(int bits, unsigned long e, void + (*callback) (int, int, void *), + void *cb_arg)) + +/* New version */ +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +/* Multi-prime version */ +int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, + BIGNUM *e, BN_GENCB *cb); + +int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, + BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2, + const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2, + const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb); +int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, + BN_GENCB *cb); + +int RSA_check_key(const RSA *); +int RSA_check_key_ex(const RSA *, BN_GENCB *cb); + /* next 4 return -1 on error */ +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +void RSA_free(RSA *r); +/* "up" the RSA object's reference count */ +int RSA_up_ref(RSA *r); + +int RSA_flags(const RSA *r); + +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_null_method(void); +const RSA_METHOD *RSA_get_method(const RSA *rsa); +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + +/* these are the actual RSA functions */ +const RSA_METHOD *RSA_PKCS1_OpenSSL(void); + +int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2); + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) + +typedef struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; + /* Decoded hash algorithm from maskGenAlgorithm */ + X509_ALGOR *maskHash; +} RSA_PSS_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS) + +typedef struct rsa_oaep_params_st { + X509_ALGOR *hashFunc; + X509_ALGOR *maskGenFunc; + X509_ALGOR *pSourceFunc; + /* Decoded hash algorithm from maskGenFunc */ + X509_ALGOR *maskHash; +} RSA_OAEP_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS) + +# ifndef OPENSSL_NO_STDIO +int RSA_print_fp(FILE *fp, const RSA *r, int offset); +# endif + +int RSA_print(BIO *bp, const RSA *r, int offset); + +/* + * The following 2 functions sign and verify a X509_SIG ASN1 object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify(int type, const unsigned char *m, unsigned int m_length, + const unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +/* + * The following 2 function sign and verify a ASN1_OCTET_STRING object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + RSA *rsa); +int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigbuf, + unsigned int siglen, RSA *rsa); + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); +void RSA_blinding_off(RSA *rsa); +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx); + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed, + long seedlen, const EVP_MD *dgst); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, + const unsigned char *p, int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len, + const unsigned char *p, int pl); +int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen, + const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num, const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md); +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_X931(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_X931_hash_id(int nid); + +int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const unsigned char *EM, + int sLen); +int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, const EVP_MD *Hash, + int sLen); + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int sLen); + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen); + +#define RSA_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, l, p, newf, dupf, freef) +int RSA_set_ex_data(RSA *r, int idx, void *arg); +void *RSA_get_ex_data(const RSA *r, int idx); + +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); + +/* + * If this flag is set the RSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define RSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define RSA_FLAG_NON_FIPS_ALLOW 0x0400 +/* + * Application has decided PRNG is good enough to generate a key: don't + * check. + */ +# define RSA_FLAG_CHECKED 0x0800 + +RSA_METHOD *RSA_meth_new(const char *name, int flags); +void RSA_meth_free(RSA_METHOD *meth); +RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth); +const char *RSA_meth_get0_name(const RSA_METHOD *meth); +int RSA_meth_set1_name(RSA_METHOD *meth, const char *name); +int RSA_meth_get_flags(const RSA_METHOD *meth); +int RSA_meth_set_flags(RSA_METHOD *meth, int flags); +void *RSA_meth_get0_app_data(const RSA_METHOD *meth); +int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data); +int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_pub_enc(RSA_METHOD *rsa, + int (*pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_pub_dec(RSA_METHOD *rsa, + int (*pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_priv_enc(RSA_METHOD *rsa, + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) + (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_meth_set_priv_dec(RSA_METHOD *rsa, + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)); +int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx); +int RSA_meth_set_mod_exp(RSA_METHOD *rsa, + int (*mod_exp) (BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx)); +int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth)) + (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int RSA_meth_set_bn_mod_exp(RSA_METHOD *rsa, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx)); +int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa); +int RSA_meth_set_init(RSA_METHOD *rsa, int (*init) (RSA *rsa)); +int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa); +int RSA_meth_set_finish(RSA_METHOD *rsa, int (*finish) (RSA *rsa)); +int (*RSA_meth_get_sign(const RSA_METHOD *meth)) + (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa); +int RSA_meth_set_sign(RSA_METHOD *rsa, + int (*sign) (int type, const unsigned char *m, + unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa)); +int (*RSA_meth_get_verify(const RSA_METHOD *meth)) + (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); +int RSA_meth_set_verify(RSA_METHOD *rsa, + int (*verify) (int dtype, const unsigned char *m, + unsigned int m_length, + const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa)); +int (*RSA_meth_get_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +int RSA_meth_set_keygen(RSA_METHOD *rsa, + int (*keygen) (RSA *rsa, int bits, BIGNUM *e, + BN_GENCB *cb)); +int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth)) + (RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb); +int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth, + int (*keygen) (RSA *rsa, int bits, + int primes, BIGNUM *e, + BN_GENCB *cb)); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/rsaerr.h b/thirdparty/user_include/openssl/rsaerr.h new file mode 100755 index 0000000000000000000000000000000000000000..d5bc01c10218488d7b38267faac0c1668359bc96 --- /dev/null +++ b/thirdparty/user_include/openssl/rsaerr.h @@ -0,0 +1,162 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_RSAERR_H +# define HEADER_RSAERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_RSA_strings(void); + +/* + * RSA function codes. + */ +# define RSA_F_CHECK_PADDING_MD 140 +# define RSA_F_ENCODE_PKCS1 146 +# define RSA_F_INT_RSA_VERIFY 145 +# define RSA_F_OLD_RSA_PRIV_DECODE 147 +# define RSA_F_PKEY_PSS_INIT 165 +# define RSA_F_PKEY_RSA_CTRL 143 +# define RSA_F_PKEY_RSA_CTRL_STR 144 +# define RSA_F_PKEY_RSA_SIGN 142 +# define RSA_F_PKEY_RSA_VERIFY 149 +# define RSA_F_PKEY_RSA_VERIFYRECOVER 141 +# define RSA_F_RSA_ALGOR_TO_MD 156 +# define RSA_F_RSA_BUILTIN_KEYGEN 129 +# define RSA_F_RSA_CHECK_KEY 123 +# define RSA_F_RSA_CHECK_KEY_EX 160 +# define RSA_F_RSA_CMS_DECRYPT 159 +# define RSA_F_RSA_CMS_VERIFY 158 +# define RSA_F_RSA_ITEM_VERIFY 148 +# define RSA_F_RSA_METH_DUP 161 +# define RSA_F_RSA_METH_NEW 162 +# define RSA_F_RSA_METH_SET1_NAME 163 +# define RSA_F_RSA_MGF1_TO_MD 157 +# define RSA_F_RSA_MULTIP_INFO_NEW 166 +# define RSA_F_RSA_NEW_METHOD 106 +# define RSA_F_RSA_NULL 124 +# define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132 +# define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133 +# define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134 +# define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135 +# define RSA_F_RSA_OSSL_PRIVATE_DECRYPT 101 +# define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 102 +# define RSA_F_RSA_OSSL_PUBLIC_DECRYPT 103 +# define RSA_F_RSA_OSSL_PUBLIC_ENCRYPT 104 +# define RSA_F_RSA_PADDING_ADD_NONE 107 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 154 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 152 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109 +# define RSA_F_RSA_PADDING_ADD_SSLV23 110 +# define RSA_F_RSA_PADDING_ADD_X931 127 +# define RSA_F_RSA_PADDING_CHECK_NONE 111 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1 153 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113 +# define RSA_F_RSA_PADDING_CHECK_SSLV23 114 +# define RSA_F_RSA_PADDING_CHECK_X931 128 +# define RSA_F_RSA_PARAM_DECODE 164 +# define RSA_F_RSA_PRINT 115 +# define RSA_F_RSA_PRINT_FP 116 +# define RSA_F_RSA_PRIV_DECODE 150 +# define RSA_F_RSA_PRIV_ENCODE 138 +# define RSA_F_RSA_PSS_GET_PARAM 151 +# define RSA_F_RSA_PSS_TO_CTX 155 +# define RSA_F_RSA_PUB_DECODE 139 +# define RSA_F_RSA_SETUP_BLINDING 136 +# define RSA_F_RSA_SIGN 117 +# define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 +# define RSA_F_RSA_VERIFY 119 +# define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 +# define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 126 +# define RSA_F_SETUP_TBUF 167 + +/* + * RSA reason codes. + */ +# define RSA_R_ALGORITHM_MISMATCH 100 +# define RSA_R_BAD_E_VALUE 101 +# define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +# define RSA_R_BAD_PAD_BYTE_COUNT 103 +# define RSA_R_BAD_SIGNATURE 104 +# define RSA_R_BLOCK_TYPE_IS_NOT_01 106 +# define RSA_R_BLOCK_TYPE_IS_NOT_02 107 +# define RSA_R_DATA_GREATER_THAN_MOD_LEN 108 +# define RSA_R_DATA_TOO_LARGE 109 +# define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110 +# define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132 +# define RSA_R_DATA_TOO_SMALL 111 +# define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122 +# define RSA_R_DIGEST_DOES_NOT_MATCH 158 +# define RSA_R_DIGEST_NOT_ALLOWED 145 +# define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112 +# define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124 +# define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125 +# define RSA_R_D_E_NOT_CONGRUENT_TO_1 123 +# define RSA_R_FIRST_OCTET_INVALID 133 +# define RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 144 +# define RSA_R_INVALID_DIGEST 157 +# define RSA_R_INVALID_DIGEST_LENGTH 143 +# define RSA_R_INVALID_HEADER 137 +# define RSA_R_INVALID_LABEL 160 +# define RSA_R_INVALID_MESSAGE_LENGTH 131 +# define RSA_R_INVALID_MGF1_MD 156 +# define RSA_R_INVALID_MULTI_PRIME_KEY 167 +# define RSA_R_INVALID_OAEP_PARAMETERS 161 +# define RSA_R_INVALID_PADDING 138 +# define RSA_R_INVALID_PADDING_MODE 141 +# define RSA_R_INVALID_PSS_PARAMETERS 149 +# define RSA_R_INVALID_PSS_SALTLEN 146 +# define RSA_R_INVALID_SALT_LENGTH 150 +# define RSA_R_INVALID_TRAILER 139 +# define RSA_R_INVALID_X931_DIGEST 142 +# define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 +# define RSA_R_KEY_PRIME_NUM_INVALID 165 +# define RSA_R_KEY_SIZE_TOO_SMALL 120 +# define RSA_R_LAST_OCTET_INVALID 134 +# define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152 +# define RSA_R_MODULUS_TOO_LARGE 105 +# define RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R 168 +# define RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D 169 +# define RSA_R_MP_R_NOT_PRIME 170 +# define RSA_R_NO_PUBLIC_EXPONENT 140 +# define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 +# define RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES 172 +# define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 +# define RSA_R_OAEP_DECODING_ERROR 121 +# define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 +# define RSA_R_PADDING_CHECK_FAILED 114 +# define RSA_R_PKCS_DECODING_ERROR 159 +# define RSA_R_PSS_SALTLEN_TOO_SMALL 164 +# define RSA_R_P_NOT_PRIME 128 +# define RSA_R_Q_NOT_PRIME 129 +# define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130 +# define RSA_R_SLEN_CHECK_FAILED 136 +# define RSA_R_SLEN_RECOVERY_FAILED 135 +# define RSA_R_SSLV3_ROLLBACK_ATTACK 115 +# define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116 +# define RSA_R_UNKNOWN_ALGORITHM_TYPE 117 +# define RSA_R_UNKNOWN_DIGEST 166 +# define RSA_R_UNKNOWN_MASK_DIGEST 151 +# define RSA_R_UNKNOWN_PADDING_TYPE 118 +# define RSA_R_UNSUPPORTED_ENCRYPTION_TYPE 162 +# define RSA_R_UNSUPPORTED_LABEL_SOURCE 163 +# define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153 +# define RSA_R_UNSUPPORTED_MASK_PARAMETER 154 +# define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 +# define RSA_R_VALUE_MISSING 147 +# define RSA_R_WRONG_SIGNATURE_LENGTH 119 + +#endif diff --git a/thirdparty/user_include/openssl/safestack.h b/thirdparty/user_include/openssl/safestack.h new file mode 100755 index 0000000000000000000000000000000000000000..38b5578978cbaf601bd70713ef091712f54458a5 --- /dev/null +++ b/thirdparty/user_include/openssl/safestack.h @@ -0,0 +1,207 @@ +/* + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SAFESTACK_H +# define HEADER_SAFESTACK_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define STACK_OF(type) struct stack_st_##type + +# define SKM_DEFINE_STACK_OF(t1, t2, t3) \ + STACK_OF(t1); \ + typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \ + typedef void (*sk_##t1##_freefunc)(t3 *a); \ + typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \ + static ossl_unused ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \ + { \ + return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \ + { \ + return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \ + { \ + return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_free((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_zero((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \ + { \ + return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \ + (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \ + { \ + return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \ + { \ + return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \ + { \ + OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \ + { \ + return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \ + } \ + static ossl_unused ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \ + { \ + return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \ + { \ + return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \ + } \ + static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \ + { \ + OPENSSL_sk_sort((OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \ + { \ + return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \ + } \ + static ossl_unused ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \ + sk_##t1##_copyfunc copyfunc, \ + sk_##t1##_freefunc freefunc) \ + { \ + return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \ + (OPENSSL_sk_copyfunc)copyfunc, \ + (OPENSSL_sk_freefunc)freefunc); \ + } \ + static ossl_unused ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \ + { \ + return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \ + } + +# define DEFINE_SPECIAL_STACK_OF(t1, t2) SKM_DEFINE_STACK_OF(t1, t2, t2) +# define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t) +# define DEFINE_SPECIAL_STACK_OF_CONST(t1, t2) \ + SKM_DEFINE_STACK_OF(t1, const t2, t2) +# define DEFINE_STACK_OF_CONST(t) SKM_DEFINE_STACK_OF(t, const t, t) + +/*- + * Strings are special: normally an lhash entry will point to a single + * (somewhat) mutable object. In the case of strings: + * + * a) Instead of a single char, there is an array of chars, NUL-terminated. + * b) The string may have be immutable. + * + * So, they need their own declarations. Especially important for + * type-checking tools, such as Deputy. + * + * In practice, however, it appears to be hard to have a const + * string. For now, I'm settling for dealing with the fact it is a + * string at all. + */ +typedef char *OPENSSL_STRING; +typedef const char *OPENSSL_CSTRING; + +/*- + * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but + * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned + * above, instead of a single char each entry is a NUL-terminated array of + * chars. So, we have to implement STRING specially for STACK_OF. This is + * dealt with in the autogenerated macros below. + */ +DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char) +DEFINE_SPECIAL_STACK_OF_CONST(OPENSSL_CSTRING, char) + +/* + * Similarly, we sometimes use a block of characters, NOT nul-terminated. + * These should also be distinguished from "normal" stacks. + */ +typedef void *OPENSSL_BLOCK; +DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) + +/* + * If called without higher optimization (min. -xO3) the Oracle Developer + * Studio compiler generates code for the defined (static inline) functions + * above. + * This would later lead to the linker complaining about missing symbols when + * this header file is included but the resulting object is not linked against + * the Crypto library (openssl#6912). + */ +# ifdef __SUNPRO_C +# pragma weak OPENSSL_sk_num +# pragma weak OPENSSL_sk_value +# pragma weak OPENSSL_sk_new +# pragma weak OPENSSL_sk_new_null +# pragma weak OPENSSL_sk_new_reserve +# pragma weak OPENSSL_sk_reserve +# pragma weak OPENSSL_sk_free +# pragma weak OPENSSL_sk_zero +# pragma weak OPENSSL_sk_delete +# pragma weak OPENSSL_sk_delete_ptr +# pragma weak OPENSSL_sk_push +# pragma weak OPENSSL_sk_unshift +# pragma weak OPENSSL_sk_pop +# pragma weak OPENSSL_sk_shift +# pragma weak OPENSSL_sk_pop_free +# pragma weak OPENSSL_sk_insert +# pragma weak OPENSSL_sk_set +# pragma weak OPENSSL_sk_find +# pragma weak OPENSSL_sk_find_ex +# pragma weak OPENSSL_sk_sort +# pragma weak OPENSSL_sk_is_sorted +# pragma weak OPENSSL_sk_dup +# pragma weak OPENSSL_sk_deep_copy +# pragma weak OPENSSL_sk_set_cmp_func +# endif /* __SUNPRO_C */ + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/seed.h b/thirdparty/user_include/openssl/seed.h new file mode 100755 index 0000000000000000000000000000000000000000..de10b08572018aceada115b3f21249222acfedf1 --- /dev/null +++ b/thirdparty/user_include/openssl/seed.h @@ -0,0 +1,96 @@ +/* + * Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Copyright (c) 2007 KISA(Korea Information Security Agency). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of author nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef HEADER_SEED_H +# define HEADER_SEED_H + +# include + +# ifndef OPENSSL_NO_SEED +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* look whether we need 'long' to get 32 bits */ +# ifdef AES_LONG +# ifndef SEED_LONG +# define SEED_LONG 1 +# endif +# endif + +# include + +# define SEED_BLOCK_SIZE 16 +# define SEED_KEY_LENGTH 16 + +typedef struct seed_key_st { +# ifdef SEED_LONG + unsigned long data[32]; +# else + unsigned int data[32]; +# endif +} SEED_KEY_SCHEDULE; + +void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH], + SEED_KEY_SCHEDULE *ks); + +void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); +void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); + +void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out, + const SEED_KEY_SCHEDULE *ks, int enc); +void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, + const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int enc); +void SEED_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num, + int enc); +void SEED_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/sha.h b/thirdparty/user_include/openssl/sha.h new file mode 100755 index 0000000000000000000000000000000000000000..6a1eb0de8bd7197b27e8c27f48c0db7687230803 --- /dev/null +++ b/thirdparty/user_include/openssl/sha.h @@ -0,0 +1,119 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SHA_H +# define HEADER_SHA_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ +# define SHA_LONG unsigned int + +# define SHA_LBLOCK 16 +# define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ +# define SHA_LAST_BLOCK (SHA_CBLOCK-8) +# define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st { + SHA_LONG h0, h1, h2, h3, h4; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num; +} SHA_CTX; + +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, size_t len); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); + +# define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ + +typedef struct SHA256state_st { + SHA_LONG h[8]; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num, md_len; +} SHA256_CTX; + +int SHA224_Init(SHA256_CTX *c); +int SHA224_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA224_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md); +int SHA256_Init(SHA256_CTX *c); +int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA256_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md); +void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); + +# define SHA224_DIGEST_LENGTH 28 +# define SHA256_DIGEST_LENGTH 32 +# define SHA384_DIGEST_LENGTH 48 +# define SHA512_DIGEST_LENGTH 64 + +/* + * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 + * being exactly 64-bit wide. See Implementation Notes in sha512.c + * for further details. + */ +/* + * SHA-512 treats input data as a + * contiguous array of 64 bit + * wide big-endian values. + */ +# define SHA512_CBLOCK (SHA_LBLOCK*8) +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +# define SHA_LONG64 unsigned __int64 +# define U64(C) C##UI64 +# elif defined(__arch64__) +# define SHA_LONG64 unsigned long +# define U64(C) C##UL +# else +# define SHA_LONG64 unsigned long long +# define U64(C) C##ULL +# endif + +typedef struct SHA512state_st { + SHA_LONG64 h[8]; + SHA_LONG64 Nl, Nh; + union { + SHA_LONG64 d[SHA_LBLOCK]; + unsigned char p[SHA512_CBLOCK]; + } u; + unsigned int num, md_len; +} SHA512_CTX; + +int SHA384_Init(SHA512_CTX *c); +int SHA384_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA384_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md); +int SHA512_Init(SHA512_CTX *c); +int SHA512_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA512_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md); +void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/srp.h b/thirdparty/user_include/openssl/srp.h new file mode 100755 index 0000000000000000000000000000000000000000..aaf13558e3cb4caeedc272914c6684d76cd25bf0 --- /dev/null +++ b/thirdparty/user_include/openssl/srp.h @@ -0,0 +1,135 @@ +/* + * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2004, EdelKey Project. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + * + * Originally written by Christophe Renou and Peter Sylvester, + * for the EdelKey project. + */ + +#ifndef HEADER_SRP_H +# define HEADER_SRP_H + +#include + +#ifndef OPENSSL_NO_SRP +# include +# include +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +typedef struct SRP_gN_cache_st { + char *b64_bn; + BIGNUM *bn; +} SRP_gN_cache; + + +DEFINE_STACK_OF(SRP_gN_cache) + +typedef struct SRP_user_pwd_st { + /* Owned by us. */ + char *id; + BIGNUM *s; + BIGNUM *v; + /* Not owned by us. */ + const BIGNUM *g; + const BIGNUM *N; + /* Owned by us. */ + char *info; +} SRP_user_pwd; + +void SRP_user_pwd_free(SRP_user_pwd *user_pwd); + +DEFINE_STACK_OF(SRP_user_pwd) + +typedef struct SRP_VBASE_st { + STACK_OF(SRP_user_pwd) *users_pwd; + STACK_OF(SRP_gN_cache) *gN_cache; +/* to simulate a user */ + char *seed_key; + const BIGNUM *default_g; + const BIGNUM *default_N; +} SRP_VBASE; + +/* + * Internal structure storing N and g pair + */ +typedef struct SRP_gN_st { + char *id; + const BIGNUM *g; + const BIGNUM *N; +} SRP_gN; + +DEFINE_STACK_OF(SRP_gN) + +SRP_VBASE *SRP_VBASE_new(char *seed_key); +void SRP_VBASE_free(SRP_VBASE *vb); +int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file); + +/* This method ignores the configured seed and fails for an unknown user. */ +DEPRECATEDIN_1_1_0(SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)) +/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username); + +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g); +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, const BIGNUM *N, + const BIGNUM *g); + +# define SRP_NO_ERROR 0 +# define SRP_ERR_VBASE_INCOMPLETE_FILE 1 +# define SRP_ERR_VBASE_BN_LIB 2 +# define SRP_ERR_OPEN_FILE 3 +# define SRP_ERR_MEMORY 4 + +# define DB_srptype 0 +# define DB_srpverifier 1 +# define DB_srpsalt 2 +# define DB_srpid 3 +# define DB_srpgN 4 +# define DB_srpinfo 5 +# undef DB_NUMBER +# define DB_NUMBER 6 + +# define DB_SRP_INDEX 'I' +# define DB_SRP_VALID 'V' +# define DB_SRP_REVOKED 'R' +# define DB_SRP_MODIF 'v' + +/* see srp.c */ +char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N); +SRP_gN *SRP_get_default_gN(const char *id); + +/* server side .... */ +BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, + const BIGNUM *b, const BIGNUM *N); +BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, + const BIGNUM *v); +int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N); +BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N); + +/* client side .... */ +BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass); +BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g); +BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, + const BIGNUM *x, const BIGNUM *a, const BIGNUM *u); +int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N); + +# define SRP_MINIMAL_N 1024 + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/srtp.h b/thirdparty/user_include/openssl/srtp.h new file mode 100755 index 0000000000000000000000000000000000000000..0b57c2356c9ea779d5415e82c58542885e240f62 --- /dev/null +++ b/thirdparty/user_include/openssl/srtp.h @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc. + */ + +#ifndef HEADER_D1_SRTP_H +# define HEADER_D1_SRTP_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define SRTP_AES128_CM_SHA1_80 0x0001 +# define SRTP_AES128_CM_SHA1_32 0x0002 +# define SRTP_AES128_F8_SHA1_80 0x0003 +# define SRTP_AES128_F8_SHA1_32 0x0004 +# define SRTP_NULL_SHA1_80 0x0005 +# define SRTP_NULL_SHA1_32 0x0006 + +/* AEAD SRTP protection profiles from RFC 7714 */ +# define SRTP_AEAD_AES_128_GCM 0x0007 +# define SRTP_AEAD_AES_256_GCM 0x0008 + +# ifndef OPENSSL_NO_SRTP + +__owur int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); +__owur int SSL_set_tlsext_use_srtp(SSL *ssl, const char *profiles); + +__owur STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); +__owur SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); + +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/ssl.h b/thirdparty/user_include/openssl/ssl.h new file mode 100755 index 0000000000000000000000000000000000000000..48e1152a27e28828c1e2dc7367eeb3ea99d400b5 --- /dev/null +++ b/thirdparty/user_include/openssl/ssl.h @@ -0,0 +1,2438 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL_H +# define HEADER_SSL_H + +# include +# include +# include +# include +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# endif +# include +# include +# include +# include + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* OpenSSL version number for ASN.1 encoding of the session information */ +/*- + * Version 0 - initial version + * Version 1 - added the optional peer certificate + */ +# define SSL_SESSION_ASN1_VERSION 0x0001 + +# define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +# define SSL_MAX_SID_CTX_LENGTH 32 + +# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) +# define SSL_MAX_KEY_ARG_LENGTH 8 +# define SSL_MAX_MASTER_KEY_LENGTH 48 + +/* The maximum number of encrypt/decrypt pipelines we can support */ +# define SSL_MAX_PIPELINES 32 + +/* text strings for the ciphers */ + +/* These are used to specify which ciphers to use and not to use */ + +# define SSL_TXT_LOW "LOW" +# define SSL_TXT_MEDIUM "MEDIUM" +# define SSL_TXT_HIGH "HIGH" +# define SSL_TXT_FIPS "FIPS" + +# define SSL_TXT_aNULL "aNULL" +# define SSL_TXT_eNULL "eNULL" +# define SSL_TXT_NULL "NULL" + +# define SSL_TXT_kRSA "kRSA" +# define SSL_TXT_kDHr "kDHr"/* this cipher class has been removed */ +# define SSL_TXT_kDHd "kDHd"/* this cipher class has been removed */ +# define SSL_TXT_kDH "kDH"/* this cipher class has been removed */ +# define SSL_TXT_kEDH "kEDH"/* alias for kDHE */ +# define SSL_TXT_kDHE "kDHE" +# define SSL_TXT_kECDHr "kECDHr"/* this cipher class has been removed */ +# define SSL_TXT_kECDHe "kECDHe"/* this cipher class has been removed */ +# define SSL_TXT_kECDH "kECDH"/* this cipher class has been removed */ +# define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */ +# define SSL_TXT_kECDHE "kECDHE" +# define SSL_TXT_kPSK "kPSK" +# define SSL_TXT_kRSAPSK "kRSAPSK" +# define SSL_TXT_kECDHEPSK "kECDHEPSK" +# define SSL_TXT_kDHEPSK "kDHEPSK" +# define SSL_TXT_kGOST "kGOST" +# define SSL_TXT_kSRP "kSRP" + +# define SSL_TXT_aRSA "aRSA" +# define SSL_TXT_aDSS "aDSS" +# define SSL_TXT_aDH "aDH"/* this cipher class has been removed */ +# define SSL_TXT_aECDH "aECDH"/* this cipher class has been removed */ +# define SSL_TXT_aECDSA "aECDSA" +# define SSL_TXT_aPSK "aPSK" +# define SSL_TXT_aGOST94 "aGOST94" +# define SSL_TXT_aGOST01 "aGOST01" +# define SSL_TXT_aGOST12 "aGOST12" +# define SSL_TXT_aGOST "aGOST" +# define SSL_TXT_aSRP "aSRP" + +# define SSL_TXT_DSS "DSS" +# define SSL_TXT_DH "DH" +# define SSL_TXT_DHE "DHE"/* same as "kDHE:-ADH" */ +# define SSL_TXT_EDH "EDH"/* alias for DHE */ +# define SSL_TXT_ADH "ADH" +# define SSL_TXT_RSA "RSA" +# define SSL_TXT_ECDH "ECDH" +# define SSL_TXT_EECDH "EECDH"/* alias for ECDHE" */ +# define SSL_TXT_ECDHE "ECDHE"/* same as "kECDHE:-AECDH" */ +# define SSL_TXT_AECDH "AECDH" +# define SSL_TXT_ECDSA "ECDSA" +# define SSL_TXT_PSK "PSK" +# define SSL_TXT_SRP "SRP" + +# define SSL_TXT_DES "DES" +# define SSL_TXT_3DES "3DES" +# define SSL_TXT_RC4 "RC4" +# define SSL_TXT_RC2 "RC2" +# define SSL_TXT_IDEA "IDEA" +# define SSL_TXT_SEED "SEED" +# define SSL_TXT_AES128 "AES128" +# define SSL_TXT_AES256 "AES256" +# define SSL_TXT_AES "AES" +# define SSL_TXT_AES_GCM "AESGCM" +# define SSL_TXT_AES_CCM "AESCCM" +# define SSL_TXT_AES_CCM_8 "AESCCM8" +# define SSL_TXT_CAMELLIA128 "CAMELLIA128" +# define SSL_TXT_CAMELLIA256 "CAMELLIA256" +# define SSL_TXT_CAMELLIA "CAMELLIA" +# define SSL_TXT_CHACHA20 "CHACHA20" +# define SSL_TXT_GOST "GOST89" +# define SSL_TXT_ARIA "ARIA" +# define SSL_TXT_ARIA_GCM "ARIAGCM" +# define SSL_TXT_ARIA128 "ARIA128" +# define SSL_TXT_ARIA256 "ARIA256" + +# define SSL_TXT_MD5 "MD5" +# define SSL_TXT_SHA1 "SHA1" +# define SSL_TXT_SHA "SHA"/* same as "SHA1" */ +# define SSL_TXT_GOST94 "GOST94" +# define SSL_TXT_GOST89MAC "GOST89MAC" +# define SSL_TXT_GOST12 "GOST12" +# define SSL_TXT_GOST89MAC12 "GOST89MAC12" +# define SSL_TXT_SHA256 "SHA256" +# define SSL_TXT_SHA384 "SHA384" + +# define SSL_TXT_SSLV3 "SSLv3" +# define SSL_TXT_TLSV1 "TLSv1" +# define SSL_TXT_TLSV1_1 "TLSv1.1" +# define SSL_TXT_TLSV1_2 "TLSv1.2" + +# define SSL_TXT_ALL "ALL" + +/*- + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +# define SSL_TXT_CMPALL "COMPLEMENTOFALL" +# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + +/* + * The following cipher list is used by default. It also is substituted when + * an application-defined cipher list string starts with 'DEFAULT'. + * This applies to ciphersuites for TLSv1.2 and below. + */ +# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL" +/* This is the default set of TLSv1.3 ciphersuites */ +# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ + "TLS_CHACHA20_POLY1305_SHA256:" \ + "TLS_AES_128_GCM_SHA256" +# else +# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ + "TLS_AES_128_GCM_SHA256" +#endif +/* + * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always + * starts with a reasonable order, and all we have to do for DEFAULT is + * throwing out anonymous and unencrypted ciphersuites! (The latter are not + * actually enabled by ALL, but "ALL:RSA" would enable some of them.) + */ + +/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ +# define SSL_SENT_SHUTDOWN 1 +# define SSL_RECEIVED_SHUTDOWN 2 + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +# define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +/* + * This is needed to stop compilers complaining about the 'struct ssl_st *' + * function parameters used to prototype callbacks in SSL_CTX. + */ +typedef struct ssl_st *ssl_crock_st; +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_session_st SSL_SESSION; +typedef struct tls_sigalgs_st TLS_SIGALGS; +typedef struct ssl_conf_ctx_st SSL_CONF_CTX; +typedef struct ssl_comp_st SSL_COMP; + +STACK_OF(SSL_CIPHER); +STACK_OF(SSL_COMP); + +/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/ +typedef struct srtp_protection_profile_st { + const char *name; + unsigned long id; +} SRTP_PROTECTION_PROFILE; + +DEFINE_STACK_OF(SRTP_PROTECTION_PROFILE) + +typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, + int len, void *arg); +typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg); + +/* Extension context codes */ +/* This extension is only allowed in TLS */ +#define SSL_EXT_TLS_ONLY 0x0001 +/* This extension is only allowed in DTLS */ +#define SSL_EXT_DTLS_ONLY 0x0002 +/* Some extensions may be allowed in DTLS but we don't implement them for it */ +#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004 +/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */ +#define SSL_EXT_SSL3_ALLOWED 0x0008 +/* Extension is only defined for TLS1.2 and below */ +#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010 +/* Extension is only defined for TLS1.3 and above */ +#define SSL_EXT_TLS1_3_ONLY 0x0020 +/* Ignore this extension during parsing if we are resuming */ +#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040 +#define SSL_EXT_CLIENT_HELLO 0x0080 +/* Really means TLS1.2 or below */ +#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100 +#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200 +#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400 +#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800 +#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000 +#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000 +#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000 + +/* Typedefs for handling custom extensions */ + +typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type, + const unsigned char **out, size_t *outlen, + int *al, void *add_arg); + +typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type, + const unsigned char *out, void *add_arg); + +typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type, + const unsigned char *in, size_t inlen, + int *al, void *parse_arg); + + +typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char **out, + size_t *outlen, X509 *x, + size_t chainidx, + int *al, void *add_arg); + +typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *out, + void *add_arg); + +typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, + size_t chainidx, + int *al, void *parse_arg); + +/* Typedef for verification callback */ +typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); + +/* + * Some values are reserved until OpenSSL 1.2.0 because they were previously + * included in SSL_OP_ALL in a 1.1.x release. + * + * Reserved value (until OpenSSL 1.2.0) 0x00000001U + * Reserved value (until OpenSSL 1.2.0) 0x00000002U + */ +/* Allow initial connection to servers that don't support RI */ +# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U + +/* Reserved value (until OpenSSL 1.2.0) 0x00000008U */ +# define SSL_OP_TLSEXT_PADDING 0x00000010U +/* Reserved value (until OpenSSL 1.2.0) 0x00000020U */ +# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U +/* + * Reserved value (until OpenSSL 1.2.0) 0x00000080U + * Reserved value (until OpenSSL 1.2.0) 0x00000100U + * Reserved value (until OpenSSL 1.2.0) 0x00000200U + */ + +/* In TLSv1.3 allow a non-(ec)dhe based kex_mode */ +# define SSL_OP_ALLOW_NO_DHE_KEX 0x00000400U + +/* + * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in + * OpenSSL 0.9.6d. Usually (depending on the application protocol) the + * workaround is not needed. Unfortunately some broken SSL/TLS + * implementations cannot handle it at all, which is why we include it in + * SSL_OP_ALL. Added in 0.9.6e + */ +# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800U + +/* DTLS options */ +# define SSL_OP_NO_QUERY_MTU 0x00001000U +/* Turn on Cookie Exchange (on relevant for servers) */ +# define SSL_OP_COOKIE_EXCHANGE 0x00002000U +/* Don't use RFC4507 ticket extension */ +# define SSL_OP_NO_TICKET 0x00004000U +# ifndef OPENSSL_NO_DTLS1_METHOD +/* Use Cisco's "speshul" version of DTLS_BAD_VER + * (only with deprecated DTLSv1_client_method()) */ +# define SSL_OP_CISCO_ANYCONNECT 0x00008000U +# endif + +/* As server, disallow session resumption on renegotiation */ +# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000U +/* Don't use compression even if supported */ +# define SSL_OP_NO_COMPRESSION 0x00020000U +/* Permit unsafe legacy renegotiation */ +# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000U +/* Disable encrypt-then-mac */ +# define SSL_OP_NO_ENCRYPT_THEN_MAC 0x00080000U + +/* + * Enable TLSv1.3 Compatibility mode. This is on by default. A future version + * of OpenSSL may have this disabled by default. + */ +# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0x00100000U + +/* Prioritize Chacha20Poly1305 when client does. + * Modifies SSL_OP_CIPHER_SERVER_PREFERENCE */ +# define SSL_OP_PRIORITIZE_CHACHA 0x00200000U + +/* + * Set on servers to choose the cipher according to the server's preferences + */ +# define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000U +/* + * If set, a server will allow a client to issue a SSLv3.0 version number as + * latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. + */ +# define SSL_OP_TLS_ROLLBACK_BUG 0x00800000U + +/* + * Switches off automatic TLSv1.3 anti-replay protection for early data. This + * is a server-side option only (no effect on the client). + */ +# define SSL_OP_NO_ANTI_REPLAY 0x01000000U + +# define SSL_OP_NO_SSLv3 0x02000000U +# define SSL_OP_NO_TLSv1 0x04000000U +# define SSL_OP_NO_TLSv1_2 0x08000000U +# define SSL_OP_NO_TLSv1_1 0x10000000U +# define SSL_OP_NO_TLSv1_3 0x20000000U + +# define SSL_OP_NO_DTLSv1 0x04000000U +# define SSL_OP_NO_DTLSv1_2 0x08000000U + +# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\ + SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3) +# define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2) + +/* Disallow all renegotiation */ +# define SSL_OP_NO_RENEGOTIATION 0x40000000U + +/* + * Make server add server-hello extension from early version of cryptopro + * draft, when GOST ciphersuite is negotiated. Required for interoperability + * with CryptoPro CSP 3.x + */ +# define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000U + +/* + * SSL_OP_ALL: various bug workarounds that should be rather harmless. + * This used to be 0x000FFFFFL before 0.9.7. + * This used to be 0x80000BFFU before 1.1.1. + */ +# define SSL_OP_ALL (SSL_OP_CRYPTOPRO_TLSEXT_BUG|\ + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS|\ + SSL_OP_LEGACY_SERVER_CONNECT|\ + SSL_OP_TLSEXT_PADDING|\ + SSL_OP_SAFARI_ECDHE_ECDSA_BUG) + +/* OBSOLETE OPTIONS: retained for compatibility */ + +/* Removed from OpenSSL 1.1.0. Was 0x00000001L */ +/* Related to removed SSLv2. */ +# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000002L */ +/* Related to removed SSLv2. */ +# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0 +/* Removed from OpenSSL 0.9.8q and 1.0.0c. Was 0x00000008L */ +/* Dead forever, see CVE-2010-4180 */ +# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0 +/* Removed from OpenSSL 1.0.1h and 1.0.2. Was 0x00000010L */ +/* Refers to ancient SSLREF and SSLv2. */ +# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000020 */ +# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0 +/* Removed from OpenSSL 0.9.7h and 0.9.8b. Was 0x00000040L */ +# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000080 */ +/* Ancient SSLeay version. */ +# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000100L */ +# define SSL_OP_TLS_D5_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00000200L */ +# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00080000L */ +# define SSL_OP_SINGLE_ECDH_USE 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x00100000L */ +# define SSL_OP_SINGLE_DH_USE 0x0 +/* Removed from OpenSSL 1.0.1k and 1.0.2. Was 0x00200000L */ +# define SSL_OP_EPHEMERAL_RSA 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x01000000L */ +# define SSL_OP_NO_SSLv2 0x0 +/* Removed from OpenSSL 1.0.1. Was 0x08000000L */ +# define SSL_OP_PKCS1_CHECK_1 0x0 +/* Removed from OpenSSL 1.0.1. Was 0x10000000L */ +# define SSL_OP_PKCS1_CHECK_2 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x20000000L */ +# define SSL_OP_NETSCAPE_CA_DN_BUG 0x0 +/* Removed from OpenSSL 1.1.0. Was 0x40000000L */ +# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0 + +/* + * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): + */ +# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001U +/* + * Make it possible to retry SSL_write() with changed buffer location (buffer + * contents must stay the same!); this is not the default to avoid the + * misconception that non-blocking SSL_write() behaves like non-blocking + * write(): + */ +# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U +/* + * Never bother the application with retries if the transport is blocking: + */ +# define SSL_MODE_AUTO_RETRY 0x00000004U +/* Don't attempt to automatically build certificate chain */ +# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U +/* + * Save RAM by releasing read and write buffers when they're empty. (SSL3 and + * TLS only.) Released buffers are freed. + */ +# define SSL_MODE_RELEASE_BUFFERS 0x00000010U +/* + * Send the current time in the Random fields of the ClientHello and + * ServerHello records for compatibility with hypothetical implementations + * that require it. + */ +# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U +# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U +/* + * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications + * that reconnect with a downgraded protocol version; see + * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your + * application attempts a normal handshake. Only use this in explicit + * fallback retries, following the guidance in + * draft-ietf-tls-downgrade-scsv-00. + */ +# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U +/* + * Support Asynchronous operation + */ +# define SSL_MODE_ASYNC 0x00000100U + +/* + * When using DTLS/SCTP, include the terminating zero in the label + * used for computing the endpoint-pair shared secret. Required for + * interoperability with implementations having this bug like these + * older version of OpenSSL: + * - OpenSSL 1.0.0 series + * - OpenSSL 1.0.1 series + * - OpenSSL 1.0.2 series + * - OpenSSL 1.1.0 series + * - OpenSSL 1.1.1 and 1.1.1a + */ +# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U + +/* Cert related flags */ +/* + * Many implementations ignore some aspects of the TLS standards such as + * enforcing certificate chain algorithms. When this is set we enforce them. + */ +# define SSL_CERT_FLAG_TLS_STRICT 0x00000001U + +/* Suite B modes, takes same values as certificate verify flags */ +# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000 + +/* Perform all sorts of protocol violations for testing purposes */ +# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000 + +/* Flags for building certificate chains */ +/* Treat any existing certificates as untrusted CAs */ +# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1 +/* Don't include root CA in chain */ +# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2 +/* Just check certificates already there */ +# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4 +/* Ignore verification errors */ +# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8 +/* Clear verification errors from queue */ +# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10 + +/* Flags returned by SSL_check_chain */ +/* Certificate can be used with this session */ +# define CERT_PKEY_VALID 0x1 +/* Certificate can also be used for signing */ +# define CERT_PKEY_SIGN 0x2 +/* EE certificate signing algorithm OK */ +# define CERT_PKEY_EE_SIGNATURE 0x10 +/* CA signature algorithms OK */ +# define CERT_PKEY_CA_SIGNATURE 0x20 +/* EE certificate parameters OK */ +# define CERT_PKEY_EE_PARAM 0x40 +/* CA certificate parameters OK */ +# define CERT_PKEY_CA_PARAM 0x80 +/* Signing explicitly allowed as opposed to SHA1 fallback */ +# define CERT_PKEY_EXPLICIT_SIGN 0x100 +/* Client CA issuer names match (always set for server cert) */ +# define CERT_PKEY_ISSUER_NAME 0x200 +/* Cert type matches client types (always set for server cert) */ +# define CERT_PKEY_CERT_TYPE 0x400 +/* Cert chain suitable to Suite B */ +# define CERT_PKEY_SUITEB 0x800 + +# define SSL_CONF_FLAG_CMDLINE 0x1 +# define SSL_CONF_FLAG_FILE 0x2 +# define SSL_CONF_FLAG_CLIENT 0x4 +# define SSL_CONF_FLAG_SERVER 0x8 +# define SSL_CONF_FLAG_SHOW_ERRORS 0x10 +# define SSL_CONF_FLAG_CERTIFICATE 0x20 +# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40 +/* Configuration value types */ +# define SSL_CONF_TYPE_UNKNOWN 0x0 +# define SSL_CONF_TYPE_STRING 0x1 +# define SSL_CONF_TYPE_FILE 0x2 +# define SSL_CONF_TYPE_DIR 0x3 +# define SSL_CONF_TYPE_NONE 0x4 + +/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */ +# define SSL_COOKIE_LENGTH 4096 + +/* + * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they + * cannot be used to clear bits. + */ + +unsigned long SSL_CTX_get_options(const SSL_CTX *ctx); +unsigned long SSL_get_options(const SSL *s); +unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op); +unsigned long SSL_clear_options(SSL *s, unsigned long op); +unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op); +unsigned long SSL_set_options(SSL *s, unsigned long op); + +# define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +# define SSL_CTX_clear_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +# define SSL_clear_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +# define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) +# define SSL_set_mtu(ssl, mtu) \ + SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL) +# define DTLS_set_link_mtu(ssl, mtu) \ + SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL) +# define DTLS_get_link_min_mtu(ssl) \ + SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL) + +# define SSL_get_secure_renegotiation_support(ssl) \ + SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_heartbeat(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT,0,NULL) +# endif + +# define SSL_CTX_set_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_set_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_CTX_clear_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) +# define SSL_clear_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + +# define SSL_get_extms_support(s) \ + SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL) + +# ifndef OPENSSL_NO_SRP + +/* see tls_srp.c */ +__owur int SSL_SRP_CTX_init(SSL *s); +__owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx); +int SSL_SRP_CTX_free(SSL *ctx); +int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx); +__owur int SSL_srp_server_param_with_username(SSL *s, int *ad); +__owur int SRP_Calc_A_param(SSL *s); + +# endif + +/* 100k max cert list */ +# define SSL_MAX_CERT_LIST_DEFAULT 1024*100 + +# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) + +/* + * This callback type is used inside SSL_CTX, SSL, and in the functions that + * set them. It is used to override the generation of SSL/TLS session IDs in + * a server. Return value should be zero on an error, non-zero to proceed. + * Also, callbacks should themselves check if the id they generate is unique + * otherwise the SSL handshake will fail with an error - callbacks can do + * this using the 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in + * is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32 + * bytes. The callback can alter this length to be less if desired. It is + * also an error for the callback to set the size to zero. + */ +typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id, + unsigned int *id_len); + +# define SSL_SESS_CACHE_OFF 0x0000 +# define SSL_SESS_CACHE_CLIENT 0x0001 +# define SSL_SESS_CACHE_SERVER 0x0002 +# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080 +/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */ +# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 +# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 +# define SSL_SESS_CACHE_NO_INTERNAL \ + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx); +# define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +# define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +# define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +# define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +# define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +# define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +# define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +# define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +# define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +# define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*new_session_cb) (struct ssl_st *ssl, + SSL_SESSION *sess)); +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + SSL_SESSION *sess); +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*remove_session_cb) (struct ssl_ctx_st + *ctx, + SSL_SESSION *sess)); +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx, + SSL_SESSION *sess); +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*get_session_cb) (struct ssl_st + *ssl, + const unsigned char + *data, int len, + int *copy)); +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + const unsigned char *data, + int len, int *copy); +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb) (const SSL *ssl, int type, int val)); +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, + int val); +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*client_cert_cb) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey)); +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey); +# ifndef OPENSSL_NO_ENGINE +__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e); +# endif +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*app_gen_cookie_cb) (SSL *ssl, + unsigned char + *cookie, + unsigned int + *cookie_len)); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*app_verify_cookie_cb) (SSL *ssl, + const unsigned + char *cookie, + unsigned int + cookie_len)); + +void SSL_CTX_set_stateless_cookie_generate_cb( + SSL_CTX *ctx, + int (*gen_stateless_cookie_cb) (SSL *ssl, + unsigned char *cookie, + size_t *cookie_len)); +void SSL_CTX_set_stateless_cookie_verify_cb( + SSL_CTX *ctx, + int (*verify_stateless_cookie_cb) (SSL *ssl, + const unsigned char *cookie, + size_t cookie_len)); +# ifndef OPENSSL_NO_NEXTPROTONEG + +typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg); +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, + SSL_CTX_npn_advertised_cb_func cb, + void *arg); +# define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb + +typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, + SSL_CTX_npn_select_cb_func cb, + void *arg); +# define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb + +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned *len); +# define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated +# endif + +__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); + +# define OPENSSL_NPN_UNSUPPORTED 0 +# define OPENSSL_NPN_NEGOTIATED 1 +# define OPENSSL_NPN_NO_OVERLAP 2 + +__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned int protos_len); +__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned int protos_len); +typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + SSL_CTX_alpn_select_cb_func cb, + void *arg); +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned int *len); + +# ifndef OPENSSL_NO_PSK +/* + * the maximum length of the buffer given to callbacks containing the + * resulting identity/psk + */ +# define PSK_MAX_IDENTITY_LEN 128 +# define PSK_MAX_PSK_LEN 256 +typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len); +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb); +void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb); + +typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl, + const char *identity, + unsigned char *psk, + unsigned int max_psk_len); +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb); +void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb); + +__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint); +__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint); +const char *SSL_get_psk_identity_hint(const SSL *s); +const char *SSL_get_psk_identity(const SSL *s); +# endif + +typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl, + const unsigned char *identity, + size_t identity_len, + SSL_SESSION **sess); +typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md, + const unsigned char **id, + size_t *idlen, + SSL_SESSION **sess); + +void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb); +void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, + SSL_psk_find_session_cb_func cb); +void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb); +void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx, + SSL_psk_use_session_cb_func cb); + +/* Register callbacks to handle custom TLS Extensions for client or server. */ + +__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, + unsigned int ext_type); + +__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + unsigned int context, + SSL_custom_ext_add_cb_ex add_cb, + SSL_custom_ext_free_cb_ex free_cb, + void *add_arg, + SSL_custom_ext_parse_cb_ex parse_cb, + void *parse_arg); + +__owur int SSL_extension_supported(unsigned int ext_type); + +# define SSL_NOTHING 1 +# define SSL_WRITING 2 +# define SSL_READING 3 +# define SSL_X509_LOOKUP 4 +# define SSL_ASYNC_PAUSED 5 +# define SSL_ASYNC_NO_JOBS 6 +# define SSL_CLIENT_HELLO_CB 7 + +/* These will only be used when doing non-blocking IO */ +# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +# define SSL_want_read(s) (SSL_want(s) == SSL_READING) +# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) +# define SSL_want_async(s) (SSL_want(s) == SSL_ASYNC_PAUSED) +# define SSL_want_async_job(s) (SSL_want(s) == SSL_ASYNC_NO_JOBS) +# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB) + +# define SSL_MAC_FLAG_READ_MAC_STREAM 1 +# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 + +/* + * A callback for logging out TLS key material. This callback should log out + * |line| followed by a newline. + */ +typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line); + +/* + * SSL_CTX_set_keylog_callback configures a callback to log key material. This + * is intended for debugging use with tools like Wireshark. The cb function + * should log line followed by a newline. + */ +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb); + +/* + * SSL_CTX_get_keylog_callback returns the callback configured by + * SSL_CTX_set_keylog_callback. + */ +SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx); + +int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data); +uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); +int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); +uint32_t SSL_get_max_early_data(const SSL *s); +int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data); +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx); +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data); +uint32_t SSL_get_recv_max_early_data(const SSL *s); + +#ifdef __cplusplus +} +#endif + +# include +# include +# include /* This is mostly sslv3 with a few tweaks */ +# include /* Datagram TLS */ +# include /* Support for the use_srtp extension */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These need to be after the above set of includes due to a compiler bug + * in VisualStudio 2015 + */ +DEFINE_STACK_OF_CONST(SSL_CIPHER) +DEFINE_STACK_OF(SSL_COMP) + +/* compatibility */ +# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)(arg))) +# define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) +# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0, \ + (char *)(a))) +# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0)) +# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0)) +# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0, \ + (char *)(arg))) +DEPRECATEDIN_1_1_0(void SSL_set_debug(SSL *s, int debug)) + +/* TLSv1.3 KeyUpdate message types */ +/* -1 used so that this is an invalid value for the on-the-wire protocol */ +#define SSL_KEY_UPDATE_NONE -1 +/* Values as defined for the on-the-wire protocol */ +#define SSL_KEY_UPDATE_NOT_REQUESTED 0 +#define SSL_KEY_UPDATE_REQUESTED 1 + +/* + * The valid handshake states (one for each type message sent and one for each + * type of message received). There are also two "special" states: + * TLS = TLS or DTLS state + * DTLS = DTLS specific state + * CR/SR = Client Read/Server Read + * CW/SW = Client Write/Server Write + * + * The "special" states are: + * TLS_ST_BEFORE = No handshake has been initiated yet + * TLS_ST_OK = A handshake has been successfully completed + */ +typedef enum { + TLS_ST_BEFORE, + TLS_ST_OK, + DTLS_ST_CR_HELLO_VERIFY_REQUEST, + TLS_ST_CR_SRVR_HELLO, + TLS_ST_CR_CERT, + TLS_ST_CR_CERT_STATUS, + TLS_ST_CR_KEY_EXCH, + TLS_ST_CR_CERT_REQ, + TLS_ST_CR_SRVR_DONE, + TLS_ST_CR_SESSION_TICKET, + TLS_ST_CR_CHANGE, + TLS_ST_CR_FINISHED, + TLS_ST_CW_CLNT_HELLO, + TLS_ST_CW_CERT, + TLS_ST_CW_KEY_EXCH, + TLS_ST_CW_CERT_VRFY, + TLS_ST_CW_CHANGE, + TLS_ST_CW_NEXT_PROTO, + TLS_ST_CW_FINISHED, + TLS_ST_SW_HELLO_REQ, + TLS_ST_SR_CLNT_HELLO, + DTLS_ST_SW_HELLO_VERIFY_REQUEST, + TLS_ST_SW_SRVR_HELLO, + TLS_ST_SW_CERT, + TLS_ST_SW_KEY_EXCH, + TLS_ST_SW_CERT_REQ, + TLS_ST_SW_SRVR_DONE, + TLS_ST_SR_CERT, + TLS_ST_SR_KEY_EXCH, + TLS_ST_SR_CERT_VRFY, + TLS_ST_SR_NEXT_PROTO, + TLS_ST_SR_CHANGE, + TLS_ST_SR_FINISHED, + TLS_ST_SW_SESSION_TICKET, + TLS_ST_SW_CERT_STATUS, + TLS_ST_SW_CHANGE, + TLS_ST_SW_FINISHED, + TLS_ST_SW_ENCRYPTED_EXTENSIONS, + TLS_ST_CR_ENCRYPTED_EXTENSIONS, + TLS_ST_CR_CERT_VRFY, + TLS_ST_SW_CERT_VRFY, + TLS_ST_CR_HELLO_REQ, + TLS_ST_SW_KEY_UPDATE, + TLS_ST_CW_KEY_UPDATE, + TLS_ST_SR_KEY_UPDATE, + TLS_ST_CR_KEY_UPDATE, + TLS_ST_EARLY_DATA, + TLS_ST_PENDING_EARLY_DATA_END, + TLS_ST_CW_END_OF_EARLY_DATA, + TLS_ST_SR_END_OF_EARLY_DATA +} OSSL_HANDSHAKE_STATE; + +/* + * Most of the following state values are no longer used and are defined to be + * the closest equivalent value in the current state machine code. Not all + * defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT + * and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP, + * SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT. + */ + +# define SSL_ST_CONNECT 0x1000 +# define SSL_ST_ACCEPT 0x2000 + +# define SSL_ST_MASK 0x0FFF + +# define SSL_CB_LOOP 0x01 +# define SSL_CB_EXIT 0x02 +# define SSL_CB_READ 0x04 +# define SSL_CB_WRITE 0x08 +# define SSL_CB_ALERT 0x4000/* used in callback */ +# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) +# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) +# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) +# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) +# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) +# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) +# define SSL_CB_HANDSHAKE_START 0x10 +# define SSL_CB_HANDSHAKE_DONE 0x20 + +/* Is the SSL_connection established? */ +# define SSL_in_connect_init(a) (SSL_in_init(a) && !SSL_is_server(a)) +# define SSL_in_accept_init(a) (SSL_in_init(a) && SSL_is_server(a)) +int SSL_in_init(const SSL *s); +int SSL_in_before(const SSL *s); +int SSL_is_init_finished(const SSL *s); + +/* + * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you + * should not need these + */ +# define SSL_ST_READ_HEADER 0xF0 +# define SSL_ST_READ_BODY 0xF1 +# define SSL_ST_READ_DONE 0xF2 + +/*- + * Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. + */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); + +/* + * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are + * 'ored' with SSL_VERIFY_PEER if they are desired + */ +# define SSL_VERIFY_NONE 0x00 +# define SSL_VERIFY_PEER 0x01 +# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +# define SSL_VERIFY_CLIENT_ONCE 0x04 +# define SSL_VERIFY_POST_HANDSHAKE 0x08 + +# if OPENSSL_API_COMPAT < 0x10100000L +# define OpenSSL_add_ssl_algorithms() SSL_library_init() +# define SSLeay_add_ssl_algorithms() SSL_library_init() +# endif + +/* More backward compatibility */ +# define SSL_get_cipher(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_cipher_bits(s,np) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +# define SSL_get_cipher_version(s) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(s)) +# define SSL_get_cipher_name(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_time(a) SSL_SESSION_get_time(a) +# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b)) +# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) +# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) + +# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id) +# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id) + +DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) +# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value + * from SSL_AD_... */ +/* These alert types are for SSLv3 and TLSv1 */ +# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY +/* fatal */ +# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE +/* fatal */ +# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC +# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED +# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW +/* fatal */ +# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE +/* fatal */ +# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE +/* Not for TLS */ +# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE +# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE +# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE +# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED +# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED +# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN +/* fatal */ +# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER +/* fatal */ +# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA +/* fatal */ +# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED +/* fatal */ +# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR +# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR +/* fatal */ +# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION +/* fatal */ +# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION +/* fatal */ +# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY +/* fatal */ +# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR +# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED +# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION +# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION +# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED +# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION +# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE +# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME +# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +/* fatal */ +# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY +/* fatal */ +# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK +# define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL +# define SSL_ERROR_NONE 0 +# define SSL_ERROR_SSL 1 +# define SSL_ERROR_WANT_READ 2 +# define SSL_ERROR_WANT_WRITE 3 +# define SSL_ERROR_WANT_X509_LOOKUP 4 +# define SSL_ERROR_SYSCALL 5/* look at error stack/return + * value/errno */ +# define SSL_ERROR_ZERO_RETURN 6 +# define SSL_ERROR_WANT_CONNECT 7 +# define SSL_ERROR_WANT_ACCEPT 8 +# define SSL_ERROR_WANT_ASYNC 9 +# define SSL_ERROR_WANT_ASYNC_JOB 10 +# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11 +# define SSL_CTRL_SET_TMP_DH 3 +# define SSL_CTRL_SET_TMP_ECDH 4 +# define SSL_CTRL_SET_TMP_DH_CB 6 +# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9 +# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10 +# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +# define SSL_CTRL_GET_FLAGS 13 +# define SSL_CTRL_EXTRA_CHAIN_CERT 14 +# define SSL_CTRL_SET_MSG_CALLBACK 15 +# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16 +/* only applies to datagram connections */ +# define SSL_CTRL_SET_MTU 17 +/* Stats */ +# define SSL_CTRL_SESS_NUMBER 20 +# define SSL_CTRL_SESS_CONNECT 21 +# define SSL_CTRL_SESS_CONNECT_GOOD 22 +# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +# define SSL_CTRL_SESS_ACCEPT 24 +# define SSL_CTRL_SESS_ACCEPT_GOOD 25 +# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +# define SSL_CTRL_SESS_HIT 27 +# define SSL_CTRL_SESS_CB_HIT 28 +# define SSL_CTRL_SESS_MISSES 29 +# define SSL_CTRL_SESS_TIMEOUTS 30 +# define SSL_CTRL_SESS_CACHE_FULL 31 +# define SSL_CTRL_MODE 33 +# define SSL_CTRL_GET_READ_AHEAD 40 +# define SSL_CTRL_SET_READ_AHEAD 41 +# define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +# define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +# define SSL_CTRL_SET_SESS_CACHE_MODE 44 +# define SSL_CTRL_GET_SESS_CACHE_MODE 45 +# define SSL_CTRL_GET_MAX_CERT_LIST 50 +# define SSL_CTRL_SET_MAX_CERT_LIST 51 +# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52 +/* see tls1.h for macros based on these */ +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56 +# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 */ +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */ +/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */ +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75 +# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76 +# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77 +# define SSL_CTRL_SET_SRP_ARG 78 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79 +# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80 +# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81 +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT 85 +# define SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING 86 +# define SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS 87 +# endif +# define DTLS_CTRL_GET_TIMEOUT 73 +# define DTLS_CTRL_HANDLE_TIMEOUT 74 +# define SSL_CTRL_GET_RI_SUPPORT 76 +# define SSL_CTRL_CLEAR_MODE 78 +# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79 +# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 +# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 +# define SSL_CTRL_CHAIN 88 +# define SSL_CTRL_CHAIN_CERT 89 +# define SSL_CTRL_GET_GROUPS 90 +# define SSL_CTRL_SET_GROUPS 91 +# define SSL_CTRL_SET_GROUPS_LIST 92 +# define SSL_CTRL_GET_SHARED_GROUP 93 +# define SSL_CTRL_SET_SIGALGS 97 +# define SSL_CTRL_SET_SIGALGS_LIST 98 +# define SSL_CTRL_CERT_FLAGS 99 +# define SSL_CTRL_CLEAR_CERT_FLAGS 100 +# define SSL_CTRL_SET_CLIENT_SIGALGS 101 +# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102 +# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103 +# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104 +# define SSL_CTRL_BUILD_CERT_CHAIN 105 +# define SSL_CTRL_SET_VERIFY_CERT_STORE 106 +# define SSL_CTRL_SET_CHAIN_CERT_STORE 107 +# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108 +# define SSL_CTRL_GET_PEER_TMP_KEY 109 +# define SSL_CTRL_GET_RAW_CIPHERLIST 110 +# define SSL_CTRL_GET_EC_POINT_FORMATS 111 +# define SSL_CTRL_GET_CHAIN_CERTS 115 +# define SSL_CTRL_SELECT_CURRENT_CERT 116 +# define SSL_CTRL_SET_CURRENT_CERT 117 +# define SSL_CTRL_SET_DH_AUTO 118 +# define DTLS_CTRL_SET_LINK_MTU 120 +# define DTLS_CTRL_GET_LINK_MIN_MTU 121 +# define SSL_CTRL_GET_EXTMS_SUPPORT 122 +# define SSL_CTRL_SET_MIN_PROTO_VERSION 123 +# define SSL_CTRL_SET_MAX_PROTO_VERSION 124 +# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT 125 +# define SSL_CTRL_SET_MAX_PIPELINES 126 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129 +# define SSL_CTRL_GET_MIN_PROTO_VERSION 130 +# define SSL_CTRL_GET_MAX_PROTO_VERSION 131 +# define SSL_CTRL_GET_SIGNATURE_NID 132 +# define SSL_CTRL_GET_TMP_KEY 133 +# define SSL_CERT_SET_FIRST 1 +# define SSL_CERT_SET_NEXT 2 +# define SSL_CERT_SET_SERVER 3 +# define DTLSv1_get_timeout(ssl, arg) \ + SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg)) +# define DTLSv1_handle_timeout(ssl) \ + SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +# define SSL_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_clear_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_total_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL) +# define SSL_CTX_set_tmp_dh(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) +# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) +# define SSL_CTX_set_dh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +# define SSL_set_dh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +# define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) +# define SSL_set_tmp_ecdh(ssl,ecdh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) +# define SSL_CTX_add_extra_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509)) +# define SSL_CTX_get_extra_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509) +# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509) +# define SSL_CTX_clear_extra_chain_certs(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL) +# define SSL_CTX_set0_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +# define SSL_CTX_set1_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk)) +# define SSL_CTX_add0_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509)) +# define SSL_CTX_add1_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509)) +# define SSL_CTX_get0_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_CTX_clear_chain_certs(ctx) \ + SSL_CTX_set0_chain(ctx,NULL) +# define SSL_CTX_build_cert_chain(ctx, flags) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_CTX_select_current_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509)) +# define SSL_CTX_set_current_cert(ctx, op) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_CTX_set0_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) +# define SSL_CTX_set1_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +# define SSL_CTX_set0_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) +# define SSL_CTX_set1_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +# define SSL_set0_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +# define SSL_set1_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk)) +# define SSL_add0_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509)) +# define SSL_add1_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509)) +# define SSL_get0_chain_certs(ctx,px509) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_clear_chain_certs(ctx) \ + SSL_set0_chain(ctx,NULL) +# define SSL_build_cert_chain(s, flags) \ + SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_select_current_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509)) +# define SSL_set_current_cert(ctx,op) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_set0_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) +# define SSL_set1_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +# define SSL_set0_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) +# define SSL_set1_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +# define SSL_get1_groups(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_GET_GROUPS,0,(char *)(s)) +# define SSL_CTX_set1_groups(ctx, glist, glistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist)) +# define SSL_CTX_set1_groups_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s)) +# define SSL_set1_groups(ctx, glist, glistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist)) +# define SSL_set1_groups_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s)) +# define SSL_get_shared_group(s, n) \ + SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL) +# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist)) +# define SSL_CTX_set1_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s)) +# define SSL_set1_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist)) +# define SSL_set1_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s)) +# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist)) +# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s)) +# define SSL_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,clistlen,(int *)(slist)) +# define SSL_set1_client_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s)) +# define SSL_get0_certificate_types(s, clist) \ + SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist)) +# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \ + (char *)(clist)) +# define SSL_set1_client_certificate_types(s, clist, clistlen) \ + SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist)) +# define SSL_get_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn) +# define SSL_get_peer_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn) +# define SSL_get_peer_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk) +# define SSL_get_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk) +# define SSL_get0_raw_cipherlist(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst) +# define SSL_get0_ec_point_formats(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst) +# define SSL_CTX_set_min_proto_version(ctx, version) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL) +# define SSL_CTX_set_max_proto_version(ctx, version) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL) +# define SSL_CTX_get_min_proto_version(ctx) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL) +# define SSL_CTX_get_max_proto_version(ctx) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL) +# define SSL_set_min_proto_version(s, version) \ + SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL) +# define SSL_set_max_proto_version(s, version) \ + SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL) +# define SSL_get_min_proto_version(s) \ + SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL) +# define SSL_get_max_proto_version(s) \ + SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL) + +/* Backwards compatibility, original 1.1.0 names */ +# define SSL_CTRL_GET_SERVER_TMP_KEY \ + SSL_CTRL_GET_PEER_TMP_KEY +# define SSL_get_server_tmp_key(s, pk) \ + SSL_get_peer_tmp_key(s, pk) + +/* + * The following symbol names are old and obsolete. They are kept + * for compatibility reasons only and should not be used anymore. + */ +# define SSL_CTRL_GET_CURVES SSL_CTRL_GET_GROUPS +# define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS +# define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST +# define SSL_CTRL_GET_SHARED_CURVE SSL_CTRL_GET_SHARED_GROUP + +# define SSL_get1_curves SSL_get1_groups +# define SSL_CTX_set1_curves SSL_CTX_set1_groups +# define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list +# define SSL_set1_curves SSL_set1_groups +# define SSL_set1_curves_list SSL_set1_groups_list +# define SSL_get_shared_curve SSL_get_shared_group + + +# if OPENSSL_API_COMPAT < 0x10100000L +/* Provide some compatibility macros for removed functionality. */ +# define SSL_CTX_need_tmp_RSA(ctx) 0 +# define SSL_CTX_set_tmp_rsa(ctx,rsa) 1 +# define SSL_need_tmp_RSA(ssl) 0 +# define SSL_set_tmp_rsa(ssl,rsa) 1 +# define SSL_CTX_set_ecdh_auto(dummy, onoff) ((onoff) != 0) +# define SSL_set_ecdh_auto(dummy, onoff) ((onoff) != 0) +/* + * We "pretend" to call the callback to avoid warnings about unused static + * functions. + */ +# define SSL_CTX_set_tmp_rsa_callback(ctx, cb) while(0) (cb)(NULL, 0, 0) +# define SSL_set_tmp_rsa_callback(ssl, cb) while(0) (cb)(NULL, 0, 0) +# endif +__owur const BIO_METHOD *BIO_f_ssl(void); +__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client); +__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx); +__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx); +__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from); +void BIO_ssl_shutdown(BIO *ssl_bio); + +__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str); +__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +int SSL_CTX_up_ref(SSL_CTX *ctx); +void SSL_CTX_free(SSL_CTX *); +__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t); +__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx); +__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); +void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *); +__owur int SSL_want(const SSL *s); +__owur int SSL_clear(SSL *s); + +void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm); + +__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s); +__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s); +__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits); +__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c); +__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c); +__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c); +__owur const char *OPENSSL_cipher_name(const char *rfc_name); +__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c); +__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c); +__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c); +__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c); +__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c); +__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c); + +__owur int SSL_get_fd(const SSL *s); +__owur int SSL_get_rfd(const SSL *s); +__owur int SSL_get_wfd(const SSL *s); +__owur const char *SSL_get_cipher_list(const SSL *s, int n); +__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size); +__owur int SSL_get_read_ahead(const SSL *s); +__owur int SSL_pending(const SSL *s); +__owur int SSL_has_pending(const SSL *s); +# ifndef OPENSSL_NO_SOCK +__owur int SSL_set_fd(SSL *s, int fd); +__owur int SSL_set_rfd(SSL *s, int fd); +__owur int SSL_set_wfd(SSL *s, int fd); +# endif +void SSL_set0_rbio(SSL *s, BIO *rbio); +void SSL_set0_wbio(SSL *s, BIO *wbio); +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio); +__owur BIO *SSL_get_rbio(const SSL *s); +__owur BIO *SSL_get_wbio(const SSL *s); +__owur int SSL_set_cipher_list(SSL *s, const char *str); +__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); +__owur int SSL_set_ciphersuites(SSL *s, const char *str); +void SSL_set_read_ahead(SSL *s, int yes); +__owur int SSL_get_verify_mode(const SSL *s); +__owur int SSL_get_verify_depth(const SSL *s); +__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s); +void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback); +void SSL_set_verify_depth(SSL *s, int depth); +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg); +# ifndef OPENSSL_NO_RSA +__owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, + long len); +# endif +__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, + long len); +__owur int SSL_use_certificate(SSL *ssl, X509 *x); +__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); +__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override); + + +/* serverinfo file format versions */ +# define SSL_SERVERINFOV1 1 +# define SSL_SERVERINFOV2 2 + +/* Set serverinfo data for the current active cert. */ +__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length); +__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, + const unsigned char *serverinfo, + size_t serverinfo_length); +__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); + +#ifndef OPENSSL_NO_RSA +__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +#endif + +__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type); + +#ifndef OPENSSL_NO_RSA +__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, + int type); +#endif +__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, + int type); +__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, + int type); +/* PEM type */ +__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); +__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file); +__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_load_error_strings() \ + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) +# endif + +__owur const char *SSL_state_string(const SSL *s); +__owur const char *SSL_rstate_string(const SSL *s); +__owur const char *SSL_state_string_long(const SSL *s); +__owur const char *SSL_rstate_string_long(const SSL *s); +__owur long SSL_SESSION_get_time(const SSL_SESSION *s); +__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t); +__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s); +__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t); +__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s); +__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version); + +__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s); +__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname); +void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, + const unsigned char **alpn, + size_t *len); +__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, + const unsigned char *alpn, + size_t len); +__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s); +__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher); +__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s); +__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s); +void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, + size_t *len); +__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s); +__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s, + uint32_t max_early_data); +__owur int SSL_copy_session_id(SSL *to, const SSL *from); +__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s); +__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s, + const unsigned char *sid_ctx, + unsigned int sid_ctx_len); +__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, + unsigned int sid_len); +__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s); + +__owur SSL_SESSION *SSL_SESSION_new(void); +__owur SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src); +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, + unsigned int *len); +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, + unsigned int *len); +__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s); +# ifndef OPENSSL_NO_STDIO +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses); +# endif +int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses); +int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x); +int SSL_SESSION_up_ref(SSL_SESSION *ses); +void SSL_SESSION_free(SSL_SESSION *ses); +__owur int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); +__owur int SSL_set_session(SSL *to, SSL_SESSION *session); +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session); +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session); +__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb); +__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb); +__owur int SSL_has_matching_session_id(const SSL *s, + const unsigned char *id, + unsigned int id_len); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length); + +# ifdef HEADER_X509_H +__owur X509 *SSL_get_peer_certificate(const SSL *s); +# endif + +__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s); + +__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); +__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb) (X509_STORE_CTX *, void *), + void *arg); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), + void *arg); +# ifndef OPENSSL_NO_RSA +__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, + long len); +# endif +__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, + const unsigned char *d, long len); +__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, + const unsigned char *d); +__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey, + STACK_OF(X509) *chain, int override); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); +pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx); +void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx); +void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb); +void SSL_set_default_passwd_cb_userdata(SSL *s, void *u); +pem_password_cb *SSL_get_default_passwd_cb(SSL *s); +void *SSL_get_default_passwd_cb_userdata(SSL *s); + +__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx); +__owur int SSL_check_private_key(const SSL *ctx); + +__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx, + const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +SSL *SSL_new(SSL_CTX *ctx); +int SSL_up_ref(SSL *s); +int SSL_is_dtls(const SSL *s); +__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose); +__owur int SSL_set_purpose(SSL *ssl, int purpose); +__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust); +__owur int SSL_set_trust(SSL *ssl, int trust); + +__owur int SSL_set1_host(SSL *s, const char *hostname); +__owur int SSL_add1_host(SSL *s, const char *hostname); +__owur const char *SSL_get0_peername(SSL *s); +void SSL_set_hostflags(SSL *s, unsigned int flags); + +__owur int SSL_CTX_dane_enable(SSL_CTX *ctx); +__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, + uint8_t mtype, uint8_t ord); +__owur int SSL_dane_enable(SSL *s, const char *basedomain); +__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector, + uint8_t mtype, unsigned const char *data, size_t dlen); +__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki); +__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector, + uint8_t *mtype, unsigned const char **data, + size_t *dlen); +/* + * Bridge opacity barrier between libcrypt and libssl, also needed to support + * offline testing in test/danetest.c + */ +SSL_DANE *SSL_get0_dane(SSL *ssl); +/* + * DANE flags + */ +unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags); +unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags); +unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags); +unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags); + +__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); +__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); + +__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); +__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + +# ifndef OPENSSL_NO_SRP +int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name); +int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password); +int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength); +int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, + char *(*cb) (SSL *, void *)); +int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, + int (*cb) (SSL *, void *)); +int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, + int (*cb) (SSL *, int *, void *)); +int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg); + +int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g, + BIGNUM *sa, BIGNUM *v, char *info); +int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, + const char *grp); + +__owur BIGNUM *SSL_get_srp_g(SSL *s); +__owur BIGNUM *SSL_get_srp_N(SSL *s); + +__owur char *SSL_get_srp_username(SSL *s); +__owur char *SSL_get_srp_userinfo(SSL *s); +# endif + +/* + * ClientHello callback and helpers. + */ + +# define SSL_CLIENT_HELLO_SUCCESS 1 +# define SSL_CLIENT_HELLO_ERROR 0 +# define SSL_CLIENT_HELLO_RETRY (-1) + +typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg); +void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb, + void *arg); +int SSL_client_hello_isv2(SSL *s); +unsigned int SSL_client_hello_get0_legacy_version(SSL *s); +size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out); +size_t SSL_client_hello_get0_compression_methods(SSL *s, + const unsigned char **out); +int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen); +int SSL_client_hello_get0_ext(SSL *s, unsigned int type, + const unsigned char **out, size_t *outlen); + +void SSL_certs_clear(SSL *s); +void SSL_free(SSL *ssl); +# ifdef OSSL_ASYNC_FD +/* + * Windows application developer has to include windows.h to use these. + */ +__owur int SSL_waiting_for_async(SSL *s); +__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds); +__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, + size_t *numaddfds, OSSL_ASYNC_FD *delfd, + size_t *numdelfds); +# endif +__owur int SSL_accept(SSL *ssl); +__owur int SSL_stateless(SSL *s); +__owur int SSL_connect(SSL *ssl); +__owur int SSL_read(SSL *ssl, void *buf, int num); +__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); + +# define SSL_READ_EARLY_DATA_ERROR 0 +# define SSL_READ_EARLY_DATA_SUCCESS 1 +# define SSL_READ_EARLY_DATA_FINISH 2 + +__owur int SSL_read_early_data(SSL *s, void *buf, size_t num, + size_t *readbytes); +__owur int SSL_peek(SSL *ssl, void *buf, int num); +__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); +__owur int SSL_write(SSL *ssl, const void *buf, int num); +__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written); +__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num, + size_t *written); +long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)(void)); +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void)); + +# define SSL_EARLY_DATA_NOT_SENT 0 +# define SSL_EARLY_DATA_REJECTED 1 +# define SSL_EARLY_DATA_ACCEPTED 2 + +__owur int SSL_get_early_data_status(const SSL *s); + +__owur int SSL_get_error(const SSL *s, int ret_code); +__owur const char *SSL_get_version(const SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth); + +# ifndef OPENSSL_NO_SSL3_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_method(void)) /* SSLv3 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_client_method(void)) +# endif + +#define SSLv23_method TLS_method +#define SSLv23_server_method TLS_server_method +#define SSLv23_client_method TLS_client_method + +/* Negotiate highest available SSL/TLS version */ +__owur const SSL_METHOD *TLS_method(void); +__owur const SSL_METHOD *TLS_server_method(void); +__owur const SSL_METHOD *TLS_client_method(void); + +# ifndef OPENSSL_NO_TLS1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_TLS1_1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_method(void)) /* TLSv1.1 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_TLS1_2_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void)) +# endif + +# ifndef OPENSSL_NO_DTLS1_METHOD +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_method(void)) /* DTLSv1.0 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_client_method(void)) +# endif + +# ifndef OPENSSL_NO_DTLS1_2_METHOD +/* DTLSv1.2 */ +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_server_method(void)) +DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_client_method(void)) +# endif + +__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */ +__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */ +__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */ + +__owur size_t DTLS_get_data_mtu(const SSL *s); + +__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); +__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx); +__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s); +__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s); + +__owur int SSL_do_handshake(SSL *s); +int SSL_key_update(SSL *s, int updatetype); +int SSL_get_key_update_type(const SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_renegotiate_abbreviated(SSL *s); +__owur int SSL_renegotiate_pending(const SSL *s); +int SSL_shutdown(SSL *s); +__owur int SSL_verify_client_post_handshake(SSL *s); +void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val); +void SSL_set_post_handshake_auth(SSL *s, int val); + +__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx); +__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s); +__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); +__owur const char *SSL_alert_type_string_long(int value); +__owur const char *SSL_alert_type_string(int value); +__owur const char *SSL_alert_desc_string_long(int value); +__owur const char *SSL_alert_desc_string(int value); + +void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s); +__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx); +__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x); +__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x); +__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); +__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s); +__owur int SSL_add_client_CA(SSL *ssl, X509 *x); +__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x); + +void SSL_set_connect_state(SSL *s); +void SSL_set_accept_state(SSL *s); + +__owur long SSL_get_default_timeout(const SSL *s); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_library_init() OPENSSL_init_ssl(0, NULL) +# endif + +__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size); +__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk); + +__owur SSL *SSL_dup(SSL *ssl); + +__owur X509 *SSL_get_certificate(const SSL *ssl); +/* + * EVP_PKEY + */ +struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl); + +__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); +__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); +__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); +void SSL_set_quiet_shutdown(SSL *ssl, int mode); +__owur int SSL_get_quiet_shutdown(const SSL *ssl); +void SSL_set_shutdown(SSL *ssl, int mode); +__owur int SSL_get_shutdown(const SSL *ssl); +__owur int SSL_version(const SSL *ssl); +__owur int SSL_client_version(const SSL *s); +__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx); +__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx); +__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +# define SSL_get0_session SSL_get_session/* just peek at pointer */ +__owur SSL_SESSION *SSL_get_session(const SSL *ssl); +__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ +__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); +void SSL_set_info_callback(SSL *ssl, + void (*cb) (const SSL *ssl, int type, int val)); +void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type, + int val); +__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl); + +void SSL_set_verify_result(SSL *ssl, long v); +__owur long SSL_get_verify_result(const SSL *ssl); +__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s); + +__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, + size_t outlen); +__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, + size_t outlen); +__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess, + unsigned char *out, size_t outlen); +__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess, + const unsigned char *in, size_t len); +uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess); + +#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef) +__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data); +void *SSL_get_ex_data(const SSL *ssl, int idx); +#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef) +__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data); +void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx); +#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef) +__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data); +void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx); + +__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void); + +# define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +# define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +# define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +# define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +# define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +# define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +# define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +# define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + +# define SSL_CTX_set_max_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +# define SSL_set_max_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +# define SSL_CTX_set_split_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL) +# define SSL_set_split_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL) +# define SSL_CTX_set_max_pipelines(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL) +# define SSL_set_max_pipelines(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL) + +void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len); +void SSL_set_default_read_buffer_len(SSL *s, size_t len); + +# ifndef OPENSSL_NO_DH +/* NB: the |keylength| is only applicable when is_export is true */ +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +# endif + +__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s); +__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s); +__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp); +__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp); +__owur int SSL_COMP_get_id(const SSL_COMP *comp); +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths); +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_COMP_free_compression_methods() while(0) continue +# endif +__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); + +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr); +int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c); +int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c); +int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len, + int isv2format, STACK_OF(SSL_CIPHER) **sk, + STACK_OF(SSL_CIPHER) **scsvs); + +/* TLS extensions functions */ +__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); + +__owur int SSL_set_session_ticket_ext_cb(SSL *s, + tls_session_ticket_ext_cb_fn cb, + void *arg); + +/* Pre-shared secret session resumption functions */ +__owur int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn session_secret_cb, + void *arg); + +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + int + is_forward_secure)); + +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb) (SSL *ssl, + int is_forward_secure)); + +void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)); +void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg); +void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx); +int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size); + +void SSL_set_record_padding_callback(SSL *ssl, + size_t (*cb) (SSL *ssl, int type, + size_t len, void *arg)); +void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg); +void *SSL_get_record_padding_callback_arg(const SSL *ssl); +int SSL_set_block_padding(SSL *ssl, size_t block_size); + +int SSL_set_num_tickets(SSL *s, size_t num_tickets); +size_t SSL_get_num_tickets(const SSL *s); +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets); +size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_cache_hit(s) SSL_session_reused(s) +# endif + +__owur int SSL_session_reused(SSL *s); +__owur int SSL_is_server(const SSL *s); + +__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void); +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx); +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx); +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags); +__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, + unsigned int flags); +__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre); + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl); +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx); + +__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value); +__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv); +__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd); + +void SSL_add_ssl_module(void); +int SSL_config(SSL *s, const char *name); +int SSL_CTX_config(SSL_CTX *ctx, const char *name); + +# ifndef OPENSSL_NO_SSL_TRACE +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); +# endif + +# ifndef OPENSSL_NO_SOCK +int DTLSv1_listen(SSL *s, BIO_ADDR *client); +# endif + +# ifndef OPENSSL_NO_CT + +/* + * A callback for verifying that the received SCTs are sufficient. + * Expected to return 1 if they are sufficient, otherwise 0. + * May return a negative integer if an error occurs. + * A connection should be aborted if the SCTs are deemed insufficient. + */ +typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx, + const STACK_OF(SCT) *scts, void *arg); + +/* + * Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate + * the received SCTs. + * If the callback returns a non-positive result, the connection is terminated. + * Call this function before beginning a handshake. + * If a NULL |callback| is provided, SCT validation is disabled. + * |arg| is arbitrary userdata that will be passed to the callback whenever it + * is invoked. Ownership of |arg| remains with the caller. + * + * NOTE: A side-effect of setting a CT callback is that an OCSP stapled response + * will be requested. + */ +int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback, + void *arg); +int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx, + ssl_ct_validation_cb callback, + void *arg); +#define SSL_disable_ct(s) \ + ((void) SSL_set_validation_callback((s), NULL, NULL)) +#define SSL_CTX_disable_ct(ctx) \ + ((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL)) + +/* + * The validation type enumerates the available behaviours of the built-in SSL + * CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct(). + * The underlying callback is a static function in libssl. + */ +enum { + SSL_CT_VALIDATION_PERMISSIVE = 0, + SSL_CT_VALIDATION_STRICT +}; + +/* + * Enable CT by setting up a callback that implements one of the built-in + * validation variants. The SSL_CT_VALIDATION_PERMISSIVE variant always + * continues the handshake, the application can make appropriate decisions at + * handshake completion. The SSL_CT_VALIDATION_STRICT variant requires at + * least one valid SCT, or else handshake termination will be requested. The + * handshake may continue anyway if SSL_VERIFY_NONE is in effect. + */ +int SSL_enable_ct(SSL *s, int validation_mode); +int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode); + +/* + * Report whether a non-NULL callback is enabled. + */ +int SSL_ct_is_enabled(const SSL *s); +int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx); + +/* Gets the SCTs received from a connection */ +const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s); + +/* + * Loads the CT log list from the default location. + * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store, + * the log information loaded from this file will be appended to the + * CTLOG_STORE. + * Returns 1 on success, 0 otherwise. + */ +int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx); + +/* + * Loads the CT log list from the specified file path. + * If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store, + * the log information loaded from this file will be appended to the + * CTLOG_STORE. + * Returns 1 on success, 0 otherwise. + */ +int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path); + +/* + * Sets the CT log list used by all SSL connections created from this SSL_CTX. + * Ownership of the CTLOG_STORE is transferred to the SSL_CTX. + */ +void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs); + +/* + * Gets the CT log list used by all SSL connections created from this SSL_CTX. + * This will be NULL unless one of the following functions has been called: + * - SSL_CTX_set_default_ctlog_list_file + * - SSL_CTX_set_ctlog_list_file + * - SSL_CTX_set_ctlog_store + */ +const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx); + +# endif /* OPENSSL_NO_CT */ + +/* What the "other" parameter contains in security callback */ +/* Mask for type */ +# define SSL_SECOP_OTHER_TYPE 0xffff0000 +# define SSL_SECOP_OTHER_NONE 0 +# define SSL_SECOP_OTHER_CIPHER (1 << 16) +# define SSL_SECOP_OTHER_CURVE (2 << 16) +# define SSL_SECOP_OTHER_DH (3 << 16) +# define SSL_SECOP_OTHER_PKEY (4 << 16) +# define SSL_SECOP_OTHER_SIGALG (5 << 16) +# define SSL_SECOP_OTHER_CERT (6 << 16) + +/* Indicated operation refers to peer key or certificate */ +# define SSL_SECOP_PEER 0x1000 + +/* Values for "op" parameter in security callback */ + +/* Called to filter ciphers */ +/* Ciphers client supports */ +# define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER) +/* Cipher shared by client/server */ +# define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER) +/* Sanity check of cipher server selects */ +# define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER) +/* Curves supported by client */ +# define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE) +/* Curves shared by client/server */ +# define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE) +/* Sanity check of curve server selects */ +# define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE) +/* Temporary DH key */ +# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY) +/* SSL/TLS version */ +# define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE) +/* Session tickets */ +# define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE) +/* Supported signature algorithms sent to peer */ +# define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG) +/* Shared signature algorithm */ +# define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG) +/* Sanity check signature algorithm allowed */ +# define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG) +/* Used to get mask of supported public key signature algorithms */ +# define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG) +/* Use to see if compression is allowed */ +# define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE) +/* EE key in certificate */ +# define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT) +/* CA key in certificate */ +# define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT) +/* CA digest algorithm in certificate */ +# define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT) +/* Peer EE key in certificate */ +# define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) +/* Peer CA key in certificate */ +# define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) +/* Peer CA digest algorithm in certificate */ +# define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) + +void SSL_set_security_level(SSL *s, int level); +__owur int SSL_get_security_level(const SSL *s); +void SSL_set_security_callback(SSL *s, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)); +int (*SSL_get_security_callback(const SSL *s)) (const SSL *s, + const SSL_CTX *ctx, int op, + int bits, int nid, void *other, + void *ex); +void SSL_set0_security_ex_data(SSL *s, void *ex); +__owur void *SSL_get0_security_ex_data(const SSL *s); + +void SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx); +void SSL_CTX_set_security_callback(SSL_CTX *ctx, + int (*cb) (const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex)); +int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s, + const SSL_CTX *ctx, + int op, int bits, + int nid, + void *other, + void *ex); +void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex); +__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx); + +/* OPENSSL_INIT flag 0x010000 reserved for internal use */ +# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L +# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L + +# define OPENSSL_INIT_SSL_DEFAULT \ + (OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + +int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); + +# ifndef OPENSSL_NO_UNIT_TEST +__owur const struct openssl_ssl_test_functions *SSL_test_functions(void); +# endif + +__owur int SSL_free_buffers(SSL *ssl); +__owur int SSL_alloc_buffers(SSL *ssl); + +/* Status codes passed to the decrypt session ticket callback. Some of these + * are for internal use only and are never passed to the callback. */ +typedef int SSL_TICKET_STATUS; + +/* Support for ticket appdata */ +/* fatal error, malloc failure */ +# define SSL_TICKET_FATAL_ERR_MALLOC 0 +/* fatal error, either from parsing or decrypting the ticket */ +# define SSL_TICKET_FATAL_ERR_OTHER 1 +/* No ticket present */ +# define SSL_TICKET_NONE 2 +/* Empty ticket present */ +# define SSL_TICKET_EMPTY 3 +/* the ticket couldn't be decrypted */ +# define SSL_TICKET_NO_DECRYPT 4 +/* a ticket was successfully decrypted */ +# define SSL_TICKET_SUCCESS 5 +/* same as above but the ticket needs to be renewed */ +# define SSL_TICKET_SUCCESS_RENEW 6 + +/* Return codes for the decrypt session ticket callback */ +typedef int SSL_TICKET_RETURN; + +/* An error occurred */ +#define SSL_TICKET_RETURN_ABORT 0 +/* Do not use the ticket, do not send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_IGNORE 1 +/* Do not use the ticket, send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_IGNORE_RENEW 2 +/* Use the ticket, do not send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_USE 3 +/* Use the ticket, send a renewed ticket to the client */ +#define SSL_TICKET_RETURN_USE_RENEW 4 + +typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg); +typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_length, + SSL_TICKET_STATUS status, + void *arg); +int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx, + SSL_CTX_generate_session_ticket_fn gen_cb, + SSL_CTX_decrypt_session_ticket_fn dec_cb, + void *arg); +int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len); +int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len); + +extern const char SSL_version_str[]; + +typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us); + +void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb); + + +typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg); +void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx, + SSL_allow_early_data_cb_fn cb, + void *arg); +void SSL_set_allow_early_data_cb(SSL *s, + SSL_allow_early_data_cb_fn cb, + void *arg); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/ssl2.h b/thirdparty/user_include/openssl/ssl2.h new file mode 100755 index 0000000000000000000000000000000000000000..5321bd272cb795664aa0c51ef3abe942837ceced --- /dev/null +++ b/thirdparty/user_include/openssl/ssl2.h @@ -0,0 +1,24 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL2_H +# define HEADER_SSL2_H + +#ifdef __cplusplus +extern "C" { +#endif + +# define SSL2_VERSION 0x0002 + +# define SSL2_MT_CLIENT_HELLO 1 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/ssl3.h b/thirdparty/user_include/openssl/ssl3.h new file mode 100755 index 0000000000000000000000000000000000000000..8d01fcc487651f535db5f5da5d6c8c4e4f0e3580 --- /dev/null +++ b/thirdparty/user_include/openssl/ssl3.h @@ -0,0 +1,339 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSL3_H +# define HEADER_SSL3_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Signalling cipher suite value from RFC 5746 + * (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + */ +# define SSL3_CK_SCSV 0x030000FF + +/* + * Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00 + * (TLS_FALLBACK_SCSV) + */ +# define SSL3_CK_FALLBACK_SCSV 0x03005600 + +# define SSL3_CK_RSA_NULL_MD5 0x03000001 +# define SSL3_CK_RSA_NULL_SHA 0x03000002 +# define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +# define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +# define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +# define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +# define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +# define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +# define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +# define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +# define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +# define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +# define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +# define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +# define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +# define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +# define SSL3_CK_DHE_DSS_DES_40_CBC_SHA 0x03000011 +# define SSL3_CK_EDH_DSS_DES_40_CBC_SHA SSL3_CK_DHE_DSS_DES_40_CBC_SHA +# define SSL3_CK_DHE_DSS_DES_64_CBC_SHA 0x03000012 +# define SSL3_CK_EDH_DSS_DES_64_CBC_SHA SSL3_CK_DHE_DSS_DES_64_CBC_SHA +# define SSL3_CK_DHE_DSS_DES_192_CBC3_SHA 0x03000013 +# define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA SSL3_CK_DHE_DSS_DES_192_CBC3_SHA +# define SSL3_CK_DHE_RSA_DES_40_CBC_SHA 0x03000014 +# define SSL3_CK_EDH_RSA_DES_40_CBC_SHA SSL3_CK_DHE_RSA_DES_40_CBC_SHA +# define SSL3_CK_DHE_RSA_DES_64_CBC_SHA 0x03000015 +# define SSL3_CK_EDH_RSA_DES_64_CBC_SHA SSL3_CK_DHE_RSA_DES_64_CBC_SHA +# define SSL3_CK_DHE_RSA_DES_192_CBC3_SHA 0x03000016 +# define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA SSL3_CK_DHE_RSA_DES_192_CBC3_SHA + +# define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +# define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +# define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +# define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +# define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +/* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */ +# define SSL3_RFC_RSA_NULL_MD5 "TLS_RSA_WITH_NULL_MD5" +# define SSL3_RFC_RSA_NULL_SHA "TLS_RSA_WITH_NULL_SHA" +# define SSL3_RFC_RSA_DES_192_CBC3_SHA "TLS_RSA_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_DHE_DSS_DES_192_CBC3_SHA "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_DHE_RSA_DES_192_CBC3_SHA "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_ADH_DES_192_CBC_SHA "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" +# define SSL3_RFC_RSA_IDEA_128_SHA "TLS_RSA_WITH_IDEA_CBC_SHA" +# define SSL3_RFC_RSA_RC4_128_MD5 "TLS_RSA_WITH_RC4_128_MD5" +# define SSL3_RFC_RSA_RC4_128_SHA "TLS_RSA_WITH_RC4_128_SHA" +# define SSL3_RFC_ADH_RC4_128_MD5 "TLS_DH_anon_WITH_RC4_128_MD5" + +# define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +# define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +# define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +# define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +# define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +# define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +# define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_DHE_DSS_DES_40_CBC_SHA "EXP-DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_64_CBC_SHA "DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA "DHE-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DHE_RSA_DES_40_CBC_SHA "EXP-DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_64_CBC_SHA "DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA "DHE-RSA-DES-CBC3-SHA" + +/* + * This next block of six "EDH" labels is for backward compatibility with + * older versions of OpenSSL. New code should use the six "DHE" labels above + * instead: + */ +# define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +# define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +# define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +# define SSL3_SSL_SESSION_ID_LENGTH 32 +# define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +# define SSL3_MASTER_SECRET_SIZE 48 +# define SSL3_RANDOM_SIZE 32 +# define SSL3_SESSION_ID_SIZE 32 +# define SSL3_RT_HEADER_LENGTH 5 + +# define SSL3_HM_HEADER_LENGTH 4 + +# ifndef SSL3_ALIGN_PAYLOAD + /* + * Some will argue that this increases memory footprint, but it's not + * actually true. Point is that malloc has to return at least 64-bit aligned + * pointers, meaning that allocating 5 bytes wastes 3 bytes in either case. + * Suggested pre-gaping simply moves these wasted bytes from the end of + * allocated region to its front, but makes data payload aligned, which + * improves performance:-) + */ +# define SSL3_ALIGN_PAYLOAD 8 +# else +# if (SSL3_ALIGN_PAYLOAD&(SSL3_ALIGN_PAYLOAD-1))!=0 +# error "insane SSL3_ALIGN_PAYLOAD" +# undef SSL3_ALIGN_PAYLOAD +# endif +# endif + +/* + * This is the maximum MAC (digest) size used by the SSL library. Currently + * maximum of 20 is used by SHA1, but we reserve for future extension for + * 512-bit hashes. + */ + +# define SSL3_RT_MAX_MD_SIZE 64 + +/* + * Maximum block size used in all ciphersuites. Currently 16 for AES. + */ + +# define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +# define SSL3_RT_MAX_EXTRA (16384) + +/* Maximum plaintext length: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_PLAIN_LENGTH 16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +/* + * The standards give a maximum encryption overhead of 1024 bytes. In + * practice the value is lower than this. The overhead is the maximum number + * of padding bytes (256) plus the mac size. + */ +# define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) +# define SSL3_RT_MAX_TLS13_ENCRYPTED_OVERHEAD 256 + +/* + * OpenSSL currently only uses a padding length of at most one block so the + * send overhead is smaller. + */ + +# define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE) + +/* If compression isn't used don't include the compression overhead */ + +# ifdef OPENSSL_NO_COMP +# define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH +# else +# define SSL3_RT_MAX_COMPRESSED_LENGTH \ + (SSL3_RT_MAX_PLAIN_LENGTH+SSL3_RT_MAX_COMPRESSED_OVERHEAD) +# endif +# define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH) +# define SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_TLS13_ENCRYPTED_OVERHEAD) +# define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) + +# define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +# define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +# define SSL3_VERSION 0x0300 +# define SSL3_VERSION_MAJOR 0x03 +# define SSL3_VERSION_MINOR 0x00 + +# define SSL3_RT_CHANGE_CIPHER_SPEC 20 +# define SSL3_RT_ALERT 21 +# define SSL3_RT_HANDSHAKE 22 +# define SSL3_RT_APPLICATION_DATA 23 +# define DTLS1_RT_HEARTBEAT 24 + +/* Pseudo content types to indicate additional parameters */ +# define TLS1_RT_CRYPTO 0x1000 +# define TLS1_RT_CRYPTO_PREMASTER (TLS1_RT_CRYPTO | 0x1) +# define TLS1_RT_CRYPTO_CLIENT_RANDOM (TLS1_RT_CRYPTO | 0x2) +# define TLS1_RT_CRYPTO_SERVER_RANDOM (TLS1_RT_CRYPTO | 0x3) +# define TLS1_RT_CRYPTO_MASTER (TLS1_RT_CRYPTO | 0x4) + +# define TLS1_RT_CRYPTO_READ 0x0000 +# define TLS1_RT_CRYPTO_WRITE 0x0100 +# define TLS1_RT_CRYPTO_MAC (TLS1_RT_CRYPTO | 0x5) +# define TLS1_RT_CRYPTO_KEY (TLS1_RT_CRYPTO | 0x6) +# define TLS1_RT_CRYPTO_IV (TLS1_RT_CRYPTO | 0x7) +# define TLS1_RT_CRYPTO_FIXED_IV (TLS1_RT_CRYPTO | 0x8) + +/* Pseudo content types for SSL/TLS header info */ +# define SSL3_RT_HEADER 0x100 +# define SSL3_RT_INNER_CONTENT_TYPE 0x101 + +# define SSL3_AL_WARNING 1 +# define SSL3_AL_FATAL 2 + +# define SSL3_AD_CLOSE_NOTIFY 0 +# define SSL3_AD_UNEXPECTED_MESSAGE 10/* fatal */ +# define SSL3_AD_BAD_RECORD_MAC 20/* fatal */ +# define SSL3_AD_DECOMPRESSION_FAILURE 30/* fatal */ +# define SSL3_AD_HANDSHAKE_FAILURE 40/* fatal */ +# define SSL3_AD_NO_CERTIFICATE 41 +# define SSL3_AD_BAD_CERTIFICATE 42 +# define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +# define SSL3_AD_CERTIFICATE_REVOKED 44 +# define SSL3_AD_CERTIFICATE_EXPIRED 45 +# define SSL3_AD_CERTIFICATE_UNKNOWN 46 +# define SSL3_AD_ILLEGAL_PARAMETER 47/* fatal */ + +# define TLS1_HB_REQUEST 1 +# define TLS1_HB_RESPONSE 2 + + +# define SSL3_CT_RSA_SIGN 1 +# define SSL3_CT_DSS_SIGN 2 +# define SSL3_CT_RSA_FIXED_DH 3 +# define SSL3_CT_DSS_FIXED_DH 4 +# define SSL3_CT_RSA_EPHEMERAL_DH 5 +# define SSL3_CT_DSS_EPHEMERAL_DH 6 +# define SSL3_CT_FORTEZZA_DMS 20 +/* + * SSL3_CT_NUMBER is used to size arrays and it must be large enough to + * contain all of the cert types defined for *either* SSLv3 and TLSv1. + */ +# define SSL3_CT_NUMBER 10 + +# if defined(TLS_CT_NUMBER) +# if TLS_CT_NUMBER != SSL3_CT_NUMBER +# error "SSL/TLS CT_NUMBER values do not match" +# endif +# endif + +/* No longer used as of OpenSSL 1.1.1 */ +# define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 + +/* Removed from OpenSSL 1.1.0 */ +# define TLS1_FLAGS_TLS_PADDING_BUG 0x0 + +# define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 + +/* Set if we encrypt then mac instead of usual mac then encrypt */ +# define TLS1_FLAGS_ENCRYPT_THEN_MAC_READ 0x0100 +# define TLS1_FLAGS_ENCRYPT_THEN_MAC TLS1_FLAGS_ENCRYPT_THEN_MAC_READ + +/* Set if extended master secret extension received from peer */ +# define TLS1_FLAGS_RECEIVED_EXTMS 0x0200 + +# define TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE 0x0400 + +# define TLS1_FLAGS_STATELESS 0x0800 + +# define SSL3_MT_HELLO_REQUEST 0 +# define SSL3_MT_CLIENT_HELLO 1 +# define SSL3_MT_SERVER_HELLO 2 +# define SSL3_MT_NEWSESSION_TICKET 4 +# define SSL3_MT_END_OF_EARLY_DATA 5 +# define SSL3_MT_ENCRYPTED_EXTENSIONS 8 +# define SSL3_MT_CERTIFICATE 11 +# define SSL3_MT_SERVER_KEY_EXCHANGE 12 +# define SSL3_MT_CERTIFICATE_REQUEST 13 +# define SSL3_MT_SERVER_DONE 14 +# define SSL3_MT_CERTIFICATE_VERIFY 15 +# define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +# define SSL3_MT_FINISHED 20 +# define SSL3_MT_CERTIFICATE_URL 21 +# define SSL3_MT_CERTIFICATE_STATUS 22 +# define SSL3_MT_SUPPLEMENTAL_DATA 23 +# define SSL3_MT_KEY_UPDATE 24 +# ifndef OPENSSL_NO_NEXTPROTONEG +# define SSL3_MT_NEXT_PROTO 67 +# endif +# define SSL3_MT_MESSAGE_HASH 254 +# define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +/* Dummy message type for handling CCS like a normal handshake message */ +# define SSL3_MT_CHANGE_CIPHER_SPEC 0x0101 + +# define SSL3_MT_CCS 1 + +/* These are used when changing over to a new cipher */ +# define SSL3_CC_READ 0x001 +# define SSL3_CC_WRITE 0x002 +# define SSL3_CC_CLIENT 0x010 +# define SSL3_CC_SERVER 0x020 +# define SSL3_CC_EARLY 0x040 +# define SSL3_CC_HANDSHAKE 0x080 +# define SSL3_CC_APPLICATION 0x100 +# define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE) +# define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/sslerr.h b/thirdparty/user_include/openssl/sslerr.h new file mode 100755 index 0000000000000000000000000000000000000000..a50a075b42ec2307eb623d9345fbbcab778fbcef --- /dev/null +++ b/thirdparty/user_include/openssl/sslerr.h @@ -0,0 +1,768 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSLERR_H +# define HEADER_SSLERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_SSL_strings(void); + +/* + * SSL function codes. + */ +# define SSL_F_ADD_CLIENT_KEY_SHARE_EXT 438 +# define SSL_F_ADD_KEY_SHARE 512 +# define SSL_F_BYTES_TO_CIPHER_LIST 519 +# define SSL_F_CHECK_SUITEB_CIPHER_LIST 331 +# define SSL_F_CIPHERSUITE_CB 622 +# define SSL_F_CONSTRUCT_CA_NAMES 552 +# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS 553 +# define SSL_F_CONSTRUCT_STATEFUL_TICKET 636 +# define SSL_F_CONSTRUCT_STATELESS_TICKET 637 +# define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH 539 +# define SSL_F_CREATE_TICKET_PREQUEL 638 +# define SSL_F_CT_MOVE_SCTS 345 +# define SSL_F_CT_STRICT 349 +# define SSL_F_CUSTOM_EXT_ADD 554 +# define SSL_F_CUSTOM_EXT_PARSE 555 +# define SSL_F_D2I_SSL_SESSION 103 +# define SSL_F_DANE_CTX_ENABLE 347 +# define SSL_F_DANE_MTYPE_SET 393 +# define SSL_F_DANE_TLSA_ADD 394 +# define SSL_F_DERIVE_SECRET_KEY_AND_IV 514 +# define SSL_F_DO_DTLS1_WRITE 245 +# define SSL_F_DO_SSL3_WRITE 104 +# define SSL_F_DTLS1_BUFFER_RECORD 247 +# define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 318 +# define SSL_F_DTLS1_HEARTBEAT 305 +# define SSL_F_DTLS1_HM_FRAGMENT_NEW 623 +# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424 +# define SSL_F_DTLS1_PROCESS_RECORD 257 +# define SSL_F_DTLS1_READ_BYTES 258 +# define SSL_F_DTLS1_READ_FAILED 339 +# define SSL_F_DTLS1_RETRANSMIT_MESSAGE 390 +# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268 +# define SSL_F_DTLS1_WRITE_BYTES 545 +# define SSL_F_DTLSV1_LISTEN 350 +# define SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC 371 +# define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST 385 +# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370 +# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 386 +# define SSL_F_DTLS_RECORD_LAYER_NEW 635 +# define SSL_F_DTLS_WAIT_FOR_DRY 592 +# define SSL_F_EARLY_DATA_COUNT_OK 532 +# define SSL_F_FINAL_EARLY_DATA 556 +# define SSL_F_FINAL_EC_PT_FORMATS 485 +# define SSL_F_FINAL_EMS 486 +# define SSL_F_FINAL_KEY_SHARE 503 +# define SSL_F_FINAL_MAXFRAGMENTLEN 557 +# define SSL_F_FINAL_RENEGOTIATE 483 +# define SSL_F_FINAL_SERVER_NAME 558 +# define SSL_F_FINAL_SIG_ALGS 497 +# define SSL_F_GET_CERT_VERIFY_TBS_DATA 588 +# define SSL_F_NSS_KEYLOG_INT 500 +# define SSL_F_OPENSSL_INIT_SSL 342 +# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION 436 +# define SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION 598 +# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE 430 +# define SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE 593 +# define SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE 594 +# define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION 417 +# define SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION 599 +# define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION 437 +# define SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION 600 +# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE 431 +# define SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE 601 +# define SSL_F_OSSL_STATEM_SERVER_POST_WORK 602 +# define SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE 603 +# define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION 418 +# define SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION 604 +# define SSL_F_PARSE_CA_NAMES 541 +# define SSL_F_PITEM_NEW 624 +# define SSL_F_PQUEUE_NEW 625 +# define SSL_F_PROCESS_KEY_SHARE_EXT 439 +# define SSL_F_READ_STATE_MACHINE 352 +# define SSL_F_SET_CLIENT_CIPHERSUITE 540 +# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 595 +# define SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET 589 +# define SSL_F_SRP_VERIFY_SERVER_PARAM 596 +# define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +# define SSL_F_SSL3_CTRL 213 +# define SSL_F_SSL3_CTX_CTRL 133 +# define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293 +# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292 +# define SSL_F_SSL3_ENC 608 +# define SSL_F_SSL3_FINAL_FINISH_MAC 285 +# define SSL_F_SSL3_FINISH_MAC 587 +# define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 +# define SSL_F_SSL3_GENERATE_MASTER_SECRET 388 +# define SSL_F_SSL3_GET_RECORD 143 +# define SSL_F_SSL3_INIT_FINISHED_MAC 397 +# define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +# define SSL_F_SSL3_READ_BYTES 148 +# define SSL_F_SSL3_READ_N 149 +# define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +# define SSL_F_SSL3_SETUP_READ_BUFFER 156 +# define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 +# define SSL_F_SSL3_WRITE_BYTES 158 +# define SSL_F_SSL3_WRITE_PENDING 159 +# define SSL_F_SSL_ADD_CERT_CHAIN 316 +# define SSL_F_SSL_ADD_CERT_TO_BUF 319 +# define SSL_F_SSL_ADD_CERT_TO_WPACKET 493 +# define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 +# define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 +# define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 +# define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +# define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 +# define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 299 +# define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278 +# define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308 +# define SSL_F_SSL_BAD_METHOD 160 +# define SSL_F_SSL_BUILD_CERT_CHAIN 332 +# define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +# define SSL_F_SSL_CACHE_CIPHERLIST 520 +# define SSL_F_SSL_CERT_ADD0_CHAIN_CERT 346 +# define SSL_F_SSL_CERT_DUP 221 +# define SSL_F_SSL_CERT_NEW 162 +# define SSL_F_SSL_CERT_SET0_CHAIN 340 +# define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +# define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 280 +# define SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO 606 +# define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 279 +# define SSL_F_SSL_CHOOSE_CLIENT_VERSION 607 +# define SSL_F_SSL_CIPHER_DESCRIPTION 626 +# define SSL_F_SSL_CIPHER_LIST_TO_BYTES 425 +# define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +# define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +# define SSL_F_SSL_CLEAR 164 +# define SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT 627 +# define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +# define SSL_F_SSL_CONF_CMD 334 +# define SSL_F_SSL_CREATE_CIPHER_LIST 166 +# define SSL_F_SSL_CTRL 232 +# define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +# define SSL_F_SSL_CTX_ENABLE_CT 398 +# define SSL_F_SSL_CTX_MAKE_PROFILES 309 +# define SSL_F_SSL_CTX_NEW 169 +# define SSL_F_SSL_CTX_SET_ALPN_PROTOS 343 +# define SSL_F_SSL_CTX_SET_CIPHER_LIST 269 +# define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 290 +# define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 396 +# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +# define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +# define SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH 551 +# define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +# define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +# define SSL_F_SSL_CTX_USE_SERVERINFO 336 +# define SSL_F_SSL_CTX_USE_SERVERINFO_EX 543 +# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 337 +# define SSL_F_SSL_DANE_DUP 403 +# define SSL_F_SSL_DANE_ENABLE 395 +# define SSL_F_SSL_DERIVE 590 +# define SSL_F_SSL_DO_CONFIG 391 +# define SSL_F_SSL_DO_HANDSHAKE 180 +# define SSL_F_SSL_DUP_CA_LIST 408 +# define SSL_F_SSL_ENABLE_CT 402 +# define SSL_F_SSL_GENERATE_PKEY_GROUP 559 +# define SSL_F_SSL_GENERATE_SESSION_ID 547 +# define SSL_F_SSL_GET_NEW_SESSION 181 +# define SSL_F_SSL_GET_PREV_SESSION 217 +# define SSL_F_SSL_GET_SERVER_CERT_INDEX 322 +# define SSL_F_SSL_GET_SIGN_PKEY 183 +# define SSL_F_SSL_HANDSHAKE_HASH 560 +# define SSL_F_SSL_INIT_WBIO_BUFFER 184 +# define SSL_F_SSL_KEY_UPDATE 515 +# define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +# define SSL_F_SSL_LOG_MASTER_SECRET 498 +# define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE 499 +# define SSL_F_SSL_MODULE_INIT 392 +# define SSL_F_SSL_NEW 186 +# define SSL_F_SSL_NEXT_PROTO_VALIDATE 565 +# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 300 +# define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 302 +# define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 310 +# define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 301 +# define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 303 +# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311 +# define SSL_F_SSL_PEEK 270 +# define SSL_F_SSL_PEEK_EX 432 +# define SSL_F_SSL_PEEK_INTERNAL 522 +# define SSL_F_SSL_READ 223 +# define SSL_F_SSL_READ_EARLY_DATA 529 +# define SSL_F_SSL_READ_EX 434 +# define SSL_F_SSL_READ_INTERNAL 523 +# define SSL_F_SSL_RENEGOTIATE 516 +# define SSL_F_SSL_RENEGOTIATE_ABBREVIATED 546 +# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320 +# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321 +# define SSL_F_SSL_SESSION_DUP 348 +# define SSL_F_SSL_SESSION_NEW 189 +# define SSL_F_SSL_SESSION_PRINT_FP 190 +# define SSL_F_SSL_SESSION_SET1_ID 423 +# define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312 +# define SSL_F_SSL_SET_ALPN_PROTOS 344 +# define SSL_F_SSL_SET_CERT 191 +# define SSL_F_SSL_SET_CERT_AND_KEY 621 +# define SSL_F_SSL_SET_CIPHER_LIST 271 +# define SSL_F_SSL_SET_CT_VALIDATION_CALLBACK 399 +# define SSL_F_SSL_SET_FD 192 +# define SSL_F_SSL_SET_PKEY 193 +# define SSL_F_SSL_SET_RFD 194 +# define SSL_F_SSL_SET_SESSION 195 +# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +# define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 +# define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 550 +# define SSL_F_SSL_SET_WFD 196 +# define SSL_F_SSL_SHUTDOWN 224 +# define SSL_F_SSL_SRP_CTX_INIT 313 +# define SSL_F_SSL_START_ASYNC_JOB 389 +# define SSL_F_SSL_UNDEFINED_FUNCTION 197 +# define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244 +# define SSL_F_SSL_USE_CERTIFICATE 198 +# define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +# define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +# define SSL_F_SSL_USE_PRIVATEKEY 201 +# define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +# define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +# define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273 +# define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +# define SSL_F_SSL_VALIDATE_CT 400 +# define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +# define SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE 616 +# define SSL_F_SSL_WRITE 208 +# define SSL_F_SSL_WRITE_EARLY_DATA 526 +# define SSL_F_SSL_WRITE_EARLY_FINISH 527 +# define SSL_F_SSL_WRITE_EX 433 +# define SSL_F_SSL_WRITE_INTERNAL 524 +# define SSL_F_STATE_MACHINE 353 +# define SSL_F_TLS12_CHECK_PEER_SIGALG 333 +# define SSL_F_TLS12_COPY_SIGALGS 533 +# define SSL_F_TLS13_CHANGE_CIPHER_STATE 440 +# define SSL_F_TLS13_ENC 609 +# define SSL_F_TLS13_FINAL_FINISH_MAC 605 +# define SSL_F_TLS13_GENERATE_SECRET 591 +# define SSL_F_TLS13_HKDF_EXPAND 561 +# define SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA 617 +# define SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA 618 +# define SSL_F_TLS13_SETUP_KEY_BLOCK 441 +# define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +# define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS 341 +# define SSL_F_TLS1_ENC 401 +# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 +# define SSL_F_TLS1_GET_CURVELIST 338 +# define SSL_F_TLS1_PRF 284 +# define SSL_F_TLS1_SAVE_U16 628 +# define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +# define SSL_F_TLS1_SET_GROUPS 629 +# define SSL_F_TLS1_SET_RAW_SIGALGS 630 +# define SSL_F_TLS1_SET_SERVER_SIGALGS 335 +# define SSL_F_TLS1_SET_SHARED_SIGALGS 631 +# define SSL_F_TLS1_SET_SIGALGS 632 +# define SSL_F_TLS_CHOOSE_SIGALG 513 +# define SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK 354 +# define SSL_F_TLS_COLLECT_EXTENSIONS 435 +# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES 542 +# define SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST 372 +# define SSL_F_TLS_CONSTRUCT_CERT_STATUS 429 +# define SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY 494 +# define SSL_F_TLS_CONSTRUCT_CERT_VERIFY 496 +# define SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC 427 +# define SSL_F_TLS_CONSTRUCT_CKE_DHE 404 +# define SSL_F_TLS_CONSTRUCT_CKE_ECDHE 405 +# define SSL_F_TLS_CONSTRUCT_CKE_GOST 406 +# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407 +# define SSL_F_TLS_CONSTRUCT_CKE_RSA 409 +# define SSL_F_TLS_CONSTRUCT_CKE_SRP 410 +# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 484 +# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 487 +# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 488 +# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 489 +# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN 466 +# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 355 +# define SSL_F_TLS_CONSTRUCT_CTOS_COOKIE 535 +# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 530 +# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 467 +# define SSL_F_TLS_CONSTRUCT_CTOS_EMS 468 +# define SSL_F_TLS_CONSTRUCT_CTOS_ETM 469 +# define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 356 +# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 357 +# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470 +# define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 549 +# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471 +# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472 +# define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 619 +# define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501 +# define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509 +# define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473 +# define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474 +# define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 475 +# define SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET 476 +# define SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS 477 +# define SSL_F_TLS_CONSTRUCT_CTOS_SRP 478 +# define SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST 479 +# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS 480 +# define SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS 481 +# define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 482 +# define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 358 +# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443 +# define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 536 +# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447 +# define SSL_F_TLS_CONSTRUCT_FINISHED 359 +# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 373 +# define SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST 510 +# define SSL_F_TLS_CONSTRUCT_KEY_UPDATE 517 +# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET 428 +# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO 426 +# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE 490 +# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO 491 +# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 492 +# define SSL_F_TLS_CONSTRUCT_STOC_ALPN 451 +# define SSL_F_TLS_CONSTRUCT_STOC_CERTIFICATE 374 +# define SSL_F_TLS_CONSTRUCT_STOC_COOKIE 613 +# define SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG 452 +# define SSL_F_TLS_CONSTRUCT_STOC_DONE 375 +# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA 531 +# define SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA_INFO 525 +# define SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS 453 +# define SSL_F_TLS_CONSTRUCT_STOC_EMS 454 +# define SSL_F_TLS_CONSTRUCT_STOC_ETM 455 +# define SSL_F_TLS_CONSTRUCT_STOC_HELLO 376 +# define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 377 +# define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 456 +# define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 548 +# define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457 +# define SSL_F_TLS_CONSTRUCT_STOC_PSK 504 +# define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458 +# define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 459 +# define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 460 +# define SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST 461 +# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS 544 +# define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS 611 +# define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP 462 +# define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 521 +# define SSL_F_TLS_FINISH_HANDSHAKE 597 +# define SSL_F_TLS_GET_MESSAGE_BODY 351 +# define SSL_F_TLS_GET_MESSAGE_HEADER 387 +# define SSL_F_TLS_HANDLE_ALPN 562 +# define SSL_F_TLS_HANDLE_STATUS_REQUEST 563 +# define SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES 566 +# define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT 449 +# define SSL_F_TLS_PARSE_CTOS_ALPN 567 +# define SSL_F_TLS_PARSE_CTOS_COOKIE 614 +# define SSL_F_TLS_PARSE_CTOS_EARLY_DATA 568 +# define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS 569 +# define SSL_F_TLS_PARSE_CTOS_EMS 570 +# define SSL_F_TLS_PARSE_CTOS_KEY_SHARE 463 +# define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN 571 +# define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 620 +# define SSL_F_TLS_PARSE_CTOS_PSK 505 +# define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572 +# define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464 +# define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 573 +# define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET 574 +# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS 575 +# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT 615 +# define SSL_F_TLS_PARSE_CTOS_SRP 576 +# define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST 577 +# define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS 578 +# define SSL_F_TLS_PARSE_CTOS_USE_SRTP 465 +# define SSL_F_TLS_PARSE_STOC_ALPN 579 +# define SSL_F_TLS_PARSE_STOC_COOKIE 534 +# define SSL_F_TLS_PARSE_STOC_EARLY_DATA 538 +# define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO 528 +# define SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS 580 +# define SSL_F_TLS_PARSE_STOC_KEY_SHARE 445 +# define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN 581 +# define SSL_F_TLS_PARSE_STOC_NPN 582 +# define SSL_F_TLS_PARSE_STOC_PSK 502 +# define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 448 +# define SSL_F_TLS_PARSE_STOC_SCT 564 +# define SSL_F_TLS_PARSE_STOC_SERVER_NAME 583 +# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET 584 +# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST 585 +# define SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS 612 +# define SSL_F_TLS_PARSE_STOC_USE_SRTP 446 +# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378 +# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384 +# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360 +# define SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST 610 +# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 361 +# define SSL_F_TLS_PROCESS_CERT_STATUS 362 +# define SSL_F_TLS_PROCESS_CERT_STATUS_BODY 495 +# define SSL_F_TLS_PROCESS_CERT_VERIFY 379 +# define SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC 363 +# define SSL_F_TLS_PROCESS_CKE_DHE 411 +# define SSL_F_TLS_PROCESS_CKE_ECDHE 412 +# define SSL_F_TLS_PROCESS_CKE_GOST 413 +# define SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE 414 +# define SSL_F_TLS_PROCESS_CKE_RSA 415 +# define SSL_F_TLS_PROCESS_CKE_SRP 416 +# define SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE 380 +# define SSL_F_TLS_PROCESS_CLIENT_HELLO 381 +# define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 382 +# define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 444 +# define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 537 +# define SSL_F_TLS_PROCESS_FINISHED 364 +# define SSL_F_TLS_PROCESS_HELLO_REQ 507 +# define SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST 511 +# define SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT 442 +# define SSL_F_TLS_PROCESS_KEY_EXCHANGE 365 +# define SSL_F_TLS_PROCESS_KEY_UPDATE 518 +# define SSL_F_TLS_PROCESS_NEW_SESSION_TICKET 366 +# define SSL_F_TLS_PROCESS_NEXT_PROTO 383 +# define SSL_F_TLS_PROCESS_SERVER_CERTIFICATE 367 +# define SSL_F_TLS_PROCESS_SERVER_DONE 368 +# define SSL_F_TLS_PROCESS_SERVER_HELLO 369 +# define SSL_F_TLS_PROCESS_SKE_DHE 419 +# define SSL_F_TLS_PROCESS_SKE_ECDHE 420 +# define SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE 421 +# define SSL_F_TLS_PROCESS_SKE_SRP 422 +# define SSL_F_TLS_PSK_DO_BINDER 506 +# define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT 450 +# define SSL_F_TLS_SETUP_HANDSHAKE 508 +# define SSL_F_USE_CERTIFICATE_CHAIN_FILE 220 +# define SSL_F_WPACKET_INTERN_INIT_LEN 633 +# define SSL_F_WPACKET_START_SUB_PACKET_LEN__ 634 +# define SSL_F_WRITE_STATE_MACHINE 586 + +/* + * SSL reason codes. + */ +# define SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY 291 +# define SSL_R_APP_DATA_IN_HANDSHAKE 100 +# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 +# define SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE 143 +# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158 +# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +# define SSL_R_BAD_CIPHER 186 +# define SSL_R_BAD_DATA 390 +# define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +# define SSL_R_BAD_DECOMPRESSION 107 +# define SSL_R_BAD_DH_VALUE 102 +# define SSL_R_BAD_DIGEST_LENGTH 111 +# define SSL_R_BAD_EARLY_DATA 233 +# define SSL_R_BAD_ECC_CERT 304 +# define SSL_R_BAD_ECPOINT 306 +# define SSL_R_BAD_EXTENSION 110 +# define SSL_R_BAD_HANDSHAKE_LENGTH 332 +# define SSL_R_BAD_HANDSHAKE_STATE 236 +# define SSL_R_BAD_HELLO_REQUEST 105 +# define SSL_R_BAD_HRR_VERSION 263 +# define SSL_R_BAD_KEY_SHARE 108 +# define SSL_R_BAD_KEY_UPDATE 122 +# define SSL_R_BAD_LEGACY_VERSION 292 +# define SSL_R_BAD_LENGTH 271 +# define SSL_R_BAD_PACKET 240 +# define SSL_R_BAD_PACKET_LENGTH 115 +# define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116 +# define SSL_R_BAD_PSK 219 +# define SSL_R_BAD_PSK_IDENTITY 114 +# define SSL_R_BAD_RECORD_TYPE 443 +# define SSL_R_BAD_RSA_ENCRYPT 119 +# define SSL_R_BAD_SIGNATURE 123 +# define SSL_R_BAD_SRP_A_LENGTH 347 +# define SSL_R_BAD_SRP_PARAMETERS 371 +# define SSL_R_BAD_SRTP_MKI_VALUE 352 +# define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 353 +# define SSL_R_BAD_SSL_FILETYPE 124 +# define SSL_R_BAD_VALUE 384 +# define SSL_R_BAD_WRITE_RETRY 127 +# define SSL_R_BINDER_DOES_NOT_VERIFY 253 +# define SSL_R_BIO_NOT_SET 128 +# define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129 +# define SSL_R_BN_LIB 130 +# define SSL_R_CALLBACK_FAILED 234 +# define SSL_R_CANNOT_CHANGE_CIPHER 109 +# define SSL_R_CA_DN_LENGTH_MISMATCH 131 +# define SSL_R_CA_KEY_TOO_SMALL 397 +# define SSL_R_CA_MD_TOO_WEAK 398 +# define SSL_R_CCS_RECEIVED_EARLY 133 +# define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +# define SSL_R_CERT_CB_ERROR 377 +# define SSL_R_CERT_LENGTH_MISMATCH 135 +# define SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED 218 +# define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 +# define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138 +# define SSL_R_CLIENTHELLO_TLSEXT 226 +# define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 +# define SSL_R_COMPRESSION_DISABLED 343 +# define SSL_R_COMPRESSION_FAILURE 141 +# define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307 +# define SSL_R_COMPRESSION_LIBRARY_ERROR 142 +# define SSL_R_CONNECTION_TYPE_NOT_SET 144 +# define SSL_R_CONTEXT_NOT_DANE_ENABLED 167 +# define SSL_R_COOKIE_GEN_CALLBACK_FAILURE 400 +# define SSL_R_COOKIE_MISMATCH 308 +# define SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED 206 +# define SSL_R_DANE_ALREADY_ENABLED 172 +# define SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL 173 +# define SSL_R_DANE_NOT_ENABLED 175 +# define SSL_R_DANE_TLSA_BAD_CERTIFICATE 180 +# define SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE 184 +# define SSL_R_DANE_TLSA_BAD_DATA_LENGTH 189 +# define SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH 192 +# define SSL_R_DANE_TLSA_BAD_MATCHING_TYPE 200 +# define SSL_R_DANE_TLSA_BAD_PUBLIC_KEY 201 +# define SSL_R_DANE_TLSA_BAD_SELECTOR 202 +# define SSL_R_DANE_TLSA_NULL_DATA 203 +# define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 +# define SSL_R_DATA_LENGTH_TOO_LONG 146 +# define SSL_R_DECRYPTION_FAILED 147 +# define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +# define SSL_R_DH_KEY_TOO_SMALL 394 +# define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 +# define SSL_R_DIGEST_CHECK_FAILED 149 +# define SSL_R_DTLS_MESSAGE_TOO_BIG 334 +# define SSL_R_DUPLICATE_COMPRESSION_ID 309 +# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 +# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374 +# define SSL_R_EE_KEY_TOO_SMALL 399 +# define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 +# define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +# define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 +# define SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN 204 +# define SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE 194 +# define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +# define SSL_R_EXTENSION_NOT_RECEIVED 279 +# define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +# define SSL_R_EXT_LENGTH_MISMATCH 163 +# define SSL_R_FAILED_TO_INIT_ASYNC 405 +# define SSL_R_FRAGMENTED_CLIENT_HELLO 401 +# define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 +# define SSL_R_HTTPS_PROXY_REQUEST 155 +# define SSL_R_HTTP_REQUEST 156 +# define SSL_R_ILLEGAL_POINT_COMPRESSION 162 +# define SSL_R_ILLEGAL_SUITEB_DIGEST 380 +# define SSL_R_INAPPROPRIATE_FALLBACK 373 +# define SSL_R_INCONSISTENT_COMPRESSION 340 +# define SSL_R_INCONSISTENT_EARLY_DATA_ALPN 222 +# define SSL_R_INCONSISTENT_EARLY_DATA_SNI 231 +# define SSL_R_INCONSISTENT_EXTMS 104 +# define SSL_R_INSUFFICIENT_SECURITY 241 +# define SSL_R_INVALID_ALERT 205 +# define SSL_R_INVALID_CCS_MESSAGE 260 +# define SSL_R_INVALID_CERTIFICATE_OR_ALG 238 +# define SSL_R_INVALID_COMMAND 280 +# define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +# define SSL_R_INVALID_CONFIG 283 +# define SSL_R_INVALID_CONFIGURATION_NAME 113 +# define SSL_R_INVALID_CONTEXT 282 +# define SSL_R_INVALID_CT_VALIDATION_TYPE 212 +# define SSL_R_INVALID_KEY_UPDATE_TYPE 120 +# define SSL_R_INVALID_MAX_EARLY_DATA 174 +# define SSL_R_INVALID_NULL_CMD_NAME 385 +# define SSL_R_INVALID_SEQUENCE_NUMBER 402 +# define SSL_R_INVALID_SERVERINFO_DATA 388 +# define SSL_R_INVALID_SESSION_ID 999 +# define SSL_R_INVALID_SRP_USERNAME 357 +# define SSL_R_INVALID_STATUS_RESPONSE 328 +# define SSL_R_INVALID_TICKET_KEYS_LENGTH 325 +# define SSL_R_LENGTH_MISMATCH 159 +# define SSL_R_LENGTH_TOO_LONG 404 +# define SSL_R_LENGTH_TOO_SHORT 160 +# define SSL_R_LIBRARY_BUG 274 +# define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +# define SSL_R_MISSING_DSA_SIGNING_CERT 165 +# define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 +# define SSL_R_MISSING_FATAL 256 +# define SSL_R_MISSING_PARAMETERS 290 +# define SSL_R_MISSING_RSA_CERTIFICATE 168 +# define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 +# define SSL_R_MISSING_RSA_SIGNING_CERT 170 +# define SSL_R_MISSING_SIGALGS_EXTENSION 112 +# define SSL_R_MISSING_SIGNING_CERT 221 +# define SSL_R_MISSING_SRP_PARAM 358 +# define SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION 209 +# define SSL_R_MISSING_TMP_DH_KEY 171 +# define SSL_R_MISSING_TMP_ECDH_KEY 311 +# define SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA 293 +# define SSL_R_NOT_ON_RECORD_BOUNDARY 182 +# define SSL_R_NOT_REPLACING_CERTIFICATE 289 +# define SSL_R_NOT_SERVER 284 +# define SSL_R_NO_APPLICATION_PROTOCOL 235 +# define SSL_R_NO_CERTIFICATES_RETURNED 176 +# define SSL_R_NO_CERTIFICATE_ASSIGNED 177 +# define SSL_R_NO_CERTIFICATE_SET 179 +# define SSL_R_NO_CHANGE_FOLLOWING_HRR 214 +# define SSL_R_NO_CIPHERS_AVAILABLE 181 +# define SSL_R_NO_CIPHERS_SPECIFIED 183 +# define SSL_R_NO_CIPHER_MATCH 185 +# define SSL_R_NO_CLIENT_CERT_METHOD 331 +# define SSL_R_NO_COMPRESSION_SPECIFIED 187 +# define SSL_R_NO_COOKIE_CALLBACK_SET 287 +# define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330 +# define SSL_R_NO_METHOD_SPECIFIED 188 +# define SSL_R_NO_PEM_EXTENSIONS 389 +# define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +# define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +# define SSL_R_NO_RENEGOTIATION 339 +# define SSL_R_NO_REQUIRED_DIGEST 324 +# define SSL_R_NO_SHARED_CIPHER 193 +# define SSL_R_NO_SHARED_GROUPS 410 +# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376 +# define SSL_R_NO_SRTP_PROFILES 359 +# define SSL_R_NO_SUITABLE_KEY_SHARE 101 +# define SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM 118 +# define SSL_R_NO_VALID_SCTS 216 +# define SSL_R_NO_VERIFY_COOKIE_CALLBACK 403 +# define SSL_R_NULL_SSL_CTX 195 +# define SSL_R_NULL_SSL_METHOD_PASSED 196 +# define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +# define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +# define SSL_R_OVERFLOW_ERROR 237 +# define SSL_R_PACKET_LENGTH_TOO_LONG 198 +# define SSL_R_PARSE_TLSEXT 227 +# define SSL_R_PATH_TOO_LONG 270 +# define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +# define SSL_R_PEM_NAME_BAD_PREFIX 391 +# define SSL_R_PEM_NAME_TOO_SHORT 392 +# define SSL_R_PIPELINE_FAILURE 406 +# define SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR 278 +# define SSL_R_PRIVATE_KEY_MISMATCH 288 +# define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +# define SSL_R_PSK_IDENTITY_NOT_FOUND 223 +# define SSL_R_PSK_NO_CLIENT_CB 224 +# define SSL_R_PSK_NO_SERVER_CB 225 +# define SSL_R_READ_BIO_NOT_SET 211 +# define SSL_R_READ_TIMEOUT_EXPIRED 312 +# define SSL_R_RECORD_LENGTH_MISMATCH 213 +# define SSL_R_RECORD_TOO_SMALL 298 +# define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335 +# define SSL_R_RENEGOTIATION_ENCODING_ERR 336 +# define SSL_R_RENEGOTIATION_MISMATCH 337 +# define SSL_R_REQUEST_PENDING 285 +# define SSL_R_REQUEST_SENT 286 +# define SSL_R_REQUIRED_CIPHER_MISSING 215 +# define SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING 342 +# define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 345 +# define SSL_R_SCT_VERIFICATION_FAILED 208 +# define SSL_R_SERVERHELLO_TLSEXT 275 +# define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +# define SSL_R_SHUTDOWN_WHILE_IN_INIT 407 +# define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360 +# define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +# define SSL_R_SRP_A_CALC 361 +# define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 +# define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 +# define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 +# define SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH 232 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320 +# define SSL_R_SSL3_SESSION_ID_TOO_LONG 300 +# define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +# define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +# define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +# define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +# define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +# define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +# define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +# define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +# define SSL_R_SSL_COMMAND_SECTION_EMPTY 117 +# define SSL_R_SSL_COMMAND_SECTION_NOT_FOUND 125 +# define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +# define SSL_R_SSL_HANDSHAKE_FAILURE 229 +# define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +# define SSL_R_SSL_NEGATIVE_LENGTH 372 +# define SSL_R_SSL_SECTION_EMPTY 126 +# define SSL_R_SSL_SECTION_NOT_FOUND 136 +# define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301 +# define SSL_R_SSL_SESSION_ID_CONFLICT 302 +# define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +# define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303 +# define SSL_R_SSL_SESSION_ID_TOO_LONG 408 +# define SSL_R_SSL_SESSION_VERSION_MISMATCH 210 +# define SSL_R_STILL_IN_INIT 121 +# define SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED 1116 +# define SSL_R_TLSV13_ALERT_MISSING_EXTENSION 1109 +# define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +# define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +# define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +# define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +# define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +# define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +# define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +# define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +# define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +# define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +# define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +# define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +# define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +# define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +# define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +# define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +# define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +# define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 +# define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT 365 +# define SSL_R_TLS_HEARTBEAT_PENDING 366 +# define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367 +# define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157 +# define SSL_R_TOO_MANY_KEY_UPDATES 132 +# define SSL_R_TOO_MANY_WARN_ALERTS 409 +# define SSL_R_TOO_MUCH_EARLY_DATA 164 +# define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314 +# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +# define SSL_R_UNEXPECTED_CCS_MESSAGE 262 +# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178 +# define SSL_R_UNEXPECTED_MESSAGE 244 +# define SSL_R_UNEXPECTED_RECORD 245 +# define SSL_R_UNINITIALIZED 276 +# define SSL_R_UNKNOWN_ALERT_TYPE 246 +# define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +# define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +# define SSL_R_UNKNOWN_CIPHER_TYPE 249 +# define SSL_R_UNKNOWN_CMD_NAME 386 +# define SSL_R_UNKNOWN_COMMAND 139 +# define SSL_R_UNKNOWN_DIGEST 368 +# define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +# define SSL_R_UNKNOWN_PKEY_TYPE 251 +# define SSL_R_UNKNOWN_PROTOCOL 252 +# define SSL_R_UNKNOWN_SSL_VERSION 254 +# define SSL_R_UNKNOWN_STATE 255 +# define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 338 +# define SSL_R_UNSOLICITED_EXTENSION 217 +# define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +# define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315 +# define SSL_R_UNSUPPORTED_PROTOCOL 258 +# define SSL_R_UNSUPPORTED_SSL_VERSION 259 +# define SSL_R_UNSUPPORTED_STATUS_TYPE 329 +# define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 +# define SSL_R_VERSION_TOO_HIGH 166 +# define SSL_R_VERSION_TOO_LOW 396 +# define SSL_R_WRONG_CERTIFICATE_TYPE 383 +# define SSL_R_WRONG_CIPHER_RETURNED 261 +# define SSL_R_WRONG_CURVE 378 +# define SSL_R_WRONG_SIGNATURE_LENGTH 264 +# define SSL_R_WRONG_SIGNATURE_SIZE 265 +# define SSL_R_WRONG_SIGNATURE_TYPE 370 +# define SSL_R_WRONG_SSL_VERSION 266 +# define SSL_R_WRONG_VERSION_NUMBER 267 +# define SSL_R_X509_LIB 268 +# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 + +#endif diff --git a/thirdparty/user_include/openssl/stack.h b/thirdparty/user_include/openssl/stack.h new file mode 100755 index 0000000000000000000000000000000000000000..cfc075057ae4bd7cd9759bb7a67a06942ea7eaae --- /dev/null +++ b/thirdparty/user_include/openssl/stack.h @@ -0,0 +1,83 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_STACK_H +# define HEADER_STACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stack_st OPENSSL_STACK; /* Use STACK_OF(...) instead */ + +typedef int (*OPENSSL_sk_compfunc)(const void *, const void *); +typedef void (*OPENSSL_sk_freefunc)(void *); +typedef void *(*OPENSSL_sk_copyfunc)(const void *); + +int OPENSSL_sk_num(const OPENSSL_STACK *); +void *OPENSSL_sk_value(const OPENSSL_STACK *, int); + +void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data); + +OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc cmp); +OPENSSL_STACK *OPENSSL_sk_new_null(void); +OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n); +int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n); +void OPENSSL_sk_free(OPENSSL_STACK *); +void OPENSSL_sk_pop_free(OPENSSL_STACK *st, void (*func) (void *)); +OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *, + OPENSSL_sk_copyfunc c, + OPENSSL_sk_freefunc f); +int OPENSSL_sk_insert(OPENSSL_STACK *sk, const void *data, int where); +void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc); +void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p); +int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data); +int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data); +void *OPENSSL_sk_shift(OPENSSL_STACK *st); +void *OPENSSL_sk_pop(OPENSSL_STACK *st); +void OPENSSL_sk_zero(OPENSSL_STACK *st); +OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, + OPENSSL_sk_compfunc cmp); +OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st); +void OPENSSL_sk_sort(OPENSSL_STACK *st); +int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define _STACK OPENSSL_STACK +# define sk_num OPENSSL_sk_num +# define sk_value OPENSSL_sk_value +# define sk_set OPENSSL_sk_set +# define sk_new OPENSSL_sk_new +# define sk_new_null OPENSSL_sk_new_null +# define sk_free OPENSSL_sk_free +# define sk_pop_free OPENSSL_sk_pop_free +# define sk_deep_copy OPENSSL_sk_deep_copy +# define sk_insert OPENSSL_sk_insert +# define sk_delete OPENSSL_sk_delete +# define sk_delete_ptr OPENSSL_sk_delete_ptr +# define sk_find OPENSSL_sk_find +# define sk_find_ex OPENSSL_sk_find_ex +# define sk_push OPENSSL_sk_push +# define sk_unshift OPENSSL_sk_unshift +# define sk_shift OPENSSL_sk_shift +# define sk_pop OPENSSL_sk_pop +# define sk_zero OPENSSL_sk_zero +# define sk_set_cmp_func OPENSSL_sk_set_cmp_func +# define sk_dup OPENSSL_sk_dup +# define sk_sort OPENSSL_sk_sort +# define sk_is_sorted OPENSSL_sk_is_sorted +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/store.h b/thirdparty/user_include/openssl/store.h new file mode 100755 index 0000000000000000000000000000000000000000..7b43e8bd03ac2cb6c21d7d1fcd77880c4a7d7012 --- /dev/null +++ b/thirdparty/user_include/openssl/store.h @@ -0,0 +1,266 @@ +/* + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OSSL_STORE_H +# define HEADER_OSSL_STORE_H + +# include +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/*- + * The main OSSL_STORE functions. + * ------------------------------ + * + * These allow applications to open a channel to a resource with supported + * data (keys, certs, crls, ...), read the data a piece at a time and decide + * what to do with it, and finally close. + */ + +typedef struct ossl_store_ctx_st OSSL_STORE_CTX; + +/* + * Typedef for the OSSL_STORE_INFO post processing callback. This can be used + * to massage the given OSSL_STORE_INFO, or to drop it entirely (by returning + * NULL). + */ +typedef OSSL_STORE_INFO *(*OSSL_STORE_post_process_info_fn)(OSSL_STORE_INFO *, + void *); + +/* + * Open a channel given a URI. The given UI method will be used any time the + * loader needs extra input, for example when a password or pin is needed, and + * will be passed the same user data every time it's needed in this context. + * + * Returns a context reference which represents the channel to communicate + * through. + */ +OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, + void *ui_data, + OSSL_STORE_post_process_info_fn post_process, + void *post_process_data); + +/* + * Control / fine tune the OSSL_STORE channel. |cmd| determines what is to be + * done, and depends on the underlying loader (use OSSL_STORE_get0_scheme to + * determine which loader is used), except for common commands (see below). + * Each command takes different arguments. + */ +int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */); +int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args); + +/* + * Common ctrl commands that different loaders may choose to support. + */ +/* int on = 0 or 1; STORE_ctrl(ctx, STORE_C_USE_SECMEM, &on); */ +# define OSSL_STORE_C_USE_SECMEM 1 +/* Where custom commands start */ +# define OSSL_STORE_C_CUSTOM_START 100 + +/* + * Read one data item (a key, a cert, a CRL) that is supported by the OSSL_STORE + * functionality, given a context. + * Returns a OSSL_STORE_INFO pointer, from which OpenSSL typed data can be + * extracted with OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(), ... + * NULL is returned on error, which may include that the data found at the URI + * can't be figured out for certain or is ambiguous. + */ +OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx); + +/* + * Check if end of data (end of file) is reached + * Returns 1 on end, 0 otherwise. + */ +int OSSL_STORE_eof(OSSL_STORE_CTX *ctx); + +/* + * Check if an error occured + * Returns 1 if it did, 0 otherwise. + */ +int OSSL_STORE_error(OSSL_STORE_CTX *ctx); + +/* + * Close the channel + * Returns 1 on success, 0 on error. + */ +int OSSL_STORE_close(OSSL_STORE_CTX *ctx); + + +/*- + * Extracting OpenSSL types from and creating new OSSL_STORE_INFOs + * --------------------------------------------------------------- + */ + +/* + * Types of data that can be ossl_stored in a OSSL_STORE_INFO. + * OSSL_STORE_INFO_NAME is typically found when getting a listing of + * available "files" / "tokens" / what have you. + */ +# define OSSL_STORE_INFO_NAME 1 /* char * */ +# define OSSL_STORE_INFO_PARAMS 2 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_PKEY 3 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_CERT 4 /* X509 * */ +# define OSSL_STORE_INFO_CRL 5 /* X509_CRL * */ + +/* + * Functions to generate OSSL_STORE_INFOs, one function for each type we + * support having in them, as well as a generic constructor. + * + * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO + * and will therefore be freed when the OSSL_STORE_INFO is freed. + */ +OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name); +int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl); + +/* + * Functions to try to extract data from a OSSL_STORE_INFO. + */ +int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info); +const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info); +char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info); +const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info); +char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info); +X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info); +X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info); +X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info); +X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info); + +const char *OSSL_STORE_INFO_type_string(int type); + +/* + * Free the OSSL_STORE_INFO + */ +void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info); + + +/*- + * Functions to construct a search URI from a base URI and search criteria + * ----------------------------------------------------------------------- + */ + +/* OSSL_STORE search types */ +# define OSSL_STORE_SEARCH_BY_NAME 1 /* subject in certs, issuer in CRLs */ +# define OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 2 +# define OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 3 +# define OSSL_STORE_SEARCH_BY_ALIAS 4 + +/* To check what search types the scheme handler supports */ +int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type); + +/* Search term constructors */ +/* + * The input is considered to be owned by the caller, and must therefore + * remain present throughout the lifetime of the returned OSSL_STORE_SEARCH + */ +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, + const ASN1_INTEGER + *serial); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest, + const unsigned char + *bytes, size_t len); +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias); + +/* Search term destructor */ +void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search); + +/* Search term accessors */ +int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion); +X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion); +const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH + *criterion); +const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH + *criterion, size_t *length); +const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion); +const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion); + +/* + * Add search criterion and expected return type (which can be unspecified) + * to the loading channel. This MUST happen before the first OSSL_STORE_load(). + */ +int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type); +int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search); + + +/*- + * Function to register a loader for the given URI scheme. + * ------------------------------------------------------- + * + * The loader receives all the main components of an URI except for the + * scheme. + */ + +typedef struct ossl_store_loader_st OSSL_STORE_LOADER; +OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme); +const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader); +const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader); +/* struct ossl_store_loader_ctx_st is defined differently by each loader */ +typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX; +typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const OSSL_STORE_LOADER + *loader, + const char *uri, + const UI_METHOD *ui_method, + void *ui_data); +int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, + OSSL_STORE_open_fn open_function); +typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd, + va_list args); +int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, + OSSL_STORE_ctrl_fn ctrl_function); +typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected); +int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, + OSSL_STORE_expect_fn expect_function); +typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx, + OSSL_STORE_SEARCH *criteria); +int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, + OSSL_STORE_find_fn find_function); +typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, + void *ui_data); +int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, + OSSL_STORE_load_fn load_function); +typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, + OSSL_STORE_eof_fn eof_function); +typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, + OSSL_STORE_error_fn error_function); +typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx); +int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, + OSSL_STORE_close_fn close_function); +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader); + +int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader); +OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme); + +/*- + * Functions to list STORE loaders + * ------------------------------- + */ +int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER + *loader, void *do_arg), + void *do_arg); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/storeerr.h b/thirdparty/user_include/openssl/storeerr.h new file mode 100755 index 0000000000000000000000000000000000000000..33d0ab7903a20bafd5db36158bdf84497810d3aa --- /dev/null +++ b/thirdparty/user_include/openssl/storeerr.h @@ -0,0 +1,87 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_OSSL_STOREERR_H +# define HEADER_OSSL_STOREERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_OSSL_STORE_strings(void); + +/* + * OSSL_STORE function codes. + */ +# define OSSL_STORE_F_FILE_CTRL 129 +# define OSSL_STORE_F_FILE_FIND 138 +# define OSSL_STORE_F_FILE_GET_PASS 118 +# define OSSL_STORE_F_FILE_LOAD 119 +# define OSSL_STORE_F_FILE_LOAD_TRY_DECODE 124 +# define OSSL_STORE_F_FILE_NAME_TO_URI 126 +# define OSSL_STORE_F_FILE_OPEN 120 +# define OSSL_STORE_F_OSSL_STORE_ATTACH_PEM_BIO 127 +# define OSSL_STORE_F_OSSL_STORE_EXPECT 130 +# define OSSL_STORE_F_OSSL_STORE_FILE_ATTACH_PEM_BIO_INT 128 +# define OSSL_STORE_F_OSSL_STORE_FIND 131 +# define OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT 100 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CERT 101 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_CRL 102 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME 103 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_NAME_DESCRIPTION 135 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PARAMS 104 +# define OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY 105 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CERT 106 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_CRL 107 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_EMBEDDED 123 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_NAME 109 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PARAMS 110 +# define OSSL_STORE_F_OSSL_STORE_INFO_NEW_PKEY 111 +# define OSSL_STORE_F_OSSL_STORE_INFO_SET0_NAME_DESCRIPTION 134 +# define OSSL_STORE_F_OSSL_STORE_INIT_ONCE 112 +# define OSSL_STORE_F_OSSL_STORE_LOADER_NEW 113 +# define OSSL_STORE_F_OSSL_STORE_OPEN 114 +# define OSSL_STORE_F_OSSL_STORE_OPEN_INT 115 +# define OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT 117 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS 132 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL 133 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT 136 +# define OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME 137 +# define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT 116 +# define OSSL_STORE_F_TRY_DECODE_PARAMS 121 +# define OSSL_STORE_F_TRY_DECODE_PKCS12 122 +# define OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED 125 + +/* + * OSSL_STORE reason codes. + */ +# define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE 107 +# define OSSL_STORE_R_BAD_PASSWORD_READ 115 +# define OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC 113 +# define OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST 121 +# define OSSL_STORE_R_INVALID_SCHEME 106 +# define OSSL_STORE_R_IS_NOT_A 112 +# define OSSL_STORE_R_LOADER_INCOMPLETE 116 +# define OSSL_STORE_R_LOADING_STARTED 117 +# define OSSL_STORE_R_NOT_A_CERTIFICATE 100 +# define OSSL_STORE_R_NOT_A_CRL 101 +# define OSSL_STORE_R_NOT_A_KEY 102 +# define OSSL_STORE_R_NOT_A_NAME 103 +# define OSSL_STORE_R_NOT_PARAMETERS 104 +# define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114 +# define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE 108 +# define OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 119 +# define OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 109 +# define OSSL_STORE_R_UNREGISTERED_SCHEME 105 +# define OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE 110 +# define OSSL_STORE_R_UNSUPPORTED_OPERATION 118 +# define OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE 120 +# define OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED 111 + +#endif diff --git a/thirdparty/user_include/openssl/symhacks.h b/thirdparty/user_include/openssl/symhacks.h new file mode 100755 index 0000000000000000000000000000000000000000..156ea6e4ee957c57628b79afc6ca0f67d366da28 --- /dev/null +++ b/thirdparty/user_include/openssl/symhacks.h @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SYMHACKS_H +# define HEADER_SYMHACKS_H + +# include + +/* Case insensitive linking causes problems.... */ +# if defined(OPENSSL_SYS_VMS) +# undef ERR_load_CRYPTO_strings +# define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings +# undef OCSP_crlID_new +# define OCSP_crlID_new OCSP_crlID2_new + +# undef d2i_ECPARAMETERS +# define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS +# undef i2d_ECPARAMETERS +# define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS +# undef d2i_ECPKPARAMETERS +# define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS +# undef i2d_ECPKPARAMETERS +# define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS + +/* This one clashes with CMS_data_create */ +# undef cms_Data_create +# define cms_Data_create priv_cms_Data_create + +# endif + +#endif /* ! defined HEADER_VMS_IDHACKS_H */ diff --git a/thirdparty/user_include/openssl/tls1.h b/thirdparty/user_include/openssl/tls1.h new file mode 100755 index 0000000000000000000000000000000000000000..e13b5dd4bc65b5ef72bf04098f6a0d18c71a5d23 --- /dev/null +++ b/thirdparty/user_include/openssl/tls1.h @@ -0,0 +1,1237 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * Copyright 2005 Nokia. All rights reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TLS1_H +# define HEADER_TLS1_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Default security level if not overridden at config time */ +# ifndef OPENSSL_TLS_SECURITY_LEVEL +# define OPENSSL_TLS_SECURITY_LEVEL 1 +# endif + +# define TLS1_VERSION 0x0301 +# define TLS1_1_VERSION 0x0302 +# define TLS1_2_VERSION 0x0303 +# define TLS1_3_VERSION 0x0304 +# define TLS_MAX_VERSION TLS1_3_VERSION + +/* Special value for method supporting multiple versions */ +# define TLS_ANY_VERSION 0x10000 + +# define TLS1_VERSION_MAJOR 0x03 +# define TLS1_VERSION_MINOR 0x01 + +# define TLS1_1_VERSION_MAJOR 0x03 +# define TLS1_1_VERSION_MINOR 0x02 + +# define TLS1_2_VERSION_MAJOR 0x03 +# define TLS1_2_VERSION_MINOR 0x03 + +# define TLS1_get_version(s) \ + ((SSL_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_version(s) : 0) + +# define TLS1_get_client_version(s) \ + ((SSL_client_version(s) >> 8) == TLS1_VERSION_MAJOR ? SSL_client_version(s) : 0) + +# define TLS1_AD_DECRYPTION_FAILED 21 +# define TLS1_AD_RECORD_OVERFLOW 22 +# define TLS1_AD_UNKNOWN_CA 48/* fatal */ +# define TLS1_AD_ACCESS_DENIED 49/* fatal */ +# define TLS1_AD_DECODE_ERROR 50/* fatal */ +# define TLS1_AD_DECRYPT_ERROR 51 +# define TLS1_AD_EXPORT_RESTRICTION 60/* fatal */ +# define TLS1_AD_PROTOCOL_VERSION 70/* fatal */ +# define TLS1_AD_INSUFFICIENT_SECURITY 71/* fatal */ +# define TLS1_AD_INTERNAL_ERROR 80/* fatal */ +# define TLS1_AD_INAPPROPRIATE_FALLBACK 86/* fatal */ +# define TLS1_AD_USER_CANCELLED 90 +# define TLS1_AD_NO_RENEGOTIATION 100 +/* TLSv1.3 alerts */ +# define TLS13_AD_MISSING_EXTENSION 109 /* fatal */ +# define TLS13_AD_CERTIFICATE_REQUIRED 116 /* fatal */ +/* codes 110-114 are from RFC3546 */ +# define TLS1_AD_UNSUPPORTED_EXTENSION 110 +# define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +# define TLS1_AD_UNRECOGNIZED_NAME 112 +# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +# define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */ +# define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */ + +/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */ +# define TLSEXT_TYPE_server_name 0 +# define TLSEXT_TYPE_max_fragment_length 1 +# define TLSEXT_TYPE_client_certificate_url 2 +# define TLSEXT_TYPE_trusted_ca_keys 3 +# define TLSEXT_TYPE_truncated_hmac 4 +# define TLSEXT_TYPE_status_request 5 +/* ExtensionType values from RFC4681 */ +# define TLSEXT_TYPE_user_mapping 6 +/* ExtensionType values from RFC5878 */ +# define TLSEXT_TYPE_client_authz 7 +# define TLSEXT_TYPE_server_authz 8 +/* ExtensionType values from RFC6091 */ +# define TLSEXT_TYPE_cert_type 9 + +/* ExtensionType values from RFC4492 */ +/* + * Prior to TLSv1.3 the supported_groups extension was known as + * elliptic_curves + */ +# define TLSEXT_TYPE_supported_groups 10 +# define TLSEXT_TYPE_elliptic_curves TLSEXT_TYPE_supported_groups +# define TLSEXT_TYPE_ec_point_formats 11 + + +/* ExtensionType value from RFC5054 */ +# define TLSEXT_TYPE_srp 12 + +/* ExtensionType values from RFC5246 */ +# define TLSEXT_TYPE_signature_algorithms 13 + +/* ExtensionType value from RFC5764 */ +# define TLSEXT_TYPE_use_srtp 14 + +/* ExtensionType value from RFC5620 */ +# define TLSEXT_TYPE_heartbeat 15 + +/* ExtensionType value from RFC7301 */ +# define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +/* + * Extension type for Certificate Transparency + * https://tools.ietf.org/html/rfc6962#section-3.3.1 + */ +# define TLSEXT_TYPE_signed_certificate_timestamp 18 + +/* + * ExtensionType value for TLS padding extension. + * http://tools.ietf.org/html/draft-agl-tls-padding + */ +# define TLSEXT_TYPE_padding 21 + +/* ExtensionType value from RFC7366 */ +# define TLSEXT_TYPE_encrypt_then_mac 22 + +/* ExtensionType value from RFC7627 */ +# define TLSEXT_TYPE_extended_master_secret 23 + +/* ExtensionType value from RFC4507 */ +# define TLSEXT_TYPE_session_ticket 35 + +/* As defined for TLS1.3 */ +# define TLSEXT_TYPE_psk 41 +# define TLSEXT_TYPE_early_data 42 +# define TLSEXT_TYPE_supported_versions 43 +# define TLSEXT_TYPE_cookie 44 +# define TLSEXT_TYPE_psk_kex_modes 45 +# define TLSEXT_TYPE_certificate_authorities 47 +# define TLSEXT_TYPE_post_handshake_auth 49 +# define TLSEXT_TYPE_signature_algorithms_cert 50 +# define TLSEXT_TYPE_key_share 51 + +/* Temporary extension type */ +# define TLSEXT_TYPE_renegotiate 0xff01 + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* This is not an IANA defined extension number */ +# define TLSEXT_TYPE_next_proto_neg 13172 +# endif + +/* NameType value from RFC3546 */ +# define TLSEXT_NAMETYPE_host_name 0 +/* status request value from RFC3546 */ +# define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from RFC4492 */ +# define TLSEXT_ECPOINTFORMAT_first 0 +# define TLSEXT_ECPOINTFORMAT_uncompressed 0 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2 +# define TLSEXT_ECPOINTFORMAT_last 2 + +/* Signature and hash algorithms from RFC5246 */ +# define TLSEXT_signature_anonymous 0 +# define TLSEXT_signature_rsa 1 +# define TLSEXT_signature_dsa 2 +# define TLSEXT_signature_ecdsa 3 +# define TLSEXT_signature_gostr34102001 237 +# define TLSEXT_signature_gostr34102012_256 238 +# define TLSEXT_signature_gostr34102012_512 239 + +/* Total number of different signature algorithms */ +# define TLSEXT_signature_num 7 + +# define TLSEXT_hash_none 0 +# define TLSEXT_hash_md5 1 +# define TLSEXT_hash_sha1 2 +# define TLSEXT_hash_sha224 3 +# define TLSEXT_hash_sha256 4 +# define TLSEXT_hash_sha384 5 +# define TLSEXT_hash_sha512 6 +# define TLSEXT_hash_gostr3411 237 +# define TLSEXT_hash_gostr34112012_256 238 +# define TLSEXT_hash_gostr34112012_512 239 + +/* Total number of different digest algorithms */ + +# define TLSEXT_hash_num 10 + +/* Flag set for unrecognised algorithms */ +# define TLSEXT_nid_unknown 0x1000000 + +/* ECC curves */ + +# define TLSEXT_curve_P_256 23 +# define TLSEXT_curve_P_384 24 + +/* OpenSSL value to disable maximum fragment length extension */ +# define TLSEXT_max_fragment_length_DISABLED 0 +/* Allowed values for max fragment length extension */ +# define TLSEXT_max_fragment_length_512 1 +# define TLSEXT_max_fragment_length_1024 2 +# define TLSEXT_max_fragment_length_2048 3 +# define TLSEXT_max_fragment_length_4096 4 + +int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode); +int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode); + +# define TLSEXT_MAXLEN_host_name 255 + +__owur const char *SSL_get_servername(const SSL *s, const int type); +__owur int SSL_get_servername_type(const SSL *s); +/* + * SSL_export_keying_material exports a value derived from the master secret, + * as specified in RFC 5705. It writes |olen| bytes to |out| given a label and + * optional context. (Since a zero length context is allowed, the |use_context| + * flag controls whether a context is included.) It returns 1 on success and + * 0 or -1 otherwise. + */ +__owur int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, + size_t contextlen, int use_context); + +/* + * SSL_export_keying_material_early exports a value derived from the + * early exporter master secret, as specified in + * https://tools.ietf.org/html/draft-ietf-tls-tls13-23. It writes + * |olen| bytes to |out| given a label and optional context. It + * returns 1 on success and 0 otherwise. + */ +__owur int SSL_export_keying_material_early(SSL *s, unsigned char *out, + size_t olen, const char *label, + size_t llen, + const unsigned char *context, + size_t contextlen); + +int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid); +int SSL_get_signature_type_nid(const SSL *s, int *pnid); + +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +__owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain); + +# define SSL_set_tlsext_host_name(s,name) \ + SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,\ + (void *)name) + +# define SSL_set_tlsext_debug_callback(ssl, cb) \ + SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,\ + (void (*)(void))cb) + +# define SSL_set_tlsext_debug_arg(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0,arg) + +# define SSL_get_tlsext_status_type(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL) + +# define SSL_set_tlsext_status_type(ssl, type) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL) + +# define SSL_get_tlsext_status_exts(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0,arg) + +# define SSL_set_tlsext_status_exts(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0,arg) + +# define SSL_get_tlsext_status_ids(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0,arg) + +# define SSL_set_tlsext_status_ids(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0,arg) + +# define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0,arg) + +# define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen,arg) + +# define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ + SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,\ + (void (*)(void))cb) + +# define SSL_TLSEXT_ERR_OK 0 +# define SSL_TLSEXT_ERR_ALERT_WARNING 1 +# define SSL_TLSEXT_ERR_ALERT_FATAL 2 +# define SSL_TLSEXT_ERR_NOACK 3 + +# define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0,arg) + +# define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_TLSEXT_TICKET_KEYS,keylen,keys) +# define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_TICKET_KEYS,keylen,keys) + +# define SSL_CTX_get_tlsext_status_cb(ssl, cb) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB,0,(void *)cb) +# define SSL_CTX_set_tlsext_status_cb(ssl, cb) \ + SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,\ + (void (*)(void))cb) + +# define SSL_CTX_get_tlsext_status_arg(ssl, arg) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG,0,arg) +# define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0,arg) + +# define SSL_CTX_set_tlsext_status_type(ssl, type) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type,NULL) + +# define SSL_CTX_get_tlsext_status_type(ssl) \ + SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL) + +# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ + SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,\ + (void (*)(void))cb) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_DTLSEXT_HB_ENABLED 0x01 +# define SSL_DTLSEXT_HB_DONT_SEND_REQUESTS 0x02 +# define SSL_DTLSEXT_HB_DONT_RECV_REQUESTS 0x04 +# define SSL_get_dtlsext_heartbeat_pending(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING,0,NULL) +# define SSL_set_dtlsext_heartbeat_no_requests(ssl, arg) \ + SSL_ctrl(ssl,SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS,arg,NULL) + +# if OPENSSL_API_COMPAT < 0x10100000L +# define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT \ + SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT +# define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING \ + SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING +# define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS \ + SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS +# define SSL_TLSEXT_HB_ENABLED \ + SSL_DTLSEXT_HB_ENABLED +# define SSL_TLSEXT_HB_DONT_SEND_REQUESTS \ + SSL_DTLSEXT_HB_DONT_SEND_REQUESTS +# define SSL_TLSEXT_HB_DONT_RECV_REQUESTS \ + SSL_DTLSEXT_HB_DONT_RECV_REQUESTS +# define SSL_get_tlsext_heartbeat_pending(ssl) \ + SSL_get_dtlsext_heartbeat_pending(ssl) +# define SSL_set_tlsext_heartbeat_no_requests(ssl, arg) \ + SSL_set_dtlsext_heartbeat_no_requests(ssl,arg) +# endif +# endif + +/* PSK ciphersuites from 4279 */ +# define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +# define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D +# define TLS1_CK_DHE_PSK_WITH_RC4_128_SHA 0x0300008E +# define TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008F +# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA 0x03000090 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA 0x03000091 +# define TLS1_CK_RSA_PSK_WITH_RC4_128_SHA 0x03000092 +# define TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x03000093 +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA 0x03000094 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA 0x03000095 + +/* PSK ciphersuites from 5487 */ +# define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256 0x030000A8 +# define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384 0x030000A9 +# define TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256 0x030000AA +# define TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384 0x030000AB +# define TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256 0x030000AC +# define TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384 0x030000AD +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA256 0x030000AE +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384 0x030000AF +# define TLS1_CK_PSK_WITH_NULL_SHA256 0x030000B0 +# define TLS1_CK_PSK_WITH_NULL_SHA384 0x030000B1 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256 0x030000B2 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384 0x030000B3 +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA256 0x030000B4 +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA384 0x030000B5 +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256 0x030000B6 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384 0x030000B7 +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA256 0x030000B8 +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA384 0x030000B9 + +/* NULL PSK ciphersuites from RFC4785 */ +# define TLS1_CK_PSK_WITH_NULL_SHA 0x0300002C +# define TLS1_CK_DHE_PSK_WITH_NULL_SHA 0x0300002D +# define TLS1_CK_RSA_PSK_WITH_NULL_SHA 0x0300002E + +/* AES ciphersuites from RFC3268 */ +# define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +# define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 +# define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +# define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +# define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +# define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +# define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +# define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +# define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +# define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +# define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +# define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +# define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +# define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +# define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +# define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +# define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +# define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +# define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +# define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +# define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +# define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +# define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +# define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +/* CCM ciphersuites from RFC6655 */ +# define TLS1_CK_RSA_WITH_AES_128_CCM 0x0300C09C +# define TLS1_CK_RSA_WITH_AES_256_CCM 0x0300C09D +# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM 0x0300C09E +# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM 0x0300C09F +# define TLS1_CK_RSA_WITH_AES_128_CCM_8 0x0300C0A0 +# define TLS1_CK_RSA_WITH_AES_256_CCM_8 0x0300C0A1 +# define TLS1_CK_DHE_RSA_WITH_AES_128_CCM_8 0x0300C0A2 +# define TLS1_CK_DHE_RSA_WITH_AES_256_CCM_8 0x0300C0A3 +# define TLS1_CK_PSK_WITH_AES_128_CCM 0x0300C0A4 +# define TLS1_CK_PSK_WITH_AES_256_CCM 0x0300C0A5 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM 0x0300C0A6 +# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM 0x0300C0A7 +# define TLS1_CK_PSK_WITH_AES_128_CCM_8 0x0300C0A8 +# define TLS1_CK_PSK_WITH_AES_256_CCM_8 0x0300C0A9 +# define TLS1_CK_DHE_PSK_WITH_AES_128_CCM_8 0x0300C0AA +# define TLS1_CK_DHE_PSK_WITH_AES_256_CCM_8 0x0300C0AB + +/* CCM ciphersuites from RFC7251 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM 0x0300C0AC +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM 0x0300C0AD +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8 0x0300C0AE +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8 0x0300C0AF + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BA +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BB +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BC +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BD +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BE +# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256 0x030000BF + +# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C0 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C1 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C2 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C3 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C4 +# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256 0x030000C5 + +/* ECC ciphersuites from RFC4492 */ +# define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +# define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +# define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +# define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +# define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +# define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +# define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +# define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +# define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +# define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +# define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +# define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +# define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +# define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +# define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +# define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +# define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +# define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +# define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +/* SRP ciphersuites from RFC 5054 */ +# define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +# define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +# define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +# define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +# define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +/* ECDH HMAC based ciphersuites from RFC5289 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +/* ECDHE PSK ciphersuites from RFC5489 */ +# define TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA 0x0300C033 +# define TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0x0300C034 +# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA 0x0300C035 +# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA 0x0300C036 + +# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037 +# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038 + +/* NULL PSK ciphersuites from RFC4785 */ +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA 0x0300C039 +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256 0x0300C03A +# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384 0x0300C03B + +/* Camellia-CBC ciphersuites from RFC6367 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C072 +# define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C073 +# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C074 +# define TLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C075 +# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C076 +# define TLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C077 +# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C078 +# define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C079 + +# define TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C094 +# define TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C095 +# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C096 +# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C097 +# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C098 +# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C099 +# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C09A +# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C09B + +/* draft-ietf-tls-chacha20-poly1305-03 */ +# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCA8 +# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0x0300CCA9 +# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCAA +# define TLS1_CK_PSK_WITH_CHACHA20_POLY1305 0x0300CCAB +# define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAC +# define TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305 0x0300CCAD +# define TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305 0x0300CCAE + +/* TLS v1.3 ciphersuites */ +# define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 +# define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 +# define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303 +# define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304 +# define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305 + +/* Aria ciphersuites from RFC6209 */ +# define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050 +# define TLS1_CK_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C051 +# define TLS1_CK_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C052 +# define TLS1_CK_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C053 +# define TLS1_CK_DH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C054 +# define TLS1_CK_DH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C055 +# define TLS1_CK_DHE_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C056 +# define TLS1_CK_DHE_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C057 +# define TLS1_CK_DH_DSS_WITH_ARIA_128_GCM_SHA256 0x0300C058 +# define TLS1_CK_DH_DSS_WITH_ARIA_256_GCM_SHA384 0x0300C059 +# define TLS1_CK_DH_anon_WITH_ARIA_128_GCM_SHA256 0x0300C05A +# define TLS1_CK_DH_anon_WITH_ARIA_256_GCM_SHA384 0x0300C05B +# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05C +# define TLS1_CK_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05D +# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0x0300C05E +# define TLS1_CK_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0x0300C05F +# define TLS1_CK_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C060 +# define TLS1_CK_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C061 +# define TLS1_CK_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C062 +# define TLS1_CK_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0x0300C063 +# define TLS1_CK_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06A +# define TLS1_CK_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06B +# define TLS1_CK_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06C +# define TLS1_CK_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06D +# define TLS1_CK_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0x0300C06E +# define TLS1_CK_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0x0300C06F + +/* a bundle of RFC standard cipher names, generated from ssl3_ciphers[] */ +# define TLS1_RFC_RSA_WITH_AES_128_SHA "TLS_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ADH_WITH_AES_128_SHA "TLS_DH_anon_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_RSA_WITH_AES_256_SHA "TLS_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ADH_WITH_AES_256_SHA "TLS_DH_anon_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_RSA_WITH_NULL_SHA256 "TLS_RSA_WITH_NULL_SHA256" +# define TLS1_RFC_RSA_WITH_AES_128_SHA256 "TLS_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_AES_256_SHA256 "TLS_RSA_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_SHA256 "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_SHA256 "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_SHA256 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_SHA256 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_AES_128_SHA256 "TLS_DH_anon_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_AES_256_SHA256 "TLS_DH_anon_WITH_AES_256_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_AES_128_GCM_SHA256 "TLS_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_RSA_WITH_AES_256_GCM_SHA384 "TLS_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_DSS_WITH_AES_128_GCM_SHA256 "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_AES_256_GCM_SHA384 "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_ADH_WITH_AES_128_GCM_SHA256 "TLS_DH_anon_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ADH_WITH_AES_256_GCM_SHA384 "TLS_DH_anon_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_RSA_WITH_AES_128_CCM "TLS_RSA_WITH_AES_128_CCM" +# define TLS1_RFC_RSA_WITH_AES_256_CCM "TLS_RSA_WITH_AES_256_CCM" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM "TLS_DHE_RSA_WITH_AES_128_CCM" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM "TLS_DHE_RSA_WITH_AES_256_CCM" +# define TLS1_RFC_RSA_WITH_AES_128_CCM_8 "TLS_RSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_RSA_WITH_AES_256_CCM_8 "TLS_RSA_WITH_AES_256_CCM_8" +# define TLS1_RFC_DHE_RSA_WITH_AES_128_CCM_8 "TLS_DHE_RSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_DHE_RSA_WITH_AES_256_CCM_8 "TLS_DHE_RSA_WITH_AES_256_CCM_8" +# define TLS1_RFC_PSK_WITH_AES_128_CCM "TLS_PSK_WITH_AES_128_CCM" +# define TLS1_RFC_PSK_WITH_AES_256_CCM "TLS_PSK_WITH_AES_256_CCM" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM "TLS_DHE_PSK_WITH_AES_128_CCM" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM "TLS_DHE_PSK_WITH_AES_256_CCM" +# define TLS1_RFC_PSK_WITH_AES_128_CCM_8 "TLS_PSK_WITH_AES_128_CCM_8" +# define TLS1_RFC_PSK_WITH_AES_256_CCM_8 "TLS_PSK_WITH_AES_256_CCM_8" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CCM_8 "TLS_PSK_DHE_WITH_AES_128_CCM_8" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CCM_8 "TLS_PSK_DHE_WITH_AES_256_CCM_8" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM "TLS_ECDHE_ECDSA_WITH_AES_256_CCM" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CCM_8 "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8" +# define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" +# define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" +# define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +# define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256" +# define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA "TLS_ECDHE_ECDSA_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_NULL_SHA "TLS_ECDHE_RSA_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_CBC_SHA "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_NULL_SHA "TLS_ECDH_anon_WITH_NULL_SHA" +# define TLS1_RFC_ECDH_anon_WITH_DES_192_CBC3_SHA "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_AES_128_CBC_SHA "TLS_ECDH_anon_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDH_anon_WITH_AES_256_CBC_SHA "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_NULL_SHA "TLS_PSK_WITH_NULL_SHA" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA "TLS_DHE_PSK_WITH_NULL_SHA" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA "TLS_RSA_PSK_WITH_NULL_SHA" +# define TLS1_RFC_PSK_WITH_3DES_EDE_CBC_SHA "TLS_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA "TLS_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA "TLS_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA "TLS_DHE_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA "TLS_DHE_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_3DES_EDE_CBC_SHA "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA "TLS_RSA_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA "TLS_RSA_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_PSK_WITH_AES_128_GCM_SHA256 "TLS_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_PSK_WITH_AES_256_GCM_SHA384 "TLS_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_GCM_SHA256 "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_GCM_SHA384 "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_GCM_SHA256 "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_GCM_SHA384 "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_AES_128_CBC_SHA256 "TLS_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_PSK_WITH_AES_256_CBC_SHA384 "TLS_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_PSK_WITH_NULL_SHA256 "TLS_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_PSK_WITH_NULL_SHA384 "TLS_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA256 "TLS_DHE_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_NULL_SHA384 "TLS_DHE_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_AES_128_CBC_SHA256 "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_AES_256_CBC_SHA384 "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA256 "TLS_RSA_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_NULL_SHA384 "TLS_RSA_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA "TLS_ECDHE_PSK_WITH_NULL_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA256 "TLS_ECDHE_PSK_WITH_NULL_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_NULL_SHA384 "TLS_ECDHE_PSK_WITH_NULL_SHA384" +# define TLS1_RFC_SRP_SHA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA" +# define TLS1_RFC_SRP_SHA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA" +# define TLS1_RFC_SRP_SHA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_PSK_WITH_CHACHA20_POLY1305 "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305 "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305 "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_CHACHA20_POLY1305 "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA256 "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256" +# define TLS1_RFC_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_ADH_WITH_CAMELLIA_256_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" +# define TLS1_RFC_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_ADH_WITH_CAMELLIA_128_CBC_SHA "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" +# define TLS1_RFC_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" +# define TLS1_RFC_RSA_WITH_SEED_SHA "TLS_RSA_WITH_SEED_CBC_SHA" +# define TLS1_RFC_DHE_DSS_WITH_SEED_SHA "TLS_DHE_DSS_WITH_SEED_CBC_SHA" +# define TLS1_RFC_DHE_RSA_WITH_SEED_SHA "TLS_DHE_RSA_WITH_SEED_CBC_SHA" +# define TLS1_RFC_ADH_WITH_SEED_SHA "TLS_DH_anon_WITH_SEED_CBC_SHA" +# define TLS1_RFC_ECDHE_PSK_WITH_RC4_128_SHA "TLS_ECDHE_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDH_anon_WITH_RC4_128_SHA "TLS_ECDH_anon_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDHE_ECDSA_WITH_RC4_128_SHA "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" +# define TLS1_RFC_ECDHE_RSA_WITH_RC4_128_SHA "TLS_ECDHE_RSA_WITH_RC4_128_SHA" +# define TLS1_RFC_PSK_WITH_RC4_128_SHA "TLS_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_RSA_PSK_WITH_RC4_128_SHA "TLS_RSA_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_DHE_PSK_WITH_RC4_128_SHA "TLS_DHE_PSK_WITH_RC4_128_SHA" +# define TLS1_RFC_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_DSS_WITH_ARIA_128_GCM_SHA256 "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_DSS_WITH_ARIA_256_GCM_SHA384 "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DH_anon_WITH_ARIA_128_GCM_SHA256 "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DH_anon_WITH_ARIA_256_GCM_SHA384 "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_PSK_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384" +# define TLS1_RFC_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256" +# define TLS1_RFC_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384" + + +/* + * XXX Backward compatibility alert: Older versions of OpenSSL gave some DHE + * ciphers names with "EDH" instead of "DHE". Going forward, we should be + * using DHE everywhere, though we may indefinitely maintain aliases for + * users or configurations that used "EDH" + */ +# define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +# define TLS1_TXT_PSK_WITH_NULL_SHA "PSK-NULL-SHA" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA "DHE-PSK-NULL-SHA" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA "RSA-PSK-NULL-SHA" + +/* AES ciphersuites from RFC3268 */ +# define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +# define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +# define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +# define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +/* ECC ciphersuites from RFC4492 */ +# define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +# define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +# define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +# define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279 */ +# define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +# define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +# define TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA "DHE-PSK-RC4-SHA" +# define TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA "DHE-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA "DHE-PSK-AES128-CBC-SHA" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA "DHE-PSK-AES256-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA "RSA-PSK-RC4-SHA" +# define TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA "RSA-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA "RSA-PSK-AES128-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA "RSA-PSK-AES256-CBC-SHA" + +/* PSK ciphersuites from RFC 5487 */ +# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256 "DHE-PSK-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384 "DHE-PSK-AES256-GCM-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256 "RSA-PSK-AES128-GCM-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384 "RSA-PSK-AES256-GCM-SHA384" + +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256 "PSK-AES128-CBC-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384 "PSK-AES256-CBC-SHA384" +# define TLS1_TXT_PSK_WITH_NULL_SHA256 "PSK-NULL-SHA256" +# define TLS1_TXT_PSK_WITH_NULL_SHA384 "PSK-NULL-SHA384" + +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256 "DHE-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384 "DHE-PSK-AES256-CBC-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA256 "DHE-PSK-NULL-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA384 "DHE-PSK-NULL-SHA384" + +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256 "RSA-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384 "RSA-PSK-AES256-CBC-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA256 "RSA-PSK-NULL-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA384 "RSA-PSK-NULL-SHA384" + +/* SRP ciphersuite from RFC 5054 */ +# define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256 "CAMELLIA128-SHA256" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DH-DSS-CAMELLIA128-SHA256" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DH-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DHE-DSS-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DHE-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256 "ADH-CAMELLIA128-SHA256" + +# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256 "CAMELLIA256-SHA256" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DH-DSS-CAMELLIA256-SHA256" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DH-RSA-CAMELLIA256-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DHE-DSS-CAMELLIA256-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DHE-RSA-CAMELLIA256-SHA256" +# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256 "ADH-CAMELLIA256-SHA256" + +# define TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256 "PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384 "PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "DHE-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "DHE-PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 "RSA-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 "RSA-PSK-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-PSK-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-PSK-CAMELLIA256-SHA384" + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +# define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +# define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +# define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +# define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +# define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +/* TLS v1.2 ciphersuites */ +# define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +# define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +# define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +/* CCM ciphersuites from RFC6655 */ +# define TLS1_TXT_RSA_WITH_AES_128_CCM "AES128-CCM" +# define TLS1_TXT_RSA_WITH_AES_256_CCM "AES256-CCM" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM "DHE-RSA-AES128-CCM" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM "DHE-RSA-AES256-CCM" + +# define TLS1_TXT_RSA_WITH_AES_128_CCM_8 "AES128-CCM8" +# define TLS1_TXT_RSA_WITH_AES_256_CCM_8 "AES256-CCM8" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_CCM_8 "DHE-RSA-AES128-CCM8" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_CCM_8 "DHE-RSA-AES256-CCM8" + +# define TLS1_TXT_PSK_WITH_AES_128_CCM "PSK-AES128-CCM" +# define TLS1_TXT_PSK_WITH_AES_256_CCM "PSK-AES256-CCM" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM "DHE-PSK-AES128-CCM" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM "DHE-PSK-AES256-CCM" + +# define TLS1_TXT_PSK_WITH_AES_128_CCM_8 "PSK-AES128-CCM8" +# define TLS1_TXT_PSK_WITH_AES_256_CCM_8 "PSK-AES256-CCM8" +# define TLS1_TXT_DHE_PSK_WITH_AES_128_CCM_8 "DHE-PSK-AES128-CCM8" +# define TLS1_TXT_DHE_PSK_WITH_AES_256_CCM_8 "DHE-PSK-AES256-CCM8" + +/* CCM ciphersuites from RFC7251 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM "ECDHE-ECDSA-AES128-CCM" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM "ECDHE-ECDSA-AES256-CCM" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM_8 "ECDHE-ECDSA-AES128-CCM8" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CCM_8 "ECDHE-ECDSA-AES256-CCM8" + +/* ECDH HMAC based ciphersuites from RFC5289 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "ECDHE-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "ECDHE-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 "ECDH-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 "ECDH-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +/* TLS v1.2 PSK GCM ciphersuites from RFC5487 */ +# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384" + +/* ECDHE PSK ciphersuites from RFC 5489 */ +# define TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA "ECDHE-PSK-RC4-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA "ECDHE-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA "ECDHE-PSK-AES128-CBC-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA "ECDHE-PSK-AES256-CBC-SHA" + +# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-AES256-CBC-SHA384" + +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA "ECDHE-PSK-NULL-SHA" +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256 "ECDHE-PSK-NULL-SHA256" +# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384 "ECDHE-PSK-NULL-SHA384" + +/* Camellia-CBC ciphersuites from RFC6367 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-ECDSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-ECDSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-ECDSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-ECDSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-RSA-CAMELLIA256-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-RSA-CAMELLIA128-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-RSA-CAMELLIA256-SHA384" + +/* draft-ietf-tls-chacha20-poly1305-03 */ +# define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305" +# define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305" +# define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305" +# define TLS1_TXT_PSK_WITH_CHACHA20_POLY1305 "PSK-CHACHA20-POLY1305" +# define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305 "ECDHE-PSK-CHACHA20-POLY1305" +# define TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305 "DHE-PSK-CHACHA20-POLY1305" +# define TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305 "RSA-PSK-CHACHA20-POLY1305" + +/* Aria ciphersuites from RFC6209 */ +# define TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256 "ARIA128-GCM-SHA256" +# define TLS1_TXT_RSA_WITH_ARIA_256_GCM_SHA384 "ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_RSA_WITH_ARIA_128_GCM_SHA256 "DHE-RSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_ARIA_256_GCM_SHA384 "DHE-RSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_RSA_WITH_ARIA_128_GCM_SHA256 "DH-RSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_RSA_WITH_ARIA_256_GCM_SHA384 "DH-RSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_DSS_WITH_ARIA_128_GCM_SHA256 "DHE-DSS-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_ARIA_256_GCM_SHA384 "DHE-DSS-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_DSS_WITH_ARIA_128_GCM_SHA256 "DH-DSS-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_DSS_WITH_ARIA_256_GCM_SHA384 "DH-DSS-ARIA256-GCM-SHA384" +# define TLS1_TXT_DH_anon_WITH_ARIA_128_GCM_SHA256 "ADH-ARIA128-GCM-SHA256" +# define TLS1_TXT_DH_anon_WITH_ARIA_256_GCM_SHA384 "ADH-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ECDSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ECDSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ECDSA-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ECDSA-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 "ECDHE-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 "ECDHE-ARIA256-GCM-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 "ECDH-ARIA128-GCM-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 "ECDH-ARIA256-GCM-SHA384" +# define TLS1_TXT_PSK_WITH_ARIA_128_GCM_SHA256 "PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_ARIA_256_GCM_SHA384 "PSK-ARIA256-GCM-SHA384" +# define TLS1_TXT_DHE_PSK_WITH_ARIA_128_GCM_SHA256 "DHE-PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_DHE_PSK_WITH_ARIA_256_GCM_SHA384 "DHE-PSK-ARIA256-GCM-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_ARIA_128_GCM_SHA256 "RSA-PSK-ARIA128-GCM-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_ARIA_256_GCM_SHA384 "RSA-PSK-ARIA256-GCM-SHA384" + +# define TLS_CT_RSA_SIGN 1 +# define TLS_CT_DSS_SIGN 2 +# define TLS_CT_RSA_FIXED_DH 3 +# define TLS_CT_DSS_FIXED_DH 4 +# define TLS_CT_ECDSA_SIGN 64 +# define TLS_CT_RSA_FIXED_ECDH 65 +# define TLS_CT_ECDSA_FIXED_ECDH 66 +# define TLS_CT_GOST01_SIGN 22 +# define TLS_CT_GOST12_SIGN 238 +# define TLS_CT_GOST12_512_SIGN 239 + +/* + * when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see + * comment there) + */ +# define TLS_CT_NUMBER 10 + +# if defined(SSL3_CT_NUMBER) +# if TLS_CT_NUMBER != SSL3_CT_NUMBER +# error "SSL/TLS CT_NUMBER values do not match" +# endif +# endif + +# define TLS1_FINISH_MAC_LENGTH 12 + +# define TLS_MD_MAX_CONST_SIZE 22 +# define TLS_MD_CLIENT_FINISH_CONST "client finished" +# define TLS_MD_CLIENT_FINISH_CONST_SIZE 15 +# define TLS_MD_SERVER_FINISH_CONST "server finished" +# define TLS_MD_SERVER_FINISH_CONST_SIZE 15 +# define TLS_MD_KEY_EXPANSION_CONST "key expansion" +# define TLS_MD_KEY_EXPANSION_CONST_SIZE 13 +# define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key" +# define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +# define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_IV_BLOCK_CONST "IV block" +# define TLS_MD_IV_BLOCK_CONST_SIZE 8 +# define TLS_MD_MASTER_SECRET_CONST "master secret" +# define TLS_MD_MASTER_SECRET_CONST_SIZE 13 +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret" +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22 + +# ifdef CHARSET_EBCDIC +# undef TLS_MD_CLIENT_FINISH_CONST +/* + * client finished + */ +# define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_FINISH_CONST +/* + * server finished + */ +# define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_KEY_EXPANSION_CONST +/* + * key expansion + */ +# define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" + +# undef TLS_MD_CLIENT_WRITE_KEY_CONST +/* + * client write key + */ +# define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_IV_BLOCK_CONST +/* + * IV block + */ +# define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" + +# undef TLS_MD_MASTER_SECRET_CONST +/* + * master secret + */ +# define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" +# undef TLS_MD_EXTENDED_MASTER_SECRET_CONST +/* + * extended master secret + */ +# define TLS_MD_EXTENDED_MASTER_SECRET_CONST "\x65\x78\x74\x65\x63\x64\x65\x64\x20\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" +# endif + +/* TLS Session Ticket extension struct */ +struct tls_session_ticket_ext_st { + unsigned short length; + void *data; +}; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/ts.h b/thirdparty/user_include/openssl/ts.h new file mode 100755 index 0000000000000000000000000000000000000000..3b58aa527ede3b41d161de6c458cbf9274165e2c --- /dev/null +++ b/thirdparty/user_include/openssl/ts.h @@ -0,0 +1,559 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TS_H +# define HEADER_TS_H + +# include + +# ifndef OPENSSL_NO_TS +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# include +# include + +typedef struct TS_msg_imprint_st TS_MSG_IMPRINT; +typedef struct TS_req_st TS_REQ; +typedef struct TS_accuracy_st TS_ACCURACY; +typedef struct TS_tst_info_st TS_TST_INFO; + +/* Possible values for status. */ +# define TS_STATUS_GRANTED 0 +# define TS_STATUS_GRANTED_WITH_MODS 1 +# define TS_STATUS_REJECTION 2 +# define TS_STATUS_WAITING 3 +# define TS_STATUS_REVOCATION_WARNING 4 +# define TS_STATUS_REVOCATION_NOTIFICATION 5 + +/* Possible values for failure_info. */ +# define TS_INFO_BAD_ALG 0 +# define TS_INFO_BAD_REQUEST 2 +# define TS_INFO_BAD_DATA_FORMAT 5 +# define TS_INFO_TIME_NOT_AVAILABLE 14 +# define TS_INFO_UNACCEPTED_POLICY 15 +# define TS_INFO_UNACCEPTED_EXTENSION 16 +# define TS_INFO_ADD_INFO_NOT_AVAILABLE 17 +# define TS_INFO_SYSTEM_FAILURE 25 + + +typedef struct TS_status_info_st TS_STATUS_INFO; +typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL; +typedef struct ESS_cert_id ESS_CERT_ID; +typedef struct ESS_signing_cert ESS_SIGNING_CERT; + +DEFINE_STACK_OF(ESS_CERT_ID) + +typedef struct ESS_cert_id_v2_st ESS_CERT_ID_V2; +typedef struct ESS_signing_cert_v2_st ESS_SIGNING_CERT_V2; + +DEFINE_STACK_OF(ESS_CERT_ID_V2) + +typedef struct TS_resp_st TS_RESP; + +TS_REQ *TS_REQ_new(void); +void TS_REQ_free(TS_REQ *a); +int i2d_TS_REQ(const TS_REQ *a, unsigned char **pp); +TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length); + +TS_REQ *TS_REQ_dup(TS_REQ *a); + +#ifndef OPENSSL_NO_STDIO +TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a); +int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a); +#endif +TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a); +int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_new(void); +void TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a); +int i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **pp); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a, + const unsigned char **pp, long length); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a); + +#ifndef OPENSSL_NO_STDIO +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a); +#endif +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_bio(BIO *bio, TS_MSG_IMPRINT *a); + +TS_RESP *TS_RESP_new(void); +void TS_RESP_free(TS_RESP *a); +int i2d_TS_RESP(const TS_RESP *a, unsigned char **pp); +TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length); +TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token); +TS_RESP *TS_RESP_dup(TS_RESP *a); + +#ifndef OPENSSL_NO_STDIO +TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a); +int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a); +#endif +TS_RESP *d2i_TS_RESP_bio(BIO *bio, TS_RESP **a); +int i2d_TS_RESP_bio(BIO *bio, TS_RESP *a); + +TS_STATUS_INFO *TS_STATUS_INFO_new(void); +void TS_STATUS_INFO_free(TS_STATUS_INFO *a); +int i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **pp); +TS_STATUS_INFO *d2i_TS_STATUS_INFO(TS_STATUS_INFO **a, + const unsigned char **pp, long length); +TS_STATUS_INFO *TS_STATUS_INFO_dup(TS_STATUS_INFO *a); + +TS_TST_INFO *TS_TST_INFO_new(void); +void TS_TST_INFO_free(TS_TST_INFO *a); +int i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **pp); +TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp, + long length); +TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a); + +#ifndef OPENSSL_NO_STDIO +TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a); +#endif +TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO **a); +int i2d_TS_TST_INFO_bio(BIO *bio, TS_TST_INFO *a); + +TS_ACCURACY *TS_ACCURACY_new(void); +void TS_ACCURACY_free(TS_ACCURACY *a); +int i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **pp); +TS_ACCURACY *d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **pp, + long length); +TS_ACCURACY *TS_ACCURACY_dup(TS_ACCURACY *a); + +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_new(void); +void ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a); +int i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, unsigned char **pp); +ESS_ISSUER_SERIAL *d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a, + const unsigned char **pp, + long length); +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *a); + +ESS_CERT_ID *ESS_CERT_ID_new(void); +void ESS_CERT_ID_free(ESS_CERT_ID *a); +int i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **pp); +ESS_CERT_ID *d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **pp, + long length); +ESS_CERT_ID *ESS_CERT_ID_dup(ESS_CERT_ID *a); + +ESS_SIGNING_CERT *ESS_SIGNING_CERT_new(void); +void ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a); +int i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, unsigned char **pp); +ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, + const unsigned char **pp, long length); +ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a); + +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new(void); +void ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a); +int i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **pp); +ESS_CERT_ID_V2 *d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a, + const unsigned char **pp, long length); +ESS_CERT_ID_V2 *ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *a); + +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new(void); +void ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a); +int i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a, unsigned char **pp); +ESS_SIGNING_CERT_V2 *d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a, + const unsigned char **pp, + long length); +ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *a); + +int TS_REQ_set_version(TS_REQ *a, long version); +long TS_REQ_get_version(const TS_REQ *a); + +int TS_STATUS_INFO_set_status(TS_STATUS_INFO *a, int i); +const ASN1_INTEGER *TS_STATUS_INFO_get0_status(const TS_STATUS_INFO *a); + +const STACK_OF(ASN1_UTF8STRING) * +TS_STATUS_INFO_get0_text(const TS_STATUS_INFO *a); + +const ASN1_BIT_STRING * +TS_STATUS_INFO_get0_failure_info(const TS_STATUS_INFO *a); + +int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_REQ_get_msg_imprint(TS_REQ *a); + +int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg); +X509_ALGOR *TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a); + +int TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len); +ASN1_OCTET_STRING *TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a); + +int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy); +ASN1_OBJECT *TS_REQ_get_policy_id(TS_REQ *a); + +int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_REQ_get_nonce(const TS_REQ *a); + +int TS_REQ_set_cert_req(TS_REQ *a, int cert_req); +int TS_REQ_get_cert_req(const TS_REQ *a); + +STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a); +void TS_REQ_ext_free(TS_REQ *a); +int TS_REQ_get_ext_count(TS_REQ *a); +int TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos); +int TS_REQ_get_ext_by_OBJ(TS_REQ *a, const ASN1_OBJECT *obj, int lastpos); +int TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos); +X509_EXTENSION *TS_REQ_get_ext(TS_REQ *a, int loc); +X509_EXTENSION *TS_REQ_delete_ext(TS_REQ *a, int loc); +int TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc); +void *TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx); + +/* Function declarations for TS_REQ defined in ts/ts_req_print.c */ + +int TS_REQ_print_bio(BIO *bio, TS_REQ *a); + +/* Function declarations for TS_RESP defined in ts/ts_resp_utils.c */ + +int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *info); +TS_STATUS_INFO *TS_RESP_get_status_info(TS_RESP *a); + +/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */ +void TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info); +PKCS7 *TS_RESP_get_token(TS_RESP *a); +TS_TST_INFO *TS_RESP_get_tst_info(TS_RESP *a); + +int TS_TST_INFO_set_version(TS_TST_INFO *a, long version); +long TS_TST_INFO_get_version(const TS_TST_INFO *a); + +int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy_id); +ASN1_OBJECT *TS_TST_INFO_get_policy_id(TS_TST_INFO *a); + +int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a); + +int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial); +const ASN1_INTEGER *TS_TST_INFO_get_serial(const TS_TST_INFO *a); + +int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime); +const ASN1_GENERALIZEDTIME *TS_TST_INFO_get_time(const TS_TST_INFO *a); + +int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy); +TS_ACCURACY *TS_TST_INFO_get_accuracy(TS_TST_INFO *a); + +int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds); +const ASN1_INTEGER *TS_ACCURACY_get_seconds(const TS_ACCURACY *a); + +int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis); +const ASN1_INTEGER *TS_ACCURACY_get_millis(const TS_ACCURACY *a); + +int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros); +const ASN1_INTEGER *TS_ACCURACY_get_micros(const TS_ACCURACY *a); + +int TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering); +int TS_TST_INFO_get_ordering(const TS_TST_INFO *a); + +int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_TST_INFO_get_nonce(const TS_TST_INFO *a); + +int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa); +GENERAL_NAME *TS_TST_INFO_get_tsa(TS_TST_INFO *a); + +STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a); +void TS_TST_INFO_ext_free(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_count(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos); +int TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, const ASN1_OBJECT *obj, + int lastpos); +int TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos); +X509_EXTENSION *TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc); +X509_EXTENSION *TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc); +int TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc); +void *TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx); + +/* + * Declarations related to response generation, defined in ts/ts_resp_sign.c. + */ + +/* Optional flags for response generation. */ + +/* Don't include the TSA name in response. */ +# define TS_TSA_NAME 0x01 + +/* Set ordering to true in response. */ +# define TS_ORDERING 0x02 + +/* + * Include the signer certificate and the other specified certificates in + * the ESS signing certificate attribute beside the PKCS7 signed data. + * Only the signer certificates is included by default. + */ +# define TS_ESS_CERT_ID_CHAIN 0x04 + +/* Forward declaration. */ +struct TS_resp_ctx; + +/* This must return a unique number less than 160 bits long. */ +typedef ASN1_INTEGER *(*TS_serial_cb) (struct TS_resp_ctx *, void *); + +/* + * This must return the seconds and microseconds since Jan 1, 1970 in the sec + * and usec variables allocated by the caller. Return non-zero for success + * and zero for failure. + */ +typedef int (*TS_time_cb) (struct TS_resp_ctx *, void *, long *sec, + long *usec); + +/* + * This must process the given extension. It can modify the TS_TST_INFO + * object of the context. Return values: !0 (processed), 0 (error, it must + * set the status info/failure info of the response). + */ +typedef int (*TS_extension_cb) (struct TS_resp_ctx *, X509_EXTENSION *, + void *); + +typedef struct TS_resp_ctx TS_RESP_CTX; + +DEFINE_STACK_OF_CONST(EVP_MD) + +/* Creates a response context that can be used for generating responses. */ +TS_RESP_CTX *TS_RESP_CTX_new(void); +void TS_RESP_CTX_free(TS_RESP_CTX *ctx); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key); + +int TS_RESP_CTX_set_signer_digest(TS_RESP_CTX *ctx, + const EVP_MD *signer_digest); +int TS_RESP_CTX_set_ess_cert_id_digest(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy); + +/* No additional certs are included in the response by default. */ +int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs); + +/* + * Adds a new acceptable policy, only the default policy is accepted by + * default. + */ +int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy); + +/* + * Adds a new acceptable message digest. Note that no message digests are + * accepted by default. The md argument is shared with the caller. + */ +int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* Accuracy is not included by default. */ +int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, + int secs, int millis, int micros); + +/* + * Clock precision digits, i.e. the number of decimal digits: '0' means sec, + * '3' msec, '6' usec, and so on. Default is 0. + */ +int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, + unsigned clock_precision_digits); +/* At most we accept usec precision. */ +# define TS_MAX_CLOCK_PRECISION_DIGITS 6 + +/* Maximum status message length */ +# define TS_MAX_STATUS_LENGTH (1024 * 1024) + +/* No flags are set by default. */ +void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags); + +/* Default callback always returns a constant. */ +void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data); + +/* Default callback uses the gettimeofday() and gmtime() system calls. */ +void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data); + +/* + * Default callback rejects all extensions. The extension callback is called + * when the TS_TST_INFO object is already set up and not signed yet. + */ +/* FIXME: extension handling is not tested yet. */ +void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, + TS_extension_cb cb, void *data); + +/* The following methods can be used in the callbacks. */ +int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, + int status, const char *text); + +/* Sets the status info only if it is still TS_STATUS_GRANTED. */ +int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, + int status, const char *text); + +int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure); + +/* The get methods below can be used in the extension callback. */ +TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx); + +TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx); + +/* + * Creates the signed TS_TST_INFO and puts it in TS_RESP. + * In case of errors it sets the status info properly. + * Returns NULL only in case of memory allocation/fatal error. + */ +TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio); + +/* + * Declarations related to response verification, + * they are defined in ts/ts_resp_verify.c. + */ + +int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, + X509_STORE *store, X509 **signer_out); + +/* Context structure for the generic verify method. */ + +/* Verify the signer's certificate and the signature of the response. */ +# define TS_VFY_SIGNATURE (1u << 0) +/* Verify the version number of the response. */ +# define TS_VFY_VERSION (1u << 1) +/* Verify if the policy supplied by the user matches the policy of the TSA. */ +# define TS_VFY_POLICY (1u << 2) +/* + * Verify the message imprint provided by the user. This flag should not be + * specified with TS_VFY_DATA. + */ +# define TS_VFY_IMPRINT (1u << 3) +/* + * Verify the message imprint computed by the verify method from the user + * provided data and the MD algorithm of the response. This flag should not + * be specified with TS_VFY_IMPRINT. + */ +# define TS_VFY_DATA (1u << 4) +/* Verify the nonce value. */ +# define TS_VFY_NONCE (1u << 5) +/* Verify if the TSA name field matches the signer certificate. */ +# define TS_VFY_SIGNER (1u << 6) +/* Verify if the TSA name field equals to the user provided name. */ +# define TS_VFY_TSA_NAME (1u << 7) + +/* You can use the following convenience constants. */ +# define TS_VFY_ALL_IMPRINT (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_IMPRINT \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) +# define TS_VFY_ALL_DATA (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_DATA \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) + +typedef struct TS_verify_ctx TS_VERIFY_CTX; + +int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response); +int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token); + +/* + * Declarations related to response verification context, + */ +TS_VERIFY_CTX *TS_VERIFY_CTX_new(void); +void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx); +int TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int f); +int TS_VERIFY_CTX_add_flags(TS_VERIFY_CTX *ctx, int f); +BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *b); +unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, + unsigned char *hexstr, long len); +X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s); +STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs); + +/*- + * If ctx is NULL, it allocates and returns a new object, otherwise + * it returns ctx. It initialises all the members as follows: + * flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE) + * certs = NULL + * store = NULL + * policy = policy from the request or NULL if absent (in this case + * TS_VFY_POLICY is cleared from flags as well) + * md_alg = MD algorithm from request + * imprint, imprint_len = imprint from request + * data = NULL + * nonce, nonce_len = nonce from the request or NULL if absent (in this case + * TS_VFY_NONCE is cleared from flags as well) + * tsa_name = NULL + * Important: after calling this method TS_VFY_SIGNATURE should be added! + */ +TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx); + +/* Function declarations for TS_RESP defined in ts/ts_resp_print.c */ + +int TS_RESP_print_bio(BIO *bio, TS_RESP *a); +int TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a); +int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a); + +/* Common utility functions defined in ts/ts_lib.c */ + +int TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num); +int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj); +int TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions); +int TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg); +int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *msg); + +/* + * Function declarations for handling configuration options, defined in + * ts/ts_conf.c + */ + +X509 *TS_CONF_load_cert(const char *file); +STACK_OF(X509) *TS_CONF_load_certs(const char *file); +EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass); +const char *TS_CONF_get_tsa_section(CONF *conf, const char *section); +int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, + TS_RESP_CTX *ctx); +#ifndef OPENSSL_NO_ENGINE +int TS_CONF_set_crypto_device(CONF *conf, const char *section, + const char *device); +int TS_CONF_set_default_engine(const char *name); +#endif +int TS_CONF_set_signer_cert(CONF *conf, const char *section, + const char *cert, TS_RESP_CTX *ctx); +int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_key(CONF *conf, const char *section, + const char *key, const char *pass, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_digest(CONF *conf, const char *section, + const char *md, TS_RESP_CTX *ctx); +int TS_CONF_set_def_policy(CONF *conf, const char *section, + const char *policy, TS_RESP_CTX *ctx); +int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, + TS_RESP_CTX *ctx); + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/thirdparty/user_include/openssl/tserr.h b/thirdparty/user_include/openssl/tserr.h new file mode 100755 index 0000000000000000000000000000000000000000..3e0492565764e8d187776d1c5747491d73f19c0a --- /dev/null +++ b/thirdparty/user_include/openssl/tserr.h @@ -0,0 +1,128 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TSERR_H +# define HEADER_TSERR_H + +# include + +# ifndef OPENSSL_NO_TS + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_TS_strings(void); + +/* + * TS function codes. + */ +# define TS_F_DEF_SERIAL_CB 110 +# define TS_F_DEF_TIME_CB 111 +# define TS_F_ESS_ADD_SIGNING_CERT 112 +# define TS_F_ESS_ADD_SIGNING_CERT_V2 147 +# define TS_F_ESS_CERT_ID_NEW_INIT 113 +# define TS_F_ESS_CERT_ID_V2_NEW_INIT 156 +# define TS_F_ESS_SIGNING_CERT_NEW_INIT 114 +# define TS_F_ESS_SIGNING_CERT_V2_NEW_INIT 157 +# define TS_F_INT_TS_RESP_VERIFY_TOKEN 149 +# define TS_F_PKCS7_TO_TS_TST_INFO 148 +# define TS_F_TS_ACCURACY_SET_MICROS 115 +# define TS_F_TS_ACCURACY_SET_MILLIS 116 +# define TS_F_TS_ACCURACY_SET_SECONDS 117 +# define TS_F_TS_CHECK_IMPRINTS 100 +# define TS_F_TS_CHECK_NONCES 101 +# define TS_F_TS_CHECK_POLICY 102 +# define TS_F_TS_CHECK_SIGNING_CERTS 103 +# define TS_F_TS_CHECK_STATUS_INFO 104 +# define TS_F_TS_COMPUTE_IMPRINT 145 +# define TS_F_TS_CONF_INVALID 151 +# define TS_F_TS_CONF_LOAD_CERT 153 +# define TS_F_TS_CONF_LOAD_CERTS 154 +# define TS_F_TS_CONF_LOAD_KEY 155 +# define TS_F_TS_CONF_LOOKUP_FAIL 152 +# define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146 +# define TS_F_TS_GET_STATUS_TEXT 105 +# define TS_F_TS_MSG_IMPRINT_SET_ALGO 118 +# define TS_F_TS_REQ_SET_MSG_IMPRINT 119 +# define TS_F_TS_REQ_SET_NONCE 120 +# define TS_F_TS_REQ_SET_POLICY_ID 121 +# define TS_F_TS_RESP_CREATE_RESPONSE 122 +# define TS_F_TS_RESP_CREATE_TST_INFO 123 +# define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 124 +# define TS_F_TS_RESP_CTX_ADD_MD 125 +# define TS_F_TS_RESP_CTX_ADD_POLICY 126 +# define TS_F_TS_RESP_CTX_NEW 127 +# define TS_F_TS_RESP_CTX_SET_ACCURACY 128 +# define TS_F_TS_RESP_CTX_SET_CERTS 129 +# define TS_F_TS_RESP_CTX_SET_DEF_POLICY 130 +# define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 131 +# define TS_F_TS_RESP_CTX_SET_STATUS_INFO 132 +# define TS_F_TS_RESP_GET_POLICY 133 +# define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 134 +# define TS_F_TS_RESP_SET_STATUS_INFO 135 +# define TS_F_TS_RESP_SET_TST_INFO 150 +# define TS_F_TS_RESP_SIGN 136 +# define TS_F_TS_RESP_VERIFY_SIGNATURE 106 +# define TS_F_TS_TST_INFO_SET_ACCURACY 137 +# define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 138 +# define TS_F_TS_TST_INFO_SET_NONCE 139 +# define TS_F_TS_TST_INFO_SET_POLICY_ID 140 +# define TS_F_TS_TST_INFO_SET_SERIAL 141 +# define TS_F_TS_TST_INFO_SET_TIME 142 +# define TS_F_TS_TST_INFO_SET_TSA 143 +# define TS_F_TS_VERIFY 108 +# define TS_F_TS_VERIFY_CERT 109 +# define TS_F_TS_VERIFY_CTX_NEW 144 + +/* + * TS reason codes. + */ +# define TS_R_BAD_PKCS7_TYPE 132 +# define TS_R_BAD_TYPE 133 +# define TS_R_CANNOT_LOAD_CERT 137 +# define TS_R_CANNOT_LOAD_KEY 138 +# define TS_R_CERTIFICATE_VERIFY_ERROR 100 +# define TS_R_COULD_NOT_SET_ENGINE 127 +# define TS_R_COULD_NOT_SET_TIME 115 +# define TS_R_DETACHED_CONTENT 134 +# define TS_R_ESS_ADD_SIGNING_CERT_ERROR 116 +# define TS_R_ESS_ADD_SIGNING_CERT_V2_ERROR 139 +# define TS_R_ESS_SIGNING_CERTIFICATE_ERROR 101 +# define TS_R_INVALID_NULL_POINTER 102 +# define TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE 117 +# define TS_R_MESSAGE_IMPRINT_MISMATCH 103 +# define TS_R_NONCE_MISMATCH 104 +# define TS_R_NONCE_NOT_RETURNED 105 +# define TS_R_NO_CONTENT 106 +# define TS_R_NO_TIME_STAMP_TOKEN 107 +# define TS_R_PKCS7_ADD_SIGNATURE_ERROR 118 +# define TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR 119 +# define TS_R_PKCS7_TO_TS_TST_INFO_FAILED 129 +# define TS_R_POLICY_MISMATCH 108 +# define TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 120 +# define TS_R_RESPONSE_SETUP_ERROR 121 +# define TS_R_SIGNATURE_FAILURE 109 +# define TS_R_THERE_MUST_BE_ONE_SIGNER 110 +# define TS_R_TIME_SYSCALL_ERROR 122 +# define TS_R_TOKEN_NOT_PRESENT 130 +# define TS_R_TOKEN_PRESENT 131 +# define TS_R_TSA_NAME_MISMATCH 111 +# define TS_R_TSA_UNTRUSTED 112 +# define TS_R_TST_INFO_SETUP_ERROR 123 +# define TS_R_TS_DATASIGN 124 +# define TS_R_UNACCEPTABLE_POLICY 125 +# define TS_R_UNSUPPORTED_MD_ALGORITHM 126 +# define TS_R_UNSUPPORTED_VERSION 113 +# define TS_R_VAR_BAD_VALUE 135 +# define TS_R_VAR_LOOKUP_FAILURE 136 +# define TS_R_WRONG_CONTENT_TYPE 114 + +# endif +#endif diff --git a/thirdparty/user_include/openssl/txt_db.h b/thirdparty/user_include/openssl/txt_db.h new file mode 100755 index 0000000000000000000000000000000000000000..ec981a439fe8bf5d7d52f7b603985ca4eb620a6e --- /dev/null +++ b/thirdparty/user_include/openssl/txt_db.h @@ -0,0 +1,57 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_TXT_DB_H +# define HEADER_TXT_DB_H + +# include +# include +# include +# include + +# define DB_ERROR_OK 0 +# define DB_ERROR_MALLOC 1 +# define DB_ERROR_INDEX_CLASH 2 +# define DB_ERROR_INDEX_OUT_OF_RANGE 3 +# define DB_ERROR_NO_INDEX 4 +# define DB_ERROR_INSERT_INDEX_CLASH 5 +# define DB_ERROR_WRONG_NUM_FIELDS 6 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OPENSSL_STRING *OPENSSL_PSTRING; +DEFINE_SPECIAL_STACK_OF(OPENSSL_PSTRING, OPENSSL_STRING) + +typedef struct txt_db_st { + int num_fields; + STACK_OF(OPENSSL_PSTRING) *data; + LHASH_OF(OPENSSL_STRING) **index; + int (**qual) (OPENSSL_STRING *); + long error; + long arg1; + long arg2; + OPENSSL_STRING *arg_row; +} TXT_DB; + +TXT_DB *TXT_DB_read(BIO *in, int num); +long TXT_DB_write(BIO *out, TXT_DB *db); +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), + OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp); +void TXT_DB_free(TXT_DB *db); +OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, + OPENSSL_STRING *value); +int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/user_include/openssl/ui.h b/thirdparty/user_include/openssl/ui.h new file mode 100755 index 0000000000000000000000000000000000000000..7c721ec818ddbffb6d10c94bc4c4af259a12411e --- /dev/null +++ b/thirdparty/user_include/openssl/ui.h @@ -0,0 +1,368 @@ +/* + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_UI_H +# define HEADER_UI_H + +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# endif +# include +# include +# include +# include + +/* For compatibility reasons, the macro OPENSSL_NO_UI is currently retained */ +# if OPENSSL_API_COMPAT < 0x10200000L +# ifdef OPENSSL_NO_UI_CONSOLE +# define OPENSSL_NO_UI +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +/* + * All the following functions return -1 or NULL on error and in some cases + * (UI_process()) -2 if interrupted or in some other way cancelled. When + * everything is fine, they return 0, a positive value or a non-NULL pointer, + * all depending on their purpose. + */ + +/* Creators and destructor. */ +UI *UI_new(void); +UI *UI_new_method(const UI_METHOD *method); +void UI_free(UI *ui); + +/*- + The following functions are used to add strings to be printed and prompt + strings to prompt for data. The names are UI_{add,dup}__string + and UI_{add,dup}_input_boolean. + + UI_{add,dup}__string have the following meanings: + add add a text or prompt string. The pointers given to these + functions are used verbatim, no copying is done. + dup make a copy of the text or prompt string, then add the copy + to the collection of strings in the user interface. + + The function is a name for the functionality that the given + string shall be used for. It can be one of: + input use the string as data prompt. + verify use the string as verification prompt. This + is used to verify a previous input. + info use the string for informational output. + error use the string for error output. + Honestly, there's currently no difference between info and error for the + moment. + + UI_{add,dup}_input_boolean have the same semantics for "add" and "dup", + and are typically used when one wants to prompt for a yes/no response. + + All of the functions in this group take a UI and a prompt string. + The string input and verify addition functions also take a flag argument, + a buffer for the result to end up with, a minimum input size and a maximum + input size (the result buffer MUST be large enough to be able to contain + the maximum number of characters). Additionally, the verify addition + functions takes another buffer to compare the result against. + The boolean input functions take an action description string (which should + be safe to ignore if the expected user action is obvious, for example with + a dialog box with an OK button and a Cancel button), a string of acceptable + characters to mean OK and to mean Cancel. The two last strings are checked + to make sure they don't have common characters. Additionally, the same + flag argument as for the string input is taken, as well as a result buffer. + The result buffer is required to be at least one byte long. Depending on + the answer, the first character from the OK or the Cancel character strings + will be stored in the first byte of the result buffer. No NUL will be + added, so the result is *not* a string. + + On success, the all return an index of the added information. That index + is useful when retrieving results with UI_get0_result(). */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_add_info_string(UI *ui, const char *text); +int UI_dup_info_string(UI *ui, const char *text); +int UI_add_error_string(UI *ui, const char *text); +int UI_dup_error_string(UI *ui, const char *text); + +/* These are the possible flags. They can be or'ed together. */ +/* Use to have echoing of input */ +# define UI_INPUT_FLAG_ECHO 0x01 +/* + * Use a default password. Where that password is found is completely up to + * the application, it might for example be in the user data set with + * UI_add_user_data(). It is not recommended to have more than one input in + * each UI being marked with this flag, or the application might get + * confused. + */ +# define UI_INPUT_FLAG_DEFAULT_PWD 0x02 + +/*- + * The user of these routines may want to define flags of their own. The core + * UI won't look at those, but will pass them on to the method routines. They + * must use higher bits so they don't get confused with the UI bits above. + * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good + * example of use is this: + * + * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE) + * +*/ +# define UI_INPUT_FLAG_USER_BASE 16 + +/*- + * The following function helps construct a prompt. object_desc is a + * textual short description of the object, for example "pass phrase", + * and object_name is the name of the object (might be a card name or + * a file name. + * The returned string shall always be allocated on the heap with + * OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). + * + * If the ui_method doesn't contain a pointer to a user-defined prompt + * constructor, a default string is built, looking like this: + * + * "Enter {object_desc} for {object_name}:" + * + * So, if object_desc has the value "pass phrase" and object_name has + * the value "foo.key", the resulting string is: + * + * "Enter pass phrase for foo.key:" +*/ +char *UI_construct_prompt(UI *ui_method, + const char *object_desc, const char *object_name); + +/* + * The following function is used to store a pointer to user-specific data. + * Any previous such pointer will be returned and replaced. + * + * For callback purposes, this function makes a lot more sense than using + * ex_data, since the latter requires that different parts of OpenSSL or + * applications share the same ex_data index. + * + * Note that the UI_OpenSSL() method completely ignores the user data. Other + * methods may not, however. + */ +void *UI_add_user_data(UI *ui, void *user_data); +/* + * Alternatively, this function is used to duplicate the user data. + * This uses the duplicator method function. The destroy function will + * be used to free the user data in this case. + */ +int UI_dup_user_data(UI *ui, void *user_data); +/* We need a user data retrieving function as well. */ +void *UI_get0_user_data(UI *ui); + +/* Return the result associated with a prompt given with the index i. */ +const char *UI_get0_result(UI *ui, int i); +int UI_get_result_length(UI *ui, int i); + +/* When all strings have been added, process the whole thing. */ +int UI_process(UI *ui); + +/* + * Give a user interface parameterised control commands. This can be used to + * send down an integer, a data pointer or a function pointer, as well as be + * used to get information from a UI. + */ +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)); + +/* The commands */ +/* + * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the + * OpenSSL error stack before printing any info or added error messages and + * before any prompting. + */ +# define UI_CTRL_PRINT_ERRORS 1 +/* + * Check if a UI_process() is possible to do again with the same instance of + * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0 + * if not. + */ +# define UI_CTRL_IS_REDOABLE 2 + +/* Some methods may use extra data */ +# define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg) +# define UI_get_app_data(s) UI_get_ex_data(s,0) + +# define UI_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, l, p, newf, dupf, freef) +int UI_set_ex_data(UI *r, int idx, void *arg); +void *UI_get_ex_data(UI *r, int idx); + +/* Use specific methods instead of the built-in one */ +void UI_set_default_method(const UI_METHOD *meth); +const UI_METHOD *UI_get_default_method(void); +const UI_METHOD *UI_get_method(UI *ui); +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth); + +# ifndef OPENSSL_NO_UI_CONSOLE + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void); + +# endif + +/* + * NULL method. Literally does nothing, but may serve as a placeholder + * to avoid internal default. + */ +const UI_METHOD *UI_null(void); + +/* ---------- For method writers ---------- */ +/*- + A method contains a number of functions that implement the low level + of the User Interface. The functions are: + + an opener This function starts a session, maybe by opening + a channel to a tty, or by opening a window. + a writer This function is called to write a given string, + maybe to the tty, maybe as a field label in a + window. + a flusher This function is called to flush everything that + has been output so far. It can be used to actually + display a dialog box after it has been built. + a reader This function is called to read a given prompt, + maybe from the tty, maybe from a field in a + window. Note that it's called with all string + structures, not only the prompt ones, so it must + check such things itself. + a closer This function closes the session, maybe by closing + the channel to the tty, or closing the window. + + All these functions are expected to return: + + 0 on error. + 1 on success. + -1 on out-of-band events, for example if some prompting has + been canceled (by pressing Ctrl-C, for example). This is + only checked when returned by the flusher or the reader. + + The way this is used, the opener is first called, then the writer for all + strings, then the flusher, then the reader for all strings and finally the + closer. Note that if you want to prompt from a terminal or other command + line interface, the best is to have the reader also write the prompts + instead of having the writer do it. If you want to prompt from a dialog + box, the writer can be used to build up the contents of the box, and the + flusher to actually display the box and run the event loop until all data + has been given, after which the reader only grabs the given data and puts + them back into the UI strings. + + All method functions take a UI as argument. Additionally, the writer and + the reader take a UI_STRING. +*/ + +/* + * The UI_STRING type is the data structure that contains all the needed info + * about a string or a prompt, including test data for a verification prompt. + */ +typedef struct ui_string_st UI_STRING; +DEFINE_STACK_OF(UI_STRING) + +/* + * The different types of strings that are currently supported. This is only + * needed by method authors. + */ +enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, /* Prompt for a string */ + UIT_VERIFY, /* Prompt for a string and verify */ + UIT_BOOLEAN, /* Prompt for a yes/no response */ + UIT_INFO, /* Send info to the user */ + UIT_ERROR /* Send an error message to the user */ +}; + +/* Create and manipulate methods */ +UI_METHOD *UI_create_method(const char *name); +void UI_destroy_method(UI_METHOD *ui_method); +int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)); +int UI_method_set_writer(UI_METHOD *method, + int (*writer) (UI *ui, UI_STRING *uis)); +int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)); +int UI_method_set_reader(UI_METHOD *method, + int (*reader) (UI *ui, UI_STRING *uis)); +int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)); +int UI_method_set_data_duplicator(UI_METHOD *method, + void *(*duplicator) (UI *ui, void *ui_data), + void (*destructor)(UI *ui, void *ui_data)); +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor) (UI *ui, + const char + *object_desc, + const char + *object_name)); +int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data); +int (*UI_method_get_opener(const UI_METHOD *method)) (UI *); +int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *); +int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_closer(const UI_METHOD *method)) (UI *); +char *(*UI_method_get_prompt_constructor(const UI_METHOD *method)) + (UI *, const char *, const char *); +void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *); +void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *); +const void *UI_method_get_ex_data(const UI_METHOD *method, int idx); + +/* + * The following functions are helpers for method writers to access relevant + * data from a UI_STRING. + */ + +/* Return type of the UI_STRING */ +enum UI_string_types UI_get_string_type(UI_STRING *uis); +/* Return input flags of the UI_STRING */ +int UI_get_input_flags(UI_STRING *uis); +/* Return the actual string to output (the prompt, info or error) */ +const char *UI_get0_output_string(UI_STRING *uis); +/* + * Return the optional action string to output (the boolean prompt + * instruction) + */ +const char *UI_get0_action_string(UI_STRING *uis); +/* Return the result of a prompt */ +const char *UI_get0_result_string(UI_STRING *uis); +int UI_get_result_string_length(UI_STRING *uis); +/* + * Return the string to test the result against. Only useful with verifies. + */ +const char *UI_get0_test_string(UI_STRING *uis); +/* Return the required minimum size of the result */ +int UI_get_result_minsize(UI_STRING *uis); +/* Return the required maximum size of the result */ +int UI_get_result_maxsize(UI_STRING *uis); +/* Set the result of a UI_STRING. */ +int UI_set_result(UI *ui, UI_STRING *uis, const char *result); +int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len); + +/* A couple of popular utility functions */ +int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int verify); +int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify); +UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag); + + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/uierr.h b/thirdparty/user_include/openssl/uierr.h new file mode 100755 index 0000000000000000000000000000000000000000..72fd9a9db04af619eb1147babf3b1103bf39d427 --- /dev/null +++ b/thirdparty/user_include/openssl/uierr.h @@ -0,0 +1,61 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_UIERR_H +# define HEADER_UIERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_UI_strings(void); + +/* + * UI function codes. + */ +# define UI_F_CLOSE_CONSOLE 115 +# define UI_F_ECHO_CONSOLE 116 +# define UI_F_GENERAL_ALLOCATE_BOOLEAN 108 +# define UI_F_GENERAL_ALLOCATE_PROMPT 109 +# define UI_F_NOECHO_CONSOLE 117 +# define UI_F_OPEN_CONSOLE 114 +# define UI_F_UI_CONSTRUCT_PROMPT 121 +# define UI_F_UI_CREATE_METHOD 112 +# define UI_F_UI_CTRL 111 +# define UI_F_UI_DUP_ERROR_STRING 101 +# define UI_F_UI_DUP_INFO_STRING 102 +# define UI_F_UI_DUP_INPUT_BOOLEAN 110 +# define UI_F_UI_DUP_INPUT_STRING 103 +# define UI_F_UI_DUP_USER_DATA 118 +# define UI_F_UI_DUP_VERIFY_STRING 106 +# define UI_F_UI_GET0_RESULT 107 +# define UI_F_UI_GET_RESULT_LENGTH 119 +# define UI_F_UI_NEW_METHOD 104 +# define UI_F_UI_PROCESS 113 +# define UI_F_UI_SET_RESULT 105 +# define UI_F_UI_SET_RESULT_EX 120 + +/* + * UI reason codes. + */ +# define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104 +# define UI_R_INDEX_TOO_LARGE 102 +# define UI_R_INDEX_TOO_SMALL 103 +# define UI_R_NO_RESULT_BUFFER 105 +# define UI_R_PROCESSING_ERROR 107 +# define UI_R_RESULT_TOO_LARGE 100 +# define UI_R_RESULT_TOO_SMALL 101 +# define UI_R_SYSASSIGN_ERROR 109 +# define UI_R_SYSDASSGN_ERROR 110 +# define UI_R_SYSQIOW_ERROR 111 +# define UI_R_UNKNOWN_CONTROL_COMMAND 106 +# define UI_R_UNKNOWN_TTYGET_ERRNO_VALUE 108 +# define UI_R_USER_DATA_DUPLICATION_UNSUPPORTED 112 + +#endif diff --git a/thirdparty/user_include/openssl/whrlpool.h b/thirdparty/user_include/openssl/whrlpool.h new file mode 100755 index 0000000000000000000000000000000000000000..20ea3503b76fe6c9d97cc68ffe6665fd6aa227b0 --- /dev/null +++ b/thirdparty/user_include/openssl/whrlpool.h @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_WHRLPOOL_H +# define HEADER_WHRLPOOL_H + +#include + +# ifndef OPENSSL_NO_WHIRLPOOL +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +# define WHIRLPOOL_DIGEST_LENGTH (512/8) +# define WHIRLPOOL_BBLOCK 512 +# define WHIRLPOOL_COUNTER (256/8) + +typedef struct { + union { + unsigned char c[WHIRLPOOL_DIGEST_LENGTH]; + /* double q is here to ensure 64-bit alignment */ + double q[WHIRLPOOL_DIGEST_LENGTH / sizeof(double)]; + } H; + unsigned char data[WHIRLPOOL_BBLOCK / 8]; + unsigned int bitoff; + size_t bitlen[WHIRLPOOL_COUNTER / sizeof(size_t)]; +} WHIRLPOOL_CTX; + +int WHIRLPOOL_Init(WHIRLPOOL_CTX *c); +int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *inp, size_t bytes); +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *inp, size_t bits); +int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c); +unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md); + +# ifdef __cplusplus +} +# endif +# endif + +#endif diff --git a/thirdparty/user_include/openssl/x509.h b/thirdparty/user_include/openssl/x509.h new file mode 100755 index 0000000000000000000000000000000000000000..39ca0ba575615a147ced9edf4ad5a777f7d76fb3 --- /dev/null +++ b/thirdparty/user_include/openssl/x509.h @@ -0,0 +1,1047 @@ +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509_H +# define HEADER_X509_H + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# if OPENSSL_API_COMPAT < 0x10100000L +# include +# include +# include +# endif + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Flags for X509_get_signature_info() */ +/* Signature info is valid */ +# define X509_SIG_INFO_VALID 0x1 +/* Signature is suitable for TLS use */ +# define X509_SIG_INFO_TLS 0x2 + +# define X509_FILETYPE_PEM 1 +# define X509_FILETYPE_ASN1 2 +# define X509_FILETYPE_DEFAULT 3 + +# define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +# define X509v3_KU_NON_REPUDIATION 0x0040 +# define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +# define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +# define X509v3_KU_KEY_AGREEMENT 0x0008 +# define X509v3_KU_KEY_CERT_SIGN 0x0004 +# define X509v3_KU_CRL_SIGN 0x0002 +# define X509v3_KU_ENCIPHER_ONLY 0x0001 +# define X509v3_KU_DECIPHER_ONLY 0x8000 +# define X509v3_KU_UNDEF 0xffff + +struct X509_algor_st { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; +} /* X509_ALGOR */ ; + +typedef STACK_OF(X509_ALGOR) X509_ALGORS; + +typedef struct X509_val_st { + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; +} X509_VAL; + +typedef struct X509_sig_st X509_SIG; + +typedef struct X509_name_entry_st X509_NAME_ENTRY; + +DEFINE_STACK_OF(X509_NAME_ENTRY) + +DEFINE_STACK_OF(X509_NAME) + +# define X509_EX_V_NETSCAPE_HACK 0x8000 +# define X509_EX_V_INIT 0x0001 +typedef struct X509_extension_st X509_EXTENSION; + +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +DEFINE_STACK_OF(X509_EXTENSION) + +typedef struct x509_attributes_st X509_ATTRIBUTE; + +DEFINE_STACK_OF(X509_ATTRIBUTE) + +typedef struct X509_req_info_st X509_REQ_INFO; + +typedef struct X509_req_st X509_REQ; + +typedef struct x509_cert_aux_st X509_CERT_AUX; + +typedef struct x509_cinf_st X509_CINF; + +DEFINE_STACK_OF(X509) + +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust; + int flags; + int (*check_trust) (struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} X509_TRUST; + +DEFINE_STACK_OF(X509_TRUST) + +/* standard trust ids */ + +# define X509_TRUST_DEFAULT 0 /* Only valid in purpose settings */ + +# define X509_TRUST_COMPAT 1 +# define X509_TRUST_SSL_CLIENT 2 +# define X509_TRUST_SSL_SERVER 3 +# define X509_TRUST_EMAIL 4 +# define X509_TRUST_OBJECT_SIGN 5 +# define X509_TRUST_OCSP_SIGN 6 +# define X509_TRUST_OCSP_REQUEST 7 +# define X509_TRUST_TSA 8 + +/* Keep these up to date! */ +# define X509_TRUST_MIN 1 +# define X509_TRUST_MAX 8 + +/* trust_flags values */ +# define X509_TRUST_DYNAMIC (1U << 0) +# define X509_TRUST_DYNAMIC_NAME (1U << 1) +/* No compat trust if self-signed, preempts "DO_SS" */ +# define X509_TRUST_NO_SS_COMPAT (1U << 2) +/* Compat trust if no explicit accepted trust EKUs */ +# define X509_TRUST_DO_SS_COMPAT (1U << 3) +/* Accept "anyEKU" as a wildcard trust OID */ +# define X509_TRUST_OK_ANY_EKU (1U << 4) + +/* check_trust return codes */ + +# define X509_TRUST_TRUSTED 1 +# define X509_TRUST_REJECTED 2 +# define X509_TRUST_UNTRUSTED 3 + +/* Flags for X509_print_ex() */ + +# define X509_FLAG_COMPAT 0 +# define X509_FLAG_NO_HEADER 1L +# define X509_FLAG_NO_VERSION (1L << 1) +# define X509_FLAG_NO_SERIAL (1L << 2) +# define X509_FLAG_NO_SIGNAME (1L << 3) +# define X509_FLAG_NO_ISSUER (1L << 4) +# define X509_FLAG_NO_VALIDITY (1L << 5) +# define X509_FLAG_NO_SUBJECT (1L << 6) +# define X509_FLAG_NO_PUBKEY (1L << 7) +# define X509_FLAG_NO_EXTENSIONS (1L << 8) +# define X509_FLAG_NO_SIGDUMP (1L << 9) +# define X509_FLAG_NO_AUX (1L << 10) +# define X509_FLAG_NO_ATTRIBUTES (1L << 11) +# define X509_FLAG_NO_IDS (1L << 12) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +# define XN_FLAG_SEP_MASK (0xf << 16) + +# define XN_FLAG_COMPAT 0/* Traditional; use old X509_NAME_print */ +# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */ +# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */ +# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */ +# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */ + +# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */ + +/* How the field name is shown */ + +# define XN_FLAG_FN_MASK (0x3 << 21) + +# define XN_FLAG_FN_SN 0/* Object short name */ +# define XN_FLAG_FN_LN (1 << 21)/* Object long name */ +# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */ +# define XN_FLAG_FN_NONE (3 << 21)/* No field names */ + +# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */ + +/* + * This determines if we dump fields we don't recognise: RFC2253 requires + * this. + */ + +# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20 + * characters */ + +/* Complete set of RFC2253 flags */ + +# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) + +DEFINE_STACK_OF(X509_REVOKED) + +typedef struct X509_crl_info_st X509_CRL_INFO; + +DEFINE_STACK_OF(X509_CRL) + +typedef struct private_key_st { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; +} X509_PKEY; + +typedef struct X509_info_st { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; +} X509_INFO; + +DEFINE_STACK_OF(X509_INFO) + +/* + * The next 2 structures and their 8 routines are used to manipulate Netscape's + * spki structures - useful if you are writing a CA web page + */ +typedef struct Netscape_spkac_st { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ +} NETSCAPE_SPKAC; + +typedef struct Netscape_spki_st { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR sig_algor; + ASN1_BIT_STRING *signature; +} NETSCAPE_SPKI; + +/* Netscape certificate sequence structure */ +typedef struct Netscape_certificate_sequence { + ASN1_OBJECT *type; + STACK_OF(X509) *certs; +} NETSCAPE_CERT_SEQUENCE; + +/*- Unused (and iv length is wrong) +typedef struct CBCParameter_st + { + unsigned char iv[8]; + } CBC_PARAM; +*/ + +/* Password based encryption structure */ + +typedef struct PBEPARAM_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; +} PBEPARAM; + +/* Password based encryption V2 structures */ + +typedef struct PBE2PARAM_st { + X509_ALGOR *keyfunc; + X509_ALGOR *encryption; +} PBE2PARAM; + +typedef struct PBKDF2PARAM_st { +/* Usually OCTET STRING but could be anything */ + ASN1_TYPE *salt; + ASN1_INTEGER *iter; + ASN1_INTEGER *keylength; + X509_ALGOR *prf; +} PBKDF2PARAM; + +#ifndef OPENSSL_NO_SCRYPT +typedef struct SCRYPT_PARAMS_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *costParameter; + ASN1_INTEGER *blockSize; + ASN1_INTEGER *parallelizationParameter; + ASN1_INTEGER *keyLength; +} SCRYPT_PARAMS; +#endif + +#ifdef __cplusplus +} +#endif + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define X509_EXT_PACK_UNKNOWN 1 +# define X509_EXT_PACK_STRING 2 + +# define X509_extract_key(x) X509_get_pubkey(x)/*****/ +# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)); +void X509_CRL_METHOD_free(X509_CRL_METHOD *m); + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); +void *X509_CRL_get_meth_data(X509_CRL *crl); + +const char *X509_verify_cert_error_string(long n); + +int X509_verify(X509 *a, EVP_PKEY *r); + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len); +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent); +int X509_signature_print(BIO *bp, const X509_ALGOR *alg, + const ASN1_STRING *sig); + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); +# ifndef OPENSSL_NO_OCSP +int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert); +# endif +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); +# ifndef OPENSSL_NO_OCSP +int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl); +# endif +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); + +# ifndef OPENSSL_NO_STDIO +X509 *d2i_X509_fp(FILE *fp, X509 **x509); +int i2d_X509_fp(FILE *fp, X509 *x509); +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req); +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8); +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); +# endif + +X509 *d2i_X509_bio(BIO *bp, X509 **x509); +int i2d_X509_bio(BIO *bp, X509 *x509); +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8); +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); + +X509 *X509_dup(X509 *x509); +X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +X509_CRL *X509_CRL_dup(X509_CRL *crl); +X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); +X509_REQ *X509_REQ_dup(X509_REQ *req); +X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, + void *pval); +void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, + const void **ppval, const X509_ALGOR *algor); +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + +X509_NAME *X509_NAME_dup(X509_NAME *xn); +X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); + +int X509_cmp_time(const ASN1_TIME *s, time_t *t); +int X509_cmp_current_time(const ASN1_TIME *s); +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *t); +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj); + +const char *X509_get_default_cert_area(void); +const char *X509_get_default_cert_dir(void); +const char *X509_get_default_cert_file(void); +const char *X509_get_default_cert_dir_env(void); +const char *X509_get_default_cert_file_env(void); +const char *X509_get_default_private_dir(void); + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey); + +DECLARE_ASN1_FUNCTIONS(X509_ALGOR) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS) +DECLARE_ASN1_FUNCTIONS(X509_VAL) + +DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key); +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); +int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); +long X509_get_pathlen(X509 *x); +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp); +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length); +# ifndef OPENSSL_NO_RSA +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp); +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_DSA +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp); +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_EC +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp); +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length); +# endif + +DECLARE_ASN1_FUNCTIONS(X509_SIG) +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest); +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, + ASN1_OCTET_STRING **pdigest); + +DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) +DECLARE_ASN1_FUNCTIONS(X509_REQ) + +DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + +DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) + +DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) + +DECLARE_ASN1_FUNCTIONS(X509_NAME) + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(X509_CINF) + +DECLARE_ASN1_FUNCTIONS(X509) +DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) + +#define X509_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, l, p, newf, dupf, freef) +int X509_set_ex_data(X509 *r, int idx, void *arg); +void *X509_get_ex_data(X509 *r, int idx); +int i2d_X509_AUX(X509 *a, unsigned char **pp); +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length); + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + +int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid, + int *secbits, uint32_t *flags); +void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid, + int secbits, uint32_t flags); + +int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, + uint32_t *flags); + +void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); +int X509_get_signature_nid(const X509 *x); + +int X509_trusted(const X509 *x); +int X509_alias_set1(X509 *x, const unsigned char *name, int len); +int X509_keyid_set1(X509 *x, const unsigned char *id, int len); +unsigned char *X509_alias_get0(X509 *x, int *len); +unsigned char *X509_keyid_get0(X509 *x, int *len); +int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, + int); +int X509_TRUST_set(int *t, int trust); +int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj); +int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj); +void X509_trust_clear(X509 *x); +void X509_reject_clear(X509 *x); + +STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x); +STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x); + +DECLARE_ASN1_FUNCTIONS(X509_REVOKED) +DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) +DECLARE_ASN1_FUNCTIONS(X509_CRL) + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial); +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); + +X509_PKEY *X509_PKEY_new(void); +void X509_PKEY_free(X509_PKEY *a); + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) + +X509_INFO *X509_INFO_new(void); +void X509_INFO_free(X509_INFO *a); +char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size); + +int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey); + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len); + +int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + char *data, EVP_PKEY *pkey, const EVP_MD *type); + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data, + unsigned char *md, unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data, + EVP_PKEY *pkey, const EVP_MD *type); +int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + void *asn, EVP_MD_CTX *ctx); + +long X509_get_version(const X509 *x); +int X509_set_version(X509 *x, long version); +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +ASN1_INTEGER *X509_get_serialNumber(X509 *x); +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x); +int X509_set_issuer_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_issuer_name(const X509 *a); +int X509_set_subject_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_subject_name(const X509 *a); +const ASN1_TIME * X509_get0_notBefore(const X509 *x); +ASN1_TIME *X509_getm_notBefore(const X509 *x); +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); +const ASN1_TIME *X509_get0_notAfter(const X509 *x); +ASN1_TIME *X509_getm_notAfter(const X509 *x); +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +int X509_up_ref(X509 *x); +int X509_get_signature_type(const X509 *x); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_get_notBefore X509_getm_notBefore +# define X509_get_notAfter X509_getm_notAfter +# define X509_set_notBefore X509_set1_notBefore +# define X509_set_notAfter X509_set1_notAfter +#endif + + +/* + * This one is only used so that a binary form can output, as in + * i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &buf) + */ +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x); +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); +void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid); +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x); + +EVP_PKEY *X509_get0_pubkey(const X509 *x); +EVP_PKEY *X509_get_pubkey(X509 *x); +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); +int X509_certificate_type(const X509 *x, const EVP_PKEY *pubkey); + +long X509_REQ_get_version(const X509_REQ *req); +int X509_REQ_set_version(X509_REQ *x, long version); +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req); +int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); +void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); +int X509_REQ_get_signature_nid(const X509_REQ *req); +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); +EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req); +X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req); +int X509_REQ_extension_nid(int nid); +int *X509_REQ_get_extension_nids(void); +void X509_REQ_set_extension_nids(int *nids); +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +int X509_REQ_get_attr_count(const X509_REQ *req); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_sort(X509_CRL *crl); +int X509_CRL_up_ref(X509_CRL *crl); + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_CRL_set_lastUpdate X509_CRL_set1_lastUpdate +# define X509_CRL_set_nextUpdate X509_CRL_set1_nextUpdate +#endif + +long X509_CRL_get_version(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); +DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl)) +DEPRECATEDIN_1_1_0(ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl)) +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); +void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); +int X509_CRL_get_signature_nid(const X509_CRL *crl); +int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp); + +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x); +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x); +int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); +const STACK_OF(X509_EXTENSION) * +X509_REVOKED_get0_extensions(const X509_REVOKED *r); + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags); + +int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey); + +int X509_check_private_key(const X509 *x509, const EVP_PKEY *pkey); +int X509_chain_check_suiteb(int *perror_depth, + X509 *x, STACK_OF(X509) *chain, + unsigned long flags); +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_and_serial_hash(X509 *a); + +int X509_issuer_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_name_hash(X509 *a); + +int X509_subject_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_subject_name_hash(X509 *x); + +# ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_name_hash_old(X509 *a); +unsigned long X509_subject_name_hash_old(X509 *x); +# endif + +int X509_cmp(const X509 *a, const X509 *b); +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +unsigned long X509_NAME_hash(X509_NAME *x); +unsigned long X509_NAME_hash_old(X509_NAME *x); + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); +int X509_aux_print(BIO *out, X509 *x, int indent); +# ifndef OPENSSL_NO_STDIO +int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print_fp(FILE *bp, X509 *x); +int X509_CRL_print_fp(FILE *bp, X509_CRL *x); +int X509_REQ_print_fp(FILE *bp, X509_REQ *req); +int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, + unsigned long flags); +# endif + +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase); +int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags); +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print(BIO *bp, X509 *x); +int X509_ocspid_print(BIO *bp, X509 *x); +int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag); +int X509_CRL_print(BIO *bp, X509_CRL *x); +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, + unsigned long cflag); +int X509_REQ_print(BIO *bp, X509_REQ *req); + +int X509_NAME_entry_count(const X509_NAME *name); +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len); +int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + char *buf, int len); + +/* + * NOTE: you should be passing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. + */ +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); +int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, + int loc, int set); +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len, int loc, + int set); +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + const unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, + const unsigned char *bytes, + int len); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, + const unsigned char *bytes, + int len); +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, + int len); +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj); +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne); +ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne); +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne); + +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, + size_t *pderlen); + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + const ASN1_OBJECT *obj, int lastpos); +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +int X509_get_ext_count(const X509 *x); +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos); +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos); +X509_EXTENSION *X509_get_ext(const X509 *x, int loc); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx); +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_CRL_get_ext_count(const X509_CRL *x); +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos); +int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, + int lastpos); +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos); +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx); +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_REVOKED_get_ext_count(const X509_REVOKED *x); +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos); +int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, + int lastpos); +int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, + int lastpos); +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); +void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, + int *idx); +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags); + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, + ASN1_OCTET_STRING *data); +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj, int crit, + ASN1_OCTET_STRING *data); +int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data); +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex); + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) + **x, const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) + **x, int nid, int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) + **x, const char *attrname, + int type, + const unsigned char *bytes, + int len); +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + const ASN1_OBJECT *obj, int lastpos, int type); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, + const unsigned char *bytes, + int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, + void *data); +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key); +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos); +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial); +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(PBEPARAM) +DECLARE_ASN1_FUNCTIONS(PBE2PARAM) +DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) +#ifndef OPENSSL_NO_SCRYPT +DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS) +#endif + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen); + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid); + +#ifndef OPENSSL_NO_SCRYPT +X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, + const unsigned char *salt, int saltlen, + unsigned char *aiv, uint64_t N, uint64_t r, + uint64_t p); +#endif + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen); + +/* PKCS#8 utilities */ + +DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, + int version, int ptype, void *pval, + unsigned char *penc, int penclen); +int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8); + +const STACK_OF(X509_ATTRIBUTE) * +PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8); +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len); + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen); +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub); + +int X509_check_trust(X509 *x, int id, int flags); +int X509_TRUST_get_count(void); +X509_TRUST *X509_TRUST_get0(int idx); +int X509_TRUST_get_by_id(int id); +int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), + const char *name, int arg1, void *arg2); +void X509_TRUST_cleanup(void); +int X509_TRUST_get_flags(const X509_TRUST *xp); +char *X509_TRUST_get0_name(const X509_TRUST *xp); +int X509_TRUST_get_trust(const X509_TRUST *xp); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/x509_vfy.h b/thirdparty/user_include/openssl/x509_vfy.h new file mode 100755 index 0000000000000000000000000000000000000000..adb8bce7cb4374fb4edcc871c8c3108a75c99f05 --- /dev/null +++ b/thirdparty/user_include/openssl/x509_vfy.h @@ -0,0 +1,628 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509_VFY_H +# define HEADER_X509_VFY_H + +/* + * Protect against recursion, x509.h and x509_vfy.h each include the other. + */ +# ifndef HEADER_X509_H +# include +# endif + +# include +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/*- +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +typedef enum { + X509_LU_NONE = 0, + X509_LU_X509, X509_LU_CRL +} X509_LOOKUP_TYPE; + +#if OPENSSL_API_COMPAT < 0x10100000L +#define X509_LU_RETRY -1 +#define X509_LU_FAIL 0 +#endif + +DEFINE_STACK_OF(X509_LOOKUP) +DEFINE_STACK_OF(X509_OBJECT) +DEFINE_STACK_OF(X509_VERIFY_PARAM) + +int X509_STORE_set_depth(X509_STORE *store, int depth); + +typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); +typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer, + X509_STORE_CTX *ctx, X509 *x); +typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx, + X509 *x, X509 *issuer); +typedef int (*X509_STORE_CTX_check_revocation_fn)(X509_STORE_CTX *ctx); +typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx, + X509_CRL **crl, X509 *x); +typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl); +typedef int (*X509_STORE_CTX_cert_crl_fn)(X509_STORE_CTX *ctx, + X509_CRL *crl, X509 *x); +typedef int (*X509_STORE_CTX_check_policy_fn)(X509_STORE_CTX *ctx); +typedef STACK_OF(X509) *(*X509_STORE_CTX_lookup_certs_fn)(X509_STORE_CTX *ctx, + X509_NAME *nm); +typedef STACK_OF(X509_CRL) *(*X509_STORE_CTX_lookup_crls_fn)(X509_STORE_CTX *ctx, + X509_NAME *nm); +typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx); + + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +# define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +# define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +# define X509_L_FILE_LOAD 1 +# define X509_L_ADD_DIR 2 + +# define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +# define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +# define X509_V_OK 0 +# define X509_V_ERR_UNSPECIFIED 1 +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +# define X509_V_ERR_UNABLE_TO_GET_CRL 3 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +# define X509_V_ERR_CERT_NOT_YET_VALID 9 +# define X509_V_ERR_CERT_HAS_EXPIRED 10 +# define X509_V_ERR_CRL_NOT_YET_VALID 11 +# define X509_V_ERR_CRL_HAS_EXPIRED 12 +# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +# define X509_V_ERR_OUT_OF_MEM 17 +# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +# define X509_V_ERR_CERT_REVOKED 23 +# define X509_V_ERR_INVALID_CA 24 +# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +# define X509_V_ERR_INVALID_PURPOSE 26 +# define X509_V_ERR_CERT_UNTRUSTED 27 +# define X509_V_ERR_CERT_REJECTED 28 +/* These are 'informational' when looking for issuer cert */ +# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +# define X509_V_ERR_AKID_SKID_MISMATCH 30 +# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 +# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +# define X509_V_ERR_INVALID_NON_CA 37 +# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 +# define X509_V_ERR_INVALID_EXTENSION 41 +# define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +# define X509_V_ERR_NO_EXPLICIT_POLICY 43 +# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 +# define X509_V_ERR_UNNESTED_RESOURCE 46 +# define X509_V_ERR_PERMITTED_VIOLATION 47 +# define X509_V_ERR_EXCLUDED_VIOLATION 48 +# define X509_V_ERR_SUBTREE_MINMAX 49 +/* The application is not happy */ +# define X509_V_ERR_APPLICATION_VERIFICATION 50 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 +/* Another issuer check debug option */ +# define X509_V_ERR_PATH_LOOP 55 +/* Suite B mode algorithm violation */ +# define X509_V_ERR_SUITE_B_INVALID_VERSION 56 +# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57 +# define X509_V_ERR_SUITE_B_INVALID_CURVE 58 +# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59 +# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60 +# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61 +/* Host, email and IP check errors */ +# define X509_V_ERR_HOSTNAME_MISMATCH 62 +# define X509_V_ERR_EMAIL_MISMATCH 63 +# define X509_V_ERR_IP_ADDRESS_MISMATCH 64 +/* DANE TLSA errors */ +# define X509_V_ERR_DANE_NO_MATCH 65 +/* security level errors */ +# define X509_V_ERR_EE_KEY_TOO_SMALL 66 +# define X509_V_ERR_CA_KEY_TOO_SMALL 67 +# define X509_V_ERR_CA_MD_TOO_WEAK 68 +/* Caller error */ +# define X509_V_ERR_INVALID_CALL 69 +/* Issuer lookup error */ +# define X509_V_ERR_STORE_LOOKUP 70 +/* Certificate transparency */ +# define X509_V_ERR_NO_VALID_SCTS 71 + +# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 72 +/* OCSP status errors */ +# define X509_V_ERR_OCSP_VERIFY_NEEDED 73 /* Need OCSP verification */ +# define X509_V_ERR_OCSP_VERIFY_FAILED 74 /* Couldn't verify cert through OCSP */ +# define X509_V_ERR_OCSP_CERT_UNKNOWN 75 /* Certificate wasn't recognized by the OCSP responder */ + +/* Certificate verify flags */ + +# if OPENSSL_API_COMPAT < 0x10100000L +# define X509_V_FLAG_CB_ISSUER_CHECK 0x0 /* Deprecated */ +# endif +/* Use check time instead of current time */ +# define X509_V_FLAG_USE_CHECK_TIME 0x2 +/* Lookup CRLs */ +# define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +# define X509_V_FLAG_CRL_CHECK_ALL 0x8 +/* Ignore unhandled critical extensions */ +# define X509_V_FLAG_IGNORE_CRITICAL 0x10 +/* Disable workarounds for broken certificates */ +# define X509_V_FLAG_X509_STRICT 0x20 +/* Enable proxy certificate validation */ +# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +/* Enable policy checking */ +# define X509_V_FLAG_POLICY_CHECK 0x80 +/* Policy variable require-explicit-policy */ +# define X509_V_FLAG_EXPLICIT_POLICY 0x100 +/* Policy variable inhibit-any-policy */ +# define X509_V_FLAG_INHIBIT_ANY 0x200 +/* Policy variable inhibit-policy-mapping */ +# define X509_V_FLAG_INHIBIT_MAP 0x400 +/* Notify callback that policy is OK */ +# define X509_V_FLAG_NOTIFY_POLICY 0x800 +/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ +# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +/* Delta CRL support */ +# define X509_V_FLAG_USE_DELTAS 0x2000 +/* Check self-signed CA signature */ +# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* Use trusted store first */ +# define X509_V_FLAG_TRUSTED_FIRST 0x8000 +/* Suite B 128 bit only mode: not normally used */ +# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define X509_V_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define X509_V_FLAG_SUITEB_128_LOS 0x30000 +/* Allow partial chains if at least one certificate is in trusted store */ +# define X509_V_FLAG_PARTIAL_CHAIN 0x80000 +/* + * If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.1.0. Setting this flag + * will force the behaviour to match that of previous versions. + */ +# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 +/* Do not check certificate/CRL validity against current time */ +# define X509_V_FLAG_NO_CHECK_TIME 0x200000 + +# define X509_VP_FLAG_DEFAULT 0x1 +# define X509_VP_FLAG_OVERWRITE 0x2 +# define X509_VP_FLAG_RESET_FLAGS 0x4 +# define X509_VP_FLAG_LOCKED 0x8 +# define X509_VP_FLAG_ONCE 0x10 + +/* Internal use: mask of policy related options */ +# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ + | X509_V_FLAG_EXPLICIT_POLICY \ + | X509_V_FLAG_INHIBIT_ANY \ + | X509_V_FLAG_INHIBIT_MAP) + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x); +int X509_OBJECT_up_ref_count(X509_OBJECT *a); +X509_OBJECT *X509_OBJECT_new(void); +void X509_OBJECT_free(X509_OBJECT *a); +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a); +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a); +int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj); +X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a); +int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj); +X509_STORE *X509_STORE_new(void); +void X509_STORE_free(X509_STORE *v); +int X509_STORE_lock(X509_STORE *ctx); +int X509_STORE_unlock(X509_STORE *ctx); +int X509_STORE_up_ref(X509_STORE *v); +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v); + +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +int X509_STORE_set_trust(X509_STORE *ctx, int trust); +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); +#define X509_STORE_set_verify_func(ctx, func) \ + X509_STORE_set_verify((ctx),(func)) +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_fn verify); +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx); +void X509_STORE_set_verify_cb(X509_STORE *ctx, + X509_STORE_CTX_verify_cb verify_cb); +# define X509_STORE_set_verify_cb_func(ctx,func) \ + X509_STORE_set_verify_cb((ctx),(func)) +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx); +void X509_STORE_set_get_issuer(X509_STORE *ctx, + X509_STORE_CTX_get_issuer_fn get_issuer); +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx); +void X509_STORE_set_check_issued(X509_STORE *ctx, + X509_STORE_CTX_check_issued_fn check_issued); +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx); +void X509_STORE_set_check_revocation(X509_STORE *ctx, + X509_STORE_CTX_check_revocation_fn check_revocation); +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx); +void X509_STORE_set_get_crl(X509_STORE *ctx, + X509_STORE_CTX_get_crl_fn get_crl); +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx); +void X509_STORE_set_check_crl(X509_STORE *ctx, + X509_STORE_CTX_check_crl_fn check_crl); +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx); +void X509_STORE_set_cert_crl(X509_STORE *ctx, + X509_STORE_CTX_cert_crl_fn cert_crl); +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx); +void X509_STORE_set_check_policy(X509_STORE *ctx, + X509_STORE_CTX_check_policy_fn check_policy); +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx); +void X509_STORE_set_lookup_certs(X509_STORE *ctx, + X509_STORE_CTX_lookup_certs_fn lookup_certs); +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx); +void X509_STORE_set_lookup_crls(X509_STORE *ctx, + X509_STORE_CTX_lookup_crls_fn lookup_crls); +#define X509_STORE_set_lookup_crls_cb(ctx, func) \ + X509_STORE_set_lookup_crls((ctx), (func)) +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx); +void X509_STORE_set_cleanup(X509_STORE *ctx, + X509_STORE_CTX_cleanup_fn cleanup); +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx); + +#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef) +int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); +void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx); + +X509_STORE_CTX *X509_STORE_CTX_new(void); + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); +STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + X509_STORE_CTX_verify_cb verify); +X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx); +X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx); +X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx); +X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx); +X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx); +X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx); +X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx); + +#if OPENSSL_API_COMPAT < 0x10100000L +# define X509_STORE_CTX_get_chain X509_STORE_CTX_get0_chain +# define X509_STORE_CTX_set_chain X509_STORE_CTX_set0_untrusted +# define X509_STORE_CTX_trusted_stack X509_STORE_CTX_set0_trusted_stack +# define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject +# define X509_STORE_get1_certs X509_STORE_CTX_get1_certs +# define X509_STORE_get1_crls X509_STORE_CTX_get1_crls +/* the following macro is misspelled; use X509_STORE_get1_certs instead */ +# define X509_STORE_get1_cert X509_STORE_CTX_get1_certs +/* the following macro is misspelled; use X509_STORE_get1_crls instead */ +# define X509_STORE_get1_crl X509_STORE_CTX_get1_crls +#endif + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); +typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + X509_NAME *name, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + X509_NAME *name, + ASN1_INTEGER *serial, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_fingerprint_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + const unsigned char* bytes, + int len, + X509_OBJECT *ret); +typedef int (*X509_LOOKUP_get_by_alias_fn)(X509_LOOKUP *ctx, + X509_LOOKUP_TYPE type, + const char *str, + int len, + X509_OBJECT *ret); + +X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name); +void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method, + int (*new_item) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_free(X509_LOOKUP_METHOD *method, + void (*free_fn) (X509_LOOKUP *ctx)); +void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method, + int (*init) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_shutdown(X509_LOOKUP_METHOD *method, + int (*shutdown) (X509_LOOKUP *ctx)); +int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method)) + (X509_LOOKUP *ctx); + +int X509_LOOKUP_meth_set_ctrl(X509_LOOKUP_METHOD *method, + X509_LOOKUP_ctrl_fn ctrl_fn); +X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_subject_fn fn); +X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_issuer_serial_fn fn); +X509_LOOKUP_get_by_issuer_serial_fn X509_LOOKUP_meth_get_get_by_issuer_serial( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_fingerprint_fn fn); +X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint( + const X509_LOOKUP_METHOD *method); + +int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method, + X509_LOOKUP_get_by_alias_fn fn); +X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias( + const X509_LOOKUP_METHOD *method); + + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, + X509_NAME *name); + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +void X509_LOOKUP_free(X509_LOOKUP *ctx); +int X509_LOOKUP_init(X509_LOOKUP *ctx); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, + X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, + X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); +int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data); +void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx); +X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx); +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +int X509_STORE_load_locations(X509_STORE *ctx, + const char *file, const char *dir); +int X509_STORE_set_default_paths(X509_STORE *ctx); + +#define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, l, p, newf, dupf, freef) +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data); +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x); +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x); +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk); +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t); + +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx); + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); + +/* + * Bridge opacity barrier between libcrypt and libssl, also needed to support + * offline testing in test/danetest.c + */ +void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, SSL_DANE *dane); +#define DANE_FLAG_NO_DANE_EE_NAMECHECKS (1L << 0) + +/* X509_VERIFY_PARAM functions */ + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); +void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level); +time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param); +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies); + +int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, + uint32_t flags); +uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param); + +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param); +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); +void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *); +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen); +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen); +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, + const char *ipasc); + +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param); +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_get_count(void); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); +void X509_VERIFY_PARAM_table_cleanup(void); + +/* Non positive return values are errors */ +#define X509_PCY_TREE_FAILURE -2 /* Failure to satisfy explicit policy */ +#define X509_PCY_TREE_INVALID -1 /* Inconsistent or invalid extensions */ +#define X509_PCY_TREE_INTERNAL 0 /* Internal error, most likely malloc */ + +/* + * Positive return values form a bit mask, all but the first are internal to + * the library and don't appear in results from X509_policy_check(). + */ +#define X509_PCY_TREE_VALID 1 /* The policy tree is valid */ +#define X509_PCY_TREE_EMPTY 2 /* The policy tree is empty */ +#define X509_PCY_TREE_EXPLICIT 4 /* Explicit policy required */ + +int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags); + +void X509_policy_tree_free(X509_POLICY_TREE *tree); + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); +X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, + int i); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const + X509_POLICY_TREE + *tree); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const + X509_POLICY_TREE + *tree); + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level); + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, + int i); + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); + +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const + X509_POLICY_NODE + *node); +const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE + *node); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thirdparty/user_include/openssl/x509err.h b/thirdparty/user_include/openssl/x509err.h new file mode 100755 index 0000000000000000000000000000000000000000..b1d6a87095c7071c13b58883dff8f320e6eaf139 --- /dev/null +++ b/thirdparty/user_include/openssl/x509err.h @@ -0,0 +1,125 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509ERR_H +# define HEADER_X509ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_X509_strings(void); + +/* + * X509 function codes. + */ +# define X509_F_ADD_CERT_DIR 100 +# define X509_F_BUILD_CHAIN 106 +# define X509_F_BY_FILE_CTRL 101 +# define X509_F_CHECK_NAME_CONSTRAINTS 149 +# define X509_F_CHECK_POLICY 145 +# define X509_F_DANE_I2D 107 +# define X509_F_DIR_CTRL 102 +# define X509_F_GET_CERT_BY_SUBJECT 103 +# define X509_F_I2D_X509_AUX 151 +# define X509_F_LOOKUP_CERTS_SK 152 +# define X509_F_NETSCAPE_SPKI_B64_DECODE 129 +# define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 +# define X509_F_NEW_DIR 153 +# define X509_F_X509AT_ADD1_ATTR 135 +# define X509_F_X509V3_ADD_EXT 104 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 +# define X509_F_X509_ATTRIBUTE_GET0_DATA 139 +# define X509_F_X509_ATTRIBUTE_SET1_DATA 138 +# define X509_F_X509_CHECK_PRIVATE_KEY 128 +# define X509_F_X509_CRL_DIFF 105 +# define X509_F_X509_CRL_METHOD_NEW 154 +# define X509_F_X509_CRL_PRINT_FP 147 +# define X509_F_X509_EXTENSION_CREATE_BY_NID 108 +# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 +# define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +# define X509_F_X509_LOAD_CERT_CRL_FILE 132 +# define X509_F_X509_LOAD_CERT_FILE 111 +# define X509_F_X509_LOAD_CRL_FILE 112 +# define X509_F_X509_LOOKUP_METH_NEW 160 +# define X509_F_X509_LOOKUP_NEW 155 +# define X509_F_X509_NAME_ADD_ENTRY 113 +# define X509_F_X509_NAME_CANON 156 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 +# define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 +# define X509_F_X509_NAME_ONELINE 116 +# define X509_F_X509_NAME_PRINT 117 +# define X509_F_X509_OBJECT_NEW 150 +# define X509_F_X509_PRINT_EX_FP 118 +# define X509_F_X509_PUBKEY_DECODE 148 +# define X509_F_X509_PUBKEY_GET0 119 +# define X509_F_X509_PUBKEY_SET 120 +# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 +# define X509_F_X509_REQ_PRINT_EX 121 +# define X509_F_X509_REQ_PRINT_FP 122 +# define X509_F_X509_REQ_TO_X509 123 +# define X509_F_X509_STORE_ADD_CERT 124 +# define X509_F_X509_STORE_ADD_CRL 125 +# define X509_F_X509_STORE_ADD_LOOKUP 157 +# define X509_F_X509_STORE_CTX_GET1_ISSUER 146 +# define X509_F_X509_STORE_CTX_INIT 143 +# define X509_F_X509_STORE_CTX_NEW 142 +# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 +# define X509_F_X509_STORE_NEW 158 +# define X509_F_X509_TO_X509_REQ 126 +# define X509_F_X509_TRUST_ADD 133 +# define X509_F_X509_TRUST_SET 141 +# define X509_F_X509_VERIFY_CERT 127 +# define X509_F_X509_VERIFY_PARAM_NEW 159 + +/* + * X509 reason codes. + */ +# define X509_R_AKID_MISMATCH 110 +# define X509_R_BAD_SELECTOR 133 +# define X509_R_BAD_X509_FILETYPE 100 +# define X509_R_BASE64_DECODE_ERROR 118 +# define X509_R_CANT_CHECK_DH_KEY 114 +# define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 +# define X509_R_CRL_ALREADY_DELTA 127 +# define X509_R_CRL_VERIFY_FAILURE 131 +# define X509_R_IDP_MISMATCH 128 +# define X509_R_INVALID_DIRECTORY 113 +# define X509_R_INVALID_FIELD_NAME 119 +# define X509_R_INVALID_TRUST 123 +# define X509_R_ISSUER_MISMATCH 129 +# define X509_R_KEY_TYPE_MISMATCH 115 +# define X509_R_KEY_VALUES_MISMATCH 116 +# define X509_R_LOADING_CERT_DIR 103 +# define X509_R_LOADING_DEFAULTS 104 +# define X509_R_METHOD_NOT_SUPPORTED 124 +# define X509_R_NAME_TOO_LONG 134 +# define X509_R_NEWER_CRL_NOT_NEWER 132 +# define X509_R_NO_CERTIFICATE_FOUND 135 +# define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 136 +# define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 +# define X509_R_NO_CRL_FOUND 137 +# define X509_R_NO_CRL_NUMBER 130 +# define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +# define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +# define X509_R_SHOULD_RETRY 106 +# define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 +# define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 +# define X509_R_UNKNOWN_KEY_TYPE 117 +# define X509_R_UNKNOWN_NID 109 +# define X509_R_UNKNOWN_PURPOSE_ID 121 +# define X509_R_UNKNOWN_TRUST_ID 120 +# define X509_R_UNSUPPORTED_ALGORITHM 111 +# define X509_R_WRONG_LOOKUP_TYPE 112 +# define X509_R_WRONG_TYPE 122 + +#endif diff --git a/thirdparty/user_include/openssl/x509v3.h b/thirdparty/user_include/openssl/x509v3.h new file mode 100755 index 0000000000000000000000000000000000000000..fe1791c6819af5a3cfb4876541ef8106283ba19a --- /dev/null +++ b/thirdparty/user_include/openssl/x509v3.h @@ -0,0 +1,935 @@ +/* + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509V3_H +# define HEADER_X509V3_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void *(*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE) (void *); +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef int (*X509V3_EXT_I2D) (void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * + (*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); +typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method, + void *ext); +typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); +typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext, + BIO *out, int indent); +typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); + +/* V3 extension structure */ + +struct v3_ext_method { + int ext_nid; + int ext_flags; +/* If this is set the following four fields are ignored */ + ASN1_ITEM_EXP *it; +/* Old style ASN1 calls */ + X509V3_EXT_NEW ext_new; + X509V3_EXT_FREE ext_free; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2D i2d; +/* The following pair is used for string extensions */ + X509V3_EXT_I2S i2s; + X509V3_EXT_S2I s2i; +/* The following pair is used for multi-valued extensions */ + X509V3_EXT_I2V i2v; + X509V3_EXT_V2I v2i; +/* The following are used for raw extensions */ + X509V3_EXT_I2R i2r; + X509V3_EXT_R2I r2i; + void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { + char *(*get_string) (void *db, const char *section, const char *value); + STACK_OF(CONF_VALUE) *(*get_section) (void *db, const char *section); + void (*free_string) (void *db, char *string); + void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { +# define CTX_TEST 0x1 +# define X509V3_CTX_REPLACE 0x2 + int flags; + X509 *issuer_cert; + X509 *subject_cert; + X509_REQ *subject_req; + X509_CRL *crl; + X509V3_CONF_METHOD *db_meth; + void *db; +/* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +DEFINE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +# define X509V3_EXT_DYNAMIC 0x1 +# define X509V3_EXT_CTX_DEP 0x2 +# define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { + int ca; + ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + +typedef struct PKEY_USAGE_PERIOD_st { + ASN1_GENERALIZEDTIME *notBefore; + ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { + ASN1_OBJECT *type_id; + ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { +# define GEN_OTHERNAME 0 +# define GEN_EMAIL 1 +# define GEN_DNS 2 +# define GEN_X400 3 +# define GEN_DIRNAME 4 +# define GEN_EDIPARTY 5 +# define GEN_URI 6 +# define GEN_IPADD 7 +# define GEN_RID 8 + int type; + union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5; /* rfc822Name, dNSName, + * uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ + } d; +} GENERAL_NAME; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +typedef STACK_OF(ASN1_INTEGER) TLS_FEATURE; + +DEFINE_STACK_OF(GENERAL_NAME) +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; +DEFINE_STACK_OF(GENERAL_NAMES) + +DEFINE_STACK_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { + int type; + union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; + } name; +/* If relativename then this contains the full distribution point name */ + X509_NAME *dpname; +} DIST_POINT_NAME; +/* All existing reasons */ +# define CRLDP_ALL_REASONS 0x807f + +# define CRL_REASON_NONE -1 +# define CRL_REASON_UNSPECIFIED 0 +# define CRL_REASON_KEY_COMPROMISE 1 +# define CRL_REASON_CA_COMPROMISE 2 +# define CRL_REASON_AFFILIATION_CHANGED 3 +# define CRL_REASON_SUPERSEDED 4 +# define CRL_REASON_CESSATION_OF_OPERATION 5 +# define CRL_REASON_CERTIFICATE_HOLD 6 +# define CRL_REASON_REMOVE_FROM_CRL 8 +# define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +# define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { + DIST_POINT_NAME *distpoint; + ASN1_BIT_STRING *reasons; + GENERAL_NAMES *CRLissuer; + int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DEFINE_STACK_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { + ASN1_OCTET_STRING *keyid; + GENERAL_NAMES *issuer; + ASN1_INTEGER *serial; +}; + +/* Strong extranet structures */ + +typedef struct SXNET_ID_st { + ASN1_INTEGER *zone; + ASN1_OCTET_STRING *user; +} SXNETID; + +DEFINE_STACK_OF(SXNETID) + +typedef struct SXNET_st { + ASN1_INTEGER *version; + STACK_OF(SXNETID) *ids; +} SXNET; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DEFINE_STACK_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DEFINE_STACK_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DEFINE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DEFINE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +/* Proxy certificate structures, see RFC 3820 */ +typedef struct PROXY_POLICY_st { + ASN1_OBJECT *policyLanguage; + ASN1_OCTET_STRING *policy; +} PROXY_POLICY; + +typedef struct PROXY_CERT_INFO_EXTENSION_st { + ASN1_INTEGER *pcPathLengthConstraint; + PROXY_POLICY *proxyPolicy; +} PROXY_CERT_INFO_EXTENSION; + +DECLARE_ASN1_FUNCTIONS(PROXY_POLICY) +DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) + +struct ISSUING_DIST_POINT_st { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; +}; + +/* Values in idp_flags field */ +/* IDP present */ +# define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +# define IDP_INVALID 0x2 +/* onlyuser true */ +# define IDP_ONLYUSER 0x4 +/* onlyCA true */ +# define IDP_ONLYCA 0x8 +/* onlyattr true */ +# define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +# define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +# define IDP_REASONS 0x40 + +# define X509V3_conf_err(val) ERR_add_error_data(6, \ + "section:", (val)->section, \ + ",name:", (val)->name, ",value:", (val)->value) + +# define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + table} + +# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* X509_PURPOSE stuff */ + +# define EXFLAG_BCONS 0x1 +# define EXFLAG_KUSAGE 0x2 +# define EXFLAG_XKUSAGE 0x4 +# define EXFLAG_NSCERT 0x8 + +# define EXFLAG_CA 0x10 +/* Really self issued not necessarily self signed */ +# define EXFLAG_SI 0x20 +# define EXFLAG_V1 0x40 +# define EXFLAG_INVALID 0x80 +/* EXFLAG_SET is set to indicate that some values have been precomputed */ +# define EXFLAG_SET 0x100 +# define EXFLAG_CRITICAL 0x200 +# define EXFLAG_PROXY 0x400 + +# define EXFLAG_INVALID_POLICY 0x800 +# define EXFLAG_FRESHEST 0x1000 +/* Self signed */ +# define EXFLAG_SS 0x2000 + +# define KU_DIGITAL_SIGNATURE 0x0080 +# define KU_NON_REPUDIATION 0x0040 +# define KU_KEY_ENCIPHERMENT 0x0020 +# define KU_DATA_ENCIPHERMENT 0x0010 +# define KU_KEY_AGREEMENT 0x0008 +# define KU_KEY_CERT_SIGN 0x0004 +# define KU_CRL_SIGN 0x0002 +# define KU_ENCIPHER_ONLY 0x0001 +# define KU_DECIPHER_ONLY 0x8000 + +# define NS_SSL_CLIENT 0x80 +# define NS_SSL_SERVER 0x40 +# define NS_SMIME 0x20 +# define NS_OBJSIGN 0x10 +# define NS_SSL_CA 0x04 +# define NS_SMIME_CA 0x02 +# define NS_OBJSIGN_CA 0x01 +# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +# define XKU_SSL_SERVER 0x1 +# define XKU_SSL_CLIENT 0x2 +# define XKU_SMIME 0x4 +# define XKU_CODE_SIGN 0x8 +# define XKU_SGC 0x10 +# define XKU_OCSP_SIGN 0x20 +# define XKU_TIMESTAMP 0x40 +# define XKU_DVCS 0x80 +# define XKU_ANYEKU 0x100 + +# define X509_PURPOSE_DYNAMIC 0x1 +# define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +# define X509_PURPOSE_SSL_CLIENT 1 +# define X509_PURPOSE_SSL_SERVER 2 +# define X509_PURPOSE_NS_SSL_SERVER 3 +# define X509_PURPOSE_SMIME_SIGN 4 +# define X509_PURPOSE_SMIME_ENCRYPT 5 +# define X509_PURPOSE_CRL_SIGN 6 +# define X509_PURPOSE_ANY 7 +# define X509_PURPOSE_OCSP_HELPER 8 +# define X509_PURPOSE_TIMESTAMP_SIGN 9 + +# define X509_PURPOSE_MIN 1 +# define X509_PURPOSE_MAX 9 + +/* Flags for X509V3_EXT_print() */ + +# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +# define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +# define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +# define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +# define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +# define X509V3_ADD_OP_MASK 0xfL +# define X509V3_ADD_DEFAULT 0L +# define X509V3_ADD_APPEND 1L +# define X509V3_ADD_REPLACE 2L +# define X509V3_ADD_REPLACE_EXISTING 3L +# define X509V3_ADD_KEEP_EXISTING 4L +# define X509V3_ADD_DELETE 5L +# define X509V3_ADD_SILENT 0x10 + +DEFINE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +DECLARE_ASN1_FUNCTIONS(SXNET) +DECLARE_ASN1_FUNCTIONS(SXNETID) + +int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen); +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user, + int userlen); +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, const char *user, + int userlen); + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone); +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone); +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone); + +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b); + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); +char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5); +ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret); +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, + STACK_OF(CONF_VALUE) *extlist); +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS(OTHERNAME) +DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value); +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue); + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + const ASN1_OCTET_STRING *ia5); +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); + +DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) +int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a); + +DECLARE_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE) + +DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS(POLICYINFO) +DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS(USERNOTICE) +DECLARE_ASN1_FUNCTIONS(NOTICEREF) + +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) +DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); +int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc); + +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +DECLARE_ASN1_ITEM(POLICY_MAPPING) +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) +DECLARE_ASN1_ITEM(POLICY_MAPPINGS) + +DECLARE_ASN1_ITEM(GENERAL_SUBTREE) +DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) + +DECLARE_ASN1_ITEM(NAME_CONSTRAINTS) +DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) +DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS) + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, + const char *value, int is_nc); + +# ifdef HEADER_CONF_H +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf); +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, + int is_nc); +void X509V3_conf_free(CONF_VALUE *val); + +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + const char *value); +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, + const char *value); +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, + STACK_OF(X509_EXTENSION) **sk); +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509 *cert); +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_REQ *req); +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_CRL *crl); + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, + const char *value); +X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *name, const char *value); +int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509 *cert); +int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_CRL *crl); + +int X509V3_add_value_bool_nf(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool); +int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint); +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash); +# endif + +char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section); +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section); +void X509V3_string_free(X509V3_CTX *ctx, char *str); +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint); +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value); +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint); +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, + const ASN1_ENUMERATED *aint); +int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +int X509V3_EXT_add_alias(int nid_to, int nid_from); +void X509V3_EXT_cleanup(void); + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +int X509V3_add_standard_extensions(void); +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +void *X509V3_EXT_d2i(X509_EXTENSION *ext); +void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx); + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags); + +#if OPENSSL_API_COMPAT < 0x10100000L +/* The new declarations are in crypto.h, but the old ones were here. */ +# define hex_to_string OPENSSL_buf2hexstr +# define string_to_hex OPENSSL_hexstr2buf +#endif + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent); +#ifndef OPENSSL_NO_STDIO +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); +#endif +int X509V3_extensions_print(BIO *out, const char *title, + const STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent); + +int X509_check_ca(X509 *x); +int X509_check_purpose(X509 *x, int id, int ca); +int X509_supported_extension(X509_EXTENSION *ex); +int X509_PURPOSE_set(int *p, int purpose); +int X509_check_issued(X509 *issuer, X509 *subject); +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); +void X509_set_proxy_flag(X509 *x); +void X509_set_proxy_pathlen(X509 *x, long l); +long X509_get_proxy_pathlen(X509 *x); + +uint32_t X509_get_extension_flags(X509 *x); +uint32_t X509_get_key_usage(X509 *x); +uint32_t X509_get_extended_key_usage(X509 *x); +const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x); +const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x); + +int X509_PURPOSE_get_count(void); +X509_PURPOSE *X509_PURPOSE_get0(int idx); +int X509_PURPOSE_get_by_sname(const char *sname); +int X509_PURPOSE_get_by_id(int id); +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + const char *name, const char *sname, void *arg); +char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp); +char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); +void X509_PURPOSE_cleanup(void); +int X509_PURPOSE_get_id(const X509_PURPOSE *); + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); +/* Flags for X509_check_* functions */ + +/* + * Always check subject name for host match even if subject alt names present + */ +# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wildcard matching for dnsName fields and common name. */ +# define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +/* Wildcards must not match a partial label. */ +# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4 +/* Allow (non-partial) wildcards to match multiple labels. */ +# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8 +/* Constraint verifier subdomain patterns to match a single labels. */ +# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10 +/* Never check the subject CN */ +# define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20 +/* + * Match reference identifiers starting with "." to any sub-domain. + * This is a non-public flag, turned on implicitly when the subject + * reference identity is a DNS name. + */ +# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags); + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, + unsigned long chtype); + +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent); +DEFINE_STACK_OF(X509_POLICY_NODE) + +#ifndef OPENSSL_NO_RFC3779 +typedef struct ASRange_st { + ASN1_INTEGER *min, *max; +} ASRange; + +# define ASIdOrRange_id 0 +# define ASIdOrRange_range 1 + +typedef struct ASIdOrRange_st { + int type; + union { + ASN1_INTEGER *id; + ASRange *range; + } u; +} ASIdOrRange; + +typedef STACK_OF(ASIdOrRange) ASIdOrRanges; +DEFINE_STACK_OF(ASIdOrRange) + +# define ASIdentifierChoice_inherit 0 +# define ASIdentifierChoice_asIdsOrRanges 1 + +typedef struct ASIdentifierChoice_st { + int type; + union { + ASN1_NULL *inherit; + ASIdOrRanges *asIdsOrRanges; + } u; +} ASIdentifierChoice; + +typedef struct ASIdentifiers_st { + ASIdentifierChoice *asnum, *rdi; +} ASIdentifiers; + +DECLARE_ASN1_FUNCTIONS(ASRange) +DECLARE_ASN1_FUNCTIONS(ASIdOrRange) +DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice) +DECLARE_ASN1_FUNCTIONS(ASIdentifiers) + +typedef struct IPAddressRange_st { + ASN1_BIT_STRING *min, *max; +} IPAddressRange; + +# define IPAddressOrRange_addressPrefix 0 +# define IPAddressOrRange_addressRange 1 + +typedef struct IPAddressOrRange_st { + int type; + union { + ASN1_BIT_STRING *addressPrefix; + IPAddressRange *addressRange; + } u; +} IPAddressOrRange; + +typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges; +DEFINE_STACK_OF(IPAddressOrRange) + +# define IPAddressChoice_inherit 0 +# define IPAddressChoice_addressesOrRanges 1 + +typedef struct IPAddressChoice_st { + int type; + union { + ASN1_NULL *inherit; + IPAddressOrRanges *addressesOrRanges; + } u; +} IPAddressChoice; + +typedef struct IPAddressFamily_st { + ASN1_OCTET_STRING *addressFamily; + IPAddressChoice *ipAddressChoice; +} IPAddressFamily; + +typedef STACK_OF(IPAddressFamily) IPAddrBlocks; +DEFINE_STACK_OF(IPAddressFamily) + +DECLARE_ASN1_FUNCTIONS(IPAddressRange) +DECLARE_ASN1_FUNCTIONS(IPAddressOrRange) +DECLARE_ASN1_FUNCTIONS(IPAddressChoice) +DECLARE_ASN1_FUNCTIONS(IPAddressFamily) + +/* + * API tag for elements of the ASIdentifer SEQUENCE. + */ +# define V3_ASID_ASNUM 0 +# define V3_ASID_RDI 1 + +/* + * AFI values, assigned by IANA. It'd be nice to make the AFI + * handling code totally generic, but there are too many little things + * that would need to be defined for other address families for it to + * be worth the trouble. + */ +# define IANA_AFI_IPV4 1 +# define IANA_AFI_IPV6 2 + +/* + * Utilities to construct and extract values from RFC3779 extensions, + * since some of the encodings (particularly for IP address prefixes + * and ranges) are a bit tedious to work with directly. + */ +int X509v3_asid_add_inherit(ASIdentifiers *asid, int which); +int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, + ASN1_INTEGER *min, ASN1_INTEGER *max); +int X509v3_addr_add_inherit(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi); +int X509v3_addr_add_prefix(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *a, const int prefixlen); +int X509v3_addr_add_range(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *min, unsigned char *max); +unsigned X509v3_addr_get_afi(const IPAddressFamily *f); +int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, + unsigned char *min, unsigned char *max, + const int length); + +/* + * Canonical forms. + */ +int X509v3_asid_is_canonical(ASIdentifiers *asid); +int X509v3_addr_is_canonical(IPAddrBlocks *addr); +int X509v3_asid_canonize(ASIdentifiers *asid); +int X509v3_addr_canonize(IPAddrBlocks *addr); + +/* + * Tests for inheritance and containment. + */ +int X509v3_asid_inherits(ASIdentifiers *asid); +int X509v3_addr_inherits(IPAddrBlocks *addr); +int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b); +int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b); + +/* + * Check whether RFC 3779 extensions nest properly in chains. + */ +int X509v3_asid_validate_path(X509_STORE_CTX *); +int X509v3_addr_validate_path(X509_STORE_CTX *); +int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, + ASIdentifiers *ext, + int allow_inheritance); +int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, + IPAddrBlocks *ext, int allow_inheritance); + +#endif /* OPENSSL_NO_RFC3779 */ + +DEFINE_STACK_OF(ASN1_STRING) + +/* + * Admission Syntax + */ +typedef struct NamingAuthority_st NAMING_AUTHORITY; +typedef struct ProfessionInfo_st PROFESSION_INFO; +typedef struct Admissions_st ADMISSIONS; +typedef struct AdmissionSyntax_st ADMISSION_SYNTAX; +DECLARE_ASN1_FUNCTIONS(NAMING_AUTHORITY) +DECLARE_ASN1_FUNCTIONS(PROFESSION_INFO) +DECLARE_ASN1_FUNCTIONS(ADMISSIONS) +DECLARE_ASN1_FUNCTIONS(ADMISSION_SYNTAX) +DEFINE_STACK_OF(ADMISSIONS) +DEFINE_STACK_OF(PROFESSION_INFO) +typedef STACK_OF(PROFESSION_INFO) PROFESSION_INFOS; + +const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId( + const NAMING_AUTHORITY *n); +const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL( + const NAMING_AUTHORITY *n); +const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText( + const NAMING_AUTHORITY *n); +void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n, + ASN1_OBJECT* namingAuthorityId); +void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n, + ASN1_IA5STRING* namingAuthorityUrl); +void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n, + ASN1_STRING* namingAuthorityText); + +const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority( + const ADMISSION_SYNTAX *as); +void ADMISSION_SYNTAX_set0_admissionAuthority( + ADMISSION_SYNTAX *as, GENERAL_NAME *aa); +const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions( + const ADMISSION_SYNTAX *as); +void ADMISSION_SYNTAX_set0_contentsOfAdmissions( + ADMISSION_SYNTAX *as, STACK_OF(ADMISSIONS) *a); +const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a); +void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa); +const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a); +void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na); +const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a); +void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi); +const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_addProfessionInfo( + PROFESSION_INFO *pi, ASN1_OCTET_STRING *aos); +const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_namingAuthority( + PROFESSION_INFO *pi, NAMING_AUTHORITY *na); +const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_professionItems( + PROFESSION_INFO *pi, STACK_OF(ASN1_STRING) *as); +const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_professionOIDs( + PROFESSION_INFO *pi, STACK_OF(ASN1_OBJECT) *po); +const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber( + const PROFESSION_INFO *pi); +void PROFESSION_INFO_set0_registrationNumber( + PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/thirdparty/user_include/openssl/x509v3err.h b/thirdparty/user_include/openssl/x509v3err.h new file mode 100755 index 0000000000000000000000000000000000000000..6b3df12b63e3c03f81bd9b8b5823183f3e47acc5 --- /dev/null +++ b/thirdparty/user_include/openssl/x509v3err.h @@ -0,0 +1,158 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_X509V3ERR_H +# define HEADER_X509V3ERR_H + +# ifdef __cplusplus +extern "C" +# endif +int ERR_load_X509V3_strings(void); + +/* + * X509V3 function codes. + */ +# define X509V3_F_A2I_GENERAL_NAME 164 +# define X509V3_F_ADDR_VALIDATE_PATH_INTERNAL 166 +# define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161 +# define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162 +# define X509V3_F_BIGNUM_TO_STRING 167 +# define X509V3_F_COPY_EMAIL 122 +# define X509V3_F_COPY_ISSUER 123 +# define X509V3_F_DO_DIRNAME 144 +# define X509V3_F_DO_EXT_I2D 135 +# define X509V3_F_DO_EXT_NCONF 151 +# define X509V3_F_GNAMES_FROM_SECTNAME 156 +# define X509V3_F_I2S_ASN1_ENUMERATED 121 +# define X509V3_F_I2S_ASN1_IA5STRING 149 +# define X509V3_F_I2S_ASN1_INTEGER 120 +# define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 +# define X509V3_F_LEVEL_ADD_NODE 168 +# define X509V3_F_NOTICE_SECTION 132 +# define X509V3_F_NREF_NOS 133 +# define X509V3_F_POLICY_CACHE_CREATE 169 +# define X509V3_F_POLICY_CACHE_NEW 170 +# define X509V3_F_POLICY_DATA_NEW 171 +# define X509V3_F_POLICY_SECTION 131 +# define X509V3_F_PROCESS_PCI_VALUE 150 +# define X509V3_F_R2I_CERTPOL 130 +# define X509V3_F_R2I_PCI 155 +# define X509V3_F_S2I_ASN1_IA5STRING 100 +# define X509V3_F_S2I_ASN1_INTEGER 108 +# define X509V3_F_S2I_ASN1_OCTET_STRING 112 +# define X509V3_F_S2I_SKEY_ID 115 +# define X509V3_F_SET_DIST_POINT_NAME 158 +# define X509V3_F_SXNET_ADD_ID_ASC 125 +# define X509V3_F_SXNET_ADD_ID_INTEGER 126 +# define X509V3_F_SXNET_ADD_ID_ULONG 127 +# define X509V3_F_SXNET_GET_ID_ASC 128 +# define X509V3_F_SXNET_GET_ID_ULONG 129 +# define X509V3_F_TREE_INIT 172 +# define X509V3_F_V2I_ASIDENTIFIERS 163 +# define X509V3_F_V2I_ASN1_BIT_STRING 101 +# define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139 +# define X509V3_F_V2I_AUTHORITY_KEYID 119 +# define X509V3_F_V2I_BASIC_CONSTRAINTS 102 +# define X509V3_F_V2I_CRLD 134 +# define X509V3_F_V2I_EXTENDED_KEY_USAGE 103 +# define X509V3_F_V2I_GENERAL_NAMES 118 +# define X509V3_F_V2I_GENERAL_NAME_EX 117 +# define X509V3_F_V2I_IDP 157 +# define X509V3_F_V2I_IPADDRBLOCKS 159 +# define X509V3_F_V2I_ISSUER_ALT 153 +# define X509V3_F_V2I_NAME_CONSTRAINTS 147 +# define X509V3_F_V2I_POLICY_CONSTRAINTS 146 +# define X509V3_F_V2I_POLICY_MAPPINGS 145 +# define X509V3_F_V2I_SUBJECT_ALT 154 +# define X509V3_F_V2I_TLS_FEATURE 165 +# define X509V3_F_V3_GENERIC_EXTENSION 116 +# define X509V3_F_X509V3_ADD1_I2D 140 +# define X509V3_F_X509V3_ADD_VALUE 105 +# define X509V3_F_X509V3_EXT_ADD 104 +# define X509V3_F_X509V3_EXT_ADD_ALIAS 106 +# define X509V3_F_X509V3_EXT_I2D 136 +# define X509V3_F_X509V3_EXT_NCONF 152 +# define X509V3_F_X509V3_GET_SECTION 142 +# define X509V3_F_X509V3_GET_STRING 143 +# define X509V3_F_X509V3_GET_VALUE_BOOL 110 +# define X509V3_F_X509V3_PARSE_LIST 109 +# define X509V3_F_X509_PURPOSE_ADD 137 +# define X509V3_F_X509_PURPOSE_SET 141 + +/* + * X509V3 reason codes. + */ +# define X509V3_R_BAD_IP_ADDRESS 118 +# define X509V3_R_BAD_OBJECT 119 +# define X509V3_R_BN_DEC2BN_ERROR 100 +# define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101 +# define X509V3_R_DIRNAME_ERROR 149 +# define X509V3_R_DISTPOINT_ALREADY_SET 160 +# define X509V3_R_DUPLICATE_ZONE_ID 133 +# define X509V3_R_ERROR_CONVERTING_ZONE 131 +# define X509V3_R_ERROR_CREATING_EXTENSION 144 +# define X509V3_R_ERROR_IN_EXTENSION 128 +# define X509V3_R_EXPECTED_A_SECTION_NAME 137 +# define X509V3_R_EXTENSION_EXISTS 145 +# define X509V3_R_EXTENSION_NAME_ERROR 115 +# define X509V3_R_EXTENSION_NOT_FOUND 102 +# define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103 +# define X509V3_R_EXTENSION_VALUE_ERROR 116 +# define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151 +# define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152 +# define X509V3_R_INVALID_ASNUMBER 162 +# define X509V3_R_INVALID_ASRANGE 163 +# define X509V3_R_INVALID_BOOLEAN_STRING 104 +# define X509V3_R_INVALID_EXTENSION_STRING 105 +# define X509V3_R_INVALID_INHERITANCE 165 +# define X509V3_R_INVALID_IPADDRESS 166 +# define X509V3_R_INVALID_MULTIPLE_RDNS 161 +# define X509V3_R_INVALID_NAME 106 +# define X509V3_R_INVALID_NULL_ARGUMENT 107 +# define X509V3_R_INVALID_NULL_NAME 108 +# define X509V3_R_INVALID_NULL_VALUE 109 +# define X509V3_R_INVALID_NUMBER 140 +# define X509V3_R_INVALID_NUMBERS 141 +# define X509V3_R_INVALID_OBJECT_IDENTIFIER 110 +# define X509V3_R_INVALID_OPTION 138 +# define X509V3_R_INVALID_POLICY_IDENTIFIER 134 +# define X509V3_R_INVALID_PROXY_POLICY_SETTING 153 +# define X509V3_R_INVALID_PURPOSE 146 +# define X509V3_R_INVALID_SAFI 164 +# define X509V3_R_INVALID_SECTION 135 +# define X509V3_R_INVALID_SYNTAX 143 +# define X509V3_R_ISSUER_DECODE_ERROR 126 +# define X509V3_R_MISSING_VALUE 124 +# define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142 +# define X509V3_R_NO_CONFIG_DATABASE 136 +# define X509V3_R_NO_ISSUER_CERTIFICATE 121 +# define X509V3_R_NO_ISSUER_DETAILS 127 +# define X509V3_R_NO_POLICY_IDENTIFIER 139 +# define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154 +# define X509V3_R_NO_PUBLIC_KEY 114 +# define X509V3_R_NO_SUBJECT_DETAILS 125 +# define X509V3_R_OPERATION_NOT_DEFINED 148 +# define X509V3_R_OTHERNAME_ERROR 147 +# define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 155 +# define X509V3_R_POLICY_PATH_LENGTH 156 +# define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 157 +# define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159 +# define X509V3_R_SECTION_NOT_FOUND 150 +# define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122 +# define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123 +# define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111 +# define X509V3_R_UNKNOWN_EXTENSION 129 +# define X509V3_R_UNKNOWN_EXTENSION_NAME 130 +# define X509V3_R_UNKNOWN_OPTION 120 +# define X509V3_R_UNSUPPORTED_OPTION 117 +# define X509V3_R_UNSUPPORTED_TYPE 167 +# define X509V3_R_USER_TOO_LONG 132 + +#endif diff --git a/thirdparty/user_include/srtp2/auth.h b/thirdparty/user_include/srtp2/auth.h new file mode 100755 index 0000000000000000000000000000000000000000..774ea1687bb8dee025b78211400cfdbae43d832e --- /dev/null +++ b/thirdparty/user_include/srtp2/auth.h @@ -0,0 +1,173 @@ +/* + * auth.h + * + * common interface to authentication functions + * + * David A. McGrew + * Cisco Systems, Inc. + */ + +/* + * + * Copyright (c) 2001-2017, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_AUTH_H +#define SRTP_AUTH_H + +#include "srtp.h" +#include "crypto_types.h" /* for values of auth_type_id_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef const struct srtp_auth_type_t *srtp_auth_type_pointer; +typedef struct srtp_auth_t *srtp_auth_pointer_t; + +typedef srtp_err_status_t (*srtp_auth_alloc_func)(srtp_auth_pointer_t *ap, + int key_len, + int out_len); + +typedef srtp_err_status_t (*srtp_auth_init_func)(void *state, + const uint8_t *key, + int key_len); + +typedef srtp_err_status_t (*srtp_auth_dealloc_func)(srtp_auth_pointer_t ap); + +typedef srtp_err_status_t (*srtp_auth_compute_func)(void *state, + const uint8_t *buffer, + int octets_to_auth, + int tag_len, + uint8_t *tag); + +typedef srtp_err_status_t (*srtp_auth_update_func)(void *state, + const uint8_t *buffer, + int octets_to_auth); + +typedef srtp_err_status_t (*srtp_auth_start_func)(void *state); + +/* some syntactic sugar on these function types */ +#define srtp_auth_type_alloc(at, a, klen, outlen) \ + ((at)->alloc((a), (klen), (outlen))) + +#define srtp_auth_init(a, key) \ + (((a)->type)->init((a)->state, (key), ((a)->key_len))) + +#define srtp_auth_compute(a, buf, len, res) \ + (((a)->type)->compute((a)->state, (buf), (len), (a)->out_len, (res))) + +#define srtp_auth_update(a, buf, len) \ + (((a)->type)->update((a)->state, (buf), (len))) + +#define srtp_auth_start(a) (((a)->type)->start((a)->state)) + +#define srtp_auth_dealloc(c) (((c)->type)->dealloc(c)) + +/* functions to get information about a particular auth_t */ +int srtp_auth_get_key_length(const struct srtp_auth_t *a); + +int srtp_auth_get_tag_length(const struct srtp_auth_t *a); + +int srtp_auth_get_prefix_length(const struct srtp_auth_t *a); + +/* + * srtp_auth_test_case_t is a (list of) key/message/tag values that are + * known to be correct for a particular cipher. this data can be used + * to test an implementation in an on-the-fly self test of the + * correctness of the implementation. (see the srtp_auth_type_self_test() + * function below) + */ +typedef struct srtp_auth_test_case_t { + int key_length_octets; /* octets in key */ + const uint8_t *key; /* key */ + int data_length_octets; /* octets in data */ + const uint8_t *data; /* data */ + int tag_length_octets; /* octets in tag */ + const uint8_t *tag; /* tag */ + const struct srtp_auth_test_case_t + *next_test_case; /* pointer to next testcase */ +} srtp_auth_test_case_t; + +/* srtp_auth_type_t */ +typedef struct srtp_auth_type_t { + srtp_auth_alloc_func alloc; + srtp_auth_dealloc_func dealloc; + srtp_auth_init_func init; + srtp_auth_compute_func compute; + srtp_auth_update_func update; + srtp_auth_start_func start; + const char *description; + const srtp_auth_test_case_t *test_data; + srtp_auth_type_id_t id; +} srtp_auth_type_t; + +typedef struct srtp_auth_t { + const srtp_auth_type_t *type; + void *state; + int out_len; /* length of output tag in octets */ + int key_len; /* length of key in octets */ + int prefix_len; /* length of keystream prefix */ +} srtp_auth_t; + +/* + * srtp_auth_type_self_test() tests an auth_type against test cases + * provided in an array of values of key/message/tag that is known to + * be good + */ +srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at); + +/* + * srtp_auth_type_test() tests an auth_type against external test cases + * provided in an array of values of key/message/tag that is known to + * be good + */ +srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, + const srtp_auth_test_case_t *test_data); + +/* + * srtp_replace_auth_type(ct, id) + * + * replaces srtp's kernel's auth type implementation for the auth_type id + * with a new one passed in externally. The new auth type must pass all the + * existing auth_type's self tests as well as its own. + */ +srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *ct, + srtp_auth_type_id_t id); + +#ifdef __cplusplus +} +#endif + +#endif /* SRTP_AUTH_H */ diff --git a/thirdparty/user_include/srtp2/cipher.h b/thirdparty/user_include/srtp2/cipher.h new file mode 100755 index 0000000000000000000000000000000000000000..4f14e3560fdd03d7dfb1944a1f16c76974f91934 --- /dev/null +++ b/thirdparty/user_include/srtp2/cipher.h @@ -0,0 +1,248 @@ +/* + * cipher.h + * + * common interface to ciphers + * + * David A. McGrew + * Cisco Systems, Inc. + */ +/* + * + * Copyright (c) 2001-2017 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_CIPHER_H +#define SRTP_CIPHER_H + +#include "srtp.h" +#include "crypto_types.h" /* for values of cipher_type_id_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * srtp_cipher_direction_t defines a particular cipher operation. + * + * A srtp_cipher_direction_t is an enum that describes a particular cipher + * operation, i.e. encryption or decryption. For some ciphers, this + * distinction does not matter, but for others, it is essential. + */ +typedef enum { + srtp_direction_encrypt, /**< encryption (convert plaintext to ciphertext) */ + srtp_direction_decrypt, /**< decryption (convert ciphertext to plaintext) */ + srtp_direction_any /**< encryption or decryption */ +} srtp_cipher_direction_t; + +/* + * the srtp_cipher_pointer_t definition is needed + * as srtp_cipher_t is not yet defined + */ +typedef struct srtp_cipher_t *srtp_cipher_pointer_t; + +/* + * a srtp_cipher_alloc_func_t allocates (but does not initialize) a + * srtp_cipher_t + */ +typedef srtp_err_status_t (*srtp_cipher_alloc_func_t)(srtp_cipher_pointer_t *cp, + int key_len, + int tag_len); + +/* + * a srtp_cipher_init_func_t [re-]initializes a cipher_t with a given key + */ +typedef srtp_err_status_t (*srtp_cipher_init_func_t)(void *state, + const uint8_t *key); + +/* a srtp_cipher_dealloc_func_t de-allocates a cipher_t */ +typedef srtp_err_status_t (*srtp_cipher_dealloc_func_t)( + srtp_cipher_pointer_t cp); + +/* + * a srtp_cipher_set_aad_func_t processes the AAD data for AEAD ciphers + */ +typedef srtp_err_status_t (*srtp_cipher_set_aad_func_t)(void *state, + const uint8_t *aad, + uint32_t aad_len); + +/* a srtp_cipher_encrypt_func_t encrypts data in-place */ +typedef srtp_err_status_t (*srtp_cipher_encrypt_func_t)( + void *state, + uint8_t *buffer, + unsigned int *octets_to_encrypt); + +/* a srtp_cipher_decrypt_func_t decrypts data in-place */ +typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t)( + void *state, + uint8_t *buffer, + unsigned int *octets_to_decrypt); + +/* + * a srtp_cipher_set_iv_func_t function sets the current initialization vector + */ +typedef srtp_err_status_t (*srtp_cipher_set_iv_func_t)( + void *state, + uint8_t *iv, + srtp_cipher_direction_t direction); + +/* + * a cipher_get_tag_func_t function is used to get the authentication + * tag that was calculated by an AEAD cipher. + */ +typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t)(void *state, + uint8_t *tag, + uint32_t *len); + +/* + * srtp_cipher_test_case_t is a (list of) key, salt, plaintext, ciphertext, + * and aad values that are known to be correct for a + * particular cipher. this data can be used to test an implementation + * in an on-the-fly self test of the correctness of the implementation. + * (see the srtp_cipher_type_self_test() function below) + */ +typedef struct srtp_cipher_test_case_t { + int key_length_octets; /* octets in key */ + const uint8_t *key; /* key */ + uint8_t *idx; /* packet index */ + unsigned int plaintext_length_octets; /* octets in plaintext */ + const uint8_t *plaintext; /* plaintext */ + unsigned int ciphertext_length_octets; /* octets in plaintext */ + const uint8_t *ciphertext; /* ciphertext */ + int aad_length_octets; /* octets in AAD */ + const uint8_t *aad; /* AAD */ + int tag_length_octets; /* Length of AEAD tag */ + const struct srtp_cipher_test_case_t + *next_test_case; /* pointer to next testcase */ +} srtp_cipher_test_case_t; + +/* srtp_cipher_type_t defines the 'metadata' for a particular cipher type */ +typedef struct srtp_cipher_type_t { + srtp_cipher_alloc_func_t alloc; + srtp_cipher_dealloc_func_t dealloc; + srtp_cipher_init_func_t init; + srtp_cipher_set_aad_func_t set_aad; + srtp_cipher_encrypt_func_t encrypt; + srtp_cipher_encrypt_func_t decrypt; + srtp_cipher_set_iv_func_t set_iv; + srtp_cipher_get_tag_func_t get_tag; + const char *description; + const srtp_cipher_test_case_t *test_data; + srtp_cipher_type_id_t id; +} srtp_cipher_type_t; + +/* + * srtp_cipher_t defines an instantiation of a particular cipher, with fixed + * key length, key and salt values + */ +typedef struct srtp_cipher_t { + const srtp_cipher_type_t *type; + void *state; + int key_len; + int algorithm; +} srtp_cipher_t; + +/* some bookkeeping functions */ +int srtp_cipher_get_key_length(const srtp_cipher_t *c); + +/* + * srtp_cipher_type_self_test() tests a cipher against test cases provided in + * an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext + * that is known to be good + */ +srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct); + +/* + * srtp_cipher_type_test() tests a cipher against external test cases provided + * in + * an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext + * that is known to be good + */ +srtp_err_status_t srtp_cipher_type_test( + const srtp_cipher_type_t *ct, + const srtp_cipher_test_case_t *test_data); + +/* + * srtp_cipher_bits_per_second(c, l, t) computes (an estimate of) the + * number of bits that a cipher implementation can encrypt in a second + * + * c is a cipher (which MUST be allocated and initialized already), l + * is the length in octets of the test data to be encrypted, and t is + * the number of trials + * + * if an error is encountered, then the value 0 is returned + */ +uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c, + int octets_in_buffer, + int num_trials); + +srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct, + srtp_cipher_t **c, + int key_len, + int tlen); +srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c); +srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key); +srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c, + uint8_t *iv, + int direction); +srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *tag_len); +srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, + const uint8_t *aad, + uint32_t aad_len); + +/* + * srtp_replace_cipher_type(ct, id) + * + * replaces srtp's existing cipher implementation for the cipher_type id + * with a new one passed in externally. The new cipher must pass all the + * existing cipher_type's self tests as well as its own. + */ +srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *ct, + srtp_cipher_type_id_t id); + +#ifdef __cplusplus +} +#endif + +#endif /* SRTP_CIPHER_H */ diff --git a/thirdparty/user_include/srtp2/crypto_types.h b/thirdparty/user_include/srtp2/crypto_types.h new file mode 100755 index 0000000000000000000000000000000000000000..7fd3178b0b04d2d560110673d23138dd49da0936 --- /dev/null +++ b/thirdparty/user_include/srtp2/crypto_types.h @@ -0,0 +1,116 @@ +/* + * crypto_types.h + * + * constants for cipher types and auth func types + * + * David A. McGrew + * Cisco Systems, Inc. + */ +/* + * + * Copyright(c) 2001-2017 Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_CRYPTO_TYPES_H +#define SRTP_CRYPTO_TYPES_H + +/* + * The null cipher performs no encryption. + * + * The SRTP_NULL_CIPHER leaves its inputs unaltered, during both the + * encryption and decryption operations. This cipher can be chosen + * to indicate that no encryption is to be performed. + */ +#define SRTP_NULL_CIPHER 0 + +/* + * AES-128 Integer Counter Mode (AES ICM) + * + * AES-128 ICM is the variant of counter mode that is used by + * Secure RTP. This cipher uses a 16-octet key concatenated with a + * 14-octet offset (or salt) value. + */ +#define SRTP_AES_ICM_128 1 + +/* + * AES-192 Integer Counter Mode (AES ICM) + * + * AES-128 ICM is the variant of counter mode that is used by + * Secure RTP. This cipher uses a 24-octet key concatenated with a + * 14-octet offset (or salt) value. + */ +#define SRTP_AES_ICM_192 4 + +/* + * AES-256 Integer Counter Mode (AES ICM) + * + * AES-128 ICM is the variant of counter mode that is used by + * Secure RTP. This cipher uses a 32-octet key concatenated with a + * 14-octet offset (or salt) value. + */ +#define SRTP_AES_ICM_256 5 + +/* + * AES-128_GCM Galois Counter Mode (AES GCM) + * + * AES-128 GCM is the variant of galois counter mode that is used by + * Secure RTP. This cipher uses a 16-octet key. + */ +#define SRTP_AES_GCM_128 6 + +/* + * AES-256_GCM Galois Counter Mode (AES GCM) + * + * AES-256 GCM is the variant of galois counter mode that is used by + * Secure RTP. This cipher uses a 32-octet key. + */ +#define SRTP_AES_GCM_256 7 + +/* + * The null authentication function performs no authentication. + * + * The NULL_AUTH function does nothing, and can be selected to indicate + * that authentication should not be performed. + */ +#define SRTP_NULL_AUTH 0 + +/* + * HMAC-SHA1 + * + * SRTP_HMAC_SHA1 implements the Hash-based MAC using the NIST Secure + * Hash Algorithm version 1 (SHA1). + */ +#define SRTP_HMAC_SHA1 3 + +#endif /* SRTP_CRYPTO_TYPES_H */ diff --git a/thirdparty/user_include/srtp2/srtp.h b/thirdparty/user_include/srtp2/srtp.h new file mode 100755 index 0000000000000000000000000000000000000000..c86b9ee7473e48f44efeaca5a1e77f25a10bb8f7 --- /dev/null +++ b/thirdparty/user_include/srtp2/srtp.h @@ -0,0 +1,1759 @@ +/* + * srtp.h + * + * interface to libsrtp + * + * David A. McGrew + * Cisco Systems, Inc. + */ +/* + * + * Copyright (c) 2001-2017, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRTP_SRTP_H +#define SRTP_SRTP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup SRTP Secure RTP + * + * @brief libSRTP provides functions for protecting RTP and RTCP. See + * Section @ref Overview for an introduction to the use of the library. + * + * @{ + */ + +/* + * SRTP_MASTER_KEY_LEN is the nominal master key length supported by libSRTP + */ + +#define SRTP_MASTER_KEY_LEN 30 + +/* + * SRTP_MAX_KEY_LEN is the maximum key length supported by libSRTP + */ +#define SRTP_MAX_KEY_LEN 64 + +/* + * SRTP_MAX_TAG_LEN is the maximum tag length supported by libSRTP + */ + +#define SRTP_MAX_TAG_LEN 16 + +/** + * SRTP_MAX_MKI_LEN is the maximum size the MKI could be which is + * 128 bytes + */ +#define SRTP_MAX_MKI_LEN 128 + +/** + * SRTP_MAX_TRAILER_LEN is the maximum length of the SRTP trailer + * (authentication tag and MKI) supported by libSRTP. This value is + * the maixmum number of octets that will be added to an RTP packet by + * srtp_protect(). + * + * @brief the maximum number of octets added by srtp_protect(). + */ +#define SRTP_MAX_TRAILER_LEN (SRTP_MAX_TAG_LEN + SRTP_MAX_MKI_LEN) + +/** + * SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for + * MKI supported by libSRTP. + * + */ +#define SRTP_MAX_NUM_MASTER_KEYS 16 + +#define SRTP_SALT_LEN 14 + +/* + * SRTP_AEAD_SALT_LEN is the length of the SALT values used with + * GCM mode. GCM mode requires an IV. The SALT value is used + * as part of the IV formation logic applied to each RTP packet. + */ +#define SRTP_AEAD_SALT_LEN 12 + +#define SRTP_AES_128_KEY_LEN 16 +#define SRTP_AES_192_KEY_LEN 24 +#define SRTP_AES_256_KEY_LEN 32 + +#define SRTP_AES_ICM_128_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_128_KEY_LEN) +#define SRTP_AES_ICM_192_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_192_KEY_LEN) +#define SRTP_AES_ICM_256_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_256_KEY_LEN) + +#define SRTP_AES_GCM_128_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_128_KEY_LEN) +#define SRTP_AES_GCM_192_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_192_KEY_LEN) +#define SRTP_AES_GCM_256_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_256_KEY_LEN) + +/** + * @brief A srtp_cipher_type_id_t is an identifier for a particular cipher + * type. + * + * A srtp_cipher_type_id_t is an integer that represents a particular + * cipher type, e.g. the Advanced Encryption Standard (AES). A + * SRTP_NULL_CIPHER is avaliable; this cipher leaves the data unchanged, + * and can be selected to indicate that no encryption is to take + * place. + * + * @ingroup Ciphers + */ +typedef uint32_t srtp_cipher_type_id_t; + +/** + * @brief An srtp_auth_type_id_t is an identifier for a particular + * authentication + * function. + * + * An srtp_auth_type_id_t is an integer that represents a particular + * authentication function type, e.g. HMAC-SHA1. A SRTP_NULL_AUTH is + * avaliable; this authentication function performs no computation, + * and can be selected to indicate that no authentication is to take + * place. + * + * @ingroup Authentication + */ +typedef uint32_t srtp_auth_type_id_t; + +/** + * @brief srtp_err_status_t defines error codes. + * + * The enumeration srtp_err_status_t defines error codes. Note that the + * value of srtp_err_status_ok is equal to zero, which can simplify error + * checking somewhat. + * + */ +typedef enum { + srtp_err_status_ok = 0, /**< nothing to report */ + srtp_err_status_fail = 1, /**< unspecified failure */ + srtp_err_status_bad_param = 2, /**< unsupported parameter */ + srtp_err_status_alloc_fail = 3, /**< couldn't allocate memory */ + srtp_err_status_dealloc_fail = 4, /**< couldn't deallocate properly */ + srtp_err_status_init_fail = 5, /**< couldn't initialize */ + srtp_err_status_terminus = 6, /**< can't process as much data as */ + /**< requested */ + srtp_err_status_auth_fail = 7, /**< authentication failure */ + srtp_err_status_cipher_fail = 8, /**< cipher failure */ + srtp_err_status_replay_fail = 9, /**< replay check failed (bad index) */ + srtp_err_status_replay_old = 10, /**< replay check failed (index too */ + /**< old) */ + srtp_err_status_algo_fail = 11, /**< algorithm failed test routine */ + srtp_err_status_no_such_op = 12, /**< unsupported operation */ + srtp_err_status_no_ctx = 13, /**< no appropriate context found */ + srtp_err_status_cant_check = 14, /**< unable to perform desired */ + /**< validation */ + srtp_err_status_key_expired = 15, /**< can't use key any more */ + srtp_err_status_socket_err = 16, /**< error in use of socket */ + srtp_err_status_signal_err = 17, /**< error in use POSIX signals */ + srtp_err_status_nonce_bad = 18, /**< nonce check failed */ + srtp_err_status_read_fail = 19, /**< couldn't read data */ + srtp_err_status_write_fail = 20, /**< couldn't write data */ + srtp_err_status_parse_err = 21, /**< error parsing data */ + srtp_err_status_encode_err = 22, /**< error encoding data */ + srtp_err_status_semaphore_err = 23, /**< error while using semaphores */ + srtp_err_status_pfkey_err = 24, /**< error while using pfkey */ + srtp_err_status_bad_mki = 25, /**< error MKI present in packet is */ + /**< invalid */ + srtp_err_status_pkt_idx_old = 26, /**< packet index is too old to */ + /**< consider */ + srtp_err_status_pkt_idx_adv = 27 /**< packet index advanced, reset */ + /**< needed */ +} srtp_err_status_t; + +typedef struct srtp_ctx_t_ srtp_ctx_t; + +/** + * @brief srtp_sec_serv_t describes a set of security services. + * + * A srtp_sec_serv_t enumeration is used to describe the particular + * security services that will be applied by a particular crypto + * policy (or other mechanism). + */ +typedef enum { + sec_serv_none = 0, /**< no services */ + sec_serv_conf = 1, /**< confidentiality */ + sec_serv_auth = 2, /**< authentication */ + sec_serv_conf_and_auth = 3 /**< confidentiality and authentication */ +} srtp_sec_serv_t; + +/** + * @brief srtp_crypto_policy_t describes a particular crypto policy that + * can be applied to an SRTP stream. + * + * A srtp_crypto_policy_t describes a particular cryptographic policy that + * can be applied to an SRTP or SRTCP stream. An SRTP session policy + * consists of a list of these policies, one for each SRTP stream + * in the session. + */ +typedef struct srtp_crypto_policy_t { + srtp_cipher_type_id_t cipher_type; /**< An integer representing */ + /**< the type of cipher. */ + int cipher_key_len; /**< The length of the cipher key */ + /**< in octets. */ + srtp_auth_type_id_t auth_type; /**< An integer representing the */ + /**< authentication function. */ + int auth_key_len; /**< The length of the authentication */ + /**< function key in octets. */ + int auth_tag_len; /**< The length of the authentication */ + /**< tag in octets. */ + srtp_sec_serv_t sec_serv; /**< The flag indicating the security */ + /**< services to be applied. */ +} srtp_crypto_policy_t; + +/** + * @brief srtp_ssrc_type_t describes the type of an SSRC. + * + * An srtp_ssrc_type_t enumeration is used to indicate a type of SSRC. See + * @ref srtp_policy_t for more informataion. + */ +typedef enum { + ssrc_undefined = 0, /**< Indicates an undefined SSRC type. */ + ssrc_specific = 1, /**< Indicates a specific SSRC value */ + ssrc_any_inbound = 2, /**< Indicates any inbound SSRC value */ + /**< (i.e. a value that is used in the */ + /**< function srtp_unprotect()) */ + ssrc_any_outbound = 3 /**< Indicates any outbound SSRC value */ + /**< (i.e. a value that is used in the */ + /**< function srtp_protect()) */ +} srtp_ssrc_type_t; + +/** + * @brief An srtp_ssrc_t represents a particular SSRC value, or a `wildcard' + * SSRC. + * + * An srtp_ssrc_t represents a particular SSRC value (if its type is + * ssrc_specific), or a wildcard SSRC value that will match all + * outbound SSRCs (if its type is ssrc_any_outbound) or all inbound + * SSRCs (if its type is ssrc_any_inbound). + */ +typedef struct { + srtp_ssrc_type_t type; /**< The type of this particular SSRC */ + unsigned int value; /**< The value of this SSRC, if it is not a */ + /**< wildcard */ +} srtp_ssrc_t; + +/** + * @brief points to an EKT policy + */ +typedef struct srtp_ekt_policy_ctx_t *srtp_ekt_policy_t; + +/** + * @brief points to EKT stream data + */ +typedef struct srtp_ekt_stream_ctx_t *srtp_ekt_stream_t; + +/** + * @brief srtp_master_key_t represents a master key. There will + * be a Master Key Index and the Master Key associated with the + * Master Key Index. Need to also keep track of the Master Key + * Index Size to correctly read it from a packet. + */ +typedef struct srtp_master_key_t { + unsigned char *key; + unsigned char *mki_id; + unsigned int mki_size; +} srtp_master_key_t; + +/** + * @brief represents the policy for an SRTP session. + * + * A single srtp_policy_t struct represents the policy for a single + * SRTP stream, and a linked list of these elements represents the + * policy for an entire SRTP session. Each element contains the SRTP + * and SRTCP crypto policies for that stream, a pointer to the SRTP + * master key for that stream, the SSRC describing that stream, or a + * flag indicating a `wildcard' SSRC value, and a `next' field that + * holds a pointer to the next element in the list of policy elements, + * or NULL if it is the last element. + * + * The wildcard value SSRC_ANY_INBOUND matches any SSRC from an + * inbound stream that for which there is no explicit SSRC entry in + * another policy element. Similarly, the value SSRC_ANY_OUTBOUND + * will matches any SSRC from an outbound stream that does not appear + * in another policy element. Note that wildcard SSRCs &b cannot be + * used to match both inbound and outbound traffic. This restriction + * is intentional, and it allows libSRTP to ensure that no security + * lapses result from accidental re-use of SSRC values during key + * sharing. + * + * @warning The final element of the list @b must have its `next' pointer + * set to NULL. + */ + +typedef struct srtp_policy_t { + srtp_ssrc_t ssrc; /**< The SSRC value of stream, or the */ + /**< flags SSRC_ANY_INBOUND or */ + /**< SSRC_ANY_OUTBOUND if key sharing */ + /**< is used for this policy element. */ + srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ + srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ + unsigned char *key; /**< Pointer to the SRTP master key for */ + /**< this stream. */ + srtp_master_key_t **keys; /** Array of Master Key structures */ + unsigned long num_master_keys; /** Number of master keys */ + srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure */ + /**< for this stream (if any) */ + unsigned long window_size; /**< The window size to use for replay */ + /**< protection. */ + int allow_repeat_tx; /**< Whether retransmissions of */ + /**< packets with the same sequence */ + /**< number are allowed. */ + /**< (Note that such repeated */ + /**< transmissions must have the same */ + /**< RTP payload, or a severe security */ + /**< weakness is introduced!) */ + int *enc_xtn_hdr; /**< List of header ids to encrypt. */ + int enc_xtn_hdr_count; /**< Number of entries in list of header */ + /**< ids. */ + struct srtp_policy_t *next; /**< Pointer to next stream policy. */ +} srtp_policy_t; + +/** + * @brief An srtp_t points to an SRTP session structure. + * + * The typedef srtp_t is a pointer to a structure that represents + * an SRTP session. This datatype is intentially opaque in + * order to separate the interface from the implementation. + * + * An SRTP session consists of all of the traffic sent to the RTP and + * RTCP destination transport addresses, using the RTP/SAVP (Secure + * Audio/Video Profile). A session can be viewed as a set of SRTP + * streams, each of which originates with a different participant. + */ +typedef srtp_ctx_t *srtp_t; + +/** + * @brief srtp_init() initializes the srtp library. + * + * @warning This function @b must be called before any other srtp + * functions. + */ +srtp_err_status_t srtp_init(void); + +/** + * @brief srtp_shutdown() de-initializes the srtp library. + * + * @warning No srtp functions may be called after calling this function. + */ +srtp_err_status_t srtp_shutdown(void); + +/** + * @brief srtp_protect() is the Secure RTP sender-side packet processing + * function. + * + * The function call srtp_protect(ctx, rtp_hdr, len_ptr) applies SRTP + * protection to the RTP packet rtp_hdr (which has length *len_ptr) using + * the SRTP context ctx. If srtp_err_status_ok is returned, then rtp_hdr + * points to the resulting SRTP packet and *len_ptr is the number of + * octets in that packet; otherwise, no assumptions should be made + * about the value of either data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTP + * packet, and assumes that the RTP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN + * into the location in memory immediately following the RTP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtp_hdr is a pointer to the RTP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param len_ptr is a pointer to the length in octets of the complete + * RTP packet (header and body) before the function call, and of the + * complete SRTP packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @return + * - srtp_err_status_ok no problems + * - srtp_err_status_replay_fail rtp sequence number was non-increasing + * - @e other failure in cryptographic mechanisms + */ +srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); + +/** + * @brief srtp_protect_mki() is the Secure RTP sender-side packet processing + * function that can utilize MKI. + * + * The function call srtp_protect(ctx, rtp_hdr, len_ptr) applies SRTP + * protection to the RTP packet rtp_hdr (which has length *len_ptr) using + * the SRTP context ctx. If srtp_err_status_ok is returned, then rtp_hdr + * points to the resulting SRTP packet and *len_ptr is the number of + * octets in that packet; otherwise, no assumptions should be made + * about the value of either data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTP + * packet, and assumes that the RTP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN + * into the location in memory immediately following the RTP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtp_hdr is a pointer to the RTP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param pkt_octet_len is a pointer to the length in octets of the complete + * RTP packet (header and body) before the function call, and of the + * complete SRTP packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will + * use the session keys identified by the mki_index + * + * @param mki_index integer value specifying which set of session keys should be + * used if use_mki is set to true. + * + * @return + * - srtp_err_status_ok no problems + * - srtp_err_status_replay_fail rtp sequence number was non-increasing + * - @e other failure in cryptographic mechanisms + */ +srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, + void *rtp_hdr, + int *pkt_octet_len, + unsigned int use_mki, + unsigned int mki_index); + +/** + * @brief srtp_unprotect() is the Secure RTP receiver-side packet + * processing function. + * + * The function call srtp_unprotect(ctx, srtp_hdr, len_ptr) verifies + * the Secure RTP protection of the SRTP packet pointed to by srtp_hdr + * (which has length *len_ptr), using the SRTP context ctx. If + * srtp_err_status_ok is returned, then srtp_hdr points to the resulting + * RTP packet and *len_ptr is the number of octets in that packet; + * otherwise, no assumptions should be made about the value of either + * data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that the SRTP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is the SRTP session which applies to the particular packet. + * + * @param srtp_hdr is a pointer to the header of the SRTP packet + * (before the call). after the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param len_ptr is a pointer to the length in octets of the complete + * srtp packet (header and body) before the function call, and of the + * complete rtp packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @return + * - srtp_err_status_ok if the RTP packet is valid. + * - srtp_err_status_auth_fail if the SRTP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet + * has already been processed and accepted). + * - [other] if there has been an error in the cryptographic mechanisms. + * + */ +srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); + +/** + * @brief srtp_unprotect_mki() is the Secure RTP receiver-side packet + * processing function that checks for MKI. + * + * The function call srtp_unprotect(ctx, srtp_hdr, len_ptr) verifies + * the Secure RTP protection of the SRTP packet pointed to by srtp_hdr + * (which has length *len_ptr), using the SRTP context ctx. If + * srtp_err_status_ok is returned, then srtp_hdr points to the resulting + * RTP packet and *len_ptr is the number of octets in that packet; + * otherwise, no assumptions should be made about the value of either + * data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that the SRTP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is the SRTP session which applies to the particular packet. + * + * @param srtp_hdr is a pointer to the header of the SRTP packet + * (before the call). after the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param len_ptr is a pointer to the length in octets of the complete + * srtp packet (header and body) before the function call, and of the + * complete rtp packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will + * use the session keys identified by the mki_index + * + * @return + * - srtp_err_status_ok if the RTP packet is valid. + * - srtp_err_status_auth_fail if the SRTP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet + * has already been processed and accepted). + * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI id + * - [other] if there has been an error in the cryptographic mechanisms. + * + */ +srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, + void *srtp_hdr, + int *len_ptr, + unsigned int use_mki); + +/** + * @brief srtp_create() allocates and initializes an SRTP session. + + * The function call srtp_create(session, policy) allocates and + * initializes an SRTP session context, applying the given policy. + * + * @param session is a pointer to the SRTP session to which the policy is + * to be added. + * + * @param policy is the srtp_policy_t struct that describes the policy + * for the session. The struct may be a single element, or it may be + * the head of a list, in which case each element of the list is + * processed. It may also be NULL, in which case streams should be added + * later using srtp_add_stream(). The final element of the list @b must + * have its `next' field set to NULL. + * + * @return + * - srtp_err_status_ok if creation succeded. + * - srtp_err_status_alloc_fail if allocation failed. + * - srtp_err_status_init_fail if initialization failed. + */ +srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t *policy); + +/** + * @brief srtp_add_stream() allocates and initializes an SRTP stream + * within a given SRTP session. + * + * The function call srtp_add_stream(session, policy) allocates and + * initializes a new SRTP stream within a given, previously created + * session, applying the policy given as the other argument to that + * stream. + * + * @return values: + * - srtp_err_status_ok if stream creation succeded. + * - srtp_err_status_alloc_fail if stream allocation failed + * - srtp_err_status_init_fail if stream initialization failed. + */ +srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy); + +/** + * @brief srtp_remove_stream() deallocates an SRTP stream. + * + * The function call srtp_remove_stream(session, ssrc) removes + * the SRTP stream with the SSRC value ssrc from the SRTP session + * context given by the argument session. + * + * @param session is the SRTP session from which the stream + * will be removed. + * + * @param ssrc is the SSRC value of the stream to be removed + * in network byte order. + * + * @warning Wildcard SSRC values cannot be removed from a + * session. + * + * @return + * - srtp_err_status_ok if the stream deallocation succeded. + * - [other] otherwise. + * + */ +srtp_err_status_t srtp_remove_stream(srtp_t session, unsigned int ssrc); + +/** + * @brief srtp_update() udpates all streams in the session. + * + * The function call srtp_update(session, policy) updates + * all the streams in the session applying the given policy + * and key. The exsisting ROC value of all streams will be + * preserved. + * + * @param session is the SRTP session that contains the streams + * to be updated. + * + * @param policy is the srtp_policy_t struct that describes the policy + * for the session. The struct may be a single element, or it may be + * the head of a list, in which case each element of the list is + * processed. The final element of the list @b must + * have its `next' field set to NULL. + * + * @return + * - srtp_err_status_ok if stream creation succeded. + * - srtp_err_status_alloc_fail if stream allocation failed + * - srtp_err_status_init_fail if stream initialization failed. + * - [other] otherwise. + * + */ +srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); + +/** + * @brief srtp_update_stream() udpates a SRTP stream. + * + * The function call srtp_update_stream(session, policy) updates + * the stream(s) in the session that match applying the given + * policy and key. The exsisting ROC value of all stream(s) will + * be preserved. + * + * @param session is the SRTP session that contains the streams + * to be updated. + * + * @param policy is the srtp_policy_t struct that describes the policy + * for the session. + * + * @return + * - srtp_err_status_ok if stream creation succeded. + * - srtp_err_status_alloc_fail if stream allocation failed + * - srtp_err_status_init_fail if stream initialization failed. + * - [other] otherwise. + * + */ +srtp_err_status_t srtp_update_stream(srtp_t session, + const srtp_policy_t *policy); + +/** + * @brief srtp_crypto_policy_set_rtp_default() sets a crypto policy + * structure to the SRTP default policy for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_rtp_default(&p) sets the + * srtp_crypto_policy_t at location p to the SRTP default policy for RTP + * protection, as defined in the specification. This function is a + * convenience that helps to avoid dealing directly with the policy + * data structure. You are encouraged to initialize policy elements + * with this function call. Doing so may allow your code to be + * forward compatible with later versions of libSRTP that include more + * elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_rtcp_default() sets a crypto policy + * structure to the SRTP default policy for RTCP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_rtcp_default(&p) sets the + * srtp_crypto_policy_t at location p to the SRTP default policy for RTCP + * protection, as defined in the specification. This function is a + * convenience that helps to avoid dealing directly with the policy + * data structure. You are encouraged to initialize policy elements + * with this function call. Doing so may allow your code to be + * forward compatible with later versions of libSRTP that include more + * elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto + * policy structure to the SRTP default policy for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() is a + * synonym for srtp_crypto_policy_set_rtp_default(). It conforms to the + * naming convention used in RFC 4568 (SDP Security Descriptions for + * Media Streams). + * + * @return void. + * + */ +#define srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(p) \ + srtp_crypto_policy_set_rtp_default(p) + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568. + * This policy uses AES-128 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_128_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_128_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto + * policy structure to an authentication-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use HMAC-SHA1 with an 80 + * bit authentication tag to provide message authentication, but to + * use no encryption. This policy is NOT RECOMMENDED for SRTP unless + * there is a requirement to forego encryption. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless there is a + * requirement to forego encryption. + * + * @return void. + * + */ +void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_null_cipher_hmac_null() sets a crypto + * policy structure to use no encryption or authentication. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_null_cipher_hmac_null(&p) + * sets the srtp_crypto_policy_t at location p to use no encryption and + * no authentication. This policy should only be used for testing and + * troubleshootingl. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless there is a + * requirement to forego encryption and authentication. + * + * @return void. + * + */ +void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto + * policy structure to a encryption and authentication policy using AES-256 + * for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_256_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-256 + * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit + * authentication tag. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy using AES-256 + * encryption. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_256_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-256 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_256_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_256_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80() sets a crypto + * policy structure to a encryption and authentication policy using AES-192 + * for RTP protection. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_192_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-192 + * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit + * authentication tag. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32() sets a crypto + * policy structure to a short-authentication tag policy using AES-192 + * encryption. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(&p) + * sets the srtp_crypto_policy_t at location p to use policy + * AES_CM_192_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-192 + * Counter Mode encryption and HMAC-SHA1 authentication, with an + * authentication tag that is only 32 bits long. This length is + * considered adequate only for protecting audio and video media that + * use a stateless playback function. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This crypto policy is intended for use in SRTP, but not in + * SRTCP. It is recommended that a policy that uses longer + * authentication tags be used for SRTCP. See Section 7.5 of RFC 3711 + * (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_cm_192_null_auth() sets a crypto + * policy structure to an encryption-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_cm_192_null_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-192 Counter Mode), but to use no authentication method. This + * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 + * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @warning This policy is NOT RECOMMENDED for SRTP unless it is + * unavoidable, and it is NOT RECOMMENDED at all for SRTCP; see + * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_128_8_auth() sets a crypto + * policy structure to an AEAD encryption policy. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_128_8_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Galois Counter Mode) with 8 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_256_8_auth() sets a crypto + * policy structure to an AEAD encryption policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_256_8_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Galois Counter Mode) with 8 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_128_8_only_auth() sets a crypto + * policy structure to an AEAD authentication-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Galois Counter Mode) with 8 octet auth tag. This policy + * applies confidentiality and authentication to the RTP packets, + * but only authentication to the RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_256_8_only_auth() sets a crypto + * policy structure to an AEAD authentication-only policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Galois Counter Mode) with 8 octet auth tag. This policy + * applies confidentiality and authentication to the RTP packets, + * but only authentication to the RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_128_16_auth() sets a crypto + * policy structure to an AEAD encryption policy. + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_128_16_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-128 Galois Counter Mode) with 16 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_crypto_policy_set_aes_gcm_256_16_auth() sets a crypto + * policy structure to an AEAD encryption policy + * + * @param p is a pointer to the policy structure to be set + * + * The function call srtp_crypto_policy_set_aes_gcm_256_16_auth(&p) sets + * the srtp_crypto_policy_t at location p to use the SRTP default cipher + * (AES-256 Galois Counter Mode) with 16 octet auth tag. This + * policy applies confidentiality and authentication to both the + * RTP and RTCP packets. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return void. + * + */ +void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); + +/** + * @brief srtp_dealloc() deallocates storage for an SRTP session + * context. + * + * The function call srtp_dealloc(s) deallocates storage for the + * SRTP session context s. This function should be called no more + * than one time for each of the contexts allocated by the function + * srtp_create(). + * + * @param s is the srtp_t for the session to be deallocated. + * + * @return + * - srtp_err_status_ok if there no problems. + * - srtp_err_status_dealloc_fail a memory deallocation failure occured. + */ +srtp_err_status_t srtp_dealloc(srtp_t s); + +/* + * @brief identifies a particular SRTP profile + * + * An srtp_profile_t enumeration is used to identify a particular SRTP + * profile (that is, a set of algorithms and parameters). These profiles + * are defined for DTLS-SRTP: + * https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + */ +typedef enum { + srtp_profile_reserved = 0, + srtp_profile_aes128_cm_sha1_80 = 1, + srtp_profile_aes128_cm_sha1_32 = 2, + srtp_profile_null_sha1_80 = 5, + srtp_profile_null_sha1_32 = 6, + srtp_profile_aead_aes_128_gcm = 7, + srtp_profile_aead_aes_256_gcm = 8, +} srtp_profile_t; + +/** + * @brief srtp_crypto_policy_set_from_profile_for_rtp() sets a crypto policy + * structure to the appropriate value for RTP based on an srtp_profile_t + * + * @param policy is a pointer to the policy structure to be set + * + * @param profile is an enumeration for the policy to be set + * + * The function call srtp_crypto_policy_set_rtp_default(&policy, profile) + * sets the srtp_crypto_policy_t at location policy to the policy for RTP + * protection, as defined by the srtp_profile_t profile. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return values + * - srtp_err_status_ok no problems were encountered + * - srtp_err_status_bad_param the profile is not supported + * + */ +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); + +/** + * @brief srtp_crypto_policy_set_from_profile_for_rtcp() sets a crypto policy + * structure to the appropriate value for RTCP based on an srtp_profile_t + * + * @param policy is a pointer to the policy structure to be set + * + * @param profile is an enumeration for the policy to be set + * + * The function call srtp_crypto_policy_set_rtcp_default(&policy, profile) + * sets the srtp_crypto_policy_t at location policy to the policy for RTCP + * protection, as defined by the srtp_profile_t profile. + * + * This function is a convenience that helps to avoid dealing directly + * with the policy data structure. You are encouraged to initialize + * policy elements with this function call. Doing so may allow your + * code to be forward compatible with later versions of libSRTP that + * include more elements in the srtp_crypto_policy_t datatype. + * + * @return values + * - srtp_err_status_ok no problems were encountered + * - srtp_err_status_bad_param the profile is not supported + * + */ +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); + +/** + * @brief returns the master key length for a given SRTP profile + */ +unsigned int srtp_profile_get_master_key_length(srtp_profile_t profile); + +/** + * @brief returns the master salt length for a given SRTP profile + */ +unsigned int srtp_profile_get_master_salt_length(srtp_profile_t profile); + +/** + * @brief appends the salt to the key + * + * The function call srtp_append_salt_to_key(k, klen, s, slen) + * copies the string s to the location at klen bytes following + * the location k. + * + * @warning There must be at least bytes_in_salt + bytes_in_key bytes + * available at the location pointed to by key. + * + */ +void srtp_append_salt_to_key(unsigned char *key, + unsigned int bytes_in_key, + unsigned char *salt, + unsigned int bytes_in_salt); + +/** + * @} + */ + +/** + * @defgroup SRTCP Secure RTCP + * @ingroup SRTP + * + * @brief Secure RTCP functions are used to protect RTCP traffic. + * + * RTCP is the control protocol for RTP. libSRTP protects RTCP + * traffic in much the same way as it does RTP traffic. The function + * srtp_protect_rtcp() applies cryptographic protections to outbound + * RTCP packets, and srtp_unprotect_rtcp() verifies the protections on + * inbound RTCP packets. + * + * A note on the naming convention: srtp_protect_rtcp() has an srtp_t + * as its first argument, and thus has `srtp_' as its prefix. The + * trailing `_rtcp' indicates the protocol on which it acts. + * + * @{ + */ + +/** + * @brief srtp_protect_rtcp() is the Secure RTCP sender-side packet + * processing function. + * + * The function call srtp_protect_rtcp(ctx, rtp_hdr, len_ptr) applies + * SRTCP protection to the RTCP packet rtcp_hdr (which has length + * *len_ptr) using the SRTP session context ctx. If srtp_err_status_ok is + * returned, then rtp_hdr points to the resulting SRTCP packet and + * *len_ptr is the number of octets in that packet; otherwise, no + * assumptions should be made about the value of either data elements. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTCP + * packet, and assumes that the RTCP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 + * into the location in memory immediately following the RTCP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTCP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtcp_hdr is a pointer to the RTCP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete RTCP packet (header and body) before the function call, + * and of the complete SRTCP packet after the call, if srtp_err_status_ok + * was returned. Otherwise, the value of the data to which it points + * is undefined. + * + * @return + * - srtp_err_status_ok if there were no problems. + * - [other] if there was a failure in + * the cryptographic mechanisms. + */ +srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len); + +/** + * @brief srtp_protect_rtcp_mki() is the Secure RTCP sender-side packet + * processing function that can utilize mki. + * + * The function call srtp_protect_rtcp(ctx, rtp_hdr, len_ptr) applies + * SRTCP protection to the RTCP packet rtcp_hdr (which has length + * *len_ptr) using the SRTP session context ctx. If srtp_err_status_ok is + * returned, then rtp_hdr points to the resulting SRTCP packet and + * *len_ptr is the number of octets in that packet; otherwise, no + * assumptions should be made about the value of either data elements. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTCP + * packet, and assumes that the RTCP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 + * into the location in memory immediately following the RTCP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTCP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtcp_hdr is a pointer to the RTCP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete RTCP packet (header and body) before the function call, + * and of the complete SRTCP packet after the call, if srtp_err_status_ok + * was returned. Otherwise, the value of the data to which it points + * is undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will + * use the session keys identified by the mki_index + * + * @param mki_index integer value specifying which set of session kesy should be + * used if use_mki is set to true. + * + * @return + * - srtp_err_status_ok if there were no problems. + * - [other] if there was a failure in + * the cryptographic mechanisms. + */ +srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki, + unsigned int mki_index); + +/** + * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet + * processing function. + * + * The function call srtp_unprotect_rtcp(ctx, srtp_hdr, len_ptr) + * verifies the Secure RTCP protection of the SRTCP packet pointed to + * by srtcp_hdr (which has length *len_ptr), using the SRTP session + * context ctx. If srtp_err_status_ok is returned, then srtcp_hdr points + * to the resulting RTCP packet and *len_ptr is the number of octets + * in that packet; otherwise, no assumptions should be made about the + * value of either data elements. + * + * @warning This function assumes that the SRTCP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is a pointer to the srtp_t which applies to the + * particular packet. + * + * @param srtcp_hdr is a pointer to the header of the SRTCP packet + * (before the call). After the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete SRTCP packet (header and body) before the function call, + * and of the complete rtp packet after the call, if srtp_err_status_ok was + * returned. Otherwise, the value of the data to which it points is + * undefined. + * + * @return + * - srtp_err_status_ok if the RTCP packet is valid. + * - srtp_err_status_auth_fail if the SRTCP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTCP packet is a replay (e.g. has + * already been processed and accepted). + * - [other] if there has been an error in the cryptographic mechanisms. + * + */ +srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, + void *srtcp_hdr, + int *pkt_octet_len); + +/** + * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet + * processing function. + * + * The function call srtp_unprotect_rtcp(ctx, srtp_hdr, len_ptr) + * verifies the Secure RTCP protection of the SRTCP packet pointed to + * by srtcp_hdr (which has length *len_ptr), using the SRTP session + * context ctx. If srtp_err_status_ok is returned, then srtcp_hdr points + * to the resulting RTCP packet and *len_ptr is the number of octets + * in that packet; otherwise, no assumptions should be made about the + * value of either data elements. + * + * @warning This function assumes that the SRTCP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is a pointer to the srtp_t which applies to the + * particular packet. + * + * @param srtcp_hdr is a pointer to the header of the SRTCP packet + * (before the call). After the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete SRTCP packet (header and body) before the function call, + * and of the complete rtp packet after the call, if srtp_err_status_ok was + * returned. Otherwise, the value of the data to which it points is + * undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will use the session keys identified by the mki_index + * + * @return + * - srtp_err_status_ok if the RTCP packet is valid. + * - srtp_err_status_auth_fail if the SRTCP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTCP packet is a replay (e.g. has + * already been processed and accepted). + * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI + * id + * - [other] if there has been an error in the + * cryptographic mechanisms. + * + */ +srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, + void *srtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki); + +/** + * @} + */ + +/** + * @defgroup User data associated to a SRTP session. + * @ingroup SRTP + * + * @brief Store custom user data within a SRTP session. + * + * @{ + */ + +/** + * @brief srtp_set_user_data() stores the given pointer into the SRTP + * session for later retrieval. + * + * @param ctx is the srtp_t context in which the given data pointer is + * stored. + * + * @param data is a pointer to the custom information (struct, function, + * etc) associated with the SRTP session. + * + * @return void. + * + */ +void srtp_set_user_data(srtp_t ctx, void *data); + +/** + * @brief srtp_get_user_data() retrieves the pointer to the custom data + * previously stored with srtp_set_user_data(). + * + * This function is mostly useful for retrieving data associated to a + * SRTP session when an event fires. The user can then get such a custom + * data by calling this function with the session field of the + * srtp_event_data_t struct as argument. + * + * @param ctx is the srtp_t context in which the given data pointer was + * stored. + * + * @return void* pointer to the user data. + * + */ +void *srtp_get_user_data(srtp_t ctx); + +/** + * @} + */ + +/** + * @defgroup SRTPevents SRTP events and callbacks + * @ingroup SRTP + * + * @brief libSRTP can use a user-provided callback function to + * handle events. + * + * + * libSRTP allows a user to provide a callback function to handle + * events that need to be dealt with outside of the data plane (see + * the enum srtp_event_t for a description of these events). Dealing + * with these events is not a strict necessity; they are not + * security-critical, but the application may suffer if they are not + * handled. The function srtp_set_event_handler() is used to provide + * the callback function. + * + * A default event handler that merely reports on the events as they + * happen is included. It is also possible to set the event handler + * function to NULL, in which case all events will just be silently + * ignored. + * + * @{ + */ + +/** + * @brief srtp_event_t defines events that need to be handled + * + * The enum srtp_event_t defines events that need to be handled + * outside the `data plane', such as SSRC collisions and + * key expirations. + * + * When a key expires or the maximum number of packets has been + * reached, an SRTP stream will enter an `expired' state in which no + * more packets can be protected or unprotected. When this happens, + * it is likely that you will want to either deallocate the stream + * (using srtp_remove_stream()), and possibly allocate a new one. + * + * When an SRTP stream expires, the other streams in the same session + * are unaffected, unless key sharing is used by that stream. In the + * latter case, all of the streams in the session will expire. + */ +typedef enum { + event_ssrc_collision, /**< An SSRC collision occured. */ + event_key_soft_limit, /**< An SRTP stream reached the soft key */ + /**< usage limit and will expire soon. */ + event_key_hard_limit, /**< An SRTP stream reached the hard */ + /**< key usage limit and has expired. */ + event_packet_index_limit /**< An SRTP stream reached the hard */ + /**< packet limit (2^48 packets). */ +} srtp_event_t; + +/** + * @brief srtp_event_data_t is the structure passed as a callback to + * the event handler function + * + * The struct srtp_event_data_t holds the data passed to the event + * handler function. + */ +typedef struct srtp_event_data_t { + srtp_t session; /**< The session in which the event happend. */ + uint32_t ssrc; /**< The ssrc in host order of the stream in which */ + /**< the event happend */ + srtp_event_t event; /**< An enum indicating the type of event. */ +} srtp_event_data_t; + +/** + * @brief srtp_event_handler_func_t is the function prototype for + * the event handler. + * + * The typedef srtp_event_handler_func_t is the prototype for the + * event handler function. It has as its only argument an + * srtp_event_data_t which describes the event that needs to be handled. + * There can only be a single, global handler for all events in + * libSRTP. + */ +typedef void(srtp_event_handler_func_t)(srtp_event_data_t *data); + +/** + * @brief sets the event handler to the function supplied by the caller. + * + * The function call srtp_install_event_handler(func) sets the event + * handler function to the value func. The value NULL is acceptable + * as an argument; in this case, events will be ignored rather than + * handled. + * + * @param func is a pointer to a fuction that takes an srtp_event_data_t + * pointer as an argument and returns void. This function + * will be used by libSRTP to handle events. + */ +srtp_err_status_t srtp_install_event_handler(srtp_event_handler_func_t func); + +/** + * @brief Returns the version string of the library. + * + */ +const char *srtp_get_version_string(void); + +/** + * @brief Returns the numeric representation of the library version. + * + */ +unsigned int srtp_get_version(void); + +/** + * @brief srtp_set_debug_module(mod_name, v) + * + * sets dynamic debugging to the value v (0 for off, 1 for on) for the + * debug module with the name mod_name + * + * returns err_status_ok on success, err_status_fail otherwise + */ +srtp_err_status_t srtp_set_debug_module(const char *mod_name, int v); + +/** + * @brief srtp_list_debug_modules() outputs a list of debugging modules + * + */ +srtp_err_status_t srtp_list_debug_modules(void); + +/** + * @brief srtp_log_level_t defines log levels. + * + * The enumeration srtp_log_level_t defines log levels reported + * in the srtp_log_handler_func_t. + * + */ +typedef enum { + srtp_log_level_error, /**< log level is reporting an error message */ + srtp_log_level_warning, /**< log level is reporting a warning message */ + srtp_log_level_info, /**< log level is reporting an info message */ + srtp_log_level_debug /**< log level is reporting a debug message */ +} srtp_log_level_t; + +/** + * @brief srtp_log_handler_func_t is the function prototype for + * the log handler. + * + * The typedef srtp_event_handler_func_t is the prototype for the + * event handler function. It has as srtp_log_level_t, log + * message and data as arguments. + * There can only be a single, global handler for all log messages in + * libSRTP. + */ +typedef void(srtp_log_handler_func_t)(srtp_log_level_t level, + const char *msg, + void *data); + +/** + * @brief sets the log handler to the function supplied by the caller. + * + * The function call srtp_install_log_handler(func) sets the log + * handler function to the value func. The value NULL is acceptable + * as an argument; in this case, log messages will be ignored. + * This function can be called before srtp_init() inorder to capture + * any logging during start up. + * + * @param func is a pointer to a fuction of type srtp_log_handler_func_t. + * This function will be used by libSRTP to output log messages. + * @param data is a user pointer that will be returned as the data argument in + * func. + */ +srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, + void *data); + +/** + * @brief srtp_get_protect_trailer_length(session, use_mki, mki_index, length) + * + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length + * parameter + * + * returns err_status_ok on success, err_status_bad_mki if the MKI index is + * invalid + * + */ +srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length); + +/** + * @brief srtp_get_protect_rtcp_trailer_length(session, use_mki, mki_index, + * length) + * + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length + * parameter + * + * returns err_status_ok on success, err_status_bad_mki if the MKI index is + * invalid + * + */ +srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length); + +/** + * @brief srtp_set_stream_roc(session, ssrc, roc) + * + * Set the roll-over-counter on a session for a given SSRC + * + * returns err_status_ok on success, srtp_err_status_bad_param if there is no + * stream found + * + */ +srtp_err_status_t srtp_set_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t roc); + +/** + * @brief srtp_get_stream_roc(session, ssrc, roc) + * + * Get the roll-over-counter on a session for a given SSRC + * + * returns err_status_ok on success, srtp_err_status_bad_param if there is no + * stream found + * + */ +srtp_err_status_t srtp_get_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t *roc); + +/** + * @} + */ + +/* in host order, so outside the #if */ +#define SRTCP_E_BIT 0x80000000 + +/* for byte-access */ +#define SRTCP_E_BYTE_BIT 0x80 +#define SRTCP_INDEX_MASK 0x7fffffff + +#ifdef __cplusplus +} +#endif + +#endif /* SRTP_SRTP_H */ diff --git a/yangplayer2/main.cpp b/yangplayer2/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d9d3c2394e730efa83216ab2f01b3c000b5462cd --- /dev/null +++ b/yangplayer2/main.cpp @@ -0,0 +1,16 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + YangRecordThread videoThread; + + w.m_videoThread=&videoThread; + w.initVideoThread(&videoThread); + w.show(); + videoThread.start(); + return a.exec(); +} diff --git a/yangplayer2/mainwindow.cpp b/yangplayer2/mainwindow.cpp new file mode 100755 index 0000000000000000000000000000000000000000..602e3c19944af3610ba07f53b17dbdc990178bf9 --- /dev/null +++ b/yangplayer2/mainwindow.cpp @@ -0,0 +1,122 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include +#include +#include +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + m_centerWdiget=new QWidget(this); + m_vb=new QVBoxLayout(); + + setCentralWidget(m_centerWdiget); + m_centerWdiget->setLayout(m_vb); + m_vb->setMargin(0); + m_vb->setSpacing(0); + + //if using remote control + // m_videoWin=new YangMouseListenWidget(this); +#if Yang_Listen_MouseAndKeyboard + m_videoWin=new YangMouseListenWidget(this); +#else + m_videoWin=new YangPlayWidget(this); +#endif + + + m_hb1=new QHBoxLayout(); + m_hb2=new QHBoxLayout(); + m_hb1->addWidget(ui->m_l_url); + m_hb1->addWidget(ui->m_url); + m_hb1->addWidget(ui->m_b_play); + + m_hb2->addWidget(m_videoWin); + m_vb->addLayout(m_hb1); + m_vb->addLayout(m_hb2); + m_vb->setStretchFactor(m_hb1,1); + m_vb->setStretchFactor(m_hb2,10); + m_ini=new YangContext(); + m_ini->init(); + + m_ini->streams.m_playBuffer=new YangSynBuffer(); + m_ini->rtc.mixAvqueue=0; + m_player= YangPlayerHandle::createPlayerHandle(m_ini,this); + + + char s[128]={0}; + sprintf(s,"webrtc://%s:1985/live/livestream",yang_getLocalInfo().c_str()); + ui->m_url->setText(s); + localPort=16005; + + yang_setLogLevle(5); + yang_setLogFile(1); + m_isStartplay=false; + + connect(this,SIGNAL(RtcConnectFailure(int)),SLOT(connectFailure(int))); + + + +} + +MainWindow::~MainWindow() +{ + delete ui; + m_videoThread->m_syn=NULL; + yang_delete(m_videoWin); + yang_delete(m_player); + yang_closeLogFile(); + yang_delete(m_ini); + +} + + +void MainWindow::success(){ + +} +void MainWindow::failure(int32_t errcode){ + emit RtcConnectFailure(errcode); + + +} +void MainWindow::connectFailure(int errcode){ + QMessageBox::about(NULL, "Error", "play error("+QString::number(errcode)+")!"); + on_m_b_play_clicked(); +} +void MainWindow::initVideoThread(YangRecordThread *prt){ + m_videoThread=prt; + m_videoThread->m_video=m_videoWin; + m_videoThread->initPara(); + m_videoThread->m_syn= m_ini->streams.m_playBuffer; + +} + +void MainWindow::on_m_b_play_clicked() +{ + if(!m_isStartplay){ + m_videoThread->m_syn=m_ini->streams.m_playBuffer; + m_videoThread->m_syn->resetVideoClock(); + if(m_player&&m_player->play(ui->m_url->text().toStdString(),localPort)==Yang_Ok){ + ui->m_b_play->setText("stop"); + + m_isStartplay=!m_isStartplay; + m_videoThread->m_isRender=true; + }else{ + QMessageBox::about(NULL, "Error", "play url error!"); + m_videoThread->m_isRender=false; + } + + }else{ + m_videoThread->m_isRender=false; + ui->m_b_play->setText("play"); + + QThread::msleep(50); + if(m_player) m_player->stopPlay(); + + m_isStartplay=!m_isStartplay; + + } +} + + diff --git a/yangplayer2/mainwindow.h b/yangplayer2/mainwindow.h new file mode 100755 index 0000000000000000000000000000000000000000..03e4fa671da4164236bbc079354a085c2cfc1466 --- /dev/null +++ b/yangplayer2/mainwindow.h @@ -0,0 +1,62 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H +#include +#include +#include + +#include "video/yangrecordthread.h" +#include "yangplayer/YangPlayerHandle.h" +#include "yangstream/YangStreamType.h" +#include "yangplayer/YangPlayWidget.h" +#include +#include +#include "yangplayer_config.h" +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow,public YangSysMessageI +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + YangRecordThread *m_videoThread; + YangPlayerHandle *m_player; +#if Yang_Listen_MouseAndKeyboard + YangMouseListenWidget *m_videoWin; +#else + YangPlayWidget *m_videoWin; +#endif + YangStreamConfig m_conf; + void initVideoThread(YangRecordThread *prt); + + void success(); + void failure(int32_t errcode); + + signals: + void RtcConnectFailure(int errcode); +protected: + YangContext* m_ini; + +private slots: + void connectFailure(int errcode); + +void on_m_b_play_clicked(); + +private: + Ui::MainWindow *ui; + + //std::string serverIp,app,stream; + // std::string localServer; + int localPort; + QWidget *m_centerWdiget; + QVBoxLayout *m_vb; + QHBoxLayout *m_hb1; + QHBoxLayout *m_hb2; +private: + bool m_isStartplay; + +}; +#endif // MAINWINDOW_H diff --git a/yangplayer2/mainwindow.ui b/yangplayer2/mainwindow.ui new file mode 100755 index 0000000000000000000000000000000000000000..f3f2d2bdd87a18a57ad9723944fe7558c970c35e --- /dev/null +++ b/yangplayer2/mainwindow.ui @@ -0,0 +1,68 @@ + + + MainWindow + + + + 0 + 0 + 1101 + 689 + + + + MainWindow + + + + + + 20 + 20 + 80 + 21 + + + + URL: + + + + + + 130 + 10 + 521 + 29 + + + + + + + 680 + 10 + 106 + 41 + + + + Play + + + + + + + 0 + 0 + 1101 + 32 + + + + + + + + diff --git a/yangplayer2/video/yangrecordthread.cpp b/yangplayer2/video/yangrecordthread.cpp new file mode 100755 index 0000000000000000000000000000000000000000..dac7ddf023e39f3ca8698eae97dc25c1f40c0409 --- /dev/null +++ b/yangplayer2/video/yangrecordthread.cpp @@ -0,0 +1,83 @@ +#include "yangrecordthread.h" +#include +#include +#include +YangRecordThread::YangRecordThread() +{ + + m_isLoop=0; + m_video=nullptr; + m_syn=nullptr; + + + m_sid=1; + showType=1; + + m_isStart=0; + m_isRender=false; + m_playWidth=640; + m_playHeight=480; + m_playBuffer=new uint8_t[m_playWidth*m_playHeight*3/2]; + memset(m_playBuffer,0,m_playWidth*m_playHeight); + memset(m_playBuffer+m_playWidth*m_playHeight,128,(m_playWidth*m_playHeight)>>1); +} + +YangRecordThread::~YangRecordThread(){ + // m_ys=nullptr; + // m_vb=NULL; + m_video=nullptr; + m_syn=nullptr; + // m_vb=NULL; + + stopAll(); + yang_deleteA(m_playBuffer); +} +void YangRecordThread::stopAll(){ + if(m_isLoop){ + m_isLoop=0; + while (m_isStart) { + QThread::msleep(1); + } + } + closeAll(); +} +void YangRecordThread::initPara(){ + +} +void YangRecordThread::closeAll(){ + //clearRender(); +} + + +void YangRecordThread::setBlackBk(){ + +} +void YangRecordThread::render(){ + if(m_isRender&&m_syn){ + uint8_t* t_vb=m_syn->getVideoRef(&m_frame); + + if(t_vb&&m_video){ + m_video->playVideo(t_vb,m_syn->m_width,m_syn->m_height); + } + + t_vb=NULL; + }else{ + if(m_video) m_video->playVideo(m_playBuffer,m_playWidth,m_playHeight); + } +} + +void YangRecordThread::run(){ + // init(); + + m_isLoop=1; + m_isStart=1; + + + while(m_isLoop){ + + QThread::msleep(10); + render(); + } + m_isStart=0; + // closeAll(); +} diff --git a/yangplayer2/video/yangrecordthread.h b/yangplayer2/video/yangrecordthread.h new file mode 100755 index 0000000000000000000000000000000000000000..83f40d6771c8a03eb6a29969e20b35b2ceb3d585 --- /dev/null +++ b/yangplayer2/video/yangrecordthread.h @@ -0,0 +1,48 @@ +#ifndef YANGTHREAD1_H +#define YANGTHREAD1_H +#include +#include + +#include +#include +#include +#include +#include +class YangRecordThread : public QThread +{ +public: + YangRecordThread(); + virtual ~YangRecordThread(); + + int m_isLoop; + void initPara(); +#if Yang_Listen_MouseAndKeyboard + YangMouseListenWidget *m_video; +#else + YangPlayWidget *m_video; +#endif + + YangSynBuffer* m_syn; + bool m_isRender; + + int m_sid; + void stopAll(); + int showType; + + void setBlackBk(); + +private: + void render(); + void closeAll(); + + YangFrame m_frame; + int m_isStart; + int m_playWidth; + int m_playHeight; + uint8_t* m_playBuffer; + +private: + virtual void run(); +}; + +#endif // YANGTHREAD_H diff --git a/yangplayer2/yangplayer/YangMouseListenWidget.cpp b/yangplayer2/yangplayer/YangMouseListenWidget.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8affe6a1c73445f834ce8417ef6108909bce7df9 --- /dev/null +++ b/yangplayer2/yangplayer/YangMouseListenWidget.cpp @@ -0,0 +1,449 @@ +#include "YangMouseListenWidget.h" +#include +#include +#include + +YangMouseListenWidget::YangMouseListenWidget(QWidget *parent) : QOpenGLWidget(parent) +{ + textureUniformY = 0; + textureUniformU = 0; + textureUniformV = 0; + id_y = 0; + id_u = 0; + id_v = 0; + m_pBufYuv420p = NULL; + m_vshader = NULL; + m_fshader = NULL; + m_shaderProgram = NULL; + m_textureY = NULL; + m_textureU = NULL; + m_textureV = NULL; + + m_nVideoH = 0; + m_nVideoW = 0; + + initKeybord(); + grabKeyboard(); + +} + +YangMouseListenWidget::~YangMouseListenWidget() +{ + if(m_textureY){ + makeCurrent(); + m_textureY->destroy(); + m_textureU->destroy(); + m_textureV->destroy(); + doneCurrent(); + m_pBufYuv420p=nullptr; + m_vshader = NULL; + m_fshader = NULL; + m_textureY = NULL; + m_textureU = NULL; + m_textureV = NULL; + } + +} + +void YangMouseListenWidget::initKeybord() +{ + m_keyboardMap[Qt::Key_Left]=0x25; + m_keyboardMap[Qt::Key_Up]=0x26; + m_keyboardMap[Qt::Key_Right]=0x27; + m_keyboardMap[Qt::Key_Down]=0x28; + m_keyboardMap[Qt::Key_Backspace]=0x08; + m_keyboardMap[Qt::Key_Tab]=0x09; + m_keyboardMap[Qt::Key_Clear]=0x0C; + m_keyboardMap[Qt::Key_Return]=0x0D; + m_keyboardMap[Qt::Key_Enter]=0x0D; + m_keyboardMap[Qt::Key_Shift]=0x10; + m_keyboardMap[Qt::Key_Control]=0x11; + m_keyboardMap[Qt::Key_Alt]=0x12; + m_keyboardMap[Qt::Key_Pause]=0x13; + m_keyboardMap[Qt::Key_CapsLock]=0x14; + m_keyboardMap[Qt::Key_Escape]=0x1B; + m_keyboardMap[Qt::Key_Space]=0x20; + m_keyboardMap[Qt::Key_PageUp]=0x21; + m_keyboardMap[Qt::Key_PageDown]=0x22; + m_keyboardMap[Qt::Key_End]=0x23; + m_keyboardMap[Qt::Key_Home]=0x24; + m_keyboardMap[Qt::Key_Select]=0x29; + m_keyboardMap[Qt::Key_Print]=0x2A; + m_keyboardMap[Qt::Key_Execute]=0x2B; + m_keyboardMap[Qt::Key_Printer]=0x2C; + m_keyboardMap[Qt::Key_Insert]=0x2D; + m_keyboardMap[Qt::Key_Delete]=0x2E; + m_keyboardMap[Qt::Key_Help]=0x2F; + m_keyboardMap[Qt::Key_0]=0x30; + m_keyboardMap[Qt::Key_ParenRight]=0x30; // ) + m_keyboardMap[Qt::Key_1]=0x31; + m_keyboardMap[Qt::Key_Exclam]=0x31; // ! + m_keyboardMap[Qt::Key_2]=0x32; + m_keyboardMap[Qt::Key_At]=0x32; // @ + m_keyboardMap[Qt::Key_3]=0x33; + m_keyboardMap[Qt::Key_NumberSign]=0x33; // # + m_keyboardMap[Qt::Key_4]=0x34; + m_keyboardMap[Qt::Key_Dollar]=0x34; // $ + m_keyboardMap[Qt::Key_5]=0x35; + m_keyboardMap[Qt::Key_Percent]=0x35; // % + m_keyboardMap[Qt::Key_6]=0x36; + m_keyboardMap[Qt::Key_AsciiCircum]=0x36; // ^ + m_keyboardMap[Qt::Key_7]=0x37; + m_keyboardMap[Qt::Key_Ampersand]=0x37; // & + m_keyboardMap[Qt::Key_8]=0x38; + m_keyboardMap[Qt::Key_Asterisk]=0x38; // * + m_keyboardMap[Qt::Key_9]=0x39; + m_keyboardMap[Qt::Key_ParenLeft]=0x39; // ( + m_keyboardMap[Qt::Key_A]=0x41; + m_keyboardMap[Qt::Key_B]=0x42; + m_keyboardMap[Qt::Key_C]=0x43; + m_keyboardMap[Qt::Key_D]=0x44; + m_keyboardMap[Qt::Key_E]=0x45; + m_keyboardMap[Qt::Key_F]=0x46; + m_keyboardMap[Qt::Key_G]=0x47; + m_keyboardMap[Qt::Key_H]=0x48; + m_keyboardMap[Qt::Key_I]=0x49; + m_keyboardMap[Qt::Key_J]=0x4A; + m_keyboardMap[Qt::Key_K]=0x4B; + m_keyboardMap[Qt::Key_L]=0x4C; + m_keyboardMap[Qt::Key_M]=0x4D; + m_keyboardMap[Qt::Key_N]=0x4E; + m_keyboardMap[Qt::Key_O]=0x4F; + m_keyboardMap[Qt::Key_P]=0x50; + m_keyboardMap[Qt::Key_Q]=0x51; + m_keyboardMap[Qt::Key_R]=0x52; + m_keyboardMap[Qt::Key_S]=0x53; + m_keyboardMap[Qt::Key_T]=0x54; + m_keyboardMap[Qt::Key_U]=0x55; + m_keyboardMap[Qt::Key_V]=0x56; + m_keyboardMap[Qt::Key_W]=0x57; + m_keyboardMap[Qt::Key_X]=0x58; + m_keyboardMap[Qt::Key_Y]=0x59; + m_keyboardMap[Qt::Key_Z]=0x5A; + m_keyboardMap[Qt::Key_multiply]=0x6A; + m_keyboardMap[Qt::Key_F1]=0x70; + m_keyboardMap[Qt::Key_F2]=0x71; + m_keyboardMap[Qt::Key_F3]=0x72; + m_keyboardMap[Qt::Key_F4]=0x73; + m_keyboardMap[Qt::Key_F5]=0x74; + m_keyboardMap[Qt::Key_F6]=0x75; + m_keyboardMap[Qt::Key_F7]=0x76; + m_keyboardMap[Qt::Key_F8]=0x77; + m_keyboardMap[Qt::Key_F9]=0x78; + m_keyboardMap[Qt::Key_F10]=0x79; + m_keyboardMap[Qt::Key_F11]=0x7A; + m_keyboardMap[Qt::Key_F12]=0x7B; + m_keyboardMap[Qt::Key_F13]=0x7C; + m_keyboardMap[Qt::Key_F14]=0x7D; + m_keyboardMap[Qt::Key_F15]=0x7E; + m_keyboardMap[Qt::Key_F16]=0x7F; + m_keyboardMap[Qt::Key_F17]=0x80; + m_keyboardMap[Qt::Key_F18]=0x81; + m_keyboardMap[Qt::Key_F19]=0x82; + m_keyboardMap[Qt::Key_F20]=0x83; + m_keyboardMap[Qt::Key_F21]=0x84; + m_keyboardMap[Qt::Key_F22]=0x85; + m_keyboardMap[Qt::Key_F23]=0x86; + m_keyboardMap[Qt::Key_F24]=0x87; + m_keyboardMap[Qt::Key_NumLock]=0x90; + m_keyboardMap[Qt::Key_ScrollLock]=0x91; + m_keyboardMap[Qt::Key_VolumeDown]=0xAE; + m_keyboardMap[Qt::Key_VolumeUp]=0xAF; + m_keyboardMap[Qt::Key_VolumeMute]=0xAD; + m_keyboardMap[Qt::Key_MediaStop]=0xB2; + m_keyboardMap[Qt::Key_MediaPlay]=0xB3; + m_keyboardMap[Qt::Key_Plus]=0xBB; // + + m_keyboardMap[Qt::Key_Minus]=0xBD; // - + m_keyboardMap[Qt::Key_Underscore]=0xBD; // _ + m_keyboardMap[Qt::Key_Equal]=0xBB; // = + m_keyboardMap[Qt::Key_Semicolon]=0xBA; // ; + m_keyboardMap[Qt::Key_Colon]=0xBA; // : + m_keyboardMap[Qt::Key_Comma]=0xBC; // ]= + m_keyboardMap[Qt::Key_Less]=0xBC; // < + m_keyboardMap[Qt::Key_Period]=0xBE; // . + m_keyboardMap[Qt::Key_Greater]=0xBE; // > + m_keyboardMap[Qt::Key_Slash]=0xBF; // / + m_keyboardMap[Qt::Key_Question]=0xBF; // ? + m_keyboardMap[Qt::Key_BracketLeft]=0xDB; // [ + m_keyboardMap[Qt::Key_BraceLeft]=0xDB; // { + m_keyboardMap[Qt::Key_BracketRight]=0xDD; // ] + m_keyboardMap[Qt::Key_BraceRight]=0xDD; // } + m_keyboardMap[Qt::Key_Bar]=0xDC; // | + m_keyboardMap[Qt::Key_Backslash]=0xDC; + m_keyboardMap[Qt::Key_Apostrophe]=0xDE; // ' + m_keyboardMap[Qt::Key_QuoteDbl]=0xDE; // " + m_keyboardMap[Qt::Key_QuoteLeft]=0xC0; // ` + m_keyboardMap[Qt::Key_AsciiTilde]=0xC0; // ~ +} +void YangMouseListenWidget::sendevent(string type, string direction, int x, int y) +{ + char msg[256]={0}; + if(direction == "key") + { + sprintf(msg,"%s,%s,%d,%d",type.c_str(),direction.c_str(),x,y); + qDebug()<<"msg==="<sendmsg(msg,strlen(msg)); + return; + } + + float width = rect().width(); + float height = rect().height(); + + float fx = x/width; + float fy = y/height; + sprintf(msg,"%s,%s,%f,%f",type.c_str(),direction.c_str(),fx,fy); + qDebug()<<"msg==="<sendmsg(msg,strlen(msg)); + +} +void YangMouseListenWidget::playVideo(unsigned char *p,int wid,int hei) +{ + + + if(m_nVideoW != wid) + { + m_nVideoW = wid; + m_nVideoH = hei; + } + m_pBufYuv420p=p; + update(); + // m_pBufYuv420p=NULL; + return; +} + +void YangMouseListenWidget::initializeGL() +{ + initializeOpenGLFunctions(); + glEnable(GL_DEPTH_TEST); + m_vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); + + const char *vsrc = "attribute vec4 vertexIn; \ + attribute vec2 textureIn; \ + varying vec2 textureOut; \ + void main(void) \ + { \ + gl_Position = vertexIn; \ + textureOut = textureIn; \ + }"; + + bool bCompile = m_vshader->compileSourceCode(vsrc); + if(!bCompile) + { + } + + m_fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); + const char *fsrc = "varying vec2 textureOut; \ + uniform sampler2D tex_y; \ + uniform sampler2D tex_u; \ + uniform sampler2D tex_v; \ + void main(void) \ + { \ + vec3 yuv; \ + vec3 rgb; \ + yuv.x = texture2D(tex_y, textureOut).r; \ + yuv.y = texture2D(tex_u, textureOut).r - 0.5; \ + yuv.z = texture2D(tex_v, textureOut).r - 0.5; \ + rgb = mat3( 1, 1, 1, \ + 0, -0.34414, 1.772, \ + 1.402, -0.71414, 0) * yuv; \ + gl_FragColor = vec4(rgb, 1); \ + }"; + //将glsl源码送入编译器编译着色器程序 + bCompile = m_fshader->compileSourceCode(fsrc); + if(!bCompile) + { + } +#define PROGRAM_VERTEX_ATTRIBUTE 0 +#define PROGRAM_TEXCOORD_ATTRIBUTE 1 + + m_shaderProgram = new QOpenGLShaderProgram; + m_shaderProgram->addShader(m_fshader); + m_shaderProgram->addShader(m_vshader); + m_shaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX); + m_shaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE); + m_shaderProgram->link(); + m_shaderProgram->bind(); + + textureUniformY = m_shaderProgram->uniformLocation("tex_y"); + textureUniformU = m_shaderProgram->uniformLocation("tex_u"); + textureUniformV = m_shaderProgram->uniformLocation("tex_v"); + + static const GLfloat vertexVertices[] = { + -1.0f, -1.0f, + 1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + }; + + static const GLfloat textureVertices[] = { + 0.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + }; + + glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices); + glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices); + + glEnableVertexAttribArray(ATTRIB_VERTEX); + glEnableVertexAttribArray(ATTRIB_TEXTURE); + + m_textureY = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureU = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureV = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureY->create(); + m_textureU->create(); + m_textureV->create(); + + id_y = m_textureY->textureId(); + id_u = m_textureU->textureId(); + id_v = m_textureV->textureId(); + glClearColor(0.3,0.3,0.3,0.0);//设置背景色 + +} + +void YangMouseListenWidget::resizeGL(int w, int h) +{ + if(h == 0)// 防止被零除 + { + h = 1;// 将高设为1 + } + + glViewport(0,0, w,h); +} + +void YangMouseListenWidget::paintGL() +{ + //if(m_pBufYuv420p==NULL) return; + glActiveTexture(GL_TEXTURE0); + + glBindTexture(GL_TEXTURE_2D, id_y); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW, m_nVideoH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, id_u); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p+m_nVideoW*m_nVideoH); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, id_v); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p+m_nVideoW*m_nVideoH*5/4); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glUniform1i(textureUniformY, 0); + glUniform1i(textureUniformU, 1); + glUniform1i(textureUniformV, 2); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + return; + } + +void YangMouseListenWidget::mousePressEvent(QMouseEvent *event) +{ + string direction = ""; + if(event->button()==Qt::LeftButton) + { + direction = "left"; + } + else if(event->button()==Qt::RightButton) + { + direction = "right"; + } + + QPoint pt = event->pos(); + int x= pt. x(); + int y = pt.y(); + + sendevent("mousePress",direction,x,y); + +} + +void YangMouseListenWidget::mouseDoubleClickEvent(QMouseEvent *event) +{ + string direction = ""; + + if(event->button()==Qt::LeftButton) + { + direction = "left"; + } + else if(event->button()==Qt::RightButton) + { + direction = "right"; + } + + QPoint pt = event->pos(); + int x= pt. x(); + int y = pt.y(); + sendevent("mouseDouble",direction,x,y); +} + +void YangMouseListenWidget::mouseReleaseEvent(QMouseEvent *event) +{ + string direction = ""; + if(event->button()==Qt::LeftButton) + { + direction = "left"; + } + else if(event->button()==Qt::RightButton) + { + direction = "right"; + } + QPoint pt = event->pos(); + int x= pt. x(); + int y = pt.y(); + + sendevent("mouseRelease",direction,x,y); +} + +void YangMouseListenWidget::mouseMoveEvent(QMouseEvent *event) +{ + string direction = ""; + if(event->button()==Qt::LeftButton) + { + direction = "left"; + } + else if(event->button()==Qt::RightButton) + { + direction = "right"; + } + QPoint pt = event->pos(); + int x= pt. x(); + int y = pt.y(); + + sendevent("mouseMove",direction,x,y); +} +void YangMouseListenWidget::wheelEvent(QWheelEvent *event){ + QPoint pt = event->pos(); + int x= pt.x(); + int y = pt.y(); + if (event->orientation() == Qt::Vertical) sendevent("wheel",to_string(event->delta()),x,y); + + +} +void YangMouseListenWidget::keyPressEvent(QKeyEvent *event) +{ + + qDebug()<<"keyPressEvent==="<key(); + map::iterator it=m_keyboardMap.find( event->key()); + if(it!=m_keyboardMap.end()){ + sendevent("keyPressEvent","key",0,it->second); + } +} + +void YangMouseListenWidget::keyReleaseEvent(QKeyEvent *event) +{ + qDebug()<<"keyReleaseEvent==="<key(); + map::iterator it=m_keyboardMap.find( event->key()); + if(it!=m_keyboardMap.end()){ + sendevent("keyReleaseEvent","key",0,it->second); + } +} diff --git a/yangplayer2/yangplayer/YangMouseListenWidget.h b/yangplayer2/yangplayer/YangMouseListenWidget.h new file mode 100755 index 0000000000000000000000000000000000000000..329e0bd32792e26aa6edc74aad45b6ec0fe4144c --- /dev/null +++ b/yangplayer2/yangplayer/YangMouseListenWidget.h @@ -0,0 +1,60 @@ +#ifndef YangMouseListenWidget_H +#define YangMouseListenWidget_H + +#include +#include +#include +#include +#include "yangplayer/YangWinPlayFactroy.h" + + +#define ATTRIB_VERTEX 3 +#define ATTRIB_TEXTURE 4 + +class YangMouseListenWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT +public: + YangMouseListenWidget(QWidget* parent); + virtual ~YangMouseListenWidget(); + void playVideo(unsigned char *p,int wid,int hei); + + +protected: + void initializeGL() Q_DECL_OVERRIDE; + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) override ; + void mouseDoubleClickEvent(QMouseEvent *event) override ; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void wheelEvent(QWheelEvent *event) override; + + +private: + GLuint textureUniformY; + GLuint textureUniformU; + GLuint textureUniformV; + GLuint id_y; + GLuint id_u; + GLuint id_v; + QOpenGLTexture* m_textureY; + QOpenGLTexture* m_textureU; + QOpenGLTexture* m_textureV; + QOpenGLShader *m_vshader; + QOpenGLShader *m_fshader; + QOpenGLShaderProgram *m_shaderProgram; + int m_nVideoW; + int m_nVideoH; + unsigned char* m_pBufYuv420p; + + map m_keyboardMap;// + + void initKeybord(); + void sendevent(string type, string direction, int x, int y); + +}; + +#endif // CPLAYWIDGET_H diff --git a/yangplayer2/yangplayer/YangPlayWidget.cpp b/yangplayer2/yangplayer/YangPlayWidget.cpp new file mode 100755 index 0000000000000000000000000000000000000000..156afd9ec9beb6d27ffee5d6e820bacae6eb3607 --- /dev/null +++ b/yangplayer2/yangplayer/YangPlayWidget.cpp @@ -0,0 +1,201 @@ +#include "YangPlayWidget.h" +#include +#include + + +YangPlayWidget::YangPlayWidget(QWidget *parent) : QOpenGLWidget(parent) +{ + textureUniformY = 0; + textureUniformU = 0; + textureUniformV = 0; + id_y = 0; + id_u = 0; + id_v = 0; + m_pBufYuv420p = NULL; + m_vshader = NULL; + m_fshader = NULL; + m_shaderProgram = NULL; + m_textureY = NULL; + m_textureU = NULL; + m_textureV = NULL; + + m_nVideoH = 0; + m_nVideoW = 0; + // QPalette pal(palette()); + // pal.setColor(QPalette::Background, Qt::black); + // setAutoFillBackground(true); + // setPalette(pal); + +} + +YangPlayWidget::~YangPlayWidget() +{ + if(m_textureY){ + makeCurrent(); + m_textureY->destroy(); + m_textureU->destroy(); + m_textureV->destroy(); + doneCurrent(); + m_pBufYuv420p=nullptr; + m_vshader = NULL; + m_fshader = NULL; + m_textureY = NULL; + m_textureU = NULL; + m_textureV = NULL; + } +} + + + +void YangPlayWidget::playVideo(unsigned char *p,int wid,int hei) +{ + + + if(m_nVideoW != wid) + { + m_nVideoW = wid; + m_nVideoH = hei; + } + m_pBufYuv420p=p; + update(); + // m_pBufYuv420p=NULL; + return; +} + +void YangPlayWidget::initializeGL() +{ + initializeOpenGLFunctions(); + glEnable(GL_DEPTH_TEST); + m_vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); + + const char *vsrc = "attribute vec4 vertexIn; \ + attribute vec2 textureIn; \ + varying vec2 textureOut; \ + void main(void) \ + { \ + gl_Position = vertexIn; \ + textureOut = textureIn; \ + }"; + + bool bCompile = m_vshader->compileSourceCode(vsrc); + if(!bCompile) + { + } + + m_fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); + const char *fsrc = "varying vec2 textureOut; \ + uniform sampler2D tex_y; \ + uniform sampler2D tex_u; \ + uniform sampler2D tex_v; \ + void main(void) \ + { \ + vec3 yuv; \ + vec3 rgb; \ + yuv.x = texture2D(tex_y, textureOut).r; \ + yuv.y = texture2D(tex_u, textureOut).r - 0.5; \ + yuv.z = texture2D(tex_v, textureOut).r - 0.5; \ + rgb = mat3( 1, 1, 1, \ + 0, -0.34414, 1.772, \ + 1.402, -0.71414, 0) * yuv; \ + gl_FragColor = vec4(rgb, 1); \ + }"; + //将glsl源码送入编译器编译着色器程序 + bCompile = m_fshader->compileSourceCode(fsrc); + if(!bCompile) + { + } +#define PROGRAM_VERTEX_ATTRIBUTE 0 +#define PROGRAM_TEXCOORD_ATTRIBUTE 1 + + m_shaderProgram = new QOpenGLShaderProgram; + m_shaderProgram->addShader(m_fshader); + m_shaderProgram->addShader(m_vshader); + m_shaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX); + m_shaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE); + m_shaderProgram->link(); + m_shaderProgram->bind(); + + textureUniformY = m_shaderProgram->uniformLocation("tex_y"); + textureUniformU = m_shaderProgram->uniformLocation("tex_u"); + textureUniformV = m_shaderProgram->uniformLocation("tex_v"); + + static const GLfloat vertexVertices[] = { + -1.0f, -1.0f, + 1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + }; + + static const GLfloat textureVertices[] = { + 0.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + }; + + glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices); + glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices); + + glEnableVertexAttribArray(ATTRIB_VERTEX); + glEnableVertexAttribArray(ATTRIB_TEXTURE); + + m_textureY = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureU = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureV = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_textureY->create(); + m_textureU->create(); + m_textureV->create(); + + id_y = m_textureY->textureId(); + id_u = m_textureU->textureId(); + id_v = m_textureV->textureId(); + // glClearColor(0,0,0,0.0); + glClearColor(0.3,0.3,0.3,0.0);//设置背景色 + +} + +void YangPlayWidget::resizeGL(int w, int h) +{ + if(h == 0)// 防止被零除 + { + h = 1;// 将高设为1 + } + + glViewport(0,0, w,h); +} + +void YangPlayWidget::paintGL() +{ + //if(m_pBufYuv420p==NULL) return; + glActiveTexture(GL_TEXTURE0); + + glBindTexture(GL_TEXTURE_2D, id_y); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW, m_nVideoH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, id_u); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p+m_nVideoW*m_nVideoH); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, id_v); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv420p+m_nVideoW*m_nVideoH*5/4); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glUniform1i(textureUniformY, 0); + glUniform1i(textureUniformU, 1); + glUniform1i(textureUniformV, 2); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + return; + } + diff --git a/yangplayer2/yangplayer/YangPlayWidget.h b/yangplayer2/yangplayer/YangPlayWidget.h new file mode 100755 index 0000000000000000000000000000000000000000..7a52beee239650c3c7a8d25007540b8285642e1a --- /dev/null +++ b/yangplayer2/yangplayer/YangPlayWidget.h @@ -0,0 +1,43 @@ +#ifndef YangPlayWidget_H +#define YangPlayWidget_H + +#include +#include +#include +#include +#include "yangplayer/YangWinPlayFactroy.h" + +#define ATTRIB_VERTEX 3 +#define ATTRIB_TEXTURE 4 + +class YangPlayWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT +public: + YangPlayWidget(QWidget* parent); + virtual ~YangPlayWidget(); + void playVideo(unsigned char *p,int wid,int hei); +protected: + void initializeGL() Q_DECL_OVERRIDE; + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; +private: + GLuint textureUniformY; + GLuint textureUniformU; + GLuint textureUniformV; + GLuint id_y; + GLuint id_u; + GLuint id_v; + QOpenGLTexture* m_textureY; + QOpenGLTexture* m_textureU; + QOpenGLTexture* m_textureV; + QOpenGLShader *m_vshader; + QOpenGLShader *m_fshader; + QOpenGLShaderProgram *m_shaderProgram; + int m_nVideoW; + int m_nVideoH; + unsigned char* m_pBufYuv420p; + +}; + +#endif // CPLAYWIDGET_H diff --git a/yangplayer2/yangplayer2.pro b/yangplayer2/yangplayer2.pro new file mode 100755 index 0000000000000000000000000000000000000000..f32ab79791184c2df2a739e712e0238207af059a --- /dev/null +++ b/yangplayer2/yangplayer2.pro @@ -0,0 +1,81 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS +#DEFINES += QT_WIN_MSC +HOME_BASE=../ +unix{ + + INCLUDEPATH += $$HOME_BASE/include + CONFIG(debug, debug|release) { + LIBS += -L$$HOME_BASE/bin/lib_debug + DESTDIR += $$HOME_BASE/bin/app_debug + }else{ + LIBS += -L$$HOME_BASE/bin/lib_release + DESTDIR += $$HOME_BASE/bin/app_release + } + LIBS += -L$$HOME_BASE/thirdparty/lib + LIBS += -lyangrtc2 -lavutil -lavcodec -lpthread -lasound -ldl -lssl2 -lcrypto2 -lsrtp2 +} +win32{ + DEFINES += __WIN32__ + DEFINES +=_AMD64_ + + INCLUDEPATH += $$HOME_BASE\include + CONFIG(debug, debug|release) { + LIBS += -L$$HOME_BASE/bin/lib_win_debug + DESTDIR += $$HOME_BASE/bin/app_win_debug + }else{ + LIBS += -L$$HOME_BASE/bin/lib_win_release + DESTDIR += $$HOME_BASE/bin/app_win_release + } + LIBS += -lyangrtc2 -lwinmm -ldmoguids -lole32 -lStrmiids -lsrtp2 + YANG_LIB= -L$$HOME_BASE/thirdparty/lib/win -lssl -lcrypto + msvc{ + QMAKE_CFLAGS += /utf-8 + QMAKE_CXXFLAGS += /utf-8 + QMAKE_LFLAGS += /ignore:4099 + DEFINES +=HAVE_STRUCT_TIMESPEC + DEFINES +=WIN32_LEAN_AND_MEAN + INCLUDEPATH += $$HOME_BASE\thirdparty\include\win\include #vc + + YANG_LIB= -L$$HOME_BASE/thirdparty/lib/win/msvc -lavutil -lavcodec -lavrt -lpthreadVC2 -luser32 -lAdvapi32 -llibcrypto -llibssl + } + LIBS += $$YANG_LIB + LIBS += -lCrypt32 -lws2_32 +} +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + video/yangrecordthread.cpp \ + yangplayer/YangMouseListenWidget.cpp \ + yangplayer/YangPlayWidget.cpp + + +HEADERS += \ + mainwindow.h \ + video/yangrecordthread.h \ + yangplayer/YangMouseListenWidget.h \ + yangplayer/YangPlayWidget.h \ + yangplayer_config.h + + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/yangplayer2/yangplayer_config.h b/yangplayer2/yangplayer_config.h new file mode 100755 index 0000000000000000000000000000000000000000..0b52666eb824f33f5b2c477c8db4bbb5aba7a616 --- /dev/null +++ b/yangplayer2/yangplayer_config.h @@ -0,0 +1,5 @@ +#ifndef YANGPLAYER_COMMON_H +#define YANGPLAYER_COMMON_H +#define Yang_Listen_MouseAndKeyboard 0 + +#endif // YANGPLAYER_COMMON_H diff --git a/yangpushstream2/main.cpp b/yangpushstream2/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..565643e63ccae74175ec2f4ded34df86afe0c22c --- /dev/null +++ b/yangpushstream2/main.cpp @@ -0,0 +1,54 @@ +#include "recordmainwindow.h" +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +#pragma execution_character_set("utf-8") +#endif +#include +#include +#include