native-media-jni.c revision fcc996296bdbf6c3949ad4312991fdde4ae2e157
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> 21fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi#define LOG_NDEBUG 0 229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#define LOG_TAG "NativeMedia" 239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include <utils/Log.h> 24c09fe859aabccb8b18e6c857d087686b37d48c1fJean-Michel Trivi 259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten#include "OMXAL/OpenMAXAL.h" 262f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi#include "OMXAL/OpenMAXAL_Android.h" 27c09fe859aabccb8b18e6c857d087686b37d48c1fJean-Michel Trivi 2873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi#include <android/native_window_jni.h> 299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten// define as 1 if ANativeWindow * is not supported as a video sink 3113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#define NO_NATIVE_WINDOW 1 3213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// engine interfaces 349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf engineObject = NULL; 359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAEngineItf engineEngine; 369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// output mix interfaces 389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenstatic XAObjectItf outputMixObject = NULL; 399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 409a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// streaming media player interfaces 412f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAObjectItf playerObj = NULL; 422f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAPlayItf playerPlayItf = NULL; 432f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivistatic XAAndroidBufferQueueItf playerBQItf = NULL; 44fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivistatic XAStreamInformationItf playerStreamInfoItf = NULL; 45fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivistatic XAVolumeItf playerVolItf; 46f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// number of required interfaces for the MediaPlayer creation 47fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf 489a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 4973d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi// cached surface where the video display happens 5013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 5113a07de046bce3663b905a892dbaf770a54d982dGlenn Kastenstatic jobject theSurfaceOrSurfaceTexture; 5213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 5373d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivistatic ANativeWindow* theNativeWindow; 5413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 56f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// number of buffers in our buffer queue 57f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define NB_BUFFERS 16 58f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// we're streaming MPEG-2 transport stream data, operate on transport stream block size 59f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define MPEG2_TS_BLOCK_SIZE 188 60f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// determines how much memory we're dedicating to memory caching 61f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi#define BUFFER_SIZE 20*MPEG2_TS_BLOCK_SIZE // 20 is an arbitrary number chosen here 62f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 63f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi// where we cache in memory the data to play 64f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivichar dataCache[BUFFER_SIZE * NB_BUFFERS]; 652f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// handle of the file to play 662f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviFILE *file; 675b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi// has the app reached the end of the file 685b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivichar reachedEof = 0; 692f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 702f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi// AndroidBufferQueueItf callback for an audio player 712f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel TriviXAresult AndroidBufferQueueCallback( 722f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAAndroidBufferQueueItf caller, 73fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi void *pCallbackContext, /* input */ 74fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi void *pBufferContext, /* input */ 75fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi void *pBufferData, /* input */ 76f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 dataSize, /* input */ 77f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 dataUsed, /* input */ 78f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi const XAAndroidBufferItem *pItems,/* input */ 79f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAuint32 itemsLength /* input */) 802f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi{ 81f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // assert(BUFFER_SIZE <= dataSize); 82fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if (pBufferData == NULL) { 83fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // this is the case when our buffer with the EOS message has been consumed 84fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi return XA_RESULT_SUCCESS; 85fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 86fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 87fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi#if 0 88fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // sample code to use the XAVolumeItf 89fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAAndroidBufferQueueState state; 90fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*caller)->GetState(caller, &state); 91fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi switch (state.index) { 92fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 300: 93fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetVolumeLevel(playerVolItf, -600); // -6dB 94fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("setting volume to -6dB"); 95fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 96fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 400: 97fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetVolumeLevel(playerVolItf, -1200); // -12dB 98fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("setting volume to -12dB"); 99fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 100fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 500: 101fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetVolumeLevel(playerVolItf, 0); // full volume 102fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("setting volume to 0dB (full volume)"); 103fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 104fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 600: 105fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetMute(playerVolItf, XA_BOOLEAN_TRUE); // mute 106fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("muting player"); 107fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 108fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 700: 109fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetMute(playerVolItf, XA_BOOLEAN_FALSE); // unmute 110fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("unmuting player"); 111fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 112fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 800: 113fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->SetStereoPosition(playerVolItf, -1000); 114fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->EnableStereoPosition(playerVolItf, XA_BOOLEAN_TRUE); 115fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("pan sound to the left (hard-left)"); 116fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 117fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi case 900: 118fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*playerVolItf)->EnableStereoPosition(playerVolItf, XA_BOOLEAN_FALSE); 119fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGV("disabling stereo position"); 120fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 121fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi default: 122fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi break; 123fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 124fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi#endif 125fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 126f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi size_t nbRead = fread((void*)pBufferData, 1, BUFFER_SIZE, file); 127fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if ((nbRead > 0) && (NULL != pBufferData)) { 128fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*caller)->Enqueue(caller, NULL /*pBufferContext*/, 129f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi pBufferData /*pData*/, 130f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi nbRead /*dataLength*/, 131f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi NULL /*pMsg*/, 132f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 0 /*msgLength*/); 1335b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi } else if (!reachedEof) { 134f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // signal EOS 135f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XAAndroidBufferItem msgEos; 136f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi msgEos.itemKey = XA_ANDROID_ITEMKEY_EOS; 137f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi msgEos.itemSize = 0; 138f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // EOS message has no parameters, so the total size of the message is the size of the key 139f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi // plus the size if itemSize, both XAuint32 140fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi (*caller)->Enqueue(caller, NULL /*pBufferContext*/, 141fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi NULL /*pData*/, 0 /*dataLength*/, 142fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi &msgEos /*pMsg*/, 143fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi sizeof(XAuint32)*2 /*msgLength*/); 1445b21a0626e173d407aa3835e5cffcaa9b582016dJean-Michel Trivi reachedEof = 1; 1452f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 1462f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1472f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return XA_RESULT_SUCCESS; 1482f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi} 1492f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 1502f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 151fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivivoid StreamChangeCallback (XAStreamInformationItf caller, 152fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAuint32 eventId, 153fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAuint32 streamIndex, 154fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi void * pEventData, 155fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi void * pContext ) 156fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi{ 157fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if (XA_STREAMCBEVENT_PROPERTYCHANGE == eventId) { 158fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGD("StreamChangeCallback called for stream %lu", streamIndex); 159fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 160fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAuint32 domain; 161fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if (XA_RESULT_SUCCESS == (*caller)->QueryStreamType(caller, streamIndex, &domain)) { 162fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if (XA_DOMAINTYPE_VIDEO == domain) { 163fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAVideoStreamInformation videoInfo; 164fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi if (XA_RESULT_SUCCESS == (*caller)->QueryStreamInformation(caller, streamIndex, 165fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi &videoInfo)) { 166fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi LOGI("Found video size %lu x %lu", videoInfo.width, videoInfo.height); 167fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 168fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 169fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 170fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi } 171fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi} 172fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 173fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 1749a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create the engine and output mix objects 1759a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_createEngine(JNIEnv* env, jclass clazz) 1769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 1772f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 1789a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1799a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create engine 1802f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 1812f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1829a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1839a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the engine 1842f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 1852f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1869a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1879a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the engine interface, which is needed in order to create other objects 1882f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 1892f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1909a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1919a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create output mix 1922f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 1932f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1949a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1959a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the output mix 1962f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 1972f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 1989a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 1999a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 2009a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2019a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2029a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// create streaming media player 2039a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenjboolean Java_com_example_nativemedia_NativeMedia_createStreamingMediaPlayer(JNIEnv* env, 2049a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jstring filename) 2059a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 2062f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 2079a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2089a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // convert Java string to UTF-8 2099a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); 2109a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten assert(NULL != utf8); 2119a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2122f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // open the file to play 2132f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi file = fopen(utf8, "rb"); 2142f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file == NULL) { 2152f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi LOGE("Failed to open %s", utf8); 2162f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi return JNI_FALSE; 2172f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 2182f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 2192f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // configure data source 220f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS }; 221f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataFormat_MIME format_mime = { 222f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XA_DATAFORMAT_MIME, (XAchar *)"video/mp2ts", XA_CONTAINERTYPE_MPEG_TS }; 2232f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XADataSource dataSrc = {&loc_abq, &format_mime}; 2249a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure audio sink 226f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject }; 227f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi XADataSink audioSnk = { &loc_outmix, NULL }; 2289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // configure image video sink 23073d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi XADataLocator_NativeDisplay loc_nd = { 23113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten XA_DATALOCATOR_NATIVEDISPLAY, // locatorType 23213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 23313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void *) theSurfaceOrSurfaceTexture, // jobject 23413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void *) env // JNIEnv *env 23513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 23613a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // later the video sink can be an ANativeWindow created from a Surface or SurfaceTexture 23713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten (void*)theNativeWindow, // hWindow 23813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // must be NULL 23913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten NULL // hDisplay 24013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 24113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten }; 2429a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XADataSink imageVideoSink = {&loc_nd, NULL}; 2439a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2442f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // declare interfaces to use 245fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAboolean required[NB_MAXAL_INTERFACES] 246fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE}; 247fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi XAInterfaceID iidArray[NB_MAXAL_INTERFACES] 248fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUE, XA_IID_STREAMINFORMATION}; 249fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 2502f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 2519a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // create media player 2522f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc, 2532f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi NULL, &audioSnk, &imageVideoSink, NULL, NULL, 254f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/, 2552f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi iidArray /*const XAInterfaceID *pInterfaceIds*/, 2562f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi required /*const XAboolean *pInterfaceRequired*/); 2572f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // release the Java string and UTF-8 2609a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*env)->ReleaseStringUTFChars(env, filename, utf8); 2619a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2629a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // realize the player 2632f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE); 2642f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2659a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 2669a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // get the play interface 2672f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf); 2682f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2692f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 270fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // get the stream information interface (for video size) 271fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_STREAMINFORMATION, &playerStreamInfoItf); 272fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 273fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 274fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // get the volume interface 275fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_VOLUME, &playerVolItf); 276fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 277fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 2782f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // get the Android buffer queue interface 2792f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUE, &playerBQItf); 2802f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 2812f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 2822f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // register the callback from which OpenMAX AL can retrieve the data to play 283f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi res = (*playerBQItf)->RegisterCallback(playerBQItf, AndroidBufferQueueCallback, NULL); 284fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 285fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 286fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // we want to be notified of the video size once it's found, so we register a callback for that 287fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi res = (*playerStreamInfoItf)->RegisterStreamChangeCallback(playerStreamInfoItf, 288fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi StreamChangeCallback, NULL); 289f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 290f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi /* Fill our cache */ 291f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi if (fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file) <= 0) { 292f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi LOGE("Error filling cache, exiting\n"); 293f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi return JNI_FALSE; 294f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi } 295f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi /* Enqueue the content of our cache before starting to play, 296f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi we don't want to starve the player */ 297f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi int i; 298f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi for (i=0 ; i < NB_BUFFERS ; i++) { 299fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/, 300fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi dataCache + i*BUFFER_SIZE, BUFFER_SIZE, NULL, 0); 301f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 302f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi } 303f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi 3042f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // prepare the player 3052f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED); 3062f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 3072f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi 308fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // set the volume 309fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi res = (*playerVolItf)->SetVolumeLevel(playerVolItf, 0);//-300); 310fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 311fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi 312fcc996296bdbf6c3949ad4312991fdde4ae2e157Jean-Michel Trivi // start the playback 3132f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PLAYING); 3142f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 3159a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3169a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten return JNI_TRUE; 3179a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 3189a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3199a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3209a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the playing state for the streaming media player 3219a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setPlayingStreamingMediaPlayer(JNIEnv* env, 3229a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten jclass clazz, jboolean isPlaying) 3239a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 3242f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi XAresult res; 3259a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3269a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // make sure the streaming media player was created 3272f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (NULL != playerPlayItf) { 3289a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3299a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // set the player's state 3302f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi res = (*playerPlayItf)->SetPlayState(playerPlayItf, isPlaying ? 3319a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten XA_PLAYSTATE_PLAYING : XA_PLAYSTATE_PAUSED); 3322f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi assert(XA_RESULT_SUCCESS == res); 3339a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3349a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 3359a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3369a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 3379a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3389a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3399a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// shut down the native media system 3409a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_shutdown(JNIEnv* env, jclass clazz) 3419a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 3429a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy streaming media player object, and invalidate all associated interfaces 3432f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (playerObj != NULL) { 3442f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi (*playerObj)->Destroy(playerObj); 3452f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerObj = NULL; 3462f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerPlayItf = NULL; 3472f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi playerBQItf = NULL; 3489a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 3499a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3509a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy output mix object, and invalidate all associated interfaces 3519a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (outputMixObject != NULL) { 3529a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*outputMixObject)->Destroy(outputMixObject); 3539a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten outputMixObject = NULL; 3549a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 3559a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3569a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten // destroy engine object, and invalidate all associated interfaces 3579a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten if (engineObject != NULL) { 3589a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten (*engineObject)->Destroy(engineObject); 3599a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineObject = NULL; 3609a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten engineEngine = NULL; 3619a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten } 3629a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3632f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi // close the file 3642f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi if (file != NULL) { 3652f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi fclose(file); 3662a1042f54c8e61a0c2a062709367093100ea6f8fGlenn Kasten file = NULL; 3672f4002b9f37501cd15a7e06cd8e19453d2770f30Jean-Michel Trivi } 36873d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi 36913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if !NO_NATIVE_WINDOW 37073d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // make sure we don't leak native windows 37113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten if (theNativeWindow != NULL) { 37213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten ANativeWindow_release(theNativeWindow); 3732a1042f54c8e61a0c2a062709367093100ea6f8fGlenn Kasten theNativeWindow = NULL; 37413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten } 37513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 3769a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 3779a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3789a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten 3799a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten// set the surface 3809a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurface(JNIEnv *env, jclass clazz, jobject surface) 3819a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten{ 38213a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 38313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theSurfaceOrSurfaceTexture = surface; 38413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 38573d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi // obtain a native window from a Java surface 38673d888bb7b15745c6456dc0fab97c39854827d2aJean-Michel Trivi theNativeWindow = ANativeWindow_fromSurface(env, surface); 38713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 38813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten} 38913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 39013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten 39113a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten// set the surface texture 39213a07de046bce3663b905a892dbaf770a54d982dGlenn Kastenvoid Java_com_example_nativemedia_NativeMedia_setSurfaceTexture(JNIEnv *env, jclass clazz, 39313a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten jobject surfaceTexture) 39413a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten{ 39513a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#if NO_NATIVE_WINDOW 39613a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theSurfaceOrSurfaceTexture = surfaceTexture; 39713a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#else 39813a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten // obtain a native window from a Java surface texture 39913a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten theNativeWindow = ANativeWindow_fromSurfaceTexture(env, surfaceTexture); 40013a07de046bce3663b905a892dbaf770a54d982dGlenn Kasten#endif 4019a709c6410ac6fd3da51dd02dda72071c5bb9310Glenn Kasten} 402