Skip to content

@mega-yfue/eufy-sdk / AccessUnitAssembler

Class: AccessUnitAssembler

Reassembles a CMD_VIDEO_FRAME access unit the station split across several frames.

Each frame declares only the payload IT carries (VideoFrameHeader.payloadLength), so the unit's total length is nowhere on the wire and cannot be waited for. What the wire does carry, verified on two models:

  • the frames of one unit repeat its header — same timestamp, same VideoFrameHeader.sequence — while consecutive units differ in both;
  • every frame of a split unit is filled to STATION_CHUNK_BYTES except the last;
  • a frame that STARTS a unit begins with an Annex-B start code once decoded, and a continuation begins mid-NAL, so it does not.

A unit is therefore held only while its latest frame is full, and completed the moment a shorter one arrives — no delivery latency for the overwhelming majority of units, which arrive in one frame below the threshold. The identity match and the missing start code are required TOGETHER before appending: either alone would let two decodable units merge, and a merge is invisible to a consumer that trusts the contract.

A unit is delivered only when it is complete. A lost datagram makes the P2P layer discard the frame it was reassembling, so a unit whose tail never arrives is ended by the next unit's first frame while still full — that one is dropped and reported, never handed on short. Truncated bytes are worse than none: a decoder given an access unit shorter than its own slice headers promise reports bitstream truncation and produces no picture at all.

Two consequences worth stating. A unit that is exactly the threshold long, or an exact multiple of it, ends on a full frame and is dropped as truncated — one frame in ~64000, reported, and the alternative is handing a decoder bytes that may genuinely be short. And a station that fills to some OTHER size is not recognised: its units stay exactly as they arrive rather than being mis-joined.

Constructors

Constructor

ts
new AccessUnitAssembler(onDropped?): AccessUnitAssembler;

Parameters

onDropped?

(drop) => void

called for each incomplete unit discarded, with what had arrived, how many frames it arrived in, and how many this assembler has dropped in total — a running count, so no caller keeps its own.

Returns

AccessUnitAssembler

Methods

push()

ts
push(payload, decode): AssembledAccessUnit[];

Feed one raw CMD_VIDEO_FRAME payload; returns the access units it completed — none while a unit is still being filled, one in the ordinary case.

decode extracts the payload of a frame, whatever the stream's encryption: it is called for EVERY frame, including a continuation, because a continuation carries its own wrapped key ahead of its share of the payload (measured: 129 bytes beyond what its header declares, exactly as a unit's first frame carries).

Parameters

payload

Buffer

decode

(payload) => Buffer<ArrayBufferLike> | undefined

Returns

AssembledAccessUnit[]

Independent and unofficial. Not affiliated with, endorsed by, or sponsored by Anker Innovations, Anker eufy, or eufy. "Anker eufy", "eufy" and "Anker" are trademarks of their respective owners. Use responsibly — rapid or failed logins can trigger captcha or temporary cooldowns.