expected lifecycle for an old-SDK DtsArchiveReader
I've been working on a custom Hikvision remote-archive integration that is 99% working correctly for things like camera discovery, live RTSP, archive timeline discovery, arbitrary historical seek and accelerated archive playback plus motion/analytics events into NX etc.
The failure appears only after I switch from archive Playback to Live and then requests archive playback again. In the failing state, Nx continues to call DtsArchiveReader::seek() on the same reader object, and the plugin can successfully locate and open the requested Hikvision recording, but Nx does not resume calls to StreamReader::getNextData(). The server-side QnArchiveStreamReader instead reports "EOF from delegate" and the client falls back to Live.
A full teardown and fresh archive-reader acquisition restores playback. Diagnostic tests returning NX_NO_DATA and NX_NETWORK_ERROR on the first post-Live seek did not reliably force Nx to replace the stale active archive adapter. This points away from Hikvision transport failure and toward archive delegate/adapter lifecycle or re-arming behaviour between the old Server Plugin SDK and Media Server.
Functions that are working
- Manual Hikvision discovery and multi-channel device creation.
- Live video via RTSP.
- Archive period/timeline discovery via ISAPI.
- Historical archive playback from arbitrary timestamps.
- Minute-accurate seek within a physical Hikvision recording.
- Fast-forward using the unpaced ISAPI download transport.
- Fresh DtsArchiveReader / StreamReader instances can deliver archive packets immediately.
Important distinction
The failing post-Live request is not simply a case where the Hikvision NVR cannot find or open the footage. In normal failing captures, the plugin receives the post-Live seek, performs a valid recording search, opens the Hikvision archive stream successfully, completes FFmpeg stream discovery and returns a selected archive position. The failure occurs after that point because Nx does not resume StreamReader::getNextData() on the existing reader.
Reproduction procedure
1. Open a camera from the custom Hikvision archive plugin.
2. Select a known recorded time and allow archive playback to run normally for approximately 20-30 seconds.
3. Select Live and leave the camera live for several seconds or longer.
4. Select another known recorded time shown in the timeline.
5. Observe that the plugin receives DtsArchiveReader::seek() on the existing ArchiveReader/StreamReader pair.
6. The plugin can successfully open the requested archive media, but Nx does not call getStreamReader() again and does not resume StreamReader::getNextData().
7. QnArchiveStreamReader reports "EOF from delegate" and the client returns to or remains on Live. Repeated archive requests can remain on the same stale adapter.
Expected behaviour
After a successful DtsArchiveReader::seek(), the existing StreamReader should be polled again, or the Media Server old-SDK bridge should reacquire/recreate the archive reader/delegate if the prior stream reference was released during the switch to Live.
Actual behaviour
The same DtsArchiveReader can continue to receive seek commands while the associated server-side QnArchiveStreamReader remains at EOF. The plugin is therefore able to reposition/open its archive source, but no packet requests reach StreamReader::getNextData().
Key evidence
Normal build: post-Live seek opens Hikvision archive successfully, but Nx does not poll it
C13 / track 1301, 16 October 2026. Before Live, archive playback is active and getNextData() is being called. When Live is selected, Nx releases its external StreamReader reference from 2 to 1; the reader is not destroyed. Five seconds later Nx sends a new seek to the same ArchiveReader/StreamReader pair.
14:39:51.887 StreamReader getNextData ... track=1301 cSeq=3 [archive working]
14:39:52.900 StreamReader releaseRef-after ... track=1301 result=1 [switch to Live]
14:39:57.539 ArchiveReader seek ... same reader, cSeq=4
14:39:57.540 StreamReader setPosition / openPlaybackAt
14:39:58.081 ISAPI download ... opened successfully
14:39:58.666 FFmpeg stream info OK; synchronous playback open succeeded
14:39:58.667 ArchiveReader seek-selected ... cSeq=4
14:39:58.667 Nx QnArchiveStreamReader(...): EOF from delegate
No post-seek plugin getNextData() follows for this stale reader.
The same C13 reader subsequently received further seeks (including cSeq 5 and cSeq 7), successfully opened valid Hikvision recordings again, and still was not polled by getNextData(). The same outer QnArchiveStreamReader continued reporting EOF from delegate.
Fresh-reader recovery
A separate C1 / track 101 sequence shows that archive media starts working again when the outer Nx archive provider/session is fully torn down and a fresh plugin reader is acquired.
14:38:00.023 Nx closes archive RTSP session for track 101
14:38:00.025 QnArchiveStreamReader data processor removed / provider deleted
14:38:00.025 Old plugin ArchiveReader and StreamReader destructed
14:38:00.027 createDtsArchiveReader called for track 101
14:38:02.362 Fresh reader: getStreamReader -> addRef result=2
14:38:02.362 Fresh reader: getNextData called immediately
14:38:02.363 Video packet delivered successfully
This strongly suggests that the Hikvision archive transport and packet production remain viable; the failure is tied to the stale archive adapter/delegate state that survives the Playback -> Live transition.
Error-return reset experiments
We added a one-shot diagnostic that detects the external StreamReader release associated with leaving archive playback and deliberately rejects the first subsequent seek. Two return codes were tested: NX_NO_DATA and NX_NETWORK_ERROR.
- NX_NO_DATA: did not cause the active old archive adapter to be discarded/recreated; the stale reader remained and no new getNextData() path was established.
- NX_NETWORK_ERROR: Nx still reported EOF from delegate. A new DtsArchiveReader object was briefly created and queried for capabilities/quality, then destroyed without seek(), getStreamReader() or getNextData(). The original stale active reader remained alive until the session later closed.
19 Oct 10:32:28.805 Existing reader receives post-Live seek
19 Oct 10:32:28.805 STALE_ADAPTER_DROP_TEST forcing NX_NETWORK_ERROR
19 Oct 10:32:28.806 QnArchiveStreamReader(...): EOF from delegate
19 Oct 10:32:29.056 createDtsArchiveReader called (transient probe)
19 Oct 10:32:29.060 transient reader destroyed without seek/getStreamReader
19 Oct 10:33:40.769 original active ArchiveReader/StreamReader finally destroyed
Questions for Network Optix Technical Support
1. Is the described Playback -> Live -> Playback behaviour a known issue in Nx Witness Media Server 6.1.2.42921 when using the old Server Plugin SDK DtsArchiveReader bridge?
2. When Nx releases its external StreamReader reference on the switch to Live but retains the DtsArchiveReader, what is the expected public SDK sequence for the plugin to resume archive playback on a later seek?
3. After a successful seek() on an existing DtsArchiveReader, should Media Server call getStreamReader() again, or should it automatically resume polling the previously returned StreamReader? In the failing state neither happens.
4. Is there a supported plugin-side API call, return code, property, command, or sequence that explicitly resets/re-arms/reopens the old-SDK archive delegate?
5. We observed the internal symbol name QnAbstractArchiveDelegate::reopen() while inspecting the server binary. Is there a public old-SDK mechanism that maps to this behaviour, or is this entirely internal?
6. Is there a server diagnostic/INI setting that enables detailed logging for the old-SDK camera/archive adapter so we can see why the delegate remains at EOF after a successful plugin seek?
7. If this is a limitation or bug in the old SDK bridge, is there a recommended newer SDK/API for third-party remote archive playback, and is there a migration example for a DtsArchiveReader-style integration?
Regards
Richard
-
Hi Richard,
Thanks for the detailed report with a clear timeline of the processes.
This makes it easier for us to understand the issue.Please find the replies to your questions below.
1. Is the described Playback -> Live -> Playback behaviour a known issue in Nx Witness Media Server 6.1.2.42921 when using the old Server Plugin SDK DtsArchiveReader bridge?
This issue has not been reported.
We find the possible cause in the 6.1.2.42921, and will forward this issue to our dev team for further inspection.
2. When Nx releases its external StreamReader reference on the switch to Live but retains the DtsArchiveReader, what is the expected public SDK sequence for the plugin to resume archive playback on a later seek?
At this time there is no such sequence. When the problem occurs, the server has no StreamReader to poll, and the bridge does not call getStreamReader() again. Nothing the plugin returns from seek() can change this.
3. After a successful seek() on an existing DtsArchiveReader, should Media Server call getStreamReader() again, or should it automatically resume polling the previously returned StreamReader? In the failing state neither happens.
The server should call getStreamReader() again. The bridge calls it only from its open step, which runs DtsArchiveReader::open() and then getStreamReader().
4. Is there a supported plugin-side API call, return code, property, command, or sequence that explicitly resets/re-arms/reopens the old-SDK archive delegate?
No. The seek() return codes are converted as follows:
- NX_NO_ERROR returns the selected position.
- NX_NO_DATA returns "end of archive" (or "start of archive" in reverse mode).
- Any other code returns "no position".None of these codes makes the server reopen the delegate or replace it.
5. We observed the internal symbol name QnAbstractArchiveDelegate::reopen() while inspecting the server binary. Is there a public old-SDK mechanism that maps to this behaviour, or is this entirely internal?
This function is internal, and the old-SDK archive delegate does not implement it. The server also does not call it in this playback path.
6. Is there a server diagnostic/INI setting that enables detailed logging for the old-SDK camera/archive adapter so we can see why the delegate remains at EOF after a successful plugin seek?
You can set the Server log level to verbose with filters for QnArchiveStreamReader and QnRtspConnectionProcessor. These logs show the provider stop and restart, the seeks, and the "EOF from delegate" line.
7. If this is a limitation or bug in the old SDK bridge, is there a recommended newer SDK/API for third-party remote archive playback, and is there a migration example for a DtsArchiveReader-style integration?
Starting with version 6.0, the Video Source, Storage and Cloud Storage SDKs are part of one Server Plugin SDK. For device integration, that SDK still uses the nxcip interfaces, and DtsArchiveReader is the only interface for archive playback from a camera or an NVR.
Thank you.0 -
Thank you for the reply
This clarifies the behaviour we saw, your explanation matches what we observed in the diagnostic logs: after switching to Live, the external StreamReader reference is released while the DtsArchiveReader remains alive etc.
A laterseek()succeeds, but because the bridge does not execute its open step again,getStreamReader()is never called and Media Server has no StreamReader to poll.As you have confirmed that there is no plugin-side API, return code or reopen sequence capable of restoring the delegate, I will leave the plugin implementation unchanged and log it on my side as the only issue/bug found during testing.
Thanks again for escalating this to the development team, hopefully they can see a workaround or add a way for us to reset the process and request a new one, i could see ONVIF profile G supported edge playback but i dont have a camera to test if that has the same playback/live/playback issue.
It's a shame as this is the only bug/issue stopping us from releasing the plugin for full HikVision camera edge and NVR storage support, but i have some internal politics to deal with before we can release it anyway, so hopefully there is a resolution for the playback issue by the time i'm ready to release it.
Best Regards
Richard
0
Please sign in to leave a comment.
Comments
2 comments