【问题标题】:iOS: Audio and Video tap from AirplayiOS:来自 Airplay 的音频和视频点击
【发布时间】:2013-07-15 09:44:49
【问题描述】:

我制作了一个视频播放器,可以从当前播放的视频中分析实时音频和视频轨道。视频存储在 iOS 设备上(在 Apps Documents 目录中)。

这一切都很好。我使用 MTAudioProcessingTap 来获取所有音频样本并进行一些 FFT,并且我通过从当前播放的 CMTime(AVPlayer currentTime 属性)复制像素缓冲区来分析视频。正如我所说,这很好用。

但现在我想支持 Airplay。只是 Airplay 本身并不难,但只要切换 Airplay 并且视频在 ATV 上播放,我的水龙头就会停止工作。不知何故,MTAudioProcessingTap 不会处理,并且像素缓冲区都是空的……我无法获取数据。

有没有办法获取这些数据?

为了获取像素缓冲区,我只是每隔几毫秒触发一个事件并检索玩家的 currentTime。那么:

CVPixelBufferRef imageBuffer = [videoOutput copyPixelBufferForItemTime:time itemTimeForDisplay:nil];
CVPixelBufferLockBaseAddress(imageBuffer,0);

uint8_t *tempAddress = (uint8_t *) CVPixelBufferGetBaseAddress(imageBuffer);

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);

CVPixelBufferUnlockBaseAddress(imageBuffer,0);

tempAddress 是我的像素缓冲区,videoOutputAVPlayerItemVideoOutput 的一个实例。

对于音频,我使用:

AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioTrack];

// Create a processing tap for the input parameters
MTAudioProcessingTapCallbacks callbacks;

callbacks.version = kMTAudioProcessingTapCallbacksVersion_0;
callbacks.clientInfo = (__bridge void *)(self);
callbacks.init = init;
callbacks.prepare = prepare;
callbacks.process = process;
callbacks.unprepare = unprepare;
callbacks.finalize = finalize;

MTAudioProcessingTapRef tap;
OSStatus err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks,
                                          kMTAudioProcessingTapCreationFlag_PostEffects, &tap);
if (err || !tap) {
    NSLog(@"Unable to create the Audio Processing Tap");
    return;
}

inputParams.audioTapProcessor = tap;

// Create a new AVAudioMix and assign it to our AVPlayerItem
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = @[inputParams];
playerItem.audioMix = audioMix;

问候, 尼克

【问题讨论】:

  • 能否请您在访问像素缓冲区的位置添加代码?
  • 播放视频的代码也有帮助:)
  • 嗯...我真的不知道。也许可以尝试查看这篇文章以及他获取像素缓冲区的方法 - 7twenty7.com/blog/2010/11/video-processing-with-av-foundation
  • 当您完成 MTAudioProcessingTap 后,您并没有弄清楚如何解除分配,是吗?我无法让它触发它的未准备并完成回调。请看我的问题:stackoverflow.com/q/19202306/506796
  • 我只是为了纯音频处理遇到了这个问题。你提交了我可以欺骗的雷达吗?

标签: ios avfoundation airplay


【解决方案1】:

不幸的是,根据我的经验,在 Airplay 期间无法获取有关音频/视频的信息,因为播放是在 Apple TV 上完成的,因此 iOS 设备没有任何信息。

我在从timedMetaData 中获取 SMPTE 字幕数据时遇到了同样的问题,在 Airplay 期间停止报告。

【讨论】:

    【解决方案2】:

    解决办法:

    这是为了实现 AirPlay,我将此代码仅用于我的应用程序上的音频我不知道您是否可以改进视频但您可以尝试 ;)

    AppDelegate.m 上:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        [RADStyle applyStyle];
        [radiosound superclass];
        [self downloadZip];
    
        NSError *sessionError = nil;
        [[AVAudioSession sharedInstance] setDelegate:self];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
    
        UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
        AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
    
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
    
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    }
    

    如果您使用airplay 很好地实现LockScreen 控件、ArtWork、Stop/play、Title ecc。

    在播放器的 DetailViewController 中使用以下代码:

    - (BOOL)canBecomeFirstResponder {
    
        return YES;
    }
    - (void)viewDidAppear:(BOOL)animated {
    
        [super viewDidAppear:animated];
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
        [self becomeFirstResponder];
    
        NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: (self.saved)[@"image"]]];
    
        if (imageData == nil){
    
        MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
        MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"lockScreen.png"]];
    
        infoCenter.nowPlayingInfo = @{MPMediaItemPropertyTitle: saved[@"web"],MPMediaItemPropertyArtist: saved[@"title"], MPMediaItemPropertyArtwork:albumArt};
    
        } else {
    
            MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
            MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageWithData:imageData]];
    
            infoCenter.nowPlayingInfo = @{MPMediaItemPropertyTitle: saved[@"link"],MPMediaItemPropertyArtist: saved[@"title"], MPMediaItemPropertyArtwork:albumArt};
    
        }
    
    }
    

    希望这段代码可以帮助你;)

    【讨论】:

    • 使用airplay不是问题,分析实时音视频数据才是问题。
    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多