web-dev-qa-db-fra.com

Endianité du NDK Android

Je travaille avec ma nouvelle application qui traite les images capturées depuis la caméra du téléphone portable. Mon téléphone est Nexus S, 2.3.4.

Je crée un bitmap ARGB_8888 avec des données capturées. Je connais la bibliothèque d'images ndk, mais ce n'est que le support 2.2 et supérieur. Je passe donc l'int [] de Bitmap à NDK et trouve que l'ordre des octets de couleur est little-endian.

J'ai cherché le wiki et trouvé que l'architecture du bras est bi-endian . http://en.wikipedia.org/wiki/Endianness#Bi-endian_hardware

Ma question est si bras est bi-endian, comment juger l'ordre des octets dans un périphérique spécifique? Devrais-je tester l'ordre des octets à chaque fois avant d'accéder aux données?

49
Matrix Bai

Oui, la plupart des processeurs sont bi-endian, mais la plupart des systèmes d’exploitation utilisés actuellement par les utilisateurs finaux choisissent de les utiliser en petit-endian. Dans cet ordre d'idées, ARM peut fonctionner dans les deux cas par souci de commodité. Sa valeur réelle après ARM 3 est little-endianess, qui est le mode Endian dans lequel il démarre. Je pense que l'on peut supposer que les appareils sont peu endian, sinon ce serait un travail supplémentaire si différents appareils Android étaient un mélange d'endianess.

Etant donné que l'ordre des octets du réseau est big-endian, il peut être utile de convertir tout format que vous prévoyez d'utiliser pour l'échange de données en ordre des octets du réseau. Encore une fois, cependant, Mac OS X sur Intel, Windows, iOS et Android sont de petite taille, vous pouvez donc coder les structures avec l’endianité native et espérer que le prochain excellent système d’exploitation sur lequel vous souhaitez transférer des données n’aura pas une grande efficacité .

34
mP.

Directement depuis mon Nexus S:

> import Java.nio.*;
> System.out.println(ByteOrder.nativeOrder());
LITTLE_ENDIAN

Il devrait également y avoir un moyen d'obtenir la commande dans le NDK.

41
lxgr

ARM processeurs (sur lesquels tourne Android) supporte les deux formats endian.

Dans NDK-ROOT/plates-formes/Android- [x] /Arch-arm/usr/include/machine/endian.h, vous pouvez trouver:

#ifdef __ARMEB__
#define _BYTE_ORDER _BIG_ENDIAN
#else
#define _BYTE_ORDER _LITTLE_ENDIAN
#endif

__ARMEB__ est défini par le compilateur gcc lors de l'utilisation de l'option -mbig-endianARM . Même si la plupart des architectures Android utilisent little endian par défaut, vous ne devez pas le prendre pour acquis et pour des raisons de le code devrait être capable de gérer les deux endiannes.

Pour ce faire, vous devez #include <endian.h> et cocher BYTE_ORDER afin de structurer correctement votre code.

20
mehi

Pour donner une réponse très simple, voici une liste:

  • armeabi: LITTLE_ENDIAN
  • armeabi-v7a: LITTLE_ENDIAN
  • arm64-v8a: LITTLE_ENDIAN
  • mips: LITTLE_ENDIAN
  • mips64: LITTLE_ENDIAN
  • x86: LITTLE_ENDIAN
  • x86_64: LITTLE_ENDIAN

... à partir de l'API Android niveau 21.

5
Ales Teska
bool isLittleEndian() {
    unsigned short Word=0x0102;
    return *(char*)&Word==2;
}

simple.

4
NoAngel

Android NDK a ci-dessous des macros qui peuvent être utilisées pour vérifier au moment de la compilation:

#if defined(__LITTLE_ENDIAN_BITFIELD)
#  error "Arch is Little Endian"
#Elif defined (__BIG_ENDIAN_BITFIELD)
#  error "Arch is Big Endian"
#endif

dans votre cas, vous devez assumer Little-Endian et placer ci-dessous quelque part dans la source native, le cas échéant:

#if _BYTE_ORDER != _LITTLE_ENDIAN || defined (__BIG_ENDIAN_BITFIELD)
#  error "Big-Endian Arch is not supported"
#endif
0
Top-Master

J'ai essayé avec la réponse "lxgr", et j'ai aussi LITTLE_ENDIAN.

Mais travaillant avec C++, j'ai lu un fichier avec cette information: 50 4B 03 04 14 00 00 00 08 00 55 8A F4 3C 9B AA ...

J'ai lu les 4 premiers octets sous le nom UnsignedLong et j'ai le 67324752 qui (en hexa) est:

4034B50 

(les 4 premiers bits, mais inversés, comme si je travaillais sur une arche BIG_ENDIAN)

Donc, probablement le "System.out.println (ByteOrder.nativeOrder ());" Pour savoir comment les gérer en Java, mais en travaillant en c ++ avec le NDK, vous devrez vous vérifier vous-même. Voici du code pour réduire les endiannes (à partir de la longue lecture dans BIG_ENDIAN):

long shrinkEndian(long value){
    long result = 0;
    result += (value & 4278190080) >> 24;
    result += (value & 16711680) >> 8;
    result += (value & 65280) << 8;
    result += (value & 255) << 24;

    return result;
}
0