Files

266 lines
9.8 KiB
C

#include <stdio.h>
#include <string.h>
#define MARK_SOI 0xFFD8
#define MARK_APP0 0xFFE0
#define MARK_DQT 0xFFDB
#define MARK_SOF0 0xFFC0
#define MARK_DHT 0xFFC4
#define MARK_SOS 0xFFDA
#define MARK_DRI 0xFFDD
#define MARK_DOI 0xFFD9
#define SPLIT_DHT 1
/* 7205 7606, There are 3 quantitative tables (DQT0 DQT1 DQT2)
* 7203 7206, There are 2 quantitative tables (DQT0 DQT1) */
#define REMOVE_DQT2 0
#define REMOVE_DRI 1
/*
* Delete DRI field in JPEG, delete quantization table 2 (DQT2), split Huffman table.
*/
void memcpy_jpeg_user(unsigned char* src_buffer, unsigned int src_len,
unsigned char* dest_buffer, unsigned int dest_length, unsigned int* dest_offset)
{
unsigned int mark, sec_len;
unsigned int copy_size;
unsigned int src_off = 0;
unsigned int dst_len = dest_length;
unsigned int dst_off = *dest_offset;
unsigned char* src_buf = src_buffer;
unsigned char* dst_buf = (dest_buffer + dst_off);
while ((src_len - src_off) > 0) {
mark = ((src_buf[0] << 8) | src_buf[1]);
sec_len = ((src_buf[2] << 8) | src_buf[3]);
switch (mark) {
case MARK_SOI:
//printf("MARK_SOI\n");
/* copy SOI */
copy_size = 2;
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += 2;
src_off += 2;
dst_buf += copy_size;
dst_off += copy_size;
break;
case MARK_APP0:
/* copy APP0 */
//printf("MARK_APP0\n");
copy_size = (2 + sec_len);
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
break;
case MARK_DQT:
//printf("MARK_DQT\n");
copy_size = (2 + sec_len);
#if REMOVE_DQT2
/* Delete the third quantification table */
/* After JPEG encoding on the Xmdeia platform, there are 3 quantization tables,
* while some decoding platforms only support 2 quantization tables.*/
if ((dst_len - dst_off) > copy_size) {
/* copy DQT0 and refactoring DQT */
dst_buf[0] = 0xFF;
dst_buf[1] = 0xDB;
dst_buf[2] = 0x00;
dst_buf[3] = 0x43;
dst_buf[4] = 0x00; /* DQT0 */
dst_buf += 5;
dst_off += 5;
src_buf += 5;
memcpy(dst_buf, src_buf, 0x40); /* 0x40: DQT0 size */
dst_buf += 0x40;
dst_off += 0x40;
src_buf += 0x40;
/* copy DQT1 and refactoring DQT*/
dst_buf[0] = 0xFF;
dst_buf[1] = 0xDB;
dst_buf[2] = 0x00;
dst_buf[3] = 0x43;
dst_buf[4] = 0x01; /* DQT1 */
dst_buf += 5;
dst_off += 5;
src_buf += 1;
memcpy(dst_buf, src_buf, 0x40); /* 0x40: DQT1 size */
dst_buf += 0x40;
dst_off += 0x40;
src_buf += 0x40;
#if 0
/* remove DQT2 */
src_buf += 0x41;
src_off += (2 + sec_len);
#endif
} else {
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
}
#else
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
#endif
break;
case MARK_SOF0:
//printf("MARK_SOF0\n");
copy_size = (2 + sec_len);
#if 0
/* copy SOF0 and refactoring DQT */
if ((dst_len - dst_off) > copy_size) {
memcpy(dst_buf, src_buf, copy_size);
dst_buf[copy_size - 1] = 0x01; /* refactoring DQT info */
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
} else {
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
}
#else
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
#endif
break;
case MARK_DHT:
/* copy DHT*/
//printf("MARK_DHT\n");
copy_size = (2 + sec_len);
#if SPLIT_DHT
/* Split Huffman table */
/* The Huffman table encoded by JPEG on the XMedia platform consists of four sets in a single DHT.
* Some decoding platforms do not support this and need to split it into four sets */
if ((dst_len - dst_off) > copy_size) {
/* copy DHT0 */
dst_buf[0] = 0xFF;
dst_buf[1] = 0xC4;
dst_buf[2] = 0x00;
dst_buf[3] = 0x1F;
dst_buf += 4;
dst_off += 4;
src_buf += 4;
copy_size = 0x1F - 2;
memcpy(dst_buf, src_buf, copy_size);
dst_buf += copy_size;
dst_off += copy_size;
src_buf += copy_size;
/* copy DHT1 */
dst_buf[0] = 0xFF;
dst_buf[1] = 0xC4;
dst_buf[2] = 0x00;
dst_buf[3] = 0xB5;
dst_buf += 4;
dst_off += 4;
copy_size = 0xB5 - 2;
memcpy(dst_buf, src_buf, copy_size);
dst_buf += copy_size;
dst_off += copy_size;
src_buf += copy_size;
/* copy DHT2 */
dst_buf[0] = 0xFF;
dst_buf[1] = 0xC4;
dst_buf[2] = 0x00;
dst_buf[3] = 0x1F;
dst_buf += 4;
dst_off += 4;
copy_size = 0x1F - 2;
memcpy(dst_buf, src_buf, copy_size);
dst_buf += copy_size;
dst_off += copy_size;
src_buf += copy_size;
/* copy DHT3 */
dst_buf[0] = 0xFF;
dst_buf[1] = 0xC4;
dst_buf[2] = 0x00;
dst_buf[3] = 0xB5;
dst_buf += 4;
dst_off += 4;
copy_size = 0xB5 - 2;
memcpy(dst_buf, src_buf, copy_size);
dst_buf += copy_size;
dst_off += copy_size;
src_buf += copy_size;
src_off += (2 + sec_len);
} else {
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
}
#else
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
#endif
break;
case MARK_DRI:
//printf("MARK_DRI\n");
copy_size = (2 + sec_len);
#if REMOVE_DRI
/* remove DRI */
src_buf += copy_size;
src_off += copy_size;
#else
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
src_buf += (2 + sec_len);
src_off += (2 + sec_len);
dst_buf += copy_size;
dst_off += copy_size;
#endif
break;
case MARK_SOS:
/* copy SOS */
//printf("MARK_SOS\n");
case MARK_DOI:
/* copy DOI */
default:
/* copy data */
copy_size = src_len - src_off;
copy_size = ((dst_len - dst_off) > copy_size) ? copy_size : (dst_len - dst_off);
memcpy(dst_buf, src_buf, copy_size);
dst_off += copy_size;
*dest_offset = dst_off;
return;
}
}
*dest_offset = dst_off;
}