aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMans Rullgard <mans@mansr.com>2010-12-22 12:57:53 +0000
committerMans Rullgard <mans@mansr.com>2011-02-11 15:48:10 +0000
commit7da48fd0111adf504cfcfc5ebda7fd0681968041 (patch)
treef5244f9af0430fcb50a9d06d76efb3fc772af253
parentaa8ac53b51cd8b9446b50404660685041060fa4f (diff)
downloadffmpeg-7da48fd0111adf504cfcfc5ebda7fd0681968041.tar.gz
ARM optimised vp56_rac_get_prob()
Approximately 3% faster on Cortex-A8. Signed-off-by: Mans Rullgard <mans@mansr.com>
-rw-r--r--libavcodec/arm/vp56_arith.h92
-rw-r--r--libavcodec/vp56.h6
2 files changed, 97 insertions, 1 deletions
diff --git a/libavcodec/arm/vp56_arith.h b/libavcodec/arm/vp56_arith.h
new file mode 100644
index 0000000000..9bcb466bdc
--- /dev/null
+++ b/libavcodec/arm/vp56_arith.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 Mans Rullgard <mans@mansr.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_ARM_VP56_ARITH_H
+#define AVCODEC_ARM_VP56_ARITH_H
+
+#if HAVE_ARMV6 && HAVE_INLINE_ASM
+
+#define vp56_rac_get_prob vp56_rac_get_prob_armv6
+static inline int vp56_rac_get_prob_armv6(VP56RangeCoder *c, int pr)
+{
+ unsigned shift = ff_vp56_norm_shift[c->high];
+ unsigned code_word = c->code_word << shift;
+ unsigned high = c->high << shift;
+ unsigned bit;
+
+ __asm__ volatile ("adds %3, %3, %0 \n"
+ "cmpcs %7, %4 \n"
+ "ldrcsh %2, [%4], #2 \n"
+ "rsb %0, %6, #256 \n"
+ "smlabb %0, %5, %6, %0 \n"
+ "rev16cs %2, %2 \n"
+ "orrcs %1, %1, %2, lsl %3 \n"
+ "subcs %3, %3, #16 \n"
+ "lsr %0, %0, #8 \n"
+ "cmp %1, %0, lsl #16 \n"
+ "subge %1, %1, %0, lsl #16 \n"
+ "subge %0, %5, %0 \n"
+ "movge %2, #1 \n"
+ "movlt %2, #0 \n"
+ : "=&r"(c->high), "=&r"(c->code_word), "=&r"(bit),
+ "+&r"(c->bits), "+&r"(c->buffer)
+ : "r"(high), "r"(pr), "r"(c->end - 1),
+ "0"(shift), "1"(code_word));
+
+ return bit;
+}
+
+#define vp56_rac_get_prob_branchy vp56_rac_get_prob_branchy_armv6
+static inline int vp56_rac_get_prob_branchy_armv6(VP56RangeCoder *c, int pr)
+{
+ unsigned shift = ff_vp56_norm_shift[c->high];
+ unsigned code_word = c->code_word << shift;
+ unsigned high = c->high << shift;
+ unsigned low;
+ unsigned tmp;
+
+ __asm__ volatile ("adds %3, %3, %0 \n"
+ "cmpcs %7, %4 \n"
+ "ldrcsh %2, [%4], #2 \n"
+ "rsb %0, %6, #256 \n"
+ "smlabb %0, %5, %6, %0 \n"
+ "rev16cs %2, %2 \n"
+ "orrcs %1, %1, %2, lsl %3 \n"
+ "subcs %3, %3, #16 \n"
+ "lsr %0, %0, #8 \n"
+ "lsl %2, %0, #16 \n"
+ : "=&r"(low), "+&r"(code_word), "=&r"(tmp),
+ "+&r"(c->bits), "+&r"(c->buffer)
+ : "r"(high), "r"(pr), "r"(c->end - 1), "0"(shift));
+
+ if (code_word >= tmp) {
+ c->high = high - low;
+ c->code_word = code_word - tmp;
+ return 1;
+ }
+
+ c->high = low;
+ c->code_word = code_word;
+ return 0;
+}
+
+#endif
+
+#endif
diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h
index da6b1b64b8..d1735e5609 100644
--- a/libavcodec/vp56.h
+++ b/libavcodec/vp56.h
@@ -201,7 +201,9 @@ static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c)
return code_word;
}
-#if ARCH_X86
+#if ARCH_ARM
+#include "arm/vp56_arith.h"
+#elif ARCH_X86
#include "x86/vp56_arith.h"
#endif
@@ -221,6 +223,7 @@ static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, uint8_t prob)
}
#endif
+#ifndef vp56_rac_get_prob_branchy
// branchy variant, to be used where there's a branch based on the bit decoded
static av_always_inline int vp56_rac_get_prob_branchy(VP56RangeCoder *c, int prob)
{
@@ -238,6 +241,7 @@ static av_always_inline int vp56_rac_get_prob_branchy(VP56RangeCoder *c, int pro
c->code_word = code_word;
return 0;
}
+#endif
static av_always_inline int vp56_rac_get(VP56RangeCoder *c)
{