tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

screencast_stream_utils.cc (5160B)


      1 /*
      2 *  Copyright 2022 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/desktop_capture/linux/wayland/screencast_stream_utils.h"
     12 
     13 #include <libdrm/drm_fourcc.h>
     14 #include <pipewire/pipewire.h>
     15 #include <spa/param/format.h>
     16 #include <spa/param/param.h>
     17 #include <spa/pod/builder.h>
     18 #include <spa/pod/iter.h>
     19 #include <spa/pod/pod.h>
     20 #include <spa/pod/vararg.h>
     21 #include <spa/utils/type.h>
     22 
     23 #include <cstdint>
     24 #include <optional>
     25 #include <tuple>
     26 #include <vector>
     27 
     28 #include "absl/strings/string_view.h"
     29 #include "rtc_base/string_encode.h"
     30 #include "rtc_base/string_to_number.h"
     31 
     32 #if !PW_CHECK_VERSION(0, 3, 29)
     33 #define SPA_POD_PROP_FLAG_MANDATORY (1u << 3)
     34 #endif
     35 #if !PW_CHECK_VERSION(0, 3, 33)
     36 #define SPA_POD_PROP_FLAG_DONT_FIXATE (1u << 4)
     37 #endif
     38 
     39 namespace webrtc {
     40 
     41 PipeWireVersion PipeWireVersion::Parse(const absl::string_view& version) {
     42  std::vector<absl::string_view> parsed_version = split(version, '.');
     43 
     44  if (parsed_version.size() != 3) {
     45    return {};
     46  }
     47 
     48  std::optional<int> major = StringToNumber<int>(parsed_version.at(0));
     49  std::optional<int> minor = StringToNumber<int>(parsed_version.at(1));
     50  std::optional<int> micro = StringToNumber<int>(parsed_version.at(2));
     51 
     52  // Return invalid version if we failed to parse it
     53  if (!major || !minor || !micro) {
     54    return {};
     55  }
     56 
     57  return {
     58      .major = major.value(), .minor = minor.value(), .micro = micro.value()};
     59 }
     60 
     61 bool PipeWireVersion::operator>=(const PipeWireVersion& other) {
     62  if (!major && !minor && !micro) {
     63    return false;
     64  }
     65 
     66  return std::tie(major, minor, micro) >=
     67         std::tie(other.major, other.minor, other.micro);
     68 }
     69 
     70 bool PipeWireVersion::operator<=(const PipeWireVersion& other) {
     71  if (!major && !minor && !micro) {
     72    return false;
     73  }
     74 
     75  return std::tie(major, minor, micro) <=
     76         std::tie(other.major, other.minor, other.micro);
     77 }
     78 
     79 spa_pod* BuildFormat(spa_pod_builder* builder,
     80                     uint32_t format,
     81                     const std::vector<uint64_t>& modifiers,
     82                     const struct spa_rectangle* resolution,
     83                     const struct spa_fraction* frame_rate) {
     84  spa_pod_frame frames[2];
     85  spa_rectangle pw_min_screen_bounds = spa_rectangle{.width = 1, .height = 1};
     86  spa_rectangle pw_max_screen_bounds =
     87      spa_rectangle{.width = UINT32_MAX, .height = UINT32_MAX};
     88  spa_pod_builder_push_object(builder, &frames[0], SPA_TYPE_OBJECT_Format,
     89                              SPA_PARAM_EnumFormat);
     90  spa_pod_builder_add(builder, SPA_FORMAT_mediaType,
     91                      SPA_POD_Id(SPA_MEDIA_TYPE_video), 0);
     92  spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype,
     93                      SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 0);
     94  spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(format), 0);
     95 
     96  if (!modifiers.empty()) {
     97    if (modifiers.size() == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
     98      spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier,
     99                           SPA_POD_PROP_FLAG_MANDATORY);
    100      spa_pod_builder_long(builder, modifiers[0]);
    101    } else {
    102      spa_pod_builder_prop(
    103          builder, SPA_FORMAT_VIDEO_modifier,
    104          SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
    105      spa_pod_builder_push_choice(builder, &frames[1], SPA_CHOICE_Enum, 0);
    106 
    107      // modifiers from the array
    108      bool first = true;
    109      for (int64_t val : modifiers) {
    110        spa_pod_builder_long(builder, val);
    111        // Add the first modifier twice as the very first value is the default
    112        // option
    113        if (first) {
    114          spa_pod_builder_long(builder, val);
    115          first = false;
    116        }
    117      }
    118      spa_pod_builder_pop(builder, &frames[1]);
    119    }
    120  }
    121 
    122  if (resolution) {
    123    spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_size,
    124                        SPA_POD_Rectangle(resolution), 0);
    125  } else {
    126    spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_size,
    127                        SPA_POD_CHOICE_RANGE_Rectangle(&pw_min_screen_bounds,
    128                                                       &pw_min_screen_bounds,
    129                                                       &pw_max_screen_bounds),
    130                        0);
    131  }
    132  if (frame_rate) {
    133    static const spa_fraction pw_min_frame_rate =
    134        spa_fraction{.num = 0, .denom = 1};
    135    spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_framerate,
    136                        SPA_POD_CHOICE_RANGE_Fraction(
    137                            frame_rate, &pw_min_frame_rate, frame_rate),
    138                        0);
    139    spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_maxFramerate,
    140                        SPA_POD_CHOICE_RANGE_Fraction(
    141                            frame_rate, &pw_min_frame_rate, frame_rate),
    142                        0);
    143  }
    144  return static_cast<spa_pod*>(spa_pod_builder_pop(builder, &frames[0]));
    145 }
    146 
    147 }  // namespace webrtc