diff --git a/ndk/Android.mk b/ndk/Android.mk index 969df044e0b..a6d5f9f1692 100644 --- a/ndk/Android.mk +++ b/ndk/Android.mk @@ -1,4 +1,4 @@ # # This file is (otherwise) empty to deliberately prevent the build system -# from building the samples below this point... +# from building the NDK tests below this point... # diff --git a/ndk/platforms/android-14/samples/native-media/AndroidManifest.xml b/ndk/platforms/android-14/samples/native-media/AndroidManifest.xml deleted file mode 100644 index acecd4ed7f0..00000000000 --- a/ndk/platforms/android-14/samples/native-media/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/ndk/platforms/android-14/samples/native-media/NativeMedia.ts b/ndk/platforms/android-14/samples/native-media/NativeMedia.ts deleted file mode 100644 index a27a514a31b..00000000000 Binary files a/ndk/platforms/android-14/samples/native-media/NativeMedia.ts and /dev/null differ diff --git a/ndk/platforms/android-14/samples/native-media/README.txt b/ndk/platforms/android-14/samples/native-media/README.txt deleted file mode 100644 index f900e31a98d..00000000000 --- a/ndk/platforms/android-14/samples/native-media/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -This sample app requires an MPEG-2 Transport Stream file to be -placed in /sdcard/NativeMedia.ts and encoded as: - - video: H.264 baseline profile - audio: AAC LC stereo - -For demonstration purposes we have supplied such a .ts file. -Any actual stream must be created according to the MPEG-2 specification. diff --git a/ndk/platforms/android-14/samples/native-media/default.properties b/ndk/platforms/android-14/samples/native-media/default.properties deleted file mode 100644 index 2d6991797f1..00000000000 --- a/ndk/platforms/android-14/samples/native-media/default.properties +++ /dev/null @@ -1,4 +0,0 @@ -# Indicates whether an apk should be generated for each density. -split.density=false -# Project target. -target=android-14 diff --git a/ndk/platforms/android-14/samples/native-media/jni/Android.mk b/ndk/platforms/android-14/samples/native-media/jni/Android.mk deleted file mode 100644 index 369ccf83441..00000000000 --- a/ndk/platforms/android-14/samples/native-media/jni/Android.mk +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2011 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := native-media-jni -LOCAL_SRC_FILES := native-media-jni.c -# for native multimedia -LOCAL_LDLIBS += -lOpenMAXAL -# for logging -LOCAL_LDLIBS += -llog -# for native windows -LOCAL_LDLIBS += -landroid - -LOCAL_CFLAGS += -UNDEBUG - -include $(BUILD_SHARED_LIBRARY) diff --git a/ndk/platforms/android-14/samples/native-media/jni/Application.mk b/ndk/platforms/android-14/samples/native-media/jni/Application.mk deleted file mode 100644 index e619d92fccc..00000000000 --- a/ndk/platforms/android-14/samples/native-media/jni/Application.mk +++ /dev/null @@ -1 +0,0 @@ -APP_ABI := all \ No newline at end of file diff --git a/ndk/platforms/android-14/samples/native-media/jni/native-media-jni.c b/ndk/platforms/android-14/samples/native-media/jni/native-media-jni.c deleted file mode 100644 index ad6d8740bb3..00000000000 --- a/ndk/platforms/android-14/samples/native-media/jni/native-media-jni.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This is a JNI example where we use native methods to play video - * using OpenMAX AL. See the corresponding Java source file located at: - * - * src/com/example/nativemedia/NativeMedia/NativeMedia.java - * - * In this example we use assert() for "impossible" error conditions, - * and explicit handling and recovery for more likely error conditions. - */ - -#include -#include -#include -#include -#include - -// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message"); -#include -#define TAG "NativeMedia" -#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) - -// for native media -#include -#include - -// for native window JNI -#include - -// engine interfaces -static XAObjectItf engineObject = NULL; -static XAEngineItf engineEngine = NULL; - -// output mix interfaces -static XAObjectItf outputMixObject = NULL; - -// streaming media player interfaces -static XAObjectItf playerObj = NULL; -static XAPlayItf playerPlayItf = NULL; -static XAAndroidBufferQueueItf playerBQItf = NULL; -static XAStreamInformationItf playerStreamInfoItf = NULL; -static XAVolumeItf playerVolItf = NULL; - -// number of required interfaces for the MediaPlayer creation -#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf - -// video sink for the player -static ANativeWindow* theNativeWindow; - -// number of buffers in our buffer queue, an arbitrary number -#define NB_BUFFERS 8 - -// we're streaming MPEG-2 transport stream data, operate on transport stream block size -#define MPEG2_TS_PACKET_SIZE 188 - -// number of MPEG-2 transport stream blocks per buffer, an arbitrary number -#define PACKETS_PER_BUFFER 10 - -// determines how much memory we're dedicating to memory caching -#define BUFFER_SIZE (PACKETS_PER_BUFFER*MPEG2_TS_PACKET_SIZE) - -// where we cache in memory the data to play -// note this memory is re-used by the buffer queue callback -static char dataCache[BUFFER_SIZE * NB_BUFFERS]; - -// handle of the file to play -static FILE *file; - -// has the app reached the end of the file -static jboolean reachedEof = JNI_FALSE; - -// constant to identify a buffer context which is the end of the stream to decode -static const int kEosBufferCntxt = 1980; // a magic value we can compare against - -// For mutual exclusion between callback thread and application thread(s). -// The mutex protects reachedEof, discontinuity, -// The condition is signalled when a discontinuity is acknowledged. - -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - -// whether a discontinuity is in progress -static jboolean discontinuity = JNI_FALSE; - -static jboolean enqueueInitialBuffers(jboolean discontinuity); - -// AndroidBufferQueueItf callback to supply MPEG-2 TS packets to the media player -static XAresult AndroidBufferQueueCallback( - XAAndroidBufferQueueItf caller, - void *pCallbackContext, /* input */ - void *pBufferContext, /* input */ - void *pBufferData, /* input */ - XAuint32 dataSize, /* input */ - XAuint32 dataUsed, /* input */ - const XAAndroidBufferItem *pItems,/* input */ - XAuint32 itemsLength /* input */) -{ - XAresult res; - int ok; - - // pCallbackContext was specified as NULL at RegisterCallback and is unused here - assert(NULL == pCallbackContext); - - // note there is never any contention on this mutex unless a discontinuity request is active - ok = pthread_mutex_lock(&mutex); - assert(0 == ok); - - // was a discontinuity requested? - if (discontinuity) { - // Note: can't rewind after EOS, which we send when reaching EOF - // (don't send EOS if you plan to play more content through the same player) - if (!reachedEof) { - // clear the buffer queue - res = (*playerBQItf)->Clear(playerBQItf); - assert(XA_RESULT_SUCCESS == res); - // rewind the data source so we are guaranteed to be at an appropriate point - rewind(file); - // Enqueue the initial buffers, with a discontinuity indicator on first buffer - (void) enqueueInitialBuffers(JNI_TRUE); - } - // acknowledge the discontinuity request - discontinuity = JNI_FALSE; - ok = pthread_cond_signal(&cond); - assert(0 == ok); - goto exit; - } - - if ((pBufferData == NULL) && (pBufferContext != NULL)) { - const int processedCommand = *(int *)pBufferContext; - if (kEosBufferCntxt == processedCommand) { - LOGV("EOS was processed\n"); - // our buffer with the EOS message has been consumed - assert(0 == dataSize); - goto exit; - } - } - - // pBufferData is a pointer to a buffer that we previously Enqueued - assert((dataSize > 0) && ((dataSize % MPEG2_TS_PACKET_SIZE) == 0)); - assert(dataCache <= (char *) pBufferData && (char *) pBufferData < - &dataCache[BUFFER_SIZE * NB_BUFFERS]); - assert(0 == (((char *) pBufferData - dataCache) % BUFFER_SIZE)); - - // don't bother trying to read more data once we've hit EOF - if (reachedEof) { - goto exit; - } - - size_t nbRead; - // note we do call fread from multiple threads, but never concurrently - size_t bytesRead; - bytesRead = fread(pBufferData, 1, BUFFER_SIZE, file); - if (bytesRead > 0) { - if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) { - LOGV("Dropping last packet because it is not whole"); - } - size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE; - size_t bufferSize = packetsRead * MPEG2_TS_PACKET_SIZE; - res = (*caller)->Enqueue(caller, NULL /*pBufferContext*/, - pBufferData /*pData*/, - bufferSize /*dataLength*/, - NULL /*pMsg*/, - 0 /*msgLength*/); - assert(XA_RESULT_SUCCESS == res); - } else { - // EOF or I/O error, signal EOS - XAAndroidBufferItem msgEos[1]; - msgEos[0].itemKey = XA_ANDROID_ITEMKEY_EOS; - msgEos[0].itemSize = 0; - // EOS message has no parameters, so the total size of the message is the size of the key - // plus the size if itemSize, both XAuint32 - res = (*caller)->Enqueue(caller, (void *)&kEosBufferCntxt /*pBufferContext*/, - NULL /*pData*/, 0 /*dataLength*/, - msgEos /*pMsg*/, - sizeof(XAuint32)*2 /*msgLength*/); - assert(XA_RESULT_SUCCESS == res); - reachedEof = JNI_TRUE; - } - -exit: - ok = pthread_mutex_unlock(&mutex); - assert(0 == ok); - return XA_RESULT_SUCCESS; -} - - -// callback invoked whenever there is new or changed stream information -static void StreamChangeCallback(XAStreamInformationItf caller, - XAuint32 eventId, - XAuint32 streamIndex, - void * pEventData, - void * pContext ) -{ - LOGV("StreamChangeCallback called for stream %u", streamIndex); - // pContext was specified as NULL at RegisterStreamChangeCallback and is unused here - assert(NULL == pContext); - switch (eventId) { - case XA_STREAMCBEVENT_PROPERTYCHANGE: { - /** From spec 1.0.1: - "This event indicates that stream property change has occurred. - The streamIndex parameter identifies the stream with the property change. - The pEventData parameter for this event is not used and shall be ignored." - */ - - XAresult res; - XAuint32 domain; - res = (*caller)->QueryStreamType(caller, streamIndex, &domain); - assert(XA_RESULT_SUCCESS == res); - switch (domain) { - case XA_DOMAINTYPE_VIDEO: { - XAVideoStreamInformation videoInfo; - res = (*caller)->QueryStreamInformation(caller, streamIndex, &videoInfo); - assert(XA_RESULT_SUCCESS == res); - LOGV("Found video size %u x %u, codec ID=%u, frameRate=%u, bitRate=%u, duration=%u ms", - videoInfo.width, videoInfo.height, videoInfo.codecId, videoInfo.frameRate, - videoInfo.bitRate, videoInfo.duration); - } break; - default: - fprintf(stderr, "Unexpected domain %u\n", domain); - break; - } - } break; - default: - fprintf(stderr, "Unexpected stream event ID %u\n", eventId); - break; - } -} - - -// create the engine and output mix objects -void Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) -{ - XAresult res; - - // create engine - res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); - assert(XA_RESULT_SUCCESS == res); - - // realize the engine - res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); - assert(XA_RESULT_SUCCESS == res); - - // get the engine interface, which is needed in order to create other objects - res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); - assert(XA_RESULT_SUCCESS == res); - - // create output mix - res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); - assert(XA_RESULT_SUCCESS == res); - - // realize the output mix - res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); - assert(XA_RESULT_SUCCESS == res); - -} - - -// Enqueue the initial buffers, and optionally signal a discontinuity in the first buffer -static jboolean enqueueInitialBuffers(jboolean discontinuity) -{ - - /* Fill our cache. - * We want to read whole packets (integral multiples of MPEG2_TS_PACKET_SIZE). - * fread returns units of "elements" not bytes, so we ask for 1-byte elements - * and then check that the number of elements is a multiple of the packet size. - */ - size_t bytesRead; - bytesRead = fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file); - if (bytesRead <= 0) { - // could be premature EOF or I/O error - return JNI_FALSE; - } - if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) { - LOGV("Dropping last packet because it is not whole"); - } - size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE; - LOGV("Initially queueing %zu packets", packetsRead); - - /* Enqueue the content of our cache before starting to play, - we don't want to starve the player */ - size_t i; - for (i = 0; i < NB_BUFFERS && packetsRead > 0; i++) { - // compute size of this buffer - size_t packetsThisBuffer = packetsRead; - if (packetsThisBuffer > PACKETS_PER_BUFFER) { - packetsThisBuffer = PACKETS_PER_BUFFER; - } - size_t bufferSize = packetsThisBuffer * MPEG2_TS_PACKET_SIZE; - XAresult res; - if (discontinuity) { - // signal discontinuity - XAAndroidBufferItem items[1]; - items[0].itemKey = XA_ANDROID_ITEMKEY_DISCONTINUITY; - items[0].itemSize = 0; - // DISCONTINUITY message has no parameters, - // so the total size of the message is the size of the key - // plus the size if itemSize, both XAuint32 - res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/, - dataCache + i*BUFFER_SIZE, bufferSize, items /*pMsg*/, - sizeof(XAuint32)*2 /*msgLength*/); - discontinuity = JNI_FALSE; - } else { - res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/, - dataCache + i*BUFFER_SIZE, bufferSize, NULL, 0); - } - assert(XA_RESULT_SUCCESS == res); - packetsRead -= packetsThisBuffer; - } - - return JNI_TRUE; -} - - -// create streaming media player -jboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, - jclass clazz, jstring filename) -{ - XAresult res; - - // convert Java string to UTF-8 - const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); - assert(NULL != utf8); - - // open the file to play - file = fopen(utf8, "rb"); - if (file == NULL) { - return JNI_FALSE; - } - - // configure data source - XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS }; - XADataFormat_MIME format_mime = { - XA_DATAFORMAT_MIME, XA_ANDROID_MIME_MP2TS, XA_CONTAINERTYPE_MPEG_TS }; - XADataSource dataSrc = {&loc_abq, &format_mime}; - - // configure audio sink - XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject }; - XADataSink audioSnk = { &loc_outmix, NULL }; - - // configure image video sink - XADataLocator_NativeDisplay loc_nd = { - XA_DATALOCATOR_NATIVEDISPLAY, // locatorType - // the video sink must be an ANativeWindow created from a Surface or SurfaceTexture - (void*)theNativeWindow, // hWindow - // must be NULL - NULL // hDisplay - }; - XADataSink imageVideoSink = {&loc_nd, NULL}; - - // declare interfaces to use - XAboolean required[NB_MAXAL_INTERFACES] - = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; - XAInterfaceID iidArray[NB_MAXAL_INTERFACES] - = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUESOURCE, - XA_IID_STREAMINFORMATION}; - - // create media player - res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, - NULL, &audioSnk, &imageVideoSink, NULL, NULL, - NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/, - iidArray /*const XAInterfaceID *pInterfaceIds*/, - required /*const XAboolean *pInterfaceRequired*/); - assert(XA_RESULT_SUCCESS == res); - - // release the Java string and UTF-8 - (*env)->ReleaseStringUTFChars(env, filename, utf8); - - // realize the player - res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); - assert(XA_RESULT_SUCCESS == res); - - // get the play interface - res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); - assert(XA_RESULT_SUCCESS == res); - - // get the stream information interface (for video size) - res = (*playerObj)->GetInterface(playerObj, XA_IID_STREAMINFORMATION, &playerStreamInfoItf); - assert(XA_RESULT_SUCCESS == res); - - // get the volume interface - res = (*playerObj)->GetInterface(playerObj, XA_IID_VOLUME, &playerVolItf); - assert(XA_RESULT_SUCCESS == res); - - // get the Android buffer queue interface - res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUESOURCE, &playerBQItf); - assert(XA_RESULT_SUCCESS == res); - - // specify which events we want to be notified of - res = (*playerBQItf)->SetCallbackEventsMask(playerBQItf, XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED); - assert(XA_RESULT_SUCCESS == res); - - // register the callback from which OpenMAX AL can retrieve the data to play - res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, NULL); - assert(XA_RESULT_SUCCESS == res); - - // we want to be notified of the video size once it's found, so we register a callback for that - res = (*playerStreamInfoItf)->RegisterStreamChangeCallback(playerStreamInfoItf, - StreamChangeCallback, NULL); - assert(XA_RESULT_SUCCESS == res); - - // enqueue the initial buffers - if (!enqueueInitialBuffers(JNI_FALSE)) { - return JNI_FALSE; - } - - // prepare the player - res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); - assert(XA_RESULT_SUCCESS == res); - - // set the volume - res = (*playerVolItf)->SetVolumeLevel(playerVolItf, 0); - assert(XA_RESULT_SUCCESS == res); - - // start the playback - res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); - assert(XA_RESULT_SUCCESS == res); - - return JNI_TRUE; -} - - -// set the playing state for the streaming media player -void Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, - jclass clazz, jboolean isPlaying) -{ - XAresult res; - - // make sure the streaming media player was created - if (NULL != playerPlayItf) { - - // set the player's state - res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? - XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); - assert(XA_RESULT_SUCCESS == res); - - } - -} - - -// shut down the native media system -void Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) -{ - // destroy streaming media player object, and invalidate all associated interfaces - if (playerObj != NULL) { - (*playerObj)->Destroy(playerObj); - playerObj = NULL; - playerPlayItf = NULL; - playerBQItf = NULL; - playerStreamInfoItf = NULL; - playerVolItf = NULL; - } - - // destroy output mix object, and invalidate all associated interfaces - if (outputMixObject != NULL) { - (*outputMixObject)->Destroy(outputMixObject); - outputMixObject = NULL; - } - - // destroy engine object, and invalidate all associated interfaces - if (engineObject != NULL) { - (*engineObject)->Destroy(engineObject); - engineObject = NULL; - engineEngine = NULL; - } - - // close the file - if (file != NULL) { - fclose(file); - file = NULL; - } - - // make sure we don't leak native windows - if (theNativeWindow != NULL) { - ANativeWindow_release(theNativeWindow); - theNativeWindow = NULL; - } -} - - -// set the surface -void Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) -{ - // obtain a native window from a Java surface - theNativeWindow = ANativeWindow_fromSurface(env, surface); -} - - -// rewind the streaming media player -void Java_com_example_nativemedia_NativeMedia_rewindStreamingMediaPlayer(JNIEnv *env, jclass clazz) -{ - XAresult res; - - // make sure the streaming media player was created - if (NULL != playerBQItf && NULL != file) { - // first wait for buffers currently in queue to be drained - int ok; - ok = pthread_mutex_lock(&mutex); - assert(0 == ok); - discontinuity = JNI_TRUE; - // wait for discontinuity request to be observed by buffer queue callback - // Note: can't rewind after EOS, which we send when reaching EOF - // (don't send EOS if you plan to play more content through the same player) - while (discontinuity && !reachedEof) { - ok = pthread_cond_wait(&cond, &mutex); - assert(0 == ok); - } - ok = pthread_mutex_unlock(&mutex); - assert(0 == ok); - } - -} diff --git a/ndk/platforms/android-14/samples/native-media/res/drawable/icon.png b/ndk/platforms/android-14/samples/native-media/res/drawable/icon.png deleted file mode 100644 index a07c69fa5a0..00000000000 Binary files a/ndk/platforms/android-14/samples/native-media/res/drawable/icon.png and /dev/null differ diff --git a/ndk/platforms/android-14/samples/native-media/res/layout/main.xml b/ndk/platforms/android-14/samples/native-media/res/layout/main.xml deleted file mode 100644 index 0e41339adcb..00000000000 --- a/ndk/platforms/android-14/samples/native-media/res/layout/main.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - -