2013-02-04 22 views
0

我基本上想按下一個按鈕,以30fps開始時間碼。 (每1/30秒調用一次)。我希望時間碼被引用到計算機內置的時鐘中。我可以很容易地使用NSDate獲取HH:mm:ss的當前時間,但是我需要計數器從零開始並實現幀格式,如HH:mm:ss:ff從計算機時鐘引用的時間碼

想法?

回答

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 
+0

太棒了!問題,_ref來自哪裏? – objectiveccoder001

+0

這是否比找到使用coreVideo顯示SMPTE時間碼的方式更好? – objectiveccoder001

+0

對不起,'_ref'是'_link',我正在從我的測試項目中複製和粘貼...我懷疑有一個快速的方法讓CVTimeSTamp給你一個合適的smpteTime字段,但是我的日常工作讓我從完成我的研究:)現在我會採取一個NSDate並將其轉換成從午夜SMPTE幀數,抵消了正常運行時間,yada yada divmod ... – iluvcapra

0

這應該使用NSTimer對象並在調用中執行可視化更新。您可以將計時器設置爲每3.3333毫秒觸發一次。我看到的唯一問題是延長很長時間,時間碼會稍微偏離。另外,如果這與視頻有關,請注意,因爲某些視頻以24 fps編碼。然後我會有一個計數器在定時器觸發的方法中執行+1,除非counter = 30,那麼我將它重置爲1.您應該能夠使用自定義格式字符串初始化NSDateFormatter對象以插入當前時間和您想要顯示給用戶的格式的計數器變量。

+1

我懷疑的NSTimer,如果說火每10.0/3.0毫秒,會像時鐘一樣精確。 –

+0

NSTimer對我來說不夠準確。 – objectiveccoder001

+0

我一直在搞這個... – objectiveccoder001