我想做的是:
- 在一个屏幕上播放大师级的快速电影(prores或pjpg)(带音频)
- 在另一个屏幕上与主屏幕同步播放另一部从属快速电影(prores或pjpg)
- 当我向左或向右按时,循环播放不同的从属电影
这就是我所做的:
- 为每个屏幕创建一个NSWindow
- 创建一个QTMovies数组(实际上是每个屏幕的数组)
- 创建一个QTMovieViews数组(实际上是每个屏幕的数组)
- 正常播放主控QTMovie
- 设置NSTimer以从主电影时间更新当前从属电影时间
- 如果按键,请将窗口的内容视图切换到新的QTMovieView
我的完整代码在http://codepad.org/gDsJLPAy
这一切都很有效,但当我切换视频时,我会看到切换到的旧视频帧的单帧闪光。也就是说,如果我运行应用程序50帧并切换到SlaveVideo2,我会瞥见SlavVideo2帧0,然后它立即跳到SlaveVideo 2帧50,并照常进行。如果在20帧之后,我切换回SlaveVideo1,我瞥见了SlaveVideo2的第50帧,然后它跳到SlaveVideo 1的第70帧,并照常进行。
我想弄清楚这件事快疯了。我尝试过各种刷新、显示方法,但都无济于事。关于我该怎么解决这个问题,有什么想法吗?
附言:你可以在timerFireMethod中看到,如果我一直更新所有从属电影(而不仅仅是活动的),我就不会闪烁。显然,这不是一个解决方案,因为我一直在寻找大量的视频,这些视频太重了,没有必要!
附言:我试过在Quartz Composer中重新创建设置,但我遇到了完全相同的问题。
我在10.7.3
为了存档,我将在这里发布我的结论。
我找不到这个问题的直接解决办法。如果从属电影暂停,当我激活它的视图时——即使我稍微早一点开始播放电影——当它变得可见时,它首先显示旧帧。我找到的解决办法是让电影一直播放(这很糟糕)。
但是我发现了https://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieInternals/MTTimeSpace/B-第/2章MovieTimeandSpace.html
通过在主影片上调用GetMovieTimeBase,并将SetTimeBaseMasterTimeBase应用于从属影片,它允许这两部影片在后端同步播放,而无需手动保持同步。因此,整个同步代码可以简化为:
-(void)setLayerIndex:(int)i {
// make sure target index is within bounds
if(i<0) i=[[movies objectAtIndex:1] count]-1;
else if(i>[[movies objectAtIndex:1] count]-1) i=0;
// pause all slave views
[[viewers objectAtIndex:1] makeObjectsPerformSelector:@selector(pause:) withObject:self];
// save current index
currentLayerIndex = i;
// sync frame of new slave movie
[[self currentSlaveMovie] setCurrentTime:[masterMovie currentTime]];
// set windows view to QTView
[[windows objectAtIndex:1] setContentView:[self currentSlaveView]];
// set timebase of slave to timebase of master
TimeBase masterTimeBase = GetMovieTimeBase([masterMovie quickTimeMovie]);
TimeValue masterTimeScale = GetMovieTimeScale([masterMovie quickTimeMovie]);
TimeRecord slaveZero;
TimeValue slaveZeroTV = GetTimeBaseStartTime(masterTimeBase, masterTimeScale, &slaveZero);
SetMovieMasterTimeBase([[self currentSlaveMovie] quickTimeMovie], masterTimeBase, &slaveZero);
// play master movie
[masterViewer play:self];
// play slave movie
[[self currentSlaveView] play:self];
}