#pragma once

#include <string>

#ifdef __cplusplus
extern "C"
{
#endif

#include "libavcodec/avcodec.h"

#ifdef __cplusplus
};
#endif

enum AVCodecID;
struct AVPacket;
struct AVStream;
struct AVFormatContext;
struct AVCodecContext;

typedef AVPacket MediaPacket;

class CFileReader
{
public:
	CFileReader();
	~CFileReader();

	
	/**
	 *	Open media file
	 *
	 *	@param	filePath	media file full path
	 *
	 *	@return 0 - success, -1 - failure
	 */
	int OpenFile(std::string filePath, std::string key = "", int nTimeOutValue = 5 * 1000);
	/**
	 *	Close media file
	 */
	int CloseFile();
	/**
	 *	Read one avpacket
	 *
	 *	@return 0 - success, -1 - EOF, <-1 - failure
	 */
	int ReadFile(AVPacket &pkt);

	/**
	 *	Pause read
	 */
	int PauseRead(bool bPause);

	/**
	 *	Get media file time length
	 *
	 *	@return	duration in seconds
	 */
	double GetFileTimeLength();

	/**
	 *	Get video size
	 *
	 *	@param	nWidht[out]		video width
	 *	@param	nHeight[out]	video height
	 *
	 *	@return	0 - success, -1 - failure
	 */
	int	   GetVideoSize(int &nWidth, int &nHeight);

	/**
	 *	Geg frame rate
	 */
	float  GetVideoFrameRate();

	/**
	 *	Seek file
	 *
	 *	@param	see 'avformat_seek_file'
	 *
	 *	@return	0 - success, -1 - failure
	 */
	int SeekFile(int streamIndex, long long minTs, long long timestamp_us, long long maxTs, int flags);

	/**
	 * Get decoder id
	 */
	AVCodecID GetVideoCodecID();
	AVCodecID GetAudioCodecID();

	/**
	 *	Get video/audio stream object
	 */
	AVStream	*GetVideoStream(){ return m_inVideoStream; }
	AVStream	*GetAudioStream(){ return m_inAudioStream; }
	int VideoStreamIndex(){	return m_nVideoIndex; }
	int AudioStreamIndex(){ return m_nAudioIndex; }

	/**
	 *	Get video/audio widht/height/size
	 */
	int GetAudioRawFrameSize();
	int	GetVideoRawFrameSize(int &width, int &height);

	bool IsNetFile() { return m_bNetFile; }
	bool HasVideoStream() { return (m_nVideoIndex == -1) ? false : true; }
	bool HasAudioStream() { return (m_nAudioIndex == -1) ? false : true; }

	bool IsAnnexb4Video();

	/**
	 *	judge ptr is not other sei data
	 */
	bool IsVideoPacketNeedDecode(char *ptr);

	/**
	 *	Get nalu type
	 */
	char GetNaluType(char *ptr, bool isAnnexb);
	/**
	 *	Get sei sub type
	 */
	char GetSeiSubType(char *ptr, bool isAnnexb);

	void SetEof(bool bEof);
	bool GetEof();
private:
	void resetReader();

private:
	AVFormatContext		*m_inFormatContext;
	AVStream			*m_inVideoStream;
	AVStream			*m_inAudioStream;
	int					m_nVideoIndex;
	int					m_nAudioIndex;

private:
	bool				m_bNetFile;	//true - ÍøÂçÂ¼Ïñ

private:
	std::string			aes_128_key_value_;
private:
	bool				m_bEof;
};
