diff --git a/src/orbit_processor.cc b/src/orbit_processor.cc
index 21fe3c8b669289392143fd94624a8413ca140ceb..29dc8252727b790b3843da9507ff32f1f7698d1a 100644
--- a/src/orbit_processor.cc
+++ b/src/orbit_processor.cc
@@ -97,20 +97,22 @@ size_t OrbitProcessor::fillFRDEventHeader_V6(char *wr_ptr_FRDHead, uint32_t inpu
 
 // Fills array pointed by `wr_ptr` with an orbit's data corresponding to non-empty bunch-crossings,
 // as marked in `bx_vect`
-OrbitProcessor::FillOrbitMetadata OrbitProcessor::FillOrbit(orbit_trailer *trailer, char *rd_ptr,
-                                                            char *wr_ptr, const char *rd_end_ptr,
-                                                            const char *wr_end_ptr) {
-  std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{ProcessOrbitHeader(rd_ptr)};
+OrbitProcessor::FillOrbitMetadata OrbitProcessor::FillOrbit(orbit_trailer *trailer,
+                                                            MemRegion &source,
+                                                            WriteMemRegion &sink) {
+  std::pair<uint32_t, bool> orbit_header =
+      std::pair<uint32_t, bool>{ProcessOrbitHeader(source.Get())};
   //.second is the warning test enable bit
-  rd_ptr += 32;  // +32 to account for orbit header
+  source.Increment(32);  // +32 to account for orbit header
   if (cmsswHeaders) {
-    wr_ptr += sizeof(FRDFileHeader_v2);
-  }  // reserving space for cmssw orbit header
+    // reserving space for cmssw orbit header
+    sink.Increment(sizeof(FRDFileHeader_v2));
+  }
 
-  uint32_t orbit = uint32_t{orbit_header.first} -
-                   1;  // Starting with orbit number one lower than what is in the header
+  // Starting with orbit number one lower than what is in the header
+  uint32_t orbit = uint32_t{orbit_header.first} - 1;
   // because the "link orbit" contains a few BXs of the previous orbit
-  auto counts = uint32_t{0};
+  uint32_t counts = 0;
   uint32_t filled_bxs = 0;
   // We loop over the BX map from the orbit trailer and then match the filled
   // BXs to the data we got. The logic below is annoyingly convoluted: The first
@@ -144,18 +146,15 @@ OrbitProcessor::FillOrbitMetadata OrbitProcessor::FillOrbit(orbit_trailer *trail
 
     ++filled_bxs;
 
-    if (CheckOrbitTrailerStart(const_cast<const char *>(rd_ptr))) {
+    if (CheckOrbitTrailerStart(const_cast<const char *>(source.Get()))) {
       // orbit trailer has been reached, end of orbit data
       break;
     }
 
-    MemRegion readable_block(&rd_ptr, rd_end_ptr);
-    WriteMemRegion writeable_block(&wr_ptr, wr_end_ptr);
-    assert(writeable_block.CheckBounds(GetPacketSize()));  // Max size a decoded block can use
-
     BxMetadata meta{orbit_header.second, bx, orbit};
+    assert(sink.CheckBounds(GetPacketSize()));  // Max size a decoded block can use
 
-    int ret_counts = ProcessBlock(readable_block, writeable_block, meta);
+    int ret_counts = ProcessBlock(source, sink, meta);
     if (ret_counts == -1) {
       continue;  // skip bunch crossing
     } else {
diff --git a/src/orbit_processor.h b/src/orbit_processor.h
index 83d66745c0ae1bd779461d78010098dfe0707b4a..1fab795cd2f3a48cddeb0e81265a0a8d3ffdc957 100644
--- a/src/orbit_processor.h
+++ b/src/orbit_processor.h
@@ -83,7 +83,7 @@ class OrbitProcessor : public Processor {
 
     void Increment(size_t size) { (*ptr_) += size; }
 
-    char **GetDoublePtr() { return ptr_; }
+    char *Get() { return *ptr_; }
 
     template <typename T>
     T *Scan() {