File: video_memory_utils.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (154 lines) | stat: -rw-r--r-- 5,680 bytes parent folder | download | duplicates (6)
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
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/video_memory_utils.h"

#include "base/logging.h"
#include "base/memory/ptr_util.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "base/memory/writable_shared_memory_region.h"
#endif

namespace remoting {

//////////////////////////////////////////////////////////////////////////////
// SharedVideoMemory

// static
std::unique_ptr<SharedVideoMemory> SharedVideoMemory::Create(
    size_t size,
    int id,
    base::OnceClosure on_deleted_callback) {
  webrtc::SharedMemory::Handle handle = webrtc::SharedMemory::kInvalidHandle;
#if BUILDFLAG(IS_WIN)
  // webrtc::ScreenCapturer uses webrtc::SharedMemory::handle() only on
  // windows. This handle must be writable. A WritableSharedMemoryRegion is
  // created, and then it is converted to read-only.  On the windows platform,
  // it happens to be the case that converting a region to read-only does not
  // change the status of existing handles. This is not true on all other
  // platforms, so please don't emulate this behavior!
  base::WritableSharedMemoryRegion region =
      base::WritableSharedMemoryRegion::Create(size);
  if (!region.IsValid()) {
    return nullptr;
  }
  base::WritableSharedMemoryMapping mapping = region.Map();
  // Converting |region| to read-only will close its associated handle, so we
  // must duplicate it into the handle used for |webrtc::ScreenCapturer|.
  HANDLE process = ::GetCurrentProcess();
  BOOL success =
      ::DuplicateHandle(process, region.UnsafeGetPlatformHandle(), process,
                        &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
  if (!success) {
    return nullptr;
  }
  base::ReadOnlySharedMemoryRegion read_only_region =
      base::WritableSharedMemoryRegion::ConvertToReadOnly(std::move(region));
#else
  base::MappedReadOnlyRegion region_mapping =
      base::ReadOnlySharedMemoryRegion::Create(size);
  base::ReadOnlySharedMemoryRegion read_only_region =
      std::move(region_mapping.region);
  base::WritableSharedMemoryMapping mapping = std::move(region_mapping.mapping);
#endif
  if (!mapping.IsValid()) {
    return nullptr;
  }
  // The SharedVideoMemory ctor is private, so std::make_unique can't be
  // used.
  return base::WrapUnique(
      new SharedVideoMemory(std::move(read_only_region), std::move(mapping),
                            handle, id, std::move(on_deleted_callback)));
}

SharedVideoMemory::~SharedVideoMemory() {
  std::move(on_deleted_callback_).Run();
}

SharedVideoMemory::SharedVideoMemory(base::ReadOnlySharedMemoryRegion region,
                                     base::WritableSharedMemoryMapping mapping,
                                     webrtc::SharedMemory::Handle handle,
                                     int id,
                                     base::OnceClosure on_deleted_callback)
    : SharedMemory(mapping.memory(), mapping.size(), handle, id),
      on_deleted_callback_(std::move(on_deleted_callback))
#if BUILDFLAG(IS_WIN)
      ,
      writable_handle_(handle)
#endif
{
  region_ = std::move(region);
  mapping_ = std::move(mapping);
}

//////////////////////////////////////////////////////////////////////////////
// SharedVideoMemoryFactory

SharedVideoMemoryFactory::SharedVideoMemoryFactory(
    SharedMemoryCreatedCallback shared_memory_created_callback,
    SharedMemoryReleasedCallback shared_memory_released_callback)
    : shared_memory_created_callback_(
          std::move(shared_memory_created_callback)),
      shared_memory_released_callback_(
          std::move(shared_memory_released_callback)) {}

SharedVideoMemoryFactory::~SharedVideoMemoryFactory() = default;

std::unique_ptr<webrtc::SharedMemory>
SharedVideoMemoryFactory::CreateSharedMemory(size_t size) {
  base::OnceClosure release_buffer_callback =
      base::BindOnce(shared_memory_released_callback_, next_shared_buffer_id_);
  std::unique_ptr<SharedVideoMemory> buffer = SharedVideoMemory::Create(
      size, next_shared_buffer_id_, std::move(release_buffer_callback));
  if (buffer) {
    // |next_shared_buffer_id_| starts from 1 and incrementing it by 2 makes
    // sure it is always odd and therefore zero is never used as a valid
    // buffer ID.
    //
    // It is very unlikely (though theoretically possible) to allocate the
    // same ID for two different buffers due to integer overflow. It should
    // take about a year of allocating 100 new buffers every second.
    // Practically speaking it never happens.
    next_shared_buffer_id_ += 2;

    shared_memory_created_callback_.Run(
        buffer->id(), buffer->region().Duplicate(), buffer->size());
  }

  return buffer;
}

//////////////////////////////////////////////////////////////////////////////
// IpcSharedBufferCore

IpcSharedBufferCore::IpcSharedBufferCore(
    int id,
    base::ReadOnlySharedMemoryRegion region)
    : id_(id) {
  mapping_ = region.Map();
  if (!mapping_.IsValid()) {
    LOG(ERROR) << "Failed to map a shared buffer: id=" << id
               << ", size=" << region.GetSize();
  }
  // After being mapped, |region| is no longer needed and can be discarded.
}

IpcSharedBufferCore::~IpcSharedBufferCore() = default;

//////////////////////////////////////////////////////////////////////////////
// IpcSharedBuffer

IpcSharedBuffer::IpcSharedBuffer(scoped_refptr<IpcSharedBufferCore> core)
    : SharedMemory(const_cast<void*>(core->memory()),
                   core->size(),
                   0,
                   core->id()),
      core_(core) {}

IpcSharedBuffer::~IpcSharedBuffer() = default;

}  // namespace remoting