diff --git a/codec/mjpeg/jpeg.go b/codec/mjpeg/jpeg.go index 85aef03c..7ad82398 100644 --- a/codec/mjpeg/jpeg.go +++ b/codec/mjpeg/jpeg.go @@ -94,6 +94,14 @@ var ( ErrNoFrameStart = errors.New("missing start of frame") ) +// n values required for huffman table generation. +var ( + nDCLum = deriveN(bitsDCLum) + nDCChr = deriveN(bitsDCChr) + nACLum = deriveN(bitsACLum) + nACChr = deriveN(bitsACChr) +) + // Slices used in the creation of huffman tables. var ( bitsDCLum = []byte{0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} @@ -291,7 +299,7 @@ func (c *Context) ParsePayload(p []byte, m bool) error { return nil } -// writeHeader writes a JPEG header to the writer w. +// writeHeader writes a JPEG header to the writer slice p. func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable []byte) int { width <<= 3 height <<= 3 @@ -305,8 +313,7 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable binary.BigEndian.PutUint16(p[idx+4:], jfifHeadLen) idx += 6 - copy(p[idx:], jfifLabel) - idx += len(jfifLabel) + idx += copy(p[idx:], jfifLabel) binary.BigEndian.PutUint16(p[idx:], jfifVer) p[idx+2] = jfifDensityUnit @@ -336,7 +343,7 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable p[idx] = byte(i) idx++ - copy(p[idx:], qtable[64*i:(64*i)+64]) + idx += copy(p[idx:], qtable[64*i:(64*i)+64]) } // Define huffman table. @@ -345,10 +352,10 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable lenIdx := idx binary.BigEndian.PutUint16(p[idx:], 0) idx += 2 - idx += writeHuffman(p[idx:], 0, 0, bitsDCLum, valDC) - idx += writeHuffman(p[idx:], 0, 1, bitsDCChr, valDC) - idx += writeHuffman(p[idx:], 1, 0, bitsACLum, valACLum) - idx += writeHuffman(p[idx:], 1, 1, bitsACChr, valACChr) + idx += writeHuffman(p[idx:], bitsDCLum, valDC, 0, nDCLum) + idx += writeHuffman(p[idx:], bitsDCChr, valDC, 1, nDCChr) + idx += writeHuffman(p[idx:], bitsACLum, valACLum, 1<<4, nACLum) + idx += writeHuffman(p[idx:], bitsACChr, valACChr, 1<<4|1, nACChr) binary.BigEndian.PutUint16(p[lenIdx:], uint16(idx-lenIdx)) // Start of frame. @@ -389,21 +396,11 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable return idx } -// writeHuffman write a JPEG huffman table to w. -func writeHuffman(p []byte, class, id int, bits, values []byte) int { - idx := 0 - p[idx] = uint8(class<<4 | id) - idx++ - - var n int - for i := 1; i <= 16; i++ { - n += int(bits[i]) - } - - idx += copy(p[idx:], bits[1:17]) - idx += copy(p[idx:], values[0:n]) - - return idx +// writeHuffman write a JPEG huffman table to alice p. +func writeHuffman(p, bits, values []byte, prefix byte, n int) int { + p[0] = prefix + i := copy(p[1:], bits[1:17]) + return copy(p[i+1:], values[0:n]) + i + 1 } // defaultQTable returns a default quantization table. @@ -443,3 +440,12 @@ func clip(v, min, max int) int { func get24(p []byte) int { return int(p[0]<<16) | int(p[1]<<8) | int(p[2]) } + +// deriveN calculates n values required for huffman table generation. +func deriveN(bits []byte) int { + var n int + for i := 1; i <= 16; i++ { + n += int(bits[i]) + } + return n +}