Hi,
So I tested the new drivers but the problem is not solved. It's seems like the frames are dropping earlier when i'm using the computer while i'm doing a playback. So it might be a performance issue. But I doubt because I can run CasparCG with the same decklink card (Quad) onto the same MacMini without having dropped frames.
So back to the OSX part.
In my code i'm tracing for dropped and late frames. If there are such frames I push the timescale 1 frame up to catch that delay. It's seems to work cause when I playback 3 streams i'm not having frames dropped after 15mins (576i) like I had before. Sometimes I can see in my log there was a dropped frame. But the code caches by the frame after.
Then after 20 to 30 mins every output starts randomly dropping frames and even while pushing the timescale 1 frame into the future the frames keep dropping or displaying late.
Anyone has an idea?
Here you can find my code where I push the frames into the future after dropping or displaying late:
- Code: Select all
HRESULT PlaybackDelegate::ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result)
{
if ((result == bmdOutputFrameDisplayedLate) || (result == bmdOutputFrameDropped))
{
// if dropped bump scheduled time further into the future by one frame
[pDecklinkDevice increaseScheduledFrames];
NSLog(@"bumped %d", [pDecklinkDevice getOutputID]);
}
if ([pDecklinkDevice getIsRunning] == TRUE)
{
[pDecklinkDevice createVideoFrame:TRUE];
}
return S_OK;
}
- (void) increaseScheduledFrames
{
totalFramesScheduled += 1;
}
and this is my code where I create a new frame and schedule that one
- Code: Select all
- (void) createVideoFrame:(BOOL)schedule
{
@autoreleasepool
{
// get displaymode
IDeckLinkDisplayMode* decklinkdisplaymode = (IDeckLinkDisplayMode*)CurrentRes;
// create new videoframe on output
if (deckLinkOutput->CreateVideoFrame((int)decklinkdisplaymode->GetWidth(), (int)decklinkdisplaymode->GetHeight(), (int)decklinkdisplaymode->GetWidth() * 4, bmdFormat8BitARGB, bmdFrameFlagFlipVertical, &videoFrame) != S_OK)
{
// failed to create new video frame on output
// display terminal message
sendMessageToTerminal = [[mogiTerminalMessage alloc] initWithSendNotification:@"terminalErrorMessage" forMessage:[NSString stringWithFormat:@"DeckLink: Output %d -> Failed to create new videoframe", outputID]];
}
unsigned frameBufferRowBytes = ((int)decklinkdisplaymode->GetWidth() * 4 + 63) & ~63;
void* frameBufferPtr = valloc((int)decklinkdisplaymode->GetHeight() * frameBufferRowBytes);
// set videoframe pointer
if (videoFrame != NULL)
{
videoFrame->GetBytes((void**)&frameBufferPtr);
}
// fill pointer with pixel data
if (scheduleBlack == TRUE)
{
[qClear renderFrameAtTime:1.0 forBuffer:(void**)frameBufferPtr forScreen:0];
// render first frame qRenderer
if (qRender != NULL)
{
[qRender renderFirstFrame];
}
}
else
{
[qRender renderFrameAtTime:totalSecondsScheduled forBuffer:(void**)frameBufferPtr forScreen:screenID];
schedule = TRUE;
}
// if playback -> schedule frame
if (schedule == TRUE)
{
// schedule frame
if (videoFrame != NULL)
{
if (deckLinkOutput->ScheduleVideoFrame(videoFrame, (totalFramesScheduled * frameDuration), frameDuration, frameTimescale) != S_OK)
{
// failed to schedule new frame
// display message to terminal
sendMessageToTerminal = [[mogiTerminalMessage alloc] initWithSendNotification:@"terminalErrorMessage" forMessage:[NSString stringWithFormat:@"DeckLink: Output %d -> Failed to schedule new videoframe", outputID]];
}
else
{
// increase totalFramesScheduled
totalFramesScheduled += 1;
// increase totalSecondsScheduled
totalSecondsScheduled += 1.0/framesPerSecond;
}
// clear videoframe
videoFrame->Release();
videoFrame = NULL;
}
}
}
}