2021-09-17 10:56:45
0
1. 介绍 视频编解码的主要工作:
- 编码,即将原始的视频信息压缩为既定格式的数据。
- 解码,即将已知格式的数据还原为视频信息。
本教程将通过启动相机捕获预览帧,转换为视频原始数据并使用HarmonyOS视频解码能力播放预览画面。
通过本教程,你将实现不受视频格式限制、不受视频完整性的影响、确保设备可以实时播放视频流数据,也可以以此为基础实现分布式相机预览、直播、视频聊天等功能。
图1-1 实时播放预览流界面
2. 搭建HarmonyOS环境
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
- 安装DevEco Studio,详情请参考下载和安装软件。
- 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
- 如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
- 如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
- 开发者可以参考以下链接,完成设备调试的相关配置:
3. 代码结构解读 - camera:整合了HarmonyOS 相机能力,通过自定义的CameraView和控制器CameraController,使得View层和Model层能更好地解耦。
- codec:是应用于视频编解码Codec的封装,包括编码器CodecEncoder和解码器CodecDecoder,方便开发者使用编码和解码。
- manager:是视频编解码播放器的封装,用于slice和编解码能力分离。
- media:是camera视频录制所使用recorder的封装,用于去CameraController代码复杂度。
- utils:工具类
- LogUtil是日志打印类,对HiLog日志进行了封装。
- ScreenUtils是获取其设备屏幕宽高和分辨率的工具类。
- CodecAbility:自定义视频编解码功能入口。
- MainAbility:主程序入口,DevEco Studio生成,未添加逻辑,无需变更。
4. HarmonyOS Camera介绍
本Codelab通过鸿蒙Camera捕获预览帧,并实现了设置自拍镜像和切换摄像头的功能。
- 自拍镜像
通过FrameConfig.Builder设置返回帧参数接口可以设置镜像功能,代码如下:
frameConfigBuilder.setParameter(ParameterKey.IMAGE_MIRROR, true); - 捕获预览帧数据
HarmonyOS编码器需要传入视频原始数据,开发者可以通过设置帧接收器的格式为YUV420_888来获取帧的原始数据,步骤如下:
1.创建帧接收器。
- imageReceiver =ImageReceiver.create(
- Math.max(resoluteX, resoluteY),
- Math.min(resoluteX, resoluteY),
- ImageFormat.YUV420_888,
- CameraConst.IMAGE_RCV_CAPACITY);
复制代码
2.设置帧接收器回调接口。
- imageReceiver.setImageArrivalListener(new ImageReceiver.IImageArrivalListener() {
- [url=home.php?mod=space&uid=2735960]@Override[/url]
- public void onImageArrival(ImageReceiver imageReceiver) {
- //帧数据回调
- }
- });
复制代码 3.开始连续捕获模式。
- frameConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
- try {
- cameraDevice.triggerLoopingCapture(frameConfigBuilder.build());
- } catch (IllegalArgumentException e) {
- LogUtil.info(TAG, "pushFlow is failed," + e.getMessage());
- }
复制代码
- 切换摄像头
通过CameraKit获取手机的摄像头硬件id,通过id创建Camera实例,代码如下:
- private void cameraInit() {
- CameraKit camerakit = CameraKit.getInstance(context.getApplicationContext());
- if (camerakit != null && camerakit.getCameraIds().length > cameraType) {
- String cameraId = camerakit.getCameraIds()[cameraType];
- cameraSupportor = camerakit.getCameraAbility(cameraId);
- CameraStateCallback cameraStateCallback = new MyCameraStatuCallback();
- camerakit.createCamera(cameraId, cameraStateCallback, eventHandler);
- captureInit();
- }
- }
复制代码
5. YUV编码
使用HarmonyOS编码器Codec对Camera获取的视频YUV数据进行编码,步骤如下:
步骤 1 - 初始化编码器。
- Format fmt = new Format();
- fmt.putStringValue(Format.MIME, Format.VIDEO_AVC);
- fmt.putIntValue(Format.WIDTH, controller.getResolution().height);
- fmt.putIntValue(Format.HEIGHT, controller.getResolution().width);
- fmt.putIntValue(Format.BIT_RATE, MediaConst.RECORDER_BIT_RATE);
- fmt.putIntValue(Format.COLOR_MODEL, CodecConst.CODEC_COLOR_MODEL);
- fmt.putIntValue(Format.FRAME_RATE, MediaConst.RECORDER_FRAME_RATE);
- fmt.putIntValue(Format.FRAME_INTERVAL, CodecConst.CODEC_FRAME_INTERVAL);
- fmt.putIntValue(Format.BITRATE_MODE, CodecConst.CODEC_BITRATE_MODE);
- videoEncoder = new CodecEncoder.Builder().setFormat(fmt).create();
复制代码 步骤 2 - 启动编码器。
- videoEncoder.openEncoder();
复制代码 步骤 3 - 开始编码,传入Camera获取的YUV帧数据。
- videoEncoder.startEncode(frame);
复制代码 步骤 4 - 设置编码成功回调,在回调中返回编码后数据,在本应用中在此回调中对数据解码播放。
- videoEncoder.setEncodeListener((byteBuffer, bufferInfo) -> {
-
- byte[] buffers = new byte[bufferInfo.size];
-
- byteBuffer.clear();
-
- byteBuffer.get(buffers);
-
- videoDecoder.startDecode(buffers);
- });
复制代码
6. 视频源解码播放
编码回调返回自定义编码格式数据,使用Codec对视频源进行播放,步骤如下:
步骤 1 - 初始化解码器,需要传入surface作为视频承载。
- videoDecoder = new CodecDecoder.Builder().setFormat(fmt). setSurface(surface).create();
复制代码 步骤 2 - 启动解码器。
- videoDecoder.openDecoder();
复制代码 步骤 3 - 开始解码。
- byte[] buffers = new byte[bufferInfo.size];
- byteBuffer.clear();
- byteBuffer.get(buffers);
- videoDecoder.startDecode(buffers);
复制代码
7. 恭喜你
你已经成功学习了如何通过HarmonyOS编解码播放Camera的实时预览流。
8. 参考
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。
侵权投诉