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> 2375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <fcntl.h> 2475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <sys/mman.h> 2575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <sys/stat.h> 2675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <unistd.h> 2775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <OMXAL/OpenMAXAL.h> 2875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include <OMXAL/OpenMAXAL_Android.h> 2975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#include "nativewindow.h" 3075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define MPEG2TS_PACKET_SIZE 188 // MPEG-2 transport stream packet size in bytes 3275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PACKETS_PER_BUFFER 20 // Number of MPEG-2 transport stream packets per buffer 3375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define NB_BUFFERS 2 // Number of buffers in Android buffer queue 3575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 3675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// MPEG-2 transport stream packet 3775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastentypedef struct { 3875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten char data[MPEG2TS_PACKET_SIZE]; 3975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} MPEG2TS_Packet; 4075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 4175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Globals shared between main thread and buffer queue callback 4275290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenMPEG2TS_Packet *packets; 43b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t totalPackets; // total number of packets in input file 44b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t numPackets; // number of packets to play, defaults to totalPackets - firstPacket 45b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t curPacket; // current packet index 46b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t discPacket; // discontinuity packet index, defaults to no discontinuity requested 47b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t afterDiscPacket; // packet index to switch to after the discontinuity 48b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t firstPacket; // first packet index to be played, defaults to zero 49b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t lastPacket; // last packet index to be played 50b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastensize_t formatPacket; // format change packet index, defaults to no format change requested 51b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAmillisecond seekPos = XA_TIME_UNKNOWN; // seek to this position initially 52b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastenint pauseMs = -1; // pause after this many ms into playback 53b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAboolean forceCallbackFailure = XA_BOOLEAN_FALSE; // force callback failures occasionally 54b17edb96ba759cd1197bf13cd13e279ee144da60Glenn KastenXAboolean sentEOS = XA_BOOLEAN_FALSE; // whether we have enqueued EOS yet 5575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 5675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// These are extensions to OpenMAX AL 1.0.1 values 5775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 5875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHSTATUS_UNKNOWN ((XAuint32) 0) 5975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHSTATUS_ERROR ((XAuint32) (-1)) 6075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Mutex and condition shared with main program to protect prefetch_status 6275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 6475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 6575290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenXAuint32 prefetch_status = PREFETCHSTATUS_UNKNOWN; 6675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 6775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten/* used to detect errors likely to have occured when the OpenMAX AL framework fails to open 6875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond. 6975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten */ 7075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \ 7175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten (XA_PREFETCHEVENT_STATUSCHANGE | XA_PREFETCHEVENT_FILLLEVELCHANGE) 7275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 7375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// stream event change callback 7475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenvoid streamEventChangeCallback(XAStreamInformationItf caller, XAuint32 eventId, 7575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 streamIndex, void *pEventData, void *pContext) 7675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 7775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // context parameter is specified as NULL and is unused here 7875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(NULL == pContext); 7975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten switch (eventId) { 8075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case XA_STREAMCBEVENT_PROPERTYCHANGE: 8175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("XA_STREAMCBEVENT_PROPERTYCHANGE on stream index %u, pEventData %p\n", streamIndex, 8275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pEventData); 8375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 8475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten default: 8575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("Unknown stream event ID %u\n", eventId); 8675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 8775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 8875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 8975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 9075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// prefetch status callback 9175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenvoid prefetchStatusCallback(XAPrefetchStatusItf caller, void *pContext, XAuint32 event) 9275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 9375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pContext is unused here, so we pass NULL 9475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(pContext == NULL); 9575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XApermille level = 0; 9675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 9775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->GetFillLevel(caller, &level); 9875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 9975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 status; 10075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->GetPrefetchStatus(caller, &status); 10175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 10275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (event & XA_PREFETCHEVENT_FILLLEVELCHANGE) { 10375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Buffer fill level is = %d\n", level); 10475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 10575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (event & XA_PREFETCHEVENT_STATUSCHANGE) { 10675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Prefetch Status is = %u\n", status); 10775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 10875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 new_prefetch_status; 10975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE)) 11075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten && (level == 0) && (status == XA_PREFETCHSTATUS_UNDERFLOW)) { 11175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("PrefetchEventCallback: Error while prefetching data, exiting\n"); 11275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten new_prefetch_status = PREFETCHSTATUS_ERROR; 11375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else if (event == XA_PREFETCHEVENT_STATUSCHANGE) { 11475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten new_prefetch_status = status; 11575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 11675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten return; 11775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 11875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int ok; 11975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_mutex_lock(&mutex); 12075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten prefetch_status = new_prefetch_status; 12275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_cond_signal(&cond); 12375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = pthread_mutex_unlock(&mutex); 12575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(ok == 0); 12675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 12775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 12875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// playback event callback 12975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenvoid playEventCallback(XAPlayItf caller, void *pContext, XAuint32 event) 13075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 13175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pContext is unused here, so we pass NULL 13275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(NULL == pContext); 13375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 134b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAresult result; 13575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAmillisecond position; 136b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*caller)->GetPosition(caller, &position); 137b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 13875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 13975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATEND & event) { 140b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATEND current position=%u ms\n", position); 14175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 14275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 14375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATNEWPOS & event) { 144b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATNEWPOS current position=%u ms\n", position); 14575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 14675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 14775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_PLAYEVENT_HEADATMARKER & event) { 148b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("XA_PLAYEVENT_HEADATMARKER current position=%u ms\n", position); 14975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 15075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 15175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 15275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// Android buffer queue callback 15375290ff394698c53f35a21612c03b8ddd21fecf9Glenn KastenXAresult bufferQueueCallback( 15475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAAndroidBufferQueueItf caller, 15575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *pCallbackContext, 15675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *pBufferContext, 15775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *pBufferData, 15875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 dataSize, 15975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 dataUsed, 16075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const XAAndroidBufferItem *pItems, 16175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 itemsLength) 16275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 163b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAPlayItf playerPlay = (XAPlayItf) pCallbackContext; 16475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the .ts data directly from mapped memory, so ignore the empty buffer pBufferData 165b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket <= lastPacket) { 16675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten static const XAAndroidBufferItem discontinuity = {XA_ANDROID_ITEMKEY_DISCONTINUITY, 0}; 16775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten static const XAAndroidBufferItem eos = {XA_ANDROID_ITEMKEY_EOS, 0}; 168b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten static const XAAndroidBufferItem formatChange = {XA_ANDROID_ITEMKEY_FORMAT_CHANGE, 0}; 16975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const XAAndroidBufferItem *items; 17075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 itemSize; 17175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // compute number of packets to be enqueued in this buffer 172b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 packetsThisBuffer = lastPacket - curPacket; 17375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (packetsThisBuffer > PACKETS_PER_BUFFER) { 17475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packetsThisBuffer = PACKETS_PER_BUFFER; 17575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 17675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // last packet? this should only happen once 177b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket == lastPacket) { 178b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (sentEOS) { 179b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("buffer completion callback after EOS\n"); 180b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return XA_RESULT_SUCCESS; 181b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 182b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending EOS\n"); 18375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = &eos; 18475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = sizeof(eos); 185b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten sentEOS = XA_BOOLEAN_TRUE; 18675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // discontinuity requested? 18775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else if (curPacket == discPacket) { 188b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending discontinuity at packet %zu, then resuming at packet %zu\n", discPacket, 189b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket); 19075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = &discontinuity; 19175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = sizeof(discontinuity); 192b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten curPacket = afterDiscPacket; 193b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // format change requested? 194b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else if (curPacket == formatPacket) { 195b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("sending format change"); 196b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten items = &formatChange; 197b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten itemSize = sizeof(formatChange); 19875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // pure data with no items 19975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 20075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten items = NULL; 20175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten itemSize = 0; 20275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 20375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 20475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the optional data and optional items; there is always at least one or the other 20575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(packetsThisBuffer > 0 || itemSize > 0); 20675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*caller)->Enqueue(caller, NULL, &packets[curPacket], 20775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten sizeof(MPEG2TS_Packet) * packetsThisBuffer, items, itemSize); 20875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 20975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten curPacket += packetsThisBuffer; 210b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // display position periodically 211b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (curPacket % 1000 == 0) { 212b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAmillisecond position; 213b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 214b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 21501f8573bc2a850536b02855d483dfe130c050a2fAshok Bhat printf("Position after enqueueing packet %zu: %u ms\n", curPacket, position); 216b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 217b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 218b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (forceCallbackFailure && (curPacket % 1230 == 0)) { 219b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return (XAresult) curPacket; 220b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 221b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return XA_RESULT_SUCCESS; 222b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 223b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten} 224b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 225b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten// convert a domain type to string 226b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kastenstatic const char *domainToString(XAuint32 domain) 227b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten{ 228b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten switch (domain) { 229b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 0: // FIXME There's a private declaration '#define XA_DOMAINTYPE_CONTAINER 0' in src/data.h 230b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // but we don't have access to it. Plan to file a bug with Khronos about this symbol. 231b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return "media container"; 232b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#define _(x) case x: return #x; 233b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_AUDIO) 234b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_VIDEO) 235b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_IMAGE) 236b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_TIMEDTEXT) 237b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_MIDI) 238b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_VENDOR) 239b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten _(XA_DOMAINTYPE_UNKNOWN) 240b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten#undef _ 241b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten default: 242b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten return "unknown"; 24375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 24475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten} 24575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 24675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten// main program 24775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kastenint main(int argc, char **argv) 24875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten{ 24975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *prog = argv[0]; 25075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int i; 25175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 25275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAboolean abq = XA_BOOLEAN_FALSE; // use AndroidBufferQueue, default is URI 25375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAboolean looping = XA_BOOLEAN_FALSE; 25475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten for (i = 1; i < argc; ++i) { 25575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *arg = argv[i]; 25675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (arg[0] != '-') 25775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 25875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten switch (arg[1]) { 25975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'a': 26075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten abq = XA_BOOLEAN_TRUE; 26175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 262b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'c': 263b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten forceCallbackFailure = XA_BOOLEAN_TRUE; 264b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 26575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'd': 26675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten discPacket = atoi(&arg[2]); 26775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 268b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'D': 269b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket = atoi(&arg[2]); 270b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 271b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'f': 272b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten firstPacket = atoi(&arg[2]); 273b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 274b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'F': 275b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten formatPacket = atoi(&arg[2]); 276b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 27775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten case 'l': 27875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten looping = XA_BOOLEAN_TRUE; 27975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 280b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'n': 281b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = atoi(&arg[2]); 282b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 283b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 'p': 284b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten pauseMs = atoi(&arg[2]); 285b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten break; 286b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten case 's': 287b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten seekPos = atoi(&arg[2]); 28875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 28975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten default: 29075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", prog, arg); 29175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 29275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 29375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 29475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 29575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // check that exactly one URI was specified 29675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (argc - i != 1) { 297b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "usage: %s [-a] [-c] [-d#] [-D#] [-f#] [-F#] [-l] [-n#] [-p#] [-s#] uri\n", 298b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten prog); 299b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -a Use Android buffer queue to supply data, default is URI\n"); 300b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -c Force callback to return an error randomly, for debugging only\n"); 301b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -d# Packet index to insert a discontinuity, default is none\n"); 302b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -D# Packet index to switch to after the discontinuity\n"); 303b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -f# First packet index, defaults to 0\n"); 304b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -F# Packet index to insert a format change, default is none\n"); 305b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -l Enable looping, for URI only\n"); 306b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -n# Number of packets to enqueue\n"); 307b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -p# Pause playback for 5 seconds after this many milliseconds\n"); 308b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, " -s# Seek position in milliseconds, for URI only\n"); 30975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten return EXIT_FAILURE; 31075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 31175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten const char *uri = argv[i]; 31275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 31375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // for AndroidBufferQueue, interpret URI as a filename and open 31475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int fd = -1; 31575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 31675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fd = open(uri, O_RDONLY); 31775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (fd < 0) { 31875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 31975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 32075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 32175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten int ok; 32275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten struct stat statbuf; 32375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ok = fstat(fd, &statbuf); 32475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (ok < 0) { 32575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 32675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 32775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 32875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (!S_ISREG(statbuf.st_mode)) { 32975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: not an ordinary file\n", uri); 33075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 33175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 33275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten void *ptr; 33375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ptr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, (off_t) 0); 33475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (ptr == MAP_FAILED) { 33575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten perror(uri); 33675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto close; 33775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 33875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten size_t filelen = statbuf.st_size; 33975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if ((filelen % MPEG2TS_PACKET_SIZE) != 0) { 34075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "%s: warning file length %zu is not a multiple of %d\n", uri, filelen, 34175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten MPEG2TS_PACKET_SIZE); 34275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 34375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packets = (MPEG2TS_Packet *) ptr; 344b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten totalPackets = filelen / MPEG2TS_PACKET_SIZE; 345b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("%s has %zu total packets\n", uri, totalPackets); 346b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (firstPacket >= totalPackets) { 347b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-f%zu ignored\n", firstPacket); 348b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten firstPacket = 0; 349b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 350b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (numPackets == 0) { 351b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = totalPackets - firstPacket; 352b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else if (firstPacket + numPackets > totalPackets) { 353b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-n%zu ignored\n", numPackets); 354b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten numPackets = totalPackets - firstPacket; 355b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 356b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten lastPacket = firstPacket + numPackets; 357b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (discPacket != 0 && (discPacket < firstPacket || discPacket >= lastPacket)) { 358b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-d%zu ignored\n", discPacket); 359b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten discPacket = 0; 360b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 361b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (afterDiscPacket < firstPacket || afterDiscPacket >= lastPacket) { 362b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-D%zu ignored\n", afterDiscPacket); 363b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten afterDiscPacket = 0; 364b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 365b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (formatPacket != 0 && (formatPacket < firstPacket || formatPacket >= lastPacket)) { 366b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-F%zu ignored\n", formatPacket); 367b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten formatPacket = 0; 368b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 36975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 37075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten ANativeWindow *nativeWindow; 37275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAresult result; 37475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf engineObject; 37575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 37675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create engine 37775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 37875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 37975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE); 38075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAEngineItf engineEngine; 38275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine); 38375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 38575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create output mix 38675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf outputMixObject; 38775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 38875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 38975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE); 39075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 39175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 39275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure media source 39375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_URI locUri; 39475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locUri.locatorType = XA_DATALOCATOR_URI; 39575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locUri.URI = (XAchar *) uri; 39675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataFormat_MIME fmtMime; 39775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.formatType = XA_DATAFORMAT_MIME; 39875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 399c3b82a293ed06001ba6d50f111608160c6065ef2Glenn Kasten fmtMime.mimeType = (XAchar *) XA_ANDROID_MIME_MP2TS; 40075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.containerType = XA_CONTAINERTYPE_MPEG_TS; 40175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 40275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.mimeType = NULL; 40375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fmtMime.containerType = XA_CONTAINERTYPE_UNSPECIFIED; 40475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 40575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_AndroidBufferQueue locABQ; 40675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locABQ.locatorType = XA_DATALOCATOR_ANDROIDBUFFERQUEUE; 40775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locABQ.numBuffers = NB_BUFFERS; 40875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSource dataSrc; 40975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 41075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pLocator = &locABQ; 41175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 41275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pLocator = &locUri; 41375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 41475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten dataSrc.pFormat = &fmtMime; 41575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 41675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure audio sink 41775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_OutputMix locOM; 41875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locOM.locatorType = XA_DATALOCATOR_OUTPUTMIX; 41975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locOM.outputMix = outputMixObject; 42075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSink audioSnk; 42175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten audioSnk.pLocator = &locOM; 42275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten audioSnk.pFormat = NULL; 42375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 42475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // configure video sink 42575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten nativeWindow = getNativeWindow(); 42675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataLocator_NativeDisplay locND; 42775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.locatorType = XA_DATALOCATOR_NATIVEDISPLAY; 42875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.hWindow = nativeWindow; 42975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten locND.hDisplay = NULL; 43075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XADataSink imageVideoSink; 43175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten imageVideoSink.pLocator = &locND; 43275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten imageVideoSink.pFormat = NULL; 43375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 43475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // create media player 43575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAObjectItf playerObject; 43675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAInterfaceID ids[4] = {XA_IID_STREAMINFORMATION, XA_IID_PREFETCHSTATUS, XA_IID_SEEK, 43760ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten XA_IID_ANDROIDBUFFERQUEUESOURCE}; 438b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAboolean req[4] = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_FALSE, XA_BOOLEAN_TRUE}; 43975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObject, &dataSrc, NULL, 44075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &audioSnk, nativeWindow != NULL ? &imageVideoSink : NULL, NULL, NULL, abq ? 4 : 3, ids, 44175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten req); 44275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 44375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 44475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // realize the player 44575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->Realize(playerObject, XA_BOOLEAN_FALSE); 44675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 44775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 448b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the play interface 449b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAPlayItf playerPlay; 450b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_PLAY, &playerPlay); 451b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 452b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 45375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (abq) { 45475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 45575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the Android buffer queue interface 45675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAAndroidBufferQueueItf playerAndroidBufferQueue; 45760ca9f9ef02f6e486c3338cb811f603dd7825c05Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_ANDROIDBUFFERQUEUESOURCE, 45875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerAndroidBufferQueue); 45975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 46175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register the buffer queue callback 46275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->RegisterCallback(playerAndroidBufferQueue, 463b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten bufferQueueCallback, (void *) playerPlay); 46475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->SetCallbackEventsMask(playerAndroidBufferQueue, 46675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED); 46775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 46875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 469b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // set the player's state to paused, to start prefetching 470b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("start early prefetch\n"); 471b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PAUSED); 472b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 473b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 47475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // enqueue the initial buffers until buffer queue is full 47575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAuint32 packetsThisBuffer; 476b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten for (curPacket = firstPacket; curPacket < lastPacket; curPacket += packetsThisBuffer) { 47775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // handle the unlikely case of a very short .ts 478b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten packetsThisBuffer = lastPacket - curPacket; 47975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (packetsThisBuffer > PACKETS_PER_BUFFER) { 48075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten packetsThisBuffer = PACKETS_PER_BUFFER; 48175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 48275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerAndroidBufferQueue)->Enqueue(playerAndroidBufferQueue, NULL, 48375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &packets[curPacket], MPEG2TS_PACKET_SIZE * packetsThisBuffer, NULL, 0); 48475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_RESULT_BUFFER_INSUFFICIENT == result) { 48501f8573bc2a850536b02855d483dfe130c050a2fAshok Bhat printf("Enqueued initial %zu packets in %zu buffers\n", curPacket - firstPacket, 486b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten (curPacket - firstPacket + PACKETS_PER_BUFFER - 1) / PACKETS_PER_BUFFER); 48775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten break; 48875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 48975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 49075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 49175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 49275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 49375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 49475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the stream information interface 49575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAStreamInformationItf playerStreamInformation; 49675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_STREAMINFORMATION, 49775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerStreamInformation); 49875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 49975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 50075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register the stream event change callback 50175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerStreamInformation)->RegisterStreamChangeCallback(playerStreamInformation, 50275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten streamEventChangeCallback, NULL); 50375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 50475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 50575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // get the prefetch status interface 50675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAPrefetchStatusItf playerPrefetchStatus; 50775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_PREFETCHSTATUS, 50875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten &playerPrefetchStatus); 50975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 51175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register prefetch status callback 51275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPrefetchStatus)->RegisterCallback(playerPrefetchStatus, prefetchStatusCallback, 51375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten NULL); 51475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPrefetchStatus)->SetCallbackEventsMask(playerPrefetchStatus, 51675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_PREFETCHEVENT_FILLLEVELCHANGE | XA_PREFETCHEVENT_STATUSCHANGE); 51775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 51875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 519b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the seek interface for seeking and/or looping 520b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (looping || seekPos != XA_TIME_UNKNOWN) { 52175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XASeekItf playerSeek; 52275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerObject)->GetInterface(playerObject, XA_IID_SEEK, &playerSeek); 52375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 524b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (seekPos != XA_TIME_UNKNOWN) { 525b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerSeek)->SetPosition(playerSeek, seekPos, XA_SEEKMODE_ACCURATE); 526b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (XA_RESULT_FEATURE_UNSUPPORTED == result) { 527b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-s%u (seek to initial position) is unsupported\n", seekPos); 528b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 529b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 530b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 531b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 532b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (looping) { 533b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerSeek)->SetLoop(playerSeek, XA_BOOLEAN_TRUE, (XAmillisecond) 0, 534b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XA_TIME_UNKNOWN); 535b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (XA_RESULT_FEATURE_UNSUPPORTED) { 536b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten fprintf(stderr, "-l (looping) is unsupported\n"); 537b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } else { 538b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 539b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 540b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten } 54175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 54275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 54375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // register play event callback 54475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->RegisterCallback(playerPlay, playEventCallback, NULL); 54575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 54675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->SetCallbackEventsMask(playerPlay, 54775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XA_PLAYEVENT_HEADATEND | XA_PLAYEVENT_HEADATMARKER | XA_PLAYEVENT_HEADATNEWPOS); 54875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 54975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 55075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set a marker 551b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetMarkerPosition(playerPlay, 5000); 55275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 55375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 55475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set position update period 555b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->SetPositionUpdatePeriod(playerPlay, 2000); 55675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 55775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 558b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the position before prefetch 559b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAmillisecond position; 560b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 561b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 562b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Position before prefetch: %u ms\n", position); 563b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 564b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the duration before prefetch 56575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten XAmillisecond duration; 56675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->GetDuration(playerPlay, &duration); 56775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 56875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (XA_TIME_UNKNOWN == duration) 569b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration before prefetch: unknown as expected\n"); 57075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten else 571b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration before prefetch: %.1f (surprise!)\n", duration / 1000.0f); 57275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 57375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // set the player's state to paused, to start prefetching 57475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten printf("start prefetch\n"); 57575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, XA_PLAYSTATE_PAUSED); 57675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 57775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 57875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten // wait for prefetch status callback to indicate either sufficient data or error 57975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_mutex_lock(&mutex); 58075290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten while (prefetch_status == PREFETCHSTATUS_UNKNOWN) { 58175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_cond_wait(&cond, &mutex); 58275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 58375290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten pthread_mutex_unlock(&mutex); 58475290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (prefetch_status == PREFETCHSTATUS_ERROR) { 58575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten fprintf(stderr, "Error during prefetch, exiting\n"); 58675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten goto destroyRes; 58775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 58875290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 589b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get the position after prefetch 590b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerPlay)->GetPosition(playerPlay, &position); 591b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 592b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Position after prefetch: %u ms\n", position); 593b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 594b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // get duration again, now it should be known for the file source or unknown for TS 59575290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten result = (*playerPlay)->GetDuration(playerPlay, &duration); 59675290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten assert(XA_RESULT_SUCCESS == result); 59775290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten if (duration == XA_TIME_UNKNOWN) { 598b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration after prefetch: unknown (expected for TS, unexpected for file)\n"); 59975290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } else { 600b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Duration after prefetch: %u ms (expected for file, unexpected for TS)\n", duration); 60175290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten } 60275290ff394698c53f35a21612c03b8ddd21fecf9Glenn Kasten 603b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // query for media container information 604b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryMediaContainerInformation(playerStreamInformation, 605b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten NULL); 606b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_PARAMETER_INVALID == result); 607b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAMediaContainerInformation mediaContainerInformation; 608b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // this verifies it is filling in all the fields 609b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten memset(&mediaContainerInformation, 0x55, sizeof(XAMediaContainerInformation)); 610b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten result = (*playerStreamInformation)->QueryMediaContainerInformation(playerStreamInformation, 611b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten &mediaContainerInformation); 612b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten assert(XA_RESULT_SUCCESS == result); 613b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf("Media container information:\n"); 614b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" containerType = %u\n", mediaContainerInformation.containerType); 615b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" mediaDuration = %u\n", mediaContainerInformation.mediaDuration); 616b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten printf(" numStreams = %u\n", mediaContainerInformation.numStreams); 617b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten 618b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // Now query for each the streams. Note that stream indices go up to and including 619b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // mediaContainerInformation.numStreams, because stream 0 is the container itself, 620b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten // while stream 1 to mediaContainerInformation.numStreams are the contained streams. 621b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten XAuint32 numStreams = mediaContainerInformation.numStreams; 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); 809b17edb96ba759cd1197bf13cd13e279ee144da60Glenn Kasten if (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