diff --git a/src/encoders/hw/encoder.c b/src/encoders/hw/encoder.c index e63ecea..e5f0660 100644 --- a/src/encoders/hw/encoder.c +++ b/src/encoders/hw/encoder.c @@ -2,6 +2,11 @@ # # # uStreamer - Lightweight and fast MJPG-HTTP streamer. # # # +# This source file based on code of MJPG-Streamer. # +# # +# Copyright (C) 2005-2006 Laurent Pinchart & Michel Xhaard # +# Copyright (C) 2006 Gabriel A. Devenyi # +# Copyright (C) 2007 Tom Stöveken # # Copyright (C) 2018 Maxim Devaev # # # # This program is free software: you can redistribute it and/or modify # @@ -20,6 +25,7 @@ *****************************************************************************/ +#include #include #include @@ -30,6 +36,13 @@ #include "../../xioctl.h" #include "../../device.h" +#include "huffman.h" +#include "encoder.h" + + +static bool _is_huffman(const unsigned char *data); +static size_t _memcpy_with_huffman(unsigned char *dest, const unsigned char *src, size_t size); + int hw_encoder_prepare_live(struct device_t *dev, unsigned quality) { struct v4l2_jpegcompression comp; @@ -52,7 +65,53 @@ void hw_encoder_compress_buffer(struct device_t *dev, unsigned index) { if (dev->run->format != V4L2_PIX_FMT_MJPEG && dev->run->format != V4L2_PIX_FMT_JPEG) { assert(0 && "Unsupported input format for HW JPEG encoder"); } - assert(dev->run->pictures[index].allocated >= dev->run->hw_buffers[index].length); - memcpy(dev->run->pictures[index].data, dev->run->hw_buffers[index].start, dev->run->hw_buffers[index].length); - dev->run->pictures[index].size = dev->run->hw_buffers[index].length; + +# define PICTURE(_next) dev->run->pictures[index]._next +# define HW_BUFFER(_next) dev->run->hw_buffers[index]._next + + assert(PICTURE(allocated) >= HW_BUFFER(length) + sizeof(HUFFMAN_TABLE)); + PICTURE(size) = _memcpy_with_huffman(PICTURE(data), HW_BUFFER(start), HW_BUFFER(length)); + +# undef HW_BUFFER +# undef PICTURE +} + + +static bool _is_huffman(const unsigned char *data) { + unsigned count = 0; + + while (((data[0] << 8) | data[1]) != 0xFFDA) { + if (count++ > 2048) { + return false; + } + if (((data[0] << 8) | data[1]) == 0xFFC4) { + return true; + } + data += 1; + } + return false; +} + +static size_t _memcpy_with_huffman(unsigned char *dest, const unsigned char *src, size_t size) { + if (!_is_huffman(src)) { + const unsigned char *src_ptr = src; + const unsigned char *src_end = src + size; + size_t paste; + + while ((((src_ptr[0] << 8) | src_ptr[1]) != 0xFFC0) && (src_ptr < src_end)) { + src_ptr += 1; + } + if (src_ptr >= src_end) { + return 0; + } + paste = src_ptr - src; + + memcpy(dest, src, paste); + memcpy(dest + paste, HUFFMAN_TABLE, sizeof(HUFFMAN_TABLE)); + memcpy(dest + paste + sizeof(HUFFMAN_TABLE), src_ptr, size - paste); + return (size + sizeof(HUFFMAN_TABLE)); + } else { + memcpy(dest, src, size); + return size; + } } diff --git a/src/encoders/hw/huffman.h b/src/encoders/hw/huffman.h new file mode 100644 index 0000000..1cef0cb --- /dev/null +++ b/src/encoders/hw/huffman.h @@ -0,0 +1,66 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# This source file based on code of MJPG-Streamer. # +# # +# Copyright (C) 2005-2006 Laurent Pinchart & Michel Xhaard # +# Copyright (C) 2006 Gabriel A. Devenyi # +# Copyright (C) 2007 Tom Stöveken # +# Copyright (C) 2018 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#pragma once + +static const unsigned char HUFFMAN_TABLE[] = { + 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, + 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, + 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, + 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, + 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, + 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, + 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, + 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, + 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, + 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, + 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, + 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, + 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, + 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, + 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, +};