From 239b88c284af3025513e5cac6e318d1f9a9cdd71 Mon Sep 17 00:00:00 2001 From: Malcolm Bechard Date: Wed, 20 Feb 2013 15:50:34 -0500 Subject: [PATCH] Improve QTRLE encoding performance, no change to output file size/content. Avoid searching for the lowest bulk cost for each pixel that isn't a repeat/skip. Instead store the lowest cost as we go along each pixel, and use it as needed. Signed-off-by: Malcolm Bechard Signed-off-by: Michael Niedermayer --- libavcodec/qtrleenc.c | 82 ++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index e151c9e1fa..a25c45d6db 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -121,8 +121,6 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui int i; signed char rlecode; - /* We will use it to compute the best bulk copy sequence */ - unsigned int av_uninit(bulkcount); /* This will be the number of pixels equal to the preivous frame one's * starting from the ith pixel */ unsigned int skipcount; @@ -131,12 +129,14 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui unsigned int av_uninit(repeatcount); /* The cost of the three different possibilities */ - int total_bulk_cost; int total_skip_cost; int total_repeat_cost; - int temp_cost; - int j; + int base_bulk_cost; + int lowest_bulk_cost; + int lowest_bulk_cost_index; + int sec_lowest_bulk_cost; + int sec_lowest_bulk_cost_index; uint8_t *this_line = p-> data[0] + line*p-> linesize[0] + (width - 1)*s->pixel_size; @@ -146,8 +146,57 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui s->length_table[width] = 0; skipcount = 0; + /* Initial values */ + lowest_bulk_cost = INT_MAX / 2; + lowest_bulk_cost_index = width; + sec_lowest_bulk_cost = INT_MAX / 2; + sec_lowest_bulk_cost_index = width; + + base_bulk_cost = 1 + s->pixel_size; + for (i = width - 1; i >= 0; i--) { + int prev_bulk_cost; + + /* If our lowest bulk cost index is too far away, replace it + * with the next lowest bulk cost */ + if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) { + lowest_bulk_cost = sec_lowest_bulk_cost; + lowest_bulk_cost_index = sec_lowest_bulk_cost_index; + + sec_lowest_bulk_cost = INT_MAX / 2; + sec_lowest_bulk_cost_index = width; + } + + /* Deal with the first pixel's bulk cost */ + if (!i) { + base_bulk_cost++; + lowest_bulk_cost++; + sec_lowest_bulk_cost++; + } + + /* Look at the bulk cost of the previous loop and see if it is + * a new lower bulk cost */ + prev_bulk_cost = s->length_table[i + 1] + base_bulk_cost; + if (prev_bulk_cost <= sec_lowest_bulk_cost) { + /* If it's lower than the 2nd lowest, then it may be lower + * than the lowest */ + if (prev_bulk_cost <= lowest_bulk_cost) { + + /* If we have found a new lowest bulk cost, + * then the 2nd lowest bulk cost is now farther than the + * lowest bulk cost, and will never be used */ + sec_lowest_bulk_cost = INT_MAX / 2; + + lowest_bulk_cost = prev_bulk_cost; + lowest_bulk_cost_index = i + 1; + } else { + /* Then it must be the 2nd lowest bulk cost */ + sec_lowest_bulk_cost = prev_bulk_cost; + sec_lowest_bulk_cost_index = i + 1; + } + } + if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size)) skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP); else @@ -183,26 +232,17 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui } else { /* We cannot do neither skip nor repeat - * thus we search for the best bulk copy to do */ + * thus we use the best bulk copy */ - int limit = FFMIN(width - i, MAX_RLE_BULK); + s->length_table[i] = lowest_bulk_cost; + s->rlecode_table[i] = lowest_bulk_cost_index - i; - temp_cost = 1 + s->pixel_size + !i; - total_bulk_cost = INT_MAX; - - for (j = 1; j <= limit; j++) { - if (s->length_table[i + j] + temp_cost < total_bulk_cost) { - /* We have found a better bulk copy ... */ - total_bulk_cost = s->length_table[i + j] + temp_cost; - bulkcount = j; - } - temp_cost += s->pixel_size; - } - - s->length_table[i] = total_bulk_cost; - s->rlecode_table[i] = bulkcount; } + /* These bulk costs increase every iteration */ + lowest_bulk_cost += s->pixel_size; + sec_lowest_bulk_cost += s->pixel_size; + this_line -= s->pixel_size; prev_line -= s->pixel_size; }