#include "DeckLinkFrameTransfer.h"

#include "DeckLinkSession.h"

////////////////////////////////////////////
// DeckLink Capture Delegate Class
////////////////////////////////////////////
CaptureDelegate::CaptureDelegate(DeckLinkSession* pOwner) :
	m_pOwner(pOwner),
	mRefCount(1)
{
}

HRESULT CaptureDelegate::QueryInterface(REFIID, LPVOID* ppv)
{
	*ppv = NULL;
	return E_NOINTERFACE;
}

ULONG CaptureDelegate::AddRef()
{
	return InterlockedIncrement(&mRefCount);
}

ULONG CaptureDelegate::Release()
{
	int newCount = InterlockedDecrement(&mRefCount);
	if (newCount == 0)
		delete this;
	return newCount;
}

HRESULT CaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* inputFrame, IDeckLinkAudioInputPacket*)
{
	if (!inputFrame)
	{
		// It's possible to receive a NULL inputFrame, but a valid audioPacket. Ignore audio-only frame.
		return S_OK;
	}

	bool hasNoInputSource = (inputFrame->GetFlags() & bmdFrameHasNoInputSource) == bmdFrameHasNoInputSource;
	m_pOwner->HandleVideoInputFrame(inputFrame, hasNoInputSource);
	return S_OK;
}

HRESULT CaptureDelegate::VideoInputFormatChanged(BMDVideoInputFormatChangedEvents, IDeckLinkDisplayMode*, BMDDetectedVideoInputFormatFlags)
{
	return S_OK;
}

////////////////////////////////////////////
// DeckLink Playout Delegate Class
////////////////////////////////////////////
PlayoutDelegate::PlayoutDelegate(DeckLinkSession* pOwner) :
	m_pOwner(pOwner),
	mRefCount(1)
{
}

HRESULT PlayoutDelegate::QueryInterface(REFIID, LPVOID* ppv)
{
	*ppv = NULL;
	return E_NOINTERFACE;
}

ULONG PlayoutDelegate::AddRef()
{
	return InterlockedIncrement(&mRefCount);
}

ULONG PlayoutDelegate::Release()
{
	int newCount = InterlockedDecrement(&mRefCount);
	if (newCount == 0)
		delete this;
	return newCount;
}

HRESULT PlayoutDelegate::ScheduledFrameCompleted(IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result)
{
	switch (result)
	{
	case bmdOutputFrameDisplayedLate:
	case bmdOutputFrameDropped:
	case bmdOutputFrameCompleted:
	case bmdOutputFrameFlushed:
		// Late/drop counts are recorded by VideoBackend; keep this callback lean.
		break;
	default:
		OutputDebugStringA("ScheduledFrameCompleted() frame did not complete: Unknown error\n");
	}

	m_pOwner->HandlePlayoutFrameCompleted(completedFrame, result);
	return S_OK;
}

HRESULT PlayoutDelegate::ScheduledPlaybackHasStopped()
{
	return S_OK;
}
