int compare_files(state *s, char *fn1, char *fn2) { FILE *h1, *h2; int status; if ((h1 = fopen(fn1,"rb")) == NULL) { perror(fn1); return TRUE; } if ((h2 = fopen(fn2,"rb")) == NULL) { perror(fn2); fclose(h1); return TRUE; } if (find_file_size(fn1,h1,&s->size1)) return TRUE; if (find_file_size(fn2,h2,&s->size2)) return TRUE; if (s->size1 != s->size2) print_error ("%s: files are not the same size", __progname); status = compare_blocks(s,h1,h2); fclose(h1); fclose(h2); return status; }
/* * encode_main * * Main encoding loop. */ static void encode_main(MimCtx *ctx, guchar *out_buf, gboolean is_pframe) { gint x, y, i, offset, chrom_ch; gint dct_block[64]; guchar *src, *dst, *p1, *p2; gdouble match; gboolean encoded; /* * Round down small differences in luminance channel. */ if (is_pframe) { p1 = ctx->cur_frame_buf; p2 = ctx->prev_frame_buf; for (i = 0; i < ctx->y_size; i++) { if (abs(p2[0] - p1[0]) < 7) p1[0] = p2[0]; p1++; p2++; } } /* * Encode Y plane. */ for (y = 0; y < ctx->num_vblocks_y; y++) { for (x = 0; x < ctx->num_hblocks_y; x++) { /* Calculate final offset into buffer. */ offset = (ctx->y_stride * 8 * y) + (x * 8); src = NULL; encoded = FALSE; if (is_pframe) { /* Is the current block similar enough to what it was in the previous frame? */ match = compare_blocks(ctx->cur_frame_buf + offset, ctx->prev_frame_buf + offset, ctx->y_stride, 8, FALSE); if (match > LUMINANCE_THRESHOLD) { /* Yes: write out '1' to indicate a no-change condition. */ _write_bits(ctx, 1, 1); src = ctx->prev_frame_buf + offset; encoded = TRUE; } else { /* No: Is the current block similar enough to what it was in one * of the (up to) 15 last frames preceding the previous? */ gint best_index = 0; gdouble best_match = 0.0; gint num_backrefs = ctx->frame_num - 1; if (num_backrefs > 15) num_backrefs = 15; for (i = 1; i <= num_backrefs; i++) { match = compare_blocks(ctx->buf_ptrs[(ctx->ptr_index + i) % 16] + offset, ctx->cur_frame_buf + offset, ctx->y_stride, 8, FALSE); if (match > LUMINANCE_THRESHOLD && match > best_match) { best_index = i; best_match = match; } } if (best_index != 0) { /* Yes: write out '01' to indicate a "change but like previous"-condition, * followed by 4 bits containing the back-reference. */ _write_bits(ctx, 0, 1); _write_bits(ctx, 1, 1); _write_bits(ctx, best_index, 4); src = ctx->buf_ptrs[(ctx->ptr_index + best_index) % 16] + offset; encoded = TRUE; } } } if (!encoded) { /* Keyframe or in any case no? ;-) Well, encode it then. */ if (is_pframe) { _write_bits(ctx, 0, 1); _write_bits(ctx, 0, 1); } _fdct_quant_block(ctx, dct_block, ctx->cur_frame_buf + offset, ctx->y_stride, FALSE, ctx->num_coeffs); _vlc_encode_block(ctx, dct_block, ctx->num_coeffs); } /* And if there was some kind of no-change condition, * we want to copy the previous block. */ if (src != NULL) { dst = ctx->cur_frame_buf + offset; for (i = 0; i < 8; i++) { memcpy(dst, src, 8); src += ctx->y_stride; dst += ctx->y_stride; } } } } /* * Encode Cr and Cb planes. */ for (chrom_ch = 0; chrom_ch < 2; chrom_ch++) { /* Calculate base offset into buffer. */ gint base_offset = ctx->y_size + (ctx->crcb_size * chrom_ch); for (y = 0; y < ctx->num_vblocks_cbcr; y++) { guchar tmp_block[64]; guint num_rows = 8; /* The last row of blocks in chrominance for 160x120 resolution * is half the normal height and must be accounted for. */ if (y + 1 == ctx->num_vblocks_cbcr && ctx->frame_height % 16 != 0) num_rows = 4; for (x = 0; x < ctx->num_hblocks_cbcr; x++) { /* Calculate final offset into buffer. */ offset = base_offset + (ctx->crcb_stride * 8 * y) + (x * 8); src = NULL; encoded = FALSE; if (is_pframe) { /* Is the current block similar enough to what it was in the previous frame? */ match = compare_blocks(ctx->prev_frame_buf + offset, ctx->cur_frame_buf + offset, ctx->crcb_stride, num_rows, TRUE); if (match > CHROMINANCE_THRESHOLD) { /* Yes: write out '0' to indicate a no-change condition. */ _write_bits(ctx, 0, 1); encoded = TRUE; src = ctx->prev_frame_buf + offset; dst = ctx->cur_frame_buf + offset; for (i = 0; i < num_rows; i++) { memcpy(dst, src, 8); src += ctx->crcb_stride; dst += ctx->crcb_stride; } } } if (!encoded) { /* Keyframe or just not similar enough? ;-) Well, encode it then. */ if (is_pframe) _write_bits(ctx, 1, 1); /* Use a temporary array to handle cases where the * current block is not of normal height (see above). */ src = ctx->cur_frame_buf + offset; dst = tmp_block; for (i = 0; i < 8; i++) { memcpy(dst, src, 8); if (i < (num_rows - 1)) src += ctx->crcb_stride; dst += 8; } _fdct_quant_block(ctx, dct_block, tmp_block, 8, TRUE, ctx->num_coeffs); _vlc_encode_block(ctx, dct_block, ctx->num_coeffs); } } } } /* * Make a copy of the current frame and store in * the circular pointer list of 16 entries. */ ctx->prev_frame_buf = ctx->buf_ptrs[ctx->ptr_index]; memcpy(ctx->prev_frame_buf, ctx->cur_frame_buf, ctx->y_size + (ctx->crcb_size * 2)); if (--ctx->ptr_index < 0) ctx->ptr_index = 15; }