亚马逊AWS官方博客

在Amazon Kinesis Video Streams WebRTC中增加H265编解码支持

1.概述

本文主要介绍Amazon Kinesis Video Streams WebRTC是什么,H.265编解码器相比H.264的技术优势,在Amazon Kinesis Video Streams WebRTC中集成H.265编解码器的完整技术方案,详细实现步骤,以及生产环境部署的注意事项。

通过本文,您将学会如何利用H.265编解码器在保持视频质量的同时显著降`低带宽消耗,提升Amazon Kinesis Video Streams WebRTC应用的整体性能表现。

2.背景介绍

2.1 Amazon Kinesis Video Streams WebRTC简介

Amazon Kinesis Video Streams 提供符合标准的 WebRTC 实现作为完全托管的功能。您可以使用 Amazon Kinesis Video Streams with WebRTC 安全地进行媒体的实时流式传输,或在任何摄像头 IoT 设备与符合 WebRTC 的移动或 Web 播放器之间执行双向音频或视频交互。借助这项全面托管的功能,您不必构建、运营或扩展任何与 WebRTC 相关的云基础设施(例如信令或媒体中继服务器)便能安全地在应用程序和设备间流式传输媒体。

2.1.1 Amazon KVS WebRTC的拓扑结构

2.1.2 Amazon KVS WebRTC的架构图

2.2 Amazon Kinesis Video Streams WebRTC支持的编解码器

音频

  • G.711 A-Law
  • G.711 U-Law
  • Opus

视频

  • H.264
  • VP8

2.3 H.265编解码器技术优势

2.4 H265对比H264的优势

  • 压缩率更高,相同清晰度的前提下,码率只有一半
  • 对网络带宽要求低,弱网更顺畅
  • 相同码率的前提下,清晰度更高
  • Relay时DTO费用更低
  • 能支持更大像素的IPC产品

2.5 H265支持情况

  • iOS从iPhone7开始就已经支持H265硬件编解码
  • Android从2016年机型开始大多支持H265硬件编解码
  • 安防芯片方案,几乎都支持H265硬件编码

2.6 为什么在KVS WebRTC中需要H.265支持

  • 对网络带宽要求低,弱网更顺畅
  • 相同码率的前提下,清晰度更高
  • Relay时DTO费用更低
  • 能支持更大像素的IPC产品

3. 技术实现方案

3.1 整体架构设计

  • 修改设备端SDK
  • 修改客户端NDK
  • 无需修改服务端KVS

3.2 关键技术实现点

3.2.1 SDP中添加H265编解码格式

  • a=rtpmap:127 H265/90000SDP(Session Description Protocol)中的”a=rtpmap”用于描述RTP(Real-time Transport Protocol)流中的编解码器参数。具体来说,它指定了RTP负载中使用的编解码器以及它们的时钟速率。在”a=rtpmap:127 H265/90000″中,”127″是RTP负载类型(Payload Type),用于标识RTP负载中使用的媒体类型。”H265″表示使用的编解码器为H.265(也称为HEVC),”90000″是该编解码器的时钟速率,单位是Hz。
  • 设备端代码修改:amazon-kinesis-video-streams-webrtc-sdk-c/src/source/PeerConnection/SessionDescription.c
  • iOS客户端修改:webrtc/sdk/objc/components/video_codec/RTCDefaultVideoDecoderFactory.m
  • Android客户端修改:webrtc/sdk/android/src/java/org/webrtc/MediaCodecVideoDecoderFactory.java

3.2.2 RTP载荷的封包与解包

  • 参照文档:H265的Rtp封包与解包,参照H265的Rtp规范rfc7798,链接:https://www.rfc-editor.org/rfc/rfc7798.html
  • 特别注意:H265的NAL包会大于MTU 1200,所以需要对NAL进行分包,否则会异常,分包策略,rfc7798的文档中有介绍,格式如下图
  • 设备端代码实现:amazon-kinesis-video-streams-webrtc-sdk-c/src/source/Rtp/Codecs/RtpH265Payloader.c
  • iOS和Android的NDK实现:webrtc/modules/video_coding/h265_vps_sps_pps_tracker.cc

3.2.3 实际数据的H265编解码

  • 设备端编码:芯片自带H265的硬编码,绝大多数方案商已经缴纳专利费,芯片有相应SDK提供接口获取H265帧
  • iOS客户端解码:webrtc/sdk/objc/components/video_codec/RTCVideoDecoderFactoryH265.m
  • Android客户端:webrtc/sdk/android/src/java/org/webrtc/HardwareVideoDecoder.java

4. 具体实现步骤

4.1 环境准备

修改涉及到设备端SDK的修改和客户端NDK的修改,需要具备代码编辑和编译环境,其中设备端使用Linux进行编辑和编译,Android也使用Linux进行编译,iOS则使用Mac环境进行编译

4.2 设备端实现

4.2.1 H.265 RTP载荷处理器

  • src/source/PeerConnection/Rtp/Codecs/RtpH265Payloader.h – 头文件定义
  • src/source/PeerConnection/Rtp/Codecs/RtpH265Payloader.c – 实现文件
STATUS createPayloadFromNaluH265(UINT32 mtu, PBYTE nalu, UINT32 naluLength, PPayloadArray pPayloadArray, PUINT32 filledLength,
                                 PUINT32 filledSubLenSize)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    PBYTE pPayload = NULL;
    UINT8 naluType = 0;
    UINT32 maxPayloadSize = 0;
    UINT32 curPayloadSize = 0;
    UINT32 remainingNaluLength = naluLength;
    UINT32 payloadLength = 0;
    UINT32 payloadSubLenSize = 0;
    PBYTE pCurPtrInNalu = NULL;
    BOOL sizeCalculationOnly = (pPayloadArray == NULL);

    CHK(nalu != NULL && filledLength != NULL && filledSubLenSize != NULL, STATUS_NULL_ARG);
    CHK(sizeCalculationOnly || (pPayloadArray->payloadSubLength != NULL && pPayloadArray->payloadBuffer != NULL), STATUS_NULL_ARG);
    CHK(mtu > H265_FU_HEADER_SIZE, STATUS_RTP_INPUT_MTU_TOO_SMALL);

    naluType = (nalu[0] & 0x7E) >> 1; // 6 bits after forbidden zero bit 0x7E(0111 1110)

    if (!sizeCalculationOnly) {
        pPayload = pPayloadArray->payloadBuffer;
    }

    if (naluLength <= mtu) {
        // Single NALU https://www.rfc-editor.org/rfc/rfc7798.html#section-4.4.1
        payloadLength += naluLength;
        payloadSubLenSize++;

        if (!sizeCalculationOnly) {
            CHK(payloadSubLenSize <= pPayloadArray->maxPayloadSubLenSize && payloadLength <= pPayloadArray->maxPayloadLength,
                STATUS_BUFFER_TOO_SMALL);

            MEMCPY(pPayload, nalu, naluLength);
            pPayloadArray->payloadSubLength[payloadSubLenSize - 1] = naluLength;
            pPayload += pPayloadArray->payloadSubLength[payloadSubLenSize - 1];
        }
    } else {
        // Fragmentation units: https://www.rfc-editor.org/rfc/rfc7798.html#section-4.4.3
        maxPayloadSize = mtu - H265_FU_HEADER_SIZE;

        // According to the RFC, the first octet is skipped due to redundant information
        remainingNaluLength -= 2;
        pCurPtrInNalu = nalu + 2;

        while (remainingNaluLength != 0) {
            curPayloadSize = MIN(maxPayloadSize, remainingNaluLength);
            payloadSubLenSize++;
            payloadLength += H265_FU_HEADER_SIZE + curPayloadSize;

            if (!sizeCalculationOnly) {
                CHK(payloadSubLenSize <= pPayloadArray->maxPayloadSubLenSize && payloadLength <= pPayloadArray->maxPayloadLength,
                    STATUS_BUFFER_TOO_SMALL);

                pPayload[0] = (H265_FU_TYPE_ID << 1) | (nalu[0] & 0x81) | (nalu[0] & 0x1); // H265_FU_TYPE_ID indicator is 49
                pPayload[1] = nalu[1] & 0xff;
                pPayload[2] = naluType & 0x3f;
                if (remainingNaluLength == naluLength - 2) {
                    pPayload[2] |= (1 << 7); // Set for starting bit
                } else if (remainingNaluLength == curPayloadSize) {
                    pPayload[2] |= (1 << 6); // Set for ending bit
                }

                MEMCPY(pPayload + H265_FU_HEADER_SIZE, pCurPtrInNalu, curPayloadSize);

                pPayloadArray->payloadSubLength[payloadSubLenSize - 1] = H265_FU_HEADER_SIZE + curPayloadSize;
                pPayload += pPayloadArray->payloadSubLength[payloadSubLenSize - 1];
            }

            pCurPtrInNalu += curPayloadSize;
            remainingNaluLength -= curPayloadSize;
        }
    }

CleanUp:
    if (STATUS_FAILED(retStatus) && sizeCalculationOnly) {
        payloadLength = 0;
        payloadSubLenSize = 0;
    }

    if (filledLength != NULL && filledSubLenSize != NULL) {
        *filledLength = payloadLength;
        *filledSubLenSize = payloadSubLenSize;
    }

    LEAVES();
    return retStatus;
}
  • 遵循RFC 7798标准,支持分片单元(FU)处理
  • 关键常量:H265_FU_HEADER_SIZE (3), H265_FU_TYPE_ID (49)

4.2.2 核心处理函数

  • createPayloadForH265 – 创建H.265载荷
  • getNextNaluLengthH265 – 获取下一个NALU长度
  • createPayloadFromNaluH265 – 从NALU创建载荷
  • depayH265FromRtpPayload – 从RTP载荷中解包H.265

4.2.3 编解码器集成

  • 编解码器枚举:RTC_CODEC_H265
  • 默认载荷类型:DEFAULT_PAYLOAD_H265 (127)
  • RTX重传支持:RTC_RTX_CODEC_H265

4.2.4 会话描述协议处理

  • src/source/PeerConnection/SessionDescription.c 中的H.265 SDP处理
  • SDP值配置:”H265/90000″ 用于rtpmap
  • 格式参数:DEFAULT_H265_FMTP 中的profile参数

4.2.5 样本帧文件

  • samples/h265SampleFrames/ 目录包含1,500个H.265样本帧文件
  • 文件大小范围:329字节到11,840字节
  • 涵盖I帧(关键帧)和P帧(预测帧)的完整测试集

4.2.6 数据包处理

  • src/source/PeerConnection/Rtp.c 中的H.265载荷创建
  • 时间戳处理和RTP数据包封装
  • 支持大于MTU的NALU单元的分片处理

4.2.7 样本程序支持

  • kvsWebrtcClientMaster – 支持H.265视频编解码器参数
  • kvsWebrtcClientMasterGstSample – GStreamer H.265集成
  • kvsWebrtcClientViewer – H.265接收和解码

这些组件共同构成了完整的H.265 WebRTC传输管道,从编码、RTP封装、SDP协商到最终的网络传输,提供了全面的H.265视频编解码器支持。

4.3 客户端实现

4.3.1 核心配置

  • 构建开关: rtc_use_h265 在 build_overrides/build.gni 中定义
  • 平台支持: 默认在 Windows、iOS、Android 平台启用H.265
  • 编译宏: 使用 DISABLE_H265 宏来控制H.265功能的编译

4.3.2 H.265解析和处理模块 (common_video/h265/)

  • h265_common.h/cc – H.265通用定义和NALU处理
  • h265_bitstream_parser.h/cc – H.265比特流解析器
  • h265_sps_parser.h/cc – 序列参数集(SPS)解析
  • h265_pps_parser.h/cc – 图像参数集(PPS)解析
  • h265_vps_parser.h/cc – 视频参数集(VPS)解析

4.3.3 RTP打包和解包 (modules/rtp_rtcp/source/)

  • rtp_format_h265.h/cc – H.265 RTP打包器
  • video_rtp_depacketizer_h265.h/cc – H.265 RTP解包器
  • h265_sps_parser.h/cc – RTP层的SPS解析

4.3.4 视频编解码接口 (modules/video_coding/)

  • h265_vps_sps_pps_tracker.h/cc – H.265参数集跟踪器
  • h265_globals.h – H.265全局定义和数据结构
  • 支持H.265的编解码器接口集成

4.3.5 API层支持 (api/video_codecs/)

  • video_codec_type.h – 定义 kVideoCodecH265 枚举
  • video_codec.h/cc – H.265编解码器配置
  • video_encoder.h/cc – H.265编码器接口

4.3.6 平台特定实现

  • iOS/macOS: sdk/objc/components/video_codec/ 下的H.265硬件编解码器
  • RTCVideoEncoderH265.h/mm
  • RTCVideoDecoderH265.h/mm
  • RTCVideoEncoderFactoryH265.h/m
  • RTCVideoDecoderFactoryH265.h/m
  • Android: sdk/android/src/jni/ 下的JNI包装器

4.3.7 媒体常量定义 (media/base/)

  • media_constants.h/cc – H.265编解码器名称和FMTP参数定义

4.3.8 关键特性

  • NALU类型支持: 支持VPS、SPS、PPS、IDR、CRA等NALU类型
  • RTP打包模式: 支持单NALU、聚合包(AP)、分片单元(FU)
  • 参数集管理: 自动跟踪和管理VPS/SPS/PPS参数集
  • 硬件加速: 在支持的平台上使用硬件编解码器

这个WebRTC工程提供了完整的H.265/HEVC支持,包括比特流解析、RTP传输、编解码器接口和平台特定的硬件加速实现。

5. 测试与验证

5.1 设备端测试

5.1.1 下载仓库

Shell
git clone --recursive https://github.com/hongliwo/amazon-kvs-webrtc-sdk-c.git

5.1.2 编译

Shell
mkdir -p amazon-kvs-webrtc-sdk-c/build; cd amazon-kvs-webrtc-sdk-c/build; cmake ..

5.1.3 配置

Shell
export AWS_KVS_LOG_LEVEL=1
export AWS_KVS_CACERT_PATH=../certs/cert.pem
export AWS_DEFAULT_REGION=cn-north-1
export AWS_ACCESS_KEY_ID=<AWS account access key>
export DEBUG_LOG_SDP=TRUE
export AWS_SECRET_ACCESS_KEY=<AWS account secret key>
export AWS_IOT_CORE_THING_NAME=demo-channel
export AWS_ENABLE_FILE_LOGGING=TRUE

5.1.4 执行

Shell
./samples/kvsWebrtcClientMaster demo-channel-250422 0 aac h265

2025-08-11 15:36:18.436 INFO    main(): [KVS Master] Finished setting handlers
2025-08-11 15:36:18.437 INFO    main(): [KVS Master] Checked H265 sample video frame availability....available
2025-08-11 15:36:18.437 INFO    main(): [KVS Master] Checked AAC sample audio frame availability....available
2025-08-11 15:36:18.437 INFO    initKvsWebRtc(): Initializing WebRTC library...
2025-08-11 15:36:18.437 PROFILE createRtcCertificate(): [Certificate creation time] Time taken: 0 ms
2025-08-11 15:36:18.437 VERBOSE pregenerateCertTimerCallback(): New certificate has been pre-generated and added to the queue
2025-08-11 15:36:18.439 INFO    initKvsWebRtc(): SDK version: 339f24ff4eb03d430d11d0ba6bf63e7946fbfbd8
2025-08-11 15:36:18.440 INFO    main(): [KVS Master] KVS WebRTC initialization completed successfully
2025-08-11 15:36:18.440 INFO    createSignalingClientSync(): Creating Signaling Client Sync

5.2 客户端测试

5.2.1 下载仓库

Shell
git clone https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-android.git

5.2.2 配置

{
 "Version": "1.0",
 "CredentialsProvider": {
   "CognitoIdentity": {
     "Default": {
       "PoolId": "us-west-2:01234567-89ab-cdef-0123-456789abcdef",
       "Region": "us-west-2"
     }
   }
 },
 "IdentityManager": {
   "Default": {}
 },
 "CognitoUserPool": {
   "Default": {
     "AppClientSecret": "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmno",
     "AppClientId": "0123456789abcdefghijklmnop",
     "PoolId": "us-west-2_qRsTuVwXy",
     "Region": "us-west-2"
   }
 }
}

5.2.3 编译

5.2.4 执行

  • Offer信息
Shell
v=0
o=- 7480476679476587374 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1 2
a=extmap-allow-mixed
a=msid-semantic: WMS KvsLocalMediaStream
m=video 9 UDP/TLS/RTP/SAVPF 97 98 99 127
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:iFY5
a=ice-pwd:L20ejiZ+tskNcmIB4qyMzg7F
a=ice-options:trickle renomination
a=fingerprint:sha-256 88:0B:73:50:7D:12:5F:A2:03:D5:42:E2:FB:E2:D2:AE:0C:11:F0:EC:0B:B9:32:56:D5:CB:1E:D0:C8:59:EB:0A
a=setup:actpass
a=mid:0
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=sendrecv
a=msid:KvsLocalMediaStream KvsVideoTrack
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=127
a=rtpmap:98 H265/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=ssrc-group:FID 2784008413 3278131480
a=ssrc:2784008413 cname:T1CdhfY8ekoTvjl9
a=ssrc:2784008413 msid:KvsLocalMediaStream KvsVideoTrack
a=ssrc:3278131480 cname:T1CdhfY8ekoTvjl9
a=ssrc:3278131480 msid:KvsLocalMediaStream KvsVideoTrack
m=audio 9 UDP/TLS/RTP/SAVPF 96 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:iFY5
a=ice-pwd:L20ejiZ+tskNcmIB4qyMzg7F
a=ice-options:trickle renomination
a=fingerprint:sha-256 88:0B:73:50:7D:12:5F:A2:03:D5:42:E2:FB:E2:D2:AE:0C:11:F0:EC:0B:B9:32:56:D5:CB:1E:D0:C8:59:EB:0A
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:96 AAC/16000
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=ice-ufrag:iFY5
a=ice-pwd:L20ejiZ+tskNcmIB4qyMzg7F
a=ice-options:trickle renomination
a=fingerprint:sha-256 88:0B:73:50:7D:12:5F:A2:03:D5:42:E2:FB:E2:D2:AE:0C:11:F0:EC:0B:B9:32:56:D5:CB:1E:D0:C8:59:EB:0A
a=setup:actpass
a=mid:2
a=sctp-port:5000
a=max-message-size:262144
  • Answer信息
Shell
v=0
o=- 1839451543 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1 2
a=ice-options:trickle
a=msid-semantic: WMS myKvsVideoStream
m=video 9 UDP/TLS/RTP/SAVPF 127
c=IN IP4 127.0.0.1
a=candidate:0 1 udp 2130706431 172.31.6.139 49869 typ host raddr 0.0.0.0 rport 0 generation 0 network-cost 999
a=msid:myKvsVideoStream myVideoTrack
a=ssrc:1319433733 cname:OFH2DfVtzdnar0C8
a=ssrc:1319433733 msid:myKvsVideoStream myVideoTrack
a=ssrc:1319433733 mslabel:myKvsVideoStream
a=ssrc:1319433733 label:myVideoTrack
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:g+OT
a=ice-pwd:gJ8wdDEeJfgk+6QmHYVmS+7C
a=ice-options:trickle
a=fingerprint:sha-256 26:D2:F8:C3:B5:6D:F5:CC:27:56:D9:58:84:A7:D5:A8:8B:FE:67:9D:CD:01:C4:DD:37:FE:77:12:08:6B:01:2E
a=setup:active
a=mid:0
a=sendrecv
a=rtcp-mux
a=rtpmap:127 H265/90000
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=ssrc:1319433733 cname:OFH2DfVtzdnar0C8
a=ssrc:1319433733 msid:myKvsVideoStream myVideoTrack
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
m=audio 9 UDP/TLS/RTP/SAVPF 96
c=IN IP4 127.0.0.1
a=candidate:0 1 udp 2130706431 172.31.6.139 49869 typ host raddr 0.0.0.0 rport 0 generation 0 network-cost 999
a=msid:myKvsVideoStream myAudioTrack
a=ssrc:680554637 cname:OFH2DfVtzdnar0C8
a=ssrc:680554637 msid:myKvsVideoStream myAudioTrack
a=ssrc:680554637 mslabel:myKvsVideoStream
a=ssrc:680554637 label:myAudioTrack
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:g+OT
a=ice-pwd:gJ8wdDEeJfgk+6QmHYVmS+7C
a=ice-options:trickle
a=fingerprint:sha-256 26:D2:F8:C3:B5:6D:F5:CC:27:56:D9:58:84:A7:D5:A8:8B:FE:67:9D:CD:01:C4:DD:37:FE:77:12:08:6B:01:2E
a=setup:active
a=mid:1
a=sendonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 AAC/16000
a=ssrc:680554637 cname:OFH2DfVtzdnar0C8
a=ssrc:680554637 msid:myKvsVideoStream myAudioTrack
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 127.0.0.1
a=candidate:0 1 udp 2130706431 172.31.6.139 49869 typ host raddr 0.0.0.0 rport 0 generation 0 network-cost 999
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:g+OT
a=ice-pwd:gJ8wdDEeJfgk+6QmHYVmS+7C
a=ice-options:trickle
a=fingerprint:sha-256 26:D2:F8:C3:B5:6D:F5:CC:27:56:D9:58:84:A7:D5:A8:8B:FE:67:9D:CD:01:C4:DD:37:FE:77:12:08:6B:01:2E
a=setup:active
a=mid:2
a=sctp-port:5000
  • 实时画面

6. 总结

本文介绍了如何在Amazon Kinesis Video Streams WebRTC中成功集成H.265编解码器支持。通过详细的技术方案设计、完整的实现步骤和全面的测试验证,我们展示了H.265在实时视频通信场景下的显著优势。

附录

参考资料

代码仓库

本篇作者

王红力

亚马逊云科技解决方案架构师,目前在制造业智能家居行业担任解决方案架构师,在设备连接、实时音视频方面有深入的理解,在入职亚马逊云科技之前,一直专注于IoT、安防领域,有15年开发和架构经验,在音视频处理和编解码方面有丰富的实践经验。