Cocoa 在NSV窗口上交换QTMovieView会导致闪烁

Cocoa 在NSV窗口上交换QTMovieView会导致闪烁,cocoa,synchronization,quicktime,qtkit,Cocoa,Synchronization,Quicktime,Qtkit,我想做的是: 在一个屏幕上播放主quicktime电影(prores或pjpg)(带音频) 在另一个屏幕上与主屏幕同步播放另一个从属quicktime电影(prores或pjpg) 当我按下左键或右键时,循环播放不同的从属影片 这就是我所做的: 为每个屏幕创建一个窗口 创建QTMovies数组(实际上是每个屏幕的数组) 创建QTmoviews数组(实际上是每个屏幕的数组) 正常播放大师级电影 设置NSTimer以从主电影时间更新当前从属电影时间 如果按下某个键,将窗口的内容视图切换到新的Q

我想做的是:

  • 在一个屏幕上播放主quicktime电影(prores或pjpg)(带音频)
  • 在另一个屏幕上与主屏幕同步播放另一个从属quicktime电影(prores或pjpg)
  • 当我按下左键或右键时,循环播放不同的从属影片
这就是我所做的:

  • 为每个屏幕创建一个窗口
  • 创建QTMovies数组(实际上是每个屏幕的数组)
  • 创建QTmoviews数组(实际上是每个屏幕的数组)
  • 正常播放大师级电影
  • 设置NSTimer以从主电影时间更新当前从属电影时间
  • 如果按下某个键,将窗口的内容视图切换到新的QTMovieView
我的完整代码在

这一切都是可行的,但当我切换视频时,我会看到切换到的旧视频帧的单帧闪光。也就是说,如果我运行应用程序50帧并切换到SlaveVideo2,我会瞥见SlaveVideo2第0帧,然后它会立即跳到SlaveVideo2第50帧并像往常一样继续运行。如果在20帧后我切换回SlaveVideo1,我瞥见SlaveVideo1第50帧,然后它跳到SlaveVideo1第70帧,并像往常一样继续

我想弄明白这件事快发疯了。我尝试过各种刷新、显示方法,但都没有用。有没有办法解决这个问题

另外,你可以在TimerFire方法中看到,如果我一直更新所有从属电影(而不仅仅是活动的),我不会得到闪烁。显然,这不是一个解决方案,因为我一直在寻找太多太沉重和不必要的视频

p.p.S.我曾尝试在Quartz Composer中重新创建设置,但我遇到了完全相同的问题


我在10.7.3上

为了存档,我将在这里发布我的结论

我找不到直接解决这个问题的办法。如果从属电影暂停,当我将其视图激活时(即使我开始播放电影的时间稍微早一点),在显示时,它首先显示旧帧。我找到的解决办法是让电影一直播放(这太糟糕了)

但是我发现了这个

通过在主电影上调用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];
-(void)setLayerIndex:(int)i{
//确保目标索引在范围内
如果(i[[movies objectAtIndex:1]计数]-1)i=0;
//暂停所有从属视图
[[viewers objectAtIndex:1]makeObjectsPerformSelector:@selector(暂停:)with object:self];
//保存当前索引
currentLayerIndex=i;
//新从属电影的同步帧
[[self-currentSlaveMovie]setCurrentTime:[masterMovie currentTime]];
//将windows视图设置为QTView
[[windows对象索引:1]setContentView:[self-currentSlaveView]];
//将从机的时基设置为主机的时基
TimeBase masterTimeBase=GetMovieTimeBase([masterMovie quickTimeMovie]);
TimeValue masterTimeScale=GetMovieTimeScale([masterMovie quickTimeMovie]);
时间记录slaveZero;
TimeValue slaveZeroTV=GetTimeBaseStartTime(主时基、主时标和slaveZero);
SetMovieMasterTimeBase([[self-currentSlaveMovie]quickTimeMovie]、masterTimeBase和slaveZero);
//播放大师级电影
[masterViewer play:self];
//播放奴隶电影
[[self-currentSlaveView]播放:self];
}