Files
ZLMediaKit/webrtc/WebRtcPlayer.h
baigao-X 3fb43c5fef feat: 增加webrtc代理拉流 (#4389)
- 增加客户端模式,支持主动拉流、推流:
   - addStreamProxy接口新增支持whep主动拉流,拉流地址目前只兼容zlm的whep url。
   - addStreamPusherProxy接口新增支持whip主动推流,推流地址目前只兼容zlm的whip url。
   - 以上推流url格式为webrtc[s]://server_host:server_port/app/stream_id?key=value, 内部会自动转换为http[s]://server_host:server_port/index/api/[whip/whep]?app=app&stream=stream_id&key=value。

- 增加WebRtc p2p 模式:
  - 增加 ICE FULL模式。
  - 增加STUN/TURN 服务器。
  - 增加websocket 信令。
  - 增加P2P代理拉流。

---------

Co-authored-by: xia-chu <771730766@qq.com>
Co-authored-by: mtdxc <mtdxc@126.com>
Co-authored-by: cqm <cqm@97kid.com>
2025-09-20 16:23:30 +08:00

166 lines
5.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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