File: media_stream_set.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (158 lines) | stat: -rw-r--r-- 6,327 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/mediastream/media_stream_set.h"

#include "base/functional/bind.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/screen_capture_media_stream_track.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_request.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/screen_details/screen_detailed.h"
#include "third_party/blink/renderer/modules/screen_details/screen_details.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
#include "ui/display/types/display_constants.h"

namespace blink {

namespace {

ScreenDetailed* FindScreenDetailedByDisplayId(
    ScreenDetails* screen_details,
    std::optional<int64_t> display_id) {
  if (display_id == display::kInvalidDisplayId) {
    return nullptr;
  }

  auto screen_iterator =
      std::ranges::find_if(screen_details->screens(),
                           [display_id](const ScreenDetailed* screen_detailed) {
                             return *display_id == screen_detailed->DisplayId();
                           });

  return (screen_iterator != screen_details->screens().end()) ? *screen_iterator
                                                              : nullptr;
}

}  // namespace

MediaStreamSet* MediaStreamSet::Create(
    ExecutionContext* context,
    const GCedMediaStreamDescriptorVector& stream_descriptors,
    UserMediaRequestType request_type,
    MediaStreamSetInitializedCallback callback) {
  DCHECK(IsMainThread());

  return MakeGarbageCollected<MediaStreamSet>(
      context, stream_descriptors, request_type, std::move(callback));
}

MediaStreamSet::MediaStreamSet(
    ExecutionContext* context,
    const GCedMediaStreamDescriptorVector& stream_descriptors,
    UserMediaRequestType request_type,
    MediaStreamSetInitializedCallback callback)
    : ExecutionContextClient(context),
      media_streams_to_initialize_count_(stream_descriptors.size()),
      media_streams_initialized_callback_(std::move(callback)) {
  DCHECK(IsMainThread());

  if (request_type == UserMediaRequestType::kAllScreensMedia) {
    InitializeGetAllScreensMediaStreams(context, stream_descriptors);
    return;
  }

  if (stream_descriptors.empty()) {
    // No streams -> all streams are initialized, meaning the set
    // itself is fully initialized.
    context->GetTaskRunner(TaskType::kInternalMedia)
        ->PostTask(FROM_HERE,
                   WTF::BindOnce(&MediaStreamSet::OnMediaStreamSetInitialized,
                                 WrapPersistent(this)));
    return;
  }

  // The set will be initialized when all of its streams are initialized.
  // When the last stream is initialized, its callback will trigger
  // a call to OnMediaStreamSetInitialized.
  for (WTF::wtf_size_t stream_index = 0;
       stream_index < stream_descriptors.size(); ++stream_index) {
    MediaStream::Create(context, stream_descriptors[stream_index],
                        /*track=*/nullptr,
                        WTF::BindOnce(&MediaStreamSet::OnMediaStreamInitialized,
                                      WrapPersistent(this)));
  }
}

void MediaStreamSet::Trace(Visitor* visitor) const {
  visitor->Trace(initialized_media_streams_);
  ExecutionContextClient::Trace(visitor);
}

void MediaStreamSet::InitializeGetAllScreensMediaStreams(
    ExecutionContext* context,
    const GCedMediaStreamDescriptorVector& stream_descriptors) {
  DCHECK(IsMainThread());

  LocalDOMWindow* const window = To<LocalDOMWindow>(context);
  DCHECK(window);

  // TODO(crbug.com/1358949): Move the generation of the |ScreenDetails| object
  // next to the generation of the descriptors and store them as members to
  // avoid race conditions. Further, match the getAllScreensMedia API and the
  // window placement API by unique IDs instead of assuming the same order.
  ScreenDetails* const screen_details =
      MakeGarbageCollected<ScreenDetails>(window);
  const bool screen_details_match_descriptors =
      screen_details->screens().size() == stream_descriptors.size();
  for (WTF::wtf_size_t stream_index = 0;
       stream_index < stream_descriptors.size(); ++stream_index) {
    MediaStreamDescriptor* const descriptor = stream_descriptors[stream_index];
    DCHECK_EQ(1u, descriptor->NumberOfVideoComponents());

    ScreenDetailed* screen = FindScreenDetailedByDisplayId(
        screen_details,
        descriptor->VideoComponent(0u)->Source()->GetDisplayId());

    MediaStreamTrack* video_track =
        MakeGarbageCollected<ScreenCaptureMediaStreamTrack>(
            context, descriptor->VideoComponent(0u),
            screen_details_match_descriptors ? screen_details : nullptr,
            screen);
    initialized_media_streams_.push_back(
        MediaStream::Create(context, descriptor, {}, {video_track}));
  }
  context->GetTaskRunner(TaskType::kInternalMedia)
      ->PostTask(FROM_HERE,
                 WTF::BindOnce(&MediaStreamSet::OnMediaStreamSetInitialized,
                               WrapPersistent(this)));
}

void MediaStreamSet::OnMediaStreamSetInitialized() {
  DCHECK(IsMainThread());

  std::move(std::move(media_streams_initialized_callback_))
      .Run(initialized_media_streams_);
}

// TODO(crbug.com/1300883): Clean up other streams if one stream capture
// results in an error. This is only required for getAllScreensMedia.
// Currently existing functionality generates only one stream which is not
// affected by this change.
void MediaStreamSet::OnMediaStreamInitialized(
    MediaStream* initialized_media_stream) {
  DCHECK(IsMainThread());
  DCHECK_LT(initialized_media_streams_.size(),
            media_streams_to_initialize_count_);

  initialized_media_streams_.push_back(initialized_media_stream);
  if (initialized_media_streams_.size() == media_streams_to_initialize_count_) {
    OnMediaStreamSetInitialized();
  }
}

}  // namespace blink