/*
 * LibMediaRecorder.h
 *
 *  Created on: 2016年1月13日
 *      Author: terry
 */

#ifndef LIBMEDIARECORDER_H_
#define LIBMEDIARECORDER_H_


////////////////////////////////////////////////////////////////////////////

#ifdef WIN32

    #ifndef NOMINMAX
    #define NOMINMAX
    #endif //NOMINMAX

	#include <Windows.h>
#else

#endif //WIN32

////////////////////////////////////////////////////////////////////////////
#include <errno.h>


////////////////////////////////////////////////////////////////////////////

#ifdef _MSC_VER
    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        uint32_t;
    typedef long long       int64_t;
    typedef unsigned long long   uint64_t;
#else
    #include <stdint.h>
#endif //_MSC_VER


///////////////////////////////////////////////////////////////////
#ifdef WIN32
    #ifndef DLLEXPORT
    #define DLLEXPORT __declspec(dllexport)
    #endif //DLLEXPORT
#else
    #define DLLEXPORT
#endif //WIN32

///////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C"
{
#endif

/////////////////////////////////////////////////////////////////////////////

/// 设备信息
struct MRDeviceInfo
{
    int idx;	/// 设备序号, 从0开始
    char name[MAX_PATH]; /// 设备名称
};

/// 编码器信息
struct MREncoderInfo
{
	int cid;	/// 编码器ID
	char name[MAX_PATH];	/// 编码器名称
};

/// 帧类型
enum MRFrameType
{
    MRFRAME_TYPE_VIDEO = 0,	/// 视频
	MRFRAME_TYPE_AUDIO,		/// 音频
};

/// 状态
enum MRState
{
	MRSTATE_STOPPED = 0,
	MRSTATE_PAUSED,
	MRSTATE_STARTED,

};

/// 常量
enum MRConst
{
	MR_MAX_PLANE = 8,	    /// 最大平面数|通道数
    MR_MAX_DEVICE = 32,
    MR_MAX_ENCODER = 16,
    MR_RTSP_PORT = 554,      /// 默认RTSP端口

    MR_DEVICE_SCREEN = 128,
    MR_DEVICE_MIXER = 129,		/// 混音器序号

	MR_H264_BASELINE = 66,
	MR_H264_MAIN = 77,
	MR_H264_HIGH = 100,

};


/// 音视频帧
struct MRFrame
{
	int type;	///@see MRFrameType, 用于区分音频/视频
	int fmt;	/// 帧格式

	unsigned char* data[MR_MAX_PLANE];	/// 媒体数据, 对于视频, 每个元素指向一个平面;对于音频, 元素指向通道
	int linesize[MR_MAX_PLANE];		/// 第几个平面|通道的字节数

	int64_t pts;	/// 时间戳
	int flags;		/// 标记

	/// for video only
	int width;		/// 视频高
	int height;		/// 视频宽

	/// for audio only
	int channels;	/// 音频通道
	int sampleRate;	/// 采样率
	int sampleBits;	/// 采用位数, 取值为8或者16

};


typedef 	int		MR_HANDLE;


/**
 * 帧回调
 * @param handle	采集器句柄
 * @param frame		帧
 * @param user		环境指针
 */
typedef void (*MRFrameCallback)(MR_HANDLE handle, MRFrame* frame, void* user);


///////////////////////////////////////////////////////////////////

/*
 * 如果没有特殊说明, int 返回0表示成功, 其他值表示错误码, 即 errno.h 中定义的值
 */


/**
 * 获取版本,无需调用MR_Init即可获取库的版本
 * @return
 */
DLLEXPORT const char* MR_GetVersion();

/**
 * 初始化
 * 在任何API之前调用. 应用程序应在程序启动阶段调用.
 * 只需调用一次
 * @return 0 表示成功
 */
DLLEXPORT int MR_Init();

/**
 * 反初始化
 * 不再调用任何API后调用. 应用程序在程序结束阶段调用
 */
DLLEXPORT void MR_Quit();


/**
 * 枚举视频设备
 * @param devs	设备信息数组
 * @param size	数组长度, 成功时返回设备个数
 * @return 0 表示成功
 */
DLLEXPORT int MR_GetCameraDeviceList(MRDeviceInfo* devs, int* size);

/**
 * 枚举音频设备
 * @param devs	设备信息数组
 * @param size	数组长度, 成功时返回设备个数
 * @return 0 表示成功
 */
DLLEXPORT int MR_GetSoundDeviceList(MRDeviceInfo* devs, int* size);

/**
 * 枚举视频编码器
 * @param encoders	编码器信息数组
 * @param size	编数组长度
 * @return
 */
DLLEXPORT int MR_GetVideoEncoderList(MREncoderInfo* encoders, int* size);

/**
 * 枚举音频编码器
 * @param encoders
 * @param size
 * @return
 */
DLLEXPORT int MR_GetSoundEncoderList(MREncoderInfo* encoders, int* size);


/**
 * 启动RTSP媒体服务器.
 * 和 MR_StopMediaServer 匹配调用. 可以多次启停媒体服务器
 * 在 MR_Init之后调用它启动媒体服务器.
 * 该API和 MR_StopMediaServer一起控制媒体服务器的启停时间和端口设置
 * @param port	RTSP端口
 * @return
 */
DLLEXPORT int MR_StartMediaServer(int port);

/**
 * 停止媒体服务器
 * @return
 */
DLLEXPORT int MR_StopMediaServer();


/**
 * 打开采集器
 * 用  MR_CloseRecorder 关闭采集器
 * @param cameraIdx	视频设备序号, -1 表示没有
 * @param soundIdx	音频设备序号, -1 表示没有
 * @return 采集器句柄, NULL表示失败
 */
DLLEXPORT MR_HANDLE MR_OpenRecorder(int cameraIdx, int soundIdx);

/**
 * 关闭采集器
 * @param handle	采集器句柄
 */
DLLEXPORT void MR_CloseRecorder(MR_HANDLE handle);


/**
 * 获取采集输出分辨率
 * @param handle	采集器句柄
 * @param width		宽
 * @param height	高
 * @return	0 表示成功
 */
DLLEXPORT int MR_GetResolution(MR_HANDLE handle, int* width, int* height);


/**
 * 设置采集输出分辨率
 * 典型分辨率有 640* 480, 352*288, 320*240, 176*144, 160*120
 * 较高的分辨率有 720*576, 704*576, 1080 * 720, 1024 * 768, 1600 * 1200, 1920 * 1080
 * 分辨率依赖于实际的设备, 大部分摄像头均支持 640*480及其以下的. 默认值为640*480
 * @param handle
 * @param width		宽, 必须是8的倍数
 * @param height	高, 必须是8的倍数
 * @return
 */
DLLEXPORT int MR_SetResolution(MR_HANDLE handle, int width, int height);

/**
 * 获取当前视频设备的帧率
 * @param handle	采集器句柄
 * @param fps		帧率, 单位为帧每秒
 * @return
 */
DLLEXPORT int MR_GetFrameRate(MR_HANDLE handle, int* fps);

/**
 * 设置当前视频设备的帧率
 * 通常取值有: 30, 25, 20, 15, 10, 5
 * 默认值一般是30, 由设备决定
 * @param handle
 * @param fps 帧率, 取值范围[1,30]
 * @return
 */
DLLEXPORT int MR_SetFrameRate(MR_HANDLE handle, int fps);

/**
 * 获取音频输出参数
 * @param handle	采集器句柄
 * @param channels	通道数
 * @param sampleRate 采样率
 * @param sampleBits 采样位, 取值8或者16
 * @return
 */
DLLEXPORT int MR_GetAudioProfile(MR_HANDLE handle, int* channels, int* sampleRate, int* sampleBits);

/**
 * 设置音频输出参数
 * @param handle	采集器句柄
 * @param channels	通道数, 取值范围为[1,2]
 * @param sampleRate 采样率, 取值有 44100, 32000, 16000, 8000, 默认取值44.1K
 * @param sampleBits 采样位, 取值8或者16
 * @return
 */
DLLEXPORT int MR_SetAudioProfile(MR_HANDLE handle, int channels, int sampleRate, int sampleBits);


/**
 * 设置视频编码器
 * 默认编码为H.264编码
 * @param handle	采集器句柄
 * @param codec		编码器ID
 * @return
 */
DLLEXPORT int MR_SetVideoEncoder(MR_HANDLE handle, int codec);

/**
 * 设置音频编码器
 * 默认编码为AAC编码
 * @param handle
 * @param codec		编码器ID
 * @return
 */
DLLEXPORT int MR_SetAudioEncoder(MR_HANDLE handle, int codec);

/**
 * 获取视频编码位率
 * @param handle
 * @param bitrate
 * @return
 */
DLLEXPORT int MR_GetVideoBitrate(MR_HANDLE handle, int* bitrate);

/**
 * 设置视频编码码率
 * 码率影响编码后的画质, 一般越大画质就越好
 * 码率与分辨率和帧率有关, 一般情况下, 30fps 640*480 的码率设为 640K bps
 * @param handle
 * @param bitrate
 * @return
 */
DLLEXPORT int MR_SetVideoBitrate(MR_HANDLE handle, int bitrate);

/**
 * 设置采集输出文件
 * 在采集器运行过程中调用该API, 会切分文件. 切分的操作不是即时的, 得等到下一个关键帧
 * @param handle	采集器
 * @param filepath	文件路径, 如果不是绝对路径,就在当前路径下生成
 * @return
 */
DLLEXPORT int MR_SetOutputFile(MR_HANDLE handle, const char* filepath);


/**
 * 启动采集器
 * @param handle
 * @return
 */
DLLEXPORT int MR_Start(MR_HANDLE handle);

/**
 * 暂停采集器
 * @param handle
 * @return
 */
DLLEXPORT int MR_Pause(MR_HANDLE handle);

/**
 * 停止采集器
 * @param handle
 * @return
 */
DLLEXPORT int MR_Stop(MR_HANDLE handle);


/**
 * 获取采集器状态,
 * @param handle
 * @param state 采集器状态,@see MRState
 * @return
 */
DLLEXPORT int MR_GetState(MR_HANDLE handle, int* state);

/**
 * 设置采集回调, 该回调既可以处理视频帧也可以处理音频帧, 通过帧类型来区分
 * 回调函数设为NULL, 表示取消回调
 * @param handle	采集器句柄
 * @param cb	回调函数
 * @param user	环境指针
 * @return
 */
DLLEXPORT int MR_SetFrameCallback(MR_HANDLE handle, MRFrameCallback* cb, void* user);


/**
 * 开始发布
 * 该采集器发布的媒体URL为: rtsp://{ip}:{port}/{name}
 * 如果 MR_StartMediaServer 没有调用, 发布失败
 * @param handle
 * @param name	发布点名称, 用于生产媒体URL
 * @return
 */
DLLEXPORT int MR_StartPublish(MR_HANDLE handle, const char* name);

/**
 * 停止发布
 * 停止采集器也会停止对应的发布.
 * @param handle
 * @return
 */
DLLEXPORT int MR_StopPublish(MR_HANDLE handle);


/**
 * 打开屏幕录像机
 * @param rc	屏幕矩形, NULL表示整个屏幕
 * @param soundIdx	音频源序号, -1 表示没有音频, MR_DEVICE_MIXER 表示混音器
 * @return 录像机句柄
 */
DLLEXPORT MR_HANDLE MR_OpenScreenRecorder(const RECT* rc, int soundIdx);


/**
 * 根据设备名称打开录像机
 * @param videoDevInfo
 * @param audioDevInfo
 * @return
 */
DLLEXPORT MR_HANDLE MR_OpenRecorder2(const MRDeviceInfo* videoDevInfo, const MRDeviceInfo* audioDevInfo);


/**
 * 设置视频编码器的档次
 * @param handle
 * @param profile	档次, 取值为[66,77,100]
 * @return
 */
DLLEXPORT int MR_SetVideoCodecProfile(MR_HANDLE handle, int profile);


/////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
}
#endif




#endif /* LIBMEDIARECORDER_H_ */
