The StarDot DVR / NVR saves a pair of files for every one hour of recording. The STX file is the index and the SDJ file in the motion JPEG video.
.stx file format
The .stx files consist of multiple "struct tindexhdr" records, one per image, starting at offset 0 in the .stx file (ie., there is no ".stx file header").
/** This is the header we write to the index file, it contains the _timeb of
* the image, and it's location in the file. During graphing and playback
* this is absolutely mandatory. It supports 64 bit file offsets. */ struct tindexhdr {
time_t time; /**< Seconds since midnight Jan 1, 1970 UTC. */
unsigned short millitm; /**< Milliseconds. */
ULONGLONG fpos; /**< Offset in image file. */
};
.sdj file format:
"struct recordhdr" + JFIF/JPEG + "struct recordtlr", one per image, starting at offset 0 in the .sdj file (there is also no ".sdj file header").
#undef OLDFORMAT /**< Define to use and read old record format. */
#define FOURCC(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
#define FOURCC_JPEG FOURCC('J','P','E','G') /**< Old header type. */
#define FOURCC_JPG1 FOURCC('J','P','G','1') /**< New header type. */
/** This is the header we write before every JPEG in our stored recorded info. */ struct recordhdr {
unsigned int type; /**< Record type: "JPG1" for a JPEG image saved with this header. */
unsigned int len; /**< Length of data for this record, which includes header,
* data, and trailer. The idea is to keep this format
* so that unknown record types can be skipped by just
* passing this length, regardless of what's in the
* record. */
_timeb timestamp; /**< Time the image/record was created. */
#ifndef OLDFORMAT
ULONGLONG MotionL; /**< Low motion trigger region, 64 regions. Top part of image,
* 16 across, 4 high. */
ULONGLONG MotionH; /**< High motion trigger region, 64 regions. Bot part of image,
* 16 across, 4 high. */
#endif
WORD triggers; /**< 0xFFF0 = Unused, clear.
* 0x000F = 4 bits of trigger info, set means trigger active. */
};
/** This is the trailer we write after every JPEG. It allows backwards
* indexing, to play the data backwards without having to resort to the
* index file. */
struct recordtlr {
unsigned int len; /**< Length of full record, all parts included. */
};