zoukankan      html  css  js  c++  java
  • iOS视频播放(AVFoundation)

    iOS视频播放(AVFoundation)

    关于iOS平台的音视频处理,苹果官方提供了OC和swift接口的AVFoundation框架,可以进行各种音频播放和剪辑,底层实现使用了GPU加速,编解码效率比软编软解提高很多。所以在iOS平台音视频方面的操作,AVFoundation是不二之选。iOS音视频处理库结构如下图:

    可以看到AVFoundation处于中间,它封装了底层的一些C接口,抽象了一层面向对象的OC接口调用,比如视频编解码我们可以直接调用VideoToolBox的c接口,也可以使用AVAssertWriter和AVAssertReader类,它们进行了较好的封装,便于使用。苹果推荐我们使用后者。


    1.1音视频播放

    AVKit框架提供了简单易用的调用,直接封装的一个播放器,而且控制UI都提供了。这个很简单不用说了。主要介绍一下AVPlayer和AVPlayerItem。AVAssert是作为音视频文件的一个抽象,AVPlayer不直接对接AVAssert,通过AVPlayerItem控制播放源的状态,代码如下:

    
    AVAsset *assert = [AVAsset assetWithURL:[NSURL URLWithString:@"example.mp4"]];
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:assert];
    AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
    
    
    

    1.2使用AVPlayerlayer播放

    视频图像要播放出来需要绘制在窗口上面,AVPlayer配套使用AVPlayerlayer。
    代码:

    // PlayerView.h
    @interface PlayerView : UIView
    @property AVPlayer *player;
    @property (readonly) AVPlayerLayer *playerLayer;
    @end
     
    // PlayerView.m
    @implementation PlayerView
    - (AVPlayer *)player {
        return self.playerLayer.player;
    }
     
    - (void)setPlayer:(AVPlayer *)player {
        self.playerLayer.player = player;
    }
     
    // Override UIView method
    + (Class)layerClass {
        return [AVPlayerLayer class];
    }
     
    - (AVPlayerLayer *)playerLayer {
        return (AVPlayerLayer *)self.layer;
    }
    @end
    
    

    1.3使用AVPlayerItemVideoOutput

    有时候我们需要进一步对输出的图像进行处理,然后中绘制到view上面。这个时候就需要AVPlayerItemVideoOutput,它相当于在一个视频播放源上安装一个水龙头,然后解码后的视频数据就从里面出来,我们还可以指定输出数据的格式,便于下一步处理。代码如下:

    //输出yuv 420格式
    NSDictionary *pixBuffAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)}; 
    AVPlayerItemVideoOutput *output = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:pixBuffAttributes];
    [playerItem addOutput:output]; //put output to item
    
    
    

    使用CADisplayLink开启定时回调方法,从output中获取图像数据进行处理,代码如下:

    
    - (void)displayLinkCallback:(CADisplayLink *)sender
    {
       
        CMTime outputItemTime = kCMTimeInvalid;
        CFTimeInterval nextVSync = ([sender timestamp] + [sender duration]);
        outputItemTime = [[self videoOutput] itemTimeForHostTime:nextVSync];
        if ([[self videoOutput] hasNewPixelBufferForItemTime:outputItemTime]) {
            CVPixelBufferRef pixelBuffer = NULL;
            pixelBuffer = [[self videoOutput] copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL];
            // ..... do something with pixbuffer
            if (pixelBuffer != NULL) {
                CFRelease(pixelBuffer);
            }
        }
    }
    
    

    CADisplayLink的回调次数是根据屏幕刷新频率来的,它的timestamp方法可以获取上次的刷新时间戳,然后加上刷新间隔,获得当前时间戳,从output获得相应数据数据,进行处理。


    参考:

    https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html#//apple_ref/doc/uid/TP40010188-CH3-SW4

    https://developer.apple.com/library/archive/samplecode/AVBasicVideoOutput/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013109

  • 相关阅读:
    自测项目:批量删除云盘重复文件
    表格更新成本 二 问用户年龄和口令,直到他们提供有效的输入
    知乎抓取、写入文档
    倒打印心
    HDU 1102 Constructing Roads
    C++模板:字典树
    HDU 3015 Disharmony Trees
    HDU 2227 Find the nondecreasing subsequences
    HDU 3486 Interviewe
    C++模板:ST算法
  • 原文地址:https://www.cnblogs.com/song-jw/p/9230150.html
Copyright © 2011-2022 走看看