我基本上想按下一个按钮,以 30fps 开始时间码。(每 1/30 秒调用一次)。我希望将时间码引用到计算机内置的时钟。我可以使用 NSDate 轻松获得 HH:mm:ss 中的当前时间,但我需要计数器从零开始并实现帧格式,如 HH:mm:ss:ff
想法?
我基本上想按下一个按钮,以 30fps 开始时间码。(每 1/30 秒调用一次)。我希望将时间码引用到计算机内置的时钟。我可以使用 NSDate 轻松获得 HH:mm:ss 中的当前时间,但我需要计数器从零开始并实现帧格式,如 HH:mm:ss:ff
想法?
使用 aCVDisplayLink
来生成具有显卡精度的脉冲,这将比 anNSTimer
或 dispatch queue 准确得多。CoreMedia/CoreVideo 也原生地谈论 SMPTE。
CVReturn MyDisplayCallback(CVDisplayLinkRef displayLink,
const CVTimeStamp *inNow,
const CVTimeStamp *inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags *flagsOut,
void *displayLinkContext) {
CVSMPTETime timecodeNow = inNow->smpteTime; // it's that easy!
DoStuffWith(timecodeNow); // you might have to modulo this run a bit if the display framerate is greater than 30fps.
return kCVReturnSuccess;
}
CVDisplayLinkRef _link;
CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(),&_link);
CVDisplayLinkSetOutputCallback(_link, MyDisplayCallback, NULL);
CVDisplayLinkStart(_link);
编辑:玩了一会儿之后,我注意到 displaylink 中的 SMPTE 字段没有被填写,但是 OTOH 主机时间是准确的。只需使用:
inNow->videoTime / inNow->videoTimeScale;
获取正常运行时间的秒数,以及
inNow->videTime % inNow->videoTimeScale
得到剩余部分。
据我所知,这是:
@implementation JHDLTAppDelegate
CVReturn MYCGCallback(CVDisplayLinkRef displayLink,
const CVTimeStamp *inNow,
const CVTimeStamp *inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags *flagsOut,
void *displayLinkContext) {
dispatch_async(dispatch_get_main_queue(), ^{
JHDLTAppDelegate *obj = (__bridge JHDLTAppDelegate *)displayLinkContext;
uint64_t seconds = inNow->videoTime / inNow->videoTimeScale;
[obj.outputView setStringValue:[NSString stringWithFormat:@"days: %llu/hours: %llu/seconds: %llu (%llu:%u)",
seconds / (3600 * 24),
seconds / 3600,
seconds,
inNow->videoTime, inNow->videoTimeScale]];
});
return kCVReturnSuccess;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &_ref);
CVDisplayLinkSetOutputCallback(_ref, MYCGCallback, (__bridge void *)self);
CVDisplayLinkStart(_ref);
}
- (void)dealloc
{
CVDisplayLinkStop(_ref);
CVDisplayLinkRelease(_ref);
}
@end
这应该使用 NSTimer 对象并在调用中进行视觉更新。您可以将计时器设置为每 3.3333 毫秒触发一次。我看到的唯一问题是很长一段时间,时间码会稍微偏离。此外,如果这与视频相关,请小心,因为某些视频以 24 fps 编码。然后我会让计数器在计时器触发的方法中执行 +1,除非计数器 = 30,然后我会将其重置为 1。您应该能够使用自定义格式字符串初始化 NSDateFormatter 对象以插入当前时间以及您希望向用户显示的格式的计数器变量。