视频解码功能实现教程
1. 概述
Mobile SDK内部已实现从相机获取视频码流的功能,开发者可以根据Mobile SDK提供的开启相机码流、添加码流观察者来获取视频码流数据,然后自行实现数据解码和视频播放功能。也可以选择使用Autel_UX_SDK demo提供的VideoStreamPlayManager、VideoOpenGLView进行视频解码播放。本教程旨在帮助您基本了解 Mobile SDK 上述两种视频解码方式的实现.
2. 视频解码流程图
以下为UI层、视频播放业务、Mobile SDK之间的调用流程
3. 视频解码API介绍
Mobile SDK视频解码功能主要集中在AUTELVideoFeed和AUTELVideoDataPacket两个类中.
AUTELVideoFeed主要提供开启、关闭码流功能,以及对码流添加或移除观察者。Mobile SDK会将每一帧码流数据分发给已添加的观察者.
3.1 开启监测相机码流
+ (void)openVideoFeed;
3.2 关闭监测相机码流
+ (void)closeVideoFeed
3.3 添加视频码流观察者
当Mobile SDK接收到视频码流后,分发给这些观察者.queue:Mobile SDK准备好码流数据包后,分发码流所在线程队列
+ (void)addVideoFeedListener:(id<AUTELVideoFeedListener>)listener withQueue:(dispatch_queue_t)queue;
3.4 移除视频码流观察者
移除后,不再分发视频码流给此观察者.
+ (void)removeVideoFeedListener:(id<AUTELVideoFeedListener>)listener;
3.5 码流数据回调
通过2.2.3 添加视频码流观察者后,需要在观察者所在类中实现码流回调API。以下为码流数据回调的API介绍
码流数据包更新回调
- (void)videoFeed:(AUTELVideoFeed *)feed didUpdateVideoData:(AUTELVideoDataPacket *)packet;
相机连接状态更新回调
由于所有视频码流数据来源于相机,所以相机断开连接后,就没有视频码流了。因此,我们需要监测相机的连接状态
- (void)videoFeed:(AUTELVideoFeed *)feed didUpdateConnecteState:(BOOL)state;
通过码流数据包回调方法,可以获取到视频码流数据AUTELVideoDataPacket以及相机的连接状态。开发者在获取到AUTELVideoDataPacket后进行解码和播放。
3.6 视频码流数据
AUTELVideoDataPacket是通过添加码流观察者后,Mobile SDK向上层回调的码流数据类,以下是对AUTELVideoDataPacket的属性说明。
@property (nonatomic, assign, readonly)uint8_t *data;// 获取当前帧的码流数据
@property (nonatomic, assign, readonly)size_t size; // 码流数据size大小
@property (nonatomic, assign, readonly)int64_t pts; // 获取当前帧的码流数据帧率
@property (nonatomic, assign, readonly)int32_t width; // 获取当前帧的码流数据(视频图片)宽
@property (nonatomic, assign, readonly)int32_t height; // 获取当前帧的码流数据(视频图片)高
@property (nonatomic, assign, readonly)int32_t keyFrame; // 是否是关键帧
@property (nonatomic, assign, readonly)AutelVideoEncodeFormat videoFormat; //H264编码格式、H265编码格式
- (instancetype)initWithData:(uint8_t *)data withSize:(size_t)size withPts:(int64_t)pts;
//为了支持H265增加,codeType定义见AutelVideoEncodeFormat
- (instancetype)initWithData:(uint8_t *)data withSize:(size_t)size withPts:(int64_t)pts encodeType: (int)codeType;
//为了支持H265增加,codeType定义见AutelVideoEncodeFormat
- (instancetype)initWithData: (uint8_t *)data
withwidth: (int32_t)width
withheight: (int32_t)height
withKeyFrame: (int32_t)keyFrame
withSize: (size_t)size
withPts: (int64_t)pts
encodeType: (int)codeType;
- (instancetype)initWithData:(uint8_t *)data;
//为了支持H265增加,codeType定义见AutelVideoEncodeFormat
- (instancetype)initWithData:(uint8_t *)data encodeType: (int)codeType;
通过上面的介绍,可以获取视频数据。如果开发者希望自己实现视频解码和播放,那么到这里就已经能达成目的。
4. 视频解码功能实现
下面以Autel_UX_SDK demo为例讲解如何进行视频解码和播放的功能开发。
在本例中,为方便视频解码功能开发,我们对底层Mobile SDK视频码流做了二次封装,主要涉及的类有VideoStreamPlayManager、VideoOpenGLView。
- VideoStreamPlayManager:开启码流、码流解码、视频帧播放功能的管理类。开发者只需要进行简单调用就能达到视频播放的效果。
- VideoOpenGLView:支持openGL渲染的视频播放视图,只需要通过正常的系统创建并设置好布局即可。
上述类封装在AUTELWidget.framework动态库。
4.1 创建视频播放视图
lazy var videoPlayView : VideoOpenGLView = {
let view = VideoOpenGLView.init()
return view
}()
view.addSubview(videoPlayView)
videoPlayView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
4.2 开启视频播放
func startPlay() {
guard !self.isPlaySetup else {
return
}
self.isPlaySetup = true
print("VideoStreamPlayManager startPlay called")
VideoStreamPlayManager.sharedInstance().setPlayView(to: videoPlayView)
}
4.3 结束视频播放
func stopPlay() {
print("VideoStreamPlayManager stopPlay called")
VideoStreamPlayManager.sharedInstance().stopPlayAndRemoveView()
self.isPlaySetup = false
}
4.4 其他功能
开启过爆提示
视频画面过度曝光部分会被标识出来,显示在实时视频画面上
VideoStreamPlayManager.sharedInstance().showOverExpose = true
设置视频宽高比(变化)回调
VideoStreamPlayManager.sharedInstance().ratioHandle = { [weak self] ratio in
GCDUtils.main {
self?.updatePlayerView(ratio)
}
}获取视频宽高size
VideoStreamPlayManager.sharedInstance().renderAspectRatio