Search code examples
c++webrtc

In the constructor of WebRTC VideoSendStreamParameters, why is the config argument not passed by a reference?


In the constructor of WebRTC VideoSendStreamParameters, config argument is passed by a value(thus introducing a copy overhead), but options argument is passed by a reference. Also the config member is initialized by std::move(config). I want to know why they designed like this.

The followings are scraped from Chromium source.

namespace webrtc {
...
class VideoSendStream {
  ...
  struct Config {
    ...
    Config() = delete;
    Config(Config&&);
    ... // It's followed by many data members.
  };
  ...
};
...
}



namespace cricket {
...
class WebRtcVideoChannel ... {
  ...
  class WebRtcVideoSendStream {
    ...
    struct VideoSendStreamParameters {
      VideoSendStreamParameters(
          webrtc::VideoSendStream::Config config,
          const VideoOptions& options, ...)
      ...
      webrtc::VideoSendStream::Config config;
      VideoOptions options;
      ...
    };
    VideoSendStreamParameters parameters_ ... ;
    ...
  };
  ...
};

WebRtcVideoChannel::WebRtcVideoSendStream::VideoSendStreamParameters::
    VideoSendStreamParameters(
        webrtc::VideoSendStream::Config config,
        const VideoOptions& options, ...)
    : config(std::move(config)),
      options(options), ... {}

WebRtcVideoChannel::WebRtcVideoSendStream::WebRtcVideoSendStream(
    ...
    webrtc::VideoSendStream::Config config,
    const VideoOptions& options, ...)
    : ...,
      parameters_(std::move(config), options, ...), ...
{
  ...  
}
...
}

Solution

  • Because the config is modified during the lifetime of the stream. Already in the stream constructor you have:

    parameters_.config.rtp.max_packet_size =
        std::min<size_t>(parameters_.config.rtp.max_packet_size, kVideoMtu);
    

    And in SetSendParameters, for example:

    parameters_.config.rtp.rtcp_mode = *params.rtcp_mode;
    

    When a class "owns" the data, it is a usual pattern to pass it by value and initialize the member with std::move. This is sometimes referred to as sink argument.

    EDIT

    Sorry, I missed the part that VideoOptions is also stored by value and is also modified in SetVideoSend():

    parameters_.options.SetAll(*options);
    

    With that, another explanation why Config is being moved, is that Config is intended to be mostly move-only type. Its assign operator is deleted, copy constructor is private and Copy() function commented with:

    Mostly used by tests. Avoid creating copies if you can.

    Why is that? Can't really tell for sure. It was changed in cc168360f413 as part of Issue 5687: Refactor Encoder - MediaTransport layer to use rtc::VideoSink/Source interface.