native-media-jni.c revision ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8
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 29ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten// define as 1 if ANativeWindow * is not supported as a video sink 30ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#define NO_NATIVE_WINDOW 1 31ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 3297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// engine interfaces 3397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf engineObject = NULL; 3497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAEngineItf engineEngine; 3597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 3697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// output mix interfaces 3797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenstatic XAObjectItf outputMixObject = NULL; 3897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 3997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// streaming media player interfaces 40eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAObjectItf playerObj = NULL; 41eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAPlayItf playerPlayItf = NULL; 42eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivistatic XAAndroidBufferQueueItf playerBQItf = NULL; 43d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi// number of required interfaces for the MediaPlayer creation 44d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi#define NB_MAXAL_INTERFACES 2 // XAAndroidBufferQueueItf and XAPlayItf 4597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 46295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi// cached surface where the video display happens 47ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#if NO_NATIVE_WINDOW 48ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kastenstatic jobject theSurfaceOrSurfaceTexture; 49ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#else 50295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivistatic ANativeWindow* theNativeWindow; 51ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#endif 5297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 53d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi// number of buffers in our buffer queue 54d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi#define NB_BUFFERS 16 55d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi// we're streaming MPEG-2 transport stream data, operate on transport stream block size 56d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi#define MPEG2_TS_BLOCK_SIZE 188 57d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi// determines how much memory we're dedicating to memory caching 58d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi#define BUFFER_SIZE 20*MPEG2_TS_BLOCK_SIZE // 20 is an arbitrary number chosen here 59d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 60d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi// where we cache in memory the data to play 61d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivichar dataCache[BUFFER_SIZE * NB_BUFFERS]; 62eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi// handle of the file to play 63eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel TriviFILE *file; 64eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 65eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi// AndroidBufferQueueItf callback for an audio player 66eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel TriviXAresult AndroidBufferQueueCallback( 67eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAAndroidBufferQueueItf caller, 68d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi void *pContext, /* input */ 69d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi const void *pBufferData, /* input */ 70d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAuint32 dataSize, /* input */ 71d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAuint32 dataUsed, /* input */ 72d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi const XAAndroidBufferItem *pItems,/* input */ 73d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAuint32 itemsLength /* input */) 74eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi{ 75d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi // assert(BUFFER_SIZE <= dataSize); 76d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE, file); 77d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (nbRead > 0) { 78d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi (*caller)->Enqueue(caller, 79d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi pBufferData /*pData*/, 80d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi nbRead /*dataLength*/, 81d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi NULL /*pMsg*/, 82d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 0 /*msgLength*/); 83eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } else { 84d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi // signal EOS 85d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAAndroidBufferItem msgEos; 86d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi msgEos.itemKey = XA_ANDROID_ITEMKEY_EOS; 87d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi msgEos.itemSize = 0; 88d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi // EOS message has no parameters, so the total size of the message is the size of the key 89d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi // plus the size if itemSize, both XAuint32 90d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi (*caller)->Enqueue(caller, NULL /*pData*/, 0 /*dataLength*/, 91d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi &msgEos /*pMsg*/, 92d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi sizeof(XAuint32)*2 /*msgLength*/); 93eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 94eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 95eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return XA_RESULT_SUCCESS; 96eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi} 97eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 98eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 9997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create the engine and output mix objects 10097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) 10197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 102eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 10397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create engine 105eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 106eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 10797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 10897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the engine 109eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 110eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 11197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 11297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // get the engine interface, which is needed in order to create other objects 113eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 114eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 11597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 11697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create output mix 117eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 118eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 11997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 12097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the output mix 121eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 122eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 12397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 12497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 12597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 12697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 12797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// create streaming media player 12897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, 12997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten jclass clazz, jstring filename) 13097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 131eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 13297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 13397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // convert Java string to UTF-8 13497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); 13597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten assert(NULL != utf8); 13697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 137eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // open the file to play 138eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi file = fopen(utf8, "rb"); 139eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (file == NULL) { 140eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi LOGE("Failed to open %s", utf8); 141eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return JNI_FALSE; 142eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 143eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 144eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // configure data source 145d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS }; 146d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XADataFormat_MIME format_mime = { 147d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XA_DATAFORMAT_MIME, (XAchar *)"video/mp2ts", XA_CONTAINERTYPE_MPEG_TS }; 148eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XADataSource dataSrc = {&loc_abq, &format_mime}; 14997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 15097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // configure audio sink 151d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject }; 152d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XADataSink audioSnk = { &loc_outmix, NULL }; 15397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 15497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // configure image video sink 155295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi XADataLocator_NativeDisplay loc_nd = { 156ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten XA_DATALOCATOR_NATIVEDISPLAY, // locatorType 157ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#if NO_NATIVE_WINDOW 158ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten (void *) theSurfaceOrSurfaceTexture, // jobject 159ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten (void *) env // JNIEnv *env 160ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#else 161ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten // later the video sink can be an ANativeWindow created from a Surface or SurfaceTexture 162ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten (void*)theNativeWindow, // hWindow 163ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten // must be NULL 164ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten NULL // hDisplay 165ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#endif 166ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten }; 16797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XADataSink imageVideoSink = {&loc_nd, NULL}; 16897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 169eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // declare interfaces to use 170d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAboolean required[NB_MAXAL_INTERFACES] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; 171d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi XAInterfaceID iidArray[NB_MAXAL_INTERFACES] = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUE}; 172eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 17397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // create media player 174eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, 175eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi NULL, &audioSnk, &imageVideoSink, NULL, NULL, 176d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/, 177eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi iidArray /*const XAInterfaceID *pInterfaceIds*/, 178eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi required /*const XAboolean *pInterfaceRequired*/); 179eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 18097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // release the Java string and UTF-8 18297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*env)->ReleaseStringUTFChars(env, filename, utf8); 18397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // realize the player 185eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); 186eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 18797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 18897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // get the play interface 189eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); 190eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 191eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 192eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // get the Android buffer queue interface 193eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf); 194eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 195eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 196eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // register the callback from which OpenMAX AL can retrieve the data to play 197d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, NULL); 198d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 199d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi /* Fill our cache */ 200d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file) <= 0) { 201d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi LOGE("Error filling cache, exiting\n"); 202d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi return JNI_FALSE; 203d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 204d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi /* Enqueue the content of our cache before starting to play, 205d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi we don't want to starve the player */ 206d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi int i; 207d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi for (i=0 ; i < NB_BUFFERS ; i++) { 208d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi res = (*playerBQItf)->Enqueue(playerBQItf, dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0); 209d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 210d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 211d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 212eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 213eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // prepare the player 214eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); 215eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 216eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 217eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); 218eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 21997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 22097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten return JNI_TRUE; 22197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 22297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 22397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 22497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the playing state for the streaming media player 22597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, 22697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten jclass clazz, jboolean isPlaying) 22797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 228eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi XAresult res; 22997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 23097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // make sure the streaming media player was created 231eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (NULL != playerPlayItf) { 23297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 23397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // set the player's state 234eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? 23597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); 236eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 23797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 23897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 23997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 24097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 24197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 24297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 24397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// shut down the native media system 24497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) 24597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 24697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy streaming media player object, and invalidate all associated interfaces 247eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (playerObj != NULL) { 248eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi (*playerObj)->Destroy(playerObj); 249eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerObj = NULL; 250eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerPlayItf = NULL; 251eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi playerBQItf = NULL; 25297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 25397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 25497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy output mix object, and invalidate all associated interfaces 25597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten if (outputMixObject != NULL) { 25697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*outputMixObject)->Destroy(outputMixObject); 25797bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten outputMixObject = NULL; 25897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 25997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 26097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten // destroy engine object, and invalidate all associated interfaces 26197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten if (engineObject != NULL) { 26297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten (*engineObject)->Destroy(engineObject); 26397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten engineObject = NULL; 26497bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten engineEngine = NULL; 26597bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten } 26697bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 267eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi // close the file 268eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (file != NULL) { 269eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi fclose(file); 270eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 271295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi 272ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#if !NO_NATIVE_WINDOW 273295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // make sure we don't leak native windows 274ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten if (theNativeWindow != NULL) { 275ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten ANativeWindow_release(theNativeWindow); 276ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten } 277ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#endif 27897bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 27997bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 28097bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten 28197bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten// set the surface 28297bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) 28397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten{ 284ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#if NO_NATIVE_WINDOW 285ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten theSurfaceOrSurfaceTexture = surface; 286ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#else 287295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi // obtain a native window from a Java surface 288295395c087000a9d804f8d12d58dea4cd9e7d26aJean-Michel Trivi theNativeWindow = ANativeWindow_fromSurface(env, surface); 289ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#endif 290ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten} 291ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 292ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 293ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten// set the surface texture 294ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurfaceTexture(JNIEnv *env, jclass clazz, 295ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten jobject surfaceTexture) 296ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten{ 297ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#if NO_NATIVE_WINDOW 298ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten theSurfaceOrSurfaceTexture = surfaceTexture; 299ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#else 300ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten // obtain a native window from a Java surface texture 301ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten theNativeWindow = ANativeWindow_fromSurfaceTexture(env, surfaceTexture); 302ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten#endif 30397bdbe13fc48640babe6c1ce270660476f04c3dfGlenn Kasten} 304