CARLA
PixelReader.h
Go to the documentation of this file.
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 #include "Carla/Game/CarlaEngine.h"
14 
16 #include <carla/Logging.h>
17 #include <carla/Buffer.h>
20 
21 // =============================================================================
22 // -- FPixelReader -------------------------------------------------------------
23 // =============================================================================
24 
25 /// Utils for reading pixels from UTextureRenderTarget2D.
26 ///
27 /// @todo This class only supports PF_R8G8B8A8 format.
29 {
30 public:
31 
32  using Payload = std::function<void(void *, uint32, uint32)>;
33 
34  /// Copy the pixels in @a RenderTarget into @a BitMap.
35  ///
36  /// @pre To be called from game-thread.
37  static bool WritePixelsToArray(
38  UTextureRenderTarget2D &RenderTarget,
39  TArray<FColor> &BitMap);
40 
41  /// Dump the pixels in @a RenderTarget.
42  ///
43  /// @pre To be called from game-thread.
44  static TUniquePtr<TImagePixelData<FColor>> DumpPixels(
45  UTextureRenderTarget2D &RenderTarget);
46 
47  /// Asynchronously save the pixels in @a RenderTarget to disk.
48  ///
49  /// @pre To be called from game-thread.
50  static TFuture<bool> SavePixelsToDisk(
51  UTextureRenderTarget2D &RenderTarget,
52  const FString &FilePath);
53 
54  /// Asynchronously save the pixels in @a PixelData to disk.
55  ///
56  /// @pre To be called from game-thread.
57  static TFuture<bool> SavePixelsToDisk(
58  TUniquePtr<TImagePixelData<FColor>> PixelData,
59  const FString &FilePath);
60 
61  /// Convenience function to enqueue a render command that sends the pixels
62  /// down the @a Sensor's data stream. It expects a sensor derived from
63  /// ASceneCaptureSensor or compatible.
64  ///
65  /// Note that the serializer needs to define a "header_offset" that it's
66  /// allocated in front of the buffer.
67  ///
68  /// @pre To be called from game-thread.
69  template <typename TSensor, typename TPixel>
70  static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat = false, std::function<TArray<TPixel>(void *, uint32)> Conversor = {});
71 
72 private:
73 
74  /// Copy the pixels in @a RenderTarget into @a Buffer.
75  ///
76  /// @pre To be called from render-thread.
77  static void WritePixelsToBuffer(
78  const UTextureRenderTarget2D &RenderTarget,
79  uint32 Offset,
80  FRHICommandListImmediate &InRHICmdList,
81  FPixelReader::Payload FuncForSending);
82 
83 };
84 
85 // =============================================================================
86 // -- FPixelReader::SendPixelsInRenderThread -----------------------------------
87 // =============================================================================
88 
89 template <typename TSensor, typename TPixel>
90 void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat, std::function<TArray<TPixel>(void *, uint32)> Conversor)
91 {
92  TRACE_CPUPROFILER_EVENT_SCOPE(FPixelReader::SendPixelsInRenderThread);
93  check(Sensor.CaptureRenderTarget != nullptr);
94 
95  if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill())
96  {
97  return;
98  }
99 
100  /// Blocks until the render thread has finished all it's tasks.
101  Sensor.EnqueueRenderSceneImmediate();
102 
103  // Enqueue a command in the render-thread that will write the image buffer to
104  // the data stream. The stream is created in the capture thus executed in the
105  // game-thread.
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 Can we make sure the sensor is not going to be destroyed?
113  if (!Sensor.IsPendingKill())
114  {
115  FPixelReader::Payload FuncForSending =
116  [&Sensor, Frame = FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](void *LockedData, uint32 Size, uint32 Offset)
117  {
118  if (Sensor.IsPendingKill()) return;
119 
120  TArray<TPixel> Converted;
121 
122  // optional conversion of data
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  {
136  TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy");
137  Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Size));
138  }
139  {
140  // send
141  TRACE_CPUPROFILER_EVENT_SCOPE_STR("Sending buffer");
142  if(Buffer.data())
143  {
144  SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
145  TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send");
146  Stream.Send(Sensor, std::move(Buffer));
147  }
148  }
149  };
150 
152  *Sensor.CaptureRenderTarget,
154  InRHICmdList,
155  std::move(FuncForSending));
156  }
157  }
158  );
159 
160  // Blocks until the render thread has finished all it's tasks
161  Sensor.WaitForRenderThreadToFinish();
162 }
static TUniquePtr< TImagePixelData< FColor > > DumpPixels(UTextureRenderTarget2D &RenderTarget)
Dump the pixels in RenderTarget.
static bool WritePixelsToArray(UTextureRenderTarget2D &RenderTarget, TArray< FColor > &BitMap)
Copy the pixels in RenderTarget into BitMap.
static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat=false, std::function< TArray< TPixel >(void *, uint32)> Conversor={})
Convenience function to enqueue a render command that sends the pixels down the Sensor&#39;s data stream...
Definition: PixelReader.h:90
typename detail::CompileTimeTypeMapImpl< sizeof...(Items), Items... >::template get< InKey > get
std::deque< std::shared_ptr< SimpleWaypoint > > Buffer
Utils for reading pixels from UTextureRenderTarget2D.
Definition: PixelReader.h:28
static void WritePixelsToBuffer(const UTextureRenderTarget2D &RenderTarget, uint32 Offset, FRHICommandListImmediate &InRHICmdList, FPixelReader::Payload FuncForSending)
Copy the pixels in RenderTarget into Buffer.
Definition: PixelReader.cpp:40
static uint64_t GetFrameCounter()
Definition: CarlaEngine.h:64
detail::Stream< detail::MultiStreamState > Stream
A stream represents an unidirectional channel for sending data from server to client.
Definition: Stream.h:19
std::function< void(void *, uint32, uint32)> Payload
Definition: PixelReader.h:32
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
Asynchronously save the pixels in RenderTarget to disk.