私は基本的に、30fps でタイムコードを開始するボタンを押したいと思っています。(1/30 秒ごとに呼び出されます)。タイムコードをコンピューターに内蔵されている時計に合わせたい。NSDate を使用して HH:mm:ss で現在の時刻を簡単に取得できますが、カウンターをゼロから開始し、HH:mm:ss:ff のような形式のフレームを実装する必要があります。
考え?
私は基本的に、30fps でタイムコードを開始するボタンを押したいと思っています。(1/30 秒ごとに呼び出されます)。タイムコードをコンピューターに内蔵されている時計に合わせたい。NSDate を使用して HH:mm:ss で現在の時刻を簡単に取得できますが、カウンターをゼロから開始し、HH:mm:ss:ff のような形式のフレームを実装する必要があります。
考え?
a を使用して、ビデオ カードの精度でパルスを生成します。これは、またはディスパッチ キュー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
これは、NSTimerオブジェクトを使用し、呼び出しで視覚的な更新を行うことで機能するはずです。3.3333ミリ秒ごとに起動するようにタイマーを設定できます。私が見る唯一の問題は、非常に長いストレッチであり、タイムコードはわずかにずれています。また、これがビデオ関連の場合、一部のビデオは24 fpsでエンコードされるため、注意してください。次に、カウンター= 30でない限り、タイマーによって起動されたメソッドでカウンターに+1を実行させ、1にリセットします。NSDateFormatterオブジェクトをカスタムフォーマット文字列で初期化して、現在の時刻を挿入できるはずです。そして、ユーザーに表示したい形式のカウンター変数。