Skip to content

Commit

Permalink
feature: added support for Q < 128 to RTP-JPEG
Browse files Browse the repository at this point in the history
For Q values less than 128, the luma and chroma
quantization tables are computed from the Q value.
  • Loading branch information
reijosirila committed Jul 24, 2019
1 parent 66a6a83 commit 00b609f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lib/components/jpegdepay/make-qtable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { clamp } from '../../utils/clamp'
/**
* @function makeQtable
* Creating a quantization table from a Q factor
* Example Code from RFC 2435 Appendix A ported to TypeScript
*
* Default luminance/chrominance quantization tables in RFC example are not in zig-zag order.
* The RFC does mention tables should be in zig-zag ordering, but they say that about the included tables.
* RFC sample code appears to have a mistake.
* All the tested cameras and LGPL projects use zig-zag default tables.
* So we use zig-zaged tables from ISO/IEC 10918-1 Annex K Section K.1
* @see https://tools.ietf.org/html/rfc2435
* @see https://www.iso.org/standard/18902.html
*/
// prettier-ignore
const jpegLumaQuantizer = [
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99,
]
// prettier-ignore
const jpeChromaQuantizer = [
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
]

export function makeQtable(Q: number): Buffer {
const factor = clamp(Q, 1, 99)
const buffer = Buffer.alloc(128)
const S = Q < 50 ? Math.floor(5000 / factor) : 200 - factor * 2

for (let i = 0; i < 64; i++) {
const lq = Math.floor((jpegLumaQuantizer[i] * S + 50) / 100)
const cq = Math.floor((jpeChromaQuantizer[i] * S + 50) / 100)
buffer.writeUInt8(clamp(lq, 1, 255), i)
buffer.writeUInt8(clamp(cq, 1, 255), i + 64)
}
return buffer
}
15 changes: 15 additions & 0 deletions lib/components/jpegdepay/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
makeFrameHeader,
} from './headers'
import { payload } from '../../utils/protocols/rtp'
import { makeQtable } from './make-qtable'

/**
* Each packet contains a special JPEG header which immediately follows
Expand Down Expand Up @@ -88,6 +89,20 @@ export function jpegDepayFactory(defaultWidth = 0, defaultHeight = 0) {
}
fragment = fragment.slice(4 + length)
}
// Compute Quantization Table
else if (Q < 128 && fragmentOffset === 0) {
const precision = 0
const qTable = makeQtable(Q)
metadata = {
typeSpecific,
type,
width,
height,
DRI,
precision,
qTable,
}
}

fragments.push(fragment)
}
Expand Down
3 changes: 3 additions & 0 deletions lib/utils/clamp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function clamp(val: number, min: number, max: number): number {
return val > max ? max : val < min ? min : val
}

0 comments on commit 00b609f

Please sign in to comment.