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