native-media-jni.c revision 73d888bb7b15745c6456dc0fab97c39854827d2a
19a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten/* 29a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * Copyright (C) 2010 The Android Open Source Project 39a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * 49a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 59a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * you may not use this file except in compliance with the License. 69a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * You may obtain a copy of the License at 79a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * 89a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 99a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * 109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * Unless required by applicable law or agreed to in writing, software 119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 129a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * See the License for the specific language governing permissions and 149a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten * limitations under the License. 159a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten */ 169a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 179a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <assert.h> 189a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <jni.h> 199a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <pthread.h> 209a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <string.h> 219a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#define LOG_TAG "NativeMedia" 229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <utils/Log.h> 232f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi//FIXME shouldn't be needed here, but needed for declaration of XA_IID_ANDROIDBUFFERQUEUE 242f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi#include "SLES/OpenSLES.h" 252f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi#include "SLES/OpenSLES_Android.h" 269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include "OMXAL/OpenMAXAL.h" 272f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi#include "OMXAL/OpenMAXAL_Android.h" 2873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi#include <android/native_window_jni.h> 299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// engine interfaces 319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf engineObject = NULL; 329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAEngineItf engineEngine; 339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// output mix interfaces 359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf outputMixObject = NULL; 369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// streaming media player interfaces 382f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAObjectItf playerObj = NULL; 392f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAPlayItf playerPlayItf = NULL; 402f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAAndroidBufferQueueItf playerBQItf = NULL; 419a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 4273d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi// cached surface where the video display happens 4373d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivistatic ANativeWindow* theNativeWindow; 449a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 452f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// handle of the file to play 462f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviFILE *file; 472f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 482f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// AndroidBufferQueueItf callback for an audio player 492f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviXAresult AndroidBufferQueueCallback( 502f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAAndroidBufferQueueItf caller, 512f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi void *pContext, 522f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAuint32 bufferId, 532f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAuint32 bufferLength, 542f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi void *pBufferDataLocation) 552f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 562f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi{ 572f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi size_t nbRead = fread(pBufferDataLocation, 1, bufferLength, file); 582f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 592f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAAbufferQueueEvent event = XA_ANDROIDBUFFERQUEUE_EVENT_NONE; 602f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (nbRead <= 0) { 612f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi event = XA_ANDROIDBUFFERQUEUE_EVENT_EOS; 622f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } else { 632f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi event = XA_ANDROIDBUFFERQUEUE_EVENT_NONE; // no event to report 642f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 652f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 662f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // enqueue the data right-away because in this example we're reading from a file, so we 672f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // can afford to do that. When streaming from the network, we would write from our cache 682f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // to this queue. 692f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // last param is NULL because we've already written the data in the buffer queue 702f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi (*caller)->Enqueue(caller, bufferId, nbRead, event, NULL); 712f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 722f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return XA_RESULT_SUCCESS; 732f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi} 742f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 752f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create the engine and output mix objects 779a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) 789a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 792f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 809a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 819a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create engine 822f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 832f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 849a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 859a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the engine 862f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 872f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 889a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 899a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the engine interface, which is needed in order to create other objects 902f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 912f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 929a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 939a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create output mix 942f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 952f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 969a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 979a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the output mix 982f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 992f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1009a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1019a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 1029a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1039a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1049a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create streaming media player 1059a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, 1069a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jstring filename) 1079a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 1082f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 1099a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // convert Java string to UTF-8 1119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); 1129a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten assert(NULL != utf8); 1139a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1142f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // open the file to play 1152f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi file = fopen(utf8, "rb"); 1162f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file == NULL) { 1172f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi LOGE("Failed to open %s", utf8); 1182f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return JNI_FALSE; 1192f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 1202f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1212f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // configure data source 1227f0e925e1a56ab80e60f2381105297184109dbc3Jean-Michel Trivi XADataLocator_AndroidBufferQueue loc_abq = {XA_DATALOCATOR_ANDROIDBUFFERQUEUE, 1237f0e925e1a56ab80e60f2381105297184109dbc3Jean-Michel Trivi 0, 0 /* number of buffers and size of queue are ignored for now, subject to change */}; 1249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataFormat_MIME format_mime = {XA_DATAFORMAT_MIME, NULL, XA_CONTAINERTYPE_UNSPECIFIED}; 1252f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XADataSource dataSrc = {&loc_abq, &format_mime}; 1269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1279a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure audio sink 1289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataLocator_OutputMix loc_outmix = {XA_DATALOCATOR_OUTPUTMIX, outputMixObject}; 1299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataSink audioSnk = {&loc_outmix, NULL}; 1309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure image video sink 13273d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi XADataLocator_NativeDisplay loc_nd = { 13373d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi XA_DATALOCATOR_NATIVEDISPLAY /* locatorType */, 13473d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // currently the video sink only works on ANativeWindow created from a Surface 13573d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi (void*)theNativeWindow /* hWindow */, 13673d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // ignored here 13773d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi 0 /* hDisplay */}; 1389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataSink imageVideoSink = {&loc_nd, NULL}; 1399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1402f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // declare interfaces to use 1412f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAboolean required[2] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; 1422f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAInterfaceID iidArray[2] = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUE}; 1432f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1449a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create media player 1452f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, 1462f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi NULL, &audioSnk, &imageVideoSink, NULL, NULL, 14773d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi 2 /*XAuint32 numInterfaces*/, 1482f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi iidArray /*const XAInterfaceID *pInterfaceIds*/, 1492f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi required /*const XAboolean *pInterfaceRequired*/); 1502f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1519a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // release the Java string and UTF-8 1539a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*env)->ReleaseStringUTFChars(env, filename, utf8); 1549a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the player 1562f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); 1572f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the play interface 1602f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); 1612f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1622f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1632f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // get the Android buffer queue interface 1642f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf); 1652f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1662f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1672f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // register the callback from which OpenMAX AL can retrieve the data to play 1682f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, &playerBQItf); 1692f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1702f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // prepare the player 1712f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); 1722f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1732f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1742f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); 1752f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1779a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten return JNI_TRUE; 1789a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 1799a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1809a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1819a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the playing state for the streaming media player 1829a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, 1839a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jboolean isPlaying) 1849a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 1852f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 1869a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1879a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // make sure the streaming media player was created 1882f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (NULL != playerPlayItf) { 1899a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1909a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // set the player's state 1912f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? 1929a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); 1932f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1949a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1959a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 1969a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1979a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 1989a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1999a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2009a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// shut down the native media system 2019a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) 2029a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 2039a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy streaming media player object, and invalidate all associated interfaces 2042f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (playerObj != NULL) { 2052f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi (*playerObj)->Destroy(playerObj); 2062f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerObj = NULL; 2072f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerPlayItf = NULL; 2082f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerBQItf = NULL; 2099a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy output mix object, and invalidate all associated interfaces 2129a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (outputMixObject != NULL) { 2139a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*outputMixObject)->Destroy(outputMixObject); 2149a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten outputMixObject = NULL; 2159a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2169a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2179a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy engine object, and invalidate all associated interfaces 2189a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (engineObject != NULL) { 2199a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*engineObject)->Destroy(engineObject); 2209a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineObject = NULL; 2219a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineEngine = NULL; 2229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2242f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // close the file 2252f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file != NULL) { 2262f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi fclose(file); 2272f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 22873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi 22973d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // make sure we don't leak native windows 23073d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi ANativeWindow_release(theNativeWindow); 2319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 2329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the surface 2359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) 2369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 23773d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // obtain a native window from a Java surface 23873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi theNativeWindow = ANativeWindow_fromSurface(env, surface); 2399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 240