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