diff -a -U 2 -r a/config.c b/config.c
--- a/config.c
+++ b/config.c
@@ -469,4 +469,5 @@
   SplitEditedFiles = 0;
   DelTimeshiftRec = 0;
+  DumpNaluFill = 0;
   MinEventTimeout = 30;
   MinUserInactivity = 300;
@@ -697,4 +698,5 @@
   else if (!strcasecmp(Name, "SplitEditedFiles"))    SplitEditedFiles   = atoi(Value);
   else if (!strcasecmp(Name, "DelTimeshiftRec"))     DelTimeshiftRec    = atoi(Value);
+  else if (!strcasecmp(Name, "DumpNaluFill"))        DumpNaluFill       = atoi(Value);
   else if (!strcasecmp(Name, "MinEventTimeout"))     MinEventTimeout    = atoi(Value);
   else if (!strcasecmp(Name, "MinUserInactivity"))   MinUserInactivity  = atoi(Value);
@@ -829,4 +831,5 @@
   Store("SplitEditedFiles",   SplitEditedFiles);
   Store("DelTimeshiftRec",    DelTimeshiftRec);
+  Store("DumpNaluFill",       DumpNaluFill);
   Store("MinEventTimeout",    MinEventTimeout);
   Store("MinUserInactivity",  MinUserInactivity);
diff -a -U 2 -r a/config.h b/config.h
--- a/config.h
+++ b/config.h
@@ -341,4 +341,5 @@
   int SplitEditedFiles;
   int DelTimeshiftRec;
+  int DumpNaluFill;
   int MinEventTimeout, MinUserInactivity;
   time_t NextWakeupTime;
diff -a -U 2 -r a/menu.c b/menu.c
--- a/menu.c
+++ b/menu.c
@@ -4185,4 +4185,5 @@
   Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"),        &data.SplitEditedFiles));
   Add(new cMenuEditStraItem(tr("Setup.Recording$Delete timeshift recording"),&data.DelTimeshiftRec, 3, delTimeshiftRecTexts));
+  Add(new cMenuEditBoolItem(tr("Setup.Recording$Dump NALU Fill data"),       &data.DumpNaluFill));
 }
 
diff -a -U 2 -r a/recorder.c b/recorder.c
--- a/recorder.c
+++ b/recorder.c
@@ -195,4 +195,12 @@
      }
   frameDetector = new cFrameDetector(Pid, Type);
+  if (   Type == 0x1B // MPEG4 video
+      && (Setup.DumpNaluFill ? (strstr(FileName, "NALUKEEP") == NULL) : (strstr(FileName, "NALUDUMP") != NULL))) { // MPEG4
+     isyslog("Starting NALU fill dumper");
+     naluStreamProcessor = new cNaluStreamProcessor();
+     naluStreamProcessor->SetPid(Pid);
+     }
+  else
+     naluStreamProcessor = NULL;
   index = NULL;
   fileSize = 0;
@@ -217,4 +225,10 @@
 {
   Detach();
+  if (naluStreamProcessor) {
+     long long int TotalPackets = naluStreamProcessor->GetTotalPackets();
+     long long int DroppedPackets = naluStreamProcessor->GetDroppedPackets();
+     isyslog("NALU fill dumper: %lld of %lld packets dropped, %lli%%", DroppedPackets, TotalPackets, TotalPackets ? DroppedPackets*100/TotalPackets : 0);
+     delete naluStreamProcessor;
+     }
   delete index;
   delete fileName;
@@ -357,10 +371,32 @@
                        t.Set(MAXBROKENTIMEOUT);
                        }
-                    if (recordFile->Write(b, Count) < 0) {
-                       LOG_ERROR_STR(fileName->Name());
-                       break;
+		    if (naluStreamProcessor) {
+                       naluStreamProcessor->PutBuffer(b, Count);
+                       bool Fail = false;
+                       while (true) {
+                             int OutLength = 0;
+                             uchar *OutData = naluStreamProcessor->GetBuffer(OutLength);
+                             if (!OutData || OutLength <= 0)
+                                break;
+                             if (recordFile->Write(OutData, OutLength) < 0) {
+                                LOG_ERROR_STR(fileName->Name());
+                                Fail = true;
+                                break;
+                                }
+                             HandleErrors();
+                             fileSize += OutLength;
+                             }
+                       if (Fail)
+                          break;
+                       }
+                    else {
+                       if (recordFile->Write(b, Count) < 0) {
+                          LOG_ERROR_STR(fileName->Name());
+                          break;
+                          }
+                       HandleErrors();
+                       fileSize += Count;
                        }
-                    HandleErrors();
-                    fileSize += Count;
+
                     }
                  }
diff -a -U 2 -r a/recorder.h b/recorder.h
--- a/recorder.h
+++ b/recorder.h	C2022-01-08 17:51:00.397595525 +0100
@@ -27,4 +27,5 @@
   cFrameDetector *frameDetector;
   cPatPmtGenerator patPmtGenerator;
+  cNaluStreamProcessor *naluStreamProcessor;
   cFileName *fileName;
   cRecordingInfo *recordingInfo;
diff -a -U 2 -r a/remux.c b/remux.c
--- a/remux.c
+++ b/remux.c
@@ -357,4 +357,40 @@
 }
 
+void TsExtendAdaptionField(unsigned char *Packet, int ToLength)
+{
+    // Hint: ExtenAdaptionField(p, TsPayloadOffset(p) - 4) is a null operation
+
+    int Offset = TsPayloadOffset(Packet); // First byte after existing adaption field
+
+    if (ToLength <= 0)
+    {
+        // Remove adaption field
+        Packet[3] = Packet[3] & ~TS_ADAPT_FIELD_EXISTS;
+        return;
+    }
+
+    // Set adaption field present
+    Packet[3] = Packet[3] | TS_ADAPT_FIELD_EXISTS;
+
+    // Set new length of adaption field:
+    Packet[4] = ToLength <= TS_SIZE-4 ? ToLength-1 : TS_SIZE-4-1;
+
+    if (Packet[4] == TS_SIZE-4-1)
+    {
+        // No more payload, remove payload flag
+        Packet[3] = Packet[3] & ~TS_PAYLOAD_EXISTS;
+    }
+
+    int NewPayload = TsPayloadOffset(Packet); // First byte after new adaption field
+
+    // Fill new adaption field
+    if (Offset == 4 && Offset < NewPayload)
+        Offset++; // skip adaptation_field_length
+    if (Offset == 5 && Offset < NewPayload)
+        Packet[Offset++] = 0; // various flags set to 0
+    while (Offset < NewPayload)
+        Packet[Offset++] = 0xff; // stuffing byte
+}
+
 // --- cPatPmtGenerator ------------------------------------------------------
 
@@ -1765,2 +1801,343 @@
   return Processed;
 }
+
+// --- cNaluDumper ---------------------------------------------------------
+
+cNaluDumper::cNaluDumper()
+{
+    LastContinuityOutput = -1;
+    reset();
+}
+
+void cNaluDumper::reset()
+{
+    LastContinuityInput = -1;
+    ContinuityOffset = 0;
+    PesId = -1;
+    PesOffset = 0;
+    NaluFillState = NALU_NONE;
+    NaluOffset = 0;
+    History = 0xffffffff;
+    DropAllPayload = false;
+}
+
+void cNaluDumper::ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info)
+{
+    Info.DropPayloadStartBytes = 0;
+    Info.DropPayloadEndBytes = 0;
+    int LastKeepByte = -1;
+
+    if (PayloadStart)
+    {
+        History = 0xffffffff;
+        PesId = -1;
+        NaluFillState = NALU_NONE;
+    }
+
+    for (int i=0; i<size; i++) {
+        History = (History << 8) | Payload[i];
+
+        PesOffset++;
+        NaluOffset++;
+
+        bool DropByte = false;
+
+        if (History >= 0x00000180 && History <= 0x000001FF)
+        {
+            // Start of PES packet
+            PesId = History & 0xff;
+            PesOffset = 0;
+            NaluFillState = NALU_NONE;
+        }
+        else if (PesId >= 0xe0 && PesId <= 0xef // video stream
+                 && History >= 0x00000100 && History <= 0x0000017F) // NALU start code
+        {
+            int NaluId = History & 0xff;
+            NaluOffset = 0;
+            NaluFillState = ((NaluId & 0x1f) == 0x0c) ? NALU_FILL : NALU_NONE;
+        }
+
+        if (PesId >= 0xe0 && PesId <= 0xef // video stream
+            && PesOffset >= 1 && PesOffset <= 2)
+        {
+            Payload[i] = 0; // Zero out PES length field
+        }
+
+        if (NaluFillState == NALU_FILL && NaluOffset > 0) // Within NALU fill data
+        {
+            // We expect a series of 0xff bytes terminated by a single 0x80 byte.
+
+            if (Payload[i] == 0xFF)
+            {
+                DropByte = true;
+            }
+            else if (Payload[i] == 0x80)
+            {
+                NaluFillState = NALU_TERM; // Last byte of NALU fill, next byte sets NaluFillEnd=true
+                DropByte = true;
+            }
+            else // Invalid NALU fill
+            {
+                dsyslog("cNaluDumper: Unexpected NALU fill data: %02x", Payload[i]);
+                NaluFillState = NALU_END;
+                if (LastKeepByte == -1)
+                {
+                    // Nalu fill from beginning of packet until last byte
+                    // packet start needs to be dropped
+                    Info.DropPayloadStartBytes = i;
+                }
+            }
+        }
+        else if (NaluFillState == NALU_TERM) // Within NALU fill data
+        {
+            // We are after the terminating 0x80 byte
+            NaluFillState = NALU_END;
+            if (LastKeepByte == -1)
+            {
+                // Nalu fill from beginning of packet until last byte
+                // packet start needs to be dropped
+                Info.DropPayloadStartBytes = i;
+            }
+        }
+
+        if (!DropByte)
+            LastKeepByte = i; // Last useful byte
+    }
+
+    Info.DropAllPayloadBytes = (LastKeepByte == -1);
+    Info.DropPayloadEndBytes = size-1-LastKeepByte;
+}
+
+bool cNaluDumper::ProcessTSPacket(unsigned char *Packet)
+{
+    bool HasAdaption = TsHasAdaptationField(Packet);
+    bool HasPayload = TsHasPayload(Packet);
+
+    // Check continuity:
+    int ContinuityInput = TsContinuityCounter(Packet);
+    if (LastContinuityInput >= 0)
+    {
+        int NewContinuityInput = HasPayload ? (LastContinuityInput + 1) & TS_CONT_CNT_MASK : LastContinuityInput;
+        int Offset = (NewContinuityInput - ContinuityInput) & TS_CONT_CNT_MASK;
+        if (Offset > 0)
+            dsyslog("cNaluDumper: TS continuity offset %i", Offset);
+        if (Offset > ContinuityOffset)
+            ContinuityOffset = Offset; // max if packets get dropped, otherwise always the current one.
+    }
+    LastContinuityInput = ContinuityInput;
+
+    if (HasPayload) {
+        sPayloadInfo Info;
+        int Offset = TsPayloadOffset(Packet);
+        ProcessPayload(Packet + Offset, TS_SIZE - Offset, TsPayloadStart(Packet), Info);
+
+        if (DropAllPayload && !Info.DropAllPayloadBytes)
+        {
+            // Return from drop packet mode to normal mode
+            DropAllPayload = false;
+
+            // Does the packet start with some remaining NALU fill data?
+            if (Info.DropPayloadStartBytes > 0)
+            {
+                // Add these bytes as stuffing to the adaption field.
+
+                // Sample payload layout:
+                // FF FF FF FF FF 80 00 00 01 xx xx xx xx
+                //                   ^DropPayloadStartBytes
+
+                TsExtendAdaptionField(Packet, Offset - 4 + Info.DropPayloadStartBytes);
+            }
+        }
+
+        bool DropThisPayload = DropAllPayload;
+
+        if (!DropAllPayload && Info.DropPayloadEndBytes > 0) // Payload ends with 0xff NALU Fill
+        {
+            // Last packet of useful data
+            // Do early termination of NALU fill data
+            Packet[TS_SIZE-1] = 0x80;
+            DropAllPayload = true;
+            // Drop all packets AFTER this one
+
+            // Since we already wrote the 0x80, we have to make sure that
+            // as soon as we stop dropping packets, any beginning NALU fill of next
+            // packet gets dumped. (see DropPayloadStartBytes above)
+        }
+
+        if (DropThisPayload && HasAdaption)
+        {
+            // Drop payload data, but keep adaption field data
+            TsExtendAdaptionField(Packet, TS_SIZE-4);
+            DropThisPayload = false;
+        }
+
+        if (DropThisPayload)
+        {
+            return true; // Drop packet
+        }
+    }
+
+    // Fix Continuity Counter and reproduce incoming offsets:
+    int NewContinuityOutput = TsHasPayload(Packet) ? (LastContinuityOutput + 1) & TS_CONT_CNT_MASK : LastContinuityOutput;
+    NewContinuityOutput = (NewContinuityOutput + ContinuityOffset) & TS_CONT_CNT_MASK;
+    TsSetContinuityCounter(Packet, NewContinuityOutput);
+    LastContinuityOutput = NewContinuityOutput;
+    ContinuityOffset = 0;
+
+    return false; // Keep packet
+}
+
+// --- cNaluStreamProcessor ---------------------------------------------------------
+
+cNaluStreamProcessor::cNaluStreamProcessor()
+{
+    pPatPmtParser = NULL;
+    vpid = -1;
+    data = NULL;
+    length = 0;
+    tempLength = 0;
+    tempLengthAtEnd = false;
+    TotalPackets = 0;
+    DroppedPackets = 0;
+}
+
+void cNaluStreamProcessor::PutBuffer(uchar *Data, int Length)
+{
+    if (length > 0)
+        esyslog("cNaluStreamProcessor::PutBuffer: New data before old data was processed!");
+
+    data = Data;
+    length = Length;
+}
+
+uchar* cNaluStreamProcessor::GetBuffer(int &OutLength)
+{
+    if (length <= 0)
+    {
+        // Need more data - quick exit
+        OutLength = 0;
+        return NULL;
+    }
+    if (tempLength > 0) // Data in temp buffer?
+    {
+        if (tempLengthAtEnd) // Data is at end, copy to beginning
+        {
+            // Overlapping src and dst!
+            for (int i=0; i<tempLength; i++)
+                tempBuffer[i] = tempBuffer[TS_SIZE-tempLength+i];
+        }
+        // Normalize TempBuffer fill
+        if (tempLength < TS_SIZE && length > 0)
+        {
+            int Size = min(TS_SIZE-tempLength, length);
+            memcpy(tempBuffer+tempLength, data, Size);
+            data += Size;
+            length -= Size;
+            tempLength += Size;
+        }
+        if (tempLength < TS_SIZE)
+        {
+            // All incoming data buffered, but need more data
+            tempLengthAtEnd = false;
+            OutLength = 0;
+            return NULL;
+        }
+        // Now: TempLength==TS_SIZE
+        if (tempBuffer[0] != TS_SYNC_BYTE)
+        {
+            // Need to sync on TS within temp buffer
+            int Skipped = 1;
+            while (Skipped < TS_SIZE && (tempBuffer[Skipped] != TS_SYNC_BYTE || (Skipped < length && data[Skipped] != TS_SYNC_BYTE)))
+                Skipped++;
+            esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
+            // Pass through skipped bytes
+            tempLengthAtEnd = true;
+            tempLength = TS_SIZE - Skipped; // may be 0, thats ok
+            OutLength = Skipped;
+            return tempBuffer;
+        }
+        // Now: TempBuffer is a TS packet
+        int Pid = TsPid(tempBuffer);
+        if (pPatPmtParser)
+        {
+            if (Pid == 0)
+                pPatPmtParser->ParsePat(tempBuffer, TS_SIZE);
+            else if (pPatPmtParser->IsPmtPid(Pid))
+                pPatPmtParser->ParsePmt(tempBuffer, TS_SIZE);
+        }
+
+        TotalPackets++;
+        bool Drop = false;
+        if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B))
+            Drop = NaluDumper.ProcessTSPacket(tempBuffer);
+        if (!Drop)
+        {
+            // Keep this packet, then continue with new data
+            tempLength = 0;
+            OutLength = TS_SIZE;
+            return tempBuffer;
+        }
+        // Drop TempBuffer
+        DroppedPackets++;
+        tempLength = 0;
+    }
+    // Now: TempLength==0, just process data/length
+
+    // Pointer to processed data / length:
+    uchar *Out = data;
+    uchar *OutEnd = Out;
+
+    while (length >= TS_SIZE)
+    {
+        if (data[0] != TS_SYNC_BYTE) {
+            int Skipped = 1;
+            while (Skipped < length && (data[Skipped] != TS_SYNC_BYTE || (length - Skipped > TS_SIZE && data[Skipped + TS_SIZE] != TS_SYNC_BYTE)))
+                Skipped++;
+            esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
+
+            // Pass through skipped bytes
+            if (OutEnd != data)
+                memcpy(OutEnd, data, Skipped);
+            OutEnd += Skipped;
+            continue;
+        }
+        // Now: Data starts with complete TS packet
+
+        int Pid = TsPid(data);
+        if (pPatPmtParser)
+        {
+            if (Pid == 0)
+                pPatPmtParser->ParsePat(data, TS_SIZE);
+            else if (pPatPmtParser->IsPmtPid(Pid))
+                pPatPmtParser->ParsePmt(data, TS_SIZE);
+        }
+
+        TotalPackets++;
+        bool Drop = false;
+        if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B))
+            Drop = NaluDumper.ProcessTSPacket(data);
+        if (!Drop)
+        {
+            if (OutEnd != data)
+                memcpy(OutEnd, data, TS_SIZE);
+            OutEnd += TS_SIZE;
+        }
+        else
+        {
+            DroppedPackets++;
+        }
+        data += TS_SIZE;
+        length -= TS_SIZE;
+    }
+    // Now: Less than a packet remains.
+    if (length > 0)
+    {
+        // copy remains into temp buffer
+        memcpy(tempBuffer, data, length);
+        tempLength = length;
+        tempLengthAtEnd = false;
+        length = 0;
+    }
+    OutLength = (OutEnd - Out);
+    return OutLength > 0 ? Out : NULL;
+}
diff -a -U 2 -r a/remux.h b/remux.h
--- a/remux.h
+++ b/remux.h
@@ -65,4 +65,9 @@
 }
 
+inline bool TsSetPayload(const uchar *p)
+{
+  return p[3] & TS_PAYLOAD_EXISTS;
+}
+
 inline bool TsHasAdaptationField(const uchar *p)
 {
@@ -156,4 +161,5 @@
 void TsSetPts(uchar *p, int l, int64_t Pts);
 void TsSetDts(uchar *p, int l, int64_t Dts);
+void TsExtendAdaptionField(unsigned char *Packet, int ToLength);
 
 // Some PES handling tools:
@@ -550,3 +556,77 @@
   };
 
+
+#define PATCH_NALUDUMP 100
+
+class cNaluDumper {
+    unsigned int History;
+
+    int LastContinuityInput;
+    int LastContinuityOutput;
+    int ContinuityOffset;
+
+    bool DropAllPayload;
+
+    int PesId;
+    int PesOffset;
+
+    int NaluOffset;
+
+    enum eNaluFillState {
+        NALU_NONE=0,    // currently not NALU fill stream
+        NALU_FILL,      // Within NALU fill stream, 0xff bytes and NALU start code in byte 0
+        NALU_TERM,      // Within NALU fill stream, read 0x80 terminating byte
+        NALU_END        // Beyond end of NALU fill stream, expecting 0x00 0x00 0x01 now
+        };
+
+    eNaluFillState NaluFillState;
+
+    struct sPayloadInfo {
+        int DropPayloadStartBytes;
+        int DropPayloadEndBytes;
+        bool DropAllPayloadBytes;
+    };
+
+public:
+    cNaluDumper();
+
+    void reset();
+
+    // Single packet interface:
+    bool ProcessTSPacket(unsigned char *Packet);
+
+private:
+    void ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info);
+};
+
+class cNaluStreamProcessor {
+    //Buffer stream interface:
+    int vpid;
+    uchar *data;
+    int length;
+    uchar tempBuffer[TS_SIZE];
+    int tempLength;
+    bool tempLengthAtEnd;
+    cPatPmtParser *pPatPmtParser;
+    cNaluDumper NaluDumper;
+
+    long long int TotalPackets;
+    long long int DroppedPackets;
+public:
+    cNaluStreamProcessor();
+
+    void SetPid(int VPid) { vpid = VPid; }
+    void SetPatPmtParser(cPatPmtParser *_pPatPmtParser) { pPatPmtParser = _pPatPmtParser; }
+    // Set either a PID or set a pointer to an PatPmtParser that will detect _one_ PID
+
+    void PutBuffer(uchar *Data, int Length);
+    // Add new data to be processed. Data must be valid until Get() returns NULL.
+    uchar* GetBuffer(int &OutLength);
+    // Returns filtered data, or NULL/0 to indicate that all data from Put() was processed
+    // or buffered.
+
+    long long int GetTotalPackets() { return TotalPackets; }
+    long long int GetDroppedPackets() { return DroppedPackets; }
+};
+
 #endif // __REMUX_H
