175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten/* 275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * 475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * you may not use this file except in compliance with the License. 675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * You may obtain a copy of the License at 775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * 875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * 1075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * Unless required by applicable law or agreed to in writing, software 1175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * See the License for the specific language governing permissions and 1475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * limitations under the License. 1575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten */ 1675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 1775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// OpenMAX AL MediaPlayer command-line player 1875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 1975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <assert.h> 2075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <pthread.h> 2175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <stdio.h> 2275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <stdlib.h> 23b93695922547aecaf67b4e9c0bf1306257ffd54dElliott Hughes#include <string.h> 2475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <fcntl.h> 2575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <sys/mman.h> 2675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <sys/stat.h> 2775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <unistd.h> 2875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <OMXAL/OpenMAXAL.h> 2975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <OMXAL/OpenMAXAL_Android.h> 3075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include "nativewindow.h" 3175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define MPEG2TS_PACKET_SIZE 188 // MPEG-2 transport stream packet size in bytes 3375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PACKETS_PER_BUFFER 20 // Number of MPEG-2 transport stream packets per buffer 3475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define NB_BUFFERS 2 // Number of buffers in Android buffer queue 3675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// MPEG-2 transport stream packet 3875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastentypedef struct { 3975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten char data[MPEG2TS_PACKET_SIZE]; 4075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} MPEG2TS_Packet; 4175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 4275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Globals shared between main thread and buffer queue callback 4375290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenMPEG2TS_Packet *packets; 44b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t totalPackets; // total number of packets in input file 45b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t numPackets; // number of packets to play, defaults to totalPackets - firstPacket 46b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t curPacket; // current packet index 47b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t discPacket; // discontinuity packet index, defaults to no discontinuity requested 48b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t afterDiscPacket; // packet index to switch to after the discontinuity 49b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t firstPacket; // first packet index to be played, defaults to zero 50b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t lastPacket; // last packet index to be played 51b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t formatPacket; // format change packet index, defaults to no format change requested 52b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAmillisecond seekPos = XA_TIME_UNKNOWN; // seek to this position initially 53b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastenint pauseMs = -1; // pause after this many ms into playback 54b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAboolean forceCallbackFailure = XA_BOOLEAN_FALSE; // force callback failures occasionally 55b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAboolean sentEOS = XA_BOOLEAN_FALSE; // whether we have enqueued EOS yet 5675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 5775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// These are extensions to OpenMAX AL 1.0.1 values 5875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 5975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHSTATUS_UNKNOWN ((XAuint32) 0) 6075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHSTATUS_ERROR ((XAuint32) (-1)) 6175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Mutex and condition shared with main program to protect prefetch_status 6375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 6575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 6675290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenXAuint32 prefetch_status = PREFETCHSTATUS_UNKNOWN; 6775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten/* used to detect errors likely to have occured when the OpenMAX AL framework fails to open 6975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond. 7075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten */ 7175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \ 7275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (XA_PREFETCHEVENT_STATUSCHANGE | XA_PREFETCHEVENT_FILLLEVELCHANGE) 7375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 7475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// stream event change callback 75086a6f51a7b12880ed114962136972f89ed70da2Glenn Kastenvoid streamEventChangeCallback(XAStreamInformationItf caller __unused, XAuint32 eventId, 7675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 streamIndex, void *pEventData, void *pContext) 7775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 7875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // context parameter is specified as NULL and is unused here 7975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(NULL == pContext); 8075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten switch (eventId) { 8175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case XA_STREAMCBEVENT_PROPERTYCHANGE: 8275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("XA_STREAMCBEVENT_PROPERTYCHANGE on stream index %u, pEventData %p\n", streamIndex, 8375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pEventData); 8475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 8575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten default: 8675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("Unknown stream event ID %u\n", eventId); 8775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 8875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 8975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 9075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 9175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// prefetch status callback 9275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenvoid prefetchStatusCallback(XAPrefetchStatusItf caller, void *pContext, XAuint32 event) 9375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 9475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pContext is unused here, so we pass NULL 9575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(pContext == NULL); 9675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XApermille level = 0; 9775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 9875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->GetFillLevel(caller, &level); 9975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 10075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 status; 10175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->GetPrefetchStatus(caller, &status); 10275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 10375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (event & XA_PREFETCHEVENT_FILLLEVELCHANGE) { 10475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Buffer fill level is = %d\n", level); 10575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 10675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (event & XA_PREFETCHEVENT_STATUSCHANGE) { 10775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Prefetch Status is = %u\n", status); 10875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 10975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 new_prefetch_status; 11075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 11175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten && (level == 0) && (status == XA_PREFETCHSTATUS_UNDERFLOW)) { 11275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Error while prefetching data, exiting\n"); 11375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten new_prefetch_status = PREFETCHSTATUS_ERROR; 11475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else if (event == XA_PREFETCHEVENT_STATUSCHANGE) { 11575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten new_prefetch_status = status; 11675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 11775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten return; 11875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 11975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int ok; 12075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_mutex_lock(&mutex); 12175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten prefetch_status = new_prefetch_status; 12375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_cond_signal(&cond); 12475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_mutex_unlock(&mutex); 12675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 12875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 12975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// playback event callback 13075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenvoid playEventCallback(XAPlayItf caller, void *pContext, XAuint32 event) 13175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 13275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pContext is unused here, so we pass NULL 13375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(NULL == pContext); 13475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 135b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAresult result; 13675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAmillisecond position; 137b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*caller)->GetPosition(caller, &position); 138b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 13975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 14075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATEND & event) { 141b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATEND current position=%u ms\n", position); 14275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 14375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 14475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATNEWPOS & event) { 145b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATNEWPOS current position=%u ms\n", position); 14675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 14775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 14875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATMARKER & event) { 149b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATMARKER current position=%u ms\n", position); 15075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 15175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 15275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 15375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Android buffer queue callback 15475290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenXAresult bufferQueueCallback( 15575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAAndroidBufferQueueItf caller, 15675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *pCallbackContext, 157086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten void *pBufferContext __unused, 158086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten void *pBufferData __unused, 159086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten XAuint32 dataSize __unused, 160086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten XAuint32 dataUsed __unused, 161086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten const XAAndroidBufferItem *pItems __unused, 162086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten XAuint32 itemsLength __unused) 16375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 164b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAPlayItf playerPlay = (XAPlayItf) pCallbackContext; 16575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the .ts data directly from mapped memory, so ignore the empty buffer pBufferData 166b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket <= lastPacket) { 16762496886cb4620c09bc5df0de70a883319616c25Aurimas Liutikas static const XAAndroidBufferItem discontinuity = {XA_ANDROID_ITEMKEY_DISCONTINUITY, 0, {}}; 16862496886cb4620c09bc5df0de70a883319616c25Aurimas Liutikas static const XAAndroidBufferItem eos = {XA_ANDROID_ITEMKEY_EOS, 0, {}}; 16962496886cb4620c09bc5df0de70a883319616c25Aurimas Liutikas static const XAAndroidBufferItem formatChange = {XA_ANDROID_ITEMKEY_FORMAT_CHANGE, 0, {}}; 17075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const XAAndroidBufferItem *items; 17175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 itemSize; 17275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // compute number of packets to be enqueued in this buffer 173b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 packetsThisBuffer = lastPacket - curPacket; 17475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (packetsThisBuffer > PACKETS_PER_BUFFER) { 17575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packetsThisBuffer = PACKETS_PER_BUFFER; 17675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 17775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // last packet? this should only happen once 178b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket == lastPacket) { 179b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (sentEOS) { 180b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("buffer completion callback after EOS\n"); 181b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return XA_RESULT_SUCCESS; 182b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 183b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending EOS\n"); 18475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = &eos; 18575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = sizeof(eos); 186b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten sentEOS = XA_BOOLEAN_TRUE; 18775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // discontinuity requested? 18875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else if (curPacket == discPacket) { 189b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending discontinuity at packet %zu, then resuming at packet %zu\n", discPacket, 190b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket); 19175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = &discontinuity; 19275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = sizeof(discontinuity); 193b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten curPacket = afterDiscPacket; 194b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // format change requested? 195b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else if (curPacket == formatPacket) { 196b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending format change"); 197b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten items = &formatChange; 198b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten itemSize = sizeof(formatChange); 19975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pure data with no items 20075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 20175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = NULL; 20275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = 0; 20375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 20475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 20575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the optional data and optional items; there is always at least one or the other 20675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(packetsThisBuffer > 0 || itemSize > 0); 20775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->Enqueue(caller, NULL, &packets[curPacket], 20875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten sizeof(MPEG2TS_Packet) * packetsThisBuffer, items, itemSize); 20975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 21075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten curPacket += packetsThisBuffer; 211b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // display position periodically 212b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket % 1000 == 0) { 213b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAmillisecond position; 214b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 215b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 21601f8573bc2a850536b02855d483dfe130c050a2fAshok Bhat printf("Position after enqueueing packet %zu: %u ms\n", curPacket, position); 217b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 218b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 219b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (forceCallbackFailure && (curPacket % 1230 == 0)) { 220b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return (XAresult) curPacket; 221b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 222b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return XA_RESULT_SUCCESS; 223b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 224b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten} 225b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 226b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten// convert a domain type to string 227b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastenstatic const char *domainToString(XAuint32 domain) 228b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten{ 229b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten switch (domain) { 230b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 0: // FIXME There's a private declaration '#define XA_DOMAINTYPE_CONTAINER 0' in src/data.h 231b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // but we don't have access to it. Plan to file a bug with Khronos about this symbol. 232b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return "media container"; 233b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#define _(x) case x: return #x; 234b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_AUDIO) 235b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_VIDEO) 236b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_IMAGE) 237b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_TIMEDTEXT) 238b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_MIDI) 239b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_VENDOR) 240b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_UNKNOWN) 241b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#undef _ 242b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten default: 243b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return "unknown"; 24475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 24575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 24675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 24775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// main program 24875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenint main(int argc, char **argv) 24975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 25075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *prog = argv[0]; 25175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int i; 25275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 25375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAboolean abq = XA_BOOLEAN_FALSE; // use AndroidBufferQueue, default is URI 25475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAboolean looping = XA_BOOLEAN_FALSE; 25575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten for (i = 1; i < argc; ++i) { 25675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *arg = argv[i]; 25775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (arg[0] != '-') 25875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 25975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten switch (arg[1]) { 26075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'a': 26175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten abq = XA_BOOLEAN_TRUE; 26275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 263b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'c': 264b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten forceCallbackFailure = XA_BOOLEAN_TRUE; 265b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 26675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'd': 26775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten discPacket = atoi(&arg[2]); 26875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 269b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'D': 270b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket = atoi(&arg[2]); 271b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 272b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'f': 273b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten firstPacket = atoi(&arg[2]); 274b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 275b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'F': 276b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten formatPacket = atoi(&arg[2]); 277b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 27875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'l': 27975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten looping = XA_BOOLEAN_TRUE; 28075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 281b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'n': 282b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = atoi(&arg[2]); 283b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 284b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'p': 285b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten pauseMs = atoi(&arg[2]); 286b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 287b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 's': 288b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten seekPos = atoi(&arg[2]); 28975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 29075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten default: 29175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", prog, arg); 29275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 29375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 29475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 29575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 29675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // check that exactly one URI was specified 29775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (argc - i != 1) { 298b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "usage: %s [-a] [-c] [-d#] [-D#] [-f#] [-F#] [-l] [-n#] [-p#] [-s#] uri\n", 299b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten prog); 300b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -a Use Android buffer queue to supply data, default is URI\n"); 301b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -c Force callback to return an error randomly, for debugging only\n"); 302b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -d# Packet index to insert a discontinuity, default is none\n"); 303b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -D# Packet index to switch to after the discontinuity\n"); 304b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -f# First packet index, defaults to 0\n"); 305b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -F# Packet index to insert a format change, default is none\n"); 306b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -l Enable looping, for URI only\n"); 307b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -n# Number of packets to enqueue\n"); 308b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -p# Pause playback for 5 seconds after this many milliseconds\n"); 309b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -s# Seek position in milliseconds, for URI only\n"); 31075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten return EXIT_FAILURE; 31175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 31275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *uri = argv[i]; 31375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 31475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // for AndroidBufferQueue, interpret URI as a filename and open 31575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int fd = -1; 31675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 31775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fd = open(uri, O_RDONLY); 31875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (fd < 0) { 31975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 32075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 32175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 32275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int ok; 32375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten struct stat statbuf; 32475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = fstat(fd, &statbuf); 32575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (ok < 0) { 32675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 32775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 32875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 32975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (!S_ISREG(statbuf.st_mode)) { 33075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: not an ordinary file\n", uri); 33175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 33275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 33375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *ptr; 33475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ptr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t) 0); 33575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (ptr == MAP_FAILED) { 33675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 33775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 33875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 33975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten size_t filelen = statbuf.st_size; 34075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if ((filelen % MPEG2TS_PACKET_SIZE) != 0) { 34175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: warning file length %zu is not a multiple of %d\n", uri, filelen, 34275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten MPEG2TS_PACKET_SIZE); 34375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 34475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packets = (MPEG2TS_Packet *) ptr; 345b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten totalPackets = filelen / MPEG2TS_PACKET_SIZE; 346b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("%s has %zu total packets\n", uri, totalPackets); 347b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (firstPacket >= totalPackets) { 348b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-f%zu ignored\n", firstPacket); 349b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten firstPacket = 0; 350b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 351b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (numPackets == 0) { 352b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = totalPackets - firstPacket; 353b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else if (firstPacket + numPackets > totalPackets) { 354b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-n%zu ignored\n", numPackets); 355b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = totalPackets - firstPacket; 356b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 357b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten lastPacket = firstPacket + numPackets; 358b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (discPacket != 0 && (discPacket < firstPacket || discPacket >= lastPacket)) { 359b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-d%zu ignored\n", discPacket); 360b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten discPacket = 0; 361b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 362b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (afterDiscPacket < firstPacket || afterDiscPacket >= lastPacket) { 363b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-D%zu ignored\n", afterDiscPacket); 364b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket = 0; 365b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 366b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (formatPacket != 0 && (formatPacket < firstPacket || formatPacket >= lastPacket)) { 367b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-F%zu ignored\n", formatPacket); 368b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten formatPacket = 0; 369b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 37075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 37175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ANativeWindow *nativeWindow; 37375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 37575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf engineObject; 37675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create engine 37875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 37975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 38175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAEngineItf engineEngine; 38375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 38475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 38675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create output mix 38775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf outputMixObject; 38875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 38975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 39075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 39175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 39275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 39375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure media source 39475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_URI locUri; 39575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locUri.locatorType = XA_DATALOCATOR_URI; 39675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locUri.URI = (XAchar *) uri; 39775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataFormat_MIME fmtMime; 39875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.formatType = XA_DATAFORMAT_MIME; 39975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 400c3b82a293ed06001ba6d50f111608160c6065ef2Glenn Kasten fmtMime.mimeType = (XAchar *) XA_ANDROID_MIME_MP2TS; 40175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.containerType = XA_CONTAINERTYPE_MPEG_TS; 40275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 40375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.mimeType = NULL; 40475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.containerType = XA_CONTAINERTYPE_UNSPECIFIED; 40575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 40675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_AndroidBufferQueue locABQ; 40775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locABQ.locatorType = XA_DATALOCATOR_ANDROIDBUFFERQUEUE; 40875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locABQ.numBuffers = NB_BUFFERS; 40975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSource dataSrc; 41075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 41175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pLocator = &locABQ; 41275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 41375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pLocator = &locUri; 41475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 41575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pFormat = &fmtMime; 41675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 41775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure audio sink 41875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_OutputMix locOM; 41975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locOM.locatorType = XA_DATALOCATOR_OUTPUTMIX; 42075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locOM.outputMix = outputMixObject; 42175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSink audioSnk; 42275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten audioSnk.pLocator = &locOM; 42375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten audioSnk.pFormat = NULL; 42475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 42575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure video sink 42675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten nativeWindow = getNativeWindow(); 42775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_NativeDisplay locND; 42875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.locatorType = XA_DATALOCATOR_NATIVEDISPLAY; 42975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.hWindow = nativeWindow; 43075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.hDisplay = NULL; 43175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSink imageVideoSink; 43275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten imageVideoSink.pLocator = &locND; 43375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten imageVideoSink.pFormat = NULL; 43475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 43575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create media player 43675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf playerObject; 43775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAInterfaceID ids[4] = {XA_IID_STREAMINFORMATION, XA_IID_PREFETCHSTATUS, XA_IID_SEEK, 43860ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten XA_IID_ANDROIDBUFFERQUEUESOURCE}; 439b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAboolean req[4] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_FALSE, XA_BOOLEAN_TRUE}; 44075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObject, &dataSrc, NULL, 44175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &audioSnk, nativeWindow != NULL ? &imageVideoSink : NULL, NULL, NULL, abq ? 4 : 3, ids, 44275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten req); 44375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 44475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 44575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // realize the player 44675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->Realize(playerObject, XA_BOOLEAN_FALSE); 44775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 44875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 449b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the play interface 450b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAPlayItf playerPlay; 451b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_PLAY, &playerPlay); 452b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 453b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 45475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 45575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 45675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the Android buffer queue interface 45775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAAndroidBufferQueueItf playerAndroidBufferQueue; 45860ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_ANDROIDBUFFERQUEUESOURCE, 45975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerAndroidBufferQueue); 46075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 46275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register the buffer queue callback 46375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->RegisterCallback(playerAndroidBufferQueue, 464b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten bufferQueueCallback, (void *) playerPlay); 46575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->SetCallbackEventsMask(playerAndroidBufferQueue, 46775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED); 46875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 470b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // set the player's state to paused, to start prefetching 471b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("start early prefetch\n"); 472b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PAUSED); 473b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 474b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 47575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the initial buffers until buffer queue is full 47675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 packetsThisBuffer; 477b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten for (curPacket = firstPacket; curPacket < lastPacket; curPacket += packetsThisBuffer) { 47875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // handle the unlikely case of a very short .ts 479b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten packetsThisBuffer = lastPacket - curPacket; 48075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (packetsThisBuffer > PACKETS_PER_BUFFER) { 48175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packetsThisBuffer = PACKETS_PER_BUFFER; 48275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 48375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->Enqueue(playerAndroidBufferQueue, NULL, 48475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &packets[curPacket], MPEG2TS_PACKET_SIZE * packetsThisBuffer, NULL, 0); 48575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_RESULT_BUFFER_INSUFFICIENT == result) { 48601f8573bc2a850536b02855d483dfe130c050a2fAshok Bhat printf("Enqueued initial %zu packets in %zu buffers\n", curPacket - firstPacket, 487b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten (curPacket - firstPacket + PACKETS_PER_BUFFER - 1) / PACKETS_PER_BUFFER); 48875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 48975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 49075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 49175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 49275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 49375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 49475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 49575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the stream information interface 49675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAStreamInformationItf playerStreamInformation; 49775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_STREAMINFORMATION, 49875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerStreamInformation); 49975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 50075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 50175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register the stream event change callback 50275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerStreamInformation)->RegisterStreamChangeCallback(playerStreamInformation, 50375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten streamEventChangeCallback, NULL); 50475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 50575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 50675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the prefetch status interface 50775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAPrefetchStatusItf playerPrefetchStatus; 50875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_PREFETCHSTATUS, 50975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerPrefetchStatus); 51075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 51275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register prefetch status callback 51375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPrefetchStatus)->RegisterCallback(playerPrefetchStatus, prefetchStatusCallback, 51475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten NULL); 51575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPrefetchStatus)->SetCallbackEventsMask(playerPrefetchStatus, 51775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_PREFETCHEVENT_FILLLEVELCHANGE | XA_PREFETCHEVENT_STATUSCHANGE); 51875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 520b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the seek interface for seeking and/or looping 521b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (looping || seekPos != XA_TIME_UNKNOWN) { 52275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XASeekItf playerSeek; 52375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_SEEK, &playerSeek); 52475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 525b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (seekPos != XA_TIME_UNKNOWN) { 526b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerSeek)->SetPosition(playerSeek, seekPos, XA_SEEKMODE_ACCURATE); 527b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (XA_RESULT_FEATURE_UNSUPPORTED == result) { 528b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-s%u (seek to initial position) is unsupported\n", seekPos); 529b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 530b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 531b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 532b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 533b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (looping) { 534b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerSeek)->SetLoop(playerSeek, XA_BOOLEAN_TRUE, (XAmillisecond) 0, 535b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XA_TIME_UNKNOWN); 536b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (XA_RESULT_FEATURE_UNSUPPORTED) { 537b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-l (looping) is unsupported\n"); 538b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 539b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 540b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 541b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 54275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 54375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 54475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register play event callback 54575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->RegisterCallback(playerPlay, playEventCallback, NULL); 54675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 54775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->SetCallbackEventsMask(playerPlay, 54875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_PLAYEVENT_HEADATEND | XA_PLAYEVENT_HEADATMARKER | XA_PLAYEVENT_HEADATNEWPOS); 54975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 55075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 55175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set a marker 552b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetMarkerPosition(playerPlay, 5000); 55375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 55475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 55575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set position update period 556b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPositionUpdatePeriod(playerPlay, 2000); 55775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 55875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 559b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the position before prefetch 560b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAmillisecond position; 561b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 562b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 563b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Position before prefetch: %u ms\n", position); 564b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 565b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the duration before prefetch 56675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAmillisecond duration; 56775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->GetDuration(playerPlay, &duration); 56875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 56975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_TIME_UNKNOWN == duration) 570b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration before prefetch: unknown as expected\n"); 57175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten else 572b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration before prefetch: %.1f (surprise!)\n", duration / 1000.0f); 57375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 57475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set the player's state to paused, to start prefetching 57575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("start prefetch\n"); 57675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PAUSED); 57775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 57875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 57975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // wait for prefetch status callback to indicate either sufficient data or error 58075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_mutex_lock(&mutex); 58175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten while (prefetch_status == PREFETCHSTATUS_UNKNOWN) { 58275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_cond_wait(&cond, &mutex); 58375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 58475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_mutex_unlock(&mutex); 58575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (prefetch_status == PREFETCHSTATUS_ERROR) { 58675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "Error during prefetch, exiting\n"); 58775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto destroyRes; 58875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 58975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 590b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the position after prefetch 591b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 592b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 593b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Position after prefetch: %u ms\n", position); 594b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 595b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get duration again, now it should be known for the file source or unknown for TS 59675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->GetDuration(playerPlay, &duration); 59775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 59875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (duration == XA_TIME_UNKNOWN) { 599b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration after prefetch: unknown (expected for TS, unexpected for file)\n"); 60075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 601b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration after prefetch: %u ms (expected for file, unexpected for TS)\n", duration); 60275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 60375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 604b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // query for media container information 605b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryMediaContainerInformation(playerStreamInformation, 606b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten NULL); 607b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 608b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAMediaContainerInformation mediaContainerInformation; 609b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // this verifies it is filling in all the fields 610b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten memset(&mediaContainerInformation, 0x55, sizeof(XAMediaContainerInformation)); 611b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryMediaContainerInformation(playerStreamInformation, 612b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten &mediaContainerInformation); 613b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 614b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Media container information:\n"); 615b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" containerType = %u\n", mediaContainerInformation.containerType); 616b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" mediaDuration = %u\n", mediaContainerInformation.mediaDuration); 617b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" numStreams = %u\n", mediaContainerInformation.numStreams); 618b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 619b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // Now query for each the streams. Note that stream indices go up to and including 620b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // mediaContainerInformation.numStreams, because stream 0 is the container itself, 621b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // while stream 1 to mediaContainerInformation.numStreams are the contained streams. 622b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 streamIndex; 623b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten for (streamIndex = 0; streamIndex <= mediaContainerInformation.numStreams; ++streamIndex) { 624b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 domain; 625b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint16 nameSize; 626b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAchar name[64]; 627b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("stream[%u]:\n", streamIndex); 628b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (streamIndex == 0) { 629b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamType(playerStreamInformation, 630b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &domain); 631b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 632b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 633b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &mediaContainerInformation); 634b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten //assert(XA_RESULT_PARAMETER_INVALID == result); 635b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten nameSize = sizeof(name); 636b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamName(playerStreamInformation, 637b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenstreamIndex, &nameSize, name); 638b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten //assert(XA_RESULT_PARAMETER_INVALID == result); 639b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten continue; 640b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 641b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamType(playerStreamInformation, streamIndex, 642b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten NULL); 643b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 644b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten domain = 12345; 645b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamType(playerStreamInformation, streamIndex, 646b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten &domain); 647b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 648b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" QueryStreamType: domain = 0x%X (%s)\n", domain, domainToString(domain)); 649b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten nameSize = sizeof(name); 650b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamName(playerStreamInformation, streamIndex, 651b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten &nameSize, name); 652b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#if 0 653b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 654b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(sizeof(name) >= nameSize); 655b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (sizeof(name) != nameSize) { 656b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert('\0' == name[nameSize]); 657b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 658b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" QueryStreamName: nameSize=%u, name=\"%.*s\"\n", nameSize, nameSize, name); 659b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 660b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, NULL); 661b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 662b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#endif 663b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 664b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" QueryStreamInformation:\n"); 665b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten switch (domain) { 666b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#if 0 667b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 0: // FIXME container 668b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 669b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenstreamIndex, &mediaContainerInformation); 670b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 671b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" containerType = %u (1=unspecified)\n", 672b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten mediaContainerInformation.containerType); 673b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" mediaDuration = %u\n", mediaContainerInformation.mediaDuration); 674b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" numStreams = %u\n", mediaContainerInformation.numStreams); 675b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 676b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#endif 677b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_AUDIO: { 678b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAAudioStreamInformation audioStreamInformation; 679b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten memset(&audioStreamInformation, 0x55, sizeof(XAAudioStreamInformation)); 680b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 681b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &audioStreamInformation); 682b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 683b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" codecId = %u\n", audioStreamInformation.codecId); 684b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" channels = %u\n", audioStreamInformation.channels); 685b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" sampleRate = %u\n", audioStreamInformation.sampleRate); 686b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" bitRate = %u\n", audioStreamInformation.bitRate); 687b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" langCountry = \"%s\"\n", audioStreamInformation.langCountry); 688b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" duration = %u\n", audioStreamInformation.duration); 689b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 690b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_VIDEO: { 691b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAVideoStreamInformation videoStreamInformation; 692b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 693b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &videoStreamInformation); 694b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 695b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" codecId = %u\n", videoStreamInformation.codecId); 696b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" width = %u\n", videoStreamInformation.width); 697b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" height = %u\n", videoStreamInformation.height); 698b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" frameRate = %u\n", videoStreamInformation.frameRate); 699b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" bitRate = %u\n", videoStreamInformation.bitRate); 700b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" duration = %u\n", videoStreamInformation.duration); 701b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 702b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_IMAGE: { 703b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAImageStreamInformation imageStreamInformation; 704b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 705b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &imageStreamInformation); 706b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 707b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" codecId = %u\n", imageStreamInformation.codecId); 708b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" width = %u\n", imageStreamInformation.width); 709b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" height = %u\n", imageStreamInformation.height); 710b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" presentationDuration = %u\n", imageStreamInformation.presentationDuration); 711b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 712b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_TIMEDTEXT: { 713b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XATimedTextStreamInformation timedTextStreamInformation; 714b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 715b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &timedTextStreamInformation); 716b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 717b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" layer = %u\n", timedTextStreamInformation.layer); 718b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" width = %u\n", timedTextStreamInformation.width); 719b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" height = %u\n", timedTextStreamInformation.height); 720b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" tx = %u\n", timedTextStreamInformation.tx); 721b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" ty = %u\n", timedTextStreamInformation.ty); 722b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" bitrate = %u\n", timedTextStreamInformation.bitrate); 723b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" langCountry = \"%s\"\n", timedTextStreamInformation.langCountry); 724b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" duration = %u\n", timedTextStreamInformation.duration); 725b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 726b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_MIDI: { 727b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAMIDIStreamInformation midiStreamInformation; 728b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 729b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &midiStreamInformation); 730b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 731b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" channels = %u\n", midiStreamInformation.channels); 732b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" tracks = %u\n", midiStreamInformation.tracks); 733b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" bankType = %u\n", midiStreamInformation.bankType); 734b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" langCountry = \"%s\"\n", midiStreamInformation.langCountry); 735b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" duration = %u\n", midiStreamInformation.duration); 736b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 737b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_VENDOR: { 738b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAVendorStreamInformation vendorStreamInformation; 739b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 740b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &vendorStreamInformation); 741b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 742b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" VendorStreamInfo = %p\n", vendorStreamInformation.VendorStreamInfo); 743b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 744b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case XA_DOMAINTYPE_UNKNOWN: { 745b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // "It is not possible to query Information for streams identified as 746b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // XA_DOMAINTYPE_UNKNOWN, any attempt to do so shall return a result of 747b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // XA_RESULT_CONTENT_UNSUPPORTED." 748b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten char big[256]; 749b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 750b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &big); 751b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_CONTENT_UNSUPPORTED == result); 752b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } break; 753b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten default: 754b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 755b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 756b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 757b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 758b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // Try one more stream index beyond the valid range 759b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 domain; 760b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamType(playerStreamInformation, streamIndex, 761b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten &domain); 762b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 763b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XATimedTextStreamInformation big; 764b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryStreamInformation(playerStreamInformation, 765b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten streamIndex, &big); 766b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 767b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 768b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("QueryActiveStreams:\n"); 769b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryActiveStreams(playerStreamInformation, NULL, NULL); 770b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 771b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 numStreams1 = 0x12345678; 772b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryActiveStreams(playerStreamInformation, &numStreams1, 773b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten NULL); 774b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 775b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" numStreams = %u\n", numStreams1); 776b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAboolean *activeStreams = calloc(numStreams1 + 1, sizeof(XAboolean)); 777b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(NULL != activeStreams); 778b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" active stream(s) ="); 779b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 numStreams2 = numStreams1; 780b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryActiveStreams(playerStreamInformation, &numStreams2, 781b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten activeStreams); 782b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 783b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(numStreams2 == numStreams1); 784b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten for (streamIndex = 0; streamIndex <= numStreams1; ++streamIndex) { 785b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (activeStreams[streamIndex]) 786b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" %u", streamIndex); 787b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 788b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("\n"); 789b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 790b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // SetActiveStream is untested 791b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 79275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // start playing 79375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("starting to play\n"); 79475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PLAYING); 79575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 79675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 79775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // continue playing until end of media 79875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten for (;;) { 79975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 status; 80075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->GetPlayState(playerPlay, &status); 80175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 80275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (status == XA_PLAYSTATE_PAUSED) 80375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 80475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(status == XA_PLAYSTATE_PLAYING); 805b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten usleep(100000); 806b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (pauseMs >= 0) { 807b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 808b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 80914463a8e53e2a5185a395e2045fd33ad4a63050dGlenn Kasten if ((int) position >= pauseMs) { 810b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Pausing for 5 seconds at position %u\n", position); 811b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PAUSED); 812b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 813b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten sleep(5); 814b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // FIXME clear ABQ queue here 815b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PLAYING); 816b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 817b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten pauseMs = -1; 818b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 819b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 82075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 82175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 82275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // wait a bit more in case of additional callbacks 82375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("end of media\n"); 82475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten sleep(3); 82575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 826b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get final position 827b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 828b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 829b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Position at end: %u ms\n", position); 830b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 831b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get duration again, now it should be known 832b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetDuration(playerPlay, &duration); 833b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 834b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (duration == XA_TIME_UNKNOWN) { 835b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration at end: unknown\n"); 836b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 837b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration at end: %u ms\n", duration); 838b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 839b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 84075290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastendestroyRes: 84175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 84275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // destroy the player 84375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (*playerObject)->Destroy(playerObject); 84475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 84575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // destroy the output mix 84675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (*outputMixObject)->Destroy(outputMixObject); 84775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 84875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // destroy the engine 84975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (*engineObject)->Destroy(engineObject); 85075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 85175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#if 0 85275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (nativeWindow != NULL) { 85375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ANativeWindow_release(nativeWindow); 85475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 85575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#endif 85675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 85775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenclose: 85875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (fd >= 0) { 85975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (void) close(fd); 86075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 86175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 862b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten disposeNativeWindow(); 863b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 86475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten return EXIT_SUCCESS; 86575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 866