void start_video( ) { if (deckLinkOutput->StartScheduledPlayback(0, 100, 1.0) != S_OK) { throw std::runtime_error( "Failed to start scheduled playback!\n" ); } }
IDeckLinkDisplayMode* getDisplayMode() { mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( &m_consumer ) ); IDeckLinkDisplayModeIterator* iter; IDeckLinkDisplayMode* mode; IDeckLinkDisplayMode* result = 0; if ( m_deckLinkOutput->GetDisplayModeIterator( &iter ) == S_OK ) { while ( !result && iter->Next( &mode ) == S_OK ) { m_width = mode->GetWidth(); m_height = mode->GetHeight(); mode->GetFrameRate( &m_duration, &m_timescale ); m_fps = (double) m_timescale / m_duration; int p = mode->GetFieldDominance() == bmdProgressiveFrame; mlt_log_verbose( &m_consumer, "BMD mode %dx%d %.3f fps prog %d\n", m_width, m_height, m_fps, p ); if ( m_width == profile->width && m_height == profile->height && p == profile->progressive && m_fps == mlt_profile_fps( profile ) ) result = mode; } } return result; }
void schedule_frame(IDeckLinkMutableVideoFrame *frame) { RawFrame *input = NULL; void *data; if (in_pipe.data_ready( )) { input = in_pipe.get( ); } else if (last_frame != NULL) { /* use the stale frame */ fprintf(stderr, "DeckLink: stale frame\n"); input = last_frame; } else { /* this should likewise be a black frame */ input = NULL; } if (input != NULL) { frame->GetBytes(&data); input->unpack->CbYCrY8422((uint8_t *) data); } else { fprintf(stderr, "DeckLink: on fire\n"); } deckLinkOutput->ScheduleVideoFrame(frame, frame_counter * frame_duration, frame_duration, time_base); frame_counter++; if (last_frame != input) { delete last_frame; last_frame = input; } }
void createFrame() { m_videoFrame = 0; // Generate a DeckLink video frame if ( S_OK != m_deckLinkOutput->CreateVideoFrame( m_width, m_height, m_width * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &m_videoFrame ) ) { mlt_log_verbose( &m_consumer, "Failed to create video frame\n" ); stop(); return; } // Make the first line black for field order correction. uint8_t *buffer = 0; if ( S_OK == m_videoFrame->GetBytes( (void**) &buffer ) && buffer ) { for ( int i = 0; i < m_width; i++ ) { *buffer++ = 128; *buffer++ = 16; } } mlt_log_debug( &m_consumer, "created video frame\n" ); mlt_deque_push_back( m_videoFrameQ, m_videoFrame ); }
IDeckLinkDisplayMode *BMDOutputDelegate::GetDisplayModeByIndex(int selectedIndex) { // Populate the display mode combo with a list of display modes supported by the installed DeckLink card IDeckLinkDisplayModeIterator* displayModeIterator; IDeckLinkDisplayMode* deckLinkDisplayMode; IDeckLinkDisplayMode* selectedMode = NULL; int index = 0; if (m_deckLinkOutput->GetDisplayModeIterator(&displayModeIterator) != S_OK) goto bail; while (displayModeIterator->Next(&deckLinkDisplayMode) == S_OK) { const char *modeName; if (deckLinkDisplayMode->GetName(&modeName) == S_OK) { if (index == selectedIndex) { printf("Selected mode: %s\n", modeName); selectedMode = deckLinkDisplayMode; goto bail; } } index++; } bail: displayModeIterator->Release(); return selectedMode; }
void stop() { // Stop the audio and video output streams immediately if ( m_deckLinkOutput ) { m_deckLinkOutput->StopScheduledPlayback( 0, 0, 0 ); m_deckLinkOutput->DisableAudioOutput(); m_deckLinkOutput->DisableVideoOutput(); } while ( mlt_deque_count( m_videoFrameQ ) ) { m_videoFrame = (IDeckLinkMutableVideoFrame*) mlt_deque_pop_back( m_videoFrameQ ); m_videoFrame->Release(); } m_videoFrame = 0; if ( m_fifo ) sample_fifo_close( m_fifo ); }
void setup_audio( ) { /* FIXME hard coded default */ n_channels = 2; audio_in_pipe = new Pipe<AudioPacket *>(OUT_PIPE_SIZE); /* FIXME magic 29.97 related number */ /* Set up empty audio packet for prerolling */ current_audio_pkt = new AudioPacket(48000, n_channels, 2, 25626); samples_written_from_current_audio_pkt = 0; assert(deckLinkOutput != NULL); if (deckLinkOutput->SetAudioCallback(this) != S_OK) { throw std::runtime_error( "Failed to set DeckLink audio callback" ); } if (deckLinkOutput->EnableAudioOutput( bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, n_channels, bmdAudioOutputStreamContinuous) != S_OK) { throw std::runtime_error( "Failed to enable DeckLink audio output" ); } audio_preroll_done = 0; if (deckLinkOutput->BeginAudioPreroll( ) != S_OK) { throw std::runtime_error( "Failed to begin DeckLink audio preroll" ); } while (audio_preroll_done == 0) { /* FIXME: busy wait */ } if (deckLinkOutput->EndAudioPreroll( ) != S_OK) { throw std::runtime_error( "Failed to end DeckLink audio preroll" ); } }
~DeckLinkConsumer() { if ( m_deckLinkOutput ) m_deckLinkOutput->Release(); if ( m_deckLink ) m_deckLink->Release(); if ( m_videoFrameQ ) mlt_deque_close( m_videoFrameQ ); }
void BMDOutputDelegate::StopRunning () { // Stop the audio and video output streams immediately m_deckLinkOutput->StopScheduledPlayback(0, NULL, 0); // //m_deckLinkOutput->DisableAudioOutput(); m_deckLinkOutput->DisableVideoOutput(); if (m_yuvFrame != NULL) m_yuvFrame->Release(); m_yuvFrame = NULL; if (m_rgbFrame != NULL) m_rgbFrame->Release(); m_rgbFrame = NULL; // Success; update the UI m_running = false; }
void setup_audio( ) { IOAudioPacket preroll_audio(8008, n_channels); preroll_audio.zero( ); audio_in_pipe = new Pipe<IOAudioPacket *>(OUT_PIPE_SIZE); audio_fifo = new AudioFIFO<int16_t>(n_channels); audio_fifo->add_packet(&preroll_audio); assert(deckLinkOutput != NULL); if (deckLinkOutput->SetAudioCallback(this) != S_OK) { throw std::runtime_error( "Failed to set DeckLink audio callback" ); } if (deckLinkOutput->EnableAudioOutput( bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, n_channels, bmdAudioOutputStreamContinuous) != S_OK) { throw std::runtime_error( "Failed to enable DeckLink audio output" ); } audio_preroll_done = 0; if (deckLinkOutput->BeginAudioPreroll( ) != S_OK) { throw std::runtime_error( "Failed to begin DeckLink audio preroll" ); } while (audio_preroll_done == 0) { /* FIXME: busy wait */ } if (deckLinkOutput->EndAudioPreroll( ) != S_OK) { throw std::runtime_error( "Failed to end DeckLink audio preroll" ); } }
bool open( unsigned card = 0 ) { IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance(); unsigned i = 0; if ( !deckLinkIterator ) { mlt_log_verbose( NULL, "The DeckLink drivers not installed.\n" ); return false; } // Connect to the Nth DeckLink instance do { if ( deckLinkIterator->Next( &m_deckLink ) != S_OK ) { mlt_log_verbose( NULL, "DeckLink card not found\n" ); deckLinkIterator->Release(); return false; } } while ( ++i <= card ); // Obtain the audio/video output interface (IDeckLinkOutput) if ( m_deckLink->QueryInterface( IID_IDeckLinkOutput, (void**)&m_deckLinkOutput ) != S_OK ) { mlt_log_verbose( NULL, "No DeckLink cards support output\n" ); m_deckLink->Release(); m_deckLink = 0; deckLinkIterator->Release(); return false; } // Provide this class as a delegate to the audio and video output interfaces m_deckLinkOutput->SetScheduledFrameCompletionCallback( this ); m_deckLinkOutput->SetAudioCallback( this ); pthread_mutex_init( &m_mutex, NULL ); pthread_cond_init( &m_condition, NULL ); m_maxAudioBuffer = bmdAudioSampleRate48kHz; m_videoFrameQ = mlt_deque_init(); return true; }
/* * Try sending some audio data to the Decklink. * Call only with current_audio_pkt != NULL. * Will set current_audio_pkt to NULL and delete the packet * if it is fully consumed. * Return number of samples consumed. */ int try_finish_current_audio_packet( ) { uint32_t n_consumed; uint32_t n_left; uint32_t buffer; deckLinkOutput->GetBufferedAudioSampleFrameCount(&buffer); fprintf(stderr, "audio buffer = %u ", buffer); assert(current_audio_pkt != NULL); n_left = current_audio_pkt->n_frames( ) - samples_written_from_current_audio_pkt; if (n_left == 0) { fprintf(stderr, "Audio warning: This should not happen!\n"); return 1; } if (deckLinkOutput->ScheduleAudioSamples( current_audio_pkt->sample( samples_written_from_current_audio_pkt ), n_left, 0, 0, &n_consumed) != S_OK) { throw std::runtime_error( "Failed to schedule audio samples" ); } if (n_consumed == n_left) { delete current_audio_pkt; current_audio_pkt = NULL; } else if (n_consumed < n_left) { samples_written_from_current_audio_pkt += n_consumed; } else { throw std::runtime_error("This should not happen"); } deckLinkOutput->GetBufferedAudioSampleFrameCount(&buffer); fprintf(stderr, "-> %u\n", buffer); return n_consumed; }
void open_card( ) { IDeckLinkDisplayModeIterator *it; /* get the DeckLinkOutput interface */ if (deckLink->QueryInterface(IID_IDeckLinkOutput, (void **)&deckLinkOutput) != S_OK) { throw std::runtime_error( "Failed to get DeckLink output interface handle" ); } if (deckLinkOutput->SetScheduledFrameCompletionCallback(this) != S_OK) { throw std::runtime_error( "Failed to set DeckLink frame completion callback" ); } /* attempt to determine field dominance */ if (deckLinkOutput->GetDisplayModeIterator(&it) != S_OK) { throw std::runtime_error( "DeckLink output: failed to get display mode iterator" ); } dominance = find_dominance(norms[norm].mode, it); it->Release( ); /* and we're off to the races */ if (deckLinkOutput->EnableVideoOutput(norms[norm].mode, bmdVideoOutputFlagDefault) != S_OK) { throw std::runtime_error( "Failed to enable DeckLink video output" ); } }
void preroll_video_frames(unsigned int n_frames) { IDeckLinkMutableVideoFrame *frame; for (unsigned int i = 0; i < n_frames; i++) { if (deckLinkOutput->CreateVideoFrame(norms[norm].w, norms[norm].h, 2*norms[norm].w, bpf, bmdFrameFlagDefault, &frame) != S_OK) { throw std::runtime_error("Failed to create frame"); } schedule_frame(frame); } }
void preroll_video_frames(unsigned int n_frames) { IDeckLinkMutableVideoFrame *frame; IDeckLinkVideoFrameAncillary *anc; for (unsigned int i = 0; i < n_frames; i++) { if (deckLinkOutput->CreateVideoFrame(norms[norm].w, norms[norm].h, 2*norms[norm].w, bpf, bmdFrameFlagDefault, &frame) != S_OK) { throw std::runtime_error("Failed to create frame"); } if (deckLinkOutput->CreateAncillaryData(bpf, &anc) != S_OK) { throw std::runtime_error("failed to set frame ancillary data"); } if (frame->SetAncillaryData(anc) != S_OK) { throw std::runtime_error("failed to set frame ancillary data"); } schedule_frame(frame); } }
virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples( bool preroll ) { // Provide more audio samples to the DeckLink API HRESULT result = S_OK; uint32_t count = m_fifo->used / m_channels; uint32_t buffered = count; if ( count // Stay under preferred buffer level && ( S_OK == m_deckLinkOutput->GetBufferedAudioSampleFrameCount( &buffered ) ) && buffered < m_maxAudioBuffer ) { uint32_t written = 0; buffered = m_maxAudioBuffer - buffered; count = buffered > count ? count : buffered; result = m_deckLinkOutput->ScheduleAudioSamples( m_fifo->buffer, count, 0, 0, &written ); if ( written ) sample_fifo_remove( m_fifo, written * m_channels ); } return result; }
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; }
HRESULT render( mlt_frame frame ) { HRESULT result = S_OK; // Get the audio double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame), "_speed" ); if ( speed == 1.0 ) { mlt_audio_format format = mlt_audio_s16; int frequency = bmdAudioSampleRate48kHz; int samples = mlt_sample_calculator( m_fps, frequency, m_count ); int16_t *pcm = 0; if ( !mlt_frame_get_audio( frame, (void**) &pcm, &format, &frequency, &m_channels, &samples ) ) { int count = samples; if ( !m_isPrerolling ) { uint32_t audioCount = 0; uint32_t videoCount = 0; // Check for resync m_deckLinkOutput->GetBufferedAudioSampleFrameCount( &audioCount ); m_deckLinkOutput->GetBufferedVideoFrameCount( &videoCount ); // Underflow typically occurs during non-normal speed playback. if ( audioCount < 1 || videoCount < 1 ) { // Upon switching to normal playback, buffer some frames faster than realtime. mlt_log_info( &m_consumer, "buffer underrun: audio buf %u video buf %u frames\n", audioCount, videoCount ); m_prerollCounter = 0; } // While rebuffering if ( isBuffering() ) { // Only append audio to reach the ideal level and not overbuffer. int ideal = ( m_preroll - 1 ) * bmdAudioSampleRate48kHz / m_fps; int actual = m_fifo->used / m_channels + audioCount; int diff = ideal / 2 - actual; count = diff < 0 ? 0 : diff < count ? diff : count; } } if ( count > 0 ) sample_fifo_append( m_fifo, pcm, count * m_channels ); } } // Create video frames while pre-rolling if ( m_isPrerolling ) { createFrame(); if ( !m_videoFrame ) { mlt_log_error( &m_consumer, "failed to create video frame\n" ); return S_FALSE; } } // Get the video if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "rendered") ) { mlt_image_format format = mlt_image_yuv422; uint8_t* image = 0; uint8_t* buffer = 0; if ( !mlt_frame_get_image( frame, &image, &format, &m_width, &m_height, 0 ) ) { m_videoFrame = (IDeckLinkMutableVideoFrame*) mlt_deque_pop_back( m_videoFrameQ ); m_videoFrame->GetBytes( (void**) &buffer ); if ( m_displayMode->GetFieldDominance() == bmdUpperFieldFirst ) // convert lower field first to top field first swab( image, buffer + m_width * 2, m_width * ( m_height - 1 ) * 2 ); else swab( image, buffer, m_width * m_height * 2 ); m_deckLinkOutput->ScheduleVideoFrame( m_videoFrame, m_count * m_duration, m_duration, m_timescale ); mlt_deque_push_front( m_videoFrameQ, m_videoFrame ); } } else { mlt_log_verbose( &m_consumer, "dropped video frame\n" ); } ++m_count; // Check for end of pre-roll if ( ++m_prerollCounter > m_preroll && m_isPrerolling ) { // Start audio and video output m_deckLinkOutput->EndAudioPreroll(); m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 ); m_isPrerolling = false; } return result; }
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(); }
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(); }
void print_output_modes(IDeckLink *deckLink) { IDeckLinkOutput *deckLinkOutput = NULL; IDeckLinkDisplayModeIterator *displayModeIterator = NULL; IDeckLinkDisplayMode *displayMode = NULL; HRESULT result; int displayModeCount = 0; // 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) { BMDProbeString str; result = displayMode->GetName(&str); 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(" %2d: %-20s \t %d x %d \t %7g FPS\n", displayModeCount++, ToStr(str), modeWidth, modeHeight, (double)frameRateScale / (double)frameRateDuration); FreeStr(str); } // 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(); }
void BMDOutputDelegate::ScheduleNextFrame(bool preroll) { if(!preroll) { // If not prerolling, make sure that playback is still active if (m_running == false) return; } if(m_frameSet) { //qDebug() << "m_frameSet: not setting"; return; } m_frameSet = true; QTime t; t.start(); // if ((m_totalFramesScheduled % m_framesPerSecond) == 0) // { // // On each second, schedule a frame of black // if (m_deckLinkOutput->ScheduleVideoFrame(m_videoFrameBlack, (m_totalFramesScheduled * m_frameDuration), m_frameDuration, m_frameTimescale) != S_OK) // return; // } //qDebug() << "BMDOutputDelegate::ScheduleNextFrame: [3] Frame Repaint: "<<t.restart()<<" ms"; if(!m_image.isNull()) { void *frameBytes; m_rgbFrame->GetBytes(&frameBytes); int maxBytes = m_frameWidth * m_frameHeight * 4; memcpy(frameBytes, (const uchar*)m_image.bits(), m_image.byteCount() > maxBytes ? maxBytes : m_image.byteCount()); //qDebug() << "BMDOutputDelegate::ScheduleNextFrame: [4] Load BMD Frame with RGB: "<<t.restart()<<" ms"; // Pixel conversions // Source frame Target frame // bmdFormat8BitRGBA bmdFormat8BitYUV // bmdFormat8BitARGB // bmdFormat8BitBGRA bmdFormat8BitYUV // bmdFormat8BitARGB bmdFormat8BitYUV if(m_deckLinkConverter) { m_deckLinkConverter->ConvertFrame(m_rgbFrame, m_yuvFrame); //qDebug() << "BMDOutputDelegate::ScheduleNextFrame: [5] RGB->YUV: "<<t.restart()<<" ms"; if (m_deckLinkOutput->ScheduleVideoFrame(m_yuvFrame, (m_totalFramesScheduled * m_frameDuration), m_frameDuration, m_frameTimescale) != S_OK) return; //qDebug() << "BMDOutputDelegate::ScheduleNextFrame: [6] ScheduleVideoFrame(): "<<t.restart()<<" ms"; } else { qDebug() << "BMDOutputDelegate::ScheduleNextFrame: No m_deckLinkConverter available, unable to convert frame."; } } m_totalFramesScheduled += 1; }