native-media-jni.c revision 97bdbe13fc48640babe6c1ce270660476f04c3df
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>
2397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten#include "OMXAL/OpenMAXAL.h"
2497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
2597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// engine interfaces
2697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf engineObject = NULL;
2797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAEngineItf engineEngine;
2897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
2997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// output mix interfaces
3097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf outputMixObject = NULL;
3197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
3297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// streaming media player interfaces
3397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf streamingPlayerObject = NULL;
3497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAPlayItf streamingPlayerPlay;
3597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
3697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// cached surface
3797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic jobject theSurface;
3897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic JNIEnv *theEnv;
3997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
4097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create the engine and output mix objects
4197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz)
4297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{
4397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XAresult result;
4497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
4597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // create engine
4697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
4797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
4897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
4997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // realize the engine
5097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE);
5197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
5297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
5397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // get the engine interface, which is needed in order to create other objects
5497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine);
5597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
5697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
5797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // create output mix
5897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
5997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
6097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
6197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // realize the output mix
6297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE);
6397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
6497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
6597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten}
6697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
6797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
6897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create streaming media player
6997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env,
7097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        jclass clazz, jstring filename)
7197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{
7297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XAresult result;
7397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
7497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // convert Java string to UTF-8
7597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL);
7697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(NULL != utf8);
7797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
7897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // configure audio source
7997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataLocator_URI loc_uri = {XA_DATALOCATOR_URI, (XAchar *) utf8};
8097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataFormat_MIME format_mime = {XA_DATAFORMAT_MIME, NULL, XA_CONTAINERTYPE_UNSPECIFIED};
8197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataSource dataSrc = {&loc_uri, &format_mime};
8297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
8397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // configure audio sink
8497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataLocator_OutputMix loc_outmix = {XA_DATALOCATOR_OUTPUTMIX, outputMixObject};
8597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataSink audioSnk = {&loc_outmix, NULL};
8697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
8797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // configure image video sink
8897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataLocator_NativeDisplay loc_nd = {XA_DATALOCATOR_NATIVEDISPLAY, theSurface, theEnv};
8997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XADataSink imageVideoSink = {&loc_nd, NULL};
9097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
9197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // create media player
9297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*engineEngine)->CreateMediaPlayer(engineEngine, &streamingPlayerObject, &dataSrc,
9397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten            NULL, &audioSnk, &imageVideoSink, NULL, NULL, 0, NULL, NULL);
9497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
9597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
9697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // release the Java string and UTF-8
9797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    (*env)->ReleaseStringUTFChars(env, filename, utf8);
9897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
9997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // realize the player
10097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*streamingPlayerObject)->Realize(streamingPlayerObject, XA_BOOLEAN_FALSE);
10197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
10297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
10397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // get the play interface
10497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    result = (*streamingPlayerObject)->GetInterface(streamingPlayerObject, XA_IID_PLAY,
10597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten            &streamingPlayerPlay);
10697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    assert(XA_RESULT_SUCCESS == result);
10797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
10897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    return JNI_TRUE;
10997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten}
11097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
11197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
11297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the playing state for the streaming media player
11397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env,
11497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        jclass clazz, jboolean isPlaying)
11597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{
11697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    XAresult result;
11797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
11897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // make sure the streaming media player was created
11997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    if (NULL != streamingPlayerPlay) {
12097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
12197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        // set the player's state
12297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        result = (*streamingPlayerPlay)->SetPlayState(streamingPlayerPlay, isPlaying ?
12397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten            XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED);
12497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        assert(XA_RESULT_SUCCESS == result);
12597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
12697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    }
12797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
12897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten}
12997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
13097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
13197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// shut down the native media system
13297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz)
13397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{
13497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
13597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // destroy streaming media player object, and invalidate all associated interfaces
13697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    if (streamingPlayerObject != NULL) {
13797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        (*streamingPlayerObject)->Destroy(streamingPlayerObject);
13897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        streamingPlayerObject = NULL;
13997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        streamingPlayerPlay = NULL;
14097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    }
14197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
14297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // destroy output mix object, and invalidate all associated interfaces
14397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    if (outputMixObject != NULL) {
14497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        (*outputMixObject)->Destroy(outputMixObject);
14597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        outputMixObject = NULL;
14697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    }
14797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
14897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    // destroy engine object, and invalidate all associated interfaces
14997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    if (engineObject != NULL) {
15097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        (*engineObject)->Destroy(engineObject);
15197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        engineObject = NULL;
15297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten        engineEngine = NULL;
15397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    }
15497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
15597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten}
15697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
15797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten
15897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the surface
15997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface)
16097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{
16197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    theEnv = env;
16297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten    theSurface = surface;
16397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten}
164