native-media-jni.c revision 5b21a0626e173d407aa3835e5cffcaa9b582016d
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> 23c09fe859aabccb8b18e6c857d087686b37d48c1fJean-Michel Trivi 249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include "OMXAL/OpenMAXAL.h" 252f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi#include "OMXAL/OpenMAXAL_Android.h" 26c09fe859aabccb8b18e6c857d087686b37d48c1fJean-Michel Trivi 2773d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi#include <android/native_window_jni.h> 289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten// define as 1 if ANativeWindow * is not supported as a video sink 3013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#define NO_NATIVE_WINDOW 1 3113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// engine interfaces 339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf engineObject = NULL; 349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAEngineItf engineEngine; 359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// output mix interfaces 379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf outputMixObject = NULL; 389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// streaming media player interfaces 402f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAObjectItf playerObj = NULL; 412f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAPlayItf playerPlayItf = NULL; 422f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAAndroidBufferQueueItf playerBQItf = NULL; 43f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// number of required interfaces for the MediaPlayer creation 44f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define NB_MAXAL_INTERFACES 2 // XAAndroidBufferQueueItf and XAPlayItf 459a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 4673d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi// cached surface where the video display happens 4713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 4813a07de046bce3663b905a892dbaf770a54d982dGlenn Kastenstatic jobject theSurfaceOrSurfaceTexture; 4913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 5073d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivistatic ANativeWindow* theNativeWindow; 5113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 53f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// number of buffers in our buffer queue 54f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define NB_BUFFERS 16 55f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// we're streaming MPEG-2 transport stream data, operate on transport stream block size 56f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define MPEG2_TS_BLOCK_SIZE 188 57f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// determines how much memory we're dedicating to memory caching 58f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define BUFFER_SIZE 20*MPEG2_TS_BLOCK_SIZE // 20 is an arbitrary number chosen here 59f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 60f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// where we cache in memory the data to play 61f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivichar dataCache[BUFFER_SIZE * NB_BUFFERS]; 622f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// handle of the file to play 632f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviFILE *file; 645b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi// has the app reached the end of the file 655b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivichar reachedEof = 0; 662f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 672f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// AndroidBufferQueueItf callback for an audio player 682f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviXAresult AndroidBufferQueueCallback( 692f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAAndroidBufferQueueItf caller, 70f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi void *pContext, /* input */ 71f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi const void *pBufferData, /* input */ 72f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 dataSize, /* input */ 73f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 dataUsed, /* input */ 74f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi const XAAndroidBufferItem *pItems,/* input */ 75f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 itemsLength /* input */) 762f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi{ 77f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // assert(BUFFER_SIZE <= dataSize); 78f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE, file); 79f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi if (nbRead > 0) { 80f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi (*caller)->Enqueue(caller, 81f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi pBufferData /*pData*/, 82f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi nbRead /*dataLength*/, 83f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi NULL /*pMsg*/, 84f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 0 /*msgLength*/); 855b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi } else if (!reachedEof) { 86f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // signal EOS 87f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAAndroidBufferItem msgEos; 88f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi msgEos.itemKey = XA_ANDROID_ITEMKEY_EOS; 89f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi msgEos.itemSize = 0; 90f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // EOS message has no parameters, so the total size of the message is the size of the key 91f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // plus the size if itemSize, both XAuint32 92f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi (*caller)->Enqueue(caller, NULL /*pData*/, 0 /*dataLength*/, 93f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi &msgEos /*pMsg*/, 94f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi sizeof(XAuint32)*2 /*msgLength*/); 955b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi reachedEof = 1; 962f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 972f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 982f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return XA_RESULT_SUCCESS; 992f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi} 1002f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1012f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1029a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create the engine and output mix objects 1039a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) 1049a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 1052f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 1069a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1079a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create engine 1082f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 1092f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the engine 1122f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 1132f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1149a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1159a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the engine interface, which is needed in order to create other objects 1162f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 1172f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1189a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1199a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create output mix 1202f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 1212f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the output mix 1242f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 1252f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1279a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 1289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create streaming media player 1319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, 1329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jstring filename) 1339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 1342f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 1359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // convert Java string to UTF-8 1379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); 1389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten assert(NULL != utf8); 1399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1402f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // open the file to play 1412f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi file = fopen(utf8, "rb"); 1422f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file == NULL) { 1432f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi LOGE("Failed to open %s", utf8); 1442f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return JNI_FALSE; 1452f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 1462f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1472f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // configure data source 148f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS }; 149f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataFormat_MIME format_mime = { 150f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XA_DATAFORMAT_MIME, (XAchar *)"video/mp2ts", XA_CONTAINERTYPE_MPEG_TS }; 1512f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XADataSource dataSrc = {&loc_abq, &format_mime}; 1529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1539a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure audio sink 154f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject }; 155f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataSink audioSnk = { &loc_outmix, NULL }; 1569a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1579a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure image video sink 15873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi XADataLocator_NativeDisplay loc_nd = { 15913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten XA_DATALOCATOR_NATIVEDISPLAY, // locatorType 16013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 16113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void *) theSurfaceOrSurfaceTexture, // jobject 16213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void *) env // JNIEnv *env 16313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 16413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // later the video sink can be an ANativeWindow created from a Surface or SurfaceTexture 16513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void*)theNativeWindow, // hWindow 16613a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // must be NULL 16713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten NULL // hDisplay 16813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 16913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten }; 1709a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataSink imageVideoSink = {&loc_nd, NULL}; 1719a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1722f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // declare interfaces to use 173f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAboolean required[NB_MAXAL_INTERFACES] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; 174f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAInterfaceID iidArray[NB_MAXAL_INTERFACES] = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUE}; 1752f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create media player 1772f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, 1782f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi NULL, &audioSnk, &imageVideoSink, NULL, NULL, 179f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/, 1802f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi iidArray /*const XAInterfaceID *pInterfaceIds*/, 1812f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi required /*const XAboolean *pInterfaceRequired*/); 1822f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1839a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1849a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // release the Java string and UTF-8 1859a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*env)->ReleaseStringUTFChars(env, filename, utf8); 1869a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1879a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the player 1882f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); 1892f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1909a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1919a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the play interface 1922f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); 1932f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1942f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1952f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // get the Android buffer queue interface 1962f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf); 1972f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1982f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1992f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // register the callback from which OpenMAX AL can retrieve the data to play 200f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, NULL); 201f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 202f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi /* Fill our cache */ 203f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi if (fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file) <= 0) { 204f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi LOGE("Error filling cache, exiting\n"); 205f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi return JNI_FALSE; 206f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi } 207f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi /* Enqueue the content of our cache before starting to play, 208f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi we don't want to starve the player */ 209f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi int i; 210f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi for (i=0 ; i < NB_BUFFERS ; i++) { 211f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi res = (*playerBQItf)->Enqueue(playerBQItf, dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0); 212f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 213f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi } 214f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 2152f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 2162f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // prepare the player 2172f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); 2182f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2192f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 2202f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); 2212f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten return JNI_TRUE; 2249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 2259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2279a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the playing state for the streaming media player 2289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, 2299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jboolean isPlaying) 2309a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 2312f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 2329a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // make sure the streaming media player was created 2342f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (NULL != playerPlayItf) { 2359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // set the player's state 2372f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? 2389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); 2392f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2409a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2419a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2429a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2439a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 2449a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2459a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2469a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// shut down the native media system 2479a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) 2489a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 2499a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy streaming media player object, and invalidate all associated interfaces 2502f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (playerObj != NULL) { 2512f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi (*playerObj)->Destroy(playerObj); 2522f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerObj = NULL; 2532f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerPlayItf = NULL; 2542f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerBQItf = NULL; 2559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2569a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2579a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy output mix object, and invalidate all associated interfaces 2589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (outputMixObject != NULL) { 2599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*outputMixObject)->Destroy(outputMixObject); 2609a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten outputMixObject = NULL; 2619a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2629a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2639a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy engine object, and invalidate all associated interfaces 2649a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (engineObject != NULL) { 2659a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*engineObject)->Destroy(engineObject); 2669a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineObject = NULL; 2679a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineEngine = NULL; 2689a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 2699a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2702f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // close the file 2712f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file != NULL) { 2722f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi fclose(file); 2732f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 27473d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi 27513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if !NO_NATIVE_WINDOW 27673d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // make sure we don't leak native windows 27713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten if (theNativeWindow != NULL) { 27813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten ANativeWindow_release(theNativeWindow); 27913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten } 28013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 2819a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 2829a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2839a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2849a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the surface 2859a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) 2869a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 28713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 28813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theSurfaceOrSurfaceTexture = surface; 28913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 29073d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // obtain a native window from a Java surface 29173d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi theNativeWindow = ANativeWindow_fromSurface(env, surface); 29213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 29313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten} 29413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 29513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 29613a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten// set the surface texture 29713a07de046bce3663b905a892dbaf770a54d982dGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurfaceTexture(JNIEnv *env, jclass clazz, 29813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten jobject surfaceTexture) 29913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten{ 30013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 30113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theSurfaceOrSurfaceTexture = surfaceTexture; 30213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 30313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // obtain a native window from a Java surface texture 30413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theNativeWindow = ANativeWindow_fromSurfaceTexture(env, surfaceTexture); 30513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 3069a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 307