bool Output::startDeckLink(BMDDisplayMode mode) { IDeckLinkDisplayModeIterator* pDLDisplayModeIterator = NULL; IDeckLinkDisplayMode* pDLDisplayMode = NULL; if (pDLOutput->GetDisplayModeIterator(&pDLDisplayModeIterator) == S_OK) { while (pDLDisplayModeIterator->Next(&pDLDisplayMode) == S_OK) { if (pDLDisplayMode->GetDisplayMode() == mode) { break; } } pDLDisplayModeIterator->Release(); } if (!pDLDisplayMode) { ofLogError("ofxDeckLinkAPI::Output") << "invalid display mode"; return false; } uiFrameWidth = pDLDisplayMode->GetWidth(); uiFrameHeight = pDLDisplayMode->GetHeight(); pixels[0].allocate(uiFrameWidth, uiFrameHeight, 4); pixels[1].allocate(uiFrameWidth, uiFrameHeight, 4); front_buffer = &pixels[0]; back_buffer = &pixels[1]; pDLDisplayMode->GetFrameRate(&frameDuration, &frameTimescale); uiFPS = ((frameTimescale + (frameDuration - 1)) / frameDuration); if (pDLOutput->EnableVideoOutput(pDLDisplayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) != S_OK) return false; if (pDLOutput->CreateVideoFrame(uiFrameWidth, uiFrameHeight, uiFrameWidth * 4, bmdFormat8BitARGB, bmdFrameFlagDefault, &pDLVideoFrame) != S_OK) return false; uiTotalFrames = 0; resetFrame(); setPreroll(); pDLOutput->StartScheduledPlayback(0, frameTimescale, 1); return true; }
BMDDisplayMode getDisplayMode( mlt_profile profile, int vancLines ) { IDeckLinkDisplayModeIterator* iter = NULL; IDeckLinkDisplayMode* mode = NULL; BMDDisplayMode result = (BMDDisplayMode) bmdDisplayModeNotSupported; if ( m_decklinkInput->GetDisplayModeIterator( &iter ) == S_OK ) { while ( !result && iter->Next( &mode ) == S_OK ) { int width = mode->GetWidth(); int height = mode->GetHeight(); BMDTimeValue duration; BMDTimeScale timescale; mode->GetFrameRate( &duration, ×cale ); double fps = (double) timescale / duration; int p = mode->GetFieldDominance() == bmdProgressiveFrame; m_topFieldFirst = mode->GetFieldDominance() == bmdUpperFieldFirst; m_colorspace = ( mode->GetFlags() & bmdDisplayModeColorspaceRec709 ) ? 709 : 601; mlt_log_verbose( getProducer(), "BMD mode %dx%d %.3f fps prog %d tff %d\n", width, height, fps, p, m_topFieldFirst ); if ( width == profile->width && p == profile->progressive && ( height + vancLines == profile->height || ( height == 486 && profile->height == 480 + vancLines ) ) && fps == mlt_profile_fps( profile ) ) result = mode->GetDisplayMode(); SAFE_RELEASE( mode ); } SAFE_RELEASE( iter ); } return result; }
/* lookup the field dominance corresponding to this BMDDisplayMode */ static RawFrame::FieldDominance find_dominance(BMDDisplayMode mode, IDeckLinkDisplayModeIterator *iterator) { IDeckLinkDisplayMode *imode; if (iterator->Next(&imode) != S_OK) { throw std::runtime_error("DeckLink: failed to iterate display modes"); } while (imode) { BMDFieldDominance fd = imode->GetFieldDominance( ); BMDDisplayMode thismode = imode->GetDisplayMode( ); imode->Release( ); if (thismode == mode) { switch (fd) { case bmdLowerFieldFirst: return RawFrame::BOTTOM_FIELD_FIRST; case bmdUpperFieldFirst: return RawFrame::TOP_FIELD_FIRST; case bmdProgressiveFrame: case bmdProgressiveSegmentedFrame: return RawFrame::PROGRESSIVE; default: return RawFrame::UNKNOWN; } } if (iterator->Next(&imode) != S_OK) { throw std::runtime_error("failed to iterate display modes"); } } /* no modes matched so we don't know dominance */ return RawFrame::UNKNOWN; }
bool PlaybackHelper::setupDeckLinkOutput() { bool result = false; IDeckLinkDisplayModeIterator* displayModeIterator = NULL; IDeckLinkDisplayMode* deckLinkDisplayMode = NULL; m_width = -1; // set callback m_deckLinkOutput->SetScheduledFrameCompletionCallback(this); // get frame scale and duration for the video mode if (m_deckLinkOutput->GetDisplayModeIterator(&displayModeIterator) != S_OK) goto bail; while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK) { if (deckLinkDisplayMode->GetDisplayMode() == bmdModeNTSC) { m_width = deckLinkDisplayMode->GetWidth(); m_height = deckLinkDisplayMode->GetHeight(); deckLinkDisplayMode->GetFrameRate(&m_frameDuration, &m_timeScale); deckLinkDisplayMode->Release(); break; } deckLinkDisplayMode->Release(); } displayModeIterator->Release(); if (m_width == -1) { fprintf(stderr, "Unable to find requested video mode\n"); goto bail; } // enable video output if (m_deckLinkOutput->EnableVideoOutput(bmdModeNTSC, bmdVideoOutputFlagDefault) != S_OK) { fprintf(stderr, "Could not enable video output\n"); goto bail; } // create coloured frames if (! createFrames()) goto bail; result = true; bail: if (! result) { // release coloured frames releaseFrames(); } return result; }
void CSignalGeneratorDlg::RefreshDisplayModeMenu(void) { // Populate the display mode combo with a list of display modes supported by the installed DeckLink card IDeckLinkDisplayModeIterator* displayModeIterator; IDeckLinkDisplayMode* deckLinkDisplayMode; BMDPixelFormat pixelFormat; pixelFormat = (BMDPixelFormat)m_pixelFormatCombo.GetItemData(m_pixelFormatCombo.GetCurSel()); for (int i = 1; i < m_videoFormatCombo.GetCount(); i++) { deckLinkDisplayMode = (IDeckLinkDisplayMode*)m_videoFormatCombo.GetItemDataPtr(i-1); deckLinkDisplayMode->Release(); } m_videoFormatCombo.ResetContent(); if (m_deckLinkOutput->GetDisplayModeIterator(&displayModeIterator) != S_OK) return; while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK) { BSTR modeName; int newIndex; HRESULT hr; BMDDisplayModeSupport displayModeSupport; BMDVideoOutputFlags videoOutputFlags = bmdVideoOutputDualStream3D; if (deckLinkDisplayMode->GetName(&modeName) != S_OK) { deckLinkDisplayMode->Release(); continue; } CString modeNameCString(modeName); newIndex = m_videoFormatCombo.AddString(modeNameCString); m_videoFormatCombo.SetItemDataPtr(newIndex, deckLinkDisplayMode); hr = m_deckLinkOutput->DoesSupportVideoMode(deckLinkDisplayMode->GetDisplayMode(), pixelFormat, videoOutputFlags, &displayModeSupport, NULL); if (hr != S_OK || ! displayModeSupport) { SysFreeString(modeName); continue; } CString modeName3DCString(modeName); modeName3DCString += _T(" 3D"); newIndex = m_videoFormatCombo.AddString(modeName3DCString); m_videoFormatCombo.SetItemDataPtr(newIndex, deckLinkDisplayMode); deckLinkDisplayMode->AddRef(); SysFreeString(modeName); } displayModeIterator->Release(); m_videoFormatCombo.SetCurSel(0); }
//---------- Specification DeckLink::open(shared_ptr<Base::InitialisationSettings> initialisationSettings) { auto settings = this->getTypedSettings<InitialisationSettings>(initialisationSettings); auto devices = ofxBlackmagic::Iterator::getDeviceList(); if (devices.empty()) { throw(ofxMachineVision::Exception("No DeckLink devices available")); } if (devices.size() <= (unsigned int)settings->deviceID) { string str = "deviceID [" + ofToString(settings->deviceID) + "] out of range. [" + ofToString(devices.size()) + "] devices available"; throw(ofxMachineVision::Exception(str)); } this->device = devices[settings->deviceID]; int width, height; this->displayMode = static_cast<_BMDDisplayMode>(settings->displayMode.get()); try { CHECK_ERRORS(device.device->QueryInterface(IID_IDeckLinkInput, (void**)&this->input), "Failed to query interface"); CHECK_ERRORS(this->input->SetCallback(this), "Failed to set input callback"); //find the current display mode IDeckLinkDisplayModeIterator * displayModeIterator = 0; CHECK_ERRORS(input->GetDisplayModeIterator(&displayModeIterator), "Couldn't get DisplayModeIterator"); IDeckLinkDisplayMode * displayModeTest = nullptr; IDeckLinkDisplayMode * displayModeFound = nullptr; while (displayModeIterator->Next(&displayModeTest) == S_OK) { if (displayModeTest->GetDisplayMode() == this->displayMode) { displayModeFound = displayModeTest; } } if (!displayModeFound) { CHECK_ERRORS(S_FALSE, "Cannot find displayMode"); } width = displayModeFound->GetWidth(); height = displayModeFound->GetHeight(); } catch (std::exception e) { throw(ofxMachineVision::Exception(e.what())); } this->openTime = ofGetElapsedTimeMicros(); this->frameIndex = 0; Specification specification(width, height, "BlackMagic", device.modelName); specification.addFeature(ofxMachineVision::Feature::Feature_DeviceID); specification.addFeature(ofxMachineVision::Feature::Feature_FreeRun); return specification; }
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; IDeckLinkDisplayModeIterator *itermode; IDeckLinkDisplayMode *mode; uint32_t format_code; HRESULT res; if (direction == DIRECTION_IN) { int ret; ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection); if (ret < 0) return ret; ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection); if (ret < 0) return ret; res = ctx->dli->GetDisplayModeIterator (&itermode); } else { res = ctx->dlo->GetDisplayModeIterator (&itermode); } if (res!= S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n"); return AVERROR(EIO); } av_log(avctx, AV_LOG_INFO, "Supported formats for '%s':\n\tformat_code\tdescription", avctx->filename); while (itermode->Next(&mode) == S_OK) { BMDTimeValue tb_num, tb_den; mode->GetFrameRate(&tb_num, &tb_den); format_code = av_bswap32(mode->GetDisplayMode()); av_log(avctx, AV_LOG_INFO, "\n\t%.4s\t\t%ldx%ld at %d/%d fps", (char*) &format_code, mode->GetWidth(), mode->GetHeight(), (int) tb_den, (int) tb_num); switch (mode->GetFieldDominance()) { case bmdLowerFieldFirst: av_log(avctx, AV_LOG_INFO, " (interlaced, lower field first)"); break; case bmdUpperFieldFirst: av_log(avctx, AV_LOG_INFO, " (interlaced, upper field first)"); break; } mode->Release(); } av_log(avctx, AV_LOG_INFO, "\n"); itermode->Release(); return 0; }
void Player::StartRunning(int videomode) { IDeckLinkDisplayMode *videoDisplayMode = NULL; unsigned long audioSamplesPerFrame; // Get the display mode for 1080i 59.95 videoDisplayMode = GetDisplayModeByIndex(videomode); if (!videoDisplayMode) return; m_frameWidth = videoDisplayMode->GetWidth(); m_frameHeight = videoDisplayMode->GetHeight(); videoDisplayMode->GetFrameRate(&m_frameDuration, &m_frameTimescale); // Set the video output mode if (m_deckLinkOutput->EnableVideoOutput(videoDisplayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) != S_OK) { fprintf(stderr, "Failed to enable video output\n"); return; } // Set the audio output mode if (m_deckLinkOutput->EnableAudioOutput(bmdAudioSampleRate48kHz, m_audioSampleDepth, audio_st->codec->channels, bmdAudioOutputStreamTimestamped) != S_OK) { fprintf(stderr, "Failed to enable audio output\n"); return; } for (unsigned i = 0; i < 10; i++) ScheduleNextFrame(true); // Begin audio preroll. This will begin calling our audio callback, which will start the DeckLink output stream. // m_audioBufferOffset = 0; if (m_deckLinkOutput->BeginAudioPreroll() != S_OK) { fprintf(stderr, "Failed to begin audio preroll\n"); return; } m_running = true; return; }
bool start( unsigned preroll ) { m_displayMode = getDisplayMode(); if ( !m_displayMode ) { mlt_log_error( &m_consumer, "Profile is not compatible with decklink.\n" ); return false; } // Set the video output mode if ( S_OK != m_deckLinkOutput->EnableVideoOutput( m_displayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) ) { mlt_log_error( &m_consumer, "Failed to enable video output\n" ); return false; } // Set the audio output mode m_channels = 2; if ( S_OK != m_deckLinkOutput->EnableAudioOutput( bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, m_channels, bmdAudioOutputStreamContinuous ) ) { mlt_log_error( &m_consumer, "Failed to enable audio output\n" ); stop(); return false; } m_fifo = sample_fifo_init(); // Preroll m_isPrerolling = true; m_prerollCounter = 0; m_preroll = preroll < PREROLL_MINIMUM ? PREROLL_MINIMUM : preroll; m_count = 0; m_deckLinkOutput->BeginAudioPreroll(); return true; }
void BMDOutputDelegate::StartRunning () { IDeckLinkDisplayMode* videoDisplayMode = NULL; // Get the display mode for 1080i 59.95 - mode 6 // Changed to NTSC 23.98 - JB 20110215 videoDisplayMode = GetDisplayModeByIndex(1); if (!videoDisplayMode) return; m_frameWidth = videoDisplayMode->GetWidth(); m_frameHeight = videoDisplayMode->GetHeight(); videoDisplayMode->GetFrameRate(&m_frameDuration, &m_frameTimescale); // Calculate the number of frames per second, rounded up to the nearest integer. For example, for NTSC (29.97 FPS), framesPerSecond == 30. m_framesPerSecond = (unsigned long)((m_frameTimescale + (m_frameDuration-1)) / m_frameDuration); QImage image(m_frameWidth,m_frameHeight, QImage::Format_ARGB32); image.fill(Qt::green); //m_frame = VideoFramePtr(new VideoFrame(image, 1000/30)); HRESULT res; // Set the video output mode if (m_deckLinkOutput->EnableVideoOutput(videoDisplayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) != S_OK) { //fprintf(stderr, "Failed to enable video output\n"); qDebug() << "BMDOutputDelegate::StartRunning(): Failed to EnableVideoOutput()"; goto bail; } res = m_deckLinkOutput->CreateVideoFrame( m_frameWidth, m_frameHeight, m_frameWidth * 4, bmdFormat8BitBGRA, bmdFrameFlagDefault, &m_rgbFrame); if(res != S_OK) { qDebug() << "BMDOutputDelegate::StartRunning: Error creating RGB frame, res:"<<res; goto bail; } res = m_deckLinkOutput->CreateVideoFrame( m_frameWidth, m_frameHeight, m_frameWidth * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &m_yuvFrame); if(res != S_OK) { qDebug() << "BMDOutputDelegate::StartRunning: Error creating YUV frame, res:"<<res; goto bail; } // // Generate a frame of black // if (m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &m_videoFrameBlack) != S_OK) // { // fprintf(stderr, "Failed to create video frame\n"); // goto bail; // } // FillBlack(m_videoFrameBlack); // // // Generate a frame of colour bars // if (m_deckLinkOutput->CreateVideoFrame(m_frameWidth, m_frameHeight, m_frameWidth*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &m_videoFrameBars) != S_OK) // { // fprintf(stderr, "Failed to create video frame\n"); // goto bail; // } // FillColourBars(m_videoFrameBars); // Begin video preroll by scheduling a second of frames in hardware m_totalFramesScheduled = 0; for (unsigned i = 0; i < m_framesPerSecond; i++) { PrepareFrame(); ScheduleNextFrame(true); } // Args: startTime, timeScale, playback speed (1.0 = normal) m_deckLinkOutput->StartScheduledPlayback(0, 100, 1.0); m_running = true; return; bail: // *** Error-handling code. Cleanup any resources that were allocated. *** // StopRunning(); }
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction, int num) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; BMDDisplayModeSupport support; IDeckLinkDisplayModeIterator *itermode; IDeckLinkDisplayMode *mode; int i = 1; HRESULT res; av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d, format code %s\n", width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)"); if (ctx->duplex_mode) { DECKLINK_BOOL duplex_supported = false; if (ctx->attr->GetFlag(BMDDeckLinkSupportsDuplexModeConfiguration, &duplex_supported) != S_OK) duplex_supported = false; if (duplex_supported) { res = ctx->cfg->SetInt(bmdDeckLinkConfigDuplexMode, ctx->duplex_mode == 2 ? bmdDuplexModeFull : bmdDuplexModeHalf); if (res != S_OK) av_log(avctx, AV_LOG_WARNING, "Setting duplex mode failed.\n"); else av_log(avctx, AV_LOG_VERBOSE, "Successfully set duplex mode to %s duplex.\n", ctx->duplex_mode == 2 ? "full" : "half"); } else { av_log(avctx, AV_LOG_WARNING, "Unable to set duplex mode, because it is not supported.\n"); } } if (direction == DIRECTION_IN) { int ret; ret = decklink_select_input(avctx, bmdDeckLinkConfigAudioInputConnection); if (ret < 0) return ret; ret = decklink_select_input(avctx, bmdDeckLinkConfigVideoInputConnection); if (ret < 0) return ret; res = ctx->dli->GetDisplayModeIterator (&itermode); } else { res = ctx->dlo->GetDisplayModeIterator (&itermode); } if (res!= S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n"); return AVERROR(EIO); } char format_buf[] = " "; if (cctx->format_code) memcpy(format_buf, cctx->format_code, FFMIN(strlen(cctx->format_code), sizeof(format_buf))); BMDDisplayMode target_mode = (BMDDisplayMode)AV_RB32(format_buf); AVRational target_tb = av_make_q(tb_num, tb_den); ctx->bmd_mode = bmdModeUnknown; while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) { BMDTimeValue bmd_tb_num, bmd_tb_den; int bmd_width = mode->GetWidth(); int bmd_height = mode->GetHeight(); BMDDisplayMode bmd_mode = mode->GetDisplayMode(); BMDFieldDominance bmd_field_dominance = mode->GetFieldDominance(); mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den); AVRational mode_tb = av_make_q(bmd_tb_num, bmd_tb_den); if ((bmd_width == width && bmd_height == height && !av_cmp_q(mode_tb, target_tb) && field_order_eq(field_order, bmd_field_dominance)) || i == num || target_mode == bmd_mode) { ctx->bmd_mode = bmd_mode; ctx->bmd_width = bmd_width; ctx->bmd_height = bmd_height; ctx->bmd_tb_den = bmd_tb_den; ctx->bmd_tb_num = bmd_tb_num; ctx->bmd_field_dominance = bmd_field_dominance; av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n", bmd_width, bmd_height, 1/av_q2d(mode_tb), (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":""); } mode->Release(); i++; } itermode->Release(); if (ctx->bmd_mode == bmdModeUnknown) return -1; if (direction == DIRECTION_IN) { if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } else { if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } if (support == bmdDisplayModeSupported) return 0; return -1; }
void SignalGenerator::startRunning() { IDeckLinkDisplayMode* videoDisplayMode = NULL; BMDVideoOutputFlags videoOutputFlags = 0; QVariant v; // Determine the audio and video properties for the output stream v = ui->outputSignalPopup->itemData(ui->outputSignalPopup->currentIndex()); outputSignal = (OutputSignal)v.value<int>(); v = ui->audioChannelPopup->itemData(ui->audioChannelPopup->currentIndex()); audioChannelCount = v.value<int>(); v = ui->audioSampleDepthPopup->itemData(ui->audioSampleDepthPopup->currentIndex()); audioSampleDepth = v.value<int>(); audioSampleRate = bmdAudioSampleRate48kHz; // // - Extract the IDeckLinkDisplayMode from the display mode popup menu (stashed in the item's tag) v = ui->videoFormatPopup->itemData(ui->videoFormatPopup->currentIndex()); videoDisplayMode = (IDeckLinkDisplayMode *)v.value<void*>(); frameWidth = videoDisplayMode->GetWidth(); frameHeight = videoDisplayMode->GetHeight(); videoDisplayMode->GetFrameRate(&frameDuration, &frameTimescale); // Calculate the number of frames per second, rounded up to the nearest integer. For example, for NTSC (29.97 FPS), framesPerSecond == 30. framesPerSecond = (frameTimescale + (frameDuration-1)) / frameDuration; if (videoDisplayMode->GetDisplayMode() == bmdModeNTSC || videoDisplayMode->GetDisplayMode() == bmdModeNTSC2398 || videoDisplayMode->GetDisplayMode() == bmdModePAL) { timeCodeFormat = bmdTimecodeVITC; videoOutputFlags |= bmdVideoOutputVITC; } else { timeCodeFormat = bmdTimecodeRP188Any; videoOutputFlags |= bmdVideoOutputRP188; } if (timeCode) delete timeCode; timeCode = new Timecode(framesPerSecond); // Set the video output mode if (deckLinkOutput->EnableVideoOutput(videoDisplayMode->GetDisplayMode(), videoOutputFlags) != S_OK) goto bail; // Set the audio output mode if (deckLinkOutput->EnableAudioOutput(bmdAudioSampleRate48kHz, audioSampleDepth, audioChannelCount, bmdAudioOutputStreamTimestamped) != S_OK) goto bail; // Generate one second of audio tone audioSamplesPerFrame = ((audioSampleRate * frameDuration) / frameTimescale); audioBufferSampleLength = (framesPerSecond * audioSampleRate * frameDuration) / frameTimescale; audioBuffer = malloc(audioBufferSampleLength * audioChannelCount * (audioSampleDepth / 8)); if (audioBuffer == NULL) goto bail; FillSine(audioBuffer, audioBufferSampleLength, audioChannelCount, audioSampleDepth); // Generate a frame of black if (deckLinkOutput->CreateVideoFrame(frameWidth, frameHeight, frameWidth*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &videoFrameBlack) != S_OK) goto bail; FillBlack(videoFrameBlack); // Generate a frame of colour bars if (deckLinkOutput->CreateVideoFrame(frameWidth, frameHeight, frameWidth*2, bmdFormat8BitYUV, bmdFrameFlagDefault, &videoFrameBars) != S_OK) goto bail; FillColourBars(videoFrameBars); // Begin video preroll by scheduling a second of frames in hardware totalFramesScheduled = 0; for (unsigned int i = 0; i < framesPerSecond; i++) scheduleNextFrame(true); // Begin audio preroll. This will begin calling our audio callback, which will start the DeckLink output stream. totalAudioSecondsScheduled = 0; if (deckLinkOutput->BeginAudioPreroll() != S_OK) goto bail; // Success; update the UI running = true; ui->startButton->setText("Stop"); // Disable the user interface while running (prevent the user from making changes to the output signal) enableInterface(false); return; bail: QMessageBox::critical(this, "Failed to start output", "Failed to start output"); // *** Error-handling code. Cleanup any resources that were allocated. *** // stopRunning(); }
int main (int argc, char *argv[]) { IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance (); DeckLinkCaptureDelegate *delegate; IDeckLinkDisplayMode *displayMode; BMDVideoInputFlags inputFlags = 0; BMDDisplayMode selectedDisplayMode = bmdModeNTSC; BMDPixelFormat pixelFormat = bmdFormat8BitYUV; int displayModeCount = 0; int exitStatus = 1; int ch; bool foundDisplayMode = false; HRESULT result; pthread_mutex_init (&sleepMutex, NULL); pthread_cond_init (&sleepCond, NULL); if (!deckLinkIterator) { fprintf (stderr, "This application requires the DeckLink drivers installed.\n"); goto bail; } /* Connect to the first DeckLink instance */ result = deckLinkIterator->Next (&deckLink); if (result != S_OK) { fprintf (stderr, "No DeckLink PCI cards found.\n"); goto bail; } if (deckLink->QueryInterface (IID_IDeckLinkInput, (void **) &deckLinkInput) != S_OK) goto bail; delegate = new DeckLinkCaptureDelegate (); deckLinkInput->SetCallback (delegate); // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output result = deckLinkInput->GetDisplayModeIterator (&displayModeIterator); if (result != S_OK) { fprintf (stderr, "Could not obtain the video output display mode iterator - result = %08x\n", result); goto bail; } // Parse command line options while ((ch = getopt (argc, argv, "?h3c:s:f:a:m:n:p:t:")) != -1) { switch (ch) { case 'm': g_videoModeIndex = atoi (optarg); break; case 'c': g_audioChannels = atoi (optarg); if (g_audioChannels != 2 && g_audioChannels != 8 && g_audioChannels != 16) { fprintf (stderr, "Invalid argument: Audio Channels must be either 2, 8 or 16\n"); goto bail; } break; case 's': g_audioSampleDepth = atoi (optarg); if (g_audioSampleDepth != 16 && g_audioSampleDepth != 32) { fprintf (stderr, "Invalid argument: Audio Sample Depth must be either 16 bits or 32 bits\n"); goto bail; } break; case 'f': g_videoOutputFile = optarg; break; case 'a': g_audioOutputFile = optarg; break; case 'n': g_maxFrames = atoi (optarg); break; case '3': inputFlags |= bmdVideoInputDualStream3D; break; case 'p': switch (atoi (optarg)) { case 0: pixelFormat = bmdFormat8BitYUV; break; case 1: pixelFormat = bmdFormat10BitYUV; break; case 2: pixelFormat = bmdFormat10BitRGB; break; default: fprintf (stderr, "Invalid argument: Pixel format %d is not valid", atoi (optarg)); goto bail; } break; case 't': if (!strcmp (optarg, "rp188")) g_timecodeFormat = bmdTimecodeRP188; else if (!strcmp (optarg, "vitc")) g_timecodeFormat = bmdTimecodeVITC; else if (!strcmp (optarg, "serial")) g_timecodeFormat = bmdTimecodeSerial; else { fprintf (stderr, "Invalid argument: Timecode format \"%s\" is invalid\n", optarg); goto bail; } break; case '?': case 'h': usage (0); } } if (g_videoModeIndex < 0) { fprintf (stderr, "No video mode specified\n"); usage (0); } if (g_videoOutputFile != NULL) { videoOutputFile = open (g_videoOutputFile, O_WRONLY | O_CREAT | O_TRUNC, 0664); if (videoOutputFile < 0) { fprintf (stderr, "Could not open video output file \"%s\"\n", g_videoOutputFile); goto bail; } } if (g_audioOutputFile != NULL) { audioOutputFile = open (g_audioOutputFile, O_WRONLY | O_CREAT | O_TRUNC, 0664); if (audioOutputFile < 0) { fprintf (stderr, "Could not open audio output file \"%s\"\n", g_audioOutputFile); goto bail; } } while (displayModeIterator->Next (&displayMode) == S_OK) { if (g_videoModeIndex == displayModeCount) { BMDDisplayModeSupport result; const char *displayModeName; foundDisplayMode = true; displayMode->GetName (&displayModeName); selectedDisplayMode = displayMode->GetDisplayMode (); deckLinkInput->DoesSupportVideoMode (selectedDisplayMode, pixelFormat, bmdVideoInputFlagDefault, &result, NULL); if (result == bmdDisplayModeNotSupported) { fprintf (stderr, "The display mode %s is not supported with the selected pixel format\n", displayModeName); goto bail; } if (inputFlags & bmdVideoInputDualStream3D) { if (!(displayMode->GetFlags () & bmdDisplayModeSupports3D)) { fprintf (stderr, "The display mode %s is not supported with 3D\n", displayModeName); goto bail; } } break; } displayModeCount++; displayMode->Release (); } if (!foundDisplayMode) { fprintf (stderr, "Invalid mode %d specified\n", g_videoModeIndex); goto bail; } result = deckLinkInput->EnableVideoInput (selectedDisplayMode, pixelFormat, inputFlags); if (result != S_OK) { fprintf (stderr, "Failed to enable video input. Is another application using the card?\n"); goto bail; } result = deckLinkInput->EnableAudioInput (bmdAudioSampleRate48kHz, g_audioSampleDepth, g_audioChannels); if (result != S_OK) { goto bail; } result = deckLinkInput->StartStreams (); if (result != S_OK) { goto bail; } // All Okay. exitStatus = 0; // Block main thread until signal occurs pthread_mutex_lock (&sleepMutex); pthread_cond_wait (&sleepCond, &sleepMutex); pthread_mutex_unlock (&sleepMutex); fprintf (stderr, "Stopping Capture\n"); bail: if (videoOutputFile) close (videoOutputFile); if (audioOutputFile) close (audioOutputFile); if (displayModeIterator != NULL) { displayModeIterator->Release (); displayModeIterator = NULL; } if (deckLinkInput != NULL) { deckLinkInput->Release (); deckLinkInput = NULL; } if (deckLink != NULL) { deckLink->Release (); deckLink = NULL; } if (deckLinkIterator != NULL) deckLinkIterator->Release (); return exitStatus; }
static void print_output_modes (IDeckLink* deckLink) { IDeckLinkOutput* deckLinkOutput = NULL; IDeckLinkDisplayModeIterator* displayModeIterator = NULL; IDeckLinkDisplayMode* displayMode = NULL; HRESULT result; // Query the DeckLink for its configuration interface result = deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&deckLinkOutput); if (result != S_OK) { fprintf(stderr, "Could not obtain the IDeckLinkOutput interface - result = %08x\n", result); goto bail; } // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output result = deckLinkOutput->GetDisplayModeIterator(&displayModeIterator); if (result != S_OK) { fprintf(stderr, "Could not obtain the video output display mode iterator - result = %08x\n", result); goto bail; } // List all supported output display modes printf("Supported video output display modes and pixel formats:\n"); while (displayModeIterator->Next(&displayMode) == S_OK) { CFStringRef displayModeString; result = displayMode->GetName(&displayModeString); if (result == S_OK) { char modeName[64]; int modeWidth; int modeHeight; BMDTimeValue frameRateDuration; BMDTimeScale frameRateScale; int pixelFormatIndex = 0; // index into the gKnownPixelFormats / gKnownFormatNames arrays BMDDisplayModeSupport displayModeSupport; // Obtain the display mode's properties modeWidth = displayMode->GetWidth(); modeHeight = displayMode->GetHeight(); displayMode->GetFrameRate(&frameRateDuration, &frameRateScale); printf(" %-20s \t %d x %d \t %7g FPS\t", displayModeString, modeWidth, modeHeight, (double)frameRateScale / (double)frameRateDuration); // Print the supported pixel formats for this display mode while ((gKnownPixelFormats[pixelFormatIndex] != 0) && (gKnownPixelFormatNames[pixelFormatIndex] != NULL)) { if ((deckLinkOutput->DoesSupportVideoMode(displayMode->GetDisplayMode(), gKnownPixelFormats[pixelFormatIndex], bmdVideoOutputFlagDefault, &displayModeSupport, NULL) == S_OK) && (displayModeSupport != bmdDisplayModeNotSupported)) { printf("%s\t", gKnownPixelFormatNames[pixelFormatIndex]); } pixelFormatIndex++; } printf("\n"); // free(displayModeString); } // Release the IDeckLinkDisplayMode object to prevent a leak displayMode->Release(); } printf("\n"); bail: // Ensure that the interfaces we obtained are released to prevent a memory leak if (displayModeIterator != NULL) displayModeIterator->Release(); if (deckLinkOutput != NULL) deckLinkOutput->Release(); }
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, decklink_direction_t direction, int num) { struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; BMDDisplayModeSupport support; IDeckLinkDisplayModeIterator *itermode; IDeckLinkDisplayMode *mode; int i = 1; HRESULT res; if (direction == DIRECTION_IN) { res = ctx->dli->GetDisplayModeIterator (&itermode); } else { res = ctx->dlo->GetDisplayModeIterator (&itermode); } if (res!= S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n"); return AVERROR(EIO); } if (tb_num == 1) { tb_num *= 1000; tb_den *= 1000; } ctx->bmd_mode = bmdModeUnknown; while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) { BMDTimeValue bmd_tb_num, bmd_tb_den; int bmd_width = mode->GetWidth(); int bmd_height = mode->GetHeight(); mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den); if ((bmd_width == width && bmd_height == height && bmd_tb_num == tb_num && bmd_tb_den == tb_den) || i == num) { ctx->bmd_mode = mode->GetDisplayMode(); ctx->bmd_width = bmd_width; ctx->bmd_height = bmd_height; ctx->bmd_tb_den = bmd_tb_den; ctx->bmd_tb_num = bmd_tb_num; ctx->bmd_field_dominance = mode->GetFieldDominance(); av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n", bmd_width, bmd_height, (float)bmd_tb_den/(float)bmd_tb_num, (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":""); } mode->Release(); i++; } itermode->Release(); if (ctx->bmd_mode == bmdModeUnknown) return -1; if (direction == DIRECTION_IN) { if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } else { if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } if (support == bmdDisplayModeSupported) return 0; return -1; }
/** * process the arugments * return negative value of failed */ int Window::processArguments(int argc, char* argv[]){ IDeckLinkAttributes *deckLinkAttributes = NULL; DeckLinkCaptureDelegate *delegate; IDeckLinkDisplayMode *displayMode; BMDVideoInputFlags inputFlags = 0; BMDDisplayMode selectedDisplayMode = bmdModeNTSC; BMDPixelFormat pixelFormat = bmdFormat8BitYUV; int displayModeCount = 0; int exitStatus = 1; int ch; bool foundDisplayMode = false; HRESULT result; int dnum = 0; IDeckLink *tempLink = NULL; int found = 0; bool supported = 0; int64_t ports; int itemCount; int vinput = 0; int64_t vport = 0; IDeckLinkConfiguration *deckLinkConfiguration = NULL; bool flickerremoval = true; bool pnotpsf = true; // Parse command line options while ((ch = getopt(argc, argv, "?h3c:d:s:f:a:m:n:p:t:u::vi:jy")) != -1) { switch (ch) { case 'i': vinput = atoi(optarg); break; case 'd': card = atoi(optarg); break; case 'm': g_videoModeIndex = atoi(optarg); break; case 'n': g_maxFrames = atoi(optarg); break; case '3': inputFlags |= bmdVideoInputDualStream3D; break; case 'p': switch(atoi(optarg)) { case 0: pixelFormat = bmdFormat8BitYUV; break; case 1: pixelFormat = bmdFormat10BitYUV; break; case 2: pixelFormat = bmdFormat10BitRGB; break; default: fprintf(stderr, "Invalid argument: Pixel format %d is not valid", atoi(optarg)); exit(1); } break; case 't': if (!strcmp(optarg, "rp188")) g_timecodeFormat = bmdTimecodeRP188Any; else if (!strcmp(optarg, "vitc")) g_timecodeFormat = bmdTimecodeVITC; else if (!strcmp(optarg, "serial")) g_timecodeFormat = bmdTimecodeSerial; else { fprintf(stderr, "Invalid argument: Timecode format \"%s\" is invalid\n", optarg); exit(1); } break; case '?': case 'h': usage(); } } if (!deckLinkIterator) { fprintf(stderr, "This application requires the DeckLink drivers installed.\n"); return -1; } /* Connect to the first DeckLink instance */ while (deckLinkIterator->Next(&tempLink) == S_OK) { if (card != dnum) { dnum++; // Release the IDeckLink instance when we've finished with it to prevent leaks tempLink->Release(); continue; } else { deckLink = tempLink; found = 1; } dnum++; } if (! found ) { fprintf(stderr, "No DeckLink PCI cards found.\n"); return -1; } if (deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput) != S_OK) return -1; // Query the DeckLink for its attributes interface result = deckLink->QueryInterface(IID_IDeckLinkAttributes, (void**)&deckLinkAttributes); if (result != S_OK) { fprintf(stderr, "Could not obtain the IDeckLinkAttributes interface - result = %08x\n", result); } result = deckLinkAttributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &supported); if (result == S_OK) { fprintf(stderr, " %-40s %s\n", "Input mode detection supported ?", (supported == true) ? "Yes" : "No"); } else { fprintf(stderr, "Could not query the input mode detection attribute- result = %08x\n", result); } fprintf(stderr, "Supported video input connections (-i [input #]:\n "); itemCount = 0; result = deckLinkAttributes->GetInt(BMDDeckLinkVideoInputConnections, &ports); if (result == S_OK) { if (ports & bmdVideoConnectionSDI) { fprintf(stderr, "%d: SDI, ", bmdVideoConnectionSDI); itemCount++; } if (ports & bmdVideoConnectionHDMI) { fprintf(stderr, "%d: HDMI, ", bmdVideoConnectionHDMI); itemCount++; } if (ports & bmdVideoConnectionOpticalSDI) { fprintf(stderr, "%d: Optical SDI, ", bmdVideoConnectionOpticalSDI); itemCount++; } if (ports & bmdVideoConnectionComponent) { fprintf(stderr, "%d: Component, ", bmdVideoConnectionComponent); itemCount++; } if (ports & bmdVideoConnectionComposite) { fprintf(stderr, "%d: Composite, ", bmdVideoConnectionComposite); itemCount++; } if (ports & bmdVideoConnectionSVideo) { fprintf(stderr, "%d: S-Video, ", bmdVideoConnectionSVideo); itemCount++; } } fprintf(stderr, "\n"); //glWidget->initShaderProgram(); delegate = new DeckLinkCaptureDelegate(glWidget); connect(delegate, SIGNAL(updateGLSignal()), glWidget, SLOT(updateGLSlot())); deckLinkInput->SetCallback(delegate); // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output result = deckLinkInput->GetDisplayModeIterator(&displayModeIterator); if (result != S_OK) { fprintf(stderr, "Could not obtain the video output display mode iterator - result = %08x\n", result); return -1; } if (g_videoModeIndex < 0) { fprintf(stderr, "No video mode specified\n"); usage(); return -1; } while (displayModeIterator->Next(&displayMode) == S_OK) { if (g_videoModeIndex == displayModeCount) { BMDDisplayModeSupport result; const char *displayModeName; foundDisplayMode = true; displayMode->GetName(&displayModeName); selectedDisplayMode = displayMode->GetDisplayMode(); deckLinkInput->DoesSupportVideoMode(selectedDisplayMode, pixelFormat, bmdVideoInputFlagDefault, &result, NULL); if (result == bmdDisplayModeNotSupported) { fprintf(stderr, "The display mode %s is not supported with the selected pixel format\n", displayModeName); return -1; } if (inputFlags & bmdVideoInputDualStream3D) { if (!(displayMode->GetFlags() & bmdDisplayModeSupports3D)) { fprintf(stderr, "The display mode %s is not supported with 3D\n", displayModeName); return -1; } } fprintf(stderr, "Selecting mode: %s\n", displayModeName); break; } displayModeCount++; displayMode->Release(); } if (!foundDisplayMode) { fprintf(stderr, "Invalid mode %d specified\n", g_videoModeIndex); return -1; } // Query the DeckLink for its configuration interface result = deckLinkInput->QueryInterface(IID_IDeckLinkConfiguration, (void**)&deckLinkConfiguration); if (result != S_OK) { fprintf(stderr, "Could not obtain the IDeckLinkConfiguration interface: %08x\n", result); } BMDVideoConnection conn; switch (vinput) { case 0: conn = bmdVideoConnectionSDI; break; case 1: conn = bmdVideoConnectionHDMI; break; case 2: conn = bmdVideoConnectionComponent; break; case 3: conn = bmdVideoConnectionComposite; break; case 4: conn = bmdVideoConnectionSVideo; break; case 5: conn = bmdVideoConnectionOpticalSDI; break; default: break; } conn = vinput; // Set the input desired result = deckLinkConfiguration->SetInt(bmdDeckLinkConfigVideoInputConnection, conn); if(result != S_OK) { fprintf(stderr, "Cannot set the input to [%d]\n", conn); return -1; } // check input result = deckLinkConfiguration->GetInt(bmdDeckLinkConfigVideoInputConnection, &vport); if (vport == bmdVideoConnectionSDI) fprintf(stderr, "Before Input configured for SDI\n"); if (vport == bmdVideoConnectionHDMI) fprintf(stderr, "Before Input configured for HDMI\n"); if (deckLinkConfiguration->SetFlag(bmdDeckLinkConfigFieldFlickerRemoval, flickerremoval) == S_OK) { fprintf(stderr, "Flicker removal set : %d\n", flickerremoval); } else { fprintf(stderr, "Flicker removal NOT set\n"); } if (deckLinkConfiguration->SetFlag(bmdDeckLinkConfigUse1080pNotPsF, pnotpsf) == S_OK) { fprintf(stderr, "bmdDeckLinkConfigUse1080pNotPsF: %d\n", pnotpsf); } else { fprintf(stderr, "bmdDeckLinkConfigUse1080pNotPsF NOT set\n"); } //if (deckLinkConfiguration->SetFlag(bmdDeckLinkConfigVideoInputConnection, conn) == S_OK) { //fprintf(stderr, "Input set to: %d\n", vinput); //} result = deckLinkConfiguration->GetInt(bmdDeckLinkConfigVideoInputConnection, &vport); if (vport == bmdVideoConnectionSDI) fprintf(stderr, "After Input configured for SDI\n"); if (vport == bmdVideoConnectionHDMI) fprintf(stderr, "After Input configured for HDMI\n"); result = deckLinkInput->EnableVideoInput(selectedDisplayMode, pixelFormat, inputFlags); if(result != S_OK) { fprintf(stderr, "Failed to enable video input. Is another application using the card?\n"); return -1; } displayWidth = displayMode->GetWidth(); displayHeight = displayMode->GetHeight(); displayMode->GetFrameRate(&frameRateDuration, &frameRateScale); displayFPS = (double)frameRateScale / (double)frameRateDuration; //set to delegate delegate->setWidth(displayWidth); delegate->setHeight(displayHeight); delegate->setFPS(displayFPS); delegate->setFrameRateDuration(frameRateDuration); delegate->setFrameRateScale(frameRateScale); //set texture width and height glWidget->setTextureWidth(displayWidth); glWidget->setTextureHeight(displayHeight); glWidget->initBuffer(); fprintf(stderr, "GetFrameRate: %10ld %10ld --> fps %g\n", (long)frameRateScale, (long)frameRateDuration, displayFPS); result = deckLinkInput->StartStreams(); if(result != S_OK){ fprintf(stderr, "Cannot start streams...\n"); return -1; } fprintf(stderr, "Finish procesing arguments \n"); }
void CSignalGeneratorDlg::StartRunning () { IDeckLinkDisplayMode* videoDisplayMode = NULL; BMDVideoOutputFlags videoOutputFlags = bmdVideoOutputFlagDefault; int curSelection; CString videoFormatName; curSelection = m_videoFormatCombo.GetCurSel(); m_videoFormatCombo.GetLBText(curSelection, videoFormatName); if (videoFormatName.Find(_T(" 3D"), 0) != -1) videoOutputFlags = bmdVideoOutputDualStream3D; // Determine the audio and video properties for the output stream m_outputSignal = (OutputSignal)m_outputSignalCombo.GetCurSel(); m_audioChannelCount = m_audioChannelCombo.GetItemData(m_audioChannelCombo.GetCurSel()); m_audioSampleDepth = (BMDAudioSampleType)m_audioSampleDepthCombo.GetItemData(m_audioSampleDepthCombo.GetCurSel()); m_audioSampleRate = bmdAudioSampleRate48kHz; // // - Extract the IDeckLinkDisplayMode from the display mode popup menu (stashed in the item's tag) videoDisplayMode = (IDeckLinkDisplayMode*)m_videoFormatCombo.GetItemDataPtr(m_videoFormatCombo.GetCurSel()); m_frameWidth = videoDisplayMode->GetWidth(); m_frameHeight = videoDisplayMode->GetHeight(); videoDisplayMode->GetFrameRate(&m_frameDuration, &m_frameTimescale); // Calculate the number of frames per second, rounded up to the nearest integer. For example, for NTSC (29.97 FPS), framesPerSecond == 30. m_framesPerSecond = (unsigned long)((m_frameTimescale + (m_frameDuration-1)) / m_frameDuration); // Set the video output mode if (m_deckLinkOutput->EnableVideoOutput(videoDisplayMode->GetDisplayMode(), videoOutputFlags) != S_OK) goto bail; // Set the audio output mode if (m_deckLinkOutput->EnableAudioOutput(bmdAudioSampleRate48kHz, m_audioSampleDepth, m_audioChannelCount, bmdAudioOutputStreamTimestamped) != S_OK) goto bail; // Generate one second of audio tone m_audioSamplesPerFrame = (unsigned long)((m_audioSampleRate * m_frameDuration) / m_frameTimescale); m_audioBufferSampleLength = (unsigned long)((m_framesPerSecond * m_audioSampleRate * m_frameDuration) / m_frameTimescale); m_audioBuffer = HeapAlloc(GetProcessHeap(), 0, (m_audioBufferSampleLength * m_audioChannelCount * (m_audioSampleDepth / 8))); if (m_audioBuffer == NULL) goto bail; FillSine(m_audioBuffer, m_audioBufferSampleLength, m_audioChannelCount, m_audioSampleDepth); // Generate a frame of black m_videoFrameBlack = CreateBlackFrame(); if (! m_videoFrameBlack) goto bail; // Generate a frame of colour bars m_videoFrameBars = CreateBarsFrame(); if (! m_videoFrameBars) goto bail; // Begin video preroll by scheduling a second of frames in hardware m_totalFramesScheduled = 0; for (unsigned i = 0; i < m_framesPerSecond; i++) ScheduleNextFrame(true); // Begin audio preroll. This will begin calling our audio callback, which will start the DeckLink output stream. m_totalAudioSecondsScheduled = 0; if (m_deckLinkOutput->BeginAudioPreroll() != S_OK) goto bail; // Success; update the UI m_running = true; m_startButton.SetWindowText(_T("Stop")); // Disable the user interface while running (prevent the user from making changes to the output signal) EnableInterface(FALSE); return; bail: // *** Error-handling code. Cleanup any resources that were allocated. *** // StopRunning(); }
// Prepare IDeckLinkInput to capture video: // - Get frame width, height, duration, ... // - Setup callback object and video mode and // - Start streams bool CaptureHelper::setupDeckLinkInput() { bool result = false; IDeckLinkDisplayModeIterator* displayModeIterator = NULL; IDeckLinkDisplayMode* deckLinkDisplayMode = NULL; m_width = -1; // get frame scale and duration for the video mode if (m_deckLinkInput->GetDisplayModeIterator(&displayModeIterator) != S_OK) goto bail; while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK) { if (deckLinkDisplayMode->GetDisplayMode() == BMD_DISPLAYMODE) { m_width = deckLinkDisplayMode->GetWidth(); m_height = deckLinkDisplayMode->GetHeight(); deckLinkDisplayMode->GetFrameRate(&m_frameDuration, &m_timeScale); deckLinkDisplayMode->Release(); break; } deckLinkDisplayMode->Release(); } displayModeIterator->Release(); if (m_width == -1) { printf("Unable to find requested video mode\n"); goto bail; } // convert the in- and out-point timecodes to a frame count GET_FRAME_COUNT(m_inPointFrameCount, START_TC, m_timeScale, m_frameDuration); GET_FRAME_COUNT(m_outPointFrameCount, STOP_TC, m_timeScale, m_frameDuration); // set callback m_deckLinkInput->SetCallback(this); // enable video input if (m_deckLinkInput->EnableVideoInput(BMD_DISPLAYMODE, PIXEL_FMT, bmdVideoInputFlagDefault) != S_OK) { printf("Could not enable video input\n"); goto bail; } // start streaming if (m_deckLinkInput->StartStreams() != S_OK) { printf("Could not start streams\n"); goto bail; } result = true; bail: return result; }
static int Open(vlc_object_t *p_this) { demux_t *demux = (demux_t*)p_this; demux_sys_t *sys; int ret = VLC_EGENERIC; int card_index; int physical_channels = 0; int rate; BMDVideoInputFlags flags = bmdVideoInputFlagDefault; /* Only when selected */ if (*demux->psz_access == '\0') return VLC_EGENERIC; /* Set up demux */ demux->pf_demux = NULL; demux->pf_control = Control; demux->info.i_update = 0; demux->info.i_title = 0; demux->info.i_seekpoint = 0; demux->p_sys = sys = (demux_sys_t*)calloc(1, sizeof(demux_sys_t)); if (!sys) return VLC_ENOMEM; vlc_mutex_init(&sys->pts_lock); sys->tenbits = var_InheritBool(p_this, "decklink-tenbits"); IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance(); if (!decklink_iterator) { msg_Err(demux, "DeckLink drivers not found."); goto finish; } card_index = var_InheritInteger(demux, "decklink-card-index"); if (card_index < 0) { msg_Err(demux, "Invalid card index %d", card_index); goto finish; } for (int i = 0; i <= card_index; i++) { if (sys->card) sys->card->Release(); if (decklink_iterator->Next(&sys->card) != S_OK) { msg_Err(demux, "DeckLink PCI card %d not found", card_index); goto finish; } } const char *model_name; if (sys->card->GetModelName(&model_name) != S_OK) model_name = "unknown"; msg_Dbg(demux, "Opened DeckLink PCI card %d (%s)", card_index, model_name); if (sys->card->QueryInterface(IID_IDeckLinkInput, (void**)&sys->input) != S_OK) { msg_Err(demux, "Card has no inputs"); goto finish; } /* Set up the video and audio sources. */ if (sys->card->QueryInterface(IID_IDeckLinkConfiguration, (void**)&sys->config) != S_OK) { msg_Err(demux, "Failed to get configuration interface"); goto finish; } if (sys->card->QueryInterface(IID_IDeckLinkAttributes, (void**)&sys->attributes) != S_OK) { msg_Err(demux, "Failed to get attributes interface"); goto finish; } if (GetVideoConn(demux) || GetAudioConn(demux)) goto finish; BMDPixelFormat fmt; fmt = sys->tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV; if (sys->attributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &sys->autodetect) != S_OK) { msg_Err(demux, "Failed to query card attribute"); goto finish; } /* Get the list of display modes. */ IDeckLinkDisplayModeIterator *mode_it; if (sys->input->GetDisplayModeIterator(&mode_it) != S_OK) { msg_Err(demux, "Failed to enumerate display modes"); goto finish; } union { BMDDisplayMode id; char str[4]; } u; u.id = 0; char *mode; mode = var_CreateGetNonEmptyString(demux, "decklink-mode"); if (mode) sys->autodetect = false; // disable autodetection if mode was set if (sys->autodetect) { msg_Dbg(demux, "Card supports input format detection"); flags |= bmdVideoInputEnableFormatDetection; /* Enable a random format, we will reconfigure on format detection */ u.id = htonl(bmdModeHD1080p2997); } else { if (!mode || strlen(mode) < 3 || strlen(mode) > 4) { msg_Err(demux, "Invalid mode: \'%s\'", mode ? mode : ""); free(mode); goto finish; } msg_Dbg(demux, "Looking for mode \'%s\'", mode); memcpy(u.str, mode, 4); if (u.str[3] == '\0') u.str[3] = ' '; /* 'pal'\0 -> 'pal ' */ free(mode); } es_format_t video_fmt; video_fmt.video.i_width = 0; for (IDeckLinkDisplayMode *m;; m->Release()) { if ((mode_it->Next(&m) != S_OK) || !m) break; const char *mode_name; BMDTimeValue frame_duration, time_scale; uint32_t field_flags; const char *field = GetFieldDominance(m->GetFieldDominance(), &field_flags); BMDDisplayMode id = ntohl(m->GetDisplayMode()); if (m->GetName(&mode_name) != S_OK) mode_name = "unknown"; if (m->GetFrameRate(&frame_duration, &time_scale) != S_OK) { time_scale = 0; frame_duration = 1; } msg_Dbg(demux, "Found mode '%4.4s': %s (%dx%d, %.3f fps%s)", (char*)&id, mode_name, (int)m->GetWidth(), (int)m->GetHeight(), double(time_scale) / frame_duration, field); if (u.id == id) { video_fmt = GetModeSettings(demux, m); msg_Dbg(demux, "Using that mode"); } } mode_it->Release(); if (video_fmt.video.i_width == 0) { msg_Err(demux, "Unknown video mode `%4.4s\' specified.", (char*)&u.id); goto finish; } if (sys->input->EnableVideoInput(htonl(u.id), fmt, flags) != S_OK) { msg_Err(demux, "Failed to enable video input"); goto finish; } /* Set up audio. */ sys->channels = var_InheritInteger(demux, "decklink-audio-channels"); switch (sys->channels) { case 0: break; case 2: physical_channels = AOUT_CHANS_STEREO; break; case 8: physical_channels = AOUT_CHANS_7_1; break; //case 16: default: msg_Err(demux, "Invalid number of channels (%d), disabling audio", sys->channels); sys->channels = 0; } rate = var_InheritInteger(demux, "decklink-audio-rate"); if (rate > 0 && sys->channels > 0) { if (sys->input->EnableAudioInput(rate, bmdAudioSampleType16bitInteger, sys->channels) != S_OK) { msg_Err(demux, "Failed to enable audio input"); goto finish; } } sys->delegate = new DeckLinkCaptureDelegate(demux); sys->input->SetCallback(sys->delegate); if (sys->input->StartStreams() != S_OK) { msg_Err(demux, "Could not start streaming from SDI card. This could be caused " "by invalid video mode or flags, access denied, or card already in use."); goto finish; } msg_Dbg(demux, "added new video es %4.4s %dx%d", (char*)&video_fmt.i_codec, video_fmt.video.i_width, video_fmt.video.i_height); sys->video_es = es_out_Add(demux->out, &video_fmt); es_format_t audio_fmt; es_format_Init(&audio_fmt, AUDIO_ES, VLC_CODEC_S16N); audio_fmt.audio.i_channels = sys->channels; audio_fmt.audio.i_physical_channels = physical_channels; audio_fmt.audio.i_rate = rate; audio_fmt.audio.i_bitspersample = 16; audio_fmt.audio.i_blockalign = audio_fmt.audio.i_channels * audio_fmt.audio.i_bitspersample / 8; audio_fmt.i_bitrate = audio_fmt.audio.i_channels * audio_fmt.audio.i_rate * audio_fmt.audio.i_bitspersample; msg_Dbg(demux, "added new audio es %4.4s %dHz %dbpp %dch", (char*)&audio_fmt.i_codec, audio_fmt.audio.i_rate, audio_fmt.audio.i_bitspersample, audio_fmt.audio.i_channels); sys->audio_es = es_out_Add(demux->out, &audio_fmt); ret = VLC_SUCCESS; finish: if (decklink_iterator) decklink_iterator->Release(); if (ret != VLC_SUCCESS) Close(p_this); return ret; }
bool OpenGLComposite::InitDeckLink() { bool bSuccess = false; IDeckLinkIterator* pDLIterator = NULL; IDeckLink* pDL = NULL; IDeckLinkDisplayModeIterator* pDLDisplayModeIterator = NULL; IDeckLinkDisplayMode* pDLDisplayMode = NULL; BMDDisplayMode displayMode = bmdModeHD1080i5994; // mode to use for capture and playout float fps; HRESULT result; result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&pDLIterator); if (FAILED(result)) { MessageBox(NULL, _T("Please install the Blackmagic DeckLink drivers to use the features of this application."), _T("This application requires the DeckLink drivers installed."), MB_OK); return false; } while (pDLIterator->Next(&pDL) == S_OK) { // Use first board found as capture device, second board will be playout device if (! mDLInput) { if (pDL->QueryInterface(IID_IDeckLinkInput, (void**)&mDLInput) != S_OK) goto error; } else if (! mDLOutput) { if (pDL->QueryInterface(IID_IDeckLinkOutput, (void**)&mDLOutput) != S_OK) goto error; } } if (! mDLOutput || ! mDLInput) { MessageBox(NULL, _T("Expected both Input and Output DeckLink devices"), _T("This application requires two DeckLink devices."), MB_OK); goto error; } if (mDLOutput->GetDisplayModeIterator(&pDLDisplayModeIterator) != S_OK) { MessageBox(NULL, _T("Cannot get Display Mode Iterator."), _T("DeckLink error."), MB_OK); goto error; } while (pDLDisplayModeIterator->Next(&pDLDisplayMode) == S_OK) { if (pDLDisplayMode->GetDisplayMode() == displayMode) break; pDLDisplayMode->Release(); pDLDisplayMode = NULL; } pDLDisplayModeIterator->Release(); if (pDLDisplayMode == NULL) { MessageBox(NULL, _T("Cannot get specified BMDDisplayMode."), _T("DeckLink error."), MB_OK); goto error; } mFrameWidth = pDLDisplayMode->GetWidth(); mFrameHeight = pDLDisplayMode->GetHeight(); if (! CheckOpenGLExtensions()) goto error; if (! InitOpenGLState()) goto error; // Compute a rotate angle rate so box will spin at a rate independent of video mode frame rate pDLDisplayMode->GetFrameRate(&mFrameDuration, &mFrameTimescale); fps = (float)mFrameTimescale / (float)mFrameDuration; mRotateAngleRate = 35.0f / fps; // rotate box through 35 degrees every second // Resize window to match video frame, but scale large formats down by half for viewing if (mFrameWidth < 1920) resizeWindow(mFrameWidth, mFrameHeight); else resizeWindow(mFrameWidth / 2, mFrameHeight / 2); if (mFastTransferExtensionAvailable) { // Initialize fast video frame transfers if (! VideoFrameTransfer::initialize(mFrameWidth, mFrameHeight, mCaptureTexture, mFBOTexture)) { MessageBox(NULL, _T("Cannot initialize video transfers."), _T("VideoFrameTransfer error."), MB_OK); goto error; } } // Capture will use a user-supplied frame memory allocator mCaptureAllocator = new PinnedMemoryAllocator(hGLDC, hGLRC, VideoFrameTransfer::CPUtoGPU, 3); if (mDLInput->SetVideoInputFrameMemoryAllocator(mCaptureAllocator) != S_OK) goto error; if (mDLInput->EnableVideoInput(displayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault) != S_OK) goto error; mCaptureDelegate = new CaptureDelegate(this); if (mDLInput->SetCallback(mCaptureDelegate) != S_OK) goto error; // Playout will use a user-supplied frame memory allocator mPlayoutAllocator = new PinnedMemoryAllocator(hGLDC, hGLRC, VideoFrameTransfer::GPUtoCPU, 1); if (mDLOutput->SetVideoOutputFrameMemoryAllocator(mPlayoutAllocator) != S_OK) goto error; if (mDLOutput->EnableVideoOutput(displayMode, bmdVideoOutputFlagDefault) != S_OK) goto error; // Create a queue of 10 IDeckLinkMutableVideoFrame objects to use for scheduling output video frames. // The ScheduledFrameCompleted() callback will immediately schedule a new frame using the next video frame from this queue. for (int i = 0; i < 10; i++) { // The frame read back from the GPU frame buffer and used for the playout video frame is in BGRA format. // The BGRA frame will be converted on playout to YCbCr either in hardware on most DeckLink cards or in software // within the DeckLink API for DeckLink devices without this hardware conversion. // If you want RGB 4:4:4 format to be played out "over the wire" in SDI, turn on the "Use 4:4:4 SDI" in the control // panel or turn on the bmdDeckLinkConfig444SDIVideoOutput flag using the IDeckLinkConfiguration interface. IDeckLinkMutableVideoFrame* outputFrame; if (mDLOutput->CreateVideoFrame(mFrameWidth, mFrameHeight, mFrameWidth*4, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, &outputFrame) != S_OK) goto error; mDLOutputVideoFrameQueue.push_back(outputFrame); } mPlayoutDelegate = new PlayoutDelegate(this); if (mPlayoutDelegate == NULL) goto error; if (mDLOutput->SetScheduledFrameCompletionCallback(mPlayoutDelegate) != S_OK) goto error; bSuccess = true; error: if (!bSuccess) { if (mDLInput != NULL) { mDLInput->Release(); mDLInput = NULL; } if (mDLOutput != NULL) { mDLOutput->Release(); mDLOutput = NULL; } } if (pDL != NULL) { pDL->Release(); pDL = NULL; } if (pDLIterator != NULL) { pDLIterator->Release(); pDLIterator = NULL; } return bSuccess; }
bool BMDOpenGLOutput::Start() { IDeckLinkDisplayModeIterator* pDLDisplayModeIterator; IDeckLinkDisplayMode* pDLDisplayMode = NULL; // Get first avaliable video mode for Output if (pDLOutput->GetDisplayModeIterator(&pDLDisplayModeIterator) == S_OK) { if (pDLDisplayModeIterator->Next(&pDLDisplayMode) != S_OK) { QMessageBox::critical(NULL,"DeckLink error.", "Cannot find video mode."); pDLDisplayModeIterator->Release(); return false; } pDLDisplayModeIterator->Release(); } uiFrameWidth = pDLDisplayMode->GetWidth(); uiFrameHeight = pDLDisplayMode->GetHeight(); pDLDisplayMode->GetFrameRate(&frameDuration, &frameTimescale); uiFPS = ((frameTimescale + (frameDuration-1)) / frameDuration); if (pDLOutput->EnableVideoOutput(pDLDisplayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) != S_OK) return false; // Flip frame vertical, because OpenGL rendering starts from left bottom corner if (pDLOutput->CreateVideoFrame(uiFrameWidth, uiFrameHeight, uiFrameWidth*4, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, &pDLVideoFrame) != S_OK) return false; uiTotalFrames = 0; ResetFrame(); SetPreroll(); pContext->makeCurrent(); pGLScene->InitScene(); glGenFramebuffersEXT(1, &idFrameBuf); glGenRenderbuffersEXT(1, &idColorBuf); glGenRenderbuffersEXT(1, &idDepthBuf); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, idFrameBuf); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, idColorBuf); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, uiFrameWidth, uiFrameHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, idDepthBuf); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, uiFrameWidth, uiFrameHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, idColorBuf); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, idDepthBuf); glStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (glStatus != GL_FRAMEBUFFER_COMPLETE_EXT) { QMessageBox::critical(NULL,"OpenGL initialization error.", "Cannot initialize framebuffer."); return false; } pFrameBuf = (char*)malloc(pDLVideoFrame->GetRowBytes() * uiFrameHeight); UpdateScene(); pDLOutput->StartScheduledPlayback(0, 100, 1.0); return true; }
int main(int argc, char *argv[]) { HRESULT result; int exitStatus = 1; int idx; IDeckLinkIterator* deckLinkIterator = NULL; IDeckLink* deckLink = NULL; IDeckLinkAttributes* deckLinkAttributes = NULL; bool formatDetectionSupported; IDeckLinkDisplayModeIterator* displayModeIterator = NULL; IDeckLinkDisplayMode* displayMode = NULL; char* displayModeName = NULL; BMDDisplayModeSupport displayModeSupported; DeckLinkCaptureDelegate* delegate = NULL; pthread_mutex_init(&g_sleepMutex, NULL); pthread_cond_init(&g_sleepCond, NULL); signal(SIGINT, sigfunc); signal(SIGTERM, sigfunc); signal(SIGHUP, sigfunc); // Network g_video_sock = socket(AF_INET, SOCK_STREAM, 0); g_video_addr.sin_family = AF_INET; g_video_addr.sin_port = htons(62310); g_video_addr.sin_addr.s_addr = inet_addr("192.168.100.31"); connect(g_video_sock, (struct sockaddr *)&g_video_addr, sizeof(g_video_addr)); g_audio_sock = socket(AF_INET, SOCK_STREAM, 0); g_audio_addr.sin_family = AF_INET; g_audio_addr.sin_port = htons(62311); g_audio_addr.sin_addr.s_addr = inet_addr("192.168.100.31"); connect(g_audio_sock, (struct sockaddr *)&g_audio_addr, sizeof(g_audio_addr)); // Process the command line arguments if (!g_config.ParseArguments(argc, argv)) { g_config.DisplayUsage(exitStatus); goto bail; } // Get the DeckLink device deckLinkIterator = CreateDeckLinkIteratorInstance(); if (!deckLinkIterator) { fprintf(stderr, "This application requires the DeckLink drivers installed.\n"); goto bail; } idx = g_config.m_deckLinkIndex; while ((result = deckLinkIterator->Next(&deckLink)) == S_OK) { if (idx == 0) break; --idx; deckLink->Release(); } if (result != S_OK || deckLink == NULL) { fprintf(stderr, "Unable to get DeckLink device %u\n", g_config.m_deckLinkIndex); goto bail; } // Get the input (capture) interface of the DeckLink device result = deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&g_deckLinkInput); if (result != S_OK) goto bail; // Get the display mode if (g_config.m_displayModeIndex == -1) { // Check the card supports format detection result = deckLink->QueryInterface(IID_IDeckLinkAttributes, (void**)&deckLinkAttributes); if (result == S_OK) { result = deckLinkAttributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &formatDetectionSupported); if (result != S_OK || !formatDetectionSupported) { fprintf(stderr, "Format detection is not supported on this device\n"); goto bail; } } 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(&displayModeIterator); if (result != S_OK) { goto bail; } while ((result = displayModeIterator->Next(&displayMode)) == S_OK) { if (idx == 0) { break; } --idx; displayMode->Release(); } if (result != S_OK || displayMode == NULL) { fprintf(stderr, "Unable to get display mode %d\n", g_config.m_displayModeIndex); goto bail; } // Get display mode name result = displayMode->GetName((const char**)&displayModeName); if (result != S_OK) { displayModeName = (char *)malloc(32); snprintf(displayModeName, 32, "[index %d]", g_config.m_displayModeIndex); } // Check display mode is supported with given options result = g_deckLinkInput->DoesSupportVideoMode(displayMode->GetDisplayMode(), g_config.m_pixelFormat, bmdVideoInputFlagDefault, &displayModeSupported, NULL); if (result != S_OK) goto bail; if (displayModeSupported == bmdDisplayModeNotSupported) { fprintf(stderr, "The display mode %s is not supported with the selected pixel format\n", displayModeName); goto bail; } if (g_config.m_inputFlags & bmdVideoInputDualStream3D) { if (!(displayMode->GetFlags() & bmdDisplayModeSupports3D)) { fprintf(stderr, "The display mode %s is not supported with 3D\n", displayModeName); goto bail; } } // Print the selected configuration g_config.DisplayConfiguration(); // Configure the capture callback delegate = new DeckLinkCaptureDelegate(); g_deckLinkInput->SetCallback(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); // goto bail; // } // } // // 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); // goto bail; // } // } // Block main thread until signal occurs while (!g_do_exit) { // Start capturing result = g_deckLinkInput->EnableVideoInput(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"); goto bail; } result = g_deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz, g_config.m_audioSampleDepth, g_config.m_audioChannels); if (result != S_OK) goto bail; result = g_deckLinkInput->StartStreams(); if (result != S_OK) goto bail; // 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"); g_deckLinkInput->StopStreams(); g_deckLinkInput->DisableAudioInput(); g_deckLinkInput->DisableVideoInput(); } bail: if (g_videoOutputFile != 0) close(g_videoOutputFile); if (g_audioOutputFile != 0) close(g_audioOutputFile); if (displayModeName != NULL) free(displayModeName); if (displayMode != NULL) displayMode->Release(); if (displayModeIterator != NULL) displayModeIterator->Release(); if (g_deckLinkInput != NULL) { g_deckLinkInput->Release(); g_deckLinkInput = NULL; } if (deckLinkAttributes != NULL) deckLinkAttributes->Release(); if (deckLink != NULL) deckLink->Release(); if (deckLinkIterator != NULL) deckLinkIterator->Release(); close(g_video_sock); close(g_audio_sock); return exitStatus; }
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction, int num) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; BMDDisplayModeSupport support; IDeckLinkDisplayModeIterator *itermode; IDeckLinkDisplayMode *mode; int i = 1; HRESULT res; av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d, format code %s\n", width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)"); if (direction == DIRECTION_IN) { res = ctx->dli->GetDisplayModeIterator (&itermode); } else { res = ctx->dlo->GetDisplayModeIterator (&itermode); } if (res!= S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n"); return AVERROR(EIO); } char format_buf[] = " "; if (cctx->format_code) memcpy(format_buf, cctx->format_code, FFMIN(strlen(cctx->format_code), sizeof(format_buf))); BMDDisplayMode target_mode = (BMDDisplayMode)AV_RB32(format_buf); AVRational target_tb = av_make_q(tb_num, tb_den); ctx->bmd_mode = bmdModeUnknown; while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) { BMDTimeValue bmd_tb_num, bmd_tb_den; int bmd_width = mode->GetWidth(); int bmd_height = mode->GetHeight(); BMDDisplayMode bmd_mode = mode->GetDisplayMode(); BMDFieldDominance bmd_field_dominance = mode->GetFieldDominance(); mode->GetFrameRate(&bmd_tb_num, &bmd_tb_den); AVRational mode_tb = av_make_q(bmd_tb_num, bmd_tb_den); if ((bmd_width == width && bmd_height == height && !av_cmp_q(mode_tb, target_tb) && field_order_eq(field_order, bmd_field_dominance)) || i == num || target_mode == bmd_mode) { ctx->bmd_mode = bmd_mode; ctx->bmd_width = bmd_width; ctx->bmd_height = bmd_height; ctx->bmd_tb_den = bmd_tb_den; ctx->bmd_tb_num = bmd_tb_num; ctx->bmd_field_dominance = bmd_field_dominance; av_log(avctx, AV_LOG_INFO, "Found Decklink mode %d x %d with rate %.2f%s\n", bmd_width, bmd_height, 1/av_q2d(mode_tb), (ctx->bmd_field_dominance==bmdLowerFieldFirst || ctx->bmd_field_dominance==bmdUpperFieldFirst)?"(i)":""); } mode->Release(); i++; } itermode->Release(); if (ctx->bmd_mode == bmdModeUnknown) return -1; if (direction == DIRECTION_IN) { if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, (BMDPixelFormat) cctx->raw_format, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } else { if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; } if (support == bmdDisplayModeSupported) return 0; return -1; }