HRESULT TestPattern::CreateFrame(IDeckLinkVideoFrame** frame, void (*fillFunc)(IDeckLinkVideoFrame*))
{
	HRESULT						result;
	int							bytesPerPixel = GetBytesPerPixel(m_config->m_pixelFormat);
	IDeckLinkMutableVideoFrame*	newFrame = NULL;
	IDeckLinkMutableVideoFrame*	referenceFrame = NULL;
	IDeckLinkVideoConversion*	frameConverter = NULL;

	*frame = NULL;

	result = m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth * bytesPerPixel, m_config->m_pixelFormat, bmdFrameFlagDefault, &newFrame);
	if (result != S_OK)
	{
		fprintf(stderr, "Failed to create video frame\n");
		goto bail;
	}

	if (m_config->m_pixelFormat == bmdFormat8BitYUV)
	{
		fillFunc(newFrame);
	}
	else
	{
		// Create a black frame in 8 bit YUV and convert to desired format
		result = m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &referenceFrame);
		if (result != S_OK)
		{
			fprintf(stderr, "Failed to create reference video frame\n");
			goto bail;
		}

		fillFunc(referenceFrame);

		frameConverter = CreateVideoConversionInstance();

		result = frameConverter->ConvertFrame(referenceFrame, newFrame);
		if (result != S_OK)
		{
			fprintf(stderr, "Failed to convert frame\n");
			goto bail;
		}
	}

	*frame = newFrame;
	newFrame = NULL;

bail:
	if (referenceFrame != NULL)
		referenceFrame->Release();

	if (frameConverter != NULL)
		frameConverter->Release();

	if (newFrame != NULL)
		newFrame->Release();

	return result;
}
SignalGenerator3DVideoFrame* CSignalGeneratorDlg::CreateBlackFrame ()
{
	IDeckLinkMutableVideoFrame*		referenceBlack = NULL;
	IDeckLinkMutableVideoFrame*		scheduleBlack = NULL;
	HRESULT							hr;
	BMDPixelFormat					pixelFormat;
	int								bytesPerPixel;
	IDeckLinkVideoConversion*		frameConverter = NULL;
	SignalGenerator3DVideoFrame*	ret = NULL;

	pixelFormat = (BMDPixelFormat)m_pixelFormatCombo.GetItemData(m_pixelFormatCombo.GetCurSel());
	bytesPerPixel = GetBytesPerPixel(pixelFormat);

	hr = m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth*bytesPerPixel, pixelFormat, bmdFrameFlagDefault, &scheduleBlack);
	if (hr != S_OK)
		goto bail;

	if (pixelFormat == bmdFormat8BitYUV)
	{
		FillBlack(scheduleBlack);
	}
	else
	{
		hr = m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &referenceBlack);
		if (hr != S_OK)
			goto bail;
		FillBlack(referenceBlack);

		hr = CoCreateInstance(CLSID_CDeckLinkVideoConversion, NULL, CLSCTX_ALL, IID_IDeckLinkVideoConversion, (void**)&frameConverter);
		if (hr != S_OK)
			goto bail;

		hr = frameConverter->ConvertFrame(referenceBlack, scheduleBlack);
		if (hr != S_OK)
			goto bail;
	}

	ret = new SignalGenerator3DVideoFrame(scheduleBlack);

bail:
	if (referenceBlack)
		referenceBlack->Release();
	if (scheduleBlack)
		scheduleBlack->Release();
	if (frameConverter)
		frameConverter->Release();

	return ret;
}