Android平台GB28181设备接入、RTMP推送模块如何实现高效率的视频编码

简介: 我们在做Android平台RTMP推送、轻量级RTSP服务和GB28181设备接入模块的时候,有一个点是逃不掉的:如何高效率的实现视频数据编码?

我们在做Android平台RTMP推送、轻量级RTSP服务和GB28181设备接入模块的时候,有一个点是逃不掉的:如何高效率的实现视频数据编码?


为此,我们设计了软编码、基于MediaCodec的硬编码和MediaCodec native层硬编,尽可能的减少数据拷贝和交互,确保高效率的完成视频编码,目前,编码前数据类型,已经涵盖了YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型,无论是自己采集的数据,还是Android摄像头和camera2和屏幕采集的数据,均可实现高效率的编码。


尽管软编码有各种好处,但受限于设备配置,超过720p的,在一些特定设备,软编总是差强人意,所以Android平台,在设备允许的前提下,还是需要精细化的硬编解决方案。


为此,我们设计了以下接口:

     /**
    * Set Video H.264 HW Encoder, if support HW encoder, it will return 0(设置H.264硬编码)
    * 
    * @param kbps: the kbps of different resolution.
    * 
    * @return {0} if successful
    */
   public native int SetSmartPublisherVideoHWEncoder(long handle, int kbps);
  /**
   * Set Video H.265(hevc) hardware encoder, if support H.265(hevc) hardware encoder, it will return 0(设置H.265硬编码)
   *
   * @param kbps: the kbps of different resolution.
   *
   * @return {0} if successful
   */
  public native int SetSmartPublisherVideoHevcHWEncoder(long handle, int kbps);

两个接口,分别对应设置264、265硬编,如果不支持,自动切换到软编。


码率模式选择:

  /*
  * 设置视频硬编码码率控制模式
  * @param hw_bitrate_mode: -1表示使用默认值, 不设置也会使用默认值, 0:CQ, 1:VBR, 2:CBR, 3:CBR_FD, 请参考:android.media.MediaCodecInfo.EncoderCapabilities
  * 注意硬编码和手机硬件有关,多数手机只支持部分码率模式, 另外硬编码设备差异很大,不同设备同一码率控制模式效果可能不一样
  * @return {0} if successful
  */
  public native int SetVideoHWEncoderBitrateMode(long handle, int hw_bitrate_mode);

视频硬编码复杂度设置:

  /*
   * 设置视频硬编码复杂度, 安卓5.0及以上支持
   * @param hw_complexity: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getComplexityRange() 和 android.media.MediaFormat.KEY_COMPLEXITY
   * 注意硬编码和手机硬件有关,部分手机可能不支持此设置
   * @return {0} if successful
   */
  public native int SetVideoHWEncoderComplexity(long handle, int hw_complexity);

视频硬编码质量设置:

  /*
   * 设置视频硬编码质量, 安卓9及以上支持, 仅当硬编码器码率控制模式(BitrateMode)是CQ(constant-quality mode)时才有效
   * @param hw_quality: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getQualityRange() 和 android.media.MediaFormat.KEY_QUALITY
   * 注意硬编码和手机硬件有关,部分手机可能不支持此设置
   * @return {0} if successful
   */
  public native int SetVideoHWEncoderQuality(long handle, int hw_quality);

H.264硬编码Profile设置:

  /*
   * 设置H.264硬编码Profile, 安卓7及以上支持
   * @param hw_avc_profile: 0表示使用默认值, 0x01: Baseline, 0x02: Main, 0x08: High, 0x10000: ConstrainedBaseline, 0x80000: ConstrainedHigh;
   * 注意: ConstrainedBaseline 和 ConstrainedHigh 可能多数设备不支持,
   * H.264推荐使用 High 或者 ConstrainedHigh, 如果您使用的手机硬解码解不了,那还是设置Baseline
   * 如果设置的Profile硬编码器不支持,应编码器会使用默认值
   * 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
   * @return {0} if successful
   */
  public native int SetAVCHWEncoderProfile(long handle, int hw_avc_profile);

H.264硬编码Level设置:

  /*
   * 设置H.264硬编码Level, 这个只有在设置了Profile的情况下才有效, 安卓7及以上支持
   * @param hw_avc_level: 0表示使用默认值, 0x100: Level3, 0x200: Level3.1, 0x400: Level3.2,
   * 0x800: Level4, 0x1000: Level4.1, 0x2000: Level4.2,
   * 0x4000: Level5, 0x8000: Level5.1,  0x10000: Level5.2,
   * 0x20000: Level6, 0x40000: Level6.1,  0x80000: Level6.2,
   * 如果设置的level太高硬编码器不支持,SDK内部会做相应调整
   * 注意: 640*480@25fps最小支持的是Level3, 720p最小支持的是Level3.1, 1080p最小支持的是Level4
   * 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
   * @return {0} if successful
   */
  public native int SetAVCHWEncoderLevel(long handle, int hw_avc_level);

视频硬编码最大码率设置:

  /*
   * 设置视频硬编码最大码率, 安卓没有相关文档说明, 所以不建议设置,
   * @param hw_max_bitrate: 每秒最大码率, 单位bps
   * @return {0} if successful
   */
  public native int SetVideoHWEncoderMaxBitrate(long handle, long hw_max_bitrate);

上层调用代码如下:

        if(videoEncodeType == 1)  {
            int h264HWKbps = setHardwareEncoderKbps(true, videoWidth, videoHeight);
            h264HWKbps = h264HWKbps*fps/25;
            Log.i(TAG, "h264HWKbps: " + h264HWKbps);
            int isSupportH264HWEncoder = libPublisher
                    .SetSmartPublisherVideoHWEncoder(publisherHandle, h264HWKbps);
            if (isSupportH264HWEncoder == 0) {
                libPublisher.SetNativeMediaNDK(publisherHandle, 0);
                libPublisher.SetVideoHWEncoderBitrateMode(publisherHandle, 1); // 0:CQ, 1:VBR, 2:CBR
                libPublisher.SetVideoHWEncoderQuality(publisherHandle, 39);
                libPublisher.SetAVCHWEncoderProfile(publisherHandle, 0x08); // 0x01: Baseline, 0x02: Main, 0x08: High
                // libPublisher.SetAVCHWEncoderLevel(publisherHandle, 0x200); // Level 3.1
                // libPublisher.SetAVCHWEncoderLevel(publisherHandle, 0x400); // Level 3.2
                // libPublisher.SetAVCHWEncoderLevel(publisherHandle, 0x800); // Level 4
                libPublisher.SetAVCHWEncoderLevel(publisherHandle, 0x1000); // Level 4.1 多数情况下,这个够用了
                //libPublisher.SetAVCHWEncoderLevel(publisherHandle, 0x2000); // Level 4.2
                // libPublisher.SetVideoHWEncoderMaxBitrate(publisherHandle, ((long)h264HWKbps)*1300);
                Log.i(TAG, "Great, it supports h.264 hardware encoder!");
            }
        }
        else if (videoEncodeType == 2) {
            int hevcHWKbps = setHardwareEncoderKbps(false, videoWidth, videoHeight);
            hevcHWKbps = hevcHWKbps*fps/25;
            Log.i(TAG, "hevcHWKbps: " + hevcHWKbps);
            int isSupportHevcHWEncoder = libPublisher
                    .SetSmartPublisherVideoHevcHWEncoder(publisherHandle, hevcHWKbps);
            if (isSupportHevcHWEncoder == 0) {
                libPublisher.SetNativeMediaNDK(publisherHandle, 0);
                libPublisher.SetVideoHWEncoderBitrateMode(publisherHandle, 0); // 0:CQ, 1:VBR, 2:CBR
                libPublisher.SetVideoHWEncoderQuality(publisherHandle, 39);
                // libPublisher.SetVideoHWEncoderMaxBitrate(publisherHandle, ((long)hevcHWKbps)*1200);
                Log.i(TAG, "Great, it supports hevc hardware encoder!");
            }
        }

从实际测试来看,基于MediaCodec的硬编码相对软编来说,虽然不一定有软编码率各个方面控制的那么好,但是正确的调用MediaCodec硬编,可以显著提高视频编码能力,让1080P甚至更高分辨率帧率码率的视频编码,效率更高。

相关文章
|
7月前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
326 64
|
7月前
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
423 64
|
7月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
1254 62
|
7月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
439 61
|
4月前
|
监控 Android开发 数据安全/隐私保护
批量发送短信的平台,安卓群发短信工具插件脚本,批量群发短信软件【autojs版】
这个Auto.js脚本实现了完整的批量短信发送功能,包含联系人管理、短信内容编辑、发送状态监控等功能
|
8月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
29天前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
187 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
1月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
230 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
1月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
490 3
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
467 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡

热门文章

最新文章