• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 2008 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "VideoMIO"
21 #include <utils/Log.h>
22 #include <ui/ISurface.h>
23 
24 #include "android_surface_output.h"
25 #include <media/PVPlayer.h>
26 
27 #include "pvlogger.h"
28 #include "pv_mime_string_utils.h"
29 #include "oscl_snprintf.h"
30 
31 #include "oscl_dll.h"
32 
33 // Define entry point for this DLL
34 OSCL_DLL_ENTRY_POINT_DEFAULT()
35 
36 //The factory functions.
37 #include "oscl_mem.h"
38 
39 using namespace android;
40 
AndroidSurfaceOutput()41 OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput() :
42     OsclTimerObject(OsclActiveObject::EPriorityNominal, "androidsurfaceoutput")
43 {
44     initData();
45 
46     iColorConverter = NULL;
47     mInitialized = false;
48     mPvPlayer = NULL;
49     mEmulation = false;
50     iEosReceived = false;
51 }
52 
set(PVPlayer * pvPlayer,const sp<ISurface> & surface,bool emulation)53 status_t AndroidSurfaceOutput::set(PVPlayer* pvPlayer, const sp<ISurface>& surface, bool emulation)
54 {
55     mPvPlayer = pvPlayer;
56     mEmulation = emulation;
57     setVideoSurface(surface);
58     return NO_ERROR;
59 }
60 
setVideoSurface(const sp<ISurface> & surface)61 status_t AndroidSurfaceOutput::setVideoSurface(const sp<ISurface>& surface)
62 {
63     LOGV("setVideoSurface(%p)", surface.get());
64     // unregister buffers for the old surface
65     if (mSurface != NULL) {
66         LOGV("unregisterBuffers from old surface");
67         mSurface->unregisterBuffers();
68     }
69     mSurface = surface;
70     // register buffers for the new surface
71     if ((mSurface != NULL) && (mBufferHeap.heap != NULL)) {
72         LOGV("registerBuffers from old surface");
73         mSurface->registerBuffers(mBufferHeap);
74     }
75     return NO_ERROR;
76 }
77 
initData()78 void AndroidSurfaceOutput::initData()
79 {
80     iVideoHeight = iVideoWidth = iVideoDisplayHeight = iVideoDisplayWidth = 0;
81     iVideoFormat=PVMF_MIME_FORMAT_UNKNOWN;
82     resetVideoParameterFlags();
83 
84     iCommandCounter=0;
85     iLogger=NULL;
86     iCommandResponseQueue.reserve(5);
87     iWriteResponseQueue.reserve(5);
88     iObserver=NULL;
89     iLogger=NULL;
90     iPeer=NULL;
91     iState=STATE_IDLE;
92     iIsMIOConfigured = false;
93 }
94 
ResetData()95 void AndroidSurfaceOutput::ResetData()
96     //reset all data from this session.
97 {
98     Cleanup();
99 
100     //reset all the received media parameters.
101     iVideoFormatString="";
102     iVideoFormat=PVMF_MIME_FORMAT_UNKNOWN;
103     resetVideoParameterFlags();
104     iIsMIOConfigured = false;
105 }
106 
resetVideoParameterFlags()107 void AndroidSurfaceOutput::resetVideoParameterFlags()
108 {
109     iVideoParameterFlags = VIDEO_PARAMETERS_INVALID;
110 }
111 
checkVideoParameterFlags()112 bool AndroidSurfaceOutput::checkVideoParameterFlags()
113 {
114     return (iVideoParameterFlags & VIDEO_PARAMETERS_MASK) == VIDEO_PARAMETERS_VALID;
115 }
116 
117 /*
118  * process the write response queue by sending writeComplete to the peer
119  * (nominally the decoder node).
120  *
121  * numFramesToHold is the number of frames to be held in the MIO. During
122  * playback, we hold the last frame which is used by SurfaceFlinger
123  * to composite the final output.
124  */
processWriteResponseQueue(int numFramesToHold)125 void AndroidSurfaceOutput::processWriteResponseQueue(int numFramesToHold)
126 {
127     LOGV("processWriteResponseQueue: queued = %d, numFramesToHold = %d",
128             iWriteResponseQueue.size(), numFramesToHold);
129     while (iWriteResponseQueue.size() > numFramesToHold) {
130         if (iPeer) {
131             iPeer->writeComplete(iWriteResponseQueue[0].iStatus,
132                     iWriteResponseQueue[0].iCmdId,
133                     (OsclAny*)iWriteResponseQueue[0].iContext);
134         }
135         iWriteResponseQueue.erase(&iWriteResponseQueue[0]);
136     }
137 }
138 
Cleanup()139 void AndroidSurfaceOutput::Cleanup()
140 //cleanup all allocated memory and release resources.
141 {
142     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Cleanup() In"));
143     while (!iCommandResponseQueue.empty())
144     {
145         if (iObserver)
146             iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus));
147         iCommandResponseQueue.erase(&iCommandResponseQueue[0]);
148     }
149 
150     processWriteResponseQueue(0);
151 
152     // We'll close frame buf and delete here for now.
153     closeFrameBuf();
154 
155     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Cleanup() Out"));
156  }
157 
~AndroidSurfaceOutput()158 OSCL_EXPORT_REF AndroidSurfaceOutput::~AndroidSurfaceOutput()
159 {
160     Cleanup();
161 }
162 
163 
connect(PvmiMIOSession & aSession,PvmiMIOObserver * aObserver)164 PVMFStatus AndroidSurfaceOutput::connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver)
165 {
166     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::connect() called"));
167     // Each Session could have its own set of Configuration parameters
168     //in an array of structures and the session ID could be an index to that array.
169 
170     //currently supports only one session
171     if (iObserver)
172         return PVMFFailure;
173 
174     iObserver=aObserver;
175     return PVMFSuccess;
176 }
177 
178 
disconnect(PvmiMIOSession aSession)179 PVMFStatus AndroidSurfaceOutput::disconnect(PvmiMIOSession aSession)
180 {
181     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::disconnect() called"));
182     //currently supports only one session
183     iObserver=NULL;
184     return PVMFSuccess;
185 }
186 
187 
createMediaTransfer(PvmiMIOSession & aSession,PvmiKvp * read_formats,int32 read_flags,PvmiKvp * write_formats,int32 write_flags)188 PvmiMediaTransfer* AndroidSurfaceOutput::createMediaTransfer(PvmiMIOSession& aSession,
189                                                         PvmiKvp* read_formats, int32 read_flags,
190                                                         PvmiKvp* write_formats, int32 write_flags)
191 {
192     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::createMediaTransfer() called"));
193     return (PvmiMediaTransfer*)this;
194 }
195 
QueueCommandResponse(CommandResponse & aResp)196 void AndroidSurfaceOutput::QueueCommandResponse(CommandResponse& aResp)
197 {
198     //queue a command response and schedule processing.
199 
200     iCommandResponseQueue.push_back(aResp);
201 
202     //cancel any timer delay so the command response will happen ASAP.
203     if (IsBusy())
204         Cancel();
205 
206     RunIfNotReady();
207 }
208 
QueryUUID(const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)209 PVMFCommandId AndroidSurfaceOutput::QueryUUID(const PvmfMimeString& aMimeType,
210                                         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
211                                         bool aExactUuidsOnly, const OsclAny* aContext)
212 {
213     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::QueryUUID() called"));
214 
215     OSCL_UNUSED_ARG(aMimeType);
216     OSCL_UNUSED_ARG(aExactUuidsOnly);
217 
218     PVMFCommandId cmdid=iCommandCounter++;
219 
220     PVMFStatus status=PVMFFailure;
221     int32 err ;
222     OSCL_TRY(err, aUuids.push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID););
223     if (err==OsclErrNone)
224         status= PVMFSuccess;
225 
226     CommandResponse resp(status,cmdid,aContext);
227     QueueCommandResponse(resp);
228     return cmdid;
229 }
230 
231 
QueryInterface(const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)232 PVMFCommandId AndroidSurfaceOutput::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext)
233 {
234     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::QueryInterface() called"));
235 
236     PVMFCommandId cmdid=iCommandCounter++;
237 
238     PVMFStatus status=PVMFFailure;
239     if(aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
240     {
241         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*,this);
242         aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface);
243         status= PVMFSuccess;
244     }
245     else
246     {
247         status=PVMFFailure;
248     }
249 
250     CommandResponse resp(status,cmdid,aContext);
251     QueueCommandResponse(resp);
252     return cmdid;
253 }
254 
255 
deleteMediaTransfer(PvmiMIOSession & aSession,PvmiMediaTransfer * media_transfer)256 void AndroidSurfaceOutput::deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer)
257 {
258     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::deleteMediaTransfer() called"));
259     // This class is implementing the media transfer, so no cleanup is needed
260 }
261 
262 
Init(const OsclAny * aContext)263 PVMFCommandId AndroidSurfaceOutput:: Init(const OsclAny* aContext)
264 {
265     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Init() called"));
266 
267     PVMFCommandId cmdid=iCommandCounter++;
268 
269     PVMFStatus status=PVMFFailure;
270 
271     switch(iState)
272     {
273     case STATE_LOGGED_ON:
274         status=PVMFSuccess;
275         iState=STATE_INITIALIZED;
276         break;
277 
278     default:
279         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Invalid State"));
280         status=PVMFErrInvalidState;
281         break;
282     }
283 
284     CommandResponse resp(status,cmdid,aContext);
285     QueueCommandResponse(resp);
286     return cmdid;
287 }
288 
Reset(const OsclAny * aContext)289 PVMFCommandId AndroidSurfaceOutput::Reset(const OsclAny* aContext)
290 {
291     ResetData();
292     PVMFCommandId cmdid=iCommandCounter++;
293     CommandResponse resp(PVMFSuccess,cmdid,aContext);
294     QueueCommandResponse(resp);
295     return cmdid;
296 }
297 
298 
Start(const OsclAny * aContext)299 PVMFCommandId AndroidSurfaceOutput::Start(const OsclAny* aContext)
300 {
301     iEosReceived = false;
302     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Start() called"));
303 
304     PVMFCommandId cmdid=iCommandCounter++;
305 
306     PVMFStatus status=PVMFFailure;
307 
308     switch(iState)
309     {
310     case STATE_INITIALIZED:
311     case STATE_PAUSED:
312 
313         iState=STATE_STARTED;
314         processWriteResponseQueue(0);
315         status=PVMFSuccess;
316         break;
317 
318     default:
319         status=PVMFErrInvalidState;
320         break;
321     }
322 
323     CommandResponse resp(status,cmdid,aContext);
324     QueueCommandResponse(resp);
325     return cmdid;
326 }
327 
328 // post the last video frame to refresh screen after pause
postLastFrame()329 void AndroidSurfaceOutput::postLastFrame()
330 {
331     // ignore if no surface or heap
332     if ((mSurface == NULL) || (mBufferHeap.heap == NULL)) return;
333     mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
334 }
335 
Pause(const OsclAny * aContext)336 PVMFCommandId AndroidSurfaceOutput::Pause(const OsclAny* aContext)
337 {
338     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Pause() called"));
339 
340     PVMFCommandId cmdid=iCommandCounter++;
341 
342     PVMFStatus status=PVMFFailure;
343 
344     switch(iState)
345     {
346     case STATE_STARTED:
347 
348         iState=STATE_PAUSED;
349         status=PVMFSuccess;
350 
351         // post last buffer to prevent stale data
352         // if not configured, PVMFMIOConfigurationComplete is not sent
353         // there should not be any media data.
354     if(iIsMIOConfigured) {
355         postLastFrame();
356         }
357         break;
358 
359     default:
360         status=PVMFErrInvalidState;
361         break;
362     }
363 
364     CommandResponse resp(status,cmdid,aContext);
365     QueueCommandResponse(resp);
366     return cmdid;
367 }
368 
369 
Flush(const OsclAny * aContext)370 PVMFCommandId AndroidSurfaceOutput::Flush(const OsclAny* aContext)
371 {
372     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Flush() called"));
373 
374     PVMFCommandId cmdid=iCommandCounter++;
375 
376     PVMFStatus status=PVMFFailure;
377 
378     switch(iState)
379     {
380     case STATE_STARTED:
381 
382         iState=STATE_INITIALIZED;
383         status=PVMFSuccess;
384         break;
385 
386     default:
387         status=PVMFErrInvalidState;
388         break;
389     }
390 
391     CommandResponse resp(status,cmdid,aContext);
392     QueueCommandResponse(resp);
393     return cmdid;
394 }
395 
DiscardData(const OsclAny * aContext)396 PVMFCommandId AndroidSurfaceOutput::DiscardData(const OsclAny* aContext)
397 {
398     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::DiscardData() called"));
399 
400     PVMFCommandId cmdid=iCommandCounter++;
401 
402     //this component doesn't buffer data, so there's nothing
403     //needed here.
404 
405     PVMFStatus status=PVMFSuccess;
406     processWriteResponseQueue(0);
407 
408     CommandResponse resp(status,cmdid,aContext);
409     QueueCommandResponse(resp);
410     return cmdid;
411 }
412 
DiscardData(PVMFTimestamp aTimestamp,const OsclAny * aContext)413 PVMFCommandId AndroidSurfaceOutput::DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext)
414 {
415     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::DiscardData() called"));
416 
417     PVMFCommandId cmdid=iCommandCounter++;
418 
419     aTimestamp = 0;
420 
421     //this component doesn't buffer data, so there's nothing
422     //needed here.
423 
424     PVMFStatus status=PVMFSuccess;
425     processWriteResponseQueue(0);
426 
427     CommandResponse resp(status,cmdid,aContext);
428     QueueCommandResponse(resp);
429     return cmdid;
430 }
431 
Stop(const OsclAny * aContext)432 PVMFCommandId AndroidSurfaceOutput::Stop(const OsclAny* aContext)
433 {
434     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Stop() called"));
435 
436     PVMFCommandId cmdid=iCommandCounter++;
437 
438     PVMFStatus status=PVMFFailure;
439 
440     switch(iState)
441     {
442     case STATE_STARTED:
443     case STATE_PAUSED:
444 
445 #ifdef PERFORMANCE_MEASUREMENTS_ENABLED
446         // FIXME: This should be moved to OMAP library
447     PVOmapVideoProfile.MarkEndTime();
448     PVOmapVideoProfile.PrintStats();
449     PVOmapVideoProfile.Reset();
450 #endif
451 
452         iState=STATE_INITIALIZED;
453         status=PVMFSuccess;
454         break;
455 
456     default:
457         status=PVMFErrInvalidState;
458         break;
459     }
460 
461     CommandResponse resp(status,cmdid,aContext);
462     QueueCommandResponse(resp);
463     return cmdid;
464 }
465 
CancelAllCommands(const OsclAny * aContext)466 PVMFCommandId AndroidSurfaceOutput::CancelAllCommands(const OsclAny* aContext)
467 {
468     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::CancelAllCommands() called"));
469 
470     PVMFCommandId cmdid=iCommandCounter++;
471 
472     //commands are executed immediately upon being received, so
473     //it isn't really possible to cancel them.
474 
475     PVMFStatus status=PVMFSuccess;
476 
477     CommandResponse resp(status,cmdid,aContext);
478     QueueCommandResponse(resp);
479     return cmdid;
480 }
481 
CancelCommand(PVMFCommandId aCmdId,const OsclAny * aContext)482 PVMFCommandId AndroidSurfaceOutput::CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext)
483 {
484     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::CancelCommand() called"));
485 
486     PVMFCommandId cmdid=iCommandCounter++;
487 
488     //commands are executed immediately upon being received, so
489     //it isn't really possible to cancel them.
490 
491     //see if the response is still queued.
492     PVMFStatus status=PVMFFailure;
493     for (uint32 i=0;i<iCommandResponseQueue.size();i++)
494     {
495         if (iCommandResponseQueue[i].iCmdId==aCmdId)
496         {
497             status=PVMFSuccess;
498             break;
499         }
500     }
501 
502     CommandResponse resp(status,cmdid,aContext);
503     QueueCommandResponse(resp);
504     return cmdid;
505 }
506 
ThreadLogon()507 void AndroidSurfaceOutput::ThreadLogon()
508 {
509     if(iState==STATE_IDLE)
510     {
511         iLogger = PVLogger::GetLoggerObject("PVOmapVideo");
512         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::ThreadLogon() called"));
513         AddToScheduler();
514         iState=STATE_LOGGED_ON;
515     }
516 }
517 
518 
ThreadLogoff()519 void AndroidSurfaceOutput::ThreadLogoff()
520 {
521     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::ThreadLogoff() called"));
522 
523     if(iState!=STATE_IDLE)
524     {
525         RemoveFromScheduler();
526         iLogger=NULL;
527         iState=STATE_IDLE;
528     }
529 }
530 
531 
setPeer(PvmiMediaTransfer * aPeer)532 void AndroidSurfaceOutput::setPeer(PvmiMediaTransfer* aPeer)
533 {
534     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::setPeer() called"));
535     // Set the observer
536     iPeer = aPeer;
537 }
538 
539 
useMemoryAllocators(OsclMemAllocator * write_alloc)540 void AndroidSurfaceOutput::useMemoryAllocators(OsclMemAllocator* write_alloc)
541 {
542     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::useMemoryAllocators() called"));
543     //not supported.
544 }
545 
546 // This routine will determine whether data can be accepted in a writeAsync
547 // call and if not, will return true;
CheckWriteBusy(uint32 aSeqNum)548 bool AndroidSurfaceOutput::CheckWriteBusy(uint32 aSeqNum)
549 {
550     // for all other cases, accept data now.
551     return false;
552 }
553 
writeAsync(uint8 aFormatType,int32 aFormatIndex,uint8 * aData,uint32 aDataLen,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)554 PVMFCommandId AndroidSurfaceOutput::writeAsync(uint8 aFormatType, int32 aFormatIndex, uint8* aData, uint32 aDataLen,
555                                         const PvmiMediaXferHeader& data_header_info, OsclAny* aContext)
556 {
557     // Do a leave if MIO is not configured except when it is an EOS
558     if (!iIsMIOConfigured
559             &&
560             !((PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION == aFormatType)
561               && (PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM == aFormatIndex)))
562     {
563         LOGE("data is pumped in before MIO is configured");
564         OSCL_LEAVE(OsclErrInvalidState);
565         return -1;
566     }
567 
568     uint32 aSeqNum=data_header_info.seq_num;
569     PVMFTimestamp aTimestamp=data_header_info.timestamp;
570     uint32 flags=data_header_info.flags;
571 
572     if (aSeqNum < 6)
573     {
574         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
575             (0,"AndroidSurfaceOutput::writeAsync() seqnum %d ts %d context %d",aSeqNum,aTimestamp,aContext));
576 
577         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
578             (0,"AndroidSurfaceOutput::writeAsync() Format Type %d Format Index %d length %d",aFormatType,aFormatIndex,aDataLen));
579     }
580 
581     PVMFStatus status=PVMFFailure;
582 
583     switch(aFormatType)
584     {
585     case PVMI_MEDIAXFER_FMT_TYPE_COMMAND :
586         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
587             (0,"AndroidSurfaceOutput::writeAsync() called with Command info."));
588         //ignore
589         status= PVMFSuccess;
590         break;
591 
592     case PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION :
593         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
594             (0,"AndroidSurfaceOutput::writeAsync() called with Notification info."));
595         switch(aFormatIndex)
596         {
597         case PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM:
598             iEosReceived = true;
599             break;
600         default:
601             break;
602         }
603         //ignore
604         status= PVMFSuccess;
605         break;
606 
607     case PVMI_MEDIAXFER_FMT_TYPE_DATA :
608         switch(aFormatIndex)
609         {
610         case PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO:
611             //format-specific info contains codec headers.
612             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
613                 (0,"AndroidSurfaceOutput::writeAsync() called with format-specific info."));
614 
615             if (iState<STATE_INITIALIZED)
616             {
617                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
618                     (0,"AndroidSurfaceOutput::writeAsync: Error - Invalid state"));
619                 status=PVMFErrInvalidState;
620             }
621             else
622             {
623                 status= PVMFSuccess;
624             }
625 
626             break;
627 
628         case PVMI_MEDIAXFER_FMT_INDEX_DATA:
629             //data contains the media bitstream.
630 
631             //Verify the state
632             if (iState!=STATE_STARTED)
633             {
634                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
635                     (0,"AndroidSurfaceOutput::writeAsync: Error - Invalid state"));
636                 status=PVMFErrInvalidState;
637             }
638             else
639             {
640 
641                 //printf("V WriteAsync { seq=%d, ts=%d }\n", data_header_info.seq_num, data_header_info.timestamp);
642 
643                 // Call playback to send data to IVA for Color Convert
644                 status = writeFrameBuf(aData, aDataLen, data_header_info);
645 
646                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
647                    (0,"AndroidSurfaceOutput::writeAsync: Playback Progress - frame %d",iFrameNumber++));
648             }
649             break;
650 
651         default:
652             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
653                 (0,"AndroidSurfaceOutput::writeAsync: Error - unrecognized format index"));
654             status= PVMFFailure;
655             break;
656         }
657         break;
658 
659     default:
660         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
661             (0,"AndroidSurfaceOutput::writeAsync: Error - unrecognized format type"));
662         status= PVMFFailure;
663         break;
664     }
665 
666     //Schedule asynchronous response
667     PVMFCommandId cmdid=iCommandCounter++;
668     WriteResponse resp(status,cmdid,aContext,aTimestamp);
669     iWriteResponseQueue.push_back(resp);
670     RunIfNotReady();
671 
672     return cmdid;
673 }
674 
writeComplete(PVMFStatus aStatus,PVMFCommandId write_cmd_id,OsclAny * aContext)675 void AndroidSurfaceOutput::writeComplete(PVMFStatus aStatus, PVMFCommandId  write_cmd_id, OsclAny* aContext)
676 {
677     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::writeComplete() called"));
678     //won't be called since this component is a sink.
679 }
680 
681 
readAsync(uint8 * data,uint32 max_data_len,OsclAny * aContext,int32 * formats,uint16 num_formats)682 PVMFCommandId  AndroidSurfaceOutput::readAsync(uint8* data, uint32 max_data_len, OsclAny* aContext,
683                                             int32* formats, uint16 num_formats)
684 {
685     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::readAsync() called"));
686     //read not supported.
687     OsclError::Leave(OsclErrNotSupported);
688     return -1;
689 }
690 
691 
readComplete(PVMFStatus aStatus,PVMFCommandId read_cmd_id,int32 format_index,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)692 void AndroidSurfaceOutput::readComplete(PVMFStatus aStatus, PVMFCommandId  read_cmd_id, int32 format_index,
693                                     const PvmiMediaXferHeader& data_header_info, OsclAny* aContext)
694 {
695     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::readComplete() called"));
696     //won't be called since this component is a sink.
697 }
698 
699 
statusUpdate(uint32 status_flags)700 void AndroidSurfaceOutput::statusUpdate(uint32 status_flags)
701 {
702     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::statusUpdate() called"));
703     //won't be called since this component is a sink.
704 }
705 
706 
cancelCommand(PVMFCommandId command_id)707 void AndroidSurfaceOutput::cancelCommand(PVMFCommandId  command_id)
708 {
709     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::cancelCommand() called"));
710 
711     //the purpose of this API is to cancel a writeAsync command and report
712     //completion ASAP.
713 
714     //in this implementation, the write commands are executed immediately
715     //when received so it isn't really possible to cancel.
716     //just report completion immediately.
717     processWriteResponseQueue(0);
718 }
719 
cancelAllCommands()720 void AndroidSurfaceOutput::cancelAllCommands()
721 {
722     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::cancelAllCommands() called"));
723 
724     //the purpose of this API is to cancel all writeAsync commands and report
725     //completion ASAP.
726 
727     //in this implementaiton, the write commands are executed immediately
728     //when received so it isn't really possible to cancel.
729     //just report completion immediately.
730 
731     for (uint32 i=0;i<iWriteResponseQueue.size();i++)
732     {
733         //report completion
734         if (iPeer)
735             iPeer->writeComplete(iWriteResponseQueue[i].iStatus,iWriteResponseQueue[i].iCmdId,(OsclAny*)iWriteResponseQueue[i].iContext);
736         iWriteResponseQueue.erase(&iWriteResponseQueue[i]);
737     }
738 }
739 
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)740 void AndroidSurfaceOutput::setObserver (PvmiConfigAndCapabilityCmdObserver* aObserver)
741 {
742     OSCL_UNUSED_ARG(aObserver);
743     //not needed since this component only supports synchronous capability & config
744     //APIs.
745 }
746 
getParametersSync(PvmiMIOSession aSession,PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & num_parameter_elements,PvmiCapabilityContext aContext)747 PVMFStatus AndroidSurfaceOutput::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
748                                               PvmiKvp*& aParameters, int& num_parameter_elements,
749                                               PvmiCapabilityContext aContext)
750 {
751     OSCL_UNUSED_ARG(aSession);
752     OSCL_UNUSED_ARG(aContext);
753     aParameters=NULL;
754 
755     // This is a query for the list of supported formats.
756     if(pv_mime_strcmp(aIdentifier, INPUT_FORMATS_CAP_QUERY) == 0)
757     {
758         aParameters=(PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
759         if (aParameters == NULL) return PVMFErrNoMemory;
760         aParameters[num_parameter_elements++].value.pChar_value=(char*) PVMF_MIME_YUV420;
761 
762         return PVMFSuccess;
763     }
764 
765     //unrecognized key.
766     return PVMFFailure;
767 }
768 
releaseParameters(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)769 PVMFStatus AndroidSurfaceOutput::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
770 {
771     //release parameters that were allocated by this component.
772     if (aParameters)
773     {
774         oscl_free(aParameters);
775         return PVMFSuccess;
776     }
777     return PVMFFailure;
778 }
779 
createContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)780 void AndroidSurfaceOutput ::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
781 {
782     OsclError::Leave(OsclErrNotSupported);
783 }
784 
setContextParameters(PvmiMIOSession aSession,PvmiCapabilityContext & aContext,PvmiKvp * aParameters,int num_parameter_elements)785 void AndroidSurfaceOutput::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
786                                            PvmiKvp* aParameters, int num_parameter_elements)
787 {
788     OsclError::Leave(OsclErrNotSupported);
789 }
790 
DeleteContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)791 void AndroidSurfaceOutput::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
792 {
793     OsclError::Leave(OsclErrNotSupported);
794 }
795 
796 
setParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp)797 void AndroidSurfaceOutput::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
798                                         int num_elements, PvmiKvp * & aRet_kvp)
799 {
800     OSCL_UNUSED_ARG(aSession);
801 
802     aRet_kvp = NULL;
803 
804     LOGV("setParametersSync");
805     for (int32 i=0;i<num_elements;i++)
806     {
807         //Check against known video parameter keys...
808         if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_FORMAT_KEY) == 0)
809         {
810             iVideoFormatString=aParameters[i].value.pChar_value;
811             iVideoFormat=iVideoFormatString.get_str();
812             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
813                 (0,"AndroidSurfaceOutput::setParametersSync() Video Format Key, Value %s",iVideoFormatString.get_str()));
814         }
815         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_WIDTH_KEY) == 0)
816         {
817             iVideoWidth=(int32)aParameters[i].value.uint32_value;
818             iVideoParameterFlags |= VIDEO_WIDTH_VALID;
819             LOGV("iVideoWidth=%d", iVideoWidth);
820             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
821                 (0,"AndroidSurfaceOutput::setParametersSync() Video Width Key, Value %d",iVideoWidth));
822         }
823         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_HEIGHT_KEY) == 0)
824         {
825             iVideoHeight=(int32)aParameters[i].value.uint32_value;
826             iVideoParameterFlags |= VIDEO_HEIGHT_VALID;
827             LOGV("iVideoHeight=%d", iVideoHeight);
828             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
829                 (0,"AndroidSurfaceOutput::setParametersSync() Video Height Key, Value %d",iVideoHeight));
830         }
831         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_HEIGHT_KEY) == 0)
832         {
833             iVideoDisplayHeight=(int32)aParameters[i].value.uint32_value;
834             iVideoParameterFlags |= DISPLAY_HEIGHT_VALID;
835             LOGV("iVideoDisplayHeight=%d", iVideoDisplayHeight);
836             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
837                 (0,"AndroidSurfaceOutput::setParametersSync() Video Display Height Key, Value %d",iVideoDisplayHeight));
838         }
839         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_WIDTH_KEY) == 0)
840         {
841             iVideoDisplayWidth=(int32)aParameters[i].value.uint32_value;
842             iVideoParameterFlags |= DISPLAY_WIDTH_VALID;
843             LOGV("iVideoDisplayWidth=%d", iVideoDisplayWidth);
844             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
845                 (0,"AndroidSurfaceOutput::setParametersSync() Video Display Width Key, Value %d",iVideoDisplayWidth));
846         }
847         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_SUBFORMAT_KEY) == 0)
848         {
849             iVideoSubFormat=aParameters[i].value.pChar_value;
850             iVideoParameterFlags |= VIDEO_SUBFORMAT_VALID;
851             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
852                     (0,"AndroidSurfaceOutput::setParametersSync() Video SubFormat Key, Value %s",iVideoSubFormat.getMIMEStrPtr()));
853 
854 LOGV("VIDEO SUBFORMAT SET TO %s\n",iVideoSubFormat.getMIMEStrPtr());
855         }
856         else
857         {
858             //if we get here the key is unrecognized.
859 
860             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
861                 (0,"AndroidSurfaceOutput::setParametersSync() Error, unrecognized key = %s", aParameters[i].key));
862 
863             //set the return value to indicate the unrecognized key
864             //and return.
865             aRet_kvp = &aParameters[i];
866             return;
867         }
868     }
869     uint32 mycache = iVideoParameterFlags ;
870     // if initialization is complete, update the app display info
871     if( checkVideoParameterFlags() )
872     initCheck();
873     iVideoParameterFlags = mycache;
874 
875     // when all necessary parameters are received, send
876     // PVMFMIOConfigurationComplete event to observer
877     if(!iIsMIOConfigured && checkVideoParameterFlags() )
878     {
879         iIsMIOConfigured = true;
880         if(iObserver)
881         {
882             iObserver->ReportInfoEvent(PVMFMIOConfigurationComplete);
883         }
884     }
885 }
886 
setParametersAsync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp,OsclAny * context)887 PVMFCommandId AndroidSurfaceOutput::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters,
888                                                   int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context)
889 {
890     OsclError::Leave(OsclErrNotSupported);
891     return -1;
892 }
893 
getCapabilityMetric(PvmiMIOSession aSession)894 uint32 AndroidSurfaceOutput::getCapabilityMetric (PvmiMIOSession aSession)
895 {
896     return 0;
897 }
898 
verifyParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)899 PVMFStatus AndroidSurfaceOutput::verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
900 {
901     OSCL_UNUSED_ARG(aSession);
902 
903     // Go through each parameter
904     for (int32 i=0; i<num_elements; i++) {
905         char* compstr = NULL;
906         pv_mime_string_extract_type(0, aParameters[i].key, compstr);
907         if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format-type")) == 0) {
908             if (pv_mime_strcmp(aParameters[i].value.pChar_value, PVMF_MIME_YUV420) == 0) {
909                 return PVMFSuccess;
910             }
911             else {
912                 return PVMFErrNotSupported;
913             }
914         }
915     }
916     return PVMFSuccess;
917 }
918 
919 //
920 // Private section
921 //
922 
Run()923 void AndroidSurfaceOutput::Run()
924 {
925     //send async command responses
926     while (!iCommandResponseQueue.empty())
927     {
928         if (iObserver)
929             iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus));
930         iCommandResponseQueue.erase(&iCommandResponseQueue[0]);
931     }
932 
933     //send async write completion
934     if (iEosReceived) {
935         LOGV("Flushing buffers after EOS");
936         processWriteResponseQueue(0);
937     } else {
938         processWriteResponseQueue(1);
939     }
940 }
941 
942 // create a frame buffer for software codecs
initCheck()943 OSCL_EXPORT_REF bool AndroidSurfaceOutput::initCheck()
944 {
945 
946     // initialize only when we have all the required parameters
947     if (!checkVideoParameterFlags())
948         return mInitialized;
949 
950     // release resources if previously initialized
951     closeFrameBuf();
952 
953     // reset flags in case display format changes in the middle of a stream
954     resetVideoParameterFlags();
955 
956     // copy parameters in case we need to adjust them
957     int displayWidth = iVideoDisplayWidth;
958     int displayHeight = iVideoDisplayHeight;
959     int frameWidth = iVideoWidth;
960     int frameHeight = iVideoHeight;
961     int frameSize;
962 
963     // RGB-565 frames are 2 bytes/pixel
964     displayWidth = (displayWidth + 1) & -2;
965     displayHeight = (displayHeight + 1) & -2;
966     frameWidth = (frameWidth + 1) & -2;
967     frameHeight = (frameHeight + 1) & -2;
968     frameSize = frameWidth * frameHeight * 2;
969 
970     // create frame buffer heap and register with surfaceflinger
971     sp<MemoryHeapBase> heap = new MemoryHeapBase(frameSize * kBufferCount);
972     if (heap->heapID() < 0) {
973         LOGE("Error creating frame buffer heap");
974         return false;
975     }
976 
977     mBufferHeap = ISurface::BufferHeap(displayWidth, displayHeight,
978             frameWidth, frameHeight, PIXEL_FORMAT_RGB_565, heap);
979     mSurface->registerBuffers(mBufferHeap);
980 
981     // create frame buffers
982     for (int i = 0; i < kBufferCount; i++) {
983         mFrameBuffers[i] = i * frameSize;
984     }
985 
986     // initialize software color converter
987     iColorConverter = ColorConvert16::NewL();
988     iColorConverter->Init(displayWidth, displayHeight, frameWidth, displayWidth, displayHeight, displayWidth, CCROTATE_NONE);
989     iColorConverter->SetMemHeight(frameHeight);
990     iColorConverter->SetMode(1);
991 
992     LOGV("video = %d x %d", displayWidth, displayHeight);
993     LOGV("frame = %d x %d", frameWidth, frameHeight);
994     LOGV("frame #bytes = %d", frameSize);
995 
996     // register frame buffers with SurfaceFlinger
997     mFrameBufferIndex = 0;
998     mInitialized = true;
999     mPvPlayer->sendEvent(MEDIA_SET_VIDEO_SIZE, iVideoDisplayWidth, iVideoDisplayHeight);
1000 
1001     return mInitialized;
1002 }
1003 
writeFrameBuf(uint8 * aData,uint32 aDataLen,const PvmiMediaXferHeader & data_header_info)1004 OSCL_EXPORT_REF PVMFStatus AndroidSurfaceOutput::writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info)
1005 {
1006     // post to SurfaceFlinger
1007     if ((mSurface != NULL) && (mBufferHeap.heap != NULL)) {
1008         if (++mFrameBufferIndex == kBufferCount) mFrameBufferIndex = 0;
1009         iColorConverter->Convert(aData, static_cast<uint8*>(mBufferHeap.heap->base()) + mFrameBuffers[mFrameBufferIndex]);
1010         mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
1011     }
1012     return PVMFSuccess;
1013 }
1014 
closeFrameBuf()1015 OSCL_EXPORT_REF void AndroidSurfaceOutput::closeFrameBuf()
1016 {
1017     LOGV("closeFrameBuf");
1018     if (!mInitialized) return;
1019 
1020     mInitialized = false;
1021     if (mSurface.get()) {
1022         LOGV("unregisterBuffers");
1023         mSurface->unregisterBuffers();
1024     }
1025 
1026     // free frame buffers
1027     LOGV("free frame buffers");
1028     for (int i = 0; i < kBufferCount; i++) {
1029         mFrameBuffers[i] = 0;
1030     }
1031 
1032     // free heaps
1033     LOGV("free frame heap");
1034     mBufferHeap.heap.clear();
1035 
1036     // free color converter
1037     if (iColorConverter != 0)
1038     {
1039         LOGV("free color converter");
1040         delete iColorConverter;
1041         iColorConverter = 0;
1042     }
1043 }
1044 
GetVideoSize(int * w,int * h)1045 OSCL_EXPORT_REF bool AndroidSurfaceOutput::GetVideoSize(int *w, int *h) {
1046 
1047     *w = iVideoDisplayWidth;
1048     *h = iVideoDisplayHeight;
1049     return iVideoDisplayWidth != 0 && iVideoDisplayHeight != 0;
1050 }
1051