[文章]基于HarmonyOS编解码能力,实现Camera实时预览流的播放

阅读量0
0
1
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.创建帧接收器。
    1. imageReceiver =ImageReceiver.create(
    2.                                 Math.max(resoluteX, resoluteY),
    3.                                 Math.min(resoluteX, resoluteY),
    4.                                 ImageFormat.YUV420_888,
    5.                                 CameraConst.IMAGE_RCV_CAPACITY);
    复制代码

    2.设置帧接收器回调接口。
    1. imageReceiver.setImageArrivalListener(new ImageReceiver.IImageArrivalListener() {
    2.         [url=home.php?mod=space&uid=2735960]@Override[/url]
    3.         public void onImageArrival(ImageReceiver imageReceiver) {
    4.             //帧数据回调
    5.         }
    6. });
    复制代码
    3.开始连续捕获模式。
    1. frameConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
    2. try {
    3.         cameraDevice.triggerLoopingCapture(frameConfigBuilder.build());
    4. } catch (IllegalArgumentException e) {
    5.         LogUtil.info(TAG, "pushFlow is failed," + e.getMessage());
    6. }
    复制代码

  • 切换摄像头
    通过CameraKit获取手机的摄像头硬件id,通过id创建Camera实例,代码如下:
    1. private void cameraInit() {
    2. CameraKit camerakit = CameraKit.getInstance(context.getApplicationContext());
    3. if (camerakit != null && camerakit.getCameraIds().length > cameraType) {
    4.     String cameraId = camerakit.getCameraIds()[cameraType];
    5.     cameraSupportor = camerakit.getCameraAbility(cameraId);
    6.     CameraStateCallback cameraStateCallback = new MyCameraStatuCallback();
    7.     camerakit.createCamera(cameraId, cameraStateCallback, eventHandler);
    8.     captureInit();
    9. }
    10. }
    复制代码


5. YUV编码      
使用HarmonyOS编码器Codec对Camera获取的视频YUV数据进行编码,步骤如下:
步骤 1 -  初始化编码器。
  1. Format fmt = new Format();
  2. fmt.putStringValue(Format.MIME, Format.VIDEO_AVC);
  3. fmt.putIntValue(Format.WIDTH, controller.getResolution().height);
  4. fmt.putIntValue(Format.HEIGHT, controller.getResolution().width);
  5. fmt.putIntValue(Format.BIT_RATE, MediaConst.RECORDER_BIT_RATE);
  6. fmt.putIntValue(Format.COLOR_MODEL, CodecConst.CODEC_COLOR_MODEL);
  7. fmt.putIntValue(Format.FRAME_RATE, MediaConst.RECORDER_FRAME_RATE);
  8. fmt.putIntValue(Format.FRAME_INTERVAL, CodecConst.CODEC_FRAME_INTERVAL);
  9. fmt.putIntValue(Format.BITRATE_MODE, CodecConst.CODEC_BITRATE_MODE);
  10. videoEncoder = new CodecEncoder.Builder().setFormat(fmt).create();
复制代码
步骤 2 -  启动编码器。
  1. videoEncoder.openEncoder();
复制代码
步骤 3 -  开始编码,传入Camera获取的YUV帧数据。
  1. videoEncoder.startEncode(frame);
复制代码
步骤 4 -  设置编码成功回调,在回调中返回编码后数据,在本应用中在此回调中对数据解码播放。
  1. videoEncoder.setEncodeListener((byteBuffer, bufferInfo) -> {
  2.         
  3. byte[] buffers = new byte[bufferInfo.size];
  4.         
  5. byteBuffer.clear();
  6.         
  7. byteBuffer.get(buffers);
  8.         
  9. videoDecoder.startDecode(buffers);
  10.         });
复制代码

6. 视频源解码播放      
编码回调返回自定义编码格式数据,使用Codec对视频源进行播放,步骤如下:
步骤 1 -  初始化解码器,需要传入surface作为视频承载。
  1. videoDecoder = new CodecDecoder.Builder().setFormat(fmt). setSurface(surface).create();
复制代码
步骤 2 -  启动解码器。
  1. videoDecoder.openDecoder();
复制代码
步骤 3 -  开始解码。
  1. byte[] buffers = new byte[bufferInfo.size];
  2. byteBuffer.clear();
  3. byteBuffer.get(buffers);
  4. videoDecoder.startDecode(buffers);
复制代码

7. 恭喜你      
你已经成功学习了如何通过HarmonyOS编解码播放Camera的实时预览流。
   

8. 参考         

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友