//libavformat.h
#ifndef __LIBAVFORMAT_H__
#define __LIBAVFORMAT_H__
#ifdef __cplusplus
extern "C" {
#endif
	
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
	
#ifdef LINUX
#include <unistd.h>
#include <inttypes.h>
#include <sys/types.h>
#endif//LINUX

#include "MRComm.h"

typedef void *MRAVHANDLE;

/***************************************************** 格式打包 ********************************************************/
/* libav_format_type
 * 获得格式类型
	phandle : 打包句柄
 * 返回打包类型(MR_PACKTYPE_TYPE), 其他为错误代码
*/
int libav_format_type(MRAVHANDLE phandle);

/* libav_format_extname
 * 获得格式类型描述
	phandle : 打包句柄
 * 返回格式描述
*/
const char* libav_format_extname(MRAVHANDLE phandle);

/* libav_format_stream_curpts
 * 获得当前时间戳
	phandle : 打包句柄
	index   : 流索引, (0 - 流总数-1)
 * 返回时间戳
*/
unsigned int libav_format_stream_curpts(MRAVHANDLE phandle, int index);

/* libav_format_streams
 * 获得流总数
	phandle : 打包句柄
 * 返回流总数
*/
int libav_format_streams(MRAVHANDLE phandle);

/* libav_format_videochs
 * 获得视频通道总数
	phandle : 打包句柄
 * 返回视频通道总数
*/
int libav_format_videochs(MRAVHANDLE phandle);

/* libav_format_stream
 * 按索性获得流信息
	phandle : 打包句柄
	index   : 流索引, (0 - 流总数-1)
	pStream : 返回流信息指针
 * 返回0成功，其他为错误值
*/
int libav_format_stream(MRAVHANDLE phandle, int nIndex, MRAVSTREAM_T *pStream);

/* libav_format_stream_byid
 * 按id获得流信息
	phandle : 打包句柄
	id      : 流id
	pStream : 返回流信息指针
 * 返回0成功，其他为错误值
*/
int libav_format_stream_byid(MRAVHANDLE phandle, int id, MRAVSTREAM_T *pStream);

/* libav_format_setidx_dir
 * 设置索引打包索引目录
	phandle  : 打包句柄
	szInxDir : 目录
 * 返回0成功，其他为错误值
*/
int libav_format_setidx_dir(MRAVHANDLE phandle, const char *szInxDir);

/* libav_output_typevalid
 * 判断打包类型是否有效(支持)
	avtype   : 打包类型(MR_PACKTYPE_TYPE)
 * 返回1支持，0 不支持
*/
int libav_output_typevalid(int avtype);

/* libav_output_open
 * 打开文件输出
	ppOutput : 输出句柄指针
	avtype   : 打包类型(MR_PACKTYPE_TYPE)
	bStream  : TRUE - 按流方式打包，FALSE - 按文件方式大伯
 * 返回0成功，其他为错误值
*/
int libav_output_open(MRAVHANDLE *ppOutput, int avtype, int bStream);

/* libav_output_close
 * 关闭打包句柄
	ppOutput : 打包句柄
 * 返回0成功，其他为错误值
*/
int libav_output_close(MRAVHANDLE pOutput);

/* libav_output_reset
 * 复位打包
	pOutput : 打包句柄
 * 返回0成功，其他为错误值
 * 在开始新的一次打包时需要调用该函数复位
*/
int libav_output_reset(MRAVHANDLE pOutput);

/* libav_output_newstream
 * 添加流
	pOutput : 打包句柄
	pStream : 流信息
 * 返回0成功，其他为错误值
*/
int libav_output_newstream(MRAVHANDLE pOutput, MRAVSTREAM_T *pStream);

/* libav_output_write_head
 * 添加流
	pOutput : 打包句柄
	pOut    : 输出打包头信息指针
	szPassword : 目前没有使用，使用时设置成NULL
 * 返回0成功，其他为错误值
*/
int libav_output_write_head(MRAVHANDLE pOutput, MRAVEncFrame *pOut, const char *szPassword);

/* libav_output_write_config
 * 目前不需要使用
	pOutput : 打包句柄
 * 返回0成功，其他为错误值
*/
int libav_output_write_config(MRAVHANDLE pOutput, MRAVFrame *pkt, MRAVEncFrame *pOut);

/* libav_output_flv_config
 * FLV专用打包
	pOutput : 打包句柄
 * 返回0成功，其他为错误值
*/
int libav_output_flv_config(MRAVHANDLE pOutput, int codec_type, MRAVFrame *pkt, MRAVEncFrame *pOut);

/* libav_output_write_frame
 * 打包一帧数据
	pOutput : 打包句柄
	pkt     : 输入帧数据
	pOut    : 打包输出帧数据
 * 返回0成功，其他为错误值
*/
int libav_output_write_frame(MRAVHANDLE pOutput, MRAVFrame *pkt, MRAVEncFrame *pOut);

/* libav_output_write_frame_nobuff
 * 未使用
	pOutput : 打包句柄
	pkt     : 输入帧数据
	pOutBuff: 输出指针
 * 返回打包长度，小于0为错误代码
*/
int libav_output_write_frame_nobuff(MRAVHANDLE pOutput, MRAVFrame *pkt, unsigned char **pOutBuff);

/* libav_output_write_trailer
 * 停止打包
	pOutput : 打包句柄
	pOut    : 打包输出帧数据
 * 返回1，需要重新调用libav_output_write_head写入头，0 - 把不需要，小于0为错误代码
*/
int libav_output_write_trailer(MRAVHANDLE pOutput, MRAVEncFrame *pOut);

/* libav_output_write_pause
 * 暂停/恢复打包
	pOutput : 打包句柄
	bPause  : TRUE - 暂停，FALSE - 恢复
 * 返回0成功，其他为错误值
*/
int libav_output_write_pause(MRAVHANDLE pOutput, int bPause);

/* libav_output_write_endhead
 * 判断停止打包是否需要重新写入文件头
	pOutput : 打包句柄
 * 返回1，需要重新调用libav_output_write_head写入头，0 - 把不需要，小于0为错误代码
*/
int libav_output_write_endhead(MRAVHANDLE pOutput);


/***************************************************** 文件解析 ********************************************************/

/* libav_input_open
 * 打开文件
	ppInput     : 解析句柄指针
	szFileName  : 文件名 
	extern_data : TRUE - 获得扩展数据
 * 返回0成功，其他为错误值
*/
int libav_input_open(MRAVHANDLE *ppInput, const char *szFileName, int extern_data);

/* libav_input_openpos
 * 打开文件
	ppInput     : 解析句柄指针
	szFileName  : 文件名 
	extern_data : TRUE - 获得扩展数据
	stPos       : 文件开始位置
	edPos       : 文件结束位置
 * 返回0成功，其他为错误值
*/
int libav_input_openpos(MRAVHANDLE *ppInput, const char *szFileName, int extern_data, int64_t stPos, int64_t edPos);

/* libav_input_openpos
 * 打开文件
	ppInput     : 解析句柄指针
	szFileName  : 文件名 
	extern_data : TRUE - 获得扩展数据
	stPos       : 文件开始位置
	edPos       : 文件结束位置
	bBuildIndex : TRUE - 打开文件时创建索引
 * 返回0成功，其他为错误值
*/
int libav_input_openpos_index(MRAVHANDLE *ppInput, const char *szFileName, int extern_data, int64_t stPos, int64_t edPos, int bBuildIndex);

/* libav_input_password
 * 获得文件密码
	pInput      : 解析句柄指针
 * 返回文件密码，错误返回NULL
*/
char *libav_input_password(MRAVHANDLE pInput);

/* libav_input_checkpassword
 * 校验文件密码
	pInput      : 解析句柄指针
	szPassword  : 密码
 * 返回0成功，其他为错误值
*/
int libav_input_checkpassword(MRAVHANDLE pInput, const char *szPassword);

/* libav_input_close
 * 关闭解析句柄
	pInput      : 解析句柄指针
 * 返回0成功，其他为错误值
*/
int libav_input_close(MRAVHANDLE pInput);

/* libav_input_curpts
 * 获得当前时间戳
	pInput      : 解析句柄指针
	stream_index: 流索引，如果stream_index为-1，返回第一路视频流的当前时间戳
 * 返回时间戳
*/
int libav_input_curpts(MRAVHANDLE pInput, int stream_index);

/* libav_input_duration
 * 获得文件的持续时间
	pInput      : 解析句柄指针
 * 返回持续时间
*/
int64_t libav_input_duration(MRAVHANDLE pInput);

/* libav_input_tolalframes
 * 获得流总帧数
	pInput      : 解析句柄指针
	stream_index: 流索引，如果stream_index为-1，返回第一路视频流的总帧数
 * 返回时间戳
*/
unsigned int libav_input_tolalframes(MRAVHANDLE pInput, int stream_index);

/* libav_input_filesize
 * 获得文件的大小
	pInput      : 解析句柄指针
 * 返回文件大小
*/
int64_t libav_input_filesize(MRAVHANDLE pInput);

/* libav_input_curpos
 * 获得当前位置
	pInput      : 解析句柄指针
 * 返回当前位置
*/
int64_t libav_input_curpos(MRAVHANDLE pInput);

/* libav_input_getframe
 * 获得下一帧数据
	pInput      : 解析句柄指针
	pkt         : 输出帧数据
 * 返回帧大小，小于0为错误代码
*/
int libav_input_getframe(MRAVHANDLE pInput, MRAVFrame *pkt);

/* libav_input_getprekeyframe
 * 获得上一个关键帧数据
	pInput      : 解析句柄指针
	pkt         : 输出帧数据
 * 返回帧大小，小于0为错误代码
*/
int libav_input_getprekeyframe(MRAVHANDLE pInput, MRAVFrame *pkt);

/* libav_input_getdata
 * 获得特殊数据
	pInput      : 解析句柄指针
	pkt         : 输出帧数据
 * 返回数据，小于0为错误代码
*/
int libav_input_getdata(MRAVHANDLE pInput, MRAVFrame *pkt);

/* libav_input_seektime
 * 文件跳转(按时间)
	pInput      : 解析句柄指针
	stream_index: 流索引(目前未使用)
	nSeconds    : 跳转秒数
 * 返回数据，小于0为错误代码
*/
int libav_input_seektime(MRAVHANDLE pInput, int stream_index, int nSeconds);

/* libav_input_seekframeinx
 * 文件跳转(按帧编号)
	pInput      : 解析句柄指针
	stream_index: 流索引(无效时使用第一路视频流)
	nframeinx   : 帧编号( 0 - total frames - 1)
 * 返回数据，小于0为错误代码
*/
int libav_input_seekframeinx(MRAVHANDLE pInput, int stream_index, unsigned int nframeinx);

/* libav_input_seekpos
 * 文件跳转(按位置)
	pInput      : 解析句柄指针
	i64Pos      : 文件位置
 * 返回数据，小于0为错误代码
 * 不建议使用该函数，除非你确定i64Pos的有效性(帧对齐位置)
*/
int libav_input_seekpos(MRAVHANDLE pInput, int64_t i64Pos);

/* libav_input_raw_getfilehead
 * 获得文件原始文件头
	pInput      : 解析句柄指针
	pkt         : 输出头数据
 * 返回数据长度，小于0为错误代码
*/
int libav_input_raw_getfilehead(MRAVHANDLE pInput, MRAVFrame *pkt);

/* libav_input_raw_getframe
 * 获得下一帧数据，包含文件帧头
	pInput      : 解析句柄指针
	pkt         : 输出头数据
 * 返回数据长度，小于0为错误代码
*/
int libav_input_raw_getframe(MRAVHANDLE pInput, MRAVFrame *pkt);

/* libav_input_parserawframe
 * 解析原始帧数据
	pInput      : 解析句柄指针
	pRawData	: 原始帧数据
	nRawSize	: 帧数据长度
	pkt         : 输出帧数据，data为帧数据指针
 * 返回数据长度，小于0为错误代码
*/
int libav_input_parserawframe(MRAVHANDLE pInput, unsigned char *pRawData, int nRawSize, MRAVFrame *pkt);

/* libav_aac_adtstoasc_filter
 * 解析AAC头
*/
int libav_aac_adtstoasc_filter(int bFirstFrame, MRSTREAM_EXTDATA_T *pExtData, 
							  unsigned char **poutbuf, int *poutbuf_size,
                              unsigned char *buf, int  buf_size);

/* libav_aac_adtsenc
 * 获得AAC编码头
*/
int libav_aac_adtsenc(unsigned char *pBuf, int framesize, int objecttype, int sample_rate_index, int channel_conf);

#ifdef __cplusplus
}
#endif
#endif//__LIBAVFORMAT_H__
