From cf33ccd1604b485dc23921911027676eee20216c Mon Sep 17 00:00:00 2001 From: Vikas Arora Date: Fri, 27 Apr 2012 08:04:57 +0000 Subject: [PATCH] Evaluate output cluster's bit_costs once in HistogramRefine. Avoid bit_costs evaluated every time in function HistogramDistance. Also moved VP8LInitBackwardRefs and VP8LClearBackwardRefs to backward_references.h Change-Id: Id507f164d0fc64480aebc4a3ea3e6950ed377a60 --- src/enc/backward_references.h | 15 +++++++++ src/enc/histogram.c | 63 ++++++++++++++++++++--------------- src/enc/vp8l.c | 14 -------- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/enc/backward_references.h b/src/enc/backward_references.h index d5e1de8b..2ba55d15 100644 --- a/src/enc/backward_references.h +++ b/src/enc/backward_references.h @@ -15,6 +15,7 @@ #include #include +#include #include "../webp/types.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -172,6 +173,20 @@ static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { return p->argb_or_distance; } +static WEBP_INLINE void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) { + if (refs != NULL) { + refs->refs = NULL; + refs->size = 0; + } +} + +static WEBP_INLINE void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) { + if (refs != NULL) { + free(refs->refs); + VP8LInitBackwardRefs(refs); + } +} + // Ridiculously simple backward references for images where it is unlikely // that there are large backward references (photos). void VP8LBackwardReferencesRle( diff --git a/src/enc/histogram.c b/src/enc/histogram.c index ba232fb2..0a4aa314 100644 --- a/src/enc/histogram.c +++ b/src/enc/histogram.c @@ -197,8 +197,7 @@ double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p) { static int HistogramBuildImage(int xsize, int ysize, int histobits, int palettebits, - const PixOrCopy* const backward_refs, - int backward_refs_size, + const VP8LBackwardRefs* const backward_refs, VP8LHistogram*** const image_arg, int* const image_size) { int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1; @@ -226,8 +225,8 @@ static int HistogramBuildImage(int xsize, int ysize, VP8LHistogramInit(image[i], palettebits); } // x and y trace the position in the image. - for (i = 0; i < backward_refs_size; ++i) { - const PixOrCopy v = backward_refs[i]; + for (i = 0; i < backward_refs->size; ++i) { + const PixOrCopy v = backward_refs->refs[i]; const int ix = histobits ? (y >> histobits) * histo_xsize + (x >> histobits) : 0; VP8LHistogramAddSinglePixOrCopy(image[ix], v); @@ -338,47 +337,54 @@ Error: // What is the bit cost of moving square_histogram from // cur_symbol to candidate_symbol. static double HistogramDistance(const VP8LHistogram* const square_histogram, - int cur_symbol, - int candidate_symbol, + int cur_symbol, int candidate_symbol, + const double* const symbol_bit_costs, VP8LHistogram** const candidate_histograms) { double new_bit_cost; double previous_bit_cost; - VP8LHistogram modified; + VP8LHistogram modified_histo; if (cur_symbol == candidate_symbol) { return 0; // Going nowhere. No savings. } - previous_bit_cost = - VP8LHistogramEstimateBits(candidate_histograms[candidate_symbol]); + previous_bit_cost = symbol_bit_costs[candidate_symbol]; if (cur_symbol != -1) { - previous_bit_cost += - VP8LHistogramEstimateBits(candidate_histograms[cur_symbol]); + previous_bit_cost += symbol_bit_costs[cur_symbol]; } // Compute the bit cost of the histogram where the data moves to. - modified = *candidate_histograms[candidate_symbol]; - VP8LHistogramAdd(&modified, square_histogram); - new_bit_cost = VP8LHistogramEstimateBits(&modified); + modified_histo = *candidate_histograms[candidate_symbol]; + VP8LHistogramAdd(&modified_histo, square_histogram); + new_bit_cost = VP8LHistogramEstimateBits(&modified_histo); // Compute the bit cost of the histogram where the data moves away. if (cur_symbol != -1) { - modified = *candidate_histograms[cur_symbol]; - VP8LHistogramRemove(&modified, square_histogram); - new_bit_cost += VP8LHistogramEstimateBits(&modified); + modified_histo = *candidate_histograms[cur_symbol]; + VP8LHistogramRemove(&modified_histo, square_histogram); + new_bit_cost += VP8LHistogramEstimateBits(&modified_histo); } return new_bit_cost - previous_bit_cost; } -static void HistogramRefine(VP8LHistogram** const raw, int raw_size, - uint32_t* const symbols, int out_size, - VP8LHistogram** const out) { +static int HistogramRefine(VP8LHistogram** const raw, int raw_size, + uint32_t* const symbols, + VP8LHistogram** const out, int out_size) { int i; + double* const symbol_bit_costs = + (double*)malloc(out_size * sizeof(*symbol_bit_costs)); + if (symbol_bit_costs == NULL) return 0; + for (i = 0; i < out_size; ++i) { + symbol_bit_costs[i] = VP8LHistogramEstimateBits(out[i]); + } + // Find the best 'out' histogram for each of the raw histograms for (i = 0; i < raw_size; ++i) { int best_out = 0; - double best_bits = HistogramDistance(raw[i], symbols[i], 0, out); + double best_bits = HistogramDistance(raw[i], symbols[i], 0, + symbol_bit_costs, out); int k; for (k = 1; k < out_size; ++k) { - double cur_bits = HistogramDistance(raw[i], symbols[i], k, out); + double cur_bits = HistogramDistance(raw[i], symbols[i], k, + symbol_bit_costs, out); if (cur_bits < best_bits) { best_bits = cur_bits; best_out = k; @@ -386,6 +392,7 @@ static void HistogramRefine(VP8LHistogram** const raw, int raw_size, } symbols[i] = best_out; } + free(out_bit_costs); // Recompute each out based on raw and symbols. for (i = 0; i < out_size; ++i) { @@ -394,6 +401,8 @@ static void HistogramRefine(VP8LHistogram** const raw, int raw_size, for (i = 0; i < raw_size; ++i) { VP8LHistogramAdd(out[symbols[i]], raw[i]); } + + return 1; } int VP8LGetHistImageSymbols(int xsize, int ysize, @@ -410,8 +419,7 @@ int VP8LGetHistImageSymbols(int xsize, int ysize, VP8LHistogram** histogram_image_raw = NULL; *histogram_image = NULL; - if (!HistogramBuildImage(xsize, ysize, histogram_bits, cache_bits, - refs->refs, refs->size, + if (!HistogramBuildImage(xsize, ysize, histogram_bits, cache_bits, refs, &histogram_image_raw, &histogram_image_raw_size)) { goto Error; @@ -425,8 +433,11 @@ int VP8LGetHistImageSymbols(int xsize, int ysize, for (i = 0; i < histogram_image_raw_size; ++i) { histogram_symbols[i] = -1; } - HistogramRefine(histogram_image_raw, histogram_image_raw_size, - histogram_symbols, *histogram_image_size, *histogram_image); + if (!HistogramRefine(histogram_image_raw, histogram_image_raw_size, + histogram_symbols, + *histogram_image, *histogram_image_size)) { + goto Error; + } ok = 1; Error: diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index c666d7ea..5c9d19be 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -154,20 +154,6 @@ static int VP8LEncAnalyze(VP8LEncoder* const enc) { // ----------------------------------------------------------------------------- -static void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) { - if (refs != NULL) { - refs->refs = NULL; - refs->size = 0; - } -} - -static void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) { - if (refs != NULL) { - free(refs->refs); - VP8LInitBackwardRefs(refs); - } -} - static int GetBackwardReferences(int width, int height, const uint32_t* argb, int quality, int use_color_cache,