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; }
BMDOutputDelegate::BMDOutputDelegate(IDeckLink* link) : m_deckLink(link) , m_deckLinkConverter(0) , m_rgbFrame(0) , m_yuvFrame(0) , m_running(false) , m_frameSet(false) , m_frameReceivedCount(0) { // Obtain the audio/video output interface (IDeckLinkOutput) if (m_deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&m_deckLinkOutput) != S_OK) goto bail; #ifdef Q_OS_WIN if(CoCreateInstance(CLSID_CDeckLinkVideoConversion, NULL, CLSCTX_ALL,IID_IDeckLinkVideoConversion, (void**)&m_deckLinkConverter) != S_OK) #else if(!(m_deckLinkConverter = CreateVideoConversionInstance())) #endif { qDebug() << "BMDCaptureDelegate: Cannot create an instance of IID_IDeckLinkVideoConversion, therefore cannot convert YUV->RGB, therefore we will not emit proper RGB frames now."; m_deckLinkConverter = NULL; goto bail; } // Provide this class as a delegate to the audio and video output interfaces m_deckLinkOutput->SetScheduledFrameCompletionCallback(this); // Start. StartRunning(); return; bail: if (m_running == true) { StopRunning(); } else { // Release any resources that were partially allocated if (m_deckLinkOutput != NULL) { m_deckLinkOutput->Release(); m_deckLinkOutput = NULL; } // if (m_deckLink != NULL) { m_deckLink->Release(); m_deckLink = NULL; } } return ; };
int main(int argc, char *argv[]) { HRESULT result; int exitStatus = 1; int idx; pthread_mutex_init(&g_sleepMutex, NULL); pthread_cond_init(&g_sleepCond, NULL); signal(SIGINT, sigfunc); signal(SIGTERM, sigfunc); signal(SIGHUP, sigfunc); // Process the command line arguments if (!g_config.ParseArguments(argc, argv)) { g_config.DisplayUsage(exitStatus); cleanup(); return exitStatus; } g_lcm = new lcm::LCM(); g_conversionInst = CreateVideoConversionInstance(); // Get the DeckLink device g_deckLinkIterator = CreateDeckLinkIteratorInstance(); if (!g_deckLinkIterator) { fprintf(stderr, "This application requires the DeckLink drivers installed.\n"); cleanup(); return exitStatus; } idx = g_config.m_deckLinkIndex; while ((result = g_deckLinkIterator->Next(&g_deckLink)) == S_OK) { if (idx == 0) break; --idx; g_deckLink->Release(); } if (result != S_OK || g_deckLink == NULL) { fprintf(stderr, "Unable to get DeckLink device %u\n", g_config.m_deckLinkIndex); cleanup(); return exitStatus; } // Get the input (capture) interface of the DeckLink device result = g_deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&g_deckLinkInput); if (result != S_OK) { cleanup(); return exitStatus; } // Get the output (display) interface of the DeckLink device if (g_deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&g_deckLinkOutput) != S_OK) { cleanup(); return exitStatus; } // Get the display mode if (g_config.m_displayModeIndex == -1) { // Check the card supports format detection result = g_deckLink->QueryInterface(IID_IDeckLinkAttributes, (void**)&g_deckLinkAttributes); if (result == S_OK) { result = g_deckLinkAttributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &g_formatDetectionSupported); if (result != S_OK || !g_formatDetectionSupported) { fprintf(stderr, "Format detection is not supported on this device\n"); cleanup(); return exitStatus; } } g_config.m_inputFlags |= bmdVideoInputEnableFormatDetection; // Format detection still needs a valid mode to start with idx = 0; } else { idx = g_config.m_displayModeIndex; } result = g_deckLinkInput->GetDisplayModeIterator(&g_displayModeIterator); if (result != S_OK) { cleanup(); return exitStatus; } while ((result = g_displayModeIterator->Next(&g_displayMode)) == S_OK) { if (idx == 0) break; --idx; g_displayMode->Release(); } if (result != S_OK || g_displayMode == NULL) { fprintf(stderr, "Unable to get display mode %d\n", g_config.m_displayModeIndex); cleanup(); return exitStatus; } // Get display mode name result = g_displayMode->GetName((const char**)&g_displayModeName); if (result != S_OK) { g_displayModeName = (char *)malloc(32); snprintf(g_displayModeName, 32, "[index %d]", g_config.m_displayModeIndex); } // Check display mode is supported with given options result = g_deckLinkInput->DoesSupportVideoMode(g_displayMode->GetDisplayMode(), g_config.m_pixelFormat, bmdVideoInputFlagDefault, &g_displayModeSupported, NULL); if (result != S_OK) { cleanup(); return exitStatus; } if (g_displayModeSupported == bmdDisplayModeNotSupported) { fprintf(stderr, "The display mode %s is not supported with the selected pixel format\n", g_displayModeName); cleanup(); return exitStatus; } if (g_config.m_inputFlags & bmdVideoInputDualStream3D) { if (!(g_displayMode->GetFlags() & bmdDisplayModeSupports3D)) { fprintf(stderr, "The display mode %s is not supported with 3D\n", g_displayModeName); cleanup(); return exitStatus; } } // Print the selected configuration g_config.DisplayConfiguration(); // Configure the capture callback g_delegate = new DeckLinkCaptureDelegate(); g_deckLinkInput->SetCallback(g_delegate); // Open output files if (g_config.m_videoOutputFile != NULL) { g_videoOutputFile = open(g_config.m_videoOutputFile, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (g_videoOutputFile < 0) { fprintf(stderr, "Could not open video output file \"%s\"\n", g_config.m_videoOutputFile); cleanup(); return exitStatus; } } if (g_config.m_audioOutputFile != NULL) { g_audioOutputFile = open(g_config.m_audioOutputFile, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (g_audioOutputFile < 0) { fprintf(stderr, "Could not open audio output file \"%s\"\n", g_config.m_audioOutputFile); cleanup(); return exitStatus; } } // Block main thread until signal occurs while (!g_do_exit) { // Start capturing result = g_deckLinkInput->EnableVideoInput(g_displayMode->GetDisplayMode(), g_config.m_pixelFormat, g_config.m_inputFlags); if (result != S_OK) { fprintf(stderr, "Failed to enable video input. Is another application using the card?\n"); } else { result = g_deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz, g_config.m_audioSampleDepth, g_config.m_audioChannels); if (result == S_OK) { frameConsumer.Start(); result = g_deckLinkInput->StartStreams(); if (result == S_OK) { // All Okay. exitStatus = 0; pthread_mutex_lock(&g_sleepMutex); pthread_cond_wait(&g_sleepCond, &g_sleepMutex); pthread_mutex_unlock(&g_sleepMutex); fprintf(stderr, "Stopping Capture\n"); frameConsumer.Stop(); g_deckLinkInput->StopStreams(); g_deckLinkInput->DisableAudioInput(); g_deckLinkInput->DisableVideoInput(); } } } } cleanup(); return exitStatus; }