7.72 — three reproducible crash signatures, with dump analysis (LAVVideo AV on freed input sample, ProgDvbEngine+0xE93D9
Posted: Tue Sep 01, 2026 12:21 pm
Hello,
I run ProgDVB Professional 7.72 on two machines as a 24/7 IPTV + recording setup. Both crash regularly. I analysed the crash dumps and can give exact fault locations, faulting instructions, register state and call stacks. I hope this saves you time.
There are three distinct signatures, not one.
═══ ENVIRONMENT ═══
Both machines run two ProgDVB instances at once, playing HLS/IPTV sources over the internet, with timeshift enabled (MaxTimeShift=8) and continuous recording. Some source streams are unstable and disconnect often — this appears to matter, see TRIGGER CONDITIONS below.
═══ SIGNATURE 1 — LAVVideo.ax+0xF116D — access violation reading a freed input sample ═══
Two full dumps, byte-identical code path in both.
Faulting instruction, disassembled from the dump's own memory image:
This is the AVX2 memcpy fast path, i.e. memcpy(dst = RCX, src = RDX, len = R8):
The source pointer is the problem. In both dumps that address is absent from the dump's memory ranges entirely — the pages were decommitted, not merely heap-freed. The pointer is not NULL and looks like a plausible heap address, so this is a dangling pointer, not a missing NULL check. The length differs per crash, consistent with a compressed frame payload.
Call stack, identical in both dumps, innermost first:
I located the exact source line. LAV Filters is open source and this is CDecAvcodec::ParsePacket() in decoder/LAVVideo/decoders/avcodec.cpp:
The registers map onto it exactly: m_pFFBuffer = RCX (LAV's own buffer, valid), buffer = RDX (your IMediaSample data pointer, unmapped), buflen = R8.
m_bInputPadded is set at avcodec.cpp:582 as m_bInputPadded = (dwDecFlags & LAV_VIDEO_DEC_FLAG_LAVSPLITTER), and that flag is only set when the upstream filter is LAV Splitter. With ProgDVB upstream it is false, so LAV takes this defensive path: it allocates its own padded buffer and copies your sample data into it before touching anything else.
This means LAV Video is not doing anything wrong. That memcpy is the first read of the sample data. So the window is not "LAV held the pointer too long" — the sample's memory was already released before or during the Receive() call that delivered it.
At the moment of the crash, 102 of 103 threads were parked in ntdll waits — the releasing thread had already returned, which is what you would expect from a lifetime race rather than true simultaneous access.
Also note the pages are unmapped, not merely heap-freed. A CRT/heap free would normally leave the page readable and produce corrupt video rather than an AV. That points at a buffer allocated with VirtualAlloc and released with VirtualFree, or an allocator Decommit().
Suggested fix. Because the very first read of the sample faults, the problem is on the delivery side, not in the decoder. Worth checking in this order:
═══ SIGNATURE 2 — ProgDvbEngine.DLL+0xE93D9 — most frequent (machine B) ═══
Seven occurrences in 90 days, always the identical offset:
Same offset every time = a single deterministic code path, not memory corruption.
I could not analyse this one: no crash dump is produced on that machine, and the address is inside the protected region of the DLL. RVA 0xE93D9 lies outside the raw .text range (0x1000-0xB7200) of the on-disk image, so it only exists after the runtime unpacks — static analysis returns nothing there. A dump would resolve it immediately, as it did for signature 1.
Question: what is the supported way to make ProgDVB write a crash dump? On machine A there is a C:\PDVB\_crashdumps\ folder with ProgDvbNet.exe.<pid>.dmp files (~78 MB), but machine B has no such folder and produces none. If creating the folder is enough, please say so and I will capture one and send it. Otherwise I can enable Windows WER LocalDumps.
Two of the seven coincided (within 1 second) with a recording ending; the other five happened while that instance was only playing, so it is not recording-specific.
═══ SIGNATURE 3 — ucrtbase.dll+0xA527E — fast-fail from GDI+ / System.Drawing ═══
Entirely in the managed UI layer, unrelated to decoding. Looks like an invalid parameter reaching a GDI+ call — a disposed or concurrently-used Graphics/Bitmap on the OSD/skin drawing path would produce this. Note R8 = 0x7FFFFFFFFFFFFFFC, which looks like a bad size/offset.
═══ TRIGGER CONDITIONS ═══
I analysed 128 recordings over 22 days on machine B by measuring actual written bitrate. Sources that disconnect frequently correlate strongly with both stalls and crashes:
"Stalled" means the recording file stays open for hours while almost no data is written — e.g. 725 minutes producing 359 MB (0.07 Mbps). The existing 15-second no-data watchdog does not catch this (see below), and from the UI a trickling stream looks identical to a working one.
Every disconnect triggers a stream teardown/rebuild, and every teardown is another chance to hit the race in signature 1. Normal reconnects recover in 3-4 seconds; a crash costs about two hours because nothing restarts the application.
═══ ON THE EXISTING STREAM WATCHDOG ═══
I want to be accurate here: ProgDVB already has this recovery, and it works. On machine A I see it fire and recover correctly:
Three times today, roughly every two hours, each time recovering in a few seconds.
The gap is that the trigger appears to be absence of data for 15 s, and the failure mode above is not an absence — it is a trickle. A source delivering 0.07 Mbps never stops sending for 15 seconds, so the timer keeps resetting while the picture is unusable and the recording grows at 1/100th of the expected rate. The watchdog is presence-based; the failure is rate-based.
Request: could the refresh trigger also consider throughput — e.g. "if the incoming bitrate stays below X% of the nominal rate for N seconds, refresh the channel"? That would close the remaining case.
Question: ProgTV.win.ini contains RefreshLevelNetwork=0, which I cannot find documented anywhere. What are the valid values and what does each level change? If a higher level already makes recovery more aggressive, I would like to try that before asking you for a code change.
One more small request: auto-restart after a crash, or at least resuming an interrupted recording. A crash currently costs about two hours of recording because nothing brings the application back.
═══ WHAT I RULED OUT ═══
I run ProgDVB Professional 7.72 on two machines as a 24/7 IPTV + recording setup. Both crash regularly. I analysed the crash dumps and can give exact fault locations, faulting instructions, register state and call stacks. I hope this saves you time.
There are three distinct signatures, not one.
═══ ENVIRONMENT ═══
Code: Select all
Machine A Machine B
OS Windows 11 Pro 26200 Windows 10 Pro 22H2 19045
CPU AMD Ryzen 7 PRO 4750U 8C/16T Intel Core i7-4770 4C/8T
RAM 31 GB 20 GB
GPU AMD Radeon (Vega) 31.0.21921 Intel HD 4600 20.19.15.4531
.NET 4.8.09221 4.8.09037
ProgDVB 7.72.0.0 portable 7.72.0.0 portable
Renderer EVR EVR
Bundled LAV 0.80.0, 1294520 bytes, SHA256 10B54672...049327DA (identical)
ProgDvbNet.exe timestamp 6A40348F
ProgDvbEngine.DLL timestamp 6A17E841═══ SIGNATURE 1 — LAVVideo.ax+0xF116D — access violation reading a freed input sample ═══
Two full dumps, byte-identical code path in both.
Code: Select all
Exception : c0000005 ACCESS_VIOLATION, READ
Module : LAVVideo.ax (0.80.0) +0xF116DCode: Select all
vmovdqu ymm0, ymmword ptr [rdx] <-- AV here
vmovdqu ymm5, ymmword ptr [rdx+r8-0x20]
cmp r8, 0x100
jbe ...
mov r9, rcx
and r9, 0x1f ; align destination to 32Code: Select all
Dump Date dst (RCX) src (RDX) len (R8) src page
#1 2026-08-26 20:31 0x133362C6B40 0x1332F5BE3C0 6633 NOT MAPPED
#2 2026-08-30 16:47 0x1E3B35F0040 0x1E3C9A1AD6E 36198 NOT MAPPEDCall stack, identical in both dumps, innermost first:
Code: Select all
LAVVideo.ax+0x3364 <- memcpy
LAVVideo.ax+0xA80F4
LAVVideo.ax+0x3222
LAVVideo.ax+0x19324
LAVVideo.ax+0x3130
LAVVideo.ax+0x1DDD
combase.dll+0x78C7 <- COM boundary (dump #1)
LAVVideo.ax+0x1705D
LAVVideo.ax+0x1F916
ProgDvbEngine.DLL+0x12D192 <-- ProgDVB delivering the sample
LAVVideo.ax+0xA2B71
LAVVideo.ax+0xA8A8E
LAVVideo.ax+0xA2D22
ProgDvbEngine.DLL+0x132F32
ProgDvbEngine.DLL+0x13281C <-- ProgDVB worker thread entry
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStartCode: Select all
// re-allocate with padding, if needed
if (m_bInputPadded == false && buflen > 0)
{
BYTE *pBuf = (BYTE *)av_fast_realloc(m_pFFBuffer, &m_nFFBufferSize,
buflen + AV_INPUT_BUFFER_PADDING_SIZE);
if (!pBuf) return E_FAIL;
m_pFFBuffer = pBuf;
memcpy(m_pFFBuffer, buffer, buflen); // <-- THE CRASH IS HERE
memset(m_pFFBuffer + buflen, 0, AV_INPUT_BUFFER_PADDING_SIZE);
pDataBuffer = m_pFFBuffer;
}m_bInputPadded is set at avcodec.cpp:582 as m_bInputPadded = (dwDecFlags & LAV_VIDEO_DEC_FLAG_LAVSPLITTER), and that flag is only set when the upstream filter is LAV Splitter. With ProgDVB upstream it is false, so LAV takes this defensive path: it allocates its own padded buffer and copies your sample data into it before touching anything else.
This means LAV Video is not doing anything wrong. That memcpy is the first read of the sample data. So the window is not "LAV held the pointer too long" — the sample's memory was already released before or during the Receive() call that delivered it.
At the moment of the crash, 102 of 103 threads were parked in ntdll waits — the releasing thread had already returned, which is what you would expect from a lifetime race rather than true simultaneous access.
Also note the pages are unmapped, not merely heap-freed. A CRT/heap free would normally leave the page readable and produce corrupt video rather than an AV. That points at a buffer allocated with VirtualAlloc and released with VirtualFree, or an allocator Decommit().
Suggested fix. Because the very first read of the sample faults, the problem is on the delivery side, not in the decoder. Worth checking in this order:
- IMemAllocator::Decommit() must not release the buffer memory until every outstanding sample has been returned. If ProgDVB's allocator VirtualFrees or decommits its arena on Decommit without waiting for outstanding IMediaSample references, this is exactly the observed failure.
- Ordering of flush/stop vs. streaming: ensure BeginFlush / EndFlush / Stop cannot run the teardown path concurrently with an in-flight Receive() on the streaming thread.
- Do not deliver a sample whose allocator has already been decommitted — on a source disconnect the streaming thread may still have one sample in hand.
- If buffers are recycled rather than freed, the same symptom appears when a buffer is recycled one sample too early.
═══ SIGNATURE 2 — ProgDvbEngine.DLL+0xE93D9 — most frequent (machine B) ═══
Code: Select all
Exception : c0000005 ACCESS_VIOLATION
Module : ProgDvbEngine.DLL +0xE93D9
WER bucket: 6534305e3843e894376fa3657d11bb7e15e4ae1 / 2442a3b1Code: Select all
2026-08-11 03:41:34 2026-08-13 02:14:30 2026-08-30 15:06:31
2026-08-11 14:02:20 2026-08-26 03:16:45 2026-08-30 22:29:28
2026-08-11 21:29:23I could not analyse this one: no crash dump is produced on that machine, and the address is inside the protected region of the DLL. RVA 0xE93D9 lies outside the raw .text range (0x1000-0xB7200) of the on-disk image, so it only exists after the runtime unpacks — static analysis returns nothing there. A dump would resolve it immediately, as it did for signature 1.
Question: what is the supported way to make ProgDVB write a crash dump? On machine A there is a C:\PDVB\_crashdumps\ folder with ProgDvbNet.exe.<pid>.dmp files (~78 MB), but machine B has no such folder and produces none. If creating the folder is enough, please say so and I will capture one and send it. Otherwise I can enable Windows WER LocalDumps.
Two of the seven coincided (within 1 second) with a recording ending; the other five happened while that instance was only playing, so it is not recording-specific.
═══ SIGNATURE 3 — ucrtbase.dll+0xA527E — fast-fail from GDI+ / System.Drawing ═══
Code: Select all
Date : 2026-08-22 15:47
Instruction : int 0x29 (__fastfail)
RCX : 7 (FAST_FAIL_FATAL_APP_EXIT)
R8 : 0x7FFFFFFFFFFFFFFC
ucrtbase.dll+0xA527E
ucrtbase.dll+0xB2FA8
System.Drawing.ni.dll+0x11310
System.Drawing.ni.dll+0x6E7AA
ucrtbase.dll+0x6E70D
GdiPlus.dll+0xFA42
System.Drawing.ni.dll+0x676B5
clr.dll+0x7E7630
System.Drawing.ni.dll+0x67620
System.Drawing.ni.dll+0x6E39E
System.Drawing.ni.dll+0x124C0═══ TRIGGER CONDITIONS ═══
I analysed 128 recordings over 22 days on machine B by measuring actual written bitrate. Sources that disconnect frequently correlate strongly with both stalls and crashes:
Code: Select all
Source group healthy stalled (<0.5 Mbps for hours)
Direct, stable HLS sources 77 0
Unstable provider sources 5 7Every disconnect triggers a stream teardown/rebuild, and every teardown is another chance to hit the race in signature 1. Normal reconnects recover in 3-4 seconds; a crash costs about two hours because nothing restarts the application.
═══ ON THE EXISTING STREAM WATCHDOG ═══
I want to be accurate here: ProgDVB already has this recovery, and it works. On machine A I see it fire and recover correctly:
Code: Select all
09:41:45.292 - [101]TransponderManager::RefreshChannel ! 15s chunk=1 net=1 10000ms error0
09:41:45.294 - Do RefreshChannelThe gap is that the trigger appears to be absence of data for 15 s, and the failure mode above is not an absence — it is a trickle. A source delivering 0.07 Mbps never stops sending for 15 seconds, so the timer keeps resetting while the picture is unusable and the recording grows at 1/100th of the expected rate. The watchdog is presence-based; the failure is rate-based.
Request: could the refresh trigger also consider throughput — e.g. "if the incoming bitrate stays below X% of the nominal rate for N seconds, refresh the channel"? That would close the remaining case.
Question: ProgTV.win.ini contains RefreshLevelNetwork=0, which I cannot find documented anywhere. What are the valid values and what does each level change? If a higher level already makes recovery more aggressive, I would like to try that before asking you for a code change.
One more small request: auto-restart after a crash, or at least resuming an interrupted recording. A crash currently costs about two hours of recording because nothing brings the application back.
═══ WHAT I RULED OUT ═══
- Disk space — all record/timeshift paths point to a volume with 3.3 TB free.
- Hardware acceleration — irrelevant to signature 1 by construction: the fault happens in the input copy, before any decoding, so the decode backend cannot matter.
- CPU starvation — one machine was CPU-limited by a power policy. Fixing it (1.6 GHz -> 3.2 GHz, ProgDVB CPU use 107% of a core -> 16%) removed stuttering but did not change the crash signatures.
- Memory pressure — 31 GB / 20 GB, both machines had over 12 GB free at crash time.
- Drivers — different OS versions, CPU vendors and GPU vendors produce the same signatures.
- Three full crash dumps (~78 MB each) for signatures 1 and 3.
- Report.wer files for all eight crashes on machine B.
- A dump for signature 2 as soon as you tell me how to make ProgDVB produce one.