从计算机时钟引用的时间码

时间:2013-02-04 22:32:23

标签: objective-c cocoa

我基本上想按一个按钮,以30fps开始时间码。 (每隔1/30秒调用一次)。我希望时间码能够参考计算机内置的时钟。我可以很容易地使用NSDate获取HH:mm:ss的当前时间,但是我需要计数器从零开始并实现格式化为HH的帧:mm:ss:ff

思想?

2 个答案:

答案 0 :(得分:3)

使用CVDisplayLink生成具有视频卡准确性的脉冲,这将比NSTimer或调度队列更准确。 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

答案 1 :(得分:0)

这应该可以使用NSTimer对象并在调用中进行可视化更新。您可以将计时器设置为每3.3333毫秒触发一次。我看到的唯一问题是很长时间,时间码会略微偏离。此外,如果这与视频相关,请小心,因为某些视频以24 fps编码。然后我会有一个计数器在计时器触发的方法中执行+1,除非counter = 30,然后我将它重置为1.您应该能够使用自定义格式字符串初始化NSDateFormatter对象以插入当前时间以及您希望向用户显示的格式的计数器变量。