/********************************************************

	Classes for reading AVIs
	Copyright 2000 Eugene Kuznetsov (divx@euro.ru)

*********************************************************/

#include "AviRead.h"
#include "AviReadStreamA.h"
#include "AviReadStreamV.h"
#include <creators.h>

#include <iostream>
#include <cstdio>

#ifndef TIMING
#define Debug if(0)
#else
#define Debug
#endif

using namespace Creators;
using namespace std;
#define __MODULE__ "AviRead"

IAviReadStream::~IAviReadStream()
{
}

IAviReadFile::~IAviReadFile()
{
}

/************************************************************

		    AviReadFile functions

************************************************************/

AviReadFile::AviReadFile(const char* name)
{
    try
    {
	m_streams.clear();
	m_pIFile = 0;
	try
        {
	    m_pIFile = CreateAviMediaReadHandler(name);
        }
        catch(FatalError& e)
	{
	    e.Print();
        }
        catch(...)
	{
	    cout << "Some strange exception" << endl;
        }

	if (!m_pIFile)
        {
	    try
    	    {
    	        m_pIFile = CreateASFReadHandler(name);
	    }
    	    catch(FatalError& e)
            {
	        e.Print();
	    }
            catch(...)
	    {
		cout << "Some strange exception" << endl;
	    }
	}

        if (!m_pIFile)
	    throw FATAL("Can't open file");//never get here
//        cout<<"Successfully opened"<<endl;
        int i = 0;
        IMediaReadStream* stream;
        m_vcount = m_acount = 0;
	m_streams.clear();

	while ((stream = m_pIFile->GetStream(mmioFOURCC('v', 'i', 'd', 's'), m_vcount)))
	{
	    m_streams.push_back(new AviReadStreamV(m_vcount, stream));
	    m_vcount++;

	}

	while ((stream = m_pIFile->GetStream(mmioFOURCC('a', 'u', 'd', 's'), m_acount)))
	{
	    m_streams.push_back(new AviReadStreamA(m_vcount + i, stream));
	    m_acount++;
	}

	m_pIFile->GetHeader(&m_header, sizeof(m_header));
	cout<<"Successfully opened "<<name<<". "<<m_vcount<<" video streams, "
	    <<m_acount<<" audio streams"<<endl
	    <<"Length "<<m_header.dwTotalFrames<<endl;
    }
    catch(...)
    {
        _destruct();
	throw;
    }
}

AviReadFile::~AviReadFile()
{
    _destruct();
}

void AviReadFile::_destruct()
{
    for (unsigned i = 0; i < m_streams.size(); i++)
	delete m_streams[i];

    m_streams.clear();
    delete m_pIFile;
    m_pIFile = 0;
}

Unsigned AviReadFile::StreamCount()
{
    return m_vcount + m_acount;
}

Unsigned AviReadFile::VideoStreamCount()
{
    return m_vcount;
}

Unsigned AviReadFile::AudioStreamCount()
{
    return m_acount;
}

HRESULT AviReadFile::GetHeader(void* pheader, size_t n) const
{
    if (!pheader || (n < sizeof(m_header)))
	return -1;
    if (n > sizeof(m_header))
	memcpy(pheader, 0, n);
    // MainAVIHeader
    memcpy(pheader, &m_header, sizeof(m_header));
    return 0;
}

IAviReadStream* AviReadFile::GetStream(streamid_t stream_id, AviStream::StreamType type)
{
    if (type == AviStream::Video)
    {
	if (stream_id < VideoStreamCount())
	    return m_streams[stream_id];
    }
    else if (type == AviStream::Audio)
	if (stream_id < AudioStreamCount())
	    return m_streams[m_vcount+stream_id];

    return NULL;
}

IAviReadFile* CreateIAviReadFile(const char* name)
{
    return new AviReadFile(name);
}
