native-media-jni.c revision 9a709c6410ac6fd3da51dd02dda72071c5bb9310
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>
239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include "OMXAL/OpenMAXAL.h"
249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// engine interfaces
269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf engineObject = NULL;
279a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAEngineItf engineEngine;
289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// output mix interfaces
309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf outputMixObject = NULL;
319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// streaming media player interfaces
339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf streamingPlayerObject = NULL;
349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAPlayItf streamingPlayerPlay;
359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// cached surface
379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic jobject theSurface;
389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic JNIEnv *theEnv;
399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
409a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create the engine and output mix objects
419a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz)
429a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{
439a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XAresult result;
449a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
459a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // create engine
469a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
479a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
489a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
499a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // realize the engine
509a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE);
519a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
539a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // get the engine interface, which is needed in order to create other objects
549a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine);
559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
569a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
579a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // create output mix
589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
609a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
619a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // realize the output mix
629a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE);
639a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
649a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
659a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten}
669a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
679a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
689a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create streaming media player
699a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env,
709a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        jclass clazz, jstring filename)
719a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{
729a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XAresult result;
739a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
749a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // convert Java string to UTF-8
759a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL);
769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(NULL != utf8);
779a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
789a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // configure audio source
799a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataLocator_URI loc_uri = {XA_DATALOCATOR_URI, (XAchar *) utf8};
809a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataFormat_MIME format_mime = {XA_DATAFORMAT_MIME, NULL, XA_CONTAINERTYPE_UNSPECIFIED};
819a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataSource dataSrc = {&loc_uri, &format_mime};
829a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
839a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // configure audio sink
849a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataLocator_OutputMix loc_outmix = {XA_DATALOCATOR_OUTPUTMIX, outputMixObject};
859a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataSink audioSnk = {&loc_outmix, NULL};
869a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
879a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // configure image video sink
889a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataLocator_NativeDisplay loc_nd = {XA_DATALOCATOR_NATIVEDISPLAY, theSurface, theEnv};
899a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XADataSink imageVideoSink = {&loc_nd, NULL};
909a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
919a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // create media player
929a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*engineEngine)->CreateMediaPlayer(engineEngine, &streamingPlayerObject, &dataSrc,
939a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten            NULL, &audioSnk, &imageVideoSink, NULL, NULL, 0, NULL, NULL);
949a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
959a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
969a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // release the Java string and UTF-8
979a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    (*env)->ReleaseStringUTFChars(env, filename, utf8);
989a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
999a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // realize the player
1009a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*streamingPlayerObject)->Realize(streamingPlayerObject, XA_BOOLEAN_FALSE);
1019a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
1029a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1039a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // get the play interface
1049a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    result = (*streamingPlayerObject)->GetInterface(streamingPlayerObject, XA_IID_PLAY,
1059a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten            &streamingPlayerPlay);
1069a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    assert(XA_RESULT_SUCCESS == result);
1079a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1089a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    return JNI_TRUE;
1099a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten}
1109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1129a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the playing state for the streaming media player
1139a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env,
1149a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        jclass clazz, jboolean isPlaying)
1159a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{
1169a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    XAresult result;
1179a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1189a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // make sure the streaming media player was created
1199a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    if (NULL != streamingPlayerPlay) {
1209a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1219a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        // set the player's state
1229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        result = (*streamingPlayerPlay)->SetPlayState(streamingPlayerPlay, isPlaying ?
1239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten            XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED);
1249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        assert(XA_RESULT_SUCCESS == result);
1259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    }
1279a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten}
1299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// shut down the native media system
1329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz)
1339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{
1349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // destroy streaming media player object, and invalidate all associated interfaces
1369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    if (streamingPlayerObject != NULL) {
1379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        (*streamingPlayerObject)->Destroy(streamingPlayerObject);
1389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        streamingPlayerObject = NULL;
1399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        streamingPlayerPlay = NULL;
1409a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    }
1419a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1429a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // destroy output mix object, and invalidate all associated interfaces
1439a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    if (outputMixObject != NULL) {
1449a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        (*outputMixObject)->Destroy(outputMixObject);
1459a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        outputMixObject = NULL;
1469a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    }
1479a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1489a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    // destroy engine object, and invalidate all associated interfaces
1499a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    if (engineObject != NULL) {
1509a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        (*engineObject)->Destroy(engineObject);
1519a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        engineObject = NULL;
1529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten        engineEngine = NULL;
1539a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    }
1549a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten}
1569a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1579a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten
1589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the surface
1599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface)
1609a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{
1619a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    theEnv = env;
1629a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten    theSurface = surface;
1639a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten}
164