0

我基本上想按下一个按钮,以 30fps 开始时间码。(每 1/30 秒调用一次)。我希望将时间码引用到计算机内置的时钟。我可以使用 NSDate 轻松获得 HH:mm:ss 中的当前时间,但我需要计数器从零开始并实现帧格式,如 HH:mm:ss:ff

想法?

4

2 回答 2

3

使用 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
于 2013-02-04T23:11:34.580 回答
0

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

于 2013-02-04T22:57:58.197 回答