/*
 * (C) 2003-2006 Gabest
 * (C) 2006-2023 see Authors.txt
 *
 * This file is part of MPC-BE.
 *
 * MPC-BE 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 3 of the License, or
 * (at your option) any later version.
 *
 * MPC-BE 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, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include <Aviriff.h> // conflicts with vfw.h...
#include "../BaseSplitter/BaseSplitter.h"

class CAviFile : public CBaseSplitterFileEx
{
	HRESULT Init();
	HRESULT Parse(DWORD parentid, __int64 end);
	HRESULT BuildAMVIndex();

public:
	CAviFile(IAsyncReader* pAsyncReader, HRESULT& hr);

	//using CBaseSplitterFile::Read;
	template<typename T>
	HRESULT ReadAvi(T& var, int offset = 0) {
		memset(&var, 0, sizeof(var));
		HRESULT hr = ByteRead((BYTE*)&var + offset, sizeof(var) - offset);
		return hr;
	}

	AVIMAINHEADER m_avih;
	struct ODMLExtendedAVIHeader {
		DWORD dwTotalFrames;
	} m_dmlh;
	struct VideoPropHeader {
		WORD  VideoFormatToken;
		DWORD VideoStandard;
		DWORD dwVerticalRefreshRate;
		DWORD dwHTotalInT;
		DWORD dwVTotalInLines;
		WORD  FrameAspectRatioNum;
		WORD  FrameAspectRatioDen;
		DWORD dwFrameWidthInPixels;
		DWORD dwFrameHeightInLines;
		DWORD nbFieldPerFrame;
	} m_vprp;
	struct strm_t {
		AVISTREAMHEADER strh;
		std::vector<BYTE> strf;
		CStringA strn;
		std::unique_ptr<AVISUPERINDEX> indx;
		struct chunk {
			UINT64 fKeyFrame:1, fChunkHdr:1, size:62;
			UINT64 filepos;
			DWORD orgsize;
		};
		std::vector<chunk> cs;
		UINT64 totalsize;
		REFERENCE_TIME GetRefTime(DWORD frame, UINT64 size);
		int GetTime(DWORD frame, UINT64 size);
		DWORD GetFrame(REFERENCE_TIME rt);
		DWORD GetKeyFrame(REFERENCE_TIME rt);
		DWORD GetChunkSize(DWORD size);
		bool IsRawSubtitleStream();

		// tmp
		struct chunk2 {
			DWORD t;
			DWORD n;
		};
		std::vector<chunk2> cs2;
	};
	std::vector<std::unique_ptr<strm_t>> m_strms;
	std::map<DWORD, CStringA> m_info;
	std::unique_ptr<BYTE[]> m_idx1;

	std::list<UINT64> m_movis;
	bool m_isamv;

	REFERENCE_TIME GetTotalTime();
	HRESULT BuildIndex();
	void EmptyIndex(LONG TrackNum = -1);
	bool IsInterleaved(bool fKeepInfo = false);
};

#define TRACKNUM(fcc)	(10*((fcc&0xff)-0x30) + (((fcc>>8)&0xff)-0x30))
#define TRACKTYPE(fcc)	((WORD)((((DWORD)fcc>>24)&0xff)|((fcc>>8)&0xff00)))
