Friday, December 27, 2019

Compile libyuv 32bit and 64bit native libraries for android

Compile libyuv codebase for android to generate 32 bit and 64 bit native libraries.

libyuv is used to rotate NV21 raw data obtained from device camera when the device is held in portrait mode. Sadly android does not provide any API that alters the raw data it provides through the onPreviewFrame callback, so was looking for a way to rotate the NV21 by 90 degrees and libyuv came to the rescue.

I was facing an issue compiling the latest codebase so I checkout an older commit from 2015 as it has the functions that serves my purpose.

Prerequisites:-
  1. NDK setup must be done, and you must be able to compile sample ndk-apps provided in the android-ndk.
  2. Download the libyuv codebase.
The directory that gets created once you do SVN checkout is the libyuv root directory, am going to refer it as LRD (LIBYUV_ROOT_DIR).
LRD contains an Android.mk file which we are going to use to build our shared library (of-course some modifications would be needed).

Once the above prerequisites have been met, then proceed with the following steps to build the shared library:-
  • Create a jni folder in LRD.
  • Copy the Android.mk file to it.
  • Create an Application.mk file and add the following lines to it. 
APP_PLATFORM := android-21
APP_ABI := all
  •  Modify the Android.mk file as below to point to the source code correctly
# This is the Android makefile for libyuv for both platform and NDK.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
$(LOCAL_PATH)/../source/compare.cc \
$(LOCAL_PATH)/../source/compare_common.cc \
$(LOCAL_PATH)/../source/compare_posix.cc \
$(LOCAL_PATH)/../source/convert.cc \
$(LOCAL_PATH)/../source/convert_argb.cc \
$(LOCAL_PATH)/../source/convert_from.cc \
$(LOCAL_PATH)/../source/convert_from_argb.cc \
$(LOCAL_PATH)/../source/convert_to_argb.cc \
$(LOCAL_PATH)/../source/convert_to_i420.cc \
$(LOCAL_PATH)/../source/cpu_id.cc \
$(LOCAL_PATH)/../source/format_conversion.cc \
$(LOCAL_PATH)/../source/planar_functions.cc \
$(LOCAL_PATH)/../source/rotate.cc \
$(LOCAL_PATH)/../source/rotate_argb.cc \
$(LOCAL_PATH)/../source/rotate_mips.cc \
$(LOCAL_PATH)/../source/row_any.cc \
$(LOCAL_PATH)/../source/row_common.cc \
$(LOCAL_PATH)/../source/row_mips.cc \
$(LOCAL_PATH)/../source/row_posix.cc \
$(LOCAL_PATH)/../source/scale.cc \
$(LOCAL_PATH)/../source/scale_argb.cc \
$(LOCAL_PATH)/../source/scale_common.cc \
$(LOCAL_PATH)/../source/scale_mips.cc \
$(LOCAL_PATH)/../source/scale_posix.cc \
$(LOCAL_PATH)/../source/video_common.cc
# TODO(fbarchard): Enable mjpeg encoder.
# source/mjpeg_decoder.cc
# source/convert_jpeg.cc
# source/mjpeg_validate.cc
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS += -DLIBYUV_NEON
LOCAL_SRC_FILES += \
$(LOCAL_PATH)/../source/compare_neon.cc.neon \
$(LOCAL_PATH)/../source/rotate_neon.cc.neon \
$(LOCAL_PATH)/../source/row_neon.cc.neon \
$(LOCAL_PATH)/../source/scale_neon.cc.neon
endif
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
LOCAL_CFLAGS += -DLIBYUV_NEON
LOCAL_CFLAGS := -DHAVE_NEON=1
LOCAL_ARM_MODE := arm
LOCAL_ARM_NEON := true
LOCAL_SRC_FILES += \
$(LOCAL_PATH)/../source/compare_neon64.cc.neon \
$(LOCAL_PATH)/../source/rotate_neon64.cc.neon \
$(LOCAL_PATH)/../source/row_neon64.cc.neon \
$(LOCAL_PATH)/../source/scale_neon64.cc.neon
endif

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_MODULE := libyuv_shared
include $(BUILD_SHARED_LIBRARY)
  • Again trigger ndk-build to generate the .so at LRD/libs/
Now the shared library obtained above has all the functions exposed like ConvertToI420,I420Rotate etc......

To check the functions available use the following command on Linux or MSYS(for windows)
 nm -C -D libyuv_shared.so

No comments:

Post a Comment