2025-09-20 16:23:30 +08:00
/*
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
*
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
*
* Use of this source code is governed by MIT - like license that can be found in the
* LICENSE file in the root of the source tree . All contributing project authors
* may be found in the AUTHORS file in the root of the source tree .
*/
# ifndef ZLMEDIAKIT_WEBRTCPLAYER_H
# define ZLMEDIAKIT_WEBRTCPLAYER_H
# include "WebRtcTransport.h"
# include "Rtsp/RtspMediaSource.h"
namespace mediakit {
/**
* @ brief H .264 B 帧 过 滤 器
* 用 于 从 H .264 RTP 流 中 移 除 B 帧
*/
class H264BFrameFilter {
public :
/**
* ISO_IEC_14496 - 10 - AVC - 2012
* Table 7 - 6 – Name association to slice_type
*/
enum H264SliceType {
H264SliceTypeP = 0 ,
H264SliceTypeB = 1 ,
H264SliceTypeI = 2 ,
H264SliceTypeSP = 3 ,
H264SliceTypeSI = 4 ,
H264SliceTypeP1 = 5 ,
H264SliceTypeB1 = 6 ,
H264SliceTypeI1 = 7 ,
H264SliceTypeSP1 = 8 ,
H264SliceTypeSI1 = 9 ,
} ;
enum H264NALUType {
NAL_NIDR = 1 ,
NAL_PARTITION_A = 2 ,
NAL_PARTITION_B = 3 ,
NAL_PARTITION_C = 4 ,
NAL_IDR = 5 ,
} ;
H264BFrameFilter ( ) ;
~ H264BFrameFilter ( ) = default ;
/**
* @ brief 处 理 单 个 RTP 包 , 移 除 B 帧
* @ param packet 输 入 的 RTP 包
* @ return 如 果 不 是 B 帧 则 返 回 原 包 , 否 则 返 回 nullptr
*/
RtpPacket : : Ptr processPacket ( const RtpPacket : : Ptr & packet ) ;
private :
/**
* @ brief 判 断 RTP 包 是 否 包 含 H .264 的 B 帧
* @ param packet RTP 包
* @ return 如 果 是 B 帧 返 回 true , 否 则 返 回 false
*/
bool isH264BFrame ( const RtpPacket : : Ptr & packet ) const ;
/**
* @ brief 根 据 NAL 类 型 和 数 据 判 断 是 否 是 B 帧
* @ param nal_type NAL 单 元 类 型
* @ param data NAL 单 元 数 据 ( 不 含 NAL 头 )
* @ param size 数 据 大 小
* @ return 如 果 是 B 帧 返 回 true , 否 则 返 回 false
*/
bool isBFrameByNalType ( uint8_t nal_type , const uint8_t * data , size_t size ) const ;
/**
* @ brief 解 析 指 数 哥 伦 布 编 码
* @ param data 数 据 缓 冲 区
* @ param size 缓 冲 区 大 小
* @ param bits_offset 位 偏 移 量
* @ return 解 析 出 的 数 值
*/
int decodeExpGolomb ( const uint8_t * data , size_t size , size_t & bitPos ) const ;
/**
* @ brief 从 比 特 流 中 读 取 位
* @ param data 数 据 缓 冲 区
* @ param size 缓 冲 区 大 小
* @ return 读 取 的 位 值 ( 0 或 1 )
*/
int getBit ( const uint8_t * data , size_t size ) const ;
/**
* @ brief 提 取 切 片 类 型 值
* @ param data 数 据 缓 冲 区
* @ param size 缓 冲 区 大 小
* @ return 切 片 类 型 值
*/
uint8_t extractSliceType ( const uint8_t * data , size_t size ) const ;
/**
* @ brief 处 理 FU - A分片
* @ param payload 数 据 缓 冲 区
* @ param payload_size 缓 冲 区 大 小
* @ return 如 果 是 B 帧 返 回 true , 否 则 返 回 false
*/
bool handleFua ( const uint8_t * payload , size_t payload_size ) const ;
/**
* @ brief 处 理 STAP - A 组 合 包
* @ param payload 数 据 缓 冲 区
* @ param payload_size 缓 冲 区 大 小
* @ return 如 果 是 B 帧 返 回 true , 否 则 返 回 false
*/
bool handleStapA ( const uint8_t * payload , size_t payload_size ) const ;
private :
uint16_t _last_seq ; // 维护输出流的序列号
uint32_t _last_stamp ; // 维护输出流的时间戳
bool _first_packet ; // 是否是第一个包的标记
} ;
class WebRtcPlayer : public WebRtcTransportImp {
public :
using Ptr = std : : shared_ptr < WebRtcPlayer > ;
static Ptr create ( const toolkit : : EventPoller : : Ptr & poller , const RtspMediaSource : : Ptr & src , const MediaInfo & info ,
WebRtcTransport : : Role role , WebRtcTransport : : SignalingProtocols signaling_protocols ) ;
MediaInfo getMediaInfo ( ) { return _media_info ; }
protected :
///////WebRtcTransportImp override///////
void onStartWebRTC ( ) override ;
void onDestory ( ) override ;
void onRtcConfigure ( RtcConfigure & configure ) const override ;
private :
WebRtcPlayer ( const toolkit : : EventPoller : : Ptr & poller , const RtspMediaSource : : Ptr & src , const MediaInfo & info ) ;
void sendConfigFrames ( uint32_t before_seq , uint32_t sample_rate , uint32_t timestamp , uint64_t ntp_timestamp ) ;
private :
// 媒体相关元数据 [AUTO-TRANSLATED:f4cf8045]
// Media related metadata
MediaInfo _media_info ;
// 播放的rtsp源 [AUTO-TRANSLATED:9963eed1]
// Playing rtsp source
std : : weak_ptr < RtspMediaSource > _play_src ;
// rtp 直接转发情况下通常会缺少 sps/pps, 在转发 rtp 前, 先发送一次相关帧信息, 部分情况下是可以播放的 [AUTO-TRANSLATED:65fdf16a]
// In the case of direct RTP forwarding, sps/pps is usually missing. Before forwarding RTP, send the relevant frame information once. In some cases, it can be played.
bool _send_config_frames_once { false } ;
// 播放rtsp源的reader对象 [AUTO-TRANSLATED:7b305055]
// Reader object for playing rtsp source
RtspMediaSource : : RingType : : RingReader : : Ptr _reader ;
bool _is_h264 { false } ;
bool _bfliter_flag { false } ;
std : : shared_ptr < H264BFrameFilter > _bfilter ;
} ;
} // namespace mediakit
# endif // ZLMEDIAKIT_WEBRTCPLAYER_H