JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
  1. Main page
  2. WebRTC
  3. Main content

WebRTC研究:MediaStream概念以及定义

2019年10月22日 3149hotness 13likes 1comments

根据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/.

This article is licensed with Creative Commons Attribution-NonCommercial-No Derivatives 4.0 International License
Tag: WebRTC
Last updated:2022年3月27日

Jeff

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

Tip the author Like
< Last article
Next article >

Comments

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

文章目录
  • source与sink
  • MediaStreamTrack与MediaStream
  • 示例
  • 参考
Related Posts
  • 浅谈基于SFU实现一对一效果
  • WebRTC资讯:H265支持进展
  • Protected: WebRTC硬件编解码器出错无缝切换软编软解
  • WebRTC研究:Audio level
  • Mac平台WebRTC编译
Categories

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang