Build a Mobile Video Chat Framework With Nex Gen Media Server (NGMS) API

0
18
Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  


Introduction

Nex Gen Media Server is best known as a multi-purpose media streaming server to deliver live and stored video to a variety of devices. The same media server can be embedded into a mobile application to facilitate real time video communication. Here we will use the NGMS API to facilitate building a video chat client for Android devices using the Android Software Developer Kit (SDK) and Google Android Native Developer Kit (NDK).

We will use NGMS to provide all of the network transport RTP services, video frame compression and decompression. NGMS will run as a natively compiled shared object used by our Android app. We will use a Java Native Interface (JNI) bridging layer to invoke native methods from Java application code.

Pre-requisistes

This article assumes that you have a basic understanding and at least an intermediate level of experience building Android apps. I will not go over the details of setting up and Android project in an iDE such as Eclipse. If you have previously created Android apps, or at least went through some example tutorials you should be able to utilize this tutorial to create a real-time video streaming client.

If you haven’t already done so, you will need to download the Google Android SDK (Software Developer Kit). In this example I used Revision 15 on a Linux 32bit machine. The java application layer is used to create the actual Android app. The app code will interface with a JNI layer to invoke the NGMS API routines.

You will also need to download the Google Android NDK (Native Developer Kit). In this example I used Revision 6b on a Linux 32bit machine. The NDK will be used for creating the native interface layer which serves as the glue between the native code and Java application code. You should also have a basic understand of the C programming language.

You should first begin by creating a skeleton Android application using an IDE such as Eclipse. In this example, the application will be called ngmsclient. The Java package name will be called com.example.ngmsclient and will target Android OS 2.3 or higher. The root project directory should contain a folder called “jni” which will contain the native sources used to interface with the Java application code. The example below assumes that you have a skeleton Android app working and will show you how to integrate an ExampleChat class into your Android project.

The Native Layer

The NGMS core embedded library is written in C and is packaged as a shared object file. Since the Android OS is based on Linux, the NGMS core library will run natively within your Android application space. You will need to obtain the NGMS core library for Android OS from the ngmsvid.com website. The essential components are the library files libngms.so, libxcode.so, and the header file ngmslib.h. The ngms bundled.so files will be packaged along with your ngmsclient.apk to provide video chat services.

The JNI Layer

We will build a shared library called ngmsglue.so which will serve as the glue between the ngms API and our Java application code. The structure of the Java Native Interface (JNI) directory within your ngmsclient project directory should look like this.

jni/Android.mk

jni/ngmsglue.c

jni/ngms/include/ngmslib.h

jni/ngms/lib/libngms.so

jni/ngms/lib/libxcode.so

ngmsglue.c will contain the code to control NGMS output and input features. The code will maintain two seperate NGMS API contexts, one for stream output parameters and one for stream input parameters. You should notice that the naming convention of each function should match the Java package and class name from where you are invoking the native code.

ngmsStartReceiver is called to initialize the NGMS capture input API to listen on port 5004 for a network video stream encapsulated over MPEG-2 TS. Each successive video frame will be automatically demuxed and decoded into RGB565 pixel format. The complete frame can then be read by calling ngmsReceiveFrame.

ngmsStartSender is called to initialize the NGMS stream output API to output encoded video frames to a remote host over port 5004. ngmsTransmitFrame is called to encode and transmit a single raw frame in NV21 pixel format.

/*

* ngmsglue.c

*

* JNI layer to access the NGMS streaming and capture API

*

*/

#include

#include

#include

#include

#include "ngmslib.h"

/**

* Holds the configuration for the NGMS RTP receiver and decoder

*/

static NGMSLIB_STREAM_PARAMS_T ngmsReceiver;

/**

* Holds the configuration for the NGMS RTP sender and encoder

*/

static NGMSLIB_STREAM_PARAMS_T ngmsSender;

/**

* Starts the NGMS capture service

*/

jint Java_com_example_ngmsclient_ExampleChat_ngmsStartReceiver (JNIEnv* _env, jobject _thiz)

char xcoderConfig[512];

char sdpConfig[512];

int i;

/*

* Before doing anything call ngmslib_open to open the NGMS service

*/

i = ngmslib_open(&ngmsReceiver);

if (i!= NGMS_RC_OK)

__android_log_print(ANDROID_LOG_ERROR, "ngms", "ngmslib_open failed with error %d", i);

return -1;

/*

* Construct an xcoder configuration key value string

*/

sprintf(xcoderConfig, "vc=rgb565,vx=320,vy=240");

/*

* Construct an SDP configuration for the RTP receiver

* Here we setup NGMS to read data over a MPEG-2 Transport Stream.

*/

sprintf(sdpConfig, "sdp://"

"m=video 5004 RTP/AVP 33n"

"a=rtpmap:33 MP2T/90000n"

"a=fmtp:33n");

/*

* Customize the capture configuration parameters

*/

ngmsReceiver.inputs[0] = sdpConfig;

ngmsReceiver.strxcode = xcoderConfig;

ngmsReceiver.islive = 1;

ngmsReceiver.noaud = 1;

/*

* Start the RTP receiver

*/

i = ngmslib_stream(&ngmsReceiver);

if (i!= NGMS_RC_OK)

__android_log_print(ANDROID_LOG_ERROR, "ngms", "ngmslib_stream failed with error %d", i);

ngmslib_close(&ngmsReceiver);

return -1;

return 0;

/**

* Stops the NGMS RTP capture service

*/

jint Java_com_example_ngmsclient_ExampleChat_ngmsStopReceiver (JNIEnv* _env, jobject _thiz)

/*

* Stop the RTP receiver

*/

ngmslib_close(&ngmsReceiver);

return 0;

/**

* NGMS Callback operation which blocks until a complete video frame has been received and decoded

*/

jint Java_com_example_ngmsclient_ExampleChat_ngmsReceiveFrame (JNIEnv* _env, jobject _thiz, jbyteArray frameBytes)

jstring str;

jboolean copy;

jbyte* buffer = (*_env)->GetByteArrayElements(_env, frameBytes, ©);

jsize max = (*_env)->GetArrayLength(_env, frameBytes);

int frameSize;

frameSize = ngmslib_readVidFrame(&ngmsReceiver, buffer, max, NULL);

(*_env)->ReleaseByteArrayElements(_env, frameBytes, buffer, JNI_ABORT);

return frameSize;

/**

* Starts the NGMS streaming service

*/

jint Java_com_example_ngmsclient_ExampleChat_ngmsStartSender (JNIEnv* _env, jobject _thiz, jstring remoteAddress)

char xcoderConfig[512];

char filter[512];

char destination[512];

const char *p;

int i;

Don't miss out!
Subscribe To Newsletter

Receive top technical news, lesson ideas, travel tips and more!

Invalid email address
Give it a try. You can unsubscribe at any time.

Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

LEAVE A REPLY

Please enter your comment!
Please enter your name here