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