@@ -28,18 +28,28 @@ inline size_t headerLenFor(uint8_t flags) {
2828 return 2u + ((flags & kPts ) ? 4u : 0u ) + ((flags & kScr ) ? 6u : 0u );
2929}
3030
31+ // / Whether the flags are a header's: end of header set, no error, no reserved bit.
32+ inline bool headerFlagsOk (uint8_t flags) { return (flags & kEoh ) && !(flags & (kErr | kReserved )); }
33+
34+ // / Whether the SCR's reserved top 5 bits are zero, the strongest single check a header carries.
35+ inline bool headerScrOk (const uint8_t * h, uint8_t flags, uint8_t len) {
36+ return !(flags & kScr ) || !(h[len - 1 ] & 0xF8 );
37+ }
38+
39+ // / Whether the PTS matches the frame's first header, which is constant across one frame's payloads.
40+ inline bool headerPtsOk (const uint8_t * h, uint8_t flags, const uint8_t * pts) {
41+ return !pts || !(flags & kPts ) || std::memcmp (h + 2 , pts, 4 ) == 0 ;
42+ }
43+
3144// / Whether `h` is a payload header of exactly `want` bytes; `pts` pins it to the frame's first one.
3245inline bool isPayloadHeader (const uint8_t * h, size_t avail, size_t want, const uint8_t * pts) {
3346 if (avail < 2 ) return false ;
3447 const uint8_t len = h[0 ], flags = h[1 ];
3548 if (len != want || len != headerLenFor (flags) || avail < len) return false ;
36- if (!(flags & kEoh ) || (flags & (kErr | kReserved ))) return false ;
37- // The SCR's top 5 bits are reserved and zero, the strongest single check a header carries.
38- if ((flags & kScr ) && (h[len - 1 ] & 0xF8 )) return false ;
39- return !pts || !(flags & kPts ) || std::memcmp (h + 2 , pts, 4 ) == 0 ;
49+ return headerFlagsOk (flags) && headerScrOk (h, flags, len) && headerPtsOk (h, flags, pts);
4050}
4151
42- // / Whether headers of length `hl` really recur after `first`, which is what rules out a chance match.
52+ // / Whether headers of length `hl` recur after `first`, which is what rules out a chance match.
4353inline bool confirmedRun (const uint8_t * d, size_t len, size_t first, size_t hl) {
4454 const uint8_t * pts = (d[first + 1 ] & kPts ) ? d + first + 2 : nullptr ;
4555 const size_t stride = first + hl;
@@ -49,20 +59,15 @@ inline bool confirmedRun(const uint8_t* d, size_t len, size_t first, size_t hl)
4959 return seen > 0 || first + stride + hl > len; // a frame too short to confirm is taken as it is
5060}
5161
52- // / Drops the payload headers a bulk frame still carries, answering the compacted length.
53- inline size_t stripPayloadHeaders (uint8_t * d, size_t len) {
54- static constexpr size_t kLens [] = {12 , 8 , 6 , 2 }; // longest first: the more fields, the surer the match
55- size_t hdr = 0 , hl = 0 ;
56- for (size_t cand : kLens ) {
57- for (size_t i = kBulkMps - cand; i + cand <= len; i += kBulkMps ) {
58- if (!isPayloadHeader (d + i, len - i, cand, nullptr ) || !confirmedRun (d, len, i, cand)) continue ;
59- hdr = i;
60- hl = cand;
61- break ;
62- }
63- if (hdr) break ;
64- }
65- if (!hdr) return len;
62+ // / The offset of the first confirmed header of length `hl`, or 0 when the frame carries none.
63+ inline size_t findHeader (const uint8_t * d, size_t len, size_t hl) {
64+ for (size_t i = kBulkMps - hl; i + hl <= len; i += kBulkMps )
65+ if (isPayloadHeader (d + i, len - i, hl, nullptr ) && confirmedRun (d, len, i, hl)) return i;
66+ return 0 ;
67+ }
68+
69+ // / Close the gaps the headers from `hdr` on leave, answering the compacted length.
70+ inline size_t compactFrom (uint8_t * d, size_t len, size_t hdr, size_t hl) {
6671 const size_t payload = hdr + hl;
6772 uint8_t pts[4 ] = {}; // copied: the compaction overwrites the header it came from
6873 const bool hasPts = (d[hdr + 1 ] & kPts ) != 0 ;
@@ -79,6 +84,16 @@ inline size_t stripPayloadHeaders(uint8_t* d, size_t len) {
7984 return w + (len - r);
8085}
8186
87+ // / Drops the payload headers a bulk frame still carries, answering the compacted length.
88+ inline size_t stripPayloadHeaders (uint8_t * d, size_t len) {
89+ static constexpr size_t kLens [] = {12 , 8 , 6 , 2 }; // longest first: the more fields, the surer the match
90+ for (size_t hl : kLens ) {
91+ const size_t hdr = findHeader (d, len, hl);
92+ if (hdr) return compactFrom (d, len, hdr, hl);
93+ }
94+ return len;
95+ }
96+
8297// --- Choosing a mode ----------------------------------------------------------------------------
8398
8499// / UVC states a rate as a period in 100 ns ticks. Rounded, so 59.94 fps reads as 60 rather than 59.
@@ -96,16 +111,21 @@ inline uint8_t betterFps(uint8_t have, uint8_t row, uint8_t wanted) {
96111 return row < have ? row : have;
97112}
98113
114+ // / Whether a mode covers the ceiling and is no bigger to decode than the best so far.
115+ inline bool modeFits (const Mode& m, uint16_t width, uint16_t height, uint32_t area, uint32_t bestArea) {
116+ if (m.width < width || m.height < height) return false ; // below the ceiling it would be upscaled
117+ return !bestArea || area <= bestArea; // a bigger picture to decode every frame
118+ }
119+
99120// / The smallest mode at or above the ceiling, at the rate asked for, so decode and shrink stay cheap.
100121inline bool pickMode (const Mode* modes, size_t count, uint16_t & width, uint16_t & height, uint8_t & fps) {
101122 uint32_t bestArea = 0 ;
102123 uint16_t bw = 0 , bh = 0 ;
103124 uint8_t bestFps = 0 ;
104125 for (size_t i = 0 ; i < count; i++) {
105126 const Mode& m = modes[i];
106- if (m.width < width || m.height < height) continue ; // below the ceiling it would be upscaled
107127 const uint32_t area = static_cast <uint32_t >(m.width ) * m.height ;
108- if (bestArea && area > bestArea) continue ; // a bigger picture to decode every frame
128+ if (! modeFits (m, width, height, area, bestArea)) continue ;
109129 // The rates accumulate per resolution, not per area: two shapes can share an area.
110130 if (m.width != bw || m.height != bh) bestFps = 0 ;
111131 bestArea = area;
0 commit comments