Browse Source

Merge commit '096abfa15052977eed93f0b5e01afd2d47c53c1f'

* commit '096abfa15052977eed93f0b5e01afd2d47c53c1f':
  parser: fix large overreads
  bitstream: add get_bits64() to support reading more than 32 bits at once
  arm: detect cpu features at runtime on Linux

Conflicts:
	libavcodec/parser.c
	libavformat/mpegts.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
Michael Niedermayer 12 years ago
parent
commit
57cee85023
5 changed files with 95 additions and 18 deletions
  1. 3 1
      configure
  2. 5 5
      libavcodec/get_bits.h
  3. 3 2
      libavcodec/parser.c
  4. 1 10
      libavformat/mpegts.c
  5. 83 0
      libavutil/arm/cpu.c

+ 3 - 1
configure

@@ -3497,7 +3497,9 @@ EOF
     enabled vfp     && check_insn vfp     'fadds s0, s0, s0'
     enabled vfpv3   && check_insn vfpv3   'vmov.f32 s0, #1.0'
 
-    map 'enabled_any ${v}_external ${v}_inline || disable $v' $ARCH_EXT_LIST_ARM
+    [ $target_os = linux ] ||
+        map 'enabled_any ${v}_external ${v}_inline || disable $v' \
+            $ARCH_EXT_LIST_ARM
 
     check_inline_asm asm_mod_q '"add r0, %Q0, %R0" :: "r"((long long)0)'
     check_inline_asm asm_mod_y '"vmul.i32 d0, d0, %y0" :: "x"(0)'

+ 5 - 5
libavcodec/get_bits.h

@@ -322,15 +322,15 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n)
  */
 static inline uint64_t get_bits64(GetBitContext *s, int n)
 {
-    if (n <= 32)
+    if (n <= 32) {
         return get_bits_long(s, n);
-    else {
+    } else {
 #ifdef BITSTREAM_READER_LE
         uint64_t ret = get_bits_long(s, 32);
-        return ret | (((uint64_t)get_bits_long(s, n-32)) << 32);
+        return ret | (uint64_t)get_bits_long(s, n - 32) << 32;
 #else
-        uint64_t ret = ((uint64_t)get_bits_long(s, 32)) << (n-32);
-        return ret | get_bits_long(s, n-32);
+        uint64_t ret = (uint64_t)get_bits_long(s, n - 32) << 32;
+        return ret | get_bits_long(s, 32);
 #endif
     }
 }

+ 3 - 2
libavcodec/parser.c

@@ -253,8 +253,9 @@ int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_s
         if(!new_buffer)
             return AVERROR(ENOMEM);
         pc->buffer = new_buffer;
-        if(FF_INPUT_BUFFER_PADDING_SIZE > -next)
-        memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE );
+        if (next > -FF_INPUT_BUFFER_PADDING_SIZE)
+            memcpy(&pc->buffer[pc->index], *buf,
+                   next + FF_INPUT_BUFFER_PADDING_SIZE);
         pc->index = 0;
         *buf= pc->buffer;
     }

+ 1 - 10
libavformat/mpegts.c

@@ -714,18 +714,9 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
 
 static uint64_t get_ts64(GetBitContext *gb, int bits)
 {
-    uint64_t ret = 0;
-
     if (get_bits_left(gb) < bits)
         return AV_NOPTS_VALUE;
-    while (bits > 17) {
-        ret <<= 17;
-        ret |= get_bits(gb, 17);
-        bits -= 17;
-    }
-    ret <<= bits;
-    ret |= get_bits(gb, bits);
-    return ret;
+    return get_bits64(gb, bits);
 }
 
 static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf, int buf_size)

+ 83 - 0
libavutil/arm/cpu.c

@@ -19,6 +19,87 @@
 #include "libavutil/cpu.h"
 #include "config.h"
 
+#define CORE_FLAG(f) \
+    (AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
+
+#define CORE_CPU_FLAGS                          \
+    (CORE_FLAG(ARMV5TE) |                       \
+     CORE_FLAG(ARMV6)   |                       \
+     CORE_FLAG(ARMV6T2) |                       \
+     CORE_FLAG(VFP)     |                       \
+     CORE_FLAG(VFPV3)   |                       \
+     CORE_FLAG(NEON))
+
+#if defined __linux__ || defined __ANDROID__
+
+#include <stdint.h>
+#include <stdio.h>
+
+#define AT_HWCAP        16
+
+/* Relevant HWCAP values from kernel headers */
+#define HWCAP_VFP       (1 << 6)
+#define HWCAP_EDSP      (1 << 7)
+#define HWCAP_THUMBEE   (1 << 11)
+#define HWCAP_NEON      (1 << 12)
+#define HWCAP_VFPv3     (1 << 13)
+#define HWCAP_TLS       (1 << 15)
+
+static int get_hwcap(uint32_t *hwcap)
+{
+    struct { uint32_t a_type; uint32_t a_val; } auxv;
+    FILE *f = fopen("/proc/self/auxv", "r");
+    int err = -1;
+
+    if (!f)
+        return -1;
+
+    while (fread(&auxv, sizeof(auxv), 1, f) > 0) {
+        if (auxv.a_type == AT_HWCAP) {
+            *hwcap = auxv.a_val;
+            err = 0;
+            break;
+        }
+    }
+
+    fclose(f);
+    return err;
+}
+
+int ff_get_cpu_flags_arm(void)
+{
+    int flags = CORE_CPU_FLAGS;
+    uint32_t hwcap;
+
+    if (get_hwcap(&hwcap) < 0)
+        return flags;
+
+#define check_cap(cap, flag) do {               \
+        if (hwcap & HWCAP_ ## cap)              \
+            flags |= AV_CPU_FLAG_ ## flag;      \
+    } while (0)
+
+    /* No flags explicitly indicate v6 or v6T2 so check others which
+       imply support. */
+    check_cap(EDSP,    ARMV5TE);
+    check_cap(TLS,     ARMV6);
+    check_cap(THUMBEE, ARMV6T2);
+    check_cap(VFP,     VFP);
+    check_cap(VFPv3,   VFPV3);
+    check_cap(NEON,    NEON);
+
+    /* The v6 checks above are not reliable so let higher flags
+       trickle down. */
+    if (flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))
+        flags |= AV_CPU_FLAG_ARMV6T2;
+    if (flags & AV_CPU_FLAG_ARMV6T2)
+        flags |= AV_CPU_FLAG_ARMV6;
+
+    return flags;
+}
+
+#else
+
 int ff_get_cpu_flags_arm(void)
 {
     return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE |
@@ -28,3 +109,5 @@ int ff_get_cpu_flags_arm(void)
            AV_CPU_FLAG_VFPV3   * HAVE_VFPV3   |
            AV_CPU_FLAG_NEON    * HAVE_NEON;
 }
+
+#endif