CARLA
 
载入中...
搜索中...
未找到
PixelReader.h
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8
9#include "CoreGlobals.h"
10#include "Engine/TextureRenderTarget2D.h"
11#include "Runtime/ImageWriteQueue/Public/ImagePixelData.h"
12
13#ifdef _WIN32
14 #define WIN32_LEAN_AND_MEAN
15 #include <D3d12.h>
16#endif
17
19
21#include <carla/Logging.h>
22#include <carla/Buffer.h>
23#include <carla/BufferView.h>
26
27// =============================================================================
28// -- FPixelReader -------------------------------------------------------------
29// =============================================================================
30
31/// 用于从 UTextureRenderTarget2D 读取像素的实用工具。
32///
33/// @todo 当前该类仅支持 PF_R8G8B8A8 格式。
35{
36public:
37
38 using Payload = std::function<void(void *, uint32, uint32, uint32)>;
39
40 /// 将 @a RenderTarget 中的像素复制到 @a BitMap 中。
41 ///
42 /// @pre 必须从游戏线程调用。
43 static bool WritePixelsToArray(
44 UTextureRenderTarget2D &RenderTarget,
45 TArray<FColor> &BitMap);
46
47 /// 转储 @a RenderTarget 中的像素。
48 ///
49 /// @pre 必须从游戏线程调用。
50 static TUniquePtr<TImagePixelData<FColor>> DumpPixels(
51 UTextureRenderTarget2D &RenderTarget);
52
53 /// 异步保存 @a RenderTarget 中的像素到磁盘。
54 ///
55 /// @pre 必须从游戏线程调用。
56 static TFuture<bool> SavePixelsToDisk(
57 UTextureRenderTarget2D &RenderTarget,
58 const FString &FilePath);
59
60 /// 异步保存 @a PixelData 中的像素到磁盘。
61 ///
62 /// @pre 必须从游戏线程调用。
63 static TFuture<bool> SavePixelsToDisk(
64 TUniquePtr<TImagePixelData<FColor>> PixelData,
65 const FString &FilePath);
66
67 /// 方便函数,将渲染命令加入队列以通过 @a Sensor 的数据流发送像素。
68 /// 它需要一个继承自 ASceneCaptureSensor 或兼容的传感器。
69 ///
70 /// 注意:序列化器需要定义一个 "header_offset",分配在缓冲区前部。
71 ///
72 /// @pre 必须从游戏线程调用。
73 template <typename TSensor, typename TPixel>
74 static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat = false, std::function<TArray<TPixel>(void *, uint32)> Conversor = {});
75
76 /// 将 @a RenderTarget 中的像素复制到 @a Buffer。
77 ///
78 /// @pre 必须从渲染线程调用。
79 static void WritePixelsToBuffer(
80 const UTextureRenderTarget2D &RenderTarget,
81 uint32 Offset,
82 FRHICommandListImmediate &InRHICmdList,
83 FPixelReader::Payload FuncForSending);
84
85};
86
87// =============================================================================
88// -- FPixelReader::SendPixelsInRenderThread -----------------------------------
89// =============================================================================
90
91template <typename TSensor, typename TPixel>
92void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat, std::function<TArray<TPixel>(void *, uint32)> Conversor)
93{
94 TRACE_CPUPROFILER_EVENT_SCOPE(FPixelReader::SendPixelsInRenderThread);
95 check(Sensor.CaptureRenderTarget != nullptr);
96
97 if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill())
98 {
99 return;
100 }
101
102 /// 阻塞,直到渲染线程完成所有任务。
103 Sensor.EnqueueRenderSceneImmediate();
104
105 // 在渲染线程中加入命令,将图像缓冲区写入数据流。
106 ENQUEUE_RENDER_COMMAND(FWritePixels_SendPixelsInRenderThread)
107 (
108 [&Sensor, use16BitFormat, Conversor = std::move(Conversor)](auto &InRHICmdList) mutable
109 {
110 TRACE_CPUPROFILER_EVENT_SCOPE_STR("FWritePixels_SendPixelsInRenderThread");
111
112 /// @todo 确保传感器不会被销毁?
113 if (!Sensor.IsPendingKill())
114 {
115 FPixelReader::Payload FuncForSending =
116 [&Sensor, Frame = FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](void *LockedData, uint32 Size, uint32 Offset, uint32 ExpectedRowBytes)
117 {
118 if (Sensor.IsPendingKill()) return;
119
120 TArray<TPixel> Converted;
121
122 // 可选的数据转换
123 if (Conversor)
124 {
125 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Data conversion");
126 Converted = Conversor(LockedData, Size);
127 LockedData = reinterpret_cast<void *>(Converted.GetData());
128 Size = Converted.Num() * Converted.GetTypeSize();
129 }
130
131 auto Stream = Sensor.GetDataStream(Sensor);
132 Stream.SetFrameNumber(Frame);
133 auto Buffer = Stream.PopBufferFromPool();
134
135 uint32 CurrentRowBytes = ExpectedRowBytes;
136
137#ifdef _WIN32
138 // DirectX 为了对齐每行到 256 字节边界而增加了额外字节,需要移除这些数据。
139 if (IsD3DPlatform(GMaxRHIShaderPlatform, false))
140 {
141 CurrentRowBytes = Align(ExpectedRowBytes, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
142 if (ExpectedRowBytes != CurrentRowBytes)
143 {
144 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy (windows, row by row)");
145 Buffer.reset(Offset + Size);
146 auto DstRow = Buffer.begin() + Offset;
147 const uint8 *SrcRow = reinterpret_cast<uint8 *>(LockedData);
148 uint32 i = 0;
149 while (i < Size)
150 {
151 FMemory::Memcpy(DstRow, SrcRow, ExpectedRowBytes);
152 DstRow += ExpectedRowBytes;
153 SrcRow += CurrentRowBytes;
154 i += ExpectedRowBytes;
155 }
156 }
157 }
158#endif // _WIN32
159
160 if (ExpectedRowBytes == CurrentRowBytes)
161 {
162 check(ExpectedRowBytes == CurrentRowBytes);
163 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy");
164 Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Size));
165 }
166
167 {
168 // 发送数据
169 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Sending buffer");
170 if(Buffer.data())
171 {
172 // 序列化数据
173 carla::Buffer BufferReady(std::move(carla::sensor::SensorRegistry::Serialize(Sensor, std::move(Buffer))));
174 carla::SharedBufferView BufView = carla::BufferView::CreateFrom(std::move(BufferReady));
175
176 // ROS2 支持
177 #if defined(WITH_ROS2)
178 auto ROS2 = carla::ros2::ROS2::GetInstance();
179 if (ROS2->IsEnabled())
180 {
181 TRACE_CPUPROFILER_EVENT_SCOPE_STR("ROS2 Send PixelReader");
182 auto StreamId = carla::streaming::detail::token_type(Sensor.GetToken()).get_stream_id();
183 auto Res = std::async(std::launch::async, [&Sensor, ROS2, &Stream, StreamId, BufView]()
184 {
185 // 获取相机分辨率
186 int W = -1, H = -1;
187 float Fov = -1.0f;
188 auto WidthOpt = Sensor.GetAttribute("image_size_x");
189 if (WidthOpt.has_value())
190 W = FCString::Atoi(*WidthOpt->Value);
191 auto HeightOpt = Sensor.GetAttribute("image_size_y");
192 if (HeightOpt.has_value())
193 H = FCString::Atoi(*HeightOpt->Value);
194 auto FovOpt = Sensor.GetAttribute("fov");
195 if (FovOpt.has_value())
196 Fov = FCString::Atof(*FovOpt->Value);
197 // 将数据发送到 ROS2
198 AActor* ParentActor = Sensor.GetAttachParentActor();
199 if (ParentActor)
200 {
201 FTransform LocalTransformRelativeToParent = Sensor.GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
202 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, LocalTransformRelativeToParent, W, H, Fov, BufView, &Sensor);
203 }
204 else
205 {
206 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, Stream.GetSensorTransform(), W, H, Fov, BufView, &Sensor);
207 }
208 });
209 }
210 #endif
211
212 // 网络传输
213 SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
214 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send");
215 Stream.Send(Sensor, BufView);
216 }
217 }
218 };
219
221 *Sensor.CaptureRenderTarget,
223 InRHICmdList,
224 std::move(FuncForSending));
225 }
226 }
227 );
228
229 // 阻塞,直到渲染线程完成所有任务。
230 Sensor.WaitForRenderThreadToFinish();
231}
232
static uint64_t GetFrameCounter()
Definition CarlaEngine.h:68
用于从 UTextureRenderTarget2D 读取像素的实用工具。
Definition PixelReader.h:35
static bool WritePixelsToArray(UTextureRenderTarget2D &RenderTarget, TArray< FColor > &BitMap)
将 RenderTarget 中的像素复制到 BitMap 中。
static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat=false, std::function< TArray< TPixel >(void *, uint32)> Conversor={})
方便函数,将渲染命令加入队列以通过 Sensor 的数据流发送像素。 它需要一个继承自 ASceneCaptureSensor 或兼容的传感器。
Definition PixelReader.h:92
std::function< void(void *, uint32, uint32, uint32)> Payload
Definition PixelReader.h:38
static TUniquePtr< TImagePixelData< FColor > > DumpPixels(UTextureRenderTarget2D &RenderTarget)
转储 RenderTarget 中的像素。
static void WritePixelsToBuffer(const UTextureRenderTarget2D &RenderTarget, uint32 Offset, FRHICommandListImmediate &InRHICmdList, FPixelReader::Payload FuncForSending)
将 RenderTarget 中的像素复制到 Buffer。
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
异步保存 RenderTarget 中的像素到磁盘。
static std::shared_ptr< BufferView > CreateFrom(Buffer &&buffer)
Definition BufferView.h:60
一块原始数据。 请注意,如果需要更多容量,则会分配一个新的内存块,并 删除旧的内存块。这意味着默认情况下,缓冲区只能增长。要释放内存,使用 clear 或 pop。
static std::shared_ptr< ROS2 > GetInstance()
Definition ROS2.h:51
static Buffer Serialize(Sensor &sensor, Args &&... args)
Serialize the arguments provided into a Buffer by calling to the serializer registered for the given ...
静态断言,用于确保token_data结构体的大小与Token::data的大小相同。
const auto & get_stream_id() const
获取流ID的引用。
std::shared_ptr< BufferView > SharedBufferView
Definition BufferView.h:163
typename detail::CompileTimeTypeMapImpl< sizeof...(Items), Items... >::template get< InKey > get