Monday, February 17, 2020

Compile openh264 for 64 bit android

Back in 2014 it was compiled for 32 bit
https://rnd.sabacloud.com/Saba/Web_spf/SabaWork/app/shared;spf-url=pages%2Fpagedetailview%2Fspage000000000025569%2Fmobile%2Fcompile-openh264-for-android

Command used to compile openh264

Clean for arm architecture(32 bit)
make OS=android NDKROOT=$NDK_HOME TARGET=android-28 ARCH=arm NDKLEVEL=21 NDK_TOOLCHAIN_VERSION=clang cleanBuild for arm architecture(32 bit)
make OS=android NDKROOT=$NDK_HOME TARGET=android-28 ARCH=arm NDKLEVEL=21 NDK_TOOLCHAIN_VERSION=clang libopenh264.so


Clean for arm64 architecture(64 bit)
make OS=android NDKROOT=$NDK_HOME TARGET=android-28 ARCH=arm64 NDKLEVEL=21 NDK_TOOLCHAIN_VERSION=clang cleanBuild for arm architecture(64 bit)
make OS=android NDKROOT=$NDK_HOME TARGET=android-28 ARCH=arm64 NDKLEVEL=21 NDK_TOOLCHAIN_VERSION=clang libopenh264.so


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

Thursday, November 21, 2019

Compile WebRTC VoiceEngine for SM android(Revisited)

Back in 2015 I had compiled WebRTC codebase for android as I needed WebRTC's VoiceEngine library for android. Link given below.


The library compiled then was 32 bit only and starting August 2019 Google has mandated to include support for 64 bit native libraries.
Thus, there was need to recompile the codebase and generate the said library again.
For this, I have used the same VM as explained in link above.

This time, I used VirtualBox 6 and MacOS Mojave 10.14.6.
Initially I faced an issue importing the the VM file(Ubuntu-14.04.2.ova) but installing VirtualBox extension pack did the trick and the VM came back to life.
Another issue I faced was that Chrome browser being used on the VM Ubuntu was quite old and wasn't responding, I wanted to upgrade but I don't the remember the password for the VM :P
I followed this tutorial to reset the password and succeeded.

Next steps remain invariably the same except for 1 modification for 64 bit and 1 correction.

cd Documents/work/android/webrtc/webrtcFresh/
export PATH=`pwd`/depot_tools:"$PATH"
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/
#for 32 bit devices below command
export GYP_DEFINES="OS=android"
#for 64 bit devices below command
#export GYP_DEFINES="OS=android target_arch=arm64 target_subarch=arm64"
cd /home/azhar/Documents/work/android/webrtc/webrtcFresh/WebCRT/src

. build/android/envsetup.sh
export GYP_DEFINES="build_with_chromium=0  $GYP_DEFINES"
export GYP_DEFINES="build_with_libjingle=1 $GYP_DEFINES"
export GYP_DEFINES="libjingle_java=1 $GYP_DEFINES"
export GYP_DEFINES="enable_tracing=1 $GYP_DEFINES"

gclient runhooks

  • The above command generates all the ninja files required to build the webrtc libs. Path of ninja files is as mentioned below:-
for debug mode - WebCRT/src/webrtc/obj/Debug/webrtc/
for release mode - WebCRT/src/webrtc/obj/Release/webrtc/
above path is incorrect,
corrrect path-WebCRT/src/out/Release/obj

Before building the libs edit the libwebrtc-jni.ninja to remove the -fno-rtti flag from cflags_cc parameter, it is required because some additional code is added in the JNI wrapper to make it work with SabaMeeting.

ninja -C out/Debug #builds in debug mode
ninja -C out/Release  #builds in Release mode

  • Post successful builds the final libwebrtc-jni.so will get generated at
/Documents/work/android/webrtc/webrtcFresh/WebCRT/src/webrtc/examples/android/media_demo/libs/armeabi-v7a

  • Incase the jni wrapper needs to be modified, media_demo/jni contains the JNI wrapper.

Note: Important point to note here before beginning is that the WebRTC codebase should not updated, as the WebRTC implementation has changed significantly and I could not find the VoiceEngine library in the latest codebase.

Monday, August 15, 2016

Make color transparent (Hex values of Alpha color codes)

Here's a correct table of percentages to hex values. E.g. for 50% white you'd use #80FFFFFF

Using the below values one can achieve transparency in any color.

AARRGGBB where AA represents the alpha value and can be replaced with hex values from below table to achieve desired transparency.

  • 100% — FF
  • 95% — F2
  • 90% — E6
  • 85% — D9
  • 80% — CC
  • 75% — BF
  • 70% — B3
  • 65% — A6
  • 60% — 99
  • 55% — 8C
  • 50% — 80
  • 45% — 73
  • 40% — 66
  • 35% — 59
  • 30% — 4D
  • 25% — 40
  • 20% — 33
  • 15% — 26
  • 10% — 1A
  • 5% — 0D
  • 0% — 00

Taken from SO for my future reference 

Sunday, August 14, 2016

Screen resolutions

  • 36x36 (0.75x) for low-density
  • 48x48 (1.0x baseline) for medium-density
  • 72x72 (1.5x) for high-density
  • 96x96 (2.0x) for extra-high-density
  • 144x144 (3.0x) for extra-extra-high-density
  • 192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see note above)


In short 

mdpi
ldpi = 0.75 X mdpi
hdpi = 1.5 X mdpi
xhdpi = 2 X mdpi
xxhdpi = 3 X mdpi
xxxhdpi = 4 X mdpi

Friday, June 3, 2016

Android Studio important points


1. To Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
            File --> Other Settings --> Default settings --> Build, Execution, Deployment --> Compiler

            Command-line option takes -stacktrace option to get the stack trace.
            Run with --info or --debug option to get more log output.

2. Suggestion: add 'tools:replace="android:icon"' to <application> element in AndroidManifestAdd xmlns:tools="http://schemas.android.com/tools" to manifest tag and tools:replace="android:icon,android:theme,android:label" to application tag.

3. For the error unmappable character for encoding UTF-8.......... Add the following line to build.gradle
android {
 ...
compileOptions.encoding = 'ISO-8859-1'
 }

4. Add support library to Android Studio project

5. Open File -> Project Structure... menu.
6. Select Modules in the left pane, choose your project's main module in the middle pane and openDependencies tab in the right pane.
7. Click the plus sign in the right panel and select "Maven dependency" from the list. A Maven dependency dialog will pop up.
8. Enter "support-v4" into the search field and click the icon with magnifying glass.
9. Run the below command in terminal to detect which image file is causing the merge to fail. After running the command check for buildLog.txt file in Project window, search for Error which will point to the exact file causing the issue.
gradlew :app:mergeDebugResources --debug > buildLog.txt
10. All com.android.support libraries must use the exact same version specification
Solution : https://stackoverflow.com/a/42374426 

Saturday, May 21, 2016

Compiling POCO libraries for Android



Create a standard toolchain

http://developer.android.com/ndk/guides/standalone_toolchain.html


$NDK_ROOT/build/tools/make-standalone-toolchain.sh \
--arch=arm --platform=android-18 --toolchain=arm-linux-androideabi-4.8 --install-dir=/Users/saba/azhar/work/android/POCO/poco-android-toolchain

————————————————————————
On El-Captain Install the openssl (openssl should be already present on a linux system)

brew install openssl
brew link openssl --force


————————————————————————

POCO build complete edition with NetSSL_OpenSSL and Crypto(without ODBC and MySQL)

cd /Users/ss/aa/work/android/POCO/poco-1.6.1-all_Shared

export PATH=$PATH:/Users/ss/aa/work/android/POCO/poco-android-toolchain/bin

./configure --config=Android --no-samples --no-tests --omit=Data/ODBC,Data/MySQL --include-path=/usr/local/Cellar/openssl/1.0.2d_1/include --library-path=/usr/local/Cellar/openssl/1.0.2d_1/lib

make -s -j4
————————————————————————

POCO build basic edition 

cd /Users/ss/aa/work/android/poco-1.6.1

export PATH=$PATH:/Users/ss/aa/work/android/POCO/poco-android-toolchain/bin

./configure --config=Android --no-samples --no-tests

make -s -j4

————————————————————————

By default POCO will compile static libs (.a) files but yet I haven't been able to successfully create a JNI wrapper to use functions available in static libs. So I compiled the shared libs and used them.

To generate shared libs open the below make file
/Users/ss/aa/work/android/POCO/poco-1.6.1-all_Shared/build/config/Android 

and change from

LINKMODE           ?= STATIC

to

LINKMODE           ?= SHARED


After the complete POCO libs are built they should be available in lib folder present under Root of POCO  (poco-1.6.1-all_Shared and poco-1.6.1 in my case)

Although I could generate all static libs, I could not generate the libPocoNetSSL.so lib.
I guess it was because the openssl lib that the POCO code referes to was using a static lib on MAC and creating a shared lib using static lib was causing some problem.

I speculate that the problem should not exist on a linux machine. Will try out soon and post the results.

————————————————————————

Do a clean up of POCO

make clean
rm -f -R lib
popd

rm -f -R Platform/Android/lib

rm -f -R Platform/iOS/lib

rm -f -R Platform/MacOS/lib

rm -f -R Build/iOS

rm -f -R Build/Android

rm -f -R Build/Darwin

————————————————————————
System 

OS X El Capitan
————————————————————————


Reference : -

http://pocoproject.org/docs/99300-AndroidPlatformNotes.html 



Monday, July 20, 2015

Fetching application data

Device must be rooted

  Open cmd
  Type 'adb shell'
  su
  Press 'Allow' on device
  chmod 777 /data
  chmod 777 /data/data
  chmod 777 /data/data/com.application.package
  chmod 777 /data/data/com.application.package/*

Open DDMS view in Eclipse and from there open 'FileExplorer' to get your desired file

After this you should be able to browse the files on the device.

Thursday, June 25, 2015

Wifi debugging on eclipse for Android

Wifi debugging on eclipse for Android
Connect your phone via usb and let it detect.
Execute following commands from platform-tools/adb.
> adb tcpip 5555
this will ping your android phone
> adb connect <ipaddress_of_phone>
this will connect with your phone

On successful completion, remove usb cable and njoy debugging without usb cable.

If you wanna reconnect again your phone for debugging, just execute the second command without connecting it with usb wire.

finally
> adb disconnect

Monday, June 22, 2015

Play youtube using the iFrame API on Android

  •  The IFrame player API lets you embed a YouTube video player on your website and control the player using JavaScript. Unlike the Flash and JavaScript player APIs, which both involve embedding a Flash object on your web page, the IFrame API posts content to an <iframe> tag on your page. This approach provides more flexibility than the previously available APIs since it allows YouTube to serve an HTML5 player rather than a Flash player for mobile devices that do not support Flash.
  • Using the API's JavaScript functions, you can queue videos for playback; play, pause, or stop those videos; adjust the player volume; or retrieve information about the video being played. You can also add event listeners that will execute in response to certain player events, such as a player state change or a video playback quality change.
  • It briefs the different JavaScript functions that you can call to control the video player as well as the player parameters you can use to further customize the player.

Any web page that uses the IFrame API must implement the following JavaScript function:
  • onYouTubeIframeAPIReady – The API will call this function when the page has finished downloading the JavaScript for the player API, which enables you to then use the API on your page. Thus, this function might create the player objects that you want to display when the page loads.
     
Loading a video player 

After the API's JavaScript code loads, the API will call the onYouTubeIframeAPIReady function, at which point you can construct a YT.Player object to insert a video player on your page. The HTML excerpt below shows the onYouTubeIframeAPIReady function from the example above:
var player;
var pVars = {
             controls : 0,
             playsinline : 1,
      autohide : 1,
             showinfo : 0,
      modestbranding : 1,
      height : '100%',
      width : '100%'
            }; 
var vID = 'M7lc1UVf-VE'; 
function onYouTubeIframeAPIReady() 
{  
   player = new YT.Player('player', {
   playerVars : pVars,
   videoId: vID,
   events: { 
     'onReady': onPlayerReady,
     'onStateChange': onPlayerStateChange 
   }  
 });
}

To call the player API methods, first get a reference to the player object you wish to control. You obtain the reference by creating a YT.Player object as discussed above.

Playback controls and player settings

Playing a video

player.playVideo():Void
Plays the currently loaded video. The final player state after this function executes will be playing (1).

Note: A playback only counts toward a video's official view count if it is initiated via a native play button in the player.
player.pauseVideo():Void
Pauses the currently playing video. The final player state after this function executes will be paused (2) unless the player is in the ended (0) state when the function is called, in which case the player state will not change.
player.seekTo(seconds:Number, allowSeekAhead:Boolean):Void
Seeks to a specified time in the video. If the player is paused when the function is called, it will remain paused. If the function is called from another state (playing, video cued, etc.), the player will play the video.
  • The seconds parameter identifies the time to which the player should advance.
    The player will advance to the closest keyframe before that time unless the player has already downloaded the portion of the video to which the user is seeking. In that case, the player will advance to the closest keyframe before or after the specified time as dictated by the seek() method of the Flash player's NetStream object. (See Adobe's documentation for more information.)
  • The allowSeekAhead parameter determines whether the player will make a new request to the server if the seconds parameter specifies a time outside of the currently buffered video data.
Here is a working Android demo https://github.com/zenith22/YoutubeIFrameAPIDemo

For more details please refer  YouTube IFrame Player API

 

Compile OpenH264 for Android

OpenH264
OpenH264 is a codec library which supports H.264 encoding and decoding.
The source code repository is hosted on github at https://github.com/cisco/openh264.
See http://www.openh264.org/ for more details.

Compile OpenH264 for Android (using Windows)
  • In order to compile the openh264 the GNU Make (http://www.gnu.org/software/make/)utilityis required. Hence to provide make tool available on Windows, MSYS needs to be installed.

  • To compile openh264 for Android (using Windows) the following are required –
  1. MSYS (http://www.mingw.org/wiki/MSYS)
  2. Android NDK (https://developer.android.com/tools/sdk/ndk/index.html
  3. The openh264 source from github (https://github.com/cisco/openh264)

  • Post installations, ensure that everything is installed correctly, try building sample projects available with Android NDK.



  • After installing MSYS you should have a cyan "M" link on the Desktop. When you double-click on it, a terminal should be launched.
  1. Navigate to project directory (using UNIX style commands)
  2. Finally to compile use the following command make OS=android NDKROOT=/unix/path/to/ndk TARGET=9 libopenh264.so
  3. NDKROOT=/d/Softwares/android-ndk-r10 (in my case)
  4. All the libraries should be compiled post this command.

  • Once all the libs are compiled, then these can be used to run the sample apps for encoding and decoding.

Thursday, May 28, 2015

Using libyuv prebuilt shared library in Android

In my previous post I explained how to build libyuv shared library  now I would like to explain how to write a JNI wrapper and access the libyuv functions available.

Please go  through the above post before proceeding, as I'll be frequently referring to it.

From the post above, If you have successfully built the libyuv shared library then you should see the .so's generated at the location :-
LRD/libs/armeabi/libyuv_shared.so
LRD/libs/armeabi-v7a/libyuv_shared.so
LRD/libs/mips/libyuv_shared.so
LRD/libs/x86/libyuv_shared.so

We'll be needing the .so's, for the JNI wrapper will be accessing the functions present in it.



Create the following directory structures in your workspace:-


LibYUVDemo/prebuilt/
LibYUVDemo/include/
LibYUVDemo/jni/



Under the LibYUVDemo/prebuilt/ directoy paste the libyuv_shared.so files in the respective order :-

LibYUVDemo/prebuilt/armeabi/libyuv_shared.so
LibYUVDemo/prebuilt/armeabi-v7a/libyuv_shared.so
LibYUVDemo/prebuilt/mips/libyuv_shared.so
LibYUVDemo/prebuilt/x86/libyuv_shared.so

Copy the contents of include folder from libyuv source and paste it under
LibYUVDemo/include/ 

Now the actual JNI wrapper, create LibYUVDemo.cpp under
LibYUVDemo/jni/ and write a jni function as follows :-

#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include "libyuv.h"
#include <android/log.h>

#define LOG_TAG "YUVDemo"
#define LOGI(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define printf(...) LOGI(__VA_ARGS__)

using namespace libyuv;

extern "C" {
JNIEXPORT void Java_com_demo_libyuvdemo_MainActivity_callLibYUV(JNIEnv* env, jobject thiz) {

libyuv::RotationMode mode = libyuv::kRotate180;

/*libyuv::ConvertToI420(const unsigned char *, unsigned int, unsigned char *, int, unsigned char *, int, unsigned char *, int, int, int, int, int, int, int, enum libyuv::RotationMode, unsigned int);
 */
    printf("rotation mode selected = %d",mode);
}

Create an Android.mk file under LibYUVDemo/jni/
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := yuv_shared
LOCAL_SRC_FILES := ../prebuilt/$(TARGET_ARCH_ABI)/libyuv_shared.so
ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_SRC_FILES)))
include $(PREBUILT_SHARED_LIBRARY)
endif


include $(CLEAR_VARS)

LOCAL_MODULE    := YUVDemo
LOCAL_SRC_FILES := LibYUVDemo.cpp
#LOCAL_SRC_FILES := LibYUVDemo.c


#
# Header Includes
#
LOCAL_C_INCLUDES := \
            $(LOCAL_PATH)/../include
#
# Compile Flags and Link Libraries
#
LOCAL_CFLAGS := -DANDROID_NDK

LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := yuv_shared

include $(BUILD_SHARED_LIBRARY)
Finally create an Application.mk file under LibYUVDemo/jni/

APP_ABI := all
APP_PLATFORM := android-9
APP_STL := stlport_shared

Now navigate to LibYUVDemo/jni/ from command prompt and trigger ndk-build, the JNI should get compiled and you must have the new .so geneated at LibYUVDemo/libs/ for the all the architectures.


A complete working app is available at github.

Thursday, May 21, 2015

Building libyuv shared library for Android

         Recently for my project I wanted 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.

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, do an SVN checkout from here.
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-9
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_neon64.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/planar_functions.cc  \
    $(LOCAL_PATH)/../source/rotate.cc            \
    $(LOCAL_PATH)/../source/rotate_argb.cc       \
    $(LOCAL_PATH)/../source/rotate_mips.cc       \
    $(LOCAL_PATH)/../source/rotate_neon64.cc     \
    $(LOCAL_PATH)/../source/row_any.cc           \
    $(LOCAL_PATH)/../source/row_common.cc        \
    $(LOCAL_PATH)/../source/row_mips.cc          \
    $(LOCAL_PATH)/../source/row_neon64.cc        \
    $(LOCAL_PATH)/../source/row_posix.cc            \
    $(LOCAL_PATH)/../source/scale.cc             \
    $(LOCAL_PATH)/../source/scale_any.cc         \
    $(LOCAL_PATH)/../source/scale_argb.cc        \
    $(LOCAL_PATH)/../source/scale_common.cc      \
    $(LOCAL_PATH)/../source/scale_mips.cc        \
    $(LOCAL_PATH)/../source/scale_neon64.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

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include

LOCAL_MODULE := libyuv_static
LOCAL_MODULE_TAGS := optional

include $(BUILD_STATIC_LIBRARY)
  • Open command prompt (on Windows) or Terminal in Linux or MAC, navigate to LRD/jni and type ndk-build
  • This should trigger the build process and if all goes well the libyuv_static.a (a static library) will get created inside LRD/obj/local/armeabi/
  • But we cannot use a static library with android  so we need to generate a shared library (.so),  for that simply modify the following tags as below (Android.mk file)
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

In my next post I'll try to show how to write a JNI wrapper to use the libyuv shared library.


Thursday, May 7, 2015

Building WebRTC libraries for Android

   After banging my head almost 2 weeks trying to build WebRTC libraries on Windows and MAC machine, as of today I have successfully compiled WebRTC binaries for Android using this awesome tutorial from here http://www.khirman.com/building-webrtc-libraries-android/

   Anyone reading this post, I would like to suggest don't waste time trying to build on Windows or MAC, it doesn't help, only surges your frustration.

   Linux is the only way out to compile WebRTC, I used Ubuntu 14.04.2 LTS setup in VirtualBox on a MAC.
  
   The following is the list of commands (taken from above site) that I used to compile the libraries.


# assuming we are starting from "virgin" Ubuntu installation
sudo apt-get install git
sudo apt-get install g++
sudo apt-get install subversion
sudo apt-get install git-svn
sudo apt-get install openjdk-7-jdk
sudo apt-get install ant
sudo apt-get install lib32stdc++6 lib32z1
#
# get google build tools
#
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
#
# we'll need Java
#
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/
#
# now we are setting our target for compilation
#
export GYP_DEFINES="OS=android"
#
# New home for WebCRT
#
mkdir WebCRT
cd WebCRT
#
# Time to pull sources ( including all dependencies derived from chromium project)
# will take quite a time
#
fetch webrtc_android
#
# Now time to build
#
cd src
#
# setup Android cross compiler build environment
#
. build/android/envsetup.sh
export GYP_DEFINES="build_with_chromium=0  $GYP_DEFINES"
export GYP_DEFINES="build_with_libjingle=1 $GYP_DEFINES"
export GYP_DEFINES="libjingle_java=1 $GYP_DEFINES"
# send WEBRTC_LOGGING to Android's logcat
export GYP_DEFINES="enable_tracing=1 $GYP_DEFINES"
#
# Generate .ninja files
#
gclient runhooks
#
# and now is an actual build....
#

#
# Build AppRTCDemo application – demonstrates interoperability of native Android
# client and Chrome JavaScript client.
# source code / project root : src/talk/examples/android/
# resulting APK : src/out/Debug/AppRTCDemo-debug.apk
#
ninja -C out/Debug AppRTCDemo
#
# Build WebRTCDemo application – exchange video+audio between two
# android clients.
# source code / project root : src/webrtc/examples/android/media_demo/
# resulting APK : src/out/Debug/WebRTCDemo-debug.apk
#
ninja -C out/Debug WebRTCDemo

One small addition, post the gclient  runhooks command in list above use this command to generate all the libraries and apks

ninja -C out/Debug

I am re-posting all the commands here just for my future reference, but might help someone else trying to build the libs.

Wednesday, December 3, 2014

Cycling || Recreation

  Since childhood I have liked cycling, but then it was just for the sake of playing. Lately I have developed inclination towards cycling and decided to take it more seriously. It all started when in my previous company we had this cycling company named cymour come with their bicycles and allow us to cycle for a while, I really liked the bicycles they had got and riding them was pleasure. Post the ride I felt that I should own one of a kind, and had decided to buy one.
    I started inquiring about different bicycle brands and evaluated the different models available, had restricted my budget to 7-8k. I made a list of bicycles that I liked as well in my budget. Unfortunately the models I had listed down turned out to be fancy ones (with dual shocks and dual disc brakes that can give up anytime) that are mostly used by kids, a friend of mine (a cycling enthusiast) explained to me that models I selected were not durable and highly unreliable for long run, and that I should go for bicycles with rigid frames (no shocks) and frame material must be made up of alloy not steel. Bicycles made of alloy frames are much lighter than others.
    Started my research all over again and now the budget had to be almost doubled, since the models that I was now looking for were expensive ones. First choice in my new list (I guess everyone's is) was Btwin Rockrider 5.0 which costs around 9k plus 1k for some important accessories (that are not a part of bicycle), despite the bicycle being great it did not appeal to me much. The bicycle had large frame but the handle was very low so I had to bend a lot and plus it did not have rapid gear shifters from shimano (which is must have).
   My next choice was Hercules Act 110, this ones from BSA an Indian manufacturer and I must say the looks really impressed me, the frame is made of alloy and has rapid gear shifters from shimano. I liked this one so much that unconsciously I had decided to buy it and did not like a single bike that I saw after this one. But the price was a major hindrance for me, the site quotes the price to be 16.5k which was way out of my league, after roaming around a few days I struck a great deal, the guy agreed to 13.2k without a single penny less. Although a bit expensive than what I had planned for a think I have made a prudent decision in the long run. I am really enjoying the ride to and fro home and office (just once a week for now :) ).

Happy Cycling!!!

Sunday, May 19, 2013

Managing Audio Focus - Android

Was just googling around how to manage the media player in an android application when a call or sms arrives, and stumbled upon this very interesting and important concept of managing audio focus...........

I have taken this directly from the documentation available at developer.android.com, as the explanation is very lucid out here.........thus saving me from the trouble of retyping it...:)

With multiple apps potentially playing audio it's important to think about how they should interact. To avoid every music app playing at the same time, Android uses audio focus to moderate audio playback—only apps that hold the audio focus should play audio.
Before your app starts playing audio it should request—and receive—the audio focus. Likewise, it should know how to listen for a loss of audio focus and respond appropriately when that happens.

Request the Audio Focus


Before your app starts playing any audio, it should hold the audio focus for the stream it will be using. This is done with a call to requestAudioFocus() which returns AUDIOFOCUS_REQUEST_GRANTED if your request is successful.
You must specify which stream you're using and whether you expect to require transient or permanent audio focus. Request transient focus when you expect to play audio for only a short time (for example when playing navigation instructions). Request permanent audio focus when you plan to play audio for the foreseeable future (for example, when playing music).
The following snippet requests permanent audio focus on the music audio stream. You should request the audio focus immediately before you begin playback, such as when the user presses play or the background music for the next game level begins.
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);
   if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}
 

Once you've finished playback be sure to call abandonAudioFocus(). This notifies the system that you no longer require focus and unregisters the associated AudioManager.OnAudioFocusChangeListener. In the case of abandoning transient focus, this allows any interupted app to continue playback.

// Abandon audio focus when playback complete am.abandonAudioFocus(afChangeListener);

When requesting transient audio focus you have an additional option: whether or not you want to enable "ducking." Normally, when a well-behaved audio app loses audio focus it immediately silences its playback. By requesting a transient audio focus that allows ducking you tell other audio apps that it’s acceptable for them to keep playing, provided they lower their volume until the focus returns to them.
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                     // Use the music stream.
                      AudioManager.STREAM_MUSIC,
                     // Request permanent focus.
                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
   if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback.
}
Ducking is particularly suitable for apps that use the audio stream intermittently, such as for audible driving directions.
Whenever another app requests audio focus as described above, its choice between permanent and transient (with or without support for ducking) audio focus is received by the listener you registered when requesting focus.

Handle the Loss of Audio Focus


If your app can request audio focus, it follows that it will in turn lose that focus when another app requests it. How your app responds to a loss of audio focus depends on the manner of that loss.
The onAudioFocusChange() callback method of they audio focus change listener you registered when requesting audio focus receives a parameter that describes the focus change event. Specifically, the possible focus loss events mirror the focus request types from the previous section—permanent loss, transient loss, and transient with ducking permitted.
Generally speaking, a transient (temporary) loss of audio focus should result in your app silencing it’s audio stream, but otherwise maintaining the same state. You should continue to monitor changes in audio focus and be prepared to resume playback where it was paused once you’ve regained the focus.
If the audio focus loss is permanent, it’s assumed that another application is now being used to listen to audio and your app should effectively end itself. In practical terms, that means stopping playback, removing media button listeners—allowing the new audio player to exclusively handle those events—and abandoning your audio focus. At that point, you would expect a user action (pressing play in your app) to be required before you resume playing audio.
In the following code snippet, we pause the playback or our media player object if the audio loss is transient and resume it when we have regained the focus. If the loss is permanent, it unregisters our media button event receiver and stops monitoring audio focus changes.

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
            // Pause playback
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Resume playback 
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
            am.abandonAudioFocus(afChangeListener);
            // Stop playback
        }
    }
};
In the case of a transient loss of audio focus where ducking is permitted, rather than pausing playback, you can "duck" instead.

Duck!


Ducking is the process of lowering your audio stream output volume to make transient audio from another app easier to hear without totally disrupting the audio from your own application.
In the following code snippet lowers the volume on our media player object when we temporarily lose focus, then returns it to its previous level when we regain focus.
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
            // Lower the volume
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Raise it back to normal
        }
    }
};
A loss of audio focus is the most important broadcast to react to, but not the only one. The system broadcasts a number of intents to alert you to changes in user’s audio experience. The next lesson demonstrates how to monitor them to improve the user’s overall experience.


For more detailed explanation around Managing Audio Playback you can visit http://developer.android.com/training/managing-audio/audio-focus.html