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