📄 libmjpeg.c
字号:
uint8_t * cpy_rows[3]; // Copy to buffer first cpy_rows[0] = mjpeg->temp_rows[0][0]; cpy_rows[1] = mjpeg->temp_rows[1][0]; cpy_rows[2] = mjpeg->temp_rows[2][0]; lqt_rows_copy(row_pointers, cpy_rows, mjpeg->output_w, mjpeg->output_h, mjpeg->coded_w, mjpeg->coded_w_uv, mjpeg->rowspan, mjpeg->rowspan_uv, mjpeg->jpeg_color_model); }void mjpeg_set_quality(mjpeg_t *mjpeg, int quality) { mjpeg->quality = quality; }void mjpeg_set_float(mjpeg_t *mjpeg, int use_float) { mjpeg->use_float = use_float; }void mjpeg_set_rowspan(mjpeg_t *mjpeg, int rowspan, int rowspan_uv) { mjpeg->rowspan = rowspan; mjpeg->rowspan_uv = rowspan_uv; }int mjpeg_get_fields(mjpeg_t *mjpeg) { return mjpeg->fields; }mjpeg_t* mjpeg_new(int w, int h, int fields) { mjpeg_t *result = calloc(1, sizeof(*result)); result->output_w = w; result->output_h = h; result->fields = fields; result->quality = 80; result->use_float = 0; // Calculate coded dimensions result->coded_w = (w % 16) ? w + (16 - (w % 16)) : w; result->coded_w_uv = result->coded_w / 2; result->coded_h = (h % 16) ? h + (16 - (h % 16)) : h; return result; }void mjpeg_delete(mjpeg_t *mjpeg) { if(mjpeg->compressor) mjpeg_delete_compressor(mjpeg->compressor); if(mjpeg->decompressor) mjpeg_delete_decompressor(mjpeg->decompressor); delete_temps(mjpeg); delete_buffer(&mjpeg->output_data, &mjpeg->output_size, &mjpeg->output_allocated); free(mjpeg); }/* Open up a space to insert a marker */static void insert_space(unsigned char **buffer, long *buffer_size, long *buffer_allocated, long space_start, long space_len) { int in, out; // Make sure enough space is available if(*buffer_allocated - *buffer_size < space_len) { *buffer_allocated += space_len; *buffer = realloc(*buffer, *buffer_allocated); } // Shift data back for(in = *buffer_size - 1, out = *buffer_size - 1 + space_len; in >= space_start; in--, out--) { (*buffer)[out] = (*buffer)[in]; } *buffer_size += space_len; }static inline int nextbyte(unsigned char *data, long *offset, long length) { if(length - *offset < 1) return 0; *offset += 1; return (unsigned char)data[*offset - 1]; }static inline int next_int32(unsigned char *data, long *offset, long length) { if(length - *offset < 4) { *offset = length; return 0; } *offset += 4; return ((((unsigned int)data[*offset - 4]) << 24) | (((unsigned int)data[*offset - 3]) << 16) | (((unsigned int)data[*offset - 2]) << 8) | (((unsigned int)data[*offset - 1]))); }static inline int read_int16(unsigned char *data, long *offset, long length) { if(length - *offset < 2) { *offset = length; return 0; } *offset += 2; return ((((unsigned int)data[*offset - 2]) << 8) | (((unsigned int)data[*offset - 1]))); }static inline intnext_int16(unsigned char *data, long *offset, long length) { if(length - *offset < 2) { return 0; } return ((((unsigned int)data[*offset]) << 8) | (((unsigned int)data[*offset + 1]))); }static inline voidwrite_int32(unsigned char *data, long *offset, long length, unsigned int value) { if(length - *offset < 4) { *offset = length; return; } data[(*offset)++] = (unsigned int)(value & 0xff000000) >> 24; data[(*offset)++] = (unsigned int)(value & 0xff0000) >> 16; data[(*offset)++] = (unsigned int)(value & 0xff00) >> 8; data[(*offset)++] = (unsigned char)(value & 0xff); return; }static int next_marker(unsigned char *buffer, long *offset, long buffer_size) { while(*offset < buffer_size - 1) { if(buffer[*offset] == 0xff && buffer[*offset + 1] != 0xff) { (*offset) += 2; return buffer[*offset - 1]; } (*offset)++; } return 0; }/* Find the next marker after offset and return 0 on success */static int find_marker(unsigned char *buffer, long *offset, long buffer_size, unsigned long marker_type) { long result = 0; while(!result && *offset < buffer_size) { int marker = next_marker(buffer, offset, buffer_size); if(marker == (marker_type & 0xff)) result = 1; } return !result; }typedef struct { int field_size; int padded_field_size; int next_offset; int quant_offset; int huffman_offset; int image_offset; int scan_offset; int data_offset; } mjpeg_qt_hdr;#if 0#define LML_MARKER_SIZE 0x2c#define LML_MARKER_TAG 0xffe3static void insert_lml33_markers(unsigned char **buffer, long *field2_offset, long *buffer_size, long *buffer_allocated) { long marker_offset = -1; /* Search for existing marker to replace */ // marker_offset = find_marker(*buffer, *buffer_size, LML_MARKER_TAG); /* Insert new marker */ if(marker_offset < 0) { marker_offset = 2; insert_space(buffer, buffer_size, buffer_allocated, 2, LML_MARKER_SIZE); } }#endifstatic void table_offsets(unsigned char *buffer, long buffer_size, mjpeg_qt_hdr *header) { int done = 0; long offset = 0; int marker = 0; int field = 0; int len; bzero(header, sizeof(mjpeg_qt_hdr) * 2); // Read every marker to get the offsets for the headers for(field = 0; field < 2; field++) { done = 0; while(!done) { marker = next_marker(buffer, &offset, buffer_size); len = 0; switch(marker) { case M_SOI: // The first field may be padded if(field > 0) { header[0].next_offset = header[0].padded_field_size = offset - 2; } len = 0; break; case M_DQT: if(!header[field].quant_offset) { header[field].quant_offset = offset - 2; if(field > 0) header[field].quant_offset -= header[0].next_offset; } len = read_int16(buffer, &offset, buffer_size); len -= 2; break; case M_DHT: if(!header[field].huffman_offset) { header[field].huffman_offset = offset - 2; if(field > 0) header[field].huffman_offset -= header[0].next_offset; } len = read_int16(buffer, &offset, buffer_size); len -= 2; break; case M_SOF0: if(!header[field].image_offset) { header[field].image_offset = offset - 2; if(field > 0) header[field].image_offset -= header[0].next_offset; } len = read_int16(buffer, &offset, buffer_size); len -= 2; break; case M_SOS: header[field].scan_offset = offset - 2; if(field > 0) header[field].scan_offset -= header[0].next_offset; len = read_int16(buffer, &offset, buffer_size); len -= 2; header[field].data_offset = offset + len; if(field > 0) header[field].data_offset -= header[0].next_offset; break; // case 0: case M_EOI: if(field > 0) { header[field].field_size = header[field].padded_field_size = offset - header[0].next_offset; header[field].next_offset = 0; } else { // Often misses second SOI but gets first EOI // header[0].next_offset = // header[0].padded_field_size = // offset; } done = 1; len = 0; break; default: // Junk appears between fields len = 0; // len = read_int16(buffer, &offset, buffer_size); // len -= 2; break; } if(!done) offset += len; } } }static void insert_quicktime_marker(unsigned char *buffer, long buffer_size, long offset, mjpeg_qt_hdr *header) { write_int32(buffer, &offset, buffer_size, 0xff000000 | ((unsigned long)M_APP1 << 16) | (QUICKTIME_MARKER_SIZE - 2)); write_int32(buffer, &offset, buffer_size, 0); write_int32(buffer, &offset, buffer_size, QUICKTIME_JPEG_TAG); write_int32(buffer, &offset, buffer_size, header->field_size); write_int32(buffer, &offset, buffer_size, header->padded_field_size); write_int32(buffer, &offset, buffer_size, header->next_offset); write_int32(buffer, &offset, buffer_size, header->quant_offset); write_int32(buffer, &offset, buffer_size, header->huffman_offset); write_int32(buffer, &offset, buffer_size, header->image_offset); write_int32(buffer, &offset, buffer_size, header->scan_offset); write_int32(buffer, &offset, buffer_size, header->data_offset); }void mjpeg_insert_quicktime_markers(unsigned char **buffer, long *buffer_size, long *buffer_allocated, int fields, long *field2_offset) { mjpeg_qt_hdr header[2]; if(fields < 2) return; // Get offsets for tables in both fields table_offsets(*buffer, *buffer_size, header); header[0].field_size += QUICKTIME_MARKER_SIZE; header[0].padded_field_size += QUICKTIME_MARKER_SIZE; header[0].next_offset += QUICKTIME_MARKER_SIZE; header[0].quant_offset += QUICKTIME_MARKER_SIZE; header[0].huffman_offset += QUICKTIME_MARKER_SIZE; header[0].image_offset += QUICKTIME_MARKER_SIZE; header[0].scan_offset += QUICKTIME_MARKER_SIZE; header[0].data_offset += QUICKTIME_MARKER_SIZE; header[1].field_size += QUICKTIME_MARKER_SIZE; header[1].padded_field_size += QUICKTIME_MARKER_SIZE; header[1].quant_offset += QUICKTIME_MARKER_SIZE; header[1].huffman_offset += QUICKTIME_MARKER_SIZE; header[1].image_offset += QUICKTIME_MARKER_SIZE; header[1].scan_offset += QUICKTIME_MARKER_SIZE; header[1].data_offset += QUICKTIME_MARKER_SIZE; *field2_offset = header[0].next_offset; // Insert APP1 marker insert_space(buffer, buffer_size, buffer_allocated, 2, QUICKTIME_MARKER_SIZE); insert_quicktime_marker(*buffer, *buffer_size, 2, &header[0]); insert_space(buffer, buffer_size, buffer_allocated, header[0].next_offset + 2, QUICKTIME_MARKER_SIZE); header[1].next_offset = 0; insert_quicktime_marker(*buffer, *buffer_size, header[0].next_offset + 2, &header[1]); }static void read_quicktime_markers(unsigned char *buffer, long buffer_size, mjpeg_qt_hdr *header) { long offset = 0; int marker_count = 0; int result = 0; while(marker_count < 2 && offset < buffer_size && !result) { result = find_marker(buffer, &offset, buffer_size, M_APP1); if(!result) { // Marker size read_int16(buffer, &offset, buffer_size); // Zero next_int32(buffer, &offset, buffer_size); // MJPA next_int32(buffer, &offset, buffer_size); // Information header[marker_count].field_size = next_int32(buffer, &offset, buffer_size); header[marker_count].padded_field_size = next_int32(buffer, &offset, buffer_size); header[marker_count].next_offset = next_int32(buffer, &offset, buffer_size); header[marker_count].quant_offset = next_int32(buffer, &offset, buffer_size); header[marker_count].huffman_offset = next_int32(buffer, &offset, buffer_size); header[marker_count].image_offset = next_int32(buffer, &offset, buffer_size); header[marker_count].scan_offset = next_int32(buffer, &offset, buffer_size); header[marker_count].data_offset = next_int32(buffer, &offset, buffer_size); marker_count++; } } }long mjpeg_get_quicktime_field2(unsigned char *buffer, long buffer_size) { mjpeg_qt_hdr header[2]; bzero(&header, sizeof(mjpeg_qt_hdr) * 2); read_quicktime_markers(buffer, buffer_size, header); return header[0].next_offset; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -