native-media-jni.c revision f183d0fd23f1c0f45ceaf280d404f1b0709a699a
197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten/* 297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * 497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * you may not use this file except in compliance with the License. 697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * You may obtain a copy of the License at 797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * 897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * 1097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * Unless required by applicable law or agreed to in writing, software 1197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * See the License for the specific language governing permissions and 1497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten * limitations under the License. 1597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten */ 1697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 1797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include <assert.h> 1897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include <jni.h> 1997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include <pthread.h> 2097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include <string.h> 2197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#define LOG_TAG "NativeMedia" 2297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include <utils/Log.h> 23f183d0fd23f1c0f45ceaf280d404f1b0709a699aJean-Michel Trivi 2497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include "OMXAL/OpenMAXAL.h" 25eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi#include "OMXAL/OpenMAXAL_Android.h" 26f183d0fd23f1c0f45ceaf280d404f1b0709a699aJean-Michel Trivi 27295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi#include <android/native_window_jni.h> 2897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 2997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// engine interfaces 3097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf engineObject = NULL; 3197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAEngineItf engineEngine; 3297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 3397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// output mix interfaces 3497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf outputMixObject = NULL; 3597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 3697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// streaming media player interfaces 37eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAObjectItf playerObj = NULL; 38eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAPlayItf playerPlayItf = NULL; 39eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAAndroidBufferQueueItf playerBQItf = NULL; 4097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 41295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi// cached surface where the video display happens 42295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivistatic ANativeWindow* theNativeWindow; 4397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 44eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi// handle of the file to play 45eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel TriviFILE *file; 46eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 47eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi// AndroidBufferQueueItf callback for an audio player 48eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel TriviXAresult AndroidBufferQueueCallback( 49eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAAndroidBufferQueueItf caller, 50eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi void *pContext, 51eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAuint32 bufferId, 52eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAuint32 bufferLength, 53eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi void *pBufferDataLocation) 54eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 55eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi{ 56eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi size_t nbRead = fread(pBufferDataLocation, 1, bufferLength, file); 57eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 58eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAAbufferQueueEvent event = XA_ANDROIDBUFFERQUEUE_EVENT_NONE; 59eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (nbRead <= 0) { 60eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi event = XA_ANDROIDBUFFERQUEUE_EVENT_EOS; 61eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } else { 62eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi event = XA_ANDROIDBUFFERQUEUE_EVENT_NONE; // no event to report 63eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 64eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 65eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // enqueue the data right-away because in this example we're reading from a file, so we 66eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // can afford to do that. When streaming from the network, we would write from our cache 67eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // to this queue. 68eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // last param is NULL because we've already written the data in the buffer queue 69eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi (*caller)->Enqueue(caller, bufferId, nbRead, event, NULL); 70eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 71eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return XA_RESULT_SUCCESS; 72eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi} 73eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 74eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 7597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create the engine and output mix objects 7697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) 7797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 78eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 7997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 8097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create engine 81eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 82eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 8397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 8497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the engine 85eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 86eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 8797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 8897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // get the engine interface, which is needed in order to create other objects 89eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 90eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 9197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 9297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create output mix 93eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 94eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 9597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 9697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the output mix 97eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 98eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 9997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 10197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create streaming media player 10497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, 10597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten jclass clazz, jstring filename) 10697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 107eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 10897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // convert Java string to UTF-8 11097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); 11197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten assert(NULL != utf8); 11297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 113eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // open the file to play 114eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi file = fopen(utf8, "rb"); 115eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (file == NULL) { 116eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi LOGE("Failed to open %s", utf8); 117eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return JNI_FALSE; 118eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 119eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 120eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // configure data source 1210e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi XADataLocator_AndroidBufferQueue loc_abq = {XA_DATALOCATOR_ANDROIDBUFFERQUEUE, 1220e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi 0, 0 /* number of buffers and size of queue are ignored for now, subject to change */}; 12397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XADataFormat_MIME format_mime = {XA_DATAFORMAT_MIME, NULL, XA_CONTAINERTYPE_UNSPECIFIED}; 124eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XADataSource dataSrc = {&loc_abq, &format_mime}; 12597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 12697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // configure audio sink 12797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XADataLocator_OutputMix loc_outmix = {XA_DATALOCATOR_OUTPUTMIX, outputMixObject}; 12897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XADataSink audioSnk = {&loc_outmix, NULL}; 12997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 13097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // configure image video sink 131295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi XADataLocator_NativeDisplay loc_nd = { 132295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi XA_DATALOCATOR_NATIVEDISPLAY /* locatorType */, 133295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // currently the video sink only works on ANativeWindow created from a Surface 134295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi (void*)theNativeWindow /* hWindow */, 135295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // ignored here 136295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi 0 /* hDisplay */}; 13797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XADataSink imageVideoSink = {&loc_nd, NULL}; 13897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 139eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // declare interfaces to use 140eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAboolean required[2] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; 141eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAInterfaceID iidArray[2] = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUE}; 142eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 14397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create media player 144eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, 145eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi NULL, &audioSnk, &imageVideoSink, NULL, NULL, 146295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi 2 /*XAuint32 numInterfaces*/, 147eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi iidArray /*const XAInterfaceID *pInterfaceIds*/, 148eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi required /*const XAboolean *pInterfaceRequired*/); 149eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 15097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 15197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // release the Java string and UTF-8 15297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*env)->ReleaseStringUTFChars(env, filename, utf8); 15397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 15497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the player 155eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); 156eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 15797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 15897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // get the play interface 159eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); 160eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 161eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 162eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // get the Android buffer queue interface 163eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf); 164eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 165eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 166eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // register the callback from which OpenMAX AL can retrieve the data to play 167eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, &playerBQItf); 168eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 169eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // prepare the player 170eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); 171eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 172eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 173eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); 174eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 17597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 17697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten return JNI_TRUE; 17797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 17897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 17997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the playing state for the streaming media player 18197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, 18297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten jclass clazz, jboolean isPlaying) 18397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 184eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 18597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // make sure the streaming media player was created 187eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (NULL != playerPlayItf) { 18897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // set the player's state 190eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? 19197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); 192eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 19397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 19497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 19597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 19697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 19797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 19897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 19997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// shut down the native media system 20097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) 20197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 20297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy streaming media player object, and invalidate all associated interfaces 203eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (playerObj != NULL) { 204eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi (*playerObj)->Destroy(playerObj); 205eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerObj = NULL; 206eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerPlayItf = NULL; 207eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerBQItf = NULL; 20897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 20997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 21097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy output mix object, and invalidate all associated interfaces 21197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten if (outputMixObject != NULL) { 21297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*outputMixObject)->Destroy(outputMixObject); 21397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten outputMixObject = NULL; 21497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 21597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 21697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy engine object, and invalidate all associated interfaces 21797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten if (engineObject != NULL) { 21897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*engineObject)->Destroy(engineObject); 21997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten engineObject = NULL; 22097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten engineEngine = NULL; 22197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 22297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 223eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // close the file 224eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (file != NULL) { 225eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi fclose(file); 226eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 227295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi 228295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // make sure we don't leak native windows 229295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi ANativeWindow_release(theNativeWindow); 23097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 23197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 23297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 23397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the surface 23497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) 23597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 236295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // obtain a native window from a Java surface 237295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi theNativeWindow = ANativeWindow_fromSurface(env, surface); 23897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 239