剑痴乎

  • 首页
  • 文章分类
    • 音视频
    • WebRTC
    • 编程之美
    • Linux
    • Windows
    • 生活点滴
    • 校园生活
  • 参考
    • API参考
    • 实用工具
    • 测试音视频
    • 文档
  • 留言板
  • 关于
剑痴乎
代码为剑,如痴如醉
  1. 首页
  2. WebRTC
  3. 正文

WebRTC研究:MediaStream概念以及定义

2019年10月22日 2815点热度 12人点赞 1条评论

根据W3C的WebRTC 1.0: Real-time Communication Between Browsers规范,WebRTC的源码中定义了两套主要的C++接口,分别是MediaStream与PeerConnection相关的API。本篇文章主要介绍下MediaStream API中一些概念,方便理解内部代码如何处理。

MediaStream 相关API定义在源码api\media_stream_interface.h中。里面主要涉及这4个概念:source,sink,mediatrack,mediastream。

source与sink

在浏览器中,存在source到sink的媒体管道,source是生产媒体资源的,sink负责消费。传统的source一般是些静态资源,例如文件,以及web资源,不随时间改变。对于我们的WebRTC来说,source是动态资源,例如麦克风采集的音频,相机采集的视频,随时间而改变。sink的工作就是将这些source呈现给用户。sink可以是<img>,<video>,<audio>这些标签,用于本地渲染,也可以是RTCPeerConnection,将source通过网络传递到远端。在网络流传输中,RTCPeerConnection可同时扮演source与sink的角色,作为sink,可以将获取的source降低码率,缩放,调整帧率等,然后传递到远端,作为source,将获取的远端码流传递到本地渲染。

下面我们以video source举例,说下WebRTC源码中,source与sink定义。

在api\video\video_source_interface.h中,video source定义如下:

C++
1
2
3
4
5
6
7
8
9
10
11
template <typename VideoFrameT>
class VideoSourceInterface {
public:
  virtual ~VideoSourceInterface() = default;
 
  virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* sink,
                               const VideoSinkWants& wants) = 0;
  // RemoveSink must guarantee that at the time the method returns,
  // there is no current and no future calls to VideoSinkInterface::OnFrame.
  virtual void RemoveSink(VideoSinkInterface<VideoFrameT>* sink) = 0;
};

source可以添加、移除、更新sink,从而将VideoFrame送给对应的sink处理,一个source可对应多个sink。

在video\video_sink_interface.h中,video sink定义如下:

C++
1
2
3
4
5
6
7
8
9
10
11
template <typename VideoFrameT>
class VideoSinkInterface {
public:
  virtual ~VideoSinkInterface() = default;
 
  virtual void OnFrame(const VideoFrameT& frame) = 0;
 
  // Should be called by the source when it discards the frame due to rate
  // limiting.
  virtual void OnDiscardedFrame() {}
};

sink通过OnFrame获取source传递的VideoFrame。

MediaStreamTrack与MediaStream

MediaStream API中有两个重要组成:MediaStreamTrack以及MediaStream。MediaStreamTrack对象代表单一类型的媒体流,产生自客户端的media source,可以是音频或者视频,但只能是其中一种,是音频称作audio track,视频的话称作video track,这其实就是我们平时所说的音轨与视频轨。

一个track由source与sink组成。source给track提供数据。

Medi
aStream
用于将多个MediaStreamTrack对象打包到一起。一个MediaStream可包含audio track 与video track。类似我们平时的多媒体文件,可包含音频与视频。

一个MediaStream对象包含0或多个MediaStreamTrack对象。MediaStream中的所有MediaStreamTrack对象在渲染时必须同步。就像我们平时播放媒体文件时,音视频的同步。

简单点说,source 与sink构成一个track,多个track构成MediaStram。

在api\media_stream_interface.h中,MediaStream定义如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MediaStreamInterface : public rtc::RefCountInterface,
                             public NotifierInterface {
public:
  virtual std::string id() const = 0;
 
  virtual AudioTrackVector GetAudioTracks() = 0;
  virtual VideoTrackVector GetVideoTracks() = 0;
  virtual rtc::scoped_refptr<AudioTrackInterface> FindAudioTrack(
      const std::string& track_id) = 0;
  virtual rtc::scoped_refptr<VideoTrackInterface> FindVideoTrack(
      const std::string& track_id) = 0;
 
  virtual bool AddTrack(AudioTrackInterface* track) = 0;
  virtual bool AddTrack(VideoTrackInterface* track) = 0;
  virtual bool RemoveTrack(AudioTrackInterface* track) = 0;
  virtual bool RemoveTrack(VideoTrackInterface* track) = 0;
 
protected:
  ~MediaStreamInterface() override = default;
};

MediaStream可以添加移除audio track以及video track。

下面说下MediaTrack的定义,这里我们举例VideoTrack,代码同样位于api\media_stream_interface.h中。

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class VideoTrackInterface : public MediaStreamTrackInterface,
                            public rtc::VideoSourceInterface<VideoFrame> {
public:
  // Video track content hint, used to override the source is_screencast
  // property.
  // See https://crbug.com/653531 and https://w3c.github.io/mst-content-hint.
  enum class ContentHint { kNone, kFluid, kDetailed, kText };
 
  // Register a video sink for this track. Used to connect the track to the
  // underlying video engine.
  void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
                       const rtc::VideoSinkWants& wants) override {}
  void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
 
  virtual VideoTrackSourceInterface* GetSource() const = 0;
 
  virtual ContentHint content_hint() const;
  virtual void set_content_hint(ContentHint hint) {}
 
protected:
  ~VideoTrackInterface() override = default;
};

可以看到VideoTrack由video source与video sink组成。

pc\video_track.cc中,我们看下MediaTrack接口的一些具体实现:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void VideoTrack::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
                                 const rtc::VideoSinkWants& wants) {
  RTC_DCHECK(worker_thread_->IsCurrent());
  VideoSourceBase::AddOrUpdateSink(sink, wants);
  rtc::VideoSinkWants modified_wants = wants;
  modified_wants.black_frames = !enabled();
  video_source_->AddOrUpdateSink(sink, modified_wants);
}
 
void VideoTrack::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
  RTC_DCHECK(worker_thread_->IsCurrent());
  VideoSourceBase::RemoveSink(sink);
  video_source_->RemoveSink(sink);
}

由于VideoTrack由video source与video sink组成,所以对VideoTrack进行AddOrUpdateSink操作时,其实就是让VideoTrack的source进行AddOrUpdateSink。

示例

为了更好地理解上述概念,我们举个例子说明。下图home client中,摄像机产生视频video source。source的宽高设置分别是800以及600像素。home client 中三个MediaStream包含的track使用该摄像机视频作为source,此时就有三个video track了。三个video track分别连接三个不同的sink:<video>标签A,<video>标签B以及一个peer connection C。<video>A与<video>B分别对source的视频进行缩放处理后渲染到本地浏览器界面中。peer connection C作为sink把该video source 推流到remote client。在remote client,两个media stream使用peer connection作为source,连接到两个<video>sink(Y与Z),进行本地渲染。

参考

[1] Media Capture and Streams.https://www.w3.org/TR/mediacapture-streams/.
[2] WebRTC 1.0: Real-time Communication Between Browsers.http://w3c.github.io/webrtc-pc/.

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
标签: WebRTC
最后更新:2022年3月27日

Jeff

管理员——代码为剑,如痴如醉

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

版权声明

为支持原创,创作更好的文章,未经许可,禁止任何形式的转载与抄袭,如需转载请邮件私信!本人保留所有法定权利。违者必究!

文章目录
  • source与sink
  • MediaStreamTrack与MediaStream
  • 示例
  • 参考
最近评论
ztt 发布于 3 周前(04月05日) 你好,想看里面的视频和图片为什么没有显示呢?需要下flash吗还是什么。
huowa222 发布于 1 个月前(03月26日) 同问
邱国禄 发布于 2 个月前(02月17日) Receive Delta以0.25ms为单位,reference time以64ms为单位,kDe...
啊非 发布于 4 个月前(12月30日) 大神,请教一个问题: constexpr int kBaseScaleFactor = Tran...
啊非 发布于 4 个月前(12月30日) reference time:3字节,表示参考时间,以64ms为单位,但是 代码里面是 Trans...
相关文章
  • WebRTC资讯:H265支持进展
  • WebRTC研究:Audio level
  • Mac平台WebRTC编译
  • WebRTC研究:RTP时间戳的产生
  • WebRTC研究:统计参数之丢包率

COPYRIGHT © 2024 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang