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