OSDN Git Service

RIO-8910: Fix for MP3 parser returning incorrect value for bitrate key
[android-x86/external-opencore.git] / android / playerdriver.cpp
1 /* playerdriver.cpp
2 **
3 ** Copyright 2007, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "PlayerDriver"
20 #include <utils/Log.h>
21
22 #include <sys/prctl.h>
23 #include <sys/resource.h>
24 #include <media/mediaplayer.h>
25 #include <media/thread_init.h>
26 #include <utils/threads.h>
27 #include "playerdriver.h"
28 #include "PVPlayerExtHandler.h"
29
30 using namespace android;
31
32 # ifndef PAGESIZE
33 #  define PAGESIZE              4096
34 # endif
35
36 // library and function name to retrieve device-specific MIOs
37 static const char* MIO_LIBRARY_NAME = "libopencorehw.so";
38 static const char* VIDEO_MIO_FACTORY_NAME = "createVideoMio";
39 typedef AndroidSurfaceOutput* (*VideoMioFactory)();
40
41 namespace {
42
43
44 // For the event's buffer format is:
45 //                     1                   2                   3
46 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
47 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 // |                        buffering percent                      |
49 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 //
51 // @param buffer Pointer to the start of the buffering status data.
52 // @param size Of the buffer
53 // @param[out] percentage On return contains the amout of buffering.
54 //                        The value is in [0,100]
55 // @return true if a valid buffering update was found. false otherwise.
56 bool GetBufferingPercentage(const void *buffer,
57                             const size_t size,
58                             int *percentage)
59 {
60     if (buffer == NULL) {
61         LOGE("Invalid buffer: NULL");
62         return false;
63     }
64     if (sizeof(int) != size)
65     {
66         LOGE("Invalid percentage buffer size %d (expected %d)", size, sizeof(int));
67         return false;
68     }
69     // TODO: The PVEvent class should expose a memcopy method
70     // that does bound checking instead of having clients reaching
71     // for its internal buffer.
72     oscl_memcpy(percentage, buffer, sizeof(int));
73
74     // Clamp the value and complain loudly.
75     if (*percentage < 0 || *percentage > 100)
76     {
77         LOGE("Invalid percentage value %d", *percentage);
78         return false;
79     }
80     return true;
81 }
82
83 // Macro used in a switch statement to convert a PlayerCommand code into its
84 // string representation.
85 #ifdef CONSIDER_CODE
86 #error "CONSIDER_CODE already defined!!"
87 #endif
88 #define CONSIDER_CODE(val) case ::PlayerCommand::val: return #val
89
90 // Convert a command code into a string for logging purposes.
91 // @param code Of the command.
92 // @return a string representation of the command type.
93 const char *PlayerCommandCodeToString(PlayerCommand::Code code) {
94     switch (code) {
95         CONSIDER_CODE(PLAYER_QUIT);
96         CONSIDER_CODE(PLAYER_SETUP);
97         CONSIDER_CODE(PLAYER_SET_DATA_SOURCE);
98         CONSIDER_CODE(PLAYER_SET_VIDEO_SURFACE);
99         CONSIDER_CODE(PLAYER_SET_AUDIO_SINK);
100         CONSIDER_CODE(PLAYER_INIT);
101         CONSIDER_CODE(PLAYER_PREPARE);
102         CONSIDER_CODE(PLAYER_START);
103         CONSIDER_CODE(PLAYER_STOP);
104         CONSIDER_CODE(PLAYER_PAUSE);
105         CONSIDER_CODE(PLAYER_RESET);
106         CONSIDER_CODE(PLAYER_SET_LOOP);
107         CONSIDER_CODE(PLAYER_SEEK);
108         CONSIDER_CODE(PLAYER_GET_POSITION);
109         CONSIDER_CODE(PLAYER_GET_DURATION);
110         CONSIDER_CODE(PLAYER_GET_STATUS);
111         CONSIDER_CODE(PLAYER_REMOVE_DATA_SOURCE);
112         CONSIDER_CODE(PLAYER_CANCEL_ALL_COMMANDS);
113         CONSIDER_CODE(PLAYER_EXTENSION_COMMAND);
114         default: return "UNKNOWN PlayerCommand code";
115     }
116 }
117 #undef CONSIDER_CODE
118
119 // Map a PV status code to a message type (error/info/nop)
120 // @param status PacketVideo status code as defined in pvmf_return_codes.h
121 // @return the corresponding android message type. MEDIA_NOP is used as a default.
122 ::android::media_event_type MapStatusToEventType(const PVMFStatus status) {
123     if (status <= PVMFErrFirst) {
124         return ::android::MEDIA_ERROR;
125     } else if (status >= PVMFInfoFirst) {
126         return ::android::MEDIA_INFO;
127     } else {
128         return ::android::MEDIA_NOP;
129     }
130 }
131
132 // Map a PV status to an error/info code.
133 // @param status PacketVideo status code as defined in pvmf_return_codes.h
134 // @return the corresponding android error/info code.
135 int MapStatusToEventCode(const PVMFStatus status) {
136     switch (status) {
137         case PVMFErrContentInvalidForProgressivePlayback :
138             LOGE("PVMFErrContentInvalidForProgressivePlayback event recieved");
139             return ::android::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK;
140
141         default:
142             // Takes advantage that both error and info codes are mapped to the
143             // same value.
144             assert(::android::MEDIA_ERROR_UNKNOWN == ::android::MEDIA_INFO_UNKNOWN);
145             return ::android::MEDIA_ERROR_UNKNOWN;
146     }
147 }
148
149 }  // anonymous namespace
150
151
152 PlayerDriver::PlayerDriver(PVPlayer* pvPlayer) :
153         OsclActiveObject(OsclActiveObject::EPriorityNominal, "PVPlayerPlayer"),
154         mPvPlayer(pvPlayer),
155         mIsLooping(false),
156         mDoLoop(false),
157         mDataReadyReceived(false),
158         mPrepareDone(false),
159         mEndOfData(false),
160         mRecentSeek(0),
161         mSeekComp(true),
162         mSeekPending(false),
163         mIsLiveStreaming(false),
164         mEmulation(false)
165 {
166     LOGV("constructor");
167     mSyncSem = new OsclSemaphore();
168     mSyncSem->Create();
169
170     mDataSource = NULL;
171     mAudioSink = NULL;
172     mAudioNode = NULL;
173     mAudioOutputMIO = NULL;
174     mVideoSink = NULL;
175     mVideoNode = NULL;
176     mVideoOutputMIO = NULL;
177
178     mPlayerCapConfig = NULL;
179     mDownloadContextData = NULL;
180     mLocalContextData = NULL;
181     mExtensionHandler = NULL;
182
183     // running in emulation?
184     mLibHandle = NULL;
185     char value[PROPERTY_VALUE_MAX];
186     if (property_get("ro.kernel.qemu", value, 0)) {
187         mEmulation = true;
188         LOGV("Emulation mode - using software codecs");
189     } else {
190         // attempt to open h/w specific library
191         mLibHandle = ::dlopen(MIO_LIBRARY_NAME, RTLD_NOW);
192         if (mLibHandle != NULL) {
193             LOGV("OpenCore hardware module loaded");
194         } else {
195             LOGV("OpenCore hardware module not found");
196         }
197     }
198
199     // start player thread
200     LOGV("start player thread");
201     createThreadEtc(PlayerDriver::startPlayerThread, this, "PV player");
202
203     // mSyncSem will be signaled when the scheduler has started
204     mSyncSem->Wait();
205     mExtensionHandler = new PVPlayerExtensionHandler(*this);
206     if(!mExtensionHandler){
207        LOGV("No ExtensionHandler, Out of memory");
208     }
209 }
210
211 PlayerDriver::~PlayerDriver()
212 {
213     LOGV("destructor");
214     if (mLibHandle != NULL) {
215         ::dlclose(mLibHandle);
216     }
217     if(mExtensionHandler){
218         delete mExtensionHandler; mExtensionHandler=NULL;
219     }
220 }
221
222 PlayerCommand* PlayerDriver::dequeueCommand()
223 {
224     PlayerCommand* command;
225
226     mQueueLock.lock();
227
228     // XXX should we assert here?
229     if (mCommandQueue.empty()) {
230         PendForExec();
231         mQueueLock.unlock();
232         return NULL;
233     }
234
235     command = *(--mCommandQueue.end());
236     mCommandQueue.erase(--mCommandQueue.end());
237     if (mCommandQueue.size() > 0 )
238     {
239         RunIfNotReady();
240     }
241     else
242     {
243         PendForExec();
244     }
245     mQueueLock.unlock();
246
247     return command;
248 }
249
250 status_t PlayerDriver::enqueueCommand(PlayerCommand* command)
251 {
252     if (mPlayer == NULL) {
253         // Only commands which can come in this use-case is PLAYER_SETUP and PLAYER_QUIT
254         // The calling function should take responsibility to delete the command and cleanup
255         return NO_INIT;
256     }
257
258     OsclSemaphore *syncsemcopy = NULL;
259
260     // If the user didn't specify a completion callback, we
261     // are running in synchronous mode.
262     if (!command->hasCallback()) {
263         command->set(PlayerDriver::syncCompletion, this);
264         // make a copy of this semaphore for special handling of the PLAYER_QUIT code
265         syncsemcopy = mSyncSem;
266     }
267
268     // Add the code to the queue.
269     mQueueLock.lock();
270     mCommandQueue.push_front(command);
271
272     // save code, since command will be deleted by the standard completion function
273     int code = command->code();
274
275     // AO needs to be scheduled only if this is the first cmd after queue was empty
276     if (mCommandQueue.size() == 1)
277     {
278         PendComplete(OSCL_REQUEST_ERR_NONE);
279     }
280     mQueueLock.unlock();
281
282     // If we are in synchronous mode, wait for completion.
283     if (syncsemcopy) {
284         syncsemcopy->Wait();
285         if (code == PlayerCommand::PLAYER_QUIT) {
286             syncsemcopy->Close();
287             delete syncsemcopy;
288             return 0;
289         }
290         return mSyncStatus;
291     }
292
293     return OK;
294 }
295
296 void PlayerDriver::FinishSyncCommand(PlayerCommand* command)
297 {
298     command->complete(NO_ERROR, false);
299     delete command;
300 }
301
302 // The OSCL scheduler calls this when we get to run (this should happen only
303 // when a code has been enqueued for us).
304 void PlayerDriver::Run()
305 {
306     if (mDoLoop) {
307         mEndOfData = false;
308         PVPPlaybackPosition begin, end;
309         begin.iIndeterminate = false;
310         begin.iPosUnit = PVPPBPOSUNIT_SEC;
311         begin.iPosValue.sec_value = 0;
312         begin.iMode = PVPPBPOS_MODE_NOW;
313         end.iIndeterminate = true;
314         mPlayer->SetPlaybackRange(begin, end, false, NULL);
315         mPlayer->Resume();
316         return;
317     }
318
319     PVPlayerState state = PVP_STATE_ERROR;
320     if ((mPlayer->GetPVPlayerStateSync(state) == PVMFSuccess))
321     {
322         if (state == PVP_STATE_ERROR)
323         {
324             return;
325         }
326     }
327
328
329     PlayerCommand* command;
330
331     command = dequeueCommand();
332     if (command) {
333         LOGV("Send player code: %d", command->code());
334
335         switch (command->code()) {
336             case PlayerCommand::PLAYER_SETUP:
337                 handleSetup(static_cast<PlayerSetup*>(command));
338                 break;
339
340             case PlayerCommand::PLAYER_SET_DATA_SOURCE:
341                 handleSetDataSource(static_cast<PlayerSetDataSource*>(command));
342                 break;
343
344             case PlayerCommand::PLAYER_SET_VIDEO_SURFACE:
345                 handleSetVideoSurface(static_cast<PlayerSetVideoSurface*>(command));
346                 break;
347
348             case PlayerCommand::PLAYER_SET_AUDIO_SINK:
349                 handleSetAudioSink(static_cast<PlayerSetAudioSink*>(command));
350                 break;
351
352             case PlayerCommand::PLAYER_INIT:
353                 handleInit(static_cast<PlayerInit*>(command));
354                 break;
355
356             case PlayerCommand::PLAYER_PREPARE:
357                 handlePrepare(static_cast<PlayerPrepare*>(command));
358                 break;
359
360             case PlayerCommand::PLAYER_START:
361                 handleStart(static_cast<PlayerStart*>(command));
362                 break;
363
364             case PlayerCommand::PLAYER_STOP:
365                 handleStop(static_cast<PlayerStop*>(command));
366                 break;
367
368             case PlayerCommand::PLAYER_PAUSE:
369                 {
370                     if(mIsLiveStreaming) {
371                         LOGW("Pause denied");
372                         FinishSyncCommand(command);
373                         return;
374                     }
375                     handlePause(static_cast<PlayerPause*>(command));
376                 }
377                 break;
378
379             case PlayerCommand::PLAYER_SEEK:
380                 {
381                     if(mIsLiveStreaming) {
382                         LOGW("Seek denied");
383                         mPvPlayer->sendEvent(MEDIA_SEEK_COMPLETE);
384                         FinishSyncCommand(command);
385                         return;
386                     }
387                     handleSeek(static_cast<PlayerSeek*>(command));
388                 }
389                 break;
390
391             case PlayerCommand::PLAYER_GET_POSITION:
392                 handleGetPosition(static_cast<PlayerGetPosition*>(command));
393                 FinishSyncCommand(command);
394                 return;
395
396             case PlayerCommand::PLAYER_GET_STATUS:
397                 handleGetStatus(static_cast<PlayerGetStatus*>(command));
398                 FinishSyncCommand(command);
399                 return;
400
401             case PlayerCommand::PLAYER_CHECK_LIVE_STREAMING:
402                 handleCheckLiveStreaming(static_cast<PlayerCheckLiveStreaming*>(command));
403                 break;
404
405             case PlayerCommand::PLAYER_GET_DURATION:
406                 handleGetDuration(static_cast<PlayerGetDuration*>(command));
407                 break;
408
409             case PlayerCommand::PLAYER_REMOVE_DATA_SOURCE:
410                 handleRemoveDataSource(static_cast<PlayerRemoveDataSource*>(command));
411                 break;
412
413             case PlayerCommand::PLAYER_CANCEL_ALL_COMMANDS:
414                 handleCancelAllCommands(static_cast<PlayerCancelAllCommands*>(command));
415                 break;
416
417             case PlayerCommand::PLAYER_RESET:
418                 handleReset(static_cast<PlayerReset*>(command));
419                 break;
420
421             case PlayerCommand::PLAYER_QUIT:
422                 handleQuit(static_cast<PlayerQuit*>(command));
423                 return;
424
425             case PlayerCommand::PLAYER_SET_LOOP:
426                 mIsLooping = static_cast<PlayerSetLoop*>(command)->loop();
427                 FinishSyncCommand(command);
428                 return;
429
430             case PlayerCommand::PLAYER_EXTENSION_COMMAND:
431                 handleExtensionCommand(static_cast<PlayerExtensionCommand*>(command));
432                 return;
433             default:
434                 LOGE("Unexpected code %d", command->code());
435                 break;
436         }
437     }
438
439 }
440
441 void PlayerDriver::commandFailed(PlayerCommand* command)
442 {
443     if (command == NULL) {
444         LOGV("async code failed");
445         return;
446     }
447
448     LOGV("Command failed: %d", command->code());
449     command->complete(UNKNOWN_ERROR, false);
450     delete command;
451 }
452
453 void PlayerDriver::handleSetup(PlayerSetup* command)
454 {
455     int error = 0;
456
457     // Make sure we have the capabilities and config interface first.
458     OSCL_TRY(error, mPlayer->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID,
459                                             (PVInterface *&)mPlayerCapConfig, command));
460     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
461 }
462
463 int PlayerDriver::setupHttpStreamPre()
464 {
465     mDataSource->SetDataSourceFormatType((char*)PVMF_MIME_DATA_SOURCE_HTTP_URL);
466
467     delete mDownloadContextData;
468     mDownloadContextData = NULL;
469
470     mDownloadContextData = new PVMFSourceContextData();
471     mDownloadContextData->EnableCommonSourceContext();
472     mDownloadContextData->EnableDownloadHTTPSourceContext();
473
474     mDownloadConfigFilename = _STRLIT_WCHAR("/tmp/http-stream-cfg");
475     mDownloadFilename = NULL;
476     mDownloadProxy = _STRLIT_CHAR("");
477
478     mDownloadContextData->DownloadHTTPData()->iMaxFileSize = 0xFFFFFFFF;
479     mDownloadContextData->DownloadHTTPData()->iPlaybackControl = PVMFSourceContextDataDownloadHTTP::ENoSaveToFile;
480     mDownloadContextData->DownloadHTTPData()->iConfigFileName = mDownloadConfigFilename;
481     mDownloadContextData->DownloadHTTPData()->iDownloadFileName = mDownloadFilename;
482     mDownloadContextData->DownloadHTTPData()->iProxyName = mDownloadProxy;
483     mDownloadContextData->DownloadHTTPData()->iProxyPort = 0;
484     mDownloadContextData->DownloadHTTPData()->bIsNewSession = true;
485
486     mDataSource->SetDataSourceContextData(mDownloadContextData);
487
488     return 0;
489 }
490
491 int PlayerDriver::setupHttpStreamPost()
492 {
493     PvmiKvp iKVPSetAsync;
494     OSCL_StackString<64> iKeyStringSetAsync;
495     PvmiKvp *iErrorKVP = NULL;
496
497     int error = 0;
498
499     iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/http-timeout;valtype=uint32");
500     iKVPSetAsync.key=iKeyStringSetAsync.get_str();
501     iKVPSetAsync.value.uint32_value=20;
502     iErrorKVP=NULL;
503     OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
504     OSCL_FIRST_CATCH_ANY(error, return -1);
505
506     iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/num-redirect-attempts;valtype=uint32");
507     iKVPSetAsync.key=iKeyStringSetAsync.get_str();
508     iKVPSetAsync.value.uint32_value=4;
509     iErrorKVP=NULL;
510     OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
511     OSCL_FIRST_CATCH_ANY(error, return -1);
512
513     // enable or disable HEAD request
514     iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/http-header-request-disabled;valtype=bool");
515     iKVPSetAsync.key=iKeyStringSetAsync.get_str();
516     iKVPSetAsync.value.bool_value=false;
517     iErrorKVP=NULL;
518     OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
519     OSCL_FIRST_CATCH_ANY(error, return -1);
520
521     iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/max-tcp-recv-buffer-size-download;valtype=uint32");
522     iKVPSetAsync.key=iKeyStringSetAsync.get_str();
523     iKVPSetAsync.value.uint32_value=64000;
524     iErrorKVP=NULL;
525     OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
526     OSCL_FIRST_CATCH_ANY(error, return -1);
527
528     return 0;
529 }
530
531 void PlayerDriver::handleSetDataSource(PlayerSetDataSource* command)
532 {
533     LOGV("handleSetDataSource");
534     int error = 0;
535     const char* url = command->url();
536     int lengthofurl = strlen(url);
537     oscl_wchar output[lengthofurl + 1];
538     OSCL_wHeapString<OsclMemAllocator> wFileName;
539
540     if (mDataSource) {
541         delete mDataSource;
542         mDataSource = NULL;
543     }
544
545     // Create a URL datasource to feed PVPlayer
546     mDataSource = new PVPlayerDataSourceURL();
547     oscl_UTF8ToUnicode(url, strlen(url), output, lengthofurl+1);
548     wFileName.set(output, oscl_strlen(output));
549     mDataSource->SetDataSourceURL(wFileName);
550     LOGV("handleSetDataSource- scanning for extension");
551     if (strncmp(url, "rtsp:", strlen("rtsp:")) == 0) {
552         mDataSource->SetDataSourceFormatType((const char*)PVMF_MIME_DATA_SOURCE_RTSP_URL);
553     } else if (strncmp(url, "http:", strlen("http:")) == 0) {
554         if (0!=setupHttpStreamPre())
555         {
556             commandFailed(command);
557             return;
558         }
559     } else {
560         LOGV("handleSetDataSource - called with a filepath - %s",url);
561         mDataSource->SetDataSourceFormatType((const char*)PVMF_MIME_FORMAT_UNKNOWN); // Let PV figure it out
562         delete mLocalContextData;
563         mLocalContextData = NULL;
564         const char* ext = strrchr(url, '.');
565         if (ext && ( strcasecmp(ext, ".sdp") == 0) ) {
566             // For SDP files, currently there is no recognizer. So, to play from such files,
567             // there is a need to set the format type.
568             mDataSource->SetDataSourceFormatType((const char*)PVMF_MIME_DATA_SOURCE_SDP_FILE);
569         }
570         mLocalContextData = new PVMFSourceContextData();
571         mLocalContextData->EnableCommonSourceContext();
572         mDataSource->SetDataSourceContextData((OsclAny*)mLocalContextData);
573     }
574     OSCL_TRY(error, mPlayer->AddDataSource(*mDataSource, command));
575     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
576 }
577
578 void PlayerDriver::handleInit(PlayerInit* command)
579 {
580     int error = 0;
581
582     if (mDownloadContextData) {
583         setupHttpStreamPost();
584     }
585
586     if (mLocalContextData) {
587         PvmiKvp iKVPSetAsync;
588         int error = 0;
589
590         OSCL_StackString<64> iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/parser/mp4ff-open-file-once-per-track;valtype=bool");
591         iKVPSetAsync.key=iKeyStringSetAsync.get_str();
592         iKVPSetAsync.value.bool_value=false;
593         PvmiKvp* iErrorKVP=NULL;
594         OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
595         OSCL_FIRST_CATCH_ANY(error, return;);
596     }
597
598     {
599         PvmiKvp iKVPSetAsync;
600         OSCL_StackString<64> iKeyStringSetAsync;
601         iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/user-agent;valtype=wchar*");
602         iKVPSetAsync.key=iKeyStringSetAsync.get_str();
603         // The CORE and OpenCORE versions are set and maintained by PV
604         OSCL_wHeapString<OsclMemAllocator> userAgent = _STRLIT_WCHAR("CORE/8.507.1.1 OpenCORE/2.07 (Linux;Android ");
605
606 #if (PROPERTY_VALUE_MAX < 8)
607 #error "PROPERTY_VALUE_MAX must be at least 8"
608 #endif
609         char value[PROPERTY_VALUE_MAX];
610         int len = property_get("ro.build.version.release", value, "Unknown");
611         if (len) {
612             LOGV("release string is %s len %d", value, len);
613             oscl_wchar output[len+ 1];
614             oscl_UTF8ToUnicode(value, len, output, len+1);
615             userAgent += output;
616         }
617         userAgent += _STRLIT_WCHAR(")");
618
619         iKVPSetAsync.value.pWChar_value=userAgent.get_str();
620         int error = 0;
621         PvmiKvp *iErrorKVP = NULL;
622         OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
623         OSCL_FIRST_CATCH_ANY(error,
624                 LOGE("handleInit- setParametersSync ERROR setting useragent");
625                 );
626     }
627
628     OSCL_TRY(error, mPlayer->Init(command));
629     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
630 }
631
632 void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* command)
633 {
634     int error = 0;
635     AndroidSurfaceOutput* mio = NULL;
636
637     // attempt to load device-specific video MIO
638     if (mLibHandle != NULL) {
639         VideoMioFactory f = (VideoMioFactory) ::dlsym(mLibHandle, VIDEO_MIO_FACTORY_NAME);
640         if (f != NULL) {
641             mio = f();
642         }
643     }
644
645     // if no device-specific MIO was created, use the generic one
646     if (mio == NULL) {
647         LOGW("Using generic video MIO");
648         mio = new AndroidSurfaceOutput();
649     }
650
651     // initialize the MIO parameters
652     status_t ret = mio->set(mPvPlayer, command->surface(), mEmulation);
653     if (ret != NO_ERROR) {
654         LOGE("Video MIO set failed");
655         commandFailed(command);
656         delete mio;
657         return;
658     }
659     mVideoOutputMIO = mio;
660
661     mVideoNode = PVMediaOutputNodeFactory::CreateMediaOutputNode(mVideoOutputMIO);
662     mVideoSink = new PVPlayerDataSinkPVMFNode;
663
664     ((PVPlayerDataSinkPVMFNode *)mVideoSink)->SetDataSinkNode(mVideoNode);
665
666     OSCL_TRY(error, mPlayer->AddDataSink(*mVideoSink, command));
667     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
668 }
669
670 void PlayerDriver::handleSetAudioSink(PlayerSetAudioSink* command)
671 {
672     int error = 0;
673     if (command->audioSink()->realtime()) {
674         LOGV("Create realtime output");
675         mAudioOutputMIO = new AndroidAudioOutput();
676     } else {
677         LOGV("Create stream output");
678         mAudioOutputMIO = new AndroidAudioStream();
679     }
680     mAudioOutputMIO->setAudioSink(command->audioSink());
681
682     mAudioNode = PVMediaOutputNodeFactory::CreateMediaOutputNode(mAudioOutputMIO);
683     mAudioSink = new PVPlayerDataSinkPVMFNode;
684
685     ((PVPlayerDataSinkPVMFNode *)mAudioSink)->SetDataSinkNode(mAudioNode);
686
687     OSCL_TRY(error, mPlayer->AddDataSink(*mAudioSink, command));
688     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
689 }
690
691 void PlayerDriver::handlePrepare(PlayerPrepare* command)
692 {
693     //Keep alive is sent during the play to prevent the firewall from closing ports while
694     //streaming long clip
695     PvmiKvp iKVPSetAsync;
696     OSCL_StackString<64> iKeyStringSetAsync;
697     PvmiKvp *iErrorKVP = NULL;
698     int error=0;
699     iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/keep-alive-during-play;valtype=bool");
700     iKVPSetAsync.key=iKeyStringSetAsync.get_str();
701     iKVPSetAsync.value.bool_value=true;
702     iErrorKVP=NULL;
703     OSCL_TRY(error, mPlayerCapConfig->setParametersSync(NULL, &iKVPSetAsync, 1, iErrorKVP));
704     OSCL_TRY(error, mPlayer->Prepare(command));
705     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
706
707     char value[PROPERTY_VALUE_MAX] = {"0"};
708     property_get("ro.com.android.disable_rtsp_nat", value, "0");
709     LOGV("disable natpkt - %s",value);
710     if (1 == atoi(value))
711     {
712         //disable firewall packet
713         iKeyStringSetAsync=_STRLIT_CHAR("x-pvmf/net/disable-firewall-packets;valtype=bool");
714         iKVPSetAsync.key=iKeyStringSetAsync.get_str();
715         iKVPSetAsync.value.bool_value = 1; //1 - disable
716         iErrorKVP=NULL;
717         OSCL_TRY(error,mPlayerCapConfig->setParametersSync(NULL,&iKVPSetAsync,1,iErrorKVP));
718     }
719 }
720
721 void PlayerDriver::handleStart(PlayerStart* command)
722 {
723     int error = 0;
724
725     // for video, set thread priority so we don't hog CPU
726     if (mVideoOutputMIO) {
727         int ret = setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
728     }
729     // for audio, set thread priority so audio isn't choppy
730     else {
731         int ret = setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
732     }
733
734     // Signalling seek complete to continue obtaining the current position
735     // from PVPlayer Engine
736     mSeekComp = true;
737     // if we are paused, just resume
738     PVPlayerState state;
739     if (mPlayer->GetPVPlayerStateSync(state) == PVMFSuccess
740         && (state == PVP_STATE_PAUSED)) {
741         if (mEndOfData) {
742             // if we are at the end, seek to the beginning first
743             mEndOfData = false;
744             PVPPlaybackPosition begin, end;
745             begin.iIndeterminate = false;
746             begin.iPosUnit = PVPPBPOSUNIT_SEC;
747             begin.iPosValue.sec_value = 0;
748             begin.iMode = PVPPBPOS_MODE_NOW;
749             end.iIndeterminate = true;
750             mPlayer->SetPlaybackRange(begin, end, false, NULL);
751         }
752         OSCL_TRY(error, mPlayer->Resume(command));
753         OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
754     } else {
755         OSCL_TRY(error, mPlayer->Start(command));
756         OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
757     }
758 }
759
760 void PlayerDriver::handleSeek(PlayerSeek* command)
761 {
762     int error = 0;
763
764     LOGV("handleSeek");
765     // Cache the most recent seek request
766     mRecentSeek = command->msec();
767     // Seeking in the pause state
768     PVPlayerState state;
769     if (mPlayer->GetPVPlayerStateSync(state) == PVMFSuccess
770         && (state == PVP_STATE_PAUSED)) {
771         mSeekComp = false;
772     }
773     PVPPlaybackPosition begin, end;
774     begin.iIndeterminate = false;
775     begin.iPosUnit = PVPPBPOSUNIT_MILLISEC;
776     begin.iPosValue.millisec_value = command->msec();
777     begin.iMode = PVPPBPOS_MODE_NOW;
778     end.iIndeterminate = true;
779     mSeekPending = true;
780     OSCL_TRY(error, mPlayer->SetPlaybackRange(begin, end, false, command));
781     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
782
783     mEndOfData = false;
784 }
785
786 void PlayerDriver::handleGetPosition(PlayerGetPosition* command)
787 {
788     PVPPlaybackPosition pos;
789     pos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
790     PVPlayerState state;
791     //  In the pause state, get the progress bar position from the recent seek value
792     // instead of GetCurrentPosition() from PVPlayer Engine.
793     if (mPlayer->GetPVPlayerStateSync(state) == PVMFSuccess
794         && (state == PVP_STATE_PAUSED)
795         && (mSeekComp == false)) {
796         command->set(mRecentSeek);
797     }
798     else {
799         if (mPlayer->GetCurrentPositionSync(pos) != PVMFSuccess) {
800             command->set(-1);
801         } else {
802             LOGV("position=%d", pos.iPosValue.millisec_value);
803             command->set((int)pos.iPosValue.millisec_value);
804         }
805     }
806 }
807
808 void PlayerDriver::handleGetStatus(PlayerGetStatus* command)
809 {
810     PVPlayerState state;
811     if (mPlayer->GetPVPlayerStateSync(state) != PVMFSuccess) {
812         command->set(0);
813     } else {
814         command->set(state);
815         LOGV("status=%d", state);
816     }
817 }
818
819 void PlayerDriver::handleExtensionCommand(PlayerExtensionCommand* command)
820 {
821     LOGV("handleExtensionCommand");
822     if(mExtensionHandler){
823         if(mExtensionHandler->callPlayerExtension(command,command->getDataParcel(),command->getReplyParcel()) != NO_ERROR){
824             LOGW("handleExtensionCommand error");
825         }
826     }else{
827         LOGV("mExtensionHandler == NULL");
828         command->getReplyParcel().writeInt32(INVALID_OPERATION);
829         commandFailed(command);
830     }
831 }
832
833 void PlayerDriver::handleCheckLiveStreaming(PlayerCheckLiveStreaming* command)
834 {
835     LOGV("handleCheckLiveStreaming ...");
836     mCheckLiveKey.clear();
837     mCheckLiveKey.push_back(OSCL_HeapString<OsclMemAllocator>("pause-denied"));
838     mCheckLiveValue.clear();
839     int error = 0;
840     OSCL_TRY(error, mPlayer->GetMetadataValues(mCheckLiveKey, 0, 1, mCheckLiveMetaValues, mCheckLiveValue, command));
841     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
842 }
843
844 void PlayerDriver::handleGetDuration(PlayerGetDuration* command)
845 {
846     command->set(-1);
847     mMetaKeyList.clear();
848     mMetaKeyList.push_back(OSCL_HeapString<OsclMemAllocator>("duration"));
849     mMetaValueList.clear();
850     mNumMetaValues=0;
851     int error = 0;
852     OSCL_TRY(error, mPlayer->GetMetadataValues(mMetaKeyList,0,-1,mNumMetaValues,mMetaValueList, command));
853     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
854 }
855
856 void PlayerDriver::handleStop(PlayerStop* command)
857 {
858     int error = 0;
859     // setting the looping boolean to false. MediaPlayer app takes care of setting the loop again before the start.
860     mIsLooping = false;
861     mDoLoop = false;
862     PVPlayerState state;
863     if ((mPlayer->GetPVPlayerStateSync(state) == PVMFSuccess)
864         && ( (state == PVP_STATE_PAUSED) ||
865              (state == PVP_STATE_PREPARED) ||
866              (state == PVP_STATE_STARTED) ))
867     {
868         OSCL_TRY(error, mPlayer->Stop(command));
869         OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
870     }
871     else
872     {
873         LOGV("handleStop - Player State = %d - Sending Reset instead of Stop\n",state);
874         // TODO: Previously this called CancelAllCommands and RemoveDataSource
875         handleReset(new PlayerReset(command->callback(), command->cookie()));
876         delete command;
877     }
878 }
879
880 void PlayerDriver::handlePause(PlayerPause* command)
881 {
882     LOGV("call pause");
883     int error = 0;
884     OSCL_TRY(error, mPlayer->Pause(command));
885     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
886 }
887
888 void PlayerDriver::handleRemoveDataSource(PlayerRemoveDataSource* command)
889 {
890     LOGV("handleRemoveDataSource");
891     int error = 0;
892     OSCL_TRY(error, mPlayer->RemoveDataSource(*mDataSource, command));
893     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
894 }
895
896 void PlayerDriver::handleCancelAllCommands(PlayerCancelAllCommands* command)
897 {
898     LOGV("handleCancelAllCommands");
899     int error = 0;
900     OSCL_TRY(error, mPlayer->CancelAllCommands(command));
901     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
902 }
903
904 void PlayerDriver::handleReset(PlayerReset* command)
905 {
906     LOGV("handleReset");
907     int error = 0;
908
909     // setting the looping boolean to false. MediaPlayer app takes care of setting the loop again before the start.
910     mIsLooping = false;
911     mDoLoop = false;
912     mEndOfData = false;
913
914     OSCL_TRY(error, mPlayer->Reset(command));
915     OSCL_FIRST_CATCH_ANY(error, commandFailed(command));
916 }
917
918 void PlayerDriver::handleQuit(PlayerQuit* command)
919 {
920     OsclExecScheduler *sched = OsclExecScheduler::Current();
921     sched->StopScheduler();
922 }
923
924 PVMFFormatType PlayerDriver::getFormatType()
925 {
926     return mDataSource->GetDataSourceFormatType();
927 }
928
929 /*static*/ int PlayerDriver::startPlayerThread(void *cookie)
930 {
931     LOGV("startPlayerThread");
932     PlayerDriver *ed = (PlayerDriver *)cookie;
933     return ed->playerThread();
934 }
935
936 int PlayerDriver::playerThread()
937 {
938     int error;
939
940     LOGV("InitializeForThread");
941     if (!InitializeForThread())
942     {
943         LOGV("InitializeForThread fail");
944         mPlayer = NULL;
945         mSyncSem->Signal();
946         return -1;
947     }
948
949     LOGV("OMX_MasterInit");
950     OMX_MasterInit();
951
952     LOGV("OsclScheduler::Init");
953     OsclScheduler::Init("AndroidPVWrapper");
954
955     LOGV("CreatePlayer");
956     OSCL_TRY(error, mPlayer = PVPlayerFactory::CreatePlayer(this, this, this));
957     if (error) {
958         // Just crash the first time someone tries to use it for now?
959         mPlayer = NULL;
960         mSyncSem->Signal();
961         return -1;
962     }
963
964     LOGV("AddToScheduler");
965     AddToScheduler();
966     LOGV("PendForExec");
967     PendForExec();
968
969     LOGV("OsclActiveScheduler::Current");
970     OsclExecScheduler *sched = OsclExecScheduler::Current();
971     LOGV("StartScheduler");
972     sched->StartScheduler(mSyncSem);
973
974     LOGV("DeletePlayer");
975     PVPlayerFactory::DeletePlayer(mPlayer);
976
977     delete mDownloadContextData;
978     mDownloadContextData = NULL;
979
980     delete mLocalContextData;
981     mLocalContextData = NULL;
982
983     delete mDataSource;
984     mDataSource = NULL;
985     delete mAudioSink;
986     PVMediaOutputNodeFactory::DeleteMediaOutputNode(mAudioNode);
987     delete mAudioOutputMIO;
988     delete mVideoSink;
989     if (mVideoNode) {
990         PVMediaOutputNodeFactory::DeleteMediaOutputNode(mVideoNode);
991         delete mVideoOutputMIO;
992     }
993
994     mSyncStatus = OK;
995     mSyncSem->Signal();
996     // note that we only signal mSyncSem. Deleting it is handled
997     // in enqueueCommand(). This is done because waiting for an
998     // already-deleted OsclSemaphore doesn't work (it blocks),
999     // and it's entirely possible for this thread to exit before
1000     // enqueueCommand() gets around to waiting for the semaphore.
1001
1002     // do some of destructor's work here
1003     // goodbye cruel world
1004     delete this;
1005
1006     //Moved after the delete this, as Oscl cleanup should be done in the end.
1007     //delete this was cleaning up OsclSemaphore objects, eventually causing a crash
1008     OsclScheduler::Cleanup();
1009     LOGV("OsclScheduler::Cleanup");
1010
1011     LOGV("OMX_MasterDeinit");
1012     OMX_MasterDeinit();
1013     UninitializeForThread();
1014     return 0;
1015 }
1016
1017 /*static*/ void PlayerDriver::syncCompletion(status_t s, void *cookie, bool cancelled)
1018 {
1019     PlayerDriver *ed = static_cast<PlayerDriver*>(cookie);
1020     ed->mSyncStatus = s;
1021     ed->mSyncSem->Signal();
1022 }
1023
1024 void PlayerDriver::handleCheckLiveStreamingComplete(PlayerCheckLiveStreaming* cmd)
1025 {
1026     if (mCheckLiveValue.empty())
1027         return;
1028
1029     const char* substr = oscl_strstr((char*)(mCheckLiveValue[0].key), _STRLIT_CHAR("pause-denied;valtype=bool"));
1030     if (substr!=NULL) {
1031         if ( mCheckLiveValue[0].value.bool_value == true ) {
1032             LOGI("Live Streaming...");
1033             mIsLiveStreaming = true;
1034         }
1035     }
1036 }
1037
1038 void PlayerDriver::handleGetDurationComplete(PlayerGetDuration* cmd)
1039 {
1040     cmd->set(-1);
1041
1042     if (mMetaValueList.empty())
1043         return;
1044
1045     MediaClockConverter mcc;
1046
1047     for (uint32 i = 0; i < mMetaValueList.size(); ++i) {
1048         // Search for the duration
1049         const char* substr=oscl_strstr(mMetaValueList[i].key, _STRLIT_CHAR("duration;valtype=uint32;timescale="));
1050         if (substr!=NULL) {
1051             uint32 timescale=1000;
1052             if (PV_atoi((substr+34), 'd', timescale) == false) {
1053                 // Retrieving timescale failed so default to 1000
1054                 timescale=1000;
1055             }
1056             uint32 duration = mMetaValueList[i].value.uint32_value;
1057             if (duration > 0 && timescale > 0) {
1058                 //set the timescale
1059                 mcc.set_timescale(timescale);
1060                 //set the clock to the duration as per the timescale
1061                 mcc.set_clock(duration,0);
1062                 //convert to millisec
1063                 cmd->set(mcc.get_converted_ts(1000));
1064             }
1065         }
1066     }
1067 }
1068
1069 void PlayerDriver::CommandCompleted(const PVCmdResponse& aResponse)
1070 {
1071     LOGV("CommandCompleted");
1072     PVMFStatus status = aResponse.GetCmdStatus();
1073
1074     if (mDoLoop) {
1075         mDoLoop = false;
1076         RunIfNotReady();
1077         return;
1078     }
1079
1080     PlayerCommand* command = static_cast<PlayerCommand*>(aResponse.GetContext());
1081     LOGV("Completed command %s status=%s", command ? command->toString(): "<null>", PVMFStatusToString(status));
1082     if (command == NULL) return;
1083
1084     // FIXME: Ignore non-fatal seek errors because pvPlayerEngine returns these errors and retains it's state.
1085     if (mSeekPending) {
1086         mSeekPending = false;
1087         if ( ( (status == PVMFErrArgument) || (status == PVMFErrInvalidState) || (status == PVMFErrNotSupported) ) ) {
1088             LOGV("Ignoring error during seek");
1089             status = PVMFSuccess;
1090         }
1091     }
1092     if (command->code() == PlayerCommand::PLAYER_EXTENSION_COMMAND ) {
1093         // extension might want to know about command it initiated
1094         // returns true if command->complete was called by extension, else do it here
1095         if (mExtensionHandler->commandCompleted((PlayerExtensionCommand*)command, aResponse)) {
1096             return;
1097         }
1098     }
1099
1100     if (status == PVMFSuccess) {
1101         switch (command->code()) {
1102             case PlayerCommand::PLAYER_PREPARE:
1103                 LOGV("PLAYER_PREPARE complete mDownloadContextData=%p, mDataReadyReceived=%d", mDownloadContextData, mDataReadyReceived);
1104                 mPrepareDone = true;
1105                 // If we are streaming from the network, we
1106                 // have to wait until the first PVMFInfoDataReady
1107                 // is sent to notify the user that it is okay to
1108                 // begin playback.  If it is a local file, just
1109                 // send it now at the completion of Prepare().
1110                 if ((mDownloadContextData == NULL) || mDataReadyReceived) {
1111                     mPvPlayer->sendEvent(MEDIA_PREPARED);
1112                 }
1113                 break;
1114
1115             case PlayerCommand::PLAYER_GET_DURATION:
1116                 handleGetDurationComplete(static_cast<PlayerGetDuration*>(command));
1117                 break;
1118
1119             case PlayerCommand::PLAYER_CHECK_LIVE_STREAMING:
1120                 handleCheckLiveStreamingComplete(static_cast<PlayerCheckLiveStreaming*>(command));
1121                 break;
1122
1123             case PlayerCommand::PLAYER_PAUSE:
1124                 LOGV("pause complete");
1125                 break;
1126
1127             case PlayerCommand::PLAYER_SEEK:
1128                 mPvPlayer->sendEvent(MEDIA_SEEK_COMPLETE);
1129                 break;
1130
1131             default: /* shut up gcc */
1132                 break;
1133         }
1134
1135         // Call the user's requested completion function
1136         command->complete(NO_ERROR, false);
1137     } else if (status == PVMFErrCancelled) {
1138         // Ignore cancelled code return status (PVMFErrCancelled), since it is not an error.
1139         LOGE("Command (%d) was cancelled", command->code());
1140         status = PVMFSuccess;
1141         command->complete(NO_ERROR, true);
1142     } else {
1143         // Try to map the PV error code to an Android one.
1144         LOGE("Command %s completed with an error or info %s", command->toString(), PVMFStatusToString(status));
1145         const media_event_type event_type = MapStatusToEventType(status);
1146
1147         if (MEDIA_NOP != event_type) {
1148             mPvPlayer->sendEvent(event_type, MapStatusToEventCode(status), status);
1149         } else {
1150             LOGE("Ignoring: %d", status);
1151         }
1152         command->complete(UNKNOWN_ERROR, false);
1153     }
1154
1155     delete command;
1156 }
1157
1158 void PlayerDriver::HandleErrorEvent(const PVAsyncErrorEvent& aEvent)
1159 {
1160     PVMFStatus status = aEvent.GetEventType();
1161
1162     // Errors use negative codes (see pvmi/pvmf/include/pvmf_return_codes.h)
1163     if (status > PVMFErrFirst) {
1164         LOGE("HandleErrorEvent called with an non-error event [%d]!!", status);
1165     }
1166     LOGE("HandleErrorEvent: %s", PVMFStatusToString(status));
1167     // TODO: Map more of the PV error code into the Android Media Player ones.
1168     mPvPlayer->sendEvent(MEDIA_ERROR, ::android::MEDIA_ERROR_UNKNOWN, status);
1169 }
1170
1171 void PlayerDriver::HandleInformationalEvent(const PVAsyncInformationalEvent& aEvent)
1172 {
1173     PVMFStatus status = aEvent.GetEventType();
1174
1175     // Errors use negative codes (see pvmi/pvmf/include/pvmf_return_codes.h)
1176     if (status <= PVMFErrFirst) {
1177         // Errors should go to the HandleErrorEvent handler, not the
1178         // informational one.
1179         LOGE("HandleInformationalEvent called with an error event [%d]!!", status);
1180     }
1181
1182     LOGV("HandleInformationalEvent: %s", PVMFStatusToString(status));
1183
1184     switch (status) {
1185         case PVMFInfoEndOfData:
1186             mEndOfData = true;
1187             if (mIsLooping) {
1188                 mDoLoop = true;
1189                 Cancel();
1190                 RunIfNotReady();
1191             } else {
1192                 mPvPlayer->sendEvent(MEDIA_PLAYBACK_COMPLETE);
1193             }
1194             break;
1195
1196         case PVMFInfoErrorHandlingComplete:
1197             LOGW("PVMFInfoErrorHandlingComplete");
1198             RunIfNotReady();
1199             break;
1200
1201         case PVMFInfoBufferingStart:
1202             mPvPlayer->sendEvent(MEDIA_BUFFERING_UPDATE, 0);
1203             break;
1204
1205         case PVMFInfoBufferingStatus:
1206             {
1207                 const void *buffer = aEvent.GetLocalBuffer();
1208                 const size_t size = aEvent.GetLocalBufferSize();
1209                 int percentage;
1210
1211                 if (GetBufferingPercentage(buffer, size, &percentage))
1212                 {
1213                     LOGD("buffering (%d)", percentage);
1214                     mPvPlayer->sendEvent(MEDIA_BUFFERING_UPDATE, percentage);
1215                 }
1216             }
1217             break;
1218
1219         case PVMFInfoDurationAvailable:
1220             {
1221                 PVUuid infomsguuid = PVMFDurationInfoMessageInterfaceUUID;
1222                 PVMFDurationInfoMessageInterface* eventMsg = NULL;
1223                 PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface();
1224                 if (infoExtInterface &&
1225                     infoExtInterface->queryInterface(infomsguuid, (PVInterface*&)eventMsg))
1226                 {
1227                     PVUuid eventuuid;
1228                     int32 infoCode;
1229                     eventMsg->GetCodeUUID(infoCode, eventuuid);
1230                     if (eventuuid == infomsguuid)
1231                     {
1232                         uint32 SourceDurationInMS = eventMsg->GetDuration();
1233                         LOGV(".... with duration = %u ms",SourceDurationInMS);
1234                     }
1235                 }
1236             }
1237             break;
1238
1239         case PVMFInfoDataReady:
1240             if (mDataReadyReceived)
1241                 break;
1242             mDataReadyReceived = true;
1243             // If this is a network stream, we are now ready to play.
1244             if (mDownloadContextData && mPrepareDone) {
1245                 mPvPlayer->sendEvent(MEDIA_PREPARED);
1246             }
1247             break;
1248
1249         case PVMFInfoVideoTrackFallingBehind:
1250             // TODO: This event should not be passed to the user in the ERROR channel.
1251             LOGW("Video track fell behind");
1252             mPvPlayer->sendEvent(MEDIA_INFO, ::android::MEDIA_INFO_VIDEO_TRACK_LAGGING,
1253                                  PVMFInfoVideoTrackFallingBehind);
1254             break;
1255
1256         case PVMFInfoPoorlyInterleavedContent:
1257             // TODO: This event should not be passed to the user in the ERROR channel.
1258             LOGW("Poorly interleaved content.");
1259             mPvPlayer->sendEvent(MEDIA_INFO, ::android::MEDIA_INFO_BAD_INTERLEAVING,
1260                                  PVMFInfoPoorlyInterleavedContent);
1261             break;
1262
1263         case PVMFInfoContentTruncated:
1264             LOGE("Content is truncated.");
1265             break;
1266
1267         case PVMFInfoRemoteSourceNotification:
1268             {
1269                 PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface();
1270                 if (infoExtInterface)
1271                 {
1272                     PVUuid infomsguuid = PVMFFileFormatEventTypesUUID;
1273                     PVMFBasicErrorInfoMessage* eventMsg = OSCL_STATIC_CAST(PVMFBasicErrorInfoMessage*, infoExtInterface);
1274                     PVUuid eventuuid;
1275                     int32 infoCode;
1276                     eventMsg->GetCodeUUID(infoCode, eventuuid);
1277                     if (eventuuid == PVMFFileFormatEventTypesUUID)
1278                     {
1279                         if (infoCode == PVMFMP4FFParserInfoNotPseudostreamableFile)
1280                         {
1281                             LOGE("Not valid for Progressive Playback.");
1282                             mPvPlayer->sendEvent(MEDIA_ERROR, ::android::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK, PVMFInfoRemoteSourceNotification);
1283                         }
1284                     }
1285                 }
1286             }
1287             break;
1288
1289         /* Certain events we don't really care about, but don't
1290          * want log spewage, so just no-op them here.
1291          */
1292         case PVMFInfoPositionStatus:
1293         case PVMFInfoBufferingComplete:
1294         case PVMFInfoContentLength:
1295         case PVMFInfoContentType:
1296         case PVMFInfoUnderflow:
1297         case PVMFInfoDataDiscarded:
1298         case PVMFInfoActualPlaybackPosition:
1299             break;
1300
1301         default:
1302             LOGV("HandleInformationalEvent: type=%d UNHANDLED", status);
1303             mPvPlayer->sendEvent(MEDIA_INFO, ::android::MEDIA_INFO_UNKNOWN, status);
1304             break;
1305     }
1306 }
1307
1308 // ----------------------------------------------------------------------------
1309 // PlayerCommand implementation
1310 // ----------------------------------------------------------------------------
1311 const char* PlayerCommand::toString() const {
1312     return PlayerCommandCodeToString(code());
1313 }
1314
1315 namespace android {
1316
1317 #undef LOG_TAG
1318 #define LOG_TAG "PVPlayer"
1319
1320 #ifdef MAX_OPENCORE_INSTANCES
1321 /*static*/ volatile int32_t PVPlayer::sNumInstances = 0;
1322 #endif
1323
1324 // ----------------------------------------------------------------------------
1325 // implement the Packet Video player
1326 // ----------------------------------------------------------------------------
1327 PVPlayer::PVPlayer()
1328 {
1329     LOGV("PVPlayer constructor");
1330     mDataSourcePath = NULL;
1331     mSharedFd = -1;
1332     mIsDataSourceSet = false;
1333     mDuration = -1;
1334     mPlayerDriver = NULL;
1335
1336 #ifdef MAX_OPENCORE_INSTANCES
1337     if (android_atomic_inc(&sNumInstances) >= MAX_OPENCORE_INSTANCES) {
1338         LOGW("Exceeds maximum number of OpenCore instances");
1339         mInit = -EBUSY;
1340         return;
1341     }
1342 #endif
1343
1344     LOGV("construct PlayerDriver");
1345     mPlayerDriver = new PlayerDriver(this);
1346     LOGV("send PLAYER_SETUP");
1347     PlayerSetup* setup = new PlayerSetup(0,0);
1348     mInit = mPlayerDriver->enqueueCommand(setup);
1349     if (mInit == NO_INIT) {
1350         delete setup;
1351     }
1352 }
1353
1354 status_t PVPlayer::initCheck()
1355 {
1356     return mInit;
1357 }
1358
1359 PVPlayer::~PVPlayer()
1360 {
1361     LOGV("PVPlayer destructor");
1362     if (mPlayerDriver != NULL) {
1363         PlayerQuit quit = PlayerQuit(0,0);
1364         mPlayerDriver->enqueueCommand(&quit); // will wait on mSyncSem, signaled by player thread
1365     }
1366     free(mDataSourcePath);
1367     if (mSharedFd >= 0) {
1368         close(mSharedFd);
1369     }
1370 #ifdef MAX_OPENCORE_INSTANCES
1371     android_atomic_dec(&sNumInstances);
1372 #endif
1373 }
1374
1375 status_t PVPlayer::setDataSource(const char *url)
1376 {
1377     LOGV("setDataSource(%s)", url);
1378     if (mSharedFd >= 0) {
1379         close(mSharedFd);
1380         mSharedFd = -1;
1381     }
1382     free(mDataSourcePath);
1383     mDataSourcePath = NULL;
1384
1385     // Don't let somebody trick us in to reading some random block of memory
1386     if (strncmp("assethandle://", url, 14) == 0)
1387         return android::UNKNOWN_ERROR;
1388     mDataSourcePath = strdup(url);
1389     return OK;
1390 }
1391
1392 status_t PVPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
1393
1394     // This is all a big hack to allow PV to play from a file descriptor.
1395     // Eventually we'll fix PV to use a file descriptor directly instead
1396     // of using mmap().
1397     LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
1398     if (mSharedFd >= 0) {
1399         close(mSharedFd);
1400         mSharedFd = -1;
1401     }
1402     free(mDataSourcePath);
1403     mDataSourcePath = NULL;
1404
1405     char buf[80];
1406     mSharedFd = dup(fd);
1407     TOsclFileHandle handle = fdopen(mSharedFd,"rb");
1408     sprintf(buf, "assethandle://%ld:%lld:%lld", (long)handle, offset, length);
1409     mDataSourcePath = strdup(buf);
1410     return OK;
1411 }
1412
1413 status_t PVPlayer::setVideoSurface(const sp<ISurface>& surface)
1414 {
1415     LOGV("setVideoSurface(%p)", surface.get());
1416     mSurface = surface;
1417     return OK;
1418 }
1419
1420 status_t PVPlayer::prepare()
1421 {
1422     status_t ret;
1423
1424     // We need to differentiate the two valid use cases for prepare():
1425     // 1. new PVPlayer/reset()->setDataSource()->prepare()
1426     // 2. new PVPlayer/reset()->setDataSource()->prepare()/prepareAsync()
1427     //    ->start()->...->stop()->prepare()
1428     // If data source has already been set previously, no need to run
1429     // a sequence of commands and only the PLAYER_PREPARE code needs
1430     // to be run.
1431     if (!mIsDataSourceSet) {
1432         // set data source
1433         LOGV("prepare");
1434         LOGV("  data source = %s", mDataSourcePath);
1435         ret = mPlayerDriver->enqueueCommand(new PlayerSetDataSource(mDataSourcePath,0,0));
1436         if (ret != OK)
1437             return ret;
1438
1439         // init
1440         LOGV("  init");
1441         ret = mPlayerDriver->enqueueCommand(new PlayerInit(0,0));
1442         if (ret != OK)
1443             return ret;
1444
1445         // set video surface, if there is one
1446         if (mSurface != NULL) {
1447             LOGV("  set video surface");
1448             ret = mPlayerDriver->enqueueCommand(new PlayerSetVideoSurface(mSurface,0,0));
1449             if (ret != OK)
1450                 return ret;
1451         }
1452
1453         // set audio output
1454         // If we ever need to expose selectable audio output setup, this can be broken
1455         // out.  In the meantime, however, system audio routing APIs should suffice.
1456         LOGV("  set audio sink");
1457         ret = mPlayerDriver->enqueueCommand(new PlayerSetAudioSink(mAudioSink,0,0));
1458         if (ret != OK)
1459             return ret;
1460
1461         // New data source has been set successfully.
1462         mIsDataSourceSet = true;
1463     }
1464
1465     // prepare
1466     LOGV("  prepare");
1467     return mPlayerDriver->enqueueCommand(new PlayerPrepare(check_for_live_streaming, this));
1468 }
1469
1470 void PVPlayer::check_for_live_streaming(status_t s, void *cookie, bool cancelled)
1471 {
1472     LOGV("check_for_live_streaming s=%d, cancelled=%d", s, cancelled);
1473     if (s == NO_ERROR && !cancelled) {
1474         PVPlayer *p = (PVPlayer*)cookie;
1475         if ( (p->mPlayerDriver->getFormatType() == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
1476              (p->mPlayerDriver->getFormatType() == PVMF_MIME_DATA_SOURCE_MS_HTTP_STREAMING_URL) ) {
1477             LOGV("check_for_live_streaming enQ PlayerCheckLiveStreaming command");
1478             p->mPlayerDriver->enqueueCommand(new PlayerCheckLiveStreaming( do_nothing, NULL));
1479         }
1480     }
1481 }
1482
1483 void PVPlayer::run_init(status_t s, void *cookie, bool cancelled)
1484 {
1485     LOGV("run_init s=%d, cancelled=%d", s, cancelled);
1486     if (s == NO_ERROR && !cancelled) {
1487         PVPlayer *p = (PVPlayer*)cookie;
1488         p->mPlayerDriver->enqueueCommand(new PlayerInit(run_set_video_surface, cookie));
1489     }
1490 }
1491
1492 void PVPlayer::run_set_video_surface(status_t s, void *cookie, bool cancelled)
1493 {
1494     LOGV("run_set_video_surface s=%d, cancelled=%d", s, cancelled);
1495     if (s == NO_ERROR && !cancelled) {
1496         // If we don't have a video surface, just skip to the next step.
1497         PVPlayer *p = (PVPlayer*)cookie;
1498         if (p->mSurface == NULL) {
1499             run_set_audio_output(s, cookie, false);
1500         } else {
1501             p->mPlayerDriver->enqueueCommand(new PlayerSetVideoSurface(p->mSurface, run_set_audio_output, cookie));
1502         }
1503     }
1504 }
1505
1506 void PVPlayer::run_set_audio_output(status_t s, void *cookie, bool cancelled)
1507 {
1508     LOGV("run_set_audio_output s=%d, cancelled=%d", s, cancelled);
1509     if (s == NO_ERROR && !cancelled) {
1510         PVPlayer *p = (PVPlayer*)cookie;
1511         p->mPlayerDriver->enqueueCommand(new PlayerSetAudioSink(p->mAudioSink, run_prepare, cookie));
1512     }
1513 }
1514
1515 void PVPlayer::run_prepare(status_t s, void *cookie, bool cancelled)
1516 {
1517     LOGV("run_prepare s=%d, cancelled=%d", s, cancelled);
1518     if (s == NO_ERROR && !cancelled) {
1519         PVPlayer *p = (PVPlayer*)cookie;
1520         p->mPlayerDriver->enqueueCommand(new PlayerPrepare(check_for_live_streaming, cookie));
1521     }
1522 }
1523
1524 status_t PVPlayer::prepareAsync()
1525 {
1526     LOGV("prepareAsync");
1527     status_t ret = OK;
1528
1529     if (!mIsDataSourceSet) {  // If data source has NOT been set.
1530         // Set our data source as cached in setDataSource() above.
1531         LOGV("  data source = %s", mDataSourcePath);
1532         ret = mPlayerDriver->enqueueCommand(new PlayerSetDataSource(mDataSourcePath,run_init,this));
1533         mIsDataSourceSet = true;
1534     } else {  // If data source has been already set.
1535         // No need to run a sequence of commands.
1536         // The only code needed to run is PLAYER_PREPARE.
1537         ret = mPlayerDriver->enqueueCommand(new PlayerPrepare(do_nothing, NULL));
1538     }
1539
1540     return ret;
1541 }
1542
1543 status_t PVPlayer::start()
1544 {
1545     LOGV("start");
1546     return mPlayerDriver->enqueueCommand(new PlayerStart(0,0));
1547 }
1548
1549 status_t PVPlayer::stop()
1550 {
1551     LOGV("stop");
1552     return mPlayerDriver->enqueueCommand(new PlayerStop(0,0));
1553 }
1554
1555 status_t PVPlayer::pause()
1556 {
1557     LOGV("pause");
1558     return mPlayerDriver->enqueueCommand(new PlayerPause(0,0));
1559 }
1560
1561 bool PVPlayer::isPlaying()
1562 {
1563     int status = 0;
1564     if (mPlayerDriver->enqueueCommand(new PlayerGetStatus(&status,0,0)) == NO_ERROR) {
1565         return (status == PVP_STATE_STARTED);
1566     }
1567     return false;
1568 }
1569
1570 status_t PVPlayer::getCurrentPosition(int *msec)
1571 {
1572     return mPlayerDriver->enqueueCommand(new PlayerGetPosition(msec,0,0));
1573 }
1574
1575 status_t PVPlayer::getDuration(int *msec)
1576 {
1577     status_t ret = mPlayerDriver->enqueueCommand(new PlayerGetDuration(msec,0,0));
1578     if (ret == NO_ERROR) mDuration = *msec;
1579     LOGI("duration = %d",mDuration);
1580     return ret;
1581 }
1582
1583 status_t PVPlayer::seekTo(int msec)
1584 {
1585     LOGV("seekTo(%d)", msec);
1586     // can't always seek to end of streams - so we fudge a little
1587     if ((msec == mDuration) && (mDuration > 0)) {
1588         msec--;
1589         LOGV("Seek adjusted 1 msec from end");
1590     }
1591     return mPlayerDriver->enqueueCommand(new PlayerSeek(msec,do_nothing,0));
1592 }
1593
1594 status_t PVPlayer::reset()
1595 {
1596     LOGV("reset");
1597     status_t ret = mPlayerDriver->enqueueCommand(new PlayerCancelAllCommands(0,0));
1598     if (ret == NO_ERROR) {
1599         ret = mPlayerDriver->enqueueCommand(new PlayerReset(0,0));
1600     }
1601     if (ret == NO_ERROR) {
1602         ret = mPlayerDriver->enqueueCommand(new PlayerRemoveDataSource(0,0));
1603     }
1604     mSurface.clear();
1605     LOGV("unmap file");
1606     if (mSharedFd >= 0) {
1607         close(mSharedFd);
1608         mSharedFd = -1;
1609     }
1610     mIsDataSourceSet = false;
1611     return ret;
1612 }
1613
1614 status_t PVPlayer::setLooping(int loop)
1615 {
1616     LOGV("setLooping(%d)", loop);
1617     return mPlayerDriver->enqueueCommand(new PlayerSetLoop(loop,0,0));
1618 }
1619
1620 // This is a stub for the direct invocation API.
1621 // From include/media/MediaPlayerInterface.h where the abstract method
1622 // is declared:
1623 //
1624 //   Invoke a generic method on the player by using opaque parcels
1625 //   for the request and reply.
1626 //   @param request Parcel that must start with the media player
1627 //   interface token.
1628 //   @param[out] reply Parcel to hold the reply data. Cannot be null.
1629 //   @return OK if the invocation was made successfully.
1630 //
1631 // This stub should be replaced with a concrete implementation.
1632 //
1633 // Typically the request parcel will contain an opcode to identify an
1634 // operation to be executed. There might also be a handle used to
1635 // create a session between the client and the player.
1636 //
1637 // The concrete implementation can then dispatch the request
1638 // internally based on the double (opcode, handle).
1639 status_t PVPlayer::invoke(const Parcel& request, Parcel *reply)
1640 {
1641     return INVALID_OPERATION;
1642 }
1643
1644 status_t PVPlayer::getMetadata(const media::Metadata::Filter& ids,
1645                                Parcel *records) {
1646     return UNKNOWN_ERROR;
1647 }
1648
1649 }; // namespace android
1650
1651
1652
1653